Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1604531 > unrolled thread

[char-misc-next 1/5] mei: add pci driver ops shutdown handler.

Started byTomas Winkler <tomas.winkler@intel.com>
First post2017-03-20 14:10 +0100
Last post2017-03-20 14:10 +0100
Articles 5 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [char-misc-next 1/5] mei: add pci driver ops shutdown handler. Tomas Winkler <tomas.winkler@intel.com> - 2017-03-20 14:10 +0100
    [char-misc-next 4/5] mei: bus: elminate variable length arrays Tomas Winkler <tomas.winkler@intel.com> - 2017-03-20 14:10 +0100
    [char-misc-next 2/5] mei: drop amthif internal client Tomas Winkler <tomas.winkler@intel.com> - 2017-03-20 14:10 +0100
    [char-misc-next 3/5] mei: hbm: remove variable length arrays Tomas Winkler <tomas.winkler@intel.com> - 2017-03-20 14:10 +0100
    [char-misc-next 5/5] mei: implement fsync Tomas Winkler <tomas.winkler@intel.com> - 2017-03-20 14:10 +0100

#1604531 — [char-misc-next 1/5] mei: add pci driver ops shutdown handler.

FromTomas Winkler <tomas.winkler@intel.com>
Date2017-03-20 14:10 +0100
Subject[char-misc-next 1/5] mei: add pci driver ops shutdown handler.
Message-ID<tn5ep-5aQ-11@gated-at.bofh.it>
The shutdown handler quiesces the device, it performs link reset in
order to close all connections and notify the device that is not longer
managed by the driver.
This is essentially a stripped down version of the PCI remove() function
where only the necessary amount of work is done to stop any further
activity.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/pci-me.c  | 31 +++++++++++++++++++++++++++++--
 drivers/misc/mei/pci-txe.c | 29 ++++++++++++++++++++++++++++-
 2 files changed, 57 insertions(+), 3 deletions(-)

diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 0a668fdfbbe9..8621a198a2ce 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -242,11 +242,38 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 }
 
 /**
+ * mei_me_shutdown - Device Removal Routine
+ *
+ * @pdev: PCI device structure
+ *
+ * mei_me_shutdown is called from the reboot notifier
+ * it's a simplified version of remove so we go down
+ * faster.
+ */
+static void mei_me_shutdown(struct pci_dev *pdev)
+{
+	struct mei_device *dev;
+
+	dev = pci_get_drvdata(pdev);
+	if (!dev)
+		return;
+
+	dev_dbg(&pdev->dev, "shutdown\n");
+	mei_stop(dev);
+
+	if (!pci_dev_run_wake(pdev))
+		mei_me_unset_pm_domain(dev);
+
+	mei_disable_interrupts(dev);
+	free_irq(pdev->irq, dev);
+}
+
+/**
  * mei_me_remove - Device Removal Routine
  *
  * @pdev: PCI device structure
  *
- * mei_remove is called by the PCI subsystem to alert the driver
+ * mei_me_remove is called by the PCI subsystem to alert the driver
  * that it should release a PCI device.
  */
 static void mei_me_remove(struct pci_dev *pdev)
