mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [char-misc-next 02/18] mei: revamp me clients list handling
@ 2015-02-10  8:39 Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 03/18] mei: me: use io register wrappers consistently Tomas Winkler
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

1. Use rw lock to access the me_clients list

2. Reuse already defined find functions also when
removing particular me client

3. Add wrappers for addition  and deletion

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/client.c  | 194 +++++++++++++++++++++++++++++++++------------
 drivers/misc/mei/client.h  |   5 +-
 drivers/misc/mei/debugfs.c |  19 +++--
 drivers/misc/mei/hbm.c     |   3 +-
 drivers/misc/mei/init.c    |   1 +
 drivers/misc/mei/mei_dev.h |   2 +
 6 files changed, 162 insertions(+), 62 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 9541218c10eb..e7d28c9961fd 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -48,14 +48,14 @@ void mei_me_cl_init(struct mei_me_client *me_cl)
  */
 struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl)
 {
-	if (me_cl)
-		kref_get(&me_cl->refcnt);
+	if (me_cl && kref_get_unless_zero(&me_cl->refcnt))
+		return me_cl;
 
-	return me_cl;
+	return NULL;
 }
 
 /**
- * mei_me_cl_release - unlink and free me client
+ * mei_me_cl_release - free me client
  *
  * Locking: called under "dev->device_lock" lock
  *
@@ -65,9 +65,10 @@ static void mei_me_cl_release(struct kref *ref)
 {
 	struct mei_me_client *me_cl =
 		container_of(ref, struct mei_me_client, refcnt);
-	list_del(&me_cl->list);
+
 	kfree(me_cl);
 }
+
 /**
  * mei_me_cl_put - decrease me client refcount and free client if necessary
  *
@@ -82,51 +83,146 @@ void mei_me_cl_put(struct mei_me_client *me_cl)
 }
 
 /**
- * mei_me_cl_by_uuid - locate me client by uuid
+ * __mei_me_cl_del  - delete me client form the list and decrease
+ *     reference counter
+ *
+ * @dev: mei device
+ * @me_cl: me client
+ *
+ * Locking: dev->me_clients_rwsem
+ */
+static void __mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl)
+{
+	if (!me_cl)
+		return;
+
+	list_del(&me_cl->list);
+	mei_me_cl_put(me_cl);
+}
+
+/**
+ * mei_me_cl_add - add me client to the list
+ *
+ * @dev: mei device
+ * @me_cl: me client
+ */
+void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl)
+{
+	down_write(&dev->me_clients_rwsem);
+	list_add(&me_cl->list, &dev->me_clients);
+	up_write(&dev->me_clients_rwsem);
+}
+
+/**
+ * __mei_me_cl_by_uuid - locate me client by uuid
  *	increases ref count
  *
  * @dev: mei device
  * @uuid: me client uuid
  *
- * Locking: called under "dev->device_lock" lock
- *
  * Return: me client or NULL if not found
+ *
+ * Locking: dev->me_clients_rwsem
  */
-struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
+static struct mei_me_client *__mei_me_cl_by_uuid(struct mei_device *dev,
 					const uuid_le *uuid)
 {
 	struct mei_me_client *me_cl;
+	const uuid_le *pn;
+
+	WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
 
-	list_for_each_entry(me_cl, &dev->me_clients, list)
-		if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0)
+	list_for_each_entry(me_cl, &dev->me_clients, list) {
+		pn = &me_cl->props.protocol_name;
+		if (uuid_le_cmp(*uuid, *pn) == 0)
 			return mei_me_cl_get(me_cl);
+	}
 
 	return NULL;
 }
 
 /**
+ * mei_me_cl_by_uuid - locate me client by uuid
+ *	increases ref count
+ *
+ * @dev: mei device
+ * @uuid: me client uuid
+ *
+ * Return: me client or NULL if not found
+ *
+ * Locking: dev->me_clients_rwsem
+ */
+struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
+					const uuid_le *uuid)
+{
+	struct mei_me_client *me_cl;
+
+	down_read(&dev->me_clients_rwsem);
+	me_cl = __mei_me_cl_by_uuid(dev, uuid);
+	up_read(&dev->me_clients_rwsem);
+
+	return me_cl;
+}
+
+/**
  * mei_me_cl_by_id - locate me client by client id
  *	increases ref count
  *
  * @dev: the device structure
  * @client_id: me client id
  *
- * Locking: called under "dev->device_lock" lock
- *
  * Return: me client or NULL if not found
+ *
+ * Locking: dev->me_clients_rwsem
  */
 struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
 {
 
+	struct mei_me_client *__me_cl, *me_cl = NULL;
+
+	down_read(&dev->me_clients_rwsem);
+	list_for_each_entry(__me_cl, &dev->me_clients, list) {
+		if (__me_cl->client_id == client_id) {
+			me_cl = mei_me_cl_get(__me_cl);
+			break;
+		}
+	}
+	up_read(&dev->me_clients_rwsem);
+
+	return me_cl;
+}
+
+/**
+ * __mei_me_cl_by_uuid_id - locate me client by client id and uuid
+ *	increases ref count
+ *
+ * @dev: the device structure
+ * @uuid: me client uuid
+ * @client_id: me client id
+ *
+ * Return: me client or null if not found
+ *
+ * Locking: dev->me_clients_rwsem
+ */
+static struct mei_me_client *__mei_me_cl_by_uuid_id(struct mei_device *dev,
+					   const uuid_le *uuid, u8 client_id)
+{
 	struct mei_me_client *me_cl;
+	const uuid_le *pn;
+
+	WARN_ON(!rwsem_is_locked(&dev->me_clients_rwsem));
 
-	list_for_each_entry(me_cl, &dev->me_clients, list)
-		if (me_cl->client_id == client_id)
+	list_for_each_entry(me_cl, &dev->me_clients, list) {
+		pn = &me_cl->props.protocol_name;
+		if (uuid_le_cmp(*uuid, *pn) == 0 &&
+		    me_cl->client_id == client_id)
 			return mei_me_cl_get(me_cl);
+	}
 
 	return NULL;
 }
 
+
 /**
  * mei_me_cl_by_uuid_id - locate me client by client id and uuid
  *	increases ref count
@@ -135,21 +231,18 @@ struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id)
  * @uuid: me client uuid
  * @client_id: me client id
  *
- * Locking: called under "dev->device_lock" lock
- *
- * Return: me client or NULL if not found
+ * Return: me client or null if not found
  */
 struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
 					   const uuid_le *uuid, u8 client_id)
 {
 	struct mei_me_client *me_cl;
 
-	list_for_each_entry(me_cl, &dev->me_clients, list)
-		if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0 &&
-		    me_cl->client_id == client_id)
-			return mei_me_cl_get(me_cl);
+	down_read(&dev->me_clients_rwsem);
+	me_cl = __mei_me_cl_by_uuid_id(dev, uuid, client_id);
+	up_read(&dev->me_clients_rwsem);
 
-	return NULL;
+	return me_cl;
 }
 
 /**
@@ -162,12 +255,14 @@ struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
  */
 void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
 {
-	struct mei_me_client *me_cl, *next;
+	struct mei_me_client *me_cl;
 
 	dev_dbg(dev->dev, "remove %pUl\n", uuid);
-	list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
-		if (uuid_le_cmp(*uuid, me_cl->props.protocol_name) == 0)
-			mei_me_cl_put(me_cl);
+
+	down_write(&dev->me_clients_rwsem);
+	me_cl = __mei_me_cl_by_uuid(dev, uuid);
+	__mei_me_cl_del(dev, me_cl);
+	up_write(&dev->me_clients_rwsem);
 }
 
 /**
@@ -181,15 +276,14 @@ void mei_me_cl_rm_by_uuid(struct mei_device *dev, const uuid_le *uuid)
  */
 void mei_me_cl_rm_by_uuid_id(struct mei_device *dev, const uuid_le *uuid, u8 id)
 {
-	struct mei_me_client *me_cl, *next;
-	const uuid_le *pn;
+	struct mei_me_client *me_cl;
 
 	dev_dbg(dev->dev, "remove %pUl %d\n", uuid, id);
-	list_for_each_entry_safe(me_cl, next, &dev->me_clients, list) {
-		pn =  &me_cl->props.protocol_name;
-		if (me_cl->client_id == id && uuid_le_cmp(*uuid, *pn) == 0)
-			mei_me_cl_put(me_cl);
-	}
+
+	down_write(&dev->me_clients_rwsem);
+	me_cl = __mei_me_cl_by_uuid_id(dev, uuid, id);
+	__mei_me_cl_del(dev, me_cl);
+	up_write(&dev->me_clients_rwsem);
 }
 
 /**
@@ -203,12 +297,12 @@ void mei_me_cl_rm_all(struct mei_device *dev)
 {
 	struct mei_me_client *me_cl, *next;
 
+	down_write(&dev->me_clients_rwsem);
 	list_for_each_entry_safe(me_cl, next, &dev->me_clients, list)
-			mei_me_cl_put(me_cl);
+		__mei_me_cl_del(dev, me_cl);
+	up_write(&dev->me_clients_rwsem);
 }
 
-
-
 /**
  * mei_cl_cmp_id - tells if the clients are the same
  *
@@ -535,28 +629,28 @@ int mei_cl_unlink(struct mei_cl *cl)
 
 void mei_host_client_init(struct work_struct *work)
 {
-	struct mei_device *dev = container_of(work,
-					      struct mei_device, init_work);
+	struct mei_device *dev =
+		container_of(work, struct mei_device, init_work);
 	struct mei_me_client *me_cl;
-	struct mei_client_properties *props;
 
 	mutex_lock(&dev->device_lock);
 
-	list_for_each_entry(me_cl, &dev->me_clients, list) {
-		props = &me_cl->props;
 
-		if (!uuid_le_cmp(props->protocol_name, mei_amthif_guid))
-			mei_amthif_host_init(dev);
-		else if (!uuid_le_cmp(props->protocol_name, mei_wd_guid))
-			mei_wd_host_init(dev);
-		else if (!uuid_le_cmp(props->protocol_name, mei_nfc_guid))
-			mei_nfc_host_init(dev);
+	me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid);
+	if (me_cl)
+		mei_amthif_host_init(dev);
+
+	me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid);
+	if (me_cl)
+		mei_wd_host_init(dev);
+
+	me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
+	if (me_cl)
+		mei_nfc_host_init(dev);
 
-	}
 
 	dev->dev_state = MEI_DEV_ENABLED;
 	dev->reset_count = 0;
-
 	mutex_unlock(&dev->device_lock);
 
 	pm_runtime_mark_last_busy(dev->dev);
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index cfcde8e97fc4..80386f9c27e9 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -31,7 +31,10 @@ void mei_me_cl_init(struct mei_me_client *me_cl);
 void mei_me_cl_put(struct mei_me_client *me_cl);
 struct mei_me_client *mei_me_cl_get(struct mei_me_client *me_cl);
 
-struct mei_me_client *mei_me_cl_by_uuid(const struct mei_device *dev,
+void mei_me_cl_add(struct mei_device *dev, struct mei_me_client *me_cl);
+void mei_me_cl_del(struct mei_device *dev, struct mei_me_client *me_cl);
+
+struct mei_me_client *mei_me_cl_by_uuid(struct mei_device *dev,
 					const uuid_le *uuid);
 struct mei_me_client *mei_me_cl_by_id(struct mei_device *dev, u8 client_id);
 struct mei_me_client *mei_me_cl_by_uuid_id(struct mei_device *dev,
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index b125380ee871..50fc6635fab1 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -28,7 +28,7 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 					size_t cnt, loff_t *ppos)
 {
 	struct mei_device *dev = fp->private_data;
-	struct mei_me_client *me_cl, *n;
+	struct mei_me_client *me_cl;
 	size_t bufsz = 1;
 	char *buf;
 	int i = 0;
@@ -38,15 +38,14 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 #define HDR \
 "  |id|fix|         UUID                       |con|msg len|sb|refc|\n"
 
-	mutex_lock(&dev->device_lock);
-
+	down_read(&dev->me_clients_rwsem);
 	list_for_each_entry(me_cl, &dev->me_clients, list)
 		bufsz++;
 
 	bufsz *= sizeof(HDR) + 1;
 	buf = kzalloc(bufsz, GFP_KERNEL);
 	if (!buf) {
-		mutex_unlock(&dev->device_lock);
+		up_read(&dev->me_clients_rwsem);
 		return -ENOMEM;
 	}
 
@@ -56,10 +55,9 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 	if (dev->dev_state != MEI_DEV_ENABLED)
 		goto out;
 
-	list_for_each_entry_safe(me_cl, n, &dev->me_clients, list) {
+	list_for_each_entry(me_cl, &dev->me_clients, list) {
 
-		me_cl = mei_me_cl_get(me_cl);
-		if (me_cl) {
+		if (mei_me_cl_get(me_cl)) {
 			pos += scnprintf(buf + pos, bufsz - pos,
 				"%2d|%2d|%3d|%pUl|%3d|%7d|%2d|%4d|\n",
 				i++, me_cl->client_id,
@@ -69,12 +67,13 @@ static ssize_t mei_dbgfs_read_meclients(struct file *fp, char __user *ubuf,
 				me_cl->props.max_msg_length,
 				me_cl->props.single_recv_buf,
 				atomic_read(&me_cl->refcnt.refcount));
-		}
 
-		mei_me_cl_put(me_cl);
+			mei_me_cl_put(me_cl);
+		}
 	}
+
 out:
-	mutex_unlock(&dev->device_lock);
+	up_read(&dev->me_clients_rwsem);
 	ret = simple_read_from_buffer(ubuf, cnt, ppos, buf, pos);
 	kfree(buf);
 	return ret;
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index c8412d41e4f1..4f83e9aaa6f9 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -338,7 +338,8 @@ static int mei_hbm_me_cl_add(struct mei_device *dev,
 	me_cl->client_id = res->me_addr;
 	me_cl->mei_flow_ctrl_creds = 0;
 
-	list_add(&me_cl->list, &dev->me_clients);
+	mei_me_cl_add(dev, me_cl);
+
 	return 0;
 }
 
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 6ad049a08e4d..ad18b0d16f61 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -389,6 +389,7 @@ void mei_device_init(struct mei_device *dev,
 	INIT_LIST_HEAD(&dev->device_list);
 	INIT_LIST_HEAD(&dev->me_clients);
 	mutex_init(&dev->device_lock);
+	init_rwsem(&dev->me_clients_rwsem);
 	init_waitqueue_head(&dev->wait_hw_ready);
 	init_waitqueue_head(&dev->wait_pg);
 	init_waitqueue_head(&dev->wait_hbm_start);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 6c6ce9381535..102cc6603eba 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -460,6 +460,7 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @version     : HBM protocol version in use
  * @hbm_f_pg_supported : hbm feature pgi protocol
  *
+ * @me_clients_rwsem: rw lock over me_clients list
  * @me_clients  : list of FW clients
  * @me_clients_map : FW clients bit map
  * @host_clients_map : host clients id pool
@@ -556,6 +557,7 @@ struct mei_device {
 	struct hbm_version version;
 	unsigned int hbm_f_pg_supported:1;
 
+	struct rw_semaphore me_clients_rwsem;
 	struct list_head me_clients;
 	DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
 	DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 03/18] mei: me: use io register wrappers consistently
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 04/18] mei: me: add io register tracing Tomas Winkler
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

1. Use mei_device structure as the first argument to the io
register access wrappers so we'll have access to the device
structure needed for tracing.

2. Use wrapper consistently

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/hw-me.c | 123 +++++++++++++++++++++++++----------------------
 1 file changed, 66 insertions(+), 57 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index f8fd503dfbd6..ac82b56ccbb5 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -61,45 +61,68 @@ static inline void mei_me_reg_write(const struct mei_me_hw *hw,
  *
  * Return: ME_CB_RW register value (u32)
  */
-static u32 mei_me_mecbrw_read(const struct mei_device *dev)
+static inline u32 mei_me_mecbrw_read(const struct mei_device *dev)
 {
 	return mei_me_reg_read(to_me_hw(dev), ME_CB_RW);
 }
+
+/**
+ * mei_me_hcbww_write - write 32bit data to the host circular buffer
+ *
+ * @dev: the device structure
+ * @data: 32bit data to be written to the host circular buffer
+ */
+static inline void mei_me_hcbww_write(struct mei_device *dev, u32 data)
+{
+	mei_me_reg_write(to_me_hw(dev), H_CB_WW, data);
+}
+
 /**
  * mei_me_mecsr_read - Reads 32bit data from the ME CSR
  *
- * @hw: the me hardware structure
+ * @dev: the device structure
  *
  * Return: ME_CSR_HA register value (u32)
  */
-static inline u32 mei_me_mecsr_read(const struct mei_me_hw *hw)
+static inline u32 mei_me_mecsr_read(const struct mei_device *dev)
 {
-	return mei_me_reg_read(hw, ME_CSR_HA);
+	return mei_me_reg_read(to_me_hw(dev), ME_CSR_HA);
 }
 
 /**
  * mei_hcsr_read - Reads 32bit data from the host CSR
  *
- * @hw: the me hardware structure
+ * @dev: the device structure
  *
  * Return: H_CSR register value (u32)
  */
-static inline u32 mei_hcsr_read(const struct mei_me_hw *hw)
+static inline u32 mei_hcsr_read(const struct mei_device *dev)
 {
-	return mei_me_reg_read(hw, H_CSR);
+	return mei_me_reg_read(to_me_hw(dev), H_CSR);
+}
+
+/**
+ * mei_hcsr_write - writes H_CSR register to the mei device
+ *
+ * @dev: the device structure
+ * @reg: new register value
+ */
+static inline void mei_hcsr_write(struct mei_device *dev, u32 reg)
+{
+	mei_me_reg_write(to_me_hw(dev), H_CSR, reg);
 }
 
 /**
  * mei_hcsr_set - writes H_CSR register to the mei device,
  * and ignores the H_IS bit for it is write-one-to-zero.
  *
- * @hw: the me hardware structure
- * @hcsr: new register value
+ * @dev: the device structure
+ * @reg: new register value
  */
