linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [char-misc-next 1/3] mei: drop global me_client_index
@ 2016-04-17 16:16 Tomas Winkler
  2016-04-17 16:16 ` [char-misc-next 2/3] mei: fix NULL dereferencing during FW initiated disconnection Tomas Winkler
  2016-04-17 16:16 ` [char-misc-next 3/3] mei: amthif: discard not read messages Tomas Winkler
  0 siblings, 2 replies; 3+ messages in thread
From: Tomas Winkler @ 2016-04-17 16:16 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alexander Usyskin, linux-kernel, Tomas Winkler

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

Global me_client_index is used only during the enumeration process and
can be effectively replaced by me_addr data from the last enumeration
response as we always enumerate clients in the increasing order.

Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/hbm.c     | 23 ++++++++---------------
 drivers/misc/mei/mei_dev.h |  2 --
 2 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 5e305d2605f3..5eaa4638e824 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -113,8 +113,6 @@ void mei_hbm_idle(struct mei_device *dev)
  */
 void mei_hbm_reset(struct mei_device *dev)
 {
-	dev->me_client_index = 0;
-
 	mei_me_cl_rm_all(dev);
 
 	mei_hbm_idle(dev);
@@ -530,24 +528,22 @@ static void mei_hbm_cl_notify(struct mei_device *dev,
  * mei_hbm_prop_req - request property for a single client
  *
  * @dev: the device structure
+ * @start_idx: client index to start search
  *
  * Return: 0 on success and < 0 on failure
  */
-
-static int mei_hbm_prop_req(struct mei_device *dev)
+static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx)
 {
-
 	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	struct hbm_props_request *prop_req;
 	const size_t len = sizeof(struct hbm_props_request);
-	unsigned long next_client_index;
+	unsigned long addr;
 	int ret;
 
-	next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX,
-					  dev->me_client_index);
+	addr = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, start_idx);
 
 	/* We got all client properties */
-	if (next_client_index == MEI_CLIENTS_MAX) {
+	if (addr == MEI_CLIENTS_MAX) {
 		dev->hbm_state = MEI_HBM_STARTED;
 		mei_host_client_init(dev);
 
@@ -560,7 +556,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
 	memset(prop_req, 0, sizeof(struct hbm_props_request));
 
 	prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
-	prop_req->me_addr = next_client_index;
+	prop_req->me_addr = addr;
 
 	ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 	if (ret) {
@@ -570,7 +566,6 @@ static int mei_hbm_prop_req(struct mei_device *dev)
 	}
 
 	dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
-	dev->me_client_index = next_client_index;
 
 	return 0;
 }
@@ -1152,10 +1147,8 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 
 		mei_hbm_me_cl_add(dev, props_res);
 
-		dev->me_client_index++;
-
 		/* request property for the next client */
-		if (mei_hbm_prop_req(dev))
+		if (mei_hbm_prop_req(dev, props_res->me_addr + 1))
 			return -EIO;
 
 		break;
@@ -1181,7 +1174,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 		dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
 
 		/* first property request */
-		if (mei_hbm_prop_req(dev))
+		if (mei_hbm_prop_req(dev, 0))
 			return -EIO;
 
 		break;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index db78e6d99456..87586bbc4a41 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -396,7 +396,6 @@ const char *mei_pg_state_str(enum mei_pg_state state);
  * @me_clients  : list of FW clients
  * @me_clients_map : FW clients bit map
  * @host_clients_map : host clients id pool
- * @me_client_index : last FW client index in enumeration
  *
  * @allow_fixed_address: allow user space to connect a fixed client
  * @override_fixed_address: force allow fixed address behavior
@@ -486,7 +485,6 @@ struct mei_device {
 	struct list_head me_clients;
 	DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
 	DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
-	unsigned long me_client_index;
 
 	bool allow_fixed_address;
 	bool override_fixed_address;
-- 
2.5.5

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

* [char-misc-next 2/3] mei: fix NULL dereferencing during FW initiated disconnection
  2016-04-17 16:16 [char-misc-next 1/3] mei: drop global me_client_index Tomas Winkler
@ 2016-04-17 16:16 ` Tomas Winkler
  2016-04-17 16:16 ` [char-misc-next 3/3] mei: amthif: discard not read messages Tomas Winkler
  1 sibling, 0 replies; 3+ messages in thread
From: Tomas Winkler @ 2016-04-17 16:16 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alexander Usyskin, linux-kernel, stable, Tomas Winkler

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

In the case when disconnection is initiated from the FW
the driver is flushing items from the write control list while
iterating over it:

mei_irq_write_handler()
    list_for_each_entry_safe(ctrl_wr_list)         <-- outer loop
         mei_cl_irq_disconnect_rsp()
             mei_cl_set_disconnected()
                 mei_io_list_flush(ctrl_wr_list)   <-- destorying list

We move the list flushing to the completion routine.

Cc: <stable@vger.kernel.org> #4.2+
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/client.c    | 4 ++++
 drivers/misc/mei/hbm.c       | 3 +--
 drivers/misc/mei/interrupt.c | 5 +----
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index bab17e4197b6..09f5280fa021 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1767,6 +1767,10 @@ void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb)
 			wake_up(&cl->wait);
 
 		break;
+	case MEI_FOP_DISCONNECT_RSP:
+		mei_io_cb_free(cb);
+		mei_cl_set_disconnected(cl);
+		break;
 	default:
 		BUG_ON(0);
 	}
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 5eaa4638e824..5aa606c8a827 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -877,8 +877,7 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 		cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT_RSP, NULL);
 		if (!cb)
 			return -ENOMEM;