@@ -456,7 +483,7 @@ static struct pci_driver mei_me_driver = {
 	.id_table = mei_me_pci_tbl,
 	.probe = mei_me_probe,
 	.remove = mei_me_remove,
-	.shutdown = mei_me_remove,
+	.shutdown = mei_me_shutdown,
 	.driver.pm = MEI_ME_PM_OPS,
 };
 
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index fe088b40daf9..f811cd524468 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -161,6 +161,33 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 }
 
 /**
+ * mei_txe_remove - Device Shutdown Routine
+ *
+ * @pdev: PCI device structure
+ *
+ *  mei_txe_shutdown is called from the reboot notifier
+ *  it's a simplified version of remove so we go down
+ *  faster.
+ */
+static void mei_txe_shutdown(struct pci_dev *pdev)
+{
+	struct mei_device *dev;
+
+	dev = pci_get_drvdata(pdev);
+	if (!dev)
+		return;
+
+	dev_dbg(&pdev->dev, "shutdown\n");
+	mei_stop(dev);
+
+	if (!pci_dev_run_wake(pdev))
+		mei_txe_unset_pm_domain(dev);
+
+	mei_disable_interrupts(dev);
+	free_irq(pdev->irq, dev);
+}
+
+/**
  * mei_txe_remove - Device Removal Routine
  *
  * @pdev: PCI device structure
@@ -386,7 +413,7 @@ static struct pci_driver mei_txe_driver = {
 	.id_table = mei_txe_pci_tbl,
 	.probe = mei_txe_probe,
 	.remove = mei_txe_remove,
-	.shutdown = mei_txe_remove,
+	.shutdown = mei_txe_shutdown,
 	.driver.pm = MEI_TXE_PM_OPS,
 };
 
-- 
2.9.3

[toc] | [next] | [standalone]


#1604534 — [char-misc-next 4/5] mei: bus: elminate variable length arrays

FromTomas Winkler <tomas.winkler@intel.com>
Date2017-03-20 14:10 +0100
Subject[char-misc-next 4/5] mei: bus: elminate variable length arrays
Message-ID<tn5eq-5aQ-31@gated-at.bofh.it>
In reply to#1604531
Though VLA are supported by CC99 there are many cavities
and should be avoided.

'const size_t len = sizeof()' that we used may not be set
at the compile time hence generating VLA code.

This fixes also sparse warning
warning: Variable length array is used type.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/bus-fixup.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index 29f2daed37e0..0208c4b027c5 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -110,12 +110,13 @@ struct mkhi_msg {
 	u8 data[0];
 } __packed;
 
+#define MKHI_OSVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \
+			    sizeof(struct mkhi_fwcaps) + \
+			    sizeof(struct mei_os_ver))
 static int mei_osver(struct mei_cl_device *cldev)
 {
-	const size_t size = sizeof(struct mkhi_msg_hdr) +
-			    sizeof(struct mkhi_fwcaps) +
-			    sizeof(struct mei_os_ver);
-	char buf[size];
+	const size_t size = MKHI_OSVER_BUF_LEN;
+	char buf[MKHI_OSVER_BUF_LEN];
 	struct mkhi_msg *req;
 	struct mkhi_fwcaps *fwcaps;
 	struct mei_os_ver *os_ver;
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1604537 — [char-misc-next 2/5] mei: drop amthif internal client

FromTomas Winkler <tomas.winkler@intel.com>
Date2017-03-20 14:10 +0100
Subject[char-misc-next 2/5] mei: drop amthif internal client
Message-ID<tn5eq-5aQ-29@gated-at.bofh.it>
In reply to#1604531
From: Alexander Usyskin <alexander.usyskin@intel.com>

AMTHIF has special support in the mei drive, it handles multiplexing
multiple user space connection above single me client connection.
Since there is no additional addressing information there is a strict
requirement on the traffic order on each connection and on the "read
after write" order within the connection. This creates a lot of
complexity mostly because the other client types do not necessarily fall
under the same restriction.    After carefully studying the use of the
AMTHIF client, we came to conclusion that the multiplexing is not really
utilized by any application and we may safely remove that support and
significantly simplify the driver.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/Makefile    |   1 -
 drivers/misc/mei/amthif.c    | 340 -------------------------------------------
 drivers/misc/mei/bus.c       |   6 -
 drivers/misc/mei/client.c    |  14 +-
 drivers/misc/mei/client.h    |   5 -
 drivers/misc/mei/init.c      |  14 +-
 drivers/misc/mei/interrupt.c |  38 +----
 drivers/misc/mei/main.c      |  53 +------
 drivers/misc/mei/mei_dev.h   |  51 -------
 9 files changed, 15 insertions(+), 507 deletions(-)
 delete mode 100644 drivers/misc/mei/amthif.c

diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 59e6b0aede34..12cceb011a23 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -8,7 +8,6 @@ mei-objs += hbm.o
 mei-objs += interrupt.o
 mei-objs += client.o
 mei-objs += main.o
-mei-objs += amthif.o
 mei-objs += bus.o
 mei-objs += bus-fixup.o
 mei-$(CONFIG_DEBUG_FS) += debugfs.o
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
deleted file mode 100644
index 0e7406ccb6dd..000000000000
--- a/drivers/misc/mei/amthif.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- *
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2012, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fcntl.h>
-#include <linux/ioctl.h>
-#include <linux/cdev.h>
-#include <linux/list.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/uuid.h>
-#include <linux/jiffies.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-
-#include <linux/mei.h>
-
-#include "mei_dev.h"
-#include "hbm.h"
-#include "client.h"
-
-const uuid_le mei_amthif_guid  = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d,
-					 0xac, 0xa8, 0x46, 0xe0,
-					 0xff, 0x65, 0x81, 0x4c);
-
-/**
- * mei_amthif_reset_params - initializes mei device iamthif
- *
- * @dev: the device structure
- */
-void mei_amthif_reset_params(struct mei_device *dev)
-{
-	/* reset iamthif parameters. */
-	dev->iamthif_canceled = false;
-	dev->iamthif_state = MEI_IAMTHIF_IDLE;
-	dev->iamthif_stall_timer = 0;
-	dev->iamthif_open_count = 0;
-}
-
-/**
- * mei_amthif_host_init - mei initialization amthif client.
- *
- * @dev: the device structure
- * @me_cl: me client
- *
- * Return: 0 on success, <0 on failure.
- */
-int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
-{
-	struct mei_cl *cl = &dev->iamthif_cl;
-	int ret;
-
-	mutex_lock(&dev->device_lock);
-
-	if (mei_cl_is_connected(cl)) {
-		ret = 0;
-		goto out;
-	}
-
-	dev->iamthif_state = MEI_IAMTHIF_IDLE;
-
-	mei_cl_init(cl, dev);
-
-	ret = mei_cl_link(cl);
-	if (ret < 0) {
-		dev_err(dev->dev, "amthif: failed cl_link %d\n", ret);
-		goto out;
-	}
-
-	ret = mei_cl_connect(cl, me_cl, NULL);
-
-out:
-	mutex_unlock(&dev->device_lock);
-	return ret;
-}
-
-/**
- * mei_amthif_read_start - queue message for sending read credential
- *
- * @cl: host client
- * @fp: file pointer of message recipient
- *
- * Return: 0 on success, <0 on failure.
- */
-static int mei_amthif_read_start(struct mei_cl *cl, const struct file *fp)
-{
-	struct mei_device *dev = cl->dev;
-	struct mei_cl_cb *cb;
-
-	cb = mei_cl_enqueue_ctrl_wr_cb(cl, mei_cl_mtu(cl), MEI_FOP_READ, fp);
-	if (!cb)
-		return -ENOMEM;
-
-	cl->rx_flow_ctrl_creds++;
-
-	dev->iamthif_state = MEI_IAMTHIF_READING;
-	cl->fp = cb->fp;
-
-	return 0;
-}
-
-/**
- * mei_amthif_run_next_cmd - send next amt command from queue
- *
- * @dev: the device structure
- *
- * Return: 0 on success, <0 on failure.
- */
-int mei_amthif_run_next_cmd(struct mei_device *dev)
-{
-	struct mei_cl *cl = &dev->iamthif_cl;
-	struct mei_cl_cb *cb;
-	int ret;
-
-	dev->iamthif_canceled = false;
-
-	dev_dbg(dev->dev, "complete amthif cmd_list cb.\n");
-
-	cb = list_first_entry_or_null(&dev->amthif_cmd_list, typeof(*cb), list);
-	if (!cb) {
-		dev->iamthif_state = MEI_IAMTHIF_IDLE;
-		cl->fp = NULL;
-		return 0;
-	}
-
-	list_del_init(&cb->list);
-	dev->iamthif_state = MEI_IAMTHIF_WRITING;
-	cl->fp = cb->fp;
-
-	ret = mei_cl_write(cl, cb);
-	if (ret < 0)
-		return ret;
-
-	if (cb->completed)
-		cb->status = mei_amthif_read_start(cl, cb->fp);
-
-	return 0;
-}
-
-/**
- * mei_amthif_write - write amthif data to amthif client
- *
- * @cl: host client
- * @cb: mei call back struct
- *
- * Return: 0 on success, <0 on failure.
- */
-int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
-{
-
-	struct mei_device *dev = cl->dev;
-
-	list_add_tail(&cb->list, &dev->amthif_cmd_list);
-
-	/*
-	 * The previous request is still in processing, queue this one.
-	 */
-	if (dev->iamthif_state != MEI_IAMTHIF_IDLE)
-		return 0;
-
-	return mei_amthif_run_next_cmd(dev);
-}
-
-/**
- * mei_amthif_poll - the amthif poll function
- *
- * @file: pointer to file structure
- * @wait: pointer to poll_table structure
- *
- * Return: poll mask
- *
- * Locking: called under "dev->device_lock" lock
- */
-unsigned int mei_amthif_poll(struct file *file, poll_table *wait)
-{
-	struct mei_cl *cl = file->private_data;
-	struct mei_cl_cb *cb = mei_cl_read_cb(cl, file);
-	unsigned int mask = 0;
-
-	poll_wait(file, &cl->rx_wait, wait);
-	if (cb)
-		mask |= POLLIN | POLLRDNORM;
-
-	return mask;
-}
-
-/**
- * mei_amthif_irq_write - write iamthif command in irq thread context.
- *
- * @cl: private data of the file object.
- * @cb: callback block.
- * @cmpl_list: complete list.
- *
- * Return: 0, OK; otherwise, error.
- */
-int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
-			 struct list_head *cmpl_list)
-{
-	int ret;
-
-	ret = mei_cl_irq_write(cl, cb, cmpl_list);
-	if (ret)
-		return ret;
-
-	if (cb->completed)
-		cb->status = mei_amthif_read_start(cl, cb->fp);
-
-	return 0;
-}
-
-/**
- * mei_amthif_irq_read_msg - read routine after ISR to
- *			handle the read amthif message
- *
- * @cl: mei client
- * @mei_hdr: header of amthif message
- * @cmpl_list: completed callbacks list
- *
- * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
- */
-int mei_amthif_irq_read_msg(struct mei_cl *cl,
-			    struct mei_msg_hdr *mei_hdr,
-			    struct list_head *cmpl_list)
-{
-	struct mei_device *dev;
-	int ret;
-
-	dev = cl->dev;
-
-	if (dev->iamthif_state != MEI_IAMTHIF_READING) {
-		mei_irq_discard_msg(dev, mei_hdr);
-		return 0;
-	}
-
-	ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
-	if (ret)
-		return ret;
-
-	if (!mei_hdr->msg_complete)
-		return 0;
-
-	dev_dbg(dev->dev, "completed amthif read.\n ");
-	dev->iamthif_stall_timer = 0;
-
-	return 0;
-}
-
-/**
- * mei_amthif_complete - complete amthif callback.
- *
- * @cl: host client
- * @cb: callback block.
- */
-void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
-{
-	struct mei_device *dev = cl->dev;
-
-	dev_dbg(dev->dev, "completing amthif call back.\n");
-	switch (cb->fop_type) {
-	case MEI_FOP_WRITE:
-		if (!cb->status) {
-			dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
-			mei_schedule_stall_timer(dev);
-			mei_io_cb_free(cb);
-			return;
-		}
-		dev->iamthif_state = MEI_IAMTHIF_IDLE;
-		cl->fp = NULL;
-		if (!dev->iamthif_canceled) {
-			/*
-			 * in case of error enqueue the write cb to complete
-			 * read list so it can be propagated to the reader
-			 */
-			list_add_tail(&cb->list, &cl->rd_completed);
-			wake_up_interruptible(&cl->rx_wait);
-		} else {
-			mei_io_cb_free(cb);
-		}
-		break;
-	case MEI_FOP_READ:
-		if (!dev->iamthif_canceled) {
-			list_add_tail(&cb->list, &cl->rd_completed);
-			dev_dbg(dev->dev, "amthif read completed\n");
-			wake_up_interruptible(&cl->rx_wait);
-		} else {
-			mei_io_cb_free(cb);
-		}
-
-		dev->iamthif_stall_timer = 0;
-		mei_amthif_run_next_cmd(dev);
-		break;
-	default:
-		WARN_ON(1);
-	}
-}
-
-/**
-* mei_amthif_release - the release function
-*
-*  @dev: device structure
-*  @fp: pointer to file structure
-*
-*  Return: 0 on success, <0 on error
-*/
-int mei_amthif_release(struct mei_device *dev, struct file *fp)
-{
-	struct mei_cl *cl = fp->private_data;
-
-	if (dev->iamthif_open_count > 0)
-		dev->iamthif_open_count--;
-
-	if (cl->fp == fp && dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-
-		dev_dbg(dev->dev, "amthif canceled iamthif state %d\n",
-			dev->iamthif_state);
-		dev->iamthif_canceled = true;
-	}
-
-	/* Don't clean ctrl_rd_list here, the reads has to be completed */
-	mei_io_list_free_fp(&dev->amthif_cmd_list, fp);
-	mei_io_list_free_fp(&cl->rd_completed, fp);
-
-	return 0;
-}
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index df5f78ae3d25..d1928fdd0f43 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -1076,12 +1076,6 @@ void mei_cl_bus_rescan_work(struct work_struct *work)
 {
 	struct mei_device *bus =
 		container_of(work, struct mei_device, bus_rescan_work);
-	struct mei_me_client *me_cl;
-
-	me_cl = mei_me_cl_by_uuid(bus, &mei_amthif_guid);
-	if (me_cl)
-		mei_amthif_host_init(bus, me_cl);
-	mei_me_cl_put(me_cl);
 
 	mei_cl_bus_rescan(bus);
 }
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index d3e3372424d6..be64969d986a 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -428,7 +428,7 @@ static inline void mei_io_list_free_cl(struct list_head *head,
  * @head: io list
  * @fp: file pointer (matching cb file object), may be NULL
  */
-void mei_io_list_free_fp(struct list_head *head, const struct file *fp)
+static void mei_io_list_free_fp(struct list_head *head, const struct file *fp)
 {
 	struct mei_cl_cb *cb, *next;
 
@@ -554,7 +554,7 @@ int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
  * @cl: host client to be initialized
  * @dev: mei device
  */
-void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
+static void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
 {
 	memset(cl, 0, sizeof(struct mei_cl));
 	init_waitqueue_head(&cl->wait);
@@ -600,7 +600,6 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 int mei_cl_link(struct mei_cl *cl)
 {
 	struct mei_device *dev;
-	long open_handle_count;
 	int id;
 
 	if (WARN_ON(!cl || !cl->dev))
@@ -614,8 +613,7 @@ int mei_cl_link(struct mei_cl *cl)
 		return -EMFILE;
 	}
 
-	open_handle_count = dev->open_handle_count + dev->iamthif_open_count;
-	if (open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
+	if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT) {
 		dev_err(dev->dev, "open_handle_count exceeded %d",
 			MEI_MAX_OPEN_HANDLE_COUNT);
 		return -EMFILE;
@@ -649,8 +647,7 @@ int mei_cl_unlink(struct mei_cl *cl)
 	if (!cl)
 		return 0;
 
-	/* amthif might not be initialized */
-	if (!cl->dev)
+	if (WARN_ON(!cl->dev))
 		return 0;
 
 	dev = cl->dev;
@@ -763,7 +760,6 @@ static void mei_cl_set_disconnected(struct mei_cl *cl)
 	mei_io_list_free_cl(&dev->write_waiting_list, cl);
 	mei_io_list_flush_cl(&dev->ctrl_rd_list, cl);
 	mei_io_list_flush_cl(&dev->ctrl_wr_list, cl);
-	mei_io_list_free_cl(&dev->amthif_cmd_list, cl);
 	mei_cl_wake_all(cl);
 	cl->rx_flow_ctrl_creds = 0;
 	cl->tx_flow_ctrl_creds = 0;
@@ -1478,7 +1474,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
 		return  -ENOTTY;
 	}
 
-	if (mei_cl_is_fixed_address(cl) || cl == &dev->iamthif_cl)
+	if (mei_cl_is_fixed_address(cl))
 		return 0;
 
 	/* HW currently supports only one pending read */
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 545ae319ba90..5371df4d8af3 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -83,15 +83,12 @@ static inline u8 mei_me_cl_ver(const struct mei_me_client *me_cl)
  * MEI IO Functions
  */
 void mei_io_cb_free(struct mei_cl_cb *priv_cb);
-void mei_io_list_free_fp(struct list_head *head, const struct file *fp);
 
 /*
  * MEI Host Client Functions
  */
 
 struct mei_cl *mei_cl_allocate(struct mei_device *dev);
-void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
-
 
 int mei_cl_link(struct mei_cl *cl);
 int mei_cl_unlink(struct mei_cl *cl);
@@ -205,8 +202,6 @@ int mei_cl_connect(struct mei_cl *cl, struct mei_me_client *me_cl,
 int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
 		       struct list_head *cmpl_list);
 int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp);
-int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr,
-			struct list_head *cmpl_list);
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb);
 int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 		     struct list_head *cmpl_list);
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 13c55b8f9261..c8ad9ee7cb80 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -146,18 +146,9 @@ int mei_reset(struct mei_device *dev)
 	/* fall through and remove the sw state even if hw reset has failed */
 
 	/* no need to clean up software state in case of power up */