-static inline void mei_hcsr_set(struct mei_me_hw *hw, u32 hcsr)
+static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
 {
-	hcsr &= ~H_IS;
-	mei_me_reg_write(hw, H_CSR, hcsr);
+	reg &= ~H_IS;
+	mei_hcsr_write(dev, reg);
 }
 
 /**
@@ -141,7 +164,7 @@ static int mei_me_fw_status(struct mei_device *dev,
 static void mei_me_hw_config(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(to_me_hw(dev));
+	u32 hcsr = mei_hcsr_read(dev);
 	/* Doesn't change in runtime */
 	dev->hbuf_depth = (hcsr & H_CBD) >> 24;
 
@@ -170,11 +193,10 @@ static inline enum mei_pg_state mei_me_pg_state(struct mei_device *dev)
  */
 static void mei_me_intr_clear(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	if ((hcsr & H_IS) == H_IS)
-		mei_me_reg_write(hw, H_CSR, hcsr);
+		mei_hcsr_write(dev, hcsr);
 }
 /**
  * mei_me_intr_enable - enables mei device interrupts
@@ -183,11 +205,10 @@ static void mei_me_intr_clear(struct mei_device *dev)
  */
 static void mei_me_intr_enable(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	hcsr |= H_IE;
-	mei_hcsr_set(hw, hcsr);
+	mei_hcsr_set(dev, hcsr);
 }
 
 /**
@@ -197,11 +218,10 @@ static void mei_me_intr_enable(struct mei_device *dev)
  */
 static void mei_me_intr_disable(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	hcsr  &= ~H_IE;
-	mei_hcsr_set(hw, hcsr);
+	mei_hcsr_set(dev, hcsr);
 }
 
 /**
@@ -211,12 +231,11 @@ static void mei_me_intr_disable(struct mei_device *dev)
  */
 static void mei_me_hw_reset_release(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	hcsr |= H_IG;
 	hcsr &= ~H_RST;
-	mei_hcsr_set(hw, hcsr);
+	mei_hcsr_set(dev, hcsr);
 
 	/* complete this write before we set host ready on another CPU */
 	mmiowb();
@@ -231,8 +250,7 @@ static void mei_me_hw_reset_release(struct mei_device *dev)
  */
 static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	/* H_RST may be found lit before reset is started,
 	 * for example if preceding reset flow hasn't completed.
@@ -242,8 +260,8 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 	if ((hcsr & H_RST) == H_RST) {
 		dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
 		hcsr &= ~H_RST;
-		mei_hcsr_set(hw, hcsr);
-		hcsr = mei_hcsr_read(hw);
+		mei_hcsr_set(dev, hcsr);
+		hcsr = mei_hcsr_read(dev);
 	}
 
 	hcsr |= H_RST | H_IG | H_IS;
@@ -254,13 +272,13 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
 		hcsr &= ~H_IE;
 
 	dev->recvd_hw_ready = false;
-	mei_me_reg_write(hw, H_CSR, hcsr);
+	mei_hcsr_write(dev, hcsr);
 
 	/*
 	 * Host reads the H_CSR once to ensure that the
 	 * posted write to H_CSR completes.
 	 */
-	hcsr = mei_hcsr_read(hw);
+	hcsr = mei_hcsr_read(dev);
 
 	if ((hcsr & H_RST) == 0)
 		dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
@@ -281,11 +299,10 @@ static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
  */
 static void mei_me_host_set_ready(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	hcsr |= H_IE | H_IG | H_RDY;
-	mei_hcsr_set(hw, hcsr);
+	mei_hcsr_set(dev, hcsr);
 }
 
 /**
@@ -296,8 +313,7 @@ static void mei_me_host_set_ready(struct mei_device *dev)
  */
 static bool mei_me_host_is_ready(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 hcsr = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
 	return (hcsr & H_RDY) == H_RDY;
 }
@@ -310,8 +326,7 @@ static bool mei_me_host_is_ready(struct mei_device *dev)
  */
 static bool mei_me_hw_is_ready(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 mecsr = mei_me_mecsr_read(hw);
+	u32 mecsr = mei_me_mecsr_read(dev);
 
 	return (mecsr & ME_RDY_HRA) == ME_RDY_HRA;
 }
@@ -368,11 +383,10 @@ static int mei_me_hw_start(struct mei_device *dev)
  */
 static unsigned char mei_hbuf_filled_slots(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 hcsr;
 	char read_ptr, write_ptr;
 
-	hcsr = mei_hcsr_read(hw);
+	hcsr = mei_hcsr_read(dev);
 
 	read_ptr = (char) ((hcsr & H_CBRP) >> 8);
 	write_ptr = (char) ((hcsr & H_CBWP) >> 16);
@@ -439,7 +453,6 @@ static int mei_me_write_message(struct mei_device *dev,
 			struct mei_msg_hdr *header,
 			unsigned char *buf)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
 	unsigned long rem;
 	unsigned long length = header->length;
 	u32 *reg_buf = (u32 *)buf;
@@ -457,21 +470,21 @@ static int mei_me_write_message(struct mei_device *dev,
 	if (empty_slots < 0 || dw_cnt > empty_slots)
 		return -EMSGSIZE;
 
-	mei_me_reg_write(hw, H_CB_WW, *((u32 *) header));
+	mei_me_hcbww_write(dev, *((u32 *) header));
 
 	for (i = 0; i < length / 4; i++)
-		mei_me_reg_write(hw, H_CB_WW, reg_buf[i]);
+		mei_me_hcbww_write(dev, reg_buf[i]);
 
 	rem = length & 0x3;
 	if (rem > 0) {
 		u32 reg = 0;
 
 		memcpy(&reg, &buf[length - rem], rem);
-		mei_me_reg_write(hw, H_CB_WW, reg);
+		mei_me_hcbww_write(dev, reg);
 	}
 
-	hcsr = mei_hcsr_read(hw) | H_IG;
-	mei_hcsr_set(hw, hcsr);
+	hcsr = mei_hcsr_read(dev) | H_IG;
+	mei_hcsr_set(dev, hcsr);
 	if (!mei_me_hw_is_ready(dev))
 		return -EIO;
 
@@ -487,12 +500,11 @@ static int mei_me_write_message(struct mei_device *dev,
  */
 static int mei_me_count_full_read_slots(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 me_csr;
 	char read_ptr, write_ptr;
 	unsigned char buffer_depth, filled_slots;
 
-	me_csr = mei_me_mecsr_read(hw);
+	me_csr = mei_me_mecsr_read(dev);
 	buffer_depth = (unsigned char)((me_csr & ME_CBD_HRA) >> 24);
 	read_ptr = (char) ((me_csr & ME_CBRP_HRA) >> 8);
 	write_ptr = (char) ((me_csr & ME_CBWP_HRA) >> 16);
@@ -518,7 +530,6 @@ static int mei_me_count_full_read_slots(struct mei_device *dev)
 static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 		    unsigned long buffer_length)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 *reg_buf = (u32 *)buffer;
 	u32 hcsr;
 
@@ -531,8 +542,8 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 		memcpy(reg_buf, &reg, buffer_length);
 	}
 
-	hcsr = mei_hcsr_read(hw) | H_IG;
-	mei_hcsr_set(hw, hcsr);
+	hcsr = mei_hcsr_read(dev) | H_IG;
+	mei_hcsr_set(dev, hcsr);
 	return 0;
 }
 
@@ -649,8 +660,7 @@ reply:
  */
 static bool mei_me_pg_is_enabled(struct mei_device *dev)
 {
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 reg = mei_me_reg_read(hw, ME_CSR_HA);
+	u32 reg = mei_me_mecsr_read(dev);
 
 	if ((reg & ME_PGIC_HRA) == 0)
 		goto notsupported;
@@ -683,14 +693,13 @@ notsupported:
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
 {
 	struct mei_device *dev = (struct mei_device *) dev_id;
-	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 csr_reg = mei_hcsr_read(hw);
+	u32 hcsr = mei_hcsr_read(dev);
 
-	if ((csr_reg & H_IS) != H_IS)
+	if ((hcsr & H_IS) != H_IS)
 		return IRQ_NONE;
 
 	/* clear H_IS bit in H_CSR */
-	mei_me_reg_write(hw, H_CSR, csr_reg);
+	mei_hcsr_write(dev, hcsr);
 
 	return IRQ_WAKE_THREAD;
 }
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 04/18] mei: me: add io register tracing
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 03/18] mei: me: use io register wrappers consistently Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 05/18] mei: me: change power gating function name conventions Tomas Winkler
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

To make debugging a bit easier we add me register
access tracing
<debugfs>/tracing/events/mei/mei_reg_{read,write}

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/Makefile    |  3 ++
 drivers/misc/mei/hw-me.c     | 31 ++++++++++++++++---
 drivers/misc/mei/mei-trace.c | 25 +++++++++++++++
 drivers/misc/mei/mei-trace.h | 74 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 4 deletions(-)
 create mode 100644 drivers/misc/mei/mei-trace.c
 create mode 100644 drivers/misc/mei/mei-trace.h

diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 8ebc6cda1373..518914a82b83 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -21,3 +21,6 @@ mei-me-objs += hw-me.o
 obj-$(CONFIG_INTEL_MEI_TXE) += mei-txe.o
 mei-txe-objs := pci-txe.o
 mei-txe-objs += hw-txe.o
+
+mei-$(CONFIG_EVENT_TRACING) += mei-trace.o
+CFLAGS_mei-trace.o = -I$(src)
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index ac82b56ccbb5..d3aef82a6c89 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -25,6 +25,8 @@
 #include "hw-me.h"
 #include "hw-me-regs.h"
 
+#include "mei-trace.h"
+
 /**
  * mei_me_reg_read - Reads 32bit data from the mei device
  *
@@ -86,7 +88,12 @@ static inline void mei_me_hcbww_write(struct mei_device *dev, u32 data)
  */
 static inline u32 mei_me_mecsr_read(const struct mei_device *dev)
 {
-	return mei_me_reg_read(to_me_hw(dev), ME_CSR_HA);
+	u32 reg;
+
+	reg = mei_me_reg_read(to_me_hw(dev), ME_CSR_HA);
+	trace_mei_reg_read(dev->dev, "ME_CSR_HA", ME_CSR_HA, reg);
+
+	return reg;
 }
 
 /**
@@ -98,7 +105,12 @@ static inline u32 mei_me_mecsr_read(const struct mei_device *dev)
  */
 static inline u32 mei_hcsr_read(const struct mei_device *dev)
 {
-	return mei_me_reg_read(to_me_hw(dev), H_CSR);
+	u32 reg;
+
+	reg = mei_me_reg_read(to_me_hw(dev), H_CSR);
+	trace_mei_reg_read(dev->dev, "H_CSR", H_CSR, reg);
+
+	return reg;
 }
 
 /**
@@ -109,6 +121,7 @@ static inline u32 mei_hcsr_read(const struct mei_device *dev)
  */
 static inline void mei_hcsr_write(struct mei_device *dev, u32 reg)
 {
+	trace_mei_reg_write(dev->dev, "H_CSR", H_CSR, reg);
 	mei_me_reg_write(to_me_hw(dev), H_CSR, reg);
 }
 
@@ -555,9 +568,14 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 static void mei_me_pg_enter(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 reg = mei_me_reg_read(hw, H_HPG_CSR);
+	u32 reg;
+
+	reg = mei_me_reg_read(hw, H_HPG_CSR);
+	trace_mei_reg_read(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
 
 	reg |= H_HPG_CSR_PGI;
+
+	trace_mei_reg_write(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
 	mei_me_reg_write(hw, H_HPG_CSR, reg);
 }
 
@@ -569,11 +587,16 @@ static void mei_me_pg_enter(struct mei_device *dev)
 static void mei_me_pg_exit(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
-	u32 reg = mei_me_reg_read(hw, H_HPG_CSR);
+	u32 reg;
+
+	reg = mei_me_reg_read(hw, H_HPG_CSR);
+	trace_mei_reg_read(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
 
 	WARN(!(reg & H_HPG_CSR_PGI), "PGI is not set\n");
 
 	reg |= H_HPG_CSR_PGIHEXR;
+
+	trace_mei_reg_write(dev->dev, "H_HPG_CSR", H_HPG_CSR, reg);
 	mei_me_reg_write(hw, H_HPG_CSR, reg);
 }
 
diff --git a/drivers/misc/mei/mei-trace.c b/drivers/misc/mei/mei-trace.c
new file mode 100644
index 000000000000..388efb519138
--- /dev/null
+++ b/drivers/misc/mei/mei-trace.c
@@ -0,0 +1,25 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2015, 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/module.h>
+
+/* sparse doesn't like tracepoint macros */
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "mei-trace.h"
+
+EXPORT_TRACEPOINT_SYMBOL(mei_reg_read);
+EXPORT_TRACEPOINT_SYMBOL(mei_reg_write);
+#endif /* __CHECKER__ */
diff --git a/drivers/misc/mei/mei-trace.h b/drivers/misc/mei/mei-trace.h
new file mode 100644
index 000000000000..d5c38d15cdd9
--- /dev/null
+++ b/drivers/misc/mei/mei-trace.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+#if !defined(_MEI_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _MEI_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+
+#define TRACE_SYSTEM mei
+#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
+
+TRACE_EVENT(mei_reg_read,
+	TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val),
+	TP_ARGS(dev, reg, offs, val),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(const char *, reg)
+		__field(u32, offs)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev))
+		__entry->reg  = reg;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%s] read %s:[%#x] = %#x",
+		  __get_str(dev), __entry->reg, __entry->offs, __entry->val)
+);
+
+TRACE_EVENT(mei_reg_write,
+	TP_PROTO(const struct device *dev, const char *reg, u32 offs, u32 val),
+	TP_ARGS(dev, reg, offs, val),
+	TP_STRUCT__entry(
+		__string(dev, dev_name(dev))
+		__field(const char *, reg)
+		__field(u32, offs)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		__assign_str(dev, dev_name(dev))
+		__entry->reg = reg;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%s] write %s[%#x] = %#x)",
+		  __get_str(dev), __entry->reg,  __entry->offs, __entry->val)
+);
+
+#endif /* _MEI_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE mei-trace
+#include <trace/define_trace.h>
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 05/18] mei: me: change power gating function name conventions
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 03/18] mei: me: use io register wrappers consistently Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 04/18] mei: me: add io register tracing Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 06/18] mei: fix function names and format in KDoc Tomas Winkler
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Alexander Usyskin, Tomas Winkler

From: Alexander Usyskin <alexander.usyskin@intel.com>

The current power gating naming was confusing,
we wish to swap meanings of register and flow level power gating terms,

For registers writing level use terms set and unset:
	mei_me_pg_set, mei_me_pg_unset

For flow/high level use power gating enter and power gating exit terms
	mei_me_pg_enter_sync, mei_me_pg_exit_sync

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/hw-me.c  | 20 ++++++++++----------
 drivers/misc/mei/hw-me.h  |  4 ++--
 drivers/misc/mei/pci-me.c |  4 ++--
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index d3aef82a6c89..6fb75e62a764 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -561,11 +561,11 @@ static int mei_me_read_slots(struct mei_device *dev, unsigned char *buffer,
 }
 
 /**
- * mei_me_pg_enter - write pg enter register
+ * mei_me_pg_set - write pg enter register
  *
  * @dev: the device structure
  */
-static void mei_me_pg_enter(struct mei_device *dev)
+static void mei_me_pg_set(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 reg;
@@ -580,11 +580,11 @@ static void mei_me_pg_enter(struct mei_device *dev)
 }
 
 /**
- * mei_me_pg_exit - write pg exit register
+ * mei_me_pg_unset - write pg exit register
  *
  * @dev: the device structure
  */
-static void mei_me_pg_exit(struct mei_device *dev)
+static void mei_me_pg_unset(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	u32 reg;
@@ -601,13 +601,13 @@ static void mei_me_pg_exit(struct mei_device *dev)
 }
 
 /**
- * mei_me_pg_set_sync - perform pg entry procedure
+ * mei_me_pg_enter_sync - perform pg entry procedure
  *
  * @dev: the device structure
  *
  * Return: 0 on success an error code otherwise
  */
-int mei_me_pg_set_sync(struct mei_device *dev)
+int mei_me_pg_enter_sync(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -625,7 +625,7 @@ int mei_me_pg_set_sync(struct mei_device *dev)
 	mutex_lock(&dev->device_lock);
 
 	if (dev->pg_event == MEI_PG_EVENT_RECEIVED) {
-		mei_me_pg_enter(dev);
+		mei_me_pg_set(dev);
 		ret = 0;
 	} else {
 		ret = -ETIME;
@@ -638,13 +638,13 @@ int mei_me_pg_set_sync(struct mei_device *dev)
 }
 
 /**
- * mei_me_pg_unset_sync - perform pg exit procedure
+ * mei_me_pg_exit_sync - perform pg exit procedure
  *
  * @dev: the device structure
  *
  * Return: 0 on success an error code otherwise
  */
-int mei_me_pg_unset_sync(struct mei_device *dev)
+int mei_me_pg_exit_sync(struct mei_device *dev)
 {
 	struct mei_me_hw *hw = to_me_hw(dev);
 	unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -655,7 +655,7 @@ int mei_me_pg_unset_sync(struct mei_device *dev)
 
 	dev->pg_event = MEI_PG_EVENT_WAIT;
 
-	mei_me_pg_exit(dev);
+	mei_me_pg_unset(dev);
 
 	mutex_unlock(&dev->device_lock);
 	wait_event_timeout(dev->wait_pg,
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index d6567af44377..6022d52af6f6 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -71,8 +71,8 @@ extern const struct mei_cfg mei_me_pch8_sps_cfg;
 struct mei_device *mei_me_dev_init(struct pci_dev *pdev,
 				   const struct mei_cfg *cfg);
 
-int mei_me_pg_set_sync(struct mei_device *dev);
-int mei_me_pg_unset_sync(struct mei_device *dev);
+int mei_me_pg_enter_sync(struct mei_device *dev);
+int mei_me_pg_exit_sync(struct mei_device *dev);
 
 irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id);
 irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id);
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index bd3039ab8f98..72fb381a1245 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -389,7 +389,7 @@ static int mei_me_pm_runtime_suspend(struct device *device)
 	mutex_lock(&dev->device_lock);
 
 	if (mei_write_is_idle(dev))
-		ret = mei_me_pg_set_sync(dev);
+		ret = mei_me_pg_enter_sync(dev);
 	else
 		ret = -EAGAIN;
 
@@ -414,7 +414,7 @@ static int mei_me_pm_runtime_resume(struct device *device)
 
 	mutex_lock(&dev->device_lock);
 
-	ret = mei_me_pg_unset_sync(dev);
+	ret = mei_me_pg_exit_sync(dev);
 
 	mutex_unlock(&dev->device_lock);
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 06/18] mei: fix function names and format in KDoc
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (2 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 05/18] mei: me: change power gating function name conventions Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 07/18] mei: fix device reset on mei_cl_irq_read_msg allocation failure Tomas Winkler
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Alexander Usyskin, Tomas Winkler