-		cl_dbg(dev, cl, "add disconnect response as first\n");
-		list_add(&cb->list, &dev->ctrl_wr_list.list);
+		list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
 	}
 	return 0;
 }
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 1e5cb1f704f8..704dc6caad6d 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -194,10 +194,7 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
 		return -EMSGSIZE;
 
 	ret = mei_hbm_cl_disconnect_rsp(dev, cl);
-	mei_cl_set_disconnected(cl);
-	mei_io_cb_free(cb);
-	mei_me_cl_put(cl->me_cl);
-	cl->me_cl = NULL;
+	list_move_tail(&cb->list, &cmpl_list->list);
 
 	return ret;
 }
-- 
2.5.5

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

* [char-misc-next 3/3] mei: amthif: discard not read messages
  2016-04-17 16:16 [char-misc-next 1/3] mei: drop global me_client_index Tomas Winkler
  2016-04-17 16:16 ` [char-misc-next 2/3] mei: fix NULL dereferencing during FW initiated disconnection Tomas Winkler
@ 2016-04-17 16:16 ` Tomas Winkler
  1 sibling, 0 replies; 3+ messages in thread
From: Tomas Winkler @ 2016-04-17 16:16 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alexander Usyskin, linux-kernel, stable, Tomas Winkler

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

When a message is received and amthif client is not in reading state
the message is ignored and left dangling in the queue. This may happen
after one of the amthif host connections is closed w/o completing the
reading. Another client will pick up a wrong message on next read
attempt which will lead to link reset.
To prevent this the driver has to properly discard the message when
amthif client is not in reading state.

Cc: <stable@vger.kernel.org> #4.2+
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 4 +++-
 drivers/misc/mei/interrupt.c | 1 -
 drivers/misc/mei/mei_dev.h   | 2 ++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 194360a5f782..a039a5df6f21 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -380,8 +380,10 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl,
 
 	dev = cl->dev;
 
-	if (dev->iamthif_state != MEI_IAMTHIF_READING)
+	if (dev->iamthif_state != MEI_IAMTHIF_READING) {
+		mei_irq_discard_msg(dev, mei_hdr);
 		return 0;
+	}
 
 	ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
 	if (ret)
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 704dc6caad6d..3831a7ba2531 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -76,7 +76,6 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
  * @dev: mei device
  * @hdr: message header
  */
-static inline
 void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
 {
 	/*
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 87586bbc4a41..c9e01021eadf 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -702,6 +702,8 @@ bool mei_hbuf_acquire(struct mei_device *dev);
 
 bool mei_write_is_idle(struct mei_device *dev);
 
+void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr);
+
 #if IS_ENABLED(CONFIG_DEBUG_FS)
 int mei_dbgfs_register(struct mei_device *dev, const char *name);
 void mei_dbgfs_deregister(struct mei_device *dev);
-- 
2.5.5

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

end of thread, other threads:[~2016-04-17  9:17 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-17 16:16 [char-misc-next 1/3] mei: drop global me_client_index Tomas Winkler
2016-04-17 16:16 ` [char-misc-next 2/3] mei: fix NULL dereferencing during FW initiated disconnection Tomas Winkler
2016-04-17 16:16 ` [char-misc-next 3/3] mei: amthif: discard not read messages Tomas Winkler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).