-	if (state != MEI_DEV_INITIALIZING &&
-	    state != MEI_DEV_POWER_UP) {
-
-		/* remove all waiting requests */
+	if (state != MEI_DEV_INITIALIZING && state != MEI_DEV_POWER_UP)
 		mei_cl_all_disconnect(dev);
 
-		/* remove entry if already in list */
-		dev_dbg(dev->dev, "remove iamthif from the file list.\n");
-		mei_cl_unlink(&dev->iamthif_cl);
-		mei_amthif_reset_params(dev);
-	}
-
 	mei_hbm_reset(dev);
 
 	dev->rd_msg_hdr = 0;
@@ -401,9 +392,6 @@ void mei_device_init(struct mei_device *dev,
 	INIT_WORK(&dev->reset_work, mei_reset_work);
 	INIT_WORK(&dev->bus_rescan_work, mei_cl_bus_rescan_work);
 
-	INIT_LIST_HEAD(&dev->iamthif_cl.link);
-	INIT_LIST_HEAD(&dev->amthif_cmd_list);
-
 	bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
 	dev->open_handle_count = 0;
 
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 406e9e2b2fff..c14e35201721 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -47,10 +47,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct list_head *cmpl_list)
 		list_del_init(&cb->list);
 
 		dev_dbg(dev->dev, "completing call back.\n");