From: Alexander Usyskin <alexander.usyskin@intel.com>

Align functions names in KDoc with real ones.
Fix comment format to be KDoc and fix wrong syntax there.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/client.c  |  9 +++++----
 drivers/misc/mei/hw-txe.c  |  2 +-
 drivers/misc/mei/pci-txe.c |  4 ++--
 drivers/misc/mei/wd.c      | 18 +++++++++---------
 4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e7d28c9961fd..e9135246c00e 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -321,7 +321,7 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 }
 
 /**
- * mei_io_list_flush - removes cbs belonging to cl.
+ * __mei_io_list_flush - removes and frees cbs belonging to cl.
  *
  * @list:  an instance of our list structure
  * @cl:    host client, can be NULL for flushing the whole list
@@ -540,10 +540,11 @@ struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
 	return NULL;
 }
 
-/** mei_cl_link: allocate host id in the host map
+/**
+ * mei_cl_link - allocate host id in the host map
  *
- * @cl - host client
- * @id - fixed host id or -1 for generic one
+ * @cl: host client
+ * @id: fixed host id or -1 for generic one
  *
  * Return: 0 on success
  *	-EINVAL on incorrect values
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index 618ea721aca8..7abafe7d120d 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -412,7 +412,7 @@ static void mei_txe_intr_disable(struct mei_device *dev)
 	mei_txe_br_reg_write(hw, HIER_REG, 0);
 }
 /**
- * mei_txe_intr_disable - enable all interrupts
+ * mei_txe_intr_enable - enable all interrupts
  *
  * @dev: the device structure
  */
diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c
index c86e2ddbe30a..dcfcba44b6f7 100644
--- a/drivers/misc/mei/pci-txe.c
+++ b/drivers/misc/mei/pci-txe.c
@@ -63,7 +63,7 @@ static void mei_txe_pci_iounmap(struct pci_dev *pdev, struct mei_txe_hw *hw)
 	}
 }
 /**
- * mei_probe - Device Initialization Routine
+ * mei_txe_probe - Device Initialization Routine
  *
  * @pdev: PCI device structure
  * @ent: entry in mei_txe_pci_tbl
@@ -193,7 +193,7 @@ end:
 }
 
 /**
- * mei_remove - Device Removal Routine
+ * mei_txe_remove - Device Removal Routine
  *
  * @pdev: PCI device structure
  *
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index 475f1dea45bf..ac1e6235692d 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -202,10 +202,10 @@ err:
 	return ret;
 }
 
-/*
+/**
  * mei_wd_ops_start - wd start command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
+ * @wd_dev: watchdog device struct
  *
  * Return: 0 if success, negative errno code for failure
  */
@@ -239,10 +239,10 @@ end_unlock:
 	return err;
 }
 
-/*
+/**
  * mei_wd_ops_stop -  wd stop command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
+ * @wd_dev: watchdog device struct
  *
  * Return: 0 if success, negative errno code for failure
  */
@@ -261,10 +261,10 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
 	return 0;
 }
 
-/*
+/**
  * mei_wd_ops_ping - wd ping command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
+ * @wd_dev: watchdog device struct
  *
  * Return: 0 if success, negative errno code for failure
  */
@@ -311,11 +311,11 @@ end:
 	return ret;
 }
 
-/*
+/**
  * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core.
  *
- * @wd_dev - watchdog device struct
- * @timeout - timeout value to set
+ * @wd_dev: watchdog device struct
+ * @timeout: timeout value to set
  *
  * Return: 0 if success, negative errno code for failure
  */
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 07/18] mei: fix device reset on mei_cl_irq_read_msg allocation failure
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (3 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 06/18] mei: fix function names and format in KDoc Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 08/18] mei: iamthif: fix device reset on mei_amthif_irq_read_msg Tomas Winkler
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

On memory allocation failure mei_cl_irq_read_msg will
return with error that will cause device reset.
Instead we should propagate error to caller and
just clean the read queues.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/bus.c       |   6 +++
 drivers/misc/mei/interrupt.c | 117 ++++++++++++++++++++++---------------------
 drivers/misc/mei/main.c      |  17 +++++--
 drivers/misc/mei/mei_dev.h   |   2 +
 4 files changed, 80 insertions(+), 62 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index be767f4db26a..025626f4467d 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -322,10 +322,16 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 		goto out;
 	}
 
+	if (cb->status) {
+		rets = cb->status;
+		goto free;
+	}
+
 	r_length = min_t(size_t, length, cb->buf_idx);
 	memcpy(buf, cb->response_buffer.data, r_length);
 	rets = r_length;
 
+free:
 	mei_io_cb_free(cb);
 	cl->reading_state = MEI_IDLE;
 	cl->read_cb = NULL;
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 711cddfa9c99..587cb04a3cf5 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -69,85 +69,91 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
 		cl->me_client_id == mei_hdr->me_addr;
 }
 /**
- * mei_cl_is_reading - checks if the client
- *		is the one to read this message
+ * mei_cl_is_reading - checks if the client is in reading state
  *
  * @cl: mei client
- * @mei_hdr: header of mei message
  *
- * Return: true on match and false otherwise
+ * Return: true if the client is reading
  */
-static bool mei_cl_is_reading(struct mei_cl *cl, struct mei_msg_hdr *mei_hdr)
+static bool mei_cl_is_reading(struct mei_cl *cl)
 {
-	return mei_cl_hbm_equal(cl, mei_hdr) &&
-		cl->state == MEI_FILE_CONNECTED &&
+	return cl->state == MEI_FILE_CONNECTED &&
 		cl->reading_state != MEI_READ_COMPLETE;
 }
 
 /**
  * mei_cl_irq_read_msg - process client message
  *
- * @dev: the device structure
+ * @cl: reading client
  * @mei_hdr: header of mei client message
- * @complete_list: An instance of our list structure
+ * @complete_list: completion list
  *
- * Return: 0 on success, <0 on failure.
+ * Return: always 0
  */
-static int mei_cl_irq_read_msg(struct mei_device *dev,
+static int mei_cl_irq_read_msg(struct mei_cl *cl,
 			       struct mei_msg_hdr *mei_hdr,
 			       struct mei_cl_cb *complete_list)
 {
-	struct mei_cl *cl;
-	struct mei_cl_cb *cb, *next;
+	struct mei_device *dev = cl->dev;
+	struct mei_cl_cb *cb;
 	unsigned char *buffer = NULL;
 
-	list_for_each_entry_safe(cb, next, &dev->read_list.list, list) {
-		cl = cb->cl;
-		if (!mei_cl_is_reading(cl, mei_hdr))
-			continue;
+	list_for_each_entry(cb, &dev->read_list.list, list) {
+		if (cl == cb->cl)
+			break;
+	}
 
-		cl->reading_state = MEI_READING;
+	if (&cb->list == &dev->read_list.list) {
+		dev_err(dev->dev, "no reader found\n");
+		goto out;
+	}
 
-		if (cb->response_buffer.size == 0 ||
-		    cb->response_buffer.data == NULL) {
-			cl_err(dev, cl, "response buffer is not allocated.\n");
-			list_del(&cb->list);
-			return -ENOMEM;
-		}
+	if (!mei_cl_is_reading(cl)) {
+		cl_err(dev, cl, "cl is not reading state=%d reading state=%d\n",
+			cl->state, cl->reading_state);
+		goto out;
+	}
 
-		if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
-			cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
-				cb->response_buffer.size,
-				mei_hdr->length, cb->buf_idx);
-			buffer = krealloc(cb->response_buffer.data,
-					  mei_hdr->length + cb->buf_idx,
-					  GFP_KERNEL);
-
-			if (!buffer) {
-				list_del(&cb->list);
-				return -ENOMEM;
-			}
-			cb->response_buffer.data = buffer;
-			cb->response_buffer.size =
-				mei_hdr->length + cb->buf_idx;
-		}
+	cl->reading_state = MEI_READING;
 
-		buffer = cb->response_buffer.data + cb->buf_idx;
-		mei_read_slots(dev, buffer, mei_hdr->length);
+	if (cb->response_buffer.size == 0 ||
+	    cb->response_buffer.data == NULL) {
+		cl_err(dev, cl, "response buffer is not allocated.\n");
+		list_move_tail(&cb->list, &complete_list->list);
+		cb->status = -ENOMEM;
+		goto out;
+	}
 
-		cb->buf_idx += mei_hdr->length;
-		if (mei_hdr->msg_complete) {
-			cl->status = 0;
-			list_del(&cb->list);
-			cl_dbg(dev, cl, "completed read length = %lu\n",
-				cb->buf_idx);
-			list_add_tail(&cb->list, &complete_list->list);
+	if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
+		cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
+			cb->response_buffer.size, mei_hdr->length, cb->buf_idx);
+		buffer = krealloc(cb->response_buffer.data,
+				  mei_hdr->length + cb->buf_idx,
+				  GFP_KERNEL);
+
+		if (!buffer) {
+			cb->status = -ENOMEM;
+			list_move_tail(&cb->list, &complete_list->list);
+			goto out;
 		}
-		break;
+		cb->response_buffer.data = buffer;
+		cb->response_buffer.size = mei_hdr->length + cb->buf_idx;
 	}
 
-	dev_dbg(dev->dev, "message read\n");
+	buffer = cb->response_buffer.data + cb->buf_idx;
+	mei_read_slots(dev, buffer, mei_hdr->length);
+
+	cb->buf_idx += mei_hdr->length;
+	if (mei_hdr->msg_complete) {
+		cl_dbg(dev, cl, "completed read length = %lu\n",
+			cb->buf_idx);
+		list_move_tail(&cb->list, &complete_list->list);
+	}
+
+out:
 	if (!buffer) {
+		/* assume that mei_hdr->length <= MEI_RD_MSG_BUF_SIZE */
+		BUG_ON(mei_hdr->length > MEI_RD_MSG_BUF_SIZE);
 		mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
 		dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
 				MEI_HDR_PRM(mei_hdr));
@@ -389,14 +395,10 @@ int mei_irq_read_handler(struct mei_device *dev,
 			goto end;
 		}
 	} else {
-		ret = mei_cl_irq_read_msg(dev, mei_hdr, cmpl_list);
-		if (ret) {
-			dev_err(dev->dev, "mei_cl_irq_read_msg failed = %d\n",
-					ret);
-			goto end;
-		}
+		ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
 	}
 
+
 reset_slots:
 	/* reset the number of slots and header */
 	*slots = mei_count_full_read_slots(dev);
@@ -636,4 +638,3 @@ out:
 		schedule_delayed_work(&dev->timer_work, 2 * HZ);
 	mutex_unlock(&dev->device_lock);
 }
-
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 3c019c0e60eb..cbdbf4af2bf7 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -192,8 +192,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		goto out;
 	}
 
-	if (cl->read_cb) {
-		cb = cl->read_cb;
+	cb = cl->read_cb;
+	if (cb) {
 		/* read what left */
 		if (cb->buf_idx > *offset)
 			goto copy_buffer;
@@ -218,7 +218,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 	}
 
 	if (MEI_READ_COMPLETE != cl->reading_state &&
-			!waitqueue_active(&cl->rx_wait)) {
+		!waitqueue_active(&cl->rx_wait)) {
+
 		if (file->f_flags & O_NONBLOCK) {
 			rets = -EAGAIN;
 			goto out;
@@ -248,12 +249,20 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		rets = -ENODEV;
 		goto out;
 	}
+
 	if (cl->reading_state != MEI_READ_COMPLETE) {
 		rets = 0;
 		goto out;
 	}
-	/* now copy the data to user space */
+
 copy_buffer:
+	/* now copy the data to user space */
+	if (cb->status) {
+		rets = cb->status;
+		dev_dbg(dev->dev, "read operation failed %d\n", rets);
+		goto free;
+	}
+
 	dev_dbg(dev->dev, "buf.size = %d buf.idx= %ld\n",
 	    cb->response_buffer.size, cb->buf_idx);
 	if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 102cc6603eba..195e426b08f0 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -199,6 +199,7 @@ struct mei_cl;
  * @buf_idx: last read index
  * @read_time: last read operation time stamp (iamthif)
  * @file_object: pointer to file structure
+ * @status: io status of the cb
  * @internal: communication between driver and FW flag
  */
 struct mei_cl_cb {
@@ -210,6 +211,7 @@ struct mei_cl_cb {
 	unsigned long buf_idx;
 	unsigned long read_time;
 	struct file *file_object;
+	int status;
 	u32 internal:1;
 };
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 08/18] mei: iamthif: fix device reset on mei_amthif_irq_read_msg
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (4 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 07/18] mei: fix device reset on mei_cl_irq_read_msg allocation failure Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 09/18] mei: iamthif: remove useless iamthif_ioctl variable Tomas Winkler
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

On failure mei_amthif_irq_read_msg returns an error
that will cause device reset but the issue is software one
so instead we should propagate error to caller and just
clean the read queues.
As a side effect also removes useless BUG_ONs

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 76 ++++++++++++++++++++++++++++----------------
 drivers/misc/mei/interrupt.c |  7 ++--
 drivers/misc/mei/mei_dev.h   |  2 +-
 3 files changed, 51 insertions(+), 34 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index c4cb9a984a5f..2ad2f94678c8 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -195,23 +195,26 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		dev_dbg(dev->dev, "woke up from sleep\n");
 	}
 
+	if (cb->status) {
+		rets = cb->status;
+		dev_dbg(dev->dev, "read operation failed %d\n", rets);
+		goto free;
+	}
 
 	dev_dbg(dev->dev, "Got amthif data\n");
 	dev->iamthif_timer = 0;
 
-	if (cb) {
-		timeout = cb->read_time +
-			mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
-		dev_dbg(dev->dev, "amthif timeout = %lud\n",
-				timeout);
-
-		if  (time_after(jiffies, timeout)) {
-			dev_dbg(dev->dev, "amthif Time out\n");
-			/* 15 sec for the message has expired */
-			list_del(&cb->list);
-			rets = -ETIME;
-			goto free;
-		}
+	timeout = cb->read_time +
+		mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
+	dev_dbg(dev->dev, "amthif timeout = %lud\n",
+			timeout);
+
+	if  (time_after(jiffies, timeout)) {
+		dev_dbg(dev->dev, "amthif Time out\n");
+		/* 15 sec for the message has expired */
+		list_del(&cb->list);
+		rets = -ETIME;
+		goto free;
 	}
 	/* if the whole message will fit remove it from the list */
 	if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
@@ -501,25 +504,42 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
  * mei_amthif_irq_read_msg - read routine after ISR to
  *			handle the read amthif message
  *
- * @dev: the device structure
+ * @cl: mei client
  * @mei_hdr: header of amthif message
- * @complete_list: An instance of our list structure
+ * @complete_list: completed callbacks list
  *
- * Return: 0 on success, <0 on failure.
+ * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
  */
-int mei_amthif_irq_read_msg(struct mei_device *dev,
+int mei_amthif_irq_read_msg(struct mei_cl *cl,
 			    struct mei_msg_hdr *mei_hdr,
 			    struct mei_cl_cb *complete_list)
 {
+	struct mei_device *dev;
 	struct mei_cl_cb *cb;
 	unsigned char *buffer;
+	int ret = 0;
 
-	BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
-	BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
+	dev = cl->dev;
 
-	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
-	BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
+	if (cl->state != MEI_FILE_CONNECTED)
+		goto err;
+
+	if (dev->iamthif_state != MEI_IAMTHIF_READING)
+		goto err;
+
+	cb = dev->iamthif_current_cb;
 
+	if (!cb) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	if (dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length) {
+		cb->status = -ERANGE;
+		goto err;
+	}
+
+	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
 	mei_read_slots(dev, buffer, mei_hdr->length);
 
 	dev->iamthif_msg_buf_index += mei_hdr->length;
@@ -527,14 +547,8 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
 	if (!mei_hdr->msg_complete)
 		return 0;
 
-	dev_dbg(dev->dev, "amthif_message_buffer_index =%d\n",
-			mei_hdr->length);
-
 	dev_dbg(dev->dev, "completed amthif read.\n ");
-	if (!dev->iamthif_current_cb)
-		return -ENODEV;
 
-	cb = dev->iamthif_current_cb;
 	dev->iamthif_current_cb = NULL;
 
 	dev->iamthif_stall_timer = 0;
@@ -543,10 +557,16 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
 	if (dev->iamthif_ioctl) {
 		/* found the iamthif cb */
 		dev_dbg(dev->dev, "complete the amthif read cb.\n ");
-		dev_dbg(dev->dev, "add the amthif read cb to complete.\n ");
 		list_add_tail(&cb->list, &complete_list->list);
 	}
+
 	return 0;
+
+err:
+	mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
+	dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
+				MEI_HDR_PRM(mei_hdr));
+	return ret;
 }
 
 /**
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 587cb04a3cf5..151f0c84a65e 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -384,11 +384,8 @@ int mei_irq_read_handler(struct mei_device *dev,
 		goto end;
 	}
 
-	if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
-	    MEI_FILE_CONNECTED == dev->iamthif_cl.state &&
-	    dev->iamthif_state == MEI_IAMTHIF_READING) {
-
-		ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
+	if (cl == &dev->iamthif_cl) {
+		ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
 		if (ret) {
 			dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
 					ret);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 195e426b08f0..b74d156ed600 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -685,7 +685,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 			struct mei_cl_cb *cmpl_list);
 
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb);
-int mei_amthif_irq_read_msg(struct mei_device *dev,
+int mei_amthif_irq_read_msg(struct mei_cl *cl,
 			    struct mei_msg_hdr *mei_hdr,
 			    struct mei_cl_cb *complete_list);
 int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 09/18] mei: iamthif: remove useless iamthif_ioctl variable
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (5 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 08/18] mei: iamthif: fix device reset on mei_amthif_irq_read_msg Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 10/18] mei: iamthif: send flow control as a regular client Tomas Winkler
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

iamthif_ioctl is obsolete and can be safely dropped
Currently it is set to true during driver runtime

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 11 +++--------
 drivers/misc/mei/interrupt.c |  1 -
 drivers/misc/mei/mei_dev.h   |  2 --
 3 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 2ad2f94678c8..788b00e23353 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -52,7 +52,6 @@ void mei_amthif_reset_params(struct mei_device *dev)
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_canceled = false;
-	dev->iamthif_ioctl = false;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
 	dev->iamthif_stall_timer = 0;
@@ -279,7 +278,6 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	dev->iamthif_current_cb = cb;
 	dev->iamthif_file_object = cb->file_object;
 	dev->iamthif_canceled = false;
-	dev->iamthif_ioctl = true;
 	dev->iamthif_msg_buf_size = cb->request_buffer.size;
 	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
 	       cb->request_buffer.size);
@@ -375,7 +373,6 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_canceled = false;
-	dev->iamthif_ioctl = true;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
 	dev->iamthif_file_object = NULL;
@@ -554,11 +551,9 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
 	dev->iamthif_stall_timer = 0;
 	cb->buf_idx = dev->iamthif_msg_buf_index;
 	cb->read_time = jiffies;
-	if (dev->iamthif_ioctl) {
-		/* found the iamthif cb */
-		dev_dbg(dev->dev, "complete the amthif read cb.\n ");
-		list_add_tail(&cb->list, &complete_list->list);
-	}
+
+	dev_dbg(dev->dev, "complete the amthif read cb.\n ");
+	list_add_tail(&cb->list, &complete_list->list);
 
 	return 0;
 
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 151f0c84a65e..4cb602fba593 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -589,7 +589,6 @@ void mei_timer(struct work_struct *work)
 			dev->iamthif_msg_buf_size = 0;
 			dev->iamthif_msg_buf_index = 0;
 			dev->iamthif_canceled = false;
-			dev->iamthif_ioctl = true;
 			dev->iamthif_state = MEI_IAMTHIF_IDLE;
 			dev->iamthif_timer = 0;
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index b74d156ed600..6cc68de580ba 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -488,7 +488,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @iamthif_msg_buf_index : current index in amthif message request buffer
  * @iamthif_state : amthif processor state
  * @iamthif_flow_control_pending: amthif waits for flow control
- * @iamthif_ioctl : wait for completion if amthif control message
  * @iamthif_canceled : current amthif command is canceled
  *
  * @init_work   : work item for the device init
@@ -588,7 +587,6 @@ struct mei_device {
 	u32 iamthif_msg_buf_index;
 	enum iamthif_states iamthif_state;
 	bool iamthif_flow_control_pending;
-	bool iamthif_ioctl;
 	bool iamthif_canceled;
 
 	struct work_struct init_work;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 10/18] mei: iamthif: send flow control as a regular client
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (6 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 09/18] mei: iamthif: remove useless iamthif_ioctl variable Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 11/18] mei: iamthif: use client write functions Tomas Winkler
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Reuse common client mechanism for sending flow control
hbm message. Add new function mei_amthif_read_start
similar to mei_cl_read_start that puts control flow request
onto the control write queue and drop mei_amthif_irq_read function

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 134 +++++++++++++++++++++++--------------------
 drivers/misc/mei/interrupt.c |  25 ++------
 drivers/misc/mei/mei_dev.h   |   2 -
 3 files changed, 77 insertions(+), 84 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 788b00e23353..e6f7180fd8f2 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -255,6 +255,47 @@ out:
 }
 
 /**
+ * mei_amthif_read_start - queue message for sending read credential
+ *
+ * @cl: host client
+ * @file: file pointer of message recipient
+ *
+ * Return: 0 on success, <0 on failure.
+ */
+static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
+{
+	struct mei_device *dev = cl->dev;
+	struct mei_cl_cb *cb;
+	size_t length = dev->iamthif_mtu;
+	int rets;
+
+	cb = mei_io_cb_init(cl, file);
+	if (!cb) {
+		rets = -ENOMEM;
+		goto err;
+	}
+
+	rets = mei_io_cb_alloc_resp_buf(cb, length);
+	if (rets)
+		goto err;
+
+	cb->fop_type = MEI_FOP_READ;
+	list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
+
+	dev->iamthif_msg_buf_index = 0;
+	dev->iamthif_msg_buf_size = 0;
+
+	dev->iamthif_state = MEI_IAMTHIF_READING;
+	dev->iamthif_file_object = cb->file_object;
+	dev->iamthif_current_cb = cb;
+
+	return 0;
+err:
+	mei_io_cb_free(cb);
+	return rets;
+}
+
+/**
  * mei_amthif_send_cmd - send amthif command to the ME
  *
  * @dev: the device structure
@@ -287,6 +328,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret < 0)
 		return ret;
 
+	cb->fop_type = MEI_FOP_WRITE;
 	if (ret && mei_hbuf_acquire(dev)) {
 		ret = 0;
 		if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
@@ -309,19 +351,17 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 		if (mei_hdr.msg_complete) {
 			if (mei_cl_flow_ctrl_reduce(cl))
 				return -EIO;
-			dev->iamthif_flow_control_pending = true;
-			dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-			dev_dbg(dev->dev, "add amthif cb to write waiting list\n");
-			dev->iamthif_current_cb = cb;
-			dev->iamthif_file_object = cb->file_object;
+			cb->status = mei_amthif_read_start(cl, cb->file_object);
 			list_add_tail(&cb->list, &dev->write_waiting_list.list);
 		} else {
 			dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n");
 			list_add_tail(&cb->list, &dev->write_list.list);
 		}
 	} else {
+
 		list_add_tail(&cb->list, &dev->write_list.list);
 	}
+
 	return 0;
 }
 
@@ -336,17 +376,10 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
  */
 int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
 {
-	int ret;
-
 	if (!dev || !cb)
 		return -ENODEV;
 
-	ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu);
-	if (ret)
-		return ret;
-
 	cb->fop_type = MEI_FOP_WRITE;
-
 	if (!list_empty(&dev->amthif_cmd_list.list) ||
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
 		dev_dbg(dev->dev,
@@ -383,7 +416,7 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
 					typeof(*cb), list);
 	if (!cb)
 		return;
-	list_del(&cb->list);
+	list_del_init(&cb->list);
 	ret =  mei_amthif_send_cmd(dev, cb);
 	if (ret)
 		dev_warn(dev->dev, "amthif write failed status = %d\n", ret);
@@ -483,13 +516,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 	cl->status = 0;
 
 	if (mei_hdr.msg_complete) {
-		dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
-		dev->iamthif_flow_control_pending = true;
-
-		/* save iamthif cb sent to amthif client */
-		cb->buf_idx = dev->iamthif_msg_buf_index;
-		dev->iamthif_current_cb = cb;
-
+		cb->status = mei_amthif_read_start(cl, cb->file_object);
 		list_move_tail(&cb->list, &dev->write_waiting_list.list);
 	}
 
@@ -505,7 +532,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
  * @mei_hdr: header of amthif message
  * @complete_list: completed callbacks list
  *
- * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status
+ * Return: Always 0; error message is in cb->status
  */
 int mei_amthif_irq_read_msg(struct mei_cl *cl,
 			    struct mei_msg_hdr *mei_hdr,
@@ -514,7 +541,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
 	struct mei_device *dev;
 	struct mei_cl_cb *cb;
 	unsigned char *buffer;
-	int ret = 0;
 
 	dev = cl->dev;
 
@@ -524,10 +550,13 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
 	if (dev->iamthif_state != MEI_IAMTHIF_READING)
 		goto err;
 
-	cb = dev->iamthif_current_cb;
+	list_for_each_entry(cb, &dev->read_list.list, list) {
+		if (cl == cb->cl)
+			break;
+	}
 
-	if (!cb) {
-		ret = -ENODEV;
+	if (&cb->list == &dev->read_list.list) {
+		dev_err(dev->dev, "no reader found\n");
 		goto err;
 	}
 
@@ -553,7 +582,7 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
 	cb->read_time = jiffies;
 
 	dev_dbg(dev->dev, "complete the amthif read cb.\n ");
-	list_add_tail(&cb->list, &complete_list->list);
+	list_move_tail(&cb->list, &complete_list->list);
 
 	return 0;
 
@@ -561,38 +590,6 @@ err:
 	mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
 	dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
 				MEI_HDR_PRM(mei_hdr));
-	return ret;
-}
-
-/**
- * mei_amthif_irq_read - prepares to read amthif data.
- *
- * @dev: the device structure.
- * @slots: free slots.
- *
- * Return: 0, OK; otherwise, error.
- */
-int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
-{
-	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
-
-	if (*slots < msg_slots)
-		return -EMSGSIZE;
-
-	*slots -= msg_slots;
-
-	if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) {
-		dev_dbg(dev->dev, "iamthif flow control failed\n");
-		return -EIO;
-	}
-
-	dev_dbg(dev->dev, "iamthif flow control success\n");
-	dev->iamthif_state = MEI_IAMTHIF_READING;
-	dev->iamthif_flow_control_pending = false;
-	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_msg_buf_size = 0;
-	dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
-	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 	return 0;
 }
 
@@ -604,17 +601,32 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots)
  */
 void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 {
+
+	if (cb->fop_type == MEI_FOP_WRITE) {
+		if (!cb->status) {
+			dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER;
+			mei_io_cb_free(cb);
+			return;
+		}
+		/*
+		 * 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, &dev->amthif_rd_complete_list.list);
+		wake_up_interruptible(&dev->iamthif_cl.wait);
+		return;
+	}
+
 	if (dev->iamthif_canceled != 1) {
 		dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
 		dev->iamthif_stall_timer = 0;
 		memcpy(cb->response_buffer.data,
-				dev->iamthif_msg_buf,
-				dev->iamthif_msg_buf_index);
+			dev->iamthif_msg_buf, dev->iamthif_msg_buf_index);
 		list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
 		dev_dbg(dev->dev, "amthif read completed\n");
 		dev->iamthif_timer = jiffies;
 		dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n",
-				dev->iamthif_timer);
+			dev->iamthif_timer);
 	} else {
 		mei_amthif_run_next_cmd(dev);
 	}
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 4cb602fba593..89f2fbce160f 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -43,7 +43,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list)
 
 	list_for_each_entry_safe(cb, next, &compl_list->list, list) {
 		cl = cb->cl;
-		list_del(&cb->list);
+		list_del_init(&cb->list);
 
 		dev_dbg(dev->dev, "completing call back.\n");
 		if (cl == &dev->iamthif_cl)
@@ -386,11 +386,6 @@ int mei_irq_read_handler(struct mei_device *dev,
 
 	if (cl == &dev->iamthif_cl) {
 		ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
-		if (ret) {
-			dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
-					ret);
-			goto end;
-		}
 	} else {
 		ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
 	}
@@ -448,21 +443,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		cl = cb->cl;
 
 		cl->status = 0;
-		list_del(&cb->list);
-		if (cb->fop_type == MEI_FOP_WRITE &&
-		    cl != &dev->iamthif_cl) {
-			cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
-			cl->writing_state = MEI_WRITE_COMPLETE;
-			list_add_tail(&cb->list, &cmpl_list->list);
-		}
-		if (cl == &dev->iamthif_cl) {
-			cl_dbg(dev, cl, "check iamthif flow control.\n");
-			if (dev->iamthif_flow_control_pending) {
-				ret = mei_amthif_irq_read(dev, &slots);
-				if (ret)
-					return ret;
-			}
-		}
+		cl_dbg(dev, cl, "MEI WRITE COMPLETE\n");
+		cl->writing_state = MEI_WRITE_COMPLETE;
+		list_move_tail(&cb->list, &cmpl_list->list);
 	}
 
 	if (dev->wd_state == MEI_WD_STOPPING) {
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 6cc68de580ba..fc460af131d4 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -487,7 +487,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @iamthif_msg_buf_size : size of current amthif message request buffer
  * @iamthif_msg_buf_index : current index in amthif message request buffer
  * @iamthif_state : amthif processor state
- * @iamthif_flow_control_pending: amthif waits for flow control
  * @iamthif_canceled : current amthif command is canceled
  *
  * @init_work   : work item for the device init
@@ -586,7 +585,6 @@ struct mei_device {
 	u32 iamthif_msg_buf_size;
 	u32 iamthif_msg_buf_index;
 	enum iamthif_states iamthif_state;
-	bool iamthif_flow_control_pending;
 	bool iamthif_canceled;
 
 	struct work_struct init_work;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 11/18] mei: iamthif: use client write functions
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (7 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 10/18] mei: iamthif: send flow control as a regular client Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 12/18] mei: iamthif: use regular client read functions Tomas Winkler
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Reduce code duplication in amthif code by reusing
regular client write functions.
Add completed flag to cb so amthif client can add
rx credits on write completion

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c  | 178 +++++++++++----------------------------------
 drivers/misc/mei/client.c  |   2 +
 drivers/misc/mei/main.c    |   2 +-
 drivers/misc/mei/mei_dev.h |   8 +-
 4 files changed, 51 insertions(+), 139 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index e6f7180fd8f2..916625a8f037 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -298,110 +298,47 @@ err:
 /**
  * mei_amthif_send_cmd - send amthif command to the ME
  *
- * @dev: the device structure
+ * @cl: the host client
  * @cb: mei call back struct
  *
  * Return: 0 on success, <0 on failure.
- *
  */
-static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
+static int mei_amthif_send_cmd(struct mei_cl *cl, struct mei_cl_cb *cb)
 {
-	struct mei_msg_hdr mei_hdr;
-	struct mei_cl *cl;
+	struct mei_device *dev;
 	int ret;
 
-	if (!dev || !cb)
+	if (!cl->dev || !cb)
 		return -ENODEV;
 
-	dev_dbg(dev->dev, "write data to amthif client.\n");
+	dev = cl->dev;
 
 	dev->iamthif_state = MEI_IAMTHIF_WRITING;
 	dev->iamthif_current_cb = cb;
 	dev->iamthif_file_object = cb->file_object;
 	dev->iamthif_canceled = false;
-	dev->iamthif_msg_buf_size = cb->request_buffer.size;
-	memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
-	       cb->request_buffer.size);
-	cl = &dev->iamthif_cl;
 
-	ret = mei_cl_flow_ctrl_creds(cl);
+	ret = mei_cl_write(cl, cb, false);
 	if (ret < 0)
 		return ret;
 
-	cb->fop_type = MEI_FOP_WRITE;
-	if (ret && mei_hbuf_acquire(dev)) {
-		ret = 0;
-		if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
-			mei_hdr.length = mei_hbuf_max_len(dev);
-			mei_hdr.msg_complete = 0;
-		} else {
-			mei_hdr.length = cb->request_buffer.size;
-			mei_hdr.msg_complete = 1;
-		}
-
-		mei_hdr.host_addr = cl->host_client_id;
-		mei_hdr.me_addr = cl->me_client_id;
-		mei_hdr.reserved = 0;
-		mei_hdr.internal = 0;
-		dev->iamthif_msg_buf_index += mei_hdr.length;
-		ret = mei_write_message(dev, &mei_hdr, dev->iamthif_msg_buf);
-		if (ret)
-			return ret;
-
-		if (mei_hdr.msg_complete) {
-			if (mei_cl_flow_ctrl_reduce(cl))
-				return -EIO;
-			cb->status = mei_amthif_read_start(cl, cb->file_object);
-			list_add_tail(&cb->list, &dev->write_waiting_list.list);
-		} else {
-			dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n");
-			list_add_tail(&cb->list, &dev->write_list.list);
-		}
-	} else {
-
-		list_add_tail(&cb->list, &dev->write_list.list);
-	}
+	if (cb->completed)
+		cb->status = mei_amthif_read_start(cl, cb->file_object);
 
 	return 0;
 }
 
 /**
- * mei_amthif_write - write amthif data to amthif client
+ * mei_amthif_run_next_cmd - send next amt command from queue
  *
  * @dev: the device structure
- * @cb: mei call back struct
  *
  * Return: 0 on success, <0 on failure.
- *
  */