-		if (cl == &dev->iamthif_cl)
-			mei_amthif_complete(cl, cb);
-		else
-			mei_cl_complete(cl, cb);
+		mei_cl_complete(cl, cb);
 	}
 }
 EXPORT_SYMBOL_GPL(mei_irq_compl_handler);
@@ -76,7 +73,7 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
  * @dev: mei device
  * @hdr: message header
  */
-void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
+static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
 {
 	/*
 	 * no need to check for size as it is guarantied
@@ -96,9 +93,9 @@ void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
  *
  * Return: always 0
  */
-int mei_cl_irq_read_msg(struct mei_cl *cl,
-		       struct mei_msg_hdr *mei_hdr,
-		       struct list_head *cmpl_list)
+static int mei_cl_irq_read_msg(struct mei_cl *cl,
+			       struct mei_msg_hdr *mei_hdr,
+			       struct list_head *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
 	struct mei_cl_cb *cb;
@@ -313,11 +310,7 @@ int mei_irq_read_handler(struct mei_device *dev,
 		goto end;
 	}
 
-	if (cl == &dev->iamthif_cl) {
-		ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
-	} else {
-		ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
-	}
+	ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
 
 
 reset_slots:
@@ -423,10 +416,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct list_head *cmpl_list)
 	dev_dbg(dev->dev, "complete write list cb.\n");
 	list_for_each_entry_safe(cb, next, &dev->write_list, list) {
 		cl = cb->cl;
-		if (cl == &dev->iamthif_cl)
-			ret = mei_amthif_irq_write(cl, cb, cmpl_list);
-		else
-			ret = mei_cl_irq_write(cl, cb, cmpl_list);
+		ret = mei_cl_irq_write(cl, cb, cmpl_list);
 		if (ret)
 			return ret;
 	}
@@ -512,20 +502,6 @@ void mei_timer(struct work_struct *work)
 		}
 	}
 