-int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
-{
-	if (!dev || !cb)
-		return -ENODEV;
-
-	cb->fop_type = MEI_FOP_WRITE;
-	if (!list_empty(&dev->amthif_cmd_list.list) ||
-	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
-		dev_dbg(dev->dev,
-			"amthif state = %d\n", dev->iamthif_state);
-		dev_dbg(dev->dev, "AMTHIF: add cb to the wait list\n");
-		list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
-		return 0;
-	}
-	return mei_amthif_send_cmd(dev, cb);
-}
-/**
- * mei_amthif_run_next_cmd - send next amt command from queue
- *
- * @dev: the device structure
- */
-void mei_amthif_run_next_cmd(struct mei_device *dev)
+int mei_amthif_run_next_cmd(struct mei_device *dev)
 {
+	struct mei_cl *cl = &dev->iamthif_cl;
 	struct mei_cl_cb *cb;
-	int ret;
-
-	if (!dev)
-		return;
 
 	dev->iamthif_msg_buf_size = 0;
 	dev->iamthif_msg_buf_index = 0;
@@ -415,13 +352,37 @@ void mei_amthif_run_next_cmd(struct mei_device *dev)
 	cb = list_first_entry_or_null(&dev->amthif_cmd_list.list,
 					typeof(*cb), list);
 	if (!cb)
-		return;
+		return 0;
+
 	list_del_init(&cb->list);
-	ret =  mei_amthif_send_cmd(dev, cb);
-	if (ret)
-		dev_warn(dev->dev, "amthif write failed status = %d\n", ret);
+	return mei_amthif_send_cmd(cl, cb);
 }
 
+/**
+ * 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;
+
+	if (WARN_ON(!cl || !cl->dev))
+		return -ENODEV;
+
+	if (WARN_ON(!cb))
+		return -EINVAL;
+
+	dev = cl->dev;
+
+	cb->fop_type = MEI_FOP_WRITE;
+	list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
+	return mei_amthif_run_next_cmd(dev);
+}
 
 unsigned int mei_amthif_poll(struct mei_device *dev,
 		struct file *file, poll_table *wait)
@@ -461,65 +422,14 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 			 struct mei_cl_cb *cmpl_list)
 {
-	struct mei_device *dev = cl->dev;
-	struct mei_msg_hdr mei_hdr;
-	size_t len = dev->iamthif_msg_buf_size - dev->iamthif_msg_buf_index;
-	u32 msg_slots = mei_data2slots(len);
-	int slots;
-	int rets;
-
-	rets = mei_cl_flow_ctrl_creds(cl);
-	if (rets < 0)
-		return rets;
-
-	if (rets == 0) {
-		cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
-		return 0;
-	}
-
-	mei_hdr.host_addr = cl->host_client_id;
-	mei_hdr.me_addr = cl->me_client_id;
-	mei_hdr.reserved = 0;
-	mei_hdr.internal = 0;
-
-	slots = mei_hbuf_empty_slots(dev);
-
-	if (slots >= msg_slots) {
-		mei_hdr.length = len;
-		mei_hdr.msg_complete = 1;
-	/* Split the message only if we can write the whole host buffer */
-	} else if (slots == dev->hbuf_depth) {
-		msg_slots = slots;
-		len = (slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
-		mei_hdr.length = len;
-		mei_hdr.msg_complete = 0;
-	} else {
-		/* wait for next time the host buffer is empty */
-		return 0;
-	}
-
-	dev_dbg(dev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
-
-	rets = mei_write_message(dev, &mei_hdr,
-			dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
-	if (rets) {
-		dev->iamthif_state = MEI_IAMTHIF_IDLE;
-		cl->status = rets;
-		list_del(&cb->list);
-		return rets;
-	}
-
-	if (mei_cl_flow_ctrl_reduce(cl))
-		return -EIO;
+	int ret;
 
-	dev->iamthif_msg_buf_index += mei_hdr.length;
-	cl->status = 0;
+	ret = mei_cl_irq_write(cl, cb, cmpl_list);
+	if (ret)
+		return ret;
 
-	if (mei_hdr.msg_complete) {
+	if (cb->completed)
 		cb->status = mei_amthif_read_start(cl, cb->file_object);
-		list_move_tail(&cb->list, &dev->write_waiting_list.list);
-	}
-
 
 	return 0;
 }
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e9135246c00e..978f7f95d66d 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1106,6 +1106,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 	cl->status = 0;
 	cl->writing_state = MEI_WRITING;
 	cb->buf_idx += mei_hdr.length;
+	cb->completed = mei_hdr.msg_complete == 1;
 
 	if (mei_hdr.msg_complete) {
 		if (mei_cl_flow_ctrl_reduce(cl))
@@ -1194,6 +1195,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
 	cl->writing_state = MEI_WRITING;
 	cb->buf_idx = mei_hdr.length;
+	cb->completed = mei_hdr.msg_complete == 1;
 
 out:
 	if (mei_hdr.msg_complete) {
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index cbdbf4af2bf7..9d1a8cba81c9 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -401,7 +401,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 	}
 
 	if (cl == &dev->iamthif_cl) {
-		rets = mei_amthif_write(dev, write_cb);
+		rets = mei_amthif_write(cl, write_cb);
 
 		if (rets) {
 			dev_err(dev->dev,
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index fc460af131d4..2f2242f1bed1 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -201,6 +201,7 @@ struct mei_cl;
  * @file_object: pointer to file structure
  * @status: io status of the cb
  * @internal: communication between driver and FW flag
+ * @completed: the transfer or reception has completed
  */
 struct mei_cl_cb {
 	struct list_head list;
@@ -213,6 +214,7 @@ struct mei_cl_cb {
 	struct file *file_object;
 	int status;
 	u32 internal:1;
+	u32 completed:1;
 };
 
 /**
@@ -662,8 +664,6 @@ void mei_amthif_reset_params(struct mei_device *dev);
 
 int mei_amthif_host_init(struct mei_device *dev);
 
-int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
-
 int mei_amthif_read(struct mei_device *dev, struct file *file,
 		char __user *ubuf, size_t length, loff_t *offset);
 
@@ -675,8 +675,8 @@ int mei_amthif_release(struct mei_device *dev, struct file *file);
 struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 						struct file *file);
 
-void mei_amthif_run_next_cmd(struct mei_device *dev);
-
+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 mei_cl_cb *cmpl_list);
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 12/18] mei: iamthif: use regular client read functions
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (8 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 11/18] mei: iamthif: use client write functions Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 13/18] mei: use only one buffer in callback Tomas Winkler
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Reduce code duplication in amthif by reusing
regular client read functions.

The change also removes the need for amthif
own buffering

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 71 +++++---------------------------------------
 drivers/misc/mei/client.h    |  2 ++
 drivers/misc/mei/interrupt.c | 37 +++++++++++++++--------
 drivers/misc/mei/mei_dev.h   |  6 ----
 4 files changed, 35 insertions(+), 81 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 916625a8f037..4060e2f40286 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -49,8 +49,6 @@ void mei_amthif_reset_params(struct mei_device *dev)
 {
 	/* reset iamthif parameters. */
 	dev->iamthif_current_cb = NULL;
-	dev->iamthif_msg_buf_size = 0;
-	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_canceled = false;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
@@ -69,7 +67,6 @@ int mei_amthif_host_init(struct mei_device *dev)
 {
 	struct mei_cl *cl = &dev->iamthif_cl;
 	struct mei_me_client *me_cl;
-	unsigned char *msg_buf;
 	int ret;
 
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
@@ -90,18 +87,6 @@ int mei_amthif_host_init(struct mei_device *dev)
 	dev->iamthif_mtu = me_cl->props.max_msg_length;
 	dev_dbg(dev->dev, "IAMTHIF_MTU = %d\n", dev->iamthif_mtu);
 
-	kfree(dev->iamthif_msg_buf);
-	dev->iamthif_msg_buf = NULL;
-
-	/* allocate storage for ME message buffer */
-	msg_buf = kcalloc(dev->iamthif_mtu,
-			sizeof(unsigned char), GFP_KERNEL);
-	if (!msg_buf) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	dev->iamthif_msg_buf = msg_buf;
 
 	ret = mei_cl_link(cl, MEI_IAMTHIF_HOST_CLIENT_ID);
 	if (ret < 0) {
@@ -282,9 +267,6 @@ static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
 	cb->fop_type = MEI_FOP_READ;
 	list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 
-	dev->iamthif_msg_buf_index = 0;
-	dev->iamthif_msg_buf_size = 0;
-
 	dev->iamthif_state = MEI_IAMTHIF_READING;
 	dev->iamthif_file_object = cb->file_object;
 	dev->iamthif_current_cb = cb;
@@ -340,8 +322,6 @@ int mei_amthif_run_next_cmd(struct mei_device *dev)
 	struct mei_cl *cl = &dev->iamthif_cl;
 	struct mei_cl_cb *cb;
 
-	dev->iamthif_msg_buf_size = 0;
-	dev->iamthif_msg_buf_index = 0;
 	dev->iamthif_canceled = false;
 	dev->iamthif_state = MEI_IAMTHIF_IDLE;
 	dev->iamthif_timer = 0;
@@ -440,67 +420,34 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
  *
  * @cl: mei client
  * @mei_hdr: header of amthif message
- * @complete_list: completed callbacks list
+ * @cmpl_list: completed callbacks list
  *
- * Return: Always 0; error message is in cb->status
+ * 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 mei_cl_cb *complete_list)
+			    struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev;
-	struct mei_cl_cb *cb;
-	unsigned char *buffer;
+	int ret;
 
 	dev = cl->dev;
 
-	if (cl->state != MEI_FILE_CONNECTED)
-		goto err;
-
 	if (dev->iamthif_state != MEI_IAMTHIF_READING)
-		goto err;
-
-	list_for_each_entry(cb, &dev->read_list.list, list) {
-		if (cl == cb->cl)
-			break;
-	}
-
-	if (&cb->list == &dev->read_list.list) {
-		dev_err(dev->dev, "no reader found\n");
-		goto err;
-	}
-
-	if (dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length) {
-		cb->status = -ERANGE;
-		goto err;
-	}
-
-	buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
-	mei_read_slots(dev, buffer, mei_hdr->length);
+		return 0;
 
-	dev->iamthif_msg_buf_index += mei_hdr->length;
+	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_current_cb = NULL;
-
 	dev->iamthif_stall_timer = 0;
-	cb->buf_idx = dev->iamthif_msg_buf_index;
-	cb->read_time = jiffies;
-
-	dev_dbg(dev->dev, "complete the amthif read cb.\n ");
-	list_move_tail(&cb->list, &complete_list->list);
 
 	return 0;
-
-err:
-	mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
-	dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
-				MEI_HDR_PRM(mei_hdr));
-	return 0;
 }
 
 /**
@@ -530,8 +477,6 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (dev->iamthif_canceled != 1) {
 		dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
 		dev->iamthif_stall_timer = 0;
-		memcpy(cb->response_buffer.data,
-			dev->iamthif_msg_buf, dev->iamthif_msg_buf_index);
 		list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list);
 		dev_dbg(dev->dev, "amthif read completed\n");
 		dev->iamthif_timer = jiffies;
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 80386f9c27e9..21cf626e8908 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -102,6 +102,8 @@ bool mei_cl_is_other_connecting(struct mei_cl *cl);
 int mei_cl_disconnect(struct mei_cl *cl);
 int mei_cl_connect(struct mei_cl *cl, struct file *file);
 int mei_cl_read_start(struct mei_cl *cl, size_t length);
+int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr,
+			struct mei_cl_cb *cmpl_list);
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
 int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 		     struct mei_cl_cb *cmpl_list);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 89f2fbce160f..466c1d22fb16 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -82,6 +82,24 @@ static bool mei_cl_is_reading(struct mei_cl *cl)
 }
 
 /**
+ * mei_irq_discard_msg  - discard received message
+ *
+ * @dev: mei device
+ * @hdr: message header
+ */
+static inline
+void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
+{
+	/*
+	 * no need to check for size as it is guarantied
+	 * that length fits into rd_msg_buf
+	 */
+	mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
+	dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
+		MEI_HDR_PRM(hdr));
+}
+
+/**
  * mei_cl_irq_read_msg - process client message
  *
  * @cl: reading client
@@ -90,9 +108,9 @@ static bool mei_cl_is_reading(struct mei_cl *cl)
  *
  * Return: always 0
  */
-static int mei_cl_irq_read_msg(struct mei_cl *cl,
-			       struct mei_msg_hdr *mei_hdr,
-			       struct mei_cl_cb *complete_list)
+int mei_cl_irq_read_msg(struct mei_cl *cl,
+		       struct mei_msg_hdr *mei_hdr,
+		       struct mei_cl_cb *complete_list)
 {
 	struct mei_device *dev = cl->dev;
 	struct mei_cl_cb *cb;
@@ -144,20 +162,17 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
 	mei_read_slots(dev, buffer, mei_hdr->length);
 
 	cb->buf_idx += mei_hdr->length;
+
 	if (mei_hdr->msg_complete) {
+		cb->read_time = jiffies;
 		cl_dbg(dev, cl, "completed read length = %lu\n",
 			cb->buf_idx);
 		list_move_tail(&cb->list, &complete_list->list);
 	}
 
 out:
-	if (!buffer) {
-		/* assume that mei_hdr->length <= MEI_RD_MSG_BUF_SIZE */
-		BUG_ON(mei_hdr->length > MEI_RD_MSG_BUF_SIZE);
-		mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
-		dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
-				MEI_HDR_PRM(mei_hdr));
-	}
+	if (!buffer)
+		mei_irq_discard_msg(dev, mei_hdr);
 
 	return 0;
 }
@@ -569,8 +584,6 @@ void mei_timer(struct work_struct *work)
 		if (--dev->iamthif_stall_timer == 0) {
 			dev_err(dev->dev, "timer: amthif  hanged.\n");
 			mei_reset(dev);
-			dev->iamthif_msg_buf_size = 0;
-			dev->iamthif_msg_buf_index = 0;
 			dev->iamthif_canceled = false;
 			dev->iamthif_state = MEI_IAMTHIF_IDLE;
 			dev->iamthif_timer = 0;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 2f2242f1bed1..57a47d6b63ee 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -485,9 +485,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @iamthif_mtu : amthif client max message length
  * @iamthif_timer : time stamp of current amthif command completion
  * @iamthif_stall_timer : timer to detect amthif hang
- * @iamthif_msg_buf : amthif current message buffer
- * @iamthif_msg_buf_size : size of current amthif message request buffer
- * @iamthif_msg_buf_index : current index in amthif message request buffer
  * @iamthif_state : amthif processor state
  * @iamthif_canceled : current amthif command is canceled
  *
@@ -583,9 +580,6 @@ struct mei_device {
 	int iamthif_mtu;
 	unsigned long iamthif_timer;
 	u32 iamthif_stall_timer;
-	unsigned char *iamthif_msg_buf; /* Note: memory has to be allocated */
-	u32 iamthif_msg_buf_size;
-	u32 iamthif_msg_buf_index;
 	enum iamthif_states iamthif_state;
 	bool iamthif_canceled;
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 13/18] mei: use only one buffer in callback
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (9 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 12/18] mei: iamthif: use regular client read functions Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 14/18] mei: always initialize the callback with the intended operation type Tomas Winkler
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

The callback structure is used exclusively for reading or writing
therefore there is no reason to hold both response and request buffers
in the callback structure

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    |  8 ++++----
 drivers/misc/mei/bus.c       |  6 +++---
 drivers/misc/mei/client.c    | 47 ++++++++++----------------------------------
 drivers/misc/mei/client.h    |  3 +--
 drivers/misc/mei/interrupt.c | 16 +++++++--------
 drivers/misc/mei/main.c      |  8 ++++----
 drivers/misc/mei/mei_dev.h   |  6 ++----
 7 files changed, 31 insertions(+), 63 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 4060e2f40286..2cc41cb3bb38 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -213,15 +213,15 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 		 * remove message from deletion list
 		 */
 
-	dev_dbg(dev->dev, "amthif cb->response_buffer size - %d\n",
-	    cb->response_buffer.size);
+	dev_dbg(dev->dev, "amthif cb->buf size - %d\n",
+	    cb->buf.size);
 	dev_dbg(dev->dev, "amthif cb->buf_idx - %lu\n", cb->buf_idx);
 
 	/* length is being truncated to PAGE_SIZE, however,
 	 * the buf_idx may point beyond */
 	length = min_t(size_t, length, (cb->buf_idx - *offset));
 
-	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
+	if (copy_to_user(ubuf, cb->buf.data + *offset, length)) {
 		dev_dbg(dev->dev, "failed to copy data to userland\n");
 		rets = -EFAULT;
 	} else {
@@ -260,7 +260,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
 		goto err;
 	}
 
-	rets = mei_io_cb_alloc_resp_buf(cb, length);
+	rets = mei_io_cb_alloc_buf(cb, length);
 	if (rets)
 		goto err;
 
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 025626f4467d..36b949a0fddb 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -261,11 +261,11 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
 		goto out;
 	}
 
-	rets = mei_io_cb_alloc_req_buf(cb, length);
+	rets = mei_io_cb_alloc_buf(cb, length);
 	if (rets < 0)
 		goto out;
 
-	memcpy(cb->request_buffer.data, buf, length);
+	memcpy(cb->buf.data, buf, length);
 
 	rets = mei_cl_write(cl, cb, blocking);
 
@@ -328,7 +328,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 	}
 
 	r_length = min_t(size_t, length, cb->buf_idx);
-	memcpy(buf, cb->response_buffer.data, r_length);
+	memcpy(buf, cb->buf.data, r_length);
 	rets = r_length;
 
 free:
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 978f7f95d66d..9eee3d4b2bc0 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -376,8 +376,7 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
 	if (cb == NULL)
 		return;
 
-	kfree(cb->request_buffer.data);
-	kfree(cb->response_buffer.data);
+	kfree(cb->buf.data);
 	kfree(cb);
 }
 
@@ -406,7 +405,7 @@ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
 }
 
 /**
- * mei_io_cb_alloc_req_buf - allocate request buffer
+ * mei_io_cb_alloc_buf - allocate callback buffer
  *
  * @cb: io callback structure
  * @length: size of the buffer
@@ -415,7 +414,7 @@ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
  *         -EINVAL if cb is NULL
  *         -ENOMEM if allocation failed
  */
-int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
+int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length)
 {
 	if (!cb)
 		return -EINVAL;
@@ -423,38 +422,12 @@ int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length)
 	if (length == 0)
 		return 0;
 
-	cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
-	if (!cb->request_buffer.data)
+	cb->buf.data = kmalloc(length, GFP_KERNEL);
+	if (!cb->buf.data)
 		return -ENOMEM;
-	cb->request_buffer.size = length;
+	cb->buf.size = length;
 	return 0;
 }
-/**
- * mei_io_cb_alloc_resp_buf - allocate response buffer
- *
- * @cb: io callback structure
- * @length: size of the buffer
- *
- * Return: 0 on success
- *         -EINVAL if cb is NULL
- *         -ENOMEM if allocation failed
- */
-int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length)
-{
-	if (!cb)
-		return -EINVAL;
-
-	if (length == 0)
-		return 0;
-
-	cb->response_buffer.data = kmalloc(length, GFP_KERNEL);
-	if (!cb->response_buffer.data)
-		return -ENOMEM;
-	cb->response_buffer.size = length;
-	return 0;
-}
-
-
 
 /**
  * mei_cl_flush_queues - flushes queue lists belonging to cl.
@@ -1005,7 +978,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 		goto out;
 	}
 
-	rets = mei_io_cb_alloc_resp_buf(cb, length);
+	rets = mei_io_cb_alloc_buf(cb, length);
 	if (rets)
 		goto out;
 
@@ -1059,7 +1032,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 	dev = cl->dev;
 
-	buf = &cb->request_buffer;
+	buf = &cb->buf;
 
 	rets = mei_cl_flow_ctrl_creds(cl);
 	if (rets < 0)
@@ -1094,7 +1067,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
 	}
 
 	cl_dbg(dev, cl, "buf: size = %d idx = %lu\n",
-			cb->request_buffer.size, cb->buf_idx);
+			cb->buf.size, cb->buf_idx);
 
 	rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
 	if (rets) {
@@ -1144,7 +1117,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 	dev = cl->dev;
 
 
-	buf = &cb->request_buffer;
+	buf = &cb->buf;
 
 	cl_dbg(dev, cl, "size=%d\n", buf->size);
 
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 21cf626e8908..d430a6e09ae8 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -49,8 +49,7 @@ void mei_me_cl_rm_all(struct mei_device *dev);
  */
 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
 void mei_io_cb_free(struct mei_cl_cb *priv_cb);
-int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length);
-int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length);
+int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length);
 
 
 /**
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 466c1d22fb16..60469a0053bb 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -134,19 +134,17 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
 
 	cl->reading_state = MEI_READING;
 
-	if (cb->response_buffer.size == 0 ||
-	    cb->response_buffer.data == NULL) {
+	if (cb->buf.size == 0 || cb->buf.data == NULL) {
 		cl_err(dev, cl, "response buffer is not allocated.\n");
 		list_move_tail(&cb->list, &complete_list->list);
 		cb->status = -ENOMEM;
 		goto out;
 	}
 
-	if (cb->response_buffer.size < mei_hdr->length + cb->buf_idx) {
+	if (cb->buf.size < mei_hdr->length + cb->buf_idx) {
 		cl_dbg(dev, cl, "message overflow. size %d len %d idx %ld\n",
-			cb->response_buffer.size, mei_hdr->length, cb->buf_idx);
-		buffer = krealloc(cb->response_buffer.data,
-				  mei_hdr->length + cb->buf_idx,
+			cb->buf.size, mei_hdr->length, cb->buf_idx);
+		buffer = krealloc(cb->buf.data, mei_hdr->length + cb->buf_idx,
 				  GFP_KERNEL);
 
 		if (!buffer) {
@@ -154,11 +152,11 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
 			list_move_tail(&cb->list, &complete_list->list);
 			goto out;
 		}
-		cb->response_buffer.data = buffer;
-		cb->response_buffer.size = mei_hdr->length + cb->buf_idx;
+		cb->buf.data = buffer;
+		cb->buf.size = mei_hdr->length + cb->buf_idx;
 	}
 
-	buffer = cb->response_buffer.data + cb->buf_idx;
+	buffer = cb->buf.data + cb->buf_idx;
 	mei_read_slots(dev, buffer, mei_hdr->length);
 
 	cb->buf_idx += mei_hdr->length;
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 9d1a8cba81c9..1d44d110ed94 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -264,7 +264,7 @@ copy_buffer:
 	}
 
 	dev_dbg(dev->dev, "buf.size = %d buf.idx= %ld\n",
-	    cb->response_buffer.size, cb->buf_idx);
+	    cb->buf.size, cb->buf_idx);
 	if (length == 0 || ubuf == NULL || *offset > cb->buf_idx) {
 		rets = -EMSGSIZE;
 		goto free;
@@ -274,7 +274,7 @@ copy_buffer:
 	 * however buf_idx may point beyond that */
 	length = min_t(size_t, length, cb->buf_idx - *offset);
 
-	if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
+	if (copy_to_user(ubuf, cb->buf.data + *offset, length)) {
 		dev_dbg(dev->dev, "failed to copy data to userland\n");
 		rets = -EFAULT;
 		goto free;
@@ -389,11 +389,11 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		rets = -ENOMEM;
 		goto out;
 	}
-	rets = mei_io_cb_alloc_req_buf(write_cb, length);
+	rets = mei_io_cb_alloc_buf(write_cb, length);
 	if (rets)
 		goto out;
 
-	rets = copy_from_user(write_cb->request_buffer.data, ubuf, length);
+	rets = copy_from_user(write_cb->buf.data, ubuf, length);
 	if (rets) {
 		dev_dbg(dev->dev, "failed to copy data from userland\n");
 		rets = -EFAULT;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 57a47d6b63ee..1a0f6e9588b6 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -194,8 +194,7 @@ struct mei_cl;
  * @list: link in callback queue
  * @cl: file client who is running this operation
  * @fop_type: file operation type
- * @request_buffer: buffer to store request data
- * @response_buffer: buffer to store response data
+ * @buf: buffer for data associated with the callback
  * @buf_idx: last read index
  * @read_time: last read operation time stamp (iamthif)
  * @file_object: pointer to file structure
@@ -207,8 +206,7 @@ struct mei_cl_cb {
 	struct list_head list;
 	struct mei_cl *cl;
 	enum mei_cb_file_ops fop_type;
-	struct mei_msg_data request_buffer;
-	struct mei_msg_data response_buffer;
+	struct mei_msg_data buf;
 	unsigned long buf_idx;
 	unsigned long read_time;
 	struct file *file_object;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 14/18] mei: always initialize the callback with the intended operation type
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (10 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 13/18] mei: use only one buffer in callback Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 15/18] mei: add mei_cl_alloc_linked function Tomas Winkler
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

We set the operation type at initialization time as each cb is used only
for a single type of operation

As a byproduct we add a convenient wrapper for allocating cb with
the data buffer.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c |  4 +--
 drivers/misc/mei/bus.c    | 14 ++++-------
 drivers/misc/mei/client.c | 64 ++++++++++++++++++++++++++++++-----------------
 drivers/misc/mei/client.h |  7 ++++--
 drivers/misc/mei/hbm.c    |  3 +--
 drivers/misc/mei/main.c   |  8 ++----
 6 files changed, 55 insertions(+), 45 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 2cc41cb3bb38..3fdd22395b9f 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -254,7 +254,7 @@ static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
 	size_t length = dev->iamthif_mtu;
 	int rets;
 
-	cb = mei_io_cb_init(cl, file);
+	cb = mei_io_cb_init(cl, MEI_FOP_READ, file);
 	if (!cb) {
 		rets = -ENOMEM;
 		goto err;
@@ -264,7 +264,6 @@ static int mei_amthif_read_start(struct mei_cl *cl, struct file *file)
 	if (rets)
 		goto err;
 
-	cb->fop_type = MEI_FOP_READ;
 	list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 
 	dev->iamthif_state = MEI_IAMTHIF_READING;
@@ -359,7 +358,6 @@ int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb)
 
 	dev = cl->dev;
 
-	cb->fop_type = MEI_FOP_WRITE;
 	list_add_tail(&cb->list, &dev->amthif_cmd_list.list);
 	return mei_amthif_run_next_cmd(dev);
 }
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 36b949a0fddb..3e6ffed9402a 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -255,16 +255,12 @@ static ssize_t ___mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
 		goto out;
 	}
 
-	cb = mei_io_cb_init(cl, NULL);
+	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
 	if (!cb) {
 		rets = -ENOMEM;
 		goto out;
 	}
 
-	rets = mei_io_cb_alloc_buf(cb, length);
-	if (rets < 0)
-		goto out;
-
 	memcpy(cb->buf.data, buf, length);
 
 	rets = mei_cl_write(cl, cb, blocking);
@@ -293,7 +289,7 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 	mutex_lock(&dev->device_lock);
 
 	if (!cl->read_cb) {
-		rets = mei_cl_read_start(cl, length);
+		rets = mei_cl_read_start(cl, length, NULL);
 		if (rets < 0)
 			goto out;
 	}
@@ -392,7 +388,7 @@ static void mei_bus_event_work(struct work_struct *work)
 	device->events = 0;
 
 	/* Prepare for the next read */
-	mei_cl_read_start(device->cl, 0);
+	mei_cl_read_start(device->cl, 0, NULL);
 }
 
 int mei_cl_register_event_cb(struct mei_cl_device *device,
@@ -406,7 +402,7 @@ int mei_cl_register_event_cb(struct mei_cl_device *device,
 	device->event_context = context;
 	INIT_WORK(&device->event_work, mei_bus_event_work);
 
-	mei_cl_read_start(device->cl, 0);
+	mei_cl_read_start(device->cl, 0, NULL);
 
 	return 0;
 }
@@ -448,7 +444,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
 	mutex_unlock(&dev->device_lock);
 
 	if (device->event_cb && !cl->read_cb)
-		mei_cl_read_start(device->cl, 0);
+		mei_cl_read_start(device->cl, 0, NULL);
 
 	if (!device->ops || !device->ops->enable)
 		return 0;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 9eee3d4b2bc0..86450c2fc810 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -384,11 +384,13 @@ void mei_io_cb_free(struct mei_cl_cb *cb)
  * mei_io_cb_init - allocate and initialize io callback
  *
  * @cl: mei client
+ * @type: operation type
  * @fp: pointer to file structure
  *
  * Return: mei_cl_cb pointer or NULL;
  */
-struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
+				 struct file *fp)
 {
 	struct mei_cl_cb *cb;
 
@@ -401,6 +403,7 @@ struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp)
 	cb->file_object = fp;
 	cb->cl = cl;
 	cb->buf_idx = 0;
+	cb->fop_type = type;
 	return cb;
 }
 
@@ -430,6 +433,33 @@ int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length)
 }
 
 /**
+ * mei_cl_alloc_cb - a convenient wrapper for allocating read cb
+ *
+ * @cl: host client
+ * @length: size of the buffer
+ * @type: operation type
+ * @fp: associated file pointer (might be NULL)
+ *
+ * Return: cb on success and NULL on failure
+ */
+struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
+				  enum mei_cb_file_ops type, struct file *fp)
+{
+	struct mei_cl_cb *cb;
+
+	cb = mei_io_cb_init(cl, type, fp);
+	if (!cb)
+		return NULL;
+
+	if (mei_io_cb_alloc_buf(cb, length)) {
+		mei_io_cb_free(cb);
+		return NULL;
+	}
+
+	return cb;
+}
+
+/**
  * mei_cl_flush_queues - flushes queue lists belonging to cl.
  *
  * @cl: host client
@@ -688,13 +718,10 @@ int mei_cl_disconnect(struct mei_cl *cl)
 		return rets;
 	}
 
-	cb = mei_io_cb_init(cl, NULL);
-	if (!cb) {
-		rets = -ENOMEM;
+	cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT, NULL);
+	rets = cb ? 0 : -ENOMEM;
+	if (rets)
 		goto free;
-	}
-
-	cb->fop_type = MEI_FOP_DISCONNECT;
 
 	if (mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
@@ -795,13 +822,10 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 		return rets;
 	}
 
-	cb = mei_io_cb_init(cl, file);
-	if (!cb) {
-		rets = -ENOMEM;
+	cb = mei_io_cb_init(cl, MEI_FOP_CONNECT, file);
+	rets = cb ? 0 : -ENOMEM;
+	if (rets)
 		goto out;
-	}
-
-	cb->fop_type = MEI_FOP_CONNECT;
 
 	/* run hbuf acquire last so we don't have to undo */
 	if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
@@ -934,10 +958,11 @@ out:
  *
  * @cl: host client
  * @length: number of bytes to read
+ * @fp: pointer to file structure
  *
  * Return: 0 on success, <0 on failure.
  */
-int mei_cl_read_start(struct mei_cl *cl, size_t length)
+int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
 {
 	struct mei_device *dev;
 	struct mei_cl_cb *cb;
@@ -972,17 +997,11 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 		return rets;
 	}
 
-	cb = mei_io_cb_init(cl, NULL);
-	if (!cb) {
-		rets = -ENOMEM;
-		goto out;
-	}
-
-	rets = mei_io_cb_alloc_buf(cb, length);
+	cb = mei_cl_alloc_cb(cl, length, MEI_FOP_READ, fp);
+	rets = cb ? 0 : -ENOMEM;
 	if (rets)
 		goto out;
 
-	cb->fop_type = MEI_FOP_READ;
 	if (mei_hbuf_acquire(dev)) {
 		rets = mei_hbm_cl_flow_control_req(dev, cl);
 		if (rets < 0)
@@ -1128,7 +1147,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 		return rets;
 	}
 
-	cb->fop_type = MEI_FOP_WRITE;
 	cb->buf_idx = 0;
 	cl->writing_state = MEI_IDLE;
 
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index d430a6e09ae8..f7d0285b5f57 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -47,7 +47,8 @@ void mei_me_cl_rm_all(struct mei_device *dev);
 /*
  * MEI IO Functions
  */
-struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp);
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
+				 struct file *fp);
 void mei_io_cb_free(struct mei_cl_cb *priv_cb);
 int mei_io_cb_alloc_buf(struct mei_cl_cb *cb, size_t length);
 
@@ -77,6 +78,8 @@ int mei_cl_unlink(struct mei_cl *cl);
 int mei_cl_flush_queues(struct mei_cl *cl);
 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl);
 
+struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
+				  enum mei_cb_file_ops type, struct file *fp);
 
 int mei_cl_flow_ctrl_creds(struct mei_cl *cl);
 
@@ -100,7 +103,7 @@ static inline bool mei_cl_is_transitioning(struct mei_cl *cl)
 bool mei_cl_is_other_connecting(struct mei_cl *cl);
 int mei_cl_disconnect(struct mei_cl *cl);
 int mei_cl_connect(struct mei_cl *cl, struct file *file);
-int mei_cl_read_start(struct mei_cl *cl, size_t length);
+int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp);
 int mei_cl_irq_read_msg(struct mei_cl *cl, struct mei_msg_hdr *hdr,
 			struct mei_cl_cb *cmpl_list);
 int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 4f83e9aaa6f9..2c581dcaf3b1 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -684,10 +684,9 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 		cl->state = MEI_FILE_DISCONNECTED;
 		cl->timer_count = 0;
 
-		cb = mei_io_cb_init(cl, NULL);
+		cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL);
 		if (!cb)
 			return -ENOMEM;
-		cb->fop_type = MEI_FOP_DISCONNECT_RSP;
 		cl_dbg(dev, cl, "add disconnect response as first\n");
 		list_add(&cb->list, &dev->ctrl_wr_list.list);
 	}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 1d44d110ed94..369de0a070f1 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -209,7 +209,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		*offset = 0;
 	}
 
-	err = mei_cl_read_start(cl, length);
+	err = mei_cl_read_start(cl, length, file);
 	if (err && err != -EBUSY) {
 		dev_dbg(dev->dev,
 			"mei start read failure with status = %d\n", err);
@@ -383,15 +383,11 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 	} else if (cl->reading_state == MEI_IDLE)
 		*offset = 0;
 
-
-	write_cb = mei_io_cb_init(cl, file);
+	write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
 	if (!write_cb) {
 		rets = -ENOMEM;
 		goto out;
 	}
-	rets = mei_io_cb_alloc_buf(write_cb, length);
-	if (rets)
-		goto out;
 
 	rets = copy_from_user(write_cb->buf.data, ubuf, length);
 	if (rets) {
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 15/18] mei: add mei_cl_alloc_linked function
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (11 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 14/18] mei: always initialize the callback with the intended operation type Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 16/18] mei: simplify io callback disposal Tomas Winkler
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Add convenient wrapper mei_cl_alloc_linked
to simplify error handling

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/client.c | 35 +++++++++++++++++++++++++++++++++--
 drivers/misc/mei/client.h |  2 ++
 drivers/misc/mei/main.c   | 17 +++++------------
 drivers/misc/mei/nfc.c    | 43 +++++++++++++++++++++----------------------
 4 files changed, 61 insertions(+), 36 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 86450c2fc810..830a3facbb2b 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -547,11 +547,11 @@ struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
  * mei_cl_link - allocate host id in the host map
  *
  * @cl: host client
- * @id: fixed host id or -1 for generic one
+ * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one
  *
  * Return: 0 on success
  *	-EINVAL on incorrect values