-	if (!mei_cl_is_connected(&dev->iamthif_cl))
-		goto out;
-
-	if (dev->iamthif_stall_timer) {
-		if (--dev->iamthif_stall_timer == 0) {
-			dev_err(dev->dev, "timer: amthif  hanged.\n");
-			mei_reset(dev);
-
-			mei_amthif_run_next_cmd(dev);
-			goto out;
-		}
-		reschedule_timer = true;
-	}
-
 out:
 	if (dev->dev_state != MEI_DEV_DISABLED && reschedule_timer)
 		mei_schedule_stall_timer(dev);
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index bf816449cd40..9802c5930c10 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -103,10 +103,7 @@ static int mei_release(struct inode *inode, struct file *file)
 	dev = cl->dev;
 
 	mutex_lock(&dev->device_lock);
-	if (cl == &dev->iamthif_cl) {
-		rets = mei_amthif_release(dev, file);
-		goto out;
-	}
+
 	rets = mei_cl_disconnect(cl);
 
 	mei_cl_flush_queues(cl, file);
@@ -117,7 +114,7 @@ static int mei_release(struct inode *inode, struct file *file)
 	file->private_data = NULL;
 
 	kfree(cl);
-out:
+
 	mutex_unlock(&dev->device_lock);
 	return rets;
 }
@@ -182,8 +179,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		goto out;
 	}
 
-
-again:
 	mutex_unlock(&dev->device_lock);
 	if (wait_event_interruptible(cl->rx_wait,
 				     !list_empty(&cl->rd_completed) ||
@@ -201,14 +196,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 
 	cb = mei_cl_read_cb(cl, file);
 	if (!cb) {
-		/*
-		 * For amthif all the waiters are woken up,
-		 * but only fp with matching cb->fp get the cb,
-		 * the others have to return to wait on read.
-		 */
-		if (cl == &dev->iamthif_cl)
-			goto again;
-
 		rets = 0;
 		goto out;
 	}
@@ -319,13 +306,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		goto out;
 	}
 
-	if (cl == &dev->iamthif_cl) {
-		rets = mei_amthif_write(cl, cb);
-		if (!rets)
-			rets = length;
-		goto out;
-	}
-
 	rets = mei_cl_write(cl, cb);
 out:
 	mutex_unlock(&dev->device_lock);
@@ -388,30 +368,6 @@ static int mei_ioctl_connect_client(struct file *file,
 	dev_dbg(dev->dev, "FW Client - Max Msg Len = %d\n",
 			me_cl->props.max_msg_length);
 
-	/* if we're connecting to amthif client then we will use the
-	 * existing connection
-	 */
-	if (uuid_le_cmp(data->in_client_uuid, mei_amthif_guid) == 0) {
-		dev_dbg(dev->dev, "FW Client is amthi\n");
-		if (!mei_cl_is_connected(&dev->iamthif_cl)) {
-			rets = -ENODEV;
-			goto end;
-		}
-		mei_cl_unlink(cl);
-
-		kfree(cl);
-		cl = NULL;
-		dev->iamthif_open_count++;
-		file->private_data = &dev->iamthif_cl;
-
-		client = &data->out_client_properties;
-		client->max_msg_length = me_cl->props.max_msg_length;
-		client->protocol_version = me_cl->props.protocol_version;
-		rets = dev->iamthif_cl.status;
-
-		goto end;
-	}
-
 	/* prepare the output buffer */
 	client = &data->out_client_properties;
 	client->max_msg_length = me_cl->props.max_msg_length;
@@ -615,11 +571,6 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 			mask |= POLLPRI;
 	}
 
-	if (cl == &dev->iamthif_cl) {
-		mask |= mei_amthif_poll(file, wait);
-		goto out;
-	}
-
 	if (req_events & (POLLIN | POLLRDNORM)) {
 		poll_wait(file, &cl->rx_wait, wait);
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index d41aac53a2ac..63a67c99fc78 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -26,12 +26,6 @@
 #include "hw.h"
 #include "hbm.h"
 
-
-/*
- * AMTHI Client UUID
- */
-extern const uuid_le mei_amthif_guid;
-
 #define MEI_RD_MSG_BUF_SIZE           (128 * sizeof(u32))
 
 /*
@@ -78,12 +72,6 @@ enum mei_dev_state {
 
 const char *mei_dev_state_str(int state);
 
-enum iamthif_states {
-	MEI_IAMTHIF_IDLE,
-	MEI_IAMTHIF_WRITING,
-	MEI_IAMTHIF_READING,
-};
-
 enum mei_file_transaction_states {
 	MEI_IDLE,
 	MEI_WRITING,
@@ -418,13 +406,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @allow_fixed_address: allow user space to connect a fixed client
  * @override_fixed_address: force allow fixed address behavior
  *
- * @amthif_cmd_list : amthif list for cmd waiting
- * @iamthif_cl  : amthif host client
- * @iamthif_open_count : number of opened amthif connections
- * @iamthif_stall_timer : timer to detect amthif hang
- * @iamthif_state : amthif processor state
- * @iamthif_canceled : current amthif command is canceled
- *
  * @reset_work  : work item for the device reset
  * @bus_rescan_work : work item for the bus rescan
  *
@@ -500,14 +481,6 @@ struct mei_device {
 	bool allow_fixed_address;
 	bool override_fixed_address;
 
-	/* amthif list for cmd waiting */
-	struct list_head amthif_cmd_list;
-	struct mei_cl iamthif_cl;
-	long iamthif_open_count;
-	u32 iamthif_stall_timer;
-	enum iamthif_states iamthif_state;
-	bool iamthif_canceled;
-
 	struct work_struct reset_work;
 	struct work_struct bus_rescan_work;
 
@@ -579,28 +552,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct list_head *cmpl_list);
 void mei_irq_compl_handler(struct mei_device *dev, struct list_head *cmpl_list);
 
 /*
- * AMTHIF - AMT Host Interface Functions
- */
-void mei_amthif_reset_params(struct mei_device *dev);
-
-int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl);
-
-unsigned int mei_amthif_poll(struct file *file, poll_table *wait);
-
-int mei_amthif_release(struct mei_device *dev, struct file *file);
-
-int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb);
-int mei_amthif_run_next_cmd(struct mei_device *dev);
-int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
-			 struct list_head *cmpl_list);
-
-void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb);
-int mei_amthif_irq_read_msg(struct mei_cl *cl,
-			    struct mei_msg_hdr *mei_hdr,
-			    struct list_head *cmpl_list);
-int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
-
-/*
  * Register Access Function
  */
 