- *	-ENONET if client not found
+ *	-EMFILE if open count exceeded.
  */
 int mei_cl_link(struct mei_cl *cl, int id)
 {
@@ -870,6 +870,37 @@ out:
 }
 
 /**
+ * mei_cl_alloc_linked - allocate and link host client
+ *
+ * @dev: the device structure
+ * @id: fixed host id or MEI_HOST_CLIENT_ID_ANY (-1) for generic one
+ *
+ * Return: cl on success ERR_PTR on failure
+ */
+struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id)
+{
+	struct mei_cl *cl;
+	int ret;
+
+	cl = mei_cl_allocate(dev);
+	if (!cl) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	ret = mei_cl_link(cl, id);
+	if (ret)
+		goto err;
+
+	return cl;
+err:
+	kfree(cl);
+	return ERR_PTR(ret);
+}
+
+
+
+/**
  * mei_cl_flow_ctrl_creds - checks flow_control credits for cl.
  *
  * @cl: private data of the file object
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index f7d0285b5f57..c3d0e200a642 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -75,6 +75,8 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
 int mei_cl_link(struct mei_cl *cl, int id);
 int mei_cl_unlink(struct mei_cl *cl);
 
+struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id);
+
 int mei_cl_flush_queues(struct mei_cl *cl);
 struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl);
 
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 369de0a070f1..10fc3a6a1574 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -59,24 +59,18 @@ static int mei_open(struct inode *inode, struct file *file)
 
 	mutex_lock(&dev->device_lock);
 
-	cl = NULL;
-
-	err = -ENODEV;
 	if (dev->dev_state != MEI_DEV_ENABLED) {
 		dev_dbg(dev->dev, "dev_state != MEI_ENABLED  dev_state = %s\n",
 		    mei_dev_state_str(dev->dev_state));
+		err = -ENODEV;
 		goto err_unlock;
 	}
 
-	err = -ENOMEM;
-	cl = mei_cl_allocate(dev);
-	if (!cl)
-		goto err_unlock;
-
-	/* open_handle_count check is handled in the mei_cl_link */
-	err = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
-	if (err)
+	cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
+	if (IS_ERR(cl)) {
+		err = PTR_ERR(cl);
 		goto err_unlock;
+	}
 
 	file->private_data = cl;
 
@@ -86,7 +80,6 @@ static int mei_open(struct inode *inode, struct file *file)
 
 err_unlock:
 	mutex_unlock(&dev->device_lock);
-	kfree(cl);
 	return err;
 }
 
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
index bb61a119b8bb..c3bcb63686d7 100644
--- a/drivers/misc/mei/nfc.c
+++ b/drivers/misc/mei/nfc.c
@@ -482,8 +482,8 @@ err:
 int mei_nfc_host_init(struct mei_device *dev)
 {
 	struct mei_nfc_dev *ndev;
-	struct mei_cl *cl_info, *cl = NULL;
-	struct mei_me_client *me_cl;
+	struct mei_cl *cl_info, *cl;
+	struct mei_me_client *me_cl = NULL;
 	int ret;
 
 
@@ -500,17 +500,6 @@ int mei_nfc_host_init(struct mei_device *dev)
 		goto err;
 	}
 
-	ndev->cl_info = mei_cl_allocate(dev);
-	ndev->cl = mei_cl_allocate(dev);
-
-	cl = ndev->cl;
-	cl_info = ndev->cl_info;
-
-	if (!cl || !cl_info) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
 	/* check for valid client id */
 	me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
 	if (!me_cl) {
@@ -519,17 +508,21 @@ int mei_nfc_host_init(struct mei_device *dev)
 		goto err;
 	}
 
+	cl_info = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
+	if (IS_ERR(cl_info)) {
+		ret = PTR_ERR(cl_info);
+		goto err;
+	}
+
 	cl_info->me_client_id = me_cl->client_id;
 	cl_info->cl_uuid = me_cl->props.protocol_name;
 	mei_me_cl_put(me_cl);
-
-	ret = mei_cl_link(cl_info, MEI_HOST_CLIENT_ID_ANY);
-	if (ret)
-		goto err;
-
+	me_cl = NULL;
 
 	list_add_tail(&cl_info->device_link, &dev->device_list);
 
+	ndev->cl_info = cl_info;
+
 	/* check for valid client id */
 	me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
 	if (!me_cl) {
@@ -538,16 +531,21 @@ int mei_nfc_host_init(struct mei_device *dev)
 		goto err;
 	}
 
+	cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
+	if (IS_ERR(cl)) {
+		ret = PTR_ERR(cl);
+		goto err;
+	}
+
 	cl->me_client_id = me_cl->client_id;
 	cl->cl_uuid = me_cl->props.protocol_name;
 	mei_me_cl_put(me_cl);
-
-	ret = mei_cl_link(cl, MEI_HOST_CLIENT_ID_ANY);
-	if (ret)
-		goto err;
+	me_cl = NULL;
 
 	list_add_tail(&cl->device_link, &dev->device_list);
 
+	ndev->cl = cl;
+
 	ndev->req_id = 1;
 
 	INIT_WORK(&ndev->init_work, mei_nfc_init);
@@ -557,6 +555,7 @@ int mei_nfc_host_init(struct mei_device *dev)
 	return 0;
 
 err:
+	mei_me_cl_put(me_cl);
 	mei_nfc_free(ndev);
 
 	return ret;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 16/18] mei: simplify io callback disposal
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (12 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 15/18] mei: add mei_cl_alloc_linked function Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 17/18] mei: allow read concurrency Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 18/18] mei: bus: call device disable handler prior to disconnection Tomas Winkler
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Simplify disposal of io callback by removing the callback
implicitly from its lookup list inside mei_io_cb_free

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 24 +++++-------
 drivers/misc/mei/bus.c       | 22 ++---------
 drivers/misc/mei/client.c    | 88 ++++++++++++++++++++++----------------------
 drivers/misc/mei/hbm.c       |  2 +-
 drivers/misc/mei/interrupt.c |  3 +-
 drivers/misc/mei/main.c      | 29 +++------------
 6 files changed, 63 insertions(+), 105 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 3fdd22395b9f..7b6ed0bbfc9c 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -196,16 +196,16 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
 	if  (time_after(jiffies, timeout)) {
 		dev_dbg(dev->dev, "amthif Time out\n");
 		/* 15 sec for the message has expired */
-		list_del(&cb->list);
+		list_del_init(&cb->list);
 		rets = -ETIME;
 		goto free;
 	}
 	/* if the whole message will fit remove it from the list */
 	if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset))
-		list_del(&cb->list);
+		list_del_init(&cb->list);
 	else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) {
 		/* end of the message has been reached */
-		list_del(&cb->list);
+		list_del_init(&cb->list);
 		rets = 0;
 		goto free;
 	}
@@ -504,26 +504,22 @@ void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb)
 static bool mei_clear_list(struct mei_device *dev,
 		const struct file *file, struct list_head *mei_cb_list)
 {
-	struct mei_cl_cb *cb_pos = NULL;
-	struct mei_cl_cb *cb_next = NULL;
+	struct mei_cl *cl = &dev->iamthif_cl;
+	struct mei_cl_cb *cb, *next;
 	bool removed = false;
 
 	/* list all list member */
-	list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, list) {
+	list_for_each_entry_safe(cb, next, mei_cb_list, list) {
 		/* check if list member associated with a file */
-		if (file == cb_pos->file_object) {
-			/* remove member from the list */
-			list_del(&cb_pos->list);
+		if (file == cb->file_object) {
 			/* check if cb equal to current iamthif cb */
-			if (dev->iamthif_current_cb == cb_pos) {
+			if (dev->iamthif_current_cb == cb) {
 				dev->iamthif_current_cb = NULL;
 				/* send flow control to iamthif client */
-				mei_hbm_cl_flow_control_req(dev,
-							&dev->iamthif_cl);
+				mei_hbm_cl_flow_control_req(dev, cl);
 			}
 			/* free all allocated buffers */
-			mei_io_cb_free(cb_pos);
-			cb_pos = NULL;
+			mei_io_cb_free(cb);
 			removed = true;
 		}
 	}
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 3e6ffed9402a..b5385372693d 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -311,13 +311,13 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 		mutex_lock(&dev->device_lock);
 	}
 
-	cb = cl->read_cb;
 
 	if (cl->reading_state != MEI_READ_COMPLETE) {
 		rets = 0;
 		goto out;
 	}
 
+	cb = cl->read_cb;
 	if (cb->status) {
 		rets = cb->status;
 		goto free;
@@ -329,8 +329,8 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 
 free:
 	mei_io_cb_free(cb);
-	cl->reading_state = MEI_IDLE;
 	cl->read_cb = NULL;
+	cl->reading_state = MEI_IDLE;
 
 out:
 	mutex_unlock(&dev->device_lock);
@@ -486,23 +486,7 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 
 	/* Flush queues and remove any pending read */
 	mei_cl_flush_queues(cl);
-
-	if (cl->read_cb) {
-		struct mei_cl_cb *cb = NULL;
-
-		cb = mei_cl_find_read_cb(cl);
-		/* Remove entry from read list */
-		if (cb)
-			list_del(&cb->list);
-
-		cb = cl->read_cb;
-		cl->read_cb = NULL;
-
-		if (cb) {
-			mei_io_cb_free(cb);
-			cb = NULL;
-		}
-	}
+	mei_io_cb_free(cl->read_cb);
 
 	device->event_cb = NULL;
 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 830a3facbb2b..f28eed12e7ab 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -321,6 +321,47 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 }
 
 /**
+ * mei_io_cb_free - free mei_cb_private related memory
+ *
+ * @cb: mei callback struct
+ */
+void mei_io_cb_free(struct mei_cl_cb *cb)
+{
+	if (cb == NULL)
+		return;
+
+	list_del(&cb->list);
+	kfree(cb->buf.data);
+	kfree(cb);
+}
+
+/**
+ * mei_io_cb_init - allocate and initialize io callback
+ *
+ * @cl: mei client
+ * @type: operation type
+ * @fp: pointer to file structure
+ *
+ * Return: mei_cl_cb pointer or NULL;
+ */
+struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
+				 struct file *fp)
+{
+	struct mei_cl_cb *cb;
+
+	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
+	if (!cb)
+		return NULL;
+
+	INIT_LIST_HEAD(&cb->list);
+	cb->file_object = fp;
+	cb->cl = cl;
+	cb->buf_idx = 0;
+	cb->fop_type = type;
+	return cb;
+}
+
+/**
  * __mei_io_list_flush - removes and frees cbs belonging to cl.
  *
  * @list:  an instance of our list structure
@@ -330,13 +371,12 @@ static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
 static void __mei_io_list_flush(struct mei_cl_cb *list,
 				struct mei_cl *cl, bool free)
 {
-	struct mei_cl_cb *cb;
-	struct mei_cl_cb *next;
+	struct mei_cl_cb *cb, *next;
 
 	/* enable removing everything if no cl is specified */
 	list_for_each_entry_safe(cb, next, &list->list, list) {
 		if (!cl || mei_cl_cmp_id(cl, cb->cl)) {
-			list_del(&cb->list);
+			list_del_init(&cb->list);
 			if (free)
 				mei_io_cb_free(cb);
 		}
@@ -354,7 +394,6 @@ void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl)
 	__mei_io_list_flush(list, cl, false);
 }
 
-
 /**
  * mei_io_list_free - removes cb belonging to cl and free them
  *
@@ -367,47 +406,6 @@ static inline void mei_io_list_free(struct mei_cl_cb *list, struct mei_cl *cl)
 }
 
 /**
- * mei_io_cb_free - free mei_cb_private related memory
- *
- * @cb: mei callback struct
- */
-void mei_io_cb_free(struct mei_cl_cb *cb)
-{
-	if (cb == NULL)
-		return;
-
-	kfree(cb->buf.data);
-	kfree(cb);
-}
-
-/**
- * mei_io_cb_init - allocate and initialize io callback
- *
- * @cl: mei client
- * @type: operation type
- * @fp: pointer to file structure
- *
- * Return: mei_cl_cb pointer or NULL;
- */
-struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, enum mei_cb_file_ops type,
-				 struct file *fp)
-{
-	struct mei_cl_cb *cb;
-
-	cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
-	if (!cb)
-		return NULL;
-
-	mei_io_list_init(cb);
-
-	cb->file_object = fp;
-	cb->cl = cl;
-	cb->buf_idx = 0;
-	cb->fop_type = type;
-	return cb;
-}
-
-/**
  * mei_io_cb_alloc_buf - allocate callback buffer
  *
  * @cb: io callback structure
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 2c581dcaf3b1..58da92565c5e 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -639,7 +639,7 @@ static void mei_hbm_cl_res(struct mei_device *dev,
 			continue;
 
 		if (mei_hbm_cl_addr_equal(cl, rs)) {
-			list_del(&cb->list);
+			list_del_init(&cb->list);
 			break;
 		}
 	}
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 60469a0053bb..1e2f3c774853 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -202,7 +202,6 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 	cl->state = MEI_FILE_DISCONNECTED;
 	cl->status = 0;
-	list_del(&cb->list);
 	mei_io_cb_free(cb);
 
 	return ret;
@@ -320,7 +319,7 @@ static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
 	if (ret) {
 		cl->status = ret;
 		cb->buf_idx = 0;
-		list_del(&cb->list);
+		list_del_init(&cb->list);
 		return ret;
 	}
 
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 10fc3a6a1574..c34853be963f 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -94,7 +94,6 @@ err_unlock:
 static int mei_release(struct inode *inode, struct file *file)
 {
 	struct mei_cl *cl = file->private_data;
-	struct mei_cl_cb *cb;
 	struct mei_device *dev;
 	int rets = 0;
 
@@ -118,23 +117,11 @@ static int mei_release(struct inode *inode, struct file *file)
 
 	mei_cl_unlink(cl);
 
-
-	/* free read cb */
-	cb = NULL;
-	if (cl->read_cb) {
-		cb = mei_cl_find_read_cb(cl);
-		/* Remove entry from read list */
-		if (cb)
-			list_del(&cb->list);
-
-		cb = cl->read_cb;
-		cl->read_cb = NULL;
-	}
+	mei_io_cb_free(cl->read_cb);
+	cl->read_cb = NULL;
 
 	file->private_data = NULL;
 
-	mei_io_cb_free(cb);
-
 	kfree(cl);
 out:
 	mutex_unlock(&dev->device_lock);
@@ -156,7 +143,6 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 			size_t length, loff_t *offset)
 {
 	struct mei_cl *cl = file->private_data;
-	struct mei_cl_cb *cb_pos = NULL;
 	struct mei_cl_cb *cb = NULL;
 	struct mei_device *dev;
 	int rets;
@@ -279,13 +265,10 @@ copy_buffer:
 		goto out;
 
 free:
-	cb_pos = mei_cl_find_read_cb(cl);
-	/* Remove entry from read list */
-	if (cb_pos)
-		list_del(&cb_pos->list);
 	mei_io_cb_free(cb);
-	cl->reading_state = MEI_IDLE;
 	cl->read_cb = NULL;
+
+	cl->reading_state = MEI_IDLE;
 out:
 	dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
 	mutex_unlock(&dev->device_lock);
@@ -355,7 +338,6 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 			if (time_after(jiffies, timeout) ||
 			    cl->reading_state == MEI_READ_COMPLETE) {
 				*offset = 0;
-				list_del(&write_cb->list);
 				mei_io_cb_free(write_cb);
 				write_cb = NULL;
 			}
@@ -367,11 +349,10 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		*offset = 0;
 		write_cb = mei_cl_find_read_cb(cl);
 		if (write_cb) {
-			list_del(&write_cb->list);
 			mei_io_cb_free(write_cb);
 			write_cb = NULL;
-			cl->reading_state = MEI_IDLE;
 			cl->read_cb = NULL;
+			cl->reading_state = MEI_IDLE;
 		}
 	} else if (cl->reading_state == MEI_IDLE)
 		*offset = 0;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 17/18] mei: allow read concurrency
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (13 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 16/18] mei: simplify io callback disposal Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  2015-02-10  8:39 ` [char-misc-next 18/18] mei: bus: call device disable handler prior to disconnection Tomas Winkler
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Replace clunky read state machine with read stack
implemented as per client read list, this is important
mostly for mei drivers with unsolicited reads

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/bus.c       | 36 ++++++++++---------
 drivers/misc/mei/client.c    | 84 ++++++++++++++++++++++++++++----------------
 drivers/misc/mei/client.h    |  7 ++--
 drivers/misc/mei/debugfs.c   |  2 +-
 drivers/misc/mei/init.c      |  1 -
 drivers/misc/mei/interrupt.c | 35 +++++-------------
 drivers/misc/mei/main.c      | 42 +++++-----------------
 drivers/misc/mei/mei_dev.h   | 10 +++---
 8 files changed, 98 insertions(+), 119 deletions(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index b5385372693d..17ca7e20fb6a 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -288,19 +288,20 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 
 	mutex_lock(&dev->device_lock);
 
-	if (!cl->read_cb) {
-		rets = mei_cl_read_start(cl, length, NULL);
-		if (rets < 0)
-			goto out;
-	}
+	cb = mei_cl_read_cb(cl, NULL);
+	if (cb)
+		goto copy;
+
+	rets = mei_cl_read_start(cl, length, NULL);
+	if (rets && rets != -EBUSY)
+		goto out;
 
-	if (cl->reading_state != MEI_READ_COMPLETE &&
-	    !waitqueue_active(&cl->rx_wait)) {
+	if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
 
 		mutex_unlock(&dev->device_lock);
 
 		if (wait_event_interruptible(cl->rx_wait,
-				cl->reading_state == MEI_READ_COMPLETE  ||
+				(!list_empty(&cl->rd_completed)) ||
 				mei_cl_is_transitioning(cl))) {
 
 			if (signal_pending(current))
@@ -309,15 +310,20 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 		}
 
 		mutex_lock(&dev->device_lock);
-	}
 
+		if (mei_cl_is_transitioning(cl)) {
+			rets = -EBUSY;
+			goto out;
+		}
+	}
 
-	if (cl->reading_state != MEI_READ_COMPLETE) {
+	cb = mei_cl_read_cb(cl, NULL);
+	if (!cb) {
 		rets = 0;
 		goto out;
 	}
 
-	cb = cl->read_cb;
+copy:
 	if (cb->status) {
 		rets = cb->status;
 		goto free;
@@ -329,9 +335,6 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
 
 free:
 	mei_io_cb_free(cb);
-	cl->read_cb = NULL;
-	cl->reading_state = MEI_IDLE;
-
 out:
 	mutex_unlock(&dev->device_lock);
 
@@ -443,7 +446,7 @@ int mei_cl_enable_device(struct mei_cl_device *device)
 
 	mutex_unlock(&dev->device_lock);
 
-	if (device->event_cb && !cl->read_cb)
+	if (device->event_cb)
 		mei_cl_read_start(device->cl, 0, NULL);
 
 	if (!device->ops || !device->ops->enable)
@@ -485,8 +488,7 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 	}
 
 	/* Flush queues and remove any pending read */
-	mei_cl_flush_queues(cl);
-	mei_io_cb_free(cl->read_cb);
+	mei_cl_flush_queues(cl, NULL);
 
 	device->event_cb = NULL;
 
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index f28eed12e7ab..e220bef0173c 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -458,13 +458,55 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
 }
 
 /**
+ * mei_cl_read_cb - find this cl's callback in the read list
+ *     for a specific file
+ *
+ * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
+ *
+ * Return: cb on success, NULL if cb is not found
+ */
+struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl, const struct file *fp)
+{
+	struct mei_cl_cb *cb;
+
+	list_for_each_entry(cb, &cl->rd_completed, list)
+		if (!fp || fp == cb->file_object)
+			return cb;
+
+	return NULL;
+}
+
+/**
+ * mei_cl_read_cb_flush - free client's read pending and completed cbs
+ *   for a specific file
+ *
+ * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
+ */
+void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp)
+{
+	struct mei_cl_cb *cb, *next;
+
+	list_for_each_entry_safe(cb, next, &cl->rd_completed, list)
+		if (!fp || fp == cb->file_object)
+			mei_io_cb_free(cb);
+
+
+	list_for_each_entry_safe(cb, next, &cl->rd_pending, list)
+		if (!fp || fp == cb->file_object)
+			mei_io_cb_free(cb);
+}
+
+/**
  * mei_cl_flush_queues - flushes queue lists belonging to cl.
  *
  * @cl: host client
+ * @fp: file pointer (matching cb file object), may be NULL
  *
  * Return: 0 on success, -EINVAL if cl or cl->dev is NULL.
  */
-int mei_cl_flush_queues(struct mei_cl *cl)
+int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp)
 {
 	struct mei_device *dev;
 
@@ -474,13 +516,15 @@ int mei_cl_flush_queues(struct mei_cl *cl)
 	dev = cl->dev;
 
 	cl_dbg(dev, cl, "remove list entry belonging to cl\n");
-	mei_io_list_flush(&cl->dev->read_list, cl);
 	mei_io_list_free(&cl->dev->write_list, cl);
 	mei_io_list_free(&cl->dev->write_waiting_list, cl);
 	mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
 	mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
 	mei_io_list_flush(&cl->dev->amthif_cmd_list, cl);
 	mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl);
+
+	mei_cl_read_cb_flush(cl, fp);
+
 	return 0;
 }
 
@@ -497,9 +541,10 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev)
 	init_waitqueue_head(&cl->wait);
 	init_waitqueue_head(&cl->rx_wait);
 	init_waitqueue_head(&cl->tx_wait);
+	INIT_LIST_HEAD(&cl->rd_completed);
+	INIT_LIST_HEAD(&cl->rd_pending);
 	INIT_LIST_HEAD(&cl->link);
 	INIT_LIST_HEAD(&cl->device_link);
-	cl->reading_state = MEI_IDLE;
 	cl->writing_state = MEI_IDLE;
 	cl->dev = dev;
 }
@@ -524,24 +569,6 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev)
 }
 
 /**
- * mei_cl_find_read_cb - find this cl's callback in the read list
- *
- * @cl: host client
- *
- * Return: cb on success, NULL on error
- */
-struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl)
-{
-	struct mei_device *dev = cl->dev;
-	struct mei_cl_cb *cb;
-
-	list_for_each_entry(cb, &dev->read_list.list, list)
-		if (mei_cl_cmp_id(cl, cb->cl))
-			return cb;
-	return NULL;
-}
-
-/**
  * mei_cl_link - allocate host id in the host map
  *
  * @cl: host client
@@ -1006,10 +1033,10 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
 	if (!mei_cl_is_connected(cl))
 		return -ENODEV;
 
-	if (cl->read_cb) {
-		cl_dbg(dev, cl, "read is pending.\n");
+	/* HW currently supports only one pending read */
+	if (!list_empty(&cl->rd_pending))
 		return -EBUSY;
-	}
+
 	me_cl = mei_me_cl_by_uuid_id(dev, &cl->cl_uuid, cl->me_client_id);
 	if (!me_cl) {
 		cl_err(dev, cl, "no such me client %d\n", cl->me_client_id);
@@ -1036,13 +1063,11 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, struct file *fp)
 		if (rets < 0)
 			goto out;
 
-		list_add_tail(&cb->list, &dev->read_list.list);
+		list_add_tail(&cb->list, &cl->rd_pending);
 	} else {
 		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
 
-	cl->read_cb = cb;
-
 out:
 	cl_dbg(dev, cl, "rpm: autosuspend\n");
 	pm_runtime_mark_last_busy(dev->dev);
@@ -1267,9 +1292,8 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
 		if (waitqueue_active(&cl->tx_wait))
 			wake_up_interruptible(&cl->tx_wait);
 
-	} else if (cb->fop_type == MEI_FOP_READ &&
-			MEI_READING == cl->reading_state) {
-		cl->reading_state = MEI_READ_COMPLETE;
+	} else if (cb->fop_type == MEI_FOP_READ) {
+		list_add_tail(&cb->list, &cl->rd_completed);
 		if (waitqueue_active(&cl->rx_wait))
 			wake_up_interruptible(&cl->rx_wait);
 		else
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index c3d0e200a642..eb02f34b2fe0 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -77,11 +77,12 @@ int mei_cl_unlink(struct mei_cl *cl);
 
 struct mei_cl *mei_cl_alloc_linked(struct mei_device *dev, int id);
 
-int mei_cl_flush_queues(struct mei_cl *cl);
-struct mei_cl_cb *mei_cl_find_read_cb(struct mei_cl *cl);
-
+struct mei_cl_cb *mei_cl_read_cb(const struct mei_cl *cl,
+				 const struct file *fp);
+void mei_cl_read_cb_flush(const struct mei_cl *cl, const struct file *fp);
 struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length,
 				  enum mei_cb_file_ops type, struct file *fp);
+int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp);
 
 int mei_cl_flow_ctrl_creds(struct mei_cl *cl);
 
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index 50fc6635fab1..d9cd7e6ee484 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -117,7 +117,7 @@ static ssize_t mei_dbgfs_read_active(struct file *fp, char __user *ubuf,
 		pos += scnprintf(buf + pos, bufsz - pos,
 			"%2d|%2d|%4d|%5d|%2d|%2d|\n",
 			i, cl->me_client_id, cl->host_client_id, cl->state,
-			cl->reading_state, cl->writing_state);
+			!list_empty(&cl->rd_completed), cl->writing_state);
 		i++;
 	}
 out:
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index ad18b0d16f61..97353cf8d9b6 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -397,7 +397,6 @@ void mei_device_init(struct mei_device *dev,
 	dev->dev_state = MEI_DEV_INITIALIZING;
 	dev->reset_count = 0;
 
-	mei_io_list_init(&dev->read_list);
 	mei_io_list_init(&dev->write_list);
 	mei_io_list_init(&dev->write_waiting_list);
 	mei_io_list_init(&dev->ctrl_wr_list);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 1e2f3c774853..3f23629759db 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -68,18 +68,6 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
 	return cl->host_client_id == mei_hdr->host_addr &&
 		cl->me_client_id == mei_hdr->me_addr;
 }
-/**
- * mei_cl_is_reading - checks if the client is in reading state
- *
- * @cl: mei client
- *
- * Return: true if the client is reading
- */
-static bool mei_cl_is_reading(struct mei_cl *cl)
-{
-	return cl->state == MEI_FILE_CONNECTED &&
-		cl->reading_state != MEI_READ_COMPLETE;
-}
 
 /**
  * mei_irq_discard_msg  - discard received message
@@ -116,24 +104,18 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
 	struct mei_cl_cb *cb;
 	unsigned char *buffer = NULL;
 
-	list_for_each_entry(cb, &dev->read_list.list, list) {
-		if (cl == cb->cl)
-			break;
-	}
-
-	if (&cb->list == &dev->read_list.list) {
-		dev_err(dev->dev, "no reader found\n");
+	cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);
+	if (!cb) {
+		cl_err(dev, cl, "pending read cb not found\n");
 		goto out;
 	}
 
-	if (!mei_cl_is_reading(cl)) {
-		cl_err(dev, cl, "cl is not reading state=%d reading state=%d\n",
-			cl->state, cl->reading_state);
+	if (cl->state != MEI_FILE_CONNECTED) {
+		cl_dbg(dev, cl, "not connected\n");
+		cb->status = -ENODEV;
 		goto out;
 	}
 
-	cl->reading_state = MEI_READING;
-
 	if (cb->buf.size == 0 || cb->buf.data == NULL) {
 		cl_err(dev, cl, "response buffer is not allocated.\n");
 		list_move_tail(&cb->list, &complete_list->list);
@@ -163,8 +145,7 @@ int mei_cl_irq_read_msg(struct mei_cl *cl,
 
 	if (mei_hdr->msg_complete) {
 		cb->read_time = jiffies;
-		cl_dbg(dev, cl, "completed read length = %lu\n",
-			cb->buf_idx);
+		cl_dbg(dev, cl, "completed read length = %lu\n", cb->buf_idx);
 		list_move_tail(&cb->list, &complete_list->list);
 	}
 
@@ -281,7 +262,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
 		return ret;
 	}
 
-	list_move_tail(&cb->list, &dev->read_list.list);
+	list_move_tail(&cb->list, &cl->rd_pending);
 
 	return 0;
 }
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index c34853be963f..d80867e0d803 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -112,14 +112,11 @@ static int mei_release(struct inode *inode, struct file *file)
 		cl_dbg(dev, cl, "disconnecting\n");
 		rets = mei_cl_disconnect(cl);
 	}
-	mei_cl_flush_queues(cl);
+	mei_cl_flush_queues(cl, file);
 	cl_dbg(dev, cl, "removing\n");
 
 	mei_cl_unlink(cl);
 
-	mei_io_cb_free(cl->read_cb);
-	cl->read_cb = NULL;
-
 	file->private_data = NULL;
 
 	kfree(cl);
@@ -143,8 +140,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 			size_t length, loff_t *offset)
 {
 	struct mei_cl *cl = file->private_data;
-	struct mei_cl_cb *cb = NULL;
 	struct mei_device *dev;
+	struct mei_cl_cb *cb = NULL;
 	int rets;
 	int err;
 
@@ -171,7 +168,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		goto out;
 	}
 
-	cb = cl->read_cb;
+	cb = mei_cl_read_cb(cl, file);
 	if (cb) {
 		/* read what left */
 		if (cb->buf_idx > *offset)
@@ -196,9 +193,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		goto out;
 	}
 
-	if (MEI_READ_COMPLETE != cl->reading_state &&
-		!waitqueue_active(&cl->rx_wait)) {
-
+	if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
 		if (file->f_flags & O_NONBLOCK) {
 			rets = -EAGAIN;
 			goto out;
@@ -207,7 +202,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		mutex_unlock(&dev->device_lock);
 
 		if (wait_event_interruptible(cl->rx_wait,
-				MEI_READ_COMPLETE == cl->reading_state ||
+				(!list_empty(&cl->rd_completed)) ||
 				mei_cl_is_transitioning(cl))) {
 
 			if (signal_pending(current))
@@ -222,14 +217,8 @@ static ssize_t mei_read(struct file *file, char __user *ubuf,
 		}
 	}
 
-	cb = cl->read_cb;
-
+	cb = mei_cl_read_cb(cl, file);
 	if (!cb) {
-		rets = -ENODEV;
-		goto out;
-	}
-
-	if (cl->reading_state != MEI_READ_COMPLETE) {
 		rets = 0;
 		goto out;
 	}
@@ -266,9 +255,7 @@ copy_buffer:
 
 free:
 	mei_io_cb_free(cb);
-	cl->read_cb = NULL;
 
-	cl->reading_state = MEI_IDLE;
 out:
 	dev_dbg(dev->dev, "end mei read rets= %d\n", rets);
 	mutex_unlock(&dev->device_lock);
@@ -335,8 +322,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 			timeout = write_cb->read_time +
 				mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
 
-			if (time_after(jiffies, timeout) ||
-			    cl->reading_state == MEI_READ_COMPLETE) {
+			if (time_after(jiffies, timeout)) {
 				*offset = 0;
 				mei_io_cb_free(write_cb);
 				write_cb = NULL;
@@ -344,19 +330,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
 		}
 	}
 
-	/* free entry used in read */
-	if (cl->reading_state == MEI_READ_COMPLETE) {
-		*offset = 0;
-		write_cb = mei_cl_find_read_cb(cl);
-		if (write_cb) {
-			mei_io_cb_free(write_cb);
-			write_cb = NULL;
-			cl->read_cb = NULL;
-			cl->reading_state = MEI_IDLE;
-		}
-	} else if (cl->reading_state == MEI_IDLE)
-		*offset = 0;
-
+	*offset = 0;
 	write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
 	if (!write_cb) {
 		rets = -ENOMEM;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 1a0f6e9588b6..f066ecd71939 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -231,9 +231,9 @@ struct mei_cl_cb {
  * @me_client_id: me/fw id
  * @mei_flow_ctrl_creds: transmit flow credentials
  * @timer_count:  watchdog timer for operation completion
- * @reading_state: state of the rx
  * @writing_state: state of the tx
- * @read_cb: current pending reading callback
+ * @rd_pending: pending read credits
+ * @rd_completed: completed read
  *
  * @device: device on the mei client bus
  * @device_link:  link to bus clients
@@ -251,9 +251,9 @@ struct mei_cl {
 	u8 me_client_id;
 	u8 mei_flow_ctrl_creds;
 	u8 timer_count;
-	enum mei_file_transaction_states reading_state;
 	enum mei_file_transaction_states writing_state;
-	struct mei_cl_cb *read_cb;
+	struct list_head rd_pending;
+	struct list_head rd_completed;
 
 	/* MEI CL bus data */
 	struct mei_cl_device *device;
@@ -425,7 +425,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @cdev        : character device
  * @minor       : minor number allocated for device
  *
- * @read_list   : read completion list
  * @write_list  : write pending list
  * @write_waiting_list : write completion list
  * @ctrl_wr_list : pending control write list
@@ -501,7 +500,6 @@ struct mei_device {
 	struct cdev cdev;
 	int minor;
 
-	struct mei_cl_cb read_list;
 	struct mei_cl_cb write_list;
 	struct mei_cl_cb write_waiting_list;
 	struct mei_cl_cb ctrl_wr_list;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [char-misc-next 18/18] mei: bus: call device disable handler prior to disconnection
  2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
                   ` (14 preceding siblings ...)
  2015-02-10  8:39 ` [char-misc-next 17/18] mei: allow read concurrency Tomas Winkler
@ 2015-02-10  8:39 ` Tomas Winkler
  15 siblings, 0 replies; 17+ messages in thread
From: Tomas Winkler @ 2015-02-10  8:39 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

call device's disable handler prior to disconnection
so it can possibly close the communication with fw client
in graceful way

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

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 17ca7e20fb6a..45896f95fed1 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -467,37 +467,34 @@ int mei_cl_disable_device(struct mei_cl_device *device)
 
 	dev = cl->dev;
 
+	if (device->ops && device->ops->disable)
+		device->ops->disable(device);
+
+	device->event_cb = NULL;
+
 	mutex_lock(&dev->device_lock);
 
 	if (cl->state != MEI_FILE_CONNECTED) {
-		mutex_unlock(&dev->device_lock);
 		dev_err(dev->dev, "Already disconnected");
-
-		return 0;
+		err = 0;
+		goto out;
 	}
 
 	cl->state = MEI_FILE_DISCONNECTING;
 
 	err = mei_cl_disconnect(cl);
 	if (err < 0) {
-		mutex_unlock(&dev->device_lock);
-		dev_err(dev->dev,
-			"Could not disconnect from the ME client");
-
-		return err;
+		dev_err(dev->dev, "Could not disconnect from the ME client");
+		goto out;
 	}
 
 	/* Flush queues and remove any pending read */
 	mei_cl_flush_queues(cl, NULL);
 
-	device->event_cb = NULL;
-
+out:
 	mutex_unlock(&dev->device_lock);
+	return err;
 
-	if (!device->ops || !device->ops->disable)
-		return 0;
-
-	return device->ops->disable(device);
 }
 EXPORT_SYMBOL_GPL(mei_cl_disable_device);
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2015-02-10  8:45 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-02-10  8:39 [char-misc-next 02/18] mei: revamp me clients list handling Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 03/18] mei: me: use io register wrappers consistently Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 04/18] mei: me: add io register tracing Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 05/18] mei: me: change power gating function name conventions Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 06/18] mei: fix function names and format in KDoc Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 07/18] mei: fix device reset on mei_cl_irq_read_msg allocation failure Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 08/18] mei: iamthif: fix device reset on mei_amthif_irq_read_msg Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 09/18] mei: iamthif: remove useless iamthif_ioctl variable Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 10/18] mei: iamthif: send flow control as a regular client Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 11/18] mei: iamthif: use client write functions Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 12/18] mei: iamthif: use regular client read functions Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 13/18] mei: use only one buffer in callback Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 14/18] mei: always initialize the callback with the intended operation type Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 15/18] mei: add mei_cl_alloc_linked function Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 16/18] mei: simplify io callback disposal Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 17/18] mei: allow read concurrency Tomas Winkler
2015-02-10  8:39 ` [char-misc-next 18/18] mei: bus: call device disable handler prior to disconnection Tomas Winkler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®