@@ -711,8 +662,6 @@ bool mei_hbuf_acquire(struct mei_device *dev);
 
 bool mei_write_is_idle(struct mei_device *dev);
 
-void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr);
-
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 int mei_dbgfs_register(struct mei_device *dev, const char *name);
 void mei_dbgfs_deregister(struct mei_device *dev);
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1604538 — [char-misc-next 3/5] mei: hbm: remove variable length arrays

FromTomas Winkler <tomas.winkler@intel.com>
Date2017-03-20 14:10 +0100
Subject[char-misc-next 3/5] mei: hbm: remove variable length arrays
Message-ID<tn5eq-5aQ-47@gated-at.bofh.it>
In reply to#1604531
Though VLA are supported by CC99 there are many cavities
and should be avoided.

'const size_t len = sizeof()' that we used may not be set
at the compile time hence generating VLA code.

This fixes also sparse warning
warning: Variable length array is used type.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/hbm.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index ba3a774c8d71..fe6595fe94f1 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -166,9 +166,8 @@ void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len)
  *
  * Return: 0 on success, <0 on failure.
  */
-static inline
-int mei_hbm_cl_write(struct mei_device *dev, struct mei_cl *cl,
-		     u8 hbm_cmd, u8 *buf, size_t len)
+static inline int mei_hbm_cl_write(struct mei_device *dev, struct mei_cl *cl,
+				   u8 hbm_cmd, void *buf, size_t len)
 {
 	struct mei_msg_hdr mei_hdr;
 
@@ -632,11 +631,11 @@ static int mei_hbm_stop_req(struct mei_device *dev)
  */
 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl)
 {
-	const size_t len = sizeof(struct hbm_flow_control);
-	u8 buf[len];
+	struct hbm_flow_control req;
 
 	cl_dbg(dev, cl, "sending flow control\n");
-	return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD, buf, len);
+	return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD,
+				&req, sizeof(req));
 }
 
 /**
@@ -710,10 +709,10 @@ static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev,
  */
 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
 {
-	const size_t len = sizeof(struct hbm_client_connect_request);
-	u8 buf[len];
+	struct hbm_client_connect_request req;
 
-	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD, buf, len);
+	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD,
+				&req, sizeof(req));
 }
 
 /**
@@ -726,10 +725,10 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
  */
 int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
 {
-	const size_t len = sizeof(struct hbm_client_connect_response);
-	u8 buf[len];
+	struct hbm_client_connect_response resp;
 
-	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD, buf, len);
+	return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD,
+				&resp, sizeof(resp));
 }
 
 /**
@@ -763,10 +762,10 @@ static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl,
  */
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl)
 {
-	const size_t len = sizeof(struct hbm_client_connect_request);
-	u8 buf[len];
+	struct hbm_client_connect_request req;
 
-	return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD, buf, len);
+	return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD,
+				&req, sizeof(req));
 }
 
 /**
-- 
2.9.3

[toc] | [prev] | [next] | [standalone]


#1604542 — [char-misc-next 5/5] mei: implement fsync

FromTomas Winkler <tomas.winkler@intel.com>
Date2017-03-20 14:10 +0100
Subject[char-misc-next 5/5] mei: implement fsync
Message-ID<tn5er-5aQ-51@gated-at.bofh.it>
In reply to#1604531
From: Alexander Usyskin <alexander.usyskin@intel.com>

When write() returns successfully, it is only assumed that a message
was successfully queued. Add fsync syscall implementation to help
user-space ensure that all data is written.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
---
 drivers/misc/mei/main.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 72 insertions(+)

diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 9802c5930c10..e825f013e54e 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -586,6 +586,77 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
 }
 
 /**
+ * mei_cl_is_write_queued - check if the client has pending writes.
+ *
+ * @cl: writing host client
+ *
+ * Return: true if client is writing, false otherwise.
+ */
+static bool mei_cl_is_write_queued(struct mei_cl *cl)
+{
+	struct mei_device *dev = cl->dev;
+	struct mei_cl_cb *cb;
+
+	list_for_each_entry(cb, &dev->write_list, list)
+		if (cb->cl == cl)
+			return true;
+	list_for_each_entry(cb, &dev->write_waiting_list, list)
+		if (cb->cl == cl)
+			return true;
+	return false;
+}
+
+/**
+ * mei_fsync - the fsync handler
+ *
+ * @fp:       pointer to file structure
+ * @start:    unused
+ * @end:      unused
+ * @datasync: unused
+ *
+ * Return: 0 on success, -ENODEV if client is not connected
+ */
+static int mei_fsync(struct file *fp, loff_t start, loff_t end, int datasync)
+{
+	struct mei_cl *cl = fp->private_data;
+	struct mei_device *dev;
+	int rets;
+
+	if (WARN_ON(!cl || !cl->dev))
+		return -ENODEV;
+
+	dev = cl->dev;
+
+	mutex_lock(&dev->device_lock);
+
+	if (dev->dev_state != MEI_DEV_ENABLED || !mei_cl_is_connected(cl)) {
+		rets = -ENODEV;
+		goto out;
+	}
+
+	while (mei_cl_is_write_queued(cl)) {
+		mutex_unlock(&dev->device_lock);
+		rets = wait_event_interruptible(cl->tx_wait,
+				cl->writing_state == MEI_WRITE_COMPLETE ||
+				!mei_cl_is_connected(cl));
+		mutex_lock(&dev->device_lock);
+		if (rets) {
+			if (signal_pending(current))
+				rets = -EINTR;
+			goto out;
+		}
+		if (!mei_cl_is_connected(cl)) {
+			rets = -ENODEV;
+			goto out;
+		}
+	}
+	rets = 0;
+out:
+	mutex_unlock(&dev->device_lock);
+	return rets;
+}
+
+/**
  * mei_fasync - asynchronous io support
  *
  * @fd: file descriptor
@@ -700,6 +771,7 @@ static const struct file_operations mei_fops = {
 	.release = mei_release,
 	.write = mei_write,
 	.poll = mei_poll,
+	.fsync = mei_fsync,
 	.fasync = mei_fasync,
 	.llseek = no_llseek
 };
-- 
2.9.3

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web