All of lore.kernel.org
 help / color / mirror / Atom feed
* [char-misc-next 0/4] mei: fix txe write issue
@ 2014-02-12 19:41 Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 1/4] mei: rename MEI_FOP_IOCTL to MEI_FOP_CONNECT Tomas Winkler
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Tomas Winkler @ 2014-02-12 19:41 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

This series fixes issue on the TXE hardware
when parallel clients would override each others
writes to host.

In order to avoid conflicts please apply after
mei: set client's read_cb to NULL when flow control fails
https://lkml.org/lkml/2014/2/12/389


Tomas Winkler (4):
  mei: rename MEI_FOP_IOCTL to MEI_FOP_CONNECT
  mei: get rid of ext_msg
  mei: add mei_hbuf_acquire wrapper
  mei: revamp writing slot counting

 drivers/misc/mei/amthif.c    |  28 ++++------
 drivers/misc/mei/client.c    |  77 +++++++++++++++-----------
 drivers/misc/mei/client.h    |   4 +-
 drivers/misc/mei/hbm.c       |  66 +++++++++++++++-------
 drivers/misc/mei/hbm.h       |   1 +
 drivers/misc/mei/hw-me.c     |   7 +--
 drivers/misc/mei/hw-txe.c    |  38 ++++++-------
 drivers/misc/mei/hw-txe.h    |   1 +
 drivers/misc/mei/init.c      |   1 -
 drivers/misc/mei/interrupt.c | 127 ++++++++++++++++++++++++-------------------
 drivers/misc/mei/mei_dev.h   |  26 ++++-----
 drivers/misc/mei/wd.c        |  14 ++---
 12 files changed, 220 insertions(+), 170 deletions(-)

-- 
1.8.5.3


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

* [char-misc-next 1/4] mei: rename MEI_FOP_IOCTL to MEI_FOP_CONNECT
  2014-02-12 19:41 [char-misc-next 0/4] mei: fix txe write issue Tomas Winkler
@ 2014-02-12 19:41 ` Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 2/4] mei: get rid of ext_msg Tomas Winkler
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Tomas Winkler @ 2014-02-12 19:41 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

This operation actually only support connection
and not a generic ioctl

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    |  2 +-
 drivers/misc/mei/client.c    |  2 +-
 drivers/misc/mei/hbm.c       |  2 +-
 drivers/misc/mei/interrupt.c | 14 +++++++-------
 drivers/misc/mei/mei_dev.h   | 12 ++++++------
 5 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index d9f14ef..f88cb26 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -364,7 +364,7 @@ int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret)
 		return ret;
 
-	cb->fop_type = MEI_FOP_IOCTL;
+	cb->fop_type = MEI_FOP_WRITE;
 
 	if (!list_empty(&dev->amthif_cmd_list.list) ||
 	    dev->iamthif_state != MEI_IAMTHIF_IDLE) {
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 26da5e1..270ef15 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -505,7 +505,7 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 		goto out;
 	}
 
-	cb->fop_type = MEI_FOP_IOCTL;
+	cb->fop_type = MEI_FOP_CONNECT;
 
 	if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) {
 		dev->hbuf_is_ready = false;
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 0aaf2c5..0c77025 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -507,7 +507,7 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
 			list_del(&pos->list);
 			return;
 		}
-		if (pos->fop_type == MEI_FOP_IOCTL) {
+		if (pos->fop_type == MEI_FOP_CONNECT) {
 			if (is_treat_specially_client(cl, rs)) {
 				list_del(&pos->list);
 				cl->status = 0;
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index f0fbb51..3f0b0b9 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -244,8 +244,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 
 /**
- * mei_cl_irq_ioctl - processes client ioctl related operation from the
- *	interrupt thread context -   send connection request
+ * mei_cl_irq_connect - send connect request in irq_thread context
  *
  * @cl: client
  * @cb: callback block.
@@ -254,7 +253,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
  *
  * returns 0, OK; otherwise, error.
  */
-static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
+static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
 			   s32 *slots, struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
@@ -263,6 +262,9 @@ static int mei_cl_irq_ioctl(struct mei_cl *cl, struct mei_cl_cb *cb,
 	u32 msg_slots =
 		mei_data2slots(sizeof(struct hbm_client_connect_request));
 
+	if (mei_cl_is_other_connecting(cl))
+		return 0;
+
 	if (*slots < msg_slots) {
 		/* return the cancel routine */
 		list_del(&cb->list);
@@ -496,11 +498,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 				return ret;
 
 			break;
-		case MEI_FOP_IOCTL:
+		case MEI_FOP_CONNECT:
 			/* connect message */
-			if (mei_cl_is_other_connecting(cl))
-				continue;
-			ret = mei_cl_irq_ioctl(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_connect(cl, cb, &slots, cmpl_list);
 			if (ret)
 				return ret;
 
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index f7de95b..f2c949e 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -130,16 +130,16 @@ enum mei_wd_states {
 
 /**
  * enum mei_cb_file_ops  - file operation associated with the callback
- * @MEI_FOP_READ   - read
- * @MEI_FOP_WRITE  - write
- * @MEI_FOP_IOCTL  - ioctl
- * @MEI_FOP_OPEN   - open
- * @MEI_FOP_CLOSE  - close
+ * @MEI_FOP_READ      - read
+ * @MEI_FOP_WRITE     - write
+ * @MEI_FOP_CONNECT   - connect
+ * @MEI_FOP_OPEN      - open
+ * @MEI_FOP_CLOSE     - close
  */
 enum mei_cb_file_ops {
 	MEI_FOP_READ = 0,
 	MEI_FOP_WRITE,
-	MEI_FOP_IOCTL,
+	MEI_FOP_CONNECT,
 	MEI_FOP_OPEN,
 	MEI_FOP_CLOSE
 };
-- 
1.8.5.3


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

* [char-misc-next 2/4] mei: get rid of ext_msg
  2014-02-12 19:41 [char-misc-next 0/4] mei: fix txe write issue Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 1/4] mei: rename MEI_FOP_IOCTL to MEI_FOP_CONNECT Tomas Winkler
@ 2014-02-12 19:41 ` Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 4/4] mei: revamp writing slot counting Tomas Winkler
  3 siblings, 0 replies; 8+ messages in thread
From: Tomas Winkler @ 2014-02-12 19:41 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Use more standard message writing for
oob data.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
Note This patch causes 'over 80 characters' checkpatch waring,
but can be ignored as this is fixed in consequent patch

 drivers/misc/mei/hbm.c       | 64 +++++++++++++++++++++++++++++++-------------
 drivers/misc/mei/hbm.h       |  1 +
 drivers/misc/mei/hw-me.c     |  3 ---
 drivers/misc/mei/init.c      |  1 -
 drivers/misc/mei/interrupt.c | 47 +++++++++++++++++++++++++++-----
 drivers/misc/mei/mei_dev.h   |  8 ++----
 6 files changed, 88 insertions(+), 36 deletions(-)

diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index 0c77025..d3fcb23 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -283,17 +283,18 @@ static int mei_hbm_prop_req(struct mei_device *dev)
 }
 
 /**
- * mei_hbm_stop_req_prepare - prepare stop request message
+ * mei_hbm_stop_req - send stop request message
  *
  * @dev - mei device
- * @mei_hdr - mei message header
- * @data - hbm message body buffer
+ * @cl: client info
+ *
+ * This function returns -EIO on write failure
  */
-static void mei_hbm_stop_req_prepare(struct mei_device *dev,
-		struct mei_msg_hdr *mei_hdr, unsigned char *data)
+static int mei_hbm_stop_req(struct mei_device *dev)
 {
+	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
 	struct hbm_host_stop_request *req =
-			(struct hbm_host_stop_request *)data;
+			(struct hbm_host_stop_request *)dev->wr_msg.data;
 	const size_t len = sizeof(struct hbm_host_stop_request);
 
 	mei_hbm_hdr(mei_hdr, len);
@@ -301,6 +302,8 @@ static void mei_hbm_stop_req_prepare(struct mei_device *dev,
 	memset(req, 0, len);
 	req->hbm_cmd = HOST_STOP_REQ_CMD;
 	req->reason = DRIVER_STOP_REQUEST;
+
+	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
 }
 
 /**
@@ -405,6 +408,25 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl)
 }
 
 /**
+ * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW
+ *
+ * @dev: the device structure
+ * @cl: a client to disconnect from
+ *
+ * This function returns -EIO on write failure
+ */
+int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl)
+{
+	struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+	const size_t len = sizeof(struct hbm_client_connect_response);
+
+	mei_hbm_hdr(mei_hdr, len);
+	mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, dev->wr_msg.data, len);
+
+	return mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+}
+
+/**
  * mei_hbm_cl_disconnect_res - disconnect response from ME
  *
  * @dev: the device structure
@@ -525,12 +547,14 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev,
  *
  * @dev: the device structure.
  * @disconnect_req: disconnect request bus message from the me
+ *
+ * returns -ENOMEM on allocation failure
  */
-static void mei_hbm_fw_disconnect_req(struct mei_device *dev,
+static int mei_hbm_fw_disconnect_req(struct mei_device *dev,
 		struct hbm_client_connect_request *disconnect_req)
 {
 	struct mei_cl *cl, *next;
-	const size_t len = sizeof(struct hbm_client_connect_response);
+	struct mei_cl_cb *cb;
 
 	list_for_each_entry_safe(cl, next, &dev->file_list, link) {
 		if (mei_hbm_cl_addr_equal(cl, disconnect_req)) {
@@ -544,13 +568,17 @@ static void mei_hbm_fw_disconnect_req(struct mei_device *dev,
 			else if (cl == &dev->iamthif_cl)
 				dev->iamthif_timer = 0;
 
-			/* prepare disconnect response */
-			mei_hbm_hdr(&dev->wr_ext_msg.hdr, len);
-			mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD,
-					 dev->wr_ext_msg.data, len);
+			cb = mei_io_cb_init(cl, 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);
+
 			break;
 		}
 	}
+	return 0;
 }
 
 
@@ -629,10 +657,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 			dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n");
 
 			dev->hbm_state = MEI_HBM_STOPPED;
-			mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
-						dev->wr_msg.data);
-			if (mei_write_message(dev, &dev->wr_msg.hdr,
-					dev->wr_msg.data)) {
+			if (mei_hbm_stop_req(dev)) {
 				dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
 				return -EIO;
 			}
@@ -778,10 +803,11 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
 
 	case ME_STOP_REQ_CMD:
 		dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n");
-
 		dev->hbm_state = MEI_HBM_STOPPED;
-		mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
-					dev->wr_ext_msg.data);
+		if (mei_hbm_stop_req(dev)) {
+			dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n");
+			return -EIO;
+		}
 		break;
 	default:
 		BUG();
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h
index 5f92188..20e8782 100644
--- a/drivers/misc/mei/hbm.h
+++ b/drivers/misc/mei/hbm.h
@@ -54,6 +54,7 @@ int mei_hbm_start_req(struct mei_device *dev);
 int mei_hbm_start_wait(struct mei_device *dev);
 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl);
+int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl);
 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
 bool mei_hbm_version_is_supported(struct mei_device *dev);
 
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 54286f3..847c9e5 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -505,9 +505,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 	/* check slots available for reading */
 	slots = mei_count_full_read_slots(dev);
 	while (slots > 0) {
-		/* we have urgent data to send so break the read */
-		if (dev->wr_ext_msg.hdr.length)
-			break;
 		dev_dbg(&dev->pdev->dev, "slots to read = %08x\n", slots);
 		rets = mei_irq_read_handler(dev, &complete_list, &slots);
 		if (rets && dev->dev_state != MEI_DEV_RESETTING) {
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 95a7180..214dcef 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -116,7 +116,6 @@ int mei_reset(struct mei_device *dev)
 		mei_cl_unlink(&dev->wd_cl);
 		mei_cl_unlink(&dev->iamthif_cl);
 		mei_amthif_reset_params(dev);
-		memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg));
 	}
 
 
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 3f0b0b9..75ff409 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -161,6 +161,41 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
 }
 
 /**
+ * mei_cl_irq_disconnect_rsp - send disconnection response message
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @slots: free slots.
+ * @cmpl_list: complete list.
+ *
+ * returns 0, OK; otherwise, error.
+ */
+static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
+			s32 *slots, struct mei_cl_cb *cmpl_list)
+{
+	struct mei_device *dev = cl->dev;
+	int ret;
+
+	u32 msg_slots =
+		mei_data2slots(sizeof(struct hbm_client_connect_response));
+
+	if (*slots < msg_slots)
+		return -EMSGSIZE;
+
+	*slots -= msg_slots;
+
+	ret = mei_hbm_cl_disconnect_rsp(dev, cl);
+
+	cl->state = MEI_FILE_DISCONNECTED;
+	cl->status = 0;
+	mei_io_cb_free(cb);
+
+	return ret;
+}
+
+
+
+/**
  * mei_cl_irq_close - processes close related operation from
  *	interrupt thread context - send disconnect request
  *
@@ -452,12 +487,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		wake_up_interruptible(&dev->wait_stop_wd);
 	}
 
-	if (dev->wr_ext_msg.hdr.length) {
-		mei_write_message(dev, &dev->wr_ext_msg.hdr,
-				dev->wr_ext_msg.data);
-		slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
-		dev->wr_ext_msg.hdr.length = 0;
-	}
 	if (dev->dev_state == MEI_DEV_ENABLED) {
 		if (dev->wd_pending &&
 		    mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
@@ -505,7 +534,11 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 				return ret;
 
 			break;
-
+		case MEI_FOP_DISCONNECT_RSP:
+			/* send disconnect resp */
+			ret = mei_cl_irq_disconnect_rsp(cl, cb, &slots, cmpl_list);
+			if (ret)
+				return ret;
 		default:
 			BUG();
 		}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index f2c949e..21e5249 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -133,6 +133,7 @@ enum mei_wd_states {
  * @MEI_FOP_READ      - read
  * @MEI_FOP_WRITE     - write
  * @MEI_FOP_CONNECT   - connect
+ * @MEI_FOP_DISCONNECT_RSP - disconnect response
  * @MEI_FOP_OPEN      - open
  * @MEI_FOP_CLOSE     - close
  */
@@ -140,6 +141,7 @@ enum mei_cb_file_ops {
 	MEI_FOP_READ = 0,
 	MEI_FOP_WRITE,
 	MEI_FOP_CONNECT,
+	MEI_FOP_DISCONNECT_RSP,
 	MEI_FOP_OPEN,
 	MEI_FOP_CLOSE
 };
@@ -339,7 +341,6 @@ struct mei_cl_device {
  * @hbuf_depth - depth of hardware host/write buffer is slots
  * @hbuf_is_ready - query if the host host/write buffer is ready
  * @wr_msg - the buffer for hbm control messages
- * @wr_ext_msg - the buffer for hbm control responses (set in read cycle)
  */
 struct mei_device {
 	struct pci_dev *pdev;	/* pointer to pci device struct */
@@ -394,11 +395,6 @@ struct mei_device {
 		unsigned char data[128];
 	} wr_msg;
 
-	struct {
-		struct mei_msg_hdr hdr;
-		unsigned char data[4];	/* All HBM messages are 4 bytes */
-	} wr_ext_msg;		/* for control responses */
-
 	struct hbm_version version;
 
 	struct mei_me_client *me_clients; /* Note: memory has to be allocated */
-- 
1.8.5.3


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

* [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper
  2014-02-12 19:41 [char-misc-next 0/4] mei: fix txe write issue Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 1/4] mei: rename MEI_FOP_IOCTL to MEI_FOP_CONNECT Tomas Winkler
  2014-02-12 19:41 ` [char-misc-next 2/4] mei: get rid of ext_msg Tomas Winkler
@ 2014-02-12 19:41 ` Tomas Winkler
  2014-02-14 19:13   ` Greg KH
  2014-02-12 19:41 ` [char-misc-next 4/4] mei: revamp writing slot counting Tomas Winkler
  3 siblings, 1 reply; 8+ messages in thread
From: Tomas Winkler @ 2014-02-12 19:41 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

A client has to acquire host buffer
before writing, we add lock like wrapper
to replace the code snippet

if (dev->hbuf_is_ready)
        dev->hbuf_is_ready = false;

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    |  7 +-----
 drivers/misc/mei/client.c    | 56 ++++++++++++++++++++++++++++----------------
 drivers/misc/mei/hw-me.c     |  2 ++
 drivers/misc/mei/hw-txe.c    | 17 +++++---------
 drivers/misc/mei/interrupt.c |  6 ++---
 drivers/misc/mei/mei_dev.h   |  2 ++
 drivers/misc/mei/wd.c        | 14 +++++------
 7 files changed, 57 insertions(+), 47 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index f88cb26..71af677 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -301,9 +301,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 	if (ret < 0)
 		return ret;
 
-	if (ret && dev->hbuf_is_ready) {
+	if (ret && mei_hbuf_acquire(dev)) {
 		ret = 0;
-		dev->hbuf_is_ready = false;
 		if (cb->request_buffer.size > mei_hbuf_max_len(dev)) {
 			mei_hdr.length = mei_hbuf_max_len(dev);
 			mei_hdr.msg_complete = 0;
@@ -335,10 +334,6 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb)
 			list_add_tail(&cb->list, &dev->write_list.list);
 		}
 	} else {
-		if (!dev->hbuf_is_ready)
-			dev_dbg(&dev->pdev->dev, "host buffer is not empty");
-
-		dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n");
 		list_add_tail(&cb->list, &dev->write_list.list);
 	}
 	return 0;
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 270ef15..faa75bd 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -375,6 +375,23 @@ void mei_host_client_init(struct work_struct *work)
 	mutex_unlock(&dev->device_lock);
 }
 
+/**
+ * mei_hbuf_acquire: try to acquire host buffer
+ *
+ * @dev: the device structure
+ * returns true if host buffer was acquired
+ */
+bool mei_hbuf_acquire(struct mei_device *dev)
+{
+	if (!dev->hbuf_is_ready) {
+		dev_dbg(&dev->pdev->dev, "hbuf is not ready\n");
+		return false;
+	}
+
+	dev->hbuf_is_ready = false;
+
+	return true;
+}
 
 /**
  * mei_cl_disconnect - disconnect host client from the me one
@@ -406,8 +423,7 @@ int mei_cl_disconnect(struct mei_cl *cl)
 		return -ENOMEM;
 
 	cb->fop_type = MEI_FOP_CLOSE;
-	if (dev->hbuf_is_ready) {
-		dev->hbuf_is_ready = false;
+	if (mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_disconnect_req(dev, cl)) {
 			rets = -ENODEV;
 			cl_err(dev, cl, "failed to disconnect.\n");
@@ -507,9 +523,8 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file)
 
 	cb->fop_type = MEI_FOP_CONNECT;
 
-	if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) {
-		dev->hbuf_is_ready = false;
-
+	/* run hbuf acquire last so we don't have to undo */
+	if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_connect_req(dev, cl)) {
 			rets = -ENODEV;
 			goto out;
@@ -666,8 +681,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
 		goto err;
 
 	cb->fop_type = MEI_FOP_READ;
-	if (dev->hbuf_is_ready) {
-		dev->hbuf_is_ready = false;
+	if (mei_hbuf_acquire(dev)) {
 		if (mei_hbm_cl_flow_control_req(dev, cl)) {
 			cl_err(dev, cl, "flow control send failed\n");
 			rets = -ENODEV;
@@ -802,21 +816,29 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 
 
 	cb->fop_type = MEI_FOP_WRITE;
+	cb->buf_idx = 0;
+	cl->writing_state = MEI_IDLE;
+
+	mei_hdr.host_addr = cl->host_client_id;
+	mei_hdr.me_addr = cl->me_client_id;
+	mei_hdr.reserved = 0;
+	mei_hdr.msg_complete = 0;
+	mei_hdr.internal = cb->internal;
 
 	rets = mei_cl_flow_ctrl_creds(cl);
 	if (rets < 0)
 		goto err;
 
-	/* Host buffer is not ready, we queue the request */
-	if (rets == 0 || !dev->hbuf_is_ready) {
-		cb->buf_idx = 0;
-		/* unseting complete will enqueue the cb for write */
-		mei_hdr.msg_complete = 0;
+	if (rets == 0) {
+		cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
+		rets = buf->size;
+		goto out;
+	}
+	if (!mei_hbuf_acquire(dev)) {
+		cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
 		rets = buf->size;
 		goto out;
 	}
-
-	dev->hbuf_is_ready = false;
 
 	/* Check for a maximum length */
 	if (buf->size > mei_hbuf_max_len(dev)) {
@@ -827,12 +849,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
 		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 = cb->internal;
-
-
 	rets = mei_write_message(dev, &mei_hdr, buf->data);
 	if (rets)
 		goto err;
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 847c9e5..b0c42d6 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -513,6 +513,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
 		}
 	}
 
+	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
+
 	rets = mei_irq_write_handler(dev, &complete_list);
 
 	dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index 19579e5..ab0442e 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -604,7 +604,6 @@ static int mei_txe_write(struct mei_device *dev,
 		mei_txe_input_payload_write(dev, i + 1, reg);
 	}
 
-	dev->hbuf_is_ready = false;
 	/* Set Input-Doorbell */
 	mei_txe_input_doorbell_set(hw);
 
@@ -982,20 +981,16 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 		dev->hbuf_is_ready = true;
 
 	if (hw->aliveness && dev->hbuf_is_ready) {
-		/* if SeC did not complete reading the written data by host */
-		if (!mei_txe_is_input_ready(dev)) {
-			dev_dbg(&dev->pdev->dev, "got Input Ready Int, but SEC_IPC_INPUT_STATUS_RDY is 0.\n");
-			goto end;
-		}
 
+		/* get the real register value */
+		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 		rets = mei_irq_write_handler(dev, &complete_list);
-		if (rets)
-			dev_err(&dev->pdev->dev,
-				"mei_irq_write_handler ret = %d.\n", rets);
+		if (rets && rets != -EMSGSIZE)
+			dev_err(&dev->pdev->dev, "mei_irq_write_handler ret = %d.\n",
+				rets);
+		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 	}
 
-
-
 	mei_irq_compl_handler(dev, &complete_list);
 
 end:
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 75ff409..8f8ab08 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -446,10 +446,10 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 	s32 slots;
 	int ret;
 
-	if (!mei_hbuf_is_ready(dev)) {
-		dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
+
+	if (!mei_hbuf_acquire(dev))
 		return 0;
-	}
+
 	slots = mei_hbuf_empty_slots(dev);
 	if (slots <= 0)
 		return -EMSGSIZE;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 21e5249..c77b747 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -629,6 +629,8 @@ static inline int mei_count_full_read_slots(struct mei_device *dev)
 	return dev->ops->rdbuf_full_slots(dev);
 }
 
+bool mei_hbuf_acquire(struct mei_device *dev);
+
 #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);
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
index f70945e..a769fb1 100644
--- a/drivers/misc/mei/wd.c
+++ b/drivers/misc/mei/wd.c
@@ -153,9 +153,8 @@ int mei_wd_stop(struct mei_device *dev)
 	if (ret < 0)
 		goto out;
 
-	if (ret && dev->hbuf_is_ready) {
+	if (ret && mei_hbuf_acquire(dev)) {
 		ret = 0;
-		dev->hbuf_is_ready = false;
 
 		if (!mei_wd_send(dev)) {
 			ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl);
@@ -260,8 +259,8 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
  */
 static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 {
-	int ret = 0;
 	struct mei_device *dev;
+	int ret;
 
 	dev = watchdog_get_drvdata(wd_dev);
 	if (!dev)
@@ -277,10 +276,12 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 
 	dev->wd_state = MEI_WD_RUNNING;
 
+	ret = mei_cl_flow_ctrl_creds(&dev->wd_cl);
+	if (ret < 0)
+		goto end;
 	/* Check if we can send the ping to HW*/
-	if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
+	if (ret && mei_hbuf_acquire(dev)) {
 
-		dev->hbuf_is_ready = false;
 		dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
 
 		if (mei_wd_send(dev)) {
@@ -290,8 +291,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
 		}
 
 		if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) {
-			dev_err(&dev->pdev->dev,
-				"wd: mei_cl_flow_ctrl_reduce() failed.\n");
+			dev_err(&dev->pdev->dev, "wd: mei_cl_flow_ctrl_reduce() failed.\n");
 			ret = -EIO;
 			goto end;
 		}
-- 
1.8.5.3


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

* [char-misc-next 4/4] mei: revamp writing slot counting
  2014-02-12 19:41 [char-misc-next 0/4] mei: fix txe write issue Tomas Winkler
                   ` (2 preceding siblings ...)
  2014-02-12 19:41 ` [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper Tomas Winkler
@ 2014-02-12 19:41 ` Tomas Winkler
  3 siblings, 0 replies; 8+ messages in thread
From: Tomas Winkler @ 2014-02-12 19:41 UTC (permalink / raw)
  To: gregkh; +Cc: arnd, linux-kernel, Tomas Winkler

Since txe use doorbell and not circular buffer
we have to cheat in write slot counting, txe always consume all the
slots upon write. In order for it to work we need to track
slots using mei_hbuf_empty_slots() instead of tracking it in mei layer

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
 drivers/misc/mei/amthif.c    | 19 ++++++-----
 drivers/misc/mei/client.c    | 19 +++++------
 drivers/misc/mei/client.h    |  4 +--
 drivers/misc/mei/hw-me.c     |  2 +-
 drivers/misc/mei/hw-txe.c    | 21 +++++++-----
 drivers/misc/mei/hw-txe.h    |  1 +
 drivers/misc/mei/interrupt.c | 78 +++++++++++++++++---------------------------
 drivers/misc/mei/mei_dev.h   |  4 +--
 8 files changed, 68 insertions(+), 80 deletions(-)

diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 71af677..b8dfc61 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -441,23 +441,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
 
 
 /**
- * mei_amthif_irq_write_completed - processes completed iamthif operation.
+ * mei_amthif_irq_write - write iamthif command in irq thread context.
  *
  * @dev: the device structure.
- * @slots: free slots.
  * @cb_pos: callback block.
  * @cl: private data of the file object.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
-int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				  s32 *slots, struct mei_cl_cb *cmpl_list)
+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);
@@ -474,13 +474,15 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 	mei_hdr.reserved = 0;
 	mei_hdr.internal = 0;
 
-	if (*slots >= msg_slots) {
+	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);
+	} 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 {
@@ -490,7 +492,6 @@ int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 
 	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT,  MEI_HDR_PRM(&mei_hdr));
 
-	*slots -=  msg_slots;
 	rets = mei_write_message(dev, &mei_hdr,
 			dev->iamthif_msg_buf + dev->iamthif_msg_buf_index);
 	if (rets) {
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index faa75bd..ce8ba03 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -701,27 +701,26 @@ err:
 }
 
 /**
- * mei_cl_irq_write_complete - write a message to device
+ * mei_cl_irq_write - write a message to device
  *	from the interrupt thread context
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise error.
  */
-int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				     s32 *slots, struct mei_cl_cb *cmpl_list)
+int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
+		     struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev;
 	struct mei_msg_data *buf;
 	struct mei_msg_hdr mei_hdr;
 	size_t len;
 	u32 msg_slots;
+	int slots;
 	int rets;
 
-
 	if (WARN_ON(!cl || !cl->dev))
 		return -ENODEV;
 
@@ -738,6 +737,7 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 		return 0;
 	}
 
+	slots = mei_hbuf_empty_slots(dev);
 	len = buf->size - cb->buf_idx;
 	msg_slots = mei_data2slots(len);
 
@@ -746,13 +746,13 @@ int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
 	mei_hdr.reserved = 0;
 	mei_hdr.internal = cb->internal;
 
-	if (*slots >= msg_slots) {
+	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);
+	} 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 {
@@ -763,7 +763,6 @@ int mei_cl_irq_write_complete(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);
 
-	*slots -=  msg_slots;
 	rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
 	if (rets) {
 		cl->status = rets;
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index c8396e5..c11b663 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -102,8 +102,8 @@ 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_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking);
-int mei_cl_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				s32 *slots, struct mei_cl_cb *cmpl_list);
+int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
+		     struct mei_cl_cb *cmpl_list);
 
 void mei_cl_complete(struct mei_cl *cl, struct mei_cl_cb *cb);
 
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index b0c42d6..84165cc 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -354,7 +354,7 @@ static int mei_me_write_message(struct mei_device *dev,
 
 	dw_cnt = mei_data2slots(length);
 	if (empty_slots < 0 || dw_cnt > empty_slots)
-		return -EIO;
+		return -EMSGSIZE;
 
 	mei_me_reg_write(hw, H_CB_WW, *((u32 *) header));
 
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index ab0442e..69a5ce7 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -565,7 +565,9 @@ static int mei_txe_write(struct mei_device *dev,
 	struct mei_txe_hw *hw = to_txe_hw(dev);
 	unsigned long rem;
 	unsigned long length;
+	int slots = dev->hbuf_depth;
 	u32 *reg_buf = (u32 *)buf;
+	u32 dw_cnt;
 	int i;
 
 	if (WARN_ON(!header || !buf))
@@ -575,11 +577,9 @@ static int mei_txe_write(struct mei_device *dev,
 
 	dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
 
-	if ((length + sizeof(struct mei_msg_hdr)) > PAYLOAD_SIZE) {
-		dev_err(&dev->pdev->dev, "write length exceeded = %ld > %d\n",
-			length + sizeof(struct mei_msg_hdr), PAYLOAD_SIZE);
-		return -ERANGE;
-	}
+	dw_cnt = mei_data2slots(length);
+	if (dw_cnt > slots)
+		return -EMSGSIZE;
 
 	if (WARN(!hw->aliveness, "txe write: aliveness not asserted\n"))
 		return -EAGAIN;
@@ -604,6 +604,9 @@ static int mei_txe_write(struct mei_device *dev,
 		mei_txe_input_payload_write(dev, i + 1, reg);
 	}
 
+	/* after each write the whole buffer is consumed */
+	hw->slots = 0;
+
 	/* Set Input-Doorbell */
 	mei_txe_input_doorbell_set(hw);
 
@@ -631,7 +634,8 @@ static size_t mei_txe_hbuf_max_len(const struct mei_device *dev)
  */
 static int mei_txe_hbuf_empty_slots(struct mei_device *dev)
 {
-	return dev->hbuf_depth;
+	struct mei_txe_hw *hw = to_txe_hw(dev);
+	return hw->slots;
 }
 
 /**
@@ -977,11 +981,12 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id)
 		}
 	}
 	/* Input Ready: Detection if host can write to SeC */
-	if (test_and_clear_bit(TXE_INTR_IN_READY_BIT, &hw->intr_cause))
+	if (test_and_clear_bit(TXE_INTR_IN_READY_BIT, &hw->intr_cause)) {
 		dev->hbuf_is_ready = true;
+		hw->slots = dev->hbuf_depth;
+	}
 
 	if (hw->aliveness && dev->hbuf_is_ready) {
-
 		/* get the real register value */
 		dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
 		rets = mei_irq_write_handler(dev, &complete_list);
diff --git a/drivers/misc/mei/hw-txe.h b/drivers/misc/mei/hw-txe.h
index 857d88c..3d8d6e5 100644
--- a/drivers/misc/mei/hw-txe.h
+++ b/drivers/misc/mei/hw-txe.h
@@ -44,6 +44,7 @@ struct mei_txe_hw {
 	void __iomem *mem_addr[NUM_OF_MEM_BARS];
 	u32 aliveness;
 	u32 readiness;
+	u32 slots;
 
 	wait_queue_head_t wait_aliveness;
 	bool recvd_aliveness;
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 8f8ab08..8fbdb59 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -165,25 +165,24 @@ static int mei_cl_irq_read_msg(struct mei_device *dev,
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
 static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
-			s32 *slots, struct mei_cl_cb *cmpl_list)
+				     struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
+	u32 msg_slots;
+	int slots;
 	int ret;
 
-	u32 msg_slots =
-		mei_data2slots(sizeof(struct hbm_client_connect_response));
+	slots = mei_hbuf_empty_slots(dev);
+	msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_response));
 
-	if (*slots < msg_slots)
+	if (slots < msg_slots)
 		return -EMSGSIZE;
 
-	*slots -= msg_slots;
-
 	ret = mei_hbm_cl_disconnect_rsp(dev, cl);
 
 	cl->state = MEI_FILE_DISCONNECTED;
@@ -201,24 +200,23 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
 static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
-			s32 *slots, struct mei_cl_cb *cmpl_list)
+			    struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
+	u32 msg_slots;
+	int slots;
 
-	u32 msg_slots =
-		mei_data2slots(sizeof(struct hbm_client_connect_request));
+	msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+	slots = mei_hbuf_empty_slots(dev);
 
-	if (*slots < msg_slots)
+	if (slots < msg_slots)
 		return -EMSGSIZE;
 
-	*slots -= msg_slots;
-
 	if (mei_hbm_cl_disconnect_req(dev, cl)) {
 		cl->status = 0;
 		cb->buf_idx = 0;
@@ -242,27 +240,23 @@ static int mei_cl_irq_close(struct mei_cl *cl, struct mei_cl_cb *cb,
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
 static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
-			   s32 *slots, struct mei_cl_cb *cmpl_list)
+			   struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
-	u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
-
+	u32 msg_slots;
+	int slots;
 	int ret;
 
+	msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
+	slots = mei_hbuf_empty_slots(dev);
 
-	if (*slots < msg_slots) {
-		/* return the cancel routine */
-		list_del(&cb->list);
+	if (slots < msg_slots)
 		return -EMSGSIZE;
-	}
-
-	*slots -= msg_slots;
 
 	ret = mei_hbm_cl_flow_control_req(dev, cl);
 	if (ret) {
@@ -283,30 +277,26 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
  *
  * @cl: client
  * @cb: callback block.
- * @slots: free slots.
  * @cmpl_list: complete list.
  *
  * returns 0, OK; otherwise, error.
  */
 static int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
-			   s32 *slots, struct mei_cl_cb *cmpl_list)
+			      struct mei_cl_cb *cmpl_list)
 {
 	struct mei_device *dev = cl->dev;
+	u32 msg_slots;
+	int slots;
 	int ret;
 
-	u32 msg_slots =
-		mei_data2slots(sizeof(struct hbm_client_connect_request));
+	msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+	slots = mei_hbuf_empty_slots(dev);
 
 	if (mei_cl_is_other_connecting(cl))
 		return 0;
 
-	if (*slots < msg_slots) {
-		/* return the cancel routine */
-		list_del(&cb->list);
+	if (slots < msg_slots)
 		return -EMSGSIZE;
-	}
-
-	*slots -=  msg_slots;
 
 	cl->state = MEI_FILE_CONNECTING;
 
@@ -494,13 +484,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 				dev_dbg(&dev->pdev->dev, "wd send failed.\n");
 			else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl))
 				return -ENODEV;
-
 			dev->wd_pending = false;
-
-			if (dev->wd_state == MEI_WD_RUNNING)
-				slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
-			else
-				slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);
 		}
 	}
 
@@ -515,28 +499,28 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		switch (cb->fop_type) {
 		case MEI_FOP_CLOSE:
 			/* send disconnect message */
-			ret = mei_cl_irq_close(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_close(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
 		case MEI_FOP_READ:
 			/* send flow control message */
-			ret = mei_cl_irq_read(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_read(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
 		case MEI_FOP_CONNECT:
 			/* connect message */
-			ret = mei_cl_irq_connect(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_connect(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 
 			break;
 		case MEI_FOP_DISCONNECT_RSP:
 			/* send disconnect resp */
-			ret = mei_cl_irq_disconnect_rsp(cl, cb, &slots, cmpl_list);
+			ret = mei_cl_irq_disconnect_rsp(cl, cb, cmpl_list);
 			if (ret)
 				return ret;
 		default:
@@ -551,11 +535,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list)
 		if (cl == NULL)
 			continue;
 		if (cl == &dev->iamthif_cl)
-			ret = mei_amthif_irq_write_complete(cl, cb,
-						&slots, cmpl_list);
+			ret = mei_amthif_irq_write(cl, cb, cmpl_list);
 		else
-			ret = mei_cl_irq_write_complete(cl, cb,
-						&slots, cmpl_list);
+			ret = mei_cl_irq_write(cl, cb, cmpl_list);
 		if (ret)
 			return ret;
 	}
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index c77b747..49bf2cf 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -514,8 +514,8 @@ struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev,
 
 void mei_amthif_run_next_cmd(struct mei_device *dev);
 
-int mei_amthif_irq_write_complete(struct mei_cl *cl, struct mei_cl_cb *cb,
-				  s32 *slots, struct mei_cl_cb *cmpl_list);
+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,
-- 
1.8.5.3


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

* Re: [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper
  2014-02-12 19:41 ` [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper Tomas Winkler
@ 2014-02-14 19:13   ` Greg KH
  2014-02-15  7:46     ` Winkler, Tomas
  0 siblings, 1 reply; 8+ messages in thread
From: Greg KH @ 2014-02-14 19:13 UTC (permalink / raw)
  To: Tomas Winkler; +Cc: arnd, linux-kernel

On Wed, Feb 12, 2014 at 09:41:53PM +0200, Tomas Winkler wrote:
> A client has to acquire host buffer
> before writing, we add lock like wrapper
> to replace the code snippet
> 
> if (dev->hbuf_is_ready)
>         dev->hbuf_is_ready = false;
> 
> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
> ---
>  drivers/misc/mei/amthif.c    |  7 +-----
>  drivers/misc/mei/client.c    | 56 ++++++++++++++++++++++++++++----------------
>  drivers/misc/mei/hw-me.c     |  2 ++
>  drivers/misc/mei/hw-txe.c    | 17 +++++---------
>  drivers/misc/mei/interrupt.c |  6 ++---
>  drivers/misc/mei/mei_dev.h   |  2 ++
>  drivers/misc/mei/wd.c        | 14 +++++------
>  7 files changed, 57 insertions(+), 47 deletions(-)

This patch fails to apply:
	checking file drivers/misc/mei/amthif.c
	checking file drivers/misc/mei/client.c
	Hunk #4 FAILED at 681.
	Hunk #5 succeeded at 815 (offset -2 lines).
	Hunk #6 succeeded at 848 (offset -2 lines).
	1 out of 6 hunks FAILED
	checking file drivers/misc/mei/hw-me.c
	checking file drivers/misc/mei/hw-txe.c
	checking file drivers/misc/mei/interrupt.c
	checking file drivers/misc/mei/mei_dev.h
	checking file drivers/misc/mei/wd.c


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

* RE: [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper
  2014-02-14 19:13   ` Greg KH
@ 2014-02-15  7:46     ` Winkler, Tomas
  2014-02-15 17:37       ` Greg KH
  0 siblings, 1 reply; 8+ messages in thread
From: Winkler, Tomas @ 2014-02-15  7:46 UTC (permalink / raw)
  To: Greg KH; +Cc: arnd, linux-kernel

> 
> This patch fails to apply:
> 	checking file drivers/misc/mei/amthif.c
> 	checking file drivers/misc/mei/client.c
> 	Hunk #4 FAILED at 681.
> 	Hunk #5 succeeded at 815 (offset -2 lines).
> 	Hunk #6 succeeded at 848 (offset -2 lines).
> 	1 out of 6 hunks FAILED
> 	checking file drivers/misc/mei/hw-me.c
> 	checking file drivers/misc/mei/hw-txe.c
> 	checking file drivers/misc/mei/interrupt.c
> 	checking file drivers/misc/mei/mei_dev.h
> 	checking file drivers/misc/mei/wd.c

Did I missed something in the process? 
This patch series has dependency on path that was destined for stable https://lkml.org/lkml/2014/2/12/389
 as stated in 0/4 http://www.spinics.net/lists/kernel/msg1686728.html
Quoting:
"In order to avoid conflicts please apply after
mei: set client's read_cb to NULL when flow control fails
https://lkml.org/lkml/2014/2/12/389"


Thanks
Tomas


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

* Re: [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper
  2014-02-15  7:46     ` Winkler, Tomas
@ 2014-02-15 17:37       ` Greg KH
  0 siblings, 0 replies; 8+ messages in thread
From: Greg KH @ 2014-02-15 17:37 UTC (permalink / raw)
  To: Winkler, Tomas; +Cc: arnd, linux-kernel

On Sat, Feb 15, 2014 at 07:46:49AM +0000, Winkler, Tomas wrote:
> > 
> > This patch fails to apply:
> > 	checking file drivers/misc/mei/amthif.c
> > 	checking file drivers/misc/mei/client.c
> > 	Hunk #4 FAILED at 681.
> > 	Hunk #5 succeeded at 815 (offset -2 lines).
> > 	Hunk #6 succeeded at 848 (offset -2 lines).
> > 	1 out of 6 hunks FAILED
> > 	checking file drivers/misc/mei/hw-me.c
> > 	checking file drivers/misc/mei/hw-txe.c
> > 	checking file drivers/misc/mei/interrupt.c
> > 	checking file drivers/misc/mei/mei_dev.h
> > 	checking file drivers/misc/mei/wd.c
> 
> Did I missed something in the process? 
> This patch series has dependency on path that was destined for stable https://lkml.org/lkml/2014/2/12/389
>  as stated in 0/4 http://www.spinics.net/lists/kernel/msg1686728.html
> Quoting:
> "In order to avoid conflicts please apply after
> mei: set client's read_cb to NULL when flow control fails
> https://lkml.org/lkml/2014/2/12/389"

I never read 0/4 emails :)

Care to resend both of these patches, I'll queue them up when I merge
char-misc-linus into char-misc-next after the next -rc is out.

thanks,

greg k-h

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

end of thread, other threads:[~2014-02-15 17:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-12 19:41 [char-misc-next 0/4] mei: fix txe write issue Tomas Winkler
2014-02-12 19:41 ` [char-misc-next 1/4] mei: rename MEI_FOP_IOCTL to MEI_FOP_CONNECT Tomas Winkler
2014-02-12 19:41 ` [char-misc-next 2/4] mei: get rid of ext_msg Tomas Winkler
2014-02-12 19:41 ` [char-misc-next 3/4] mei: add mei_hbuf_acquire wrapper Tomas Winkler
2014-02-14 19:13   ` Greg KH
2014-02-15  7:46     ` Winkler, Tomas
2014-02-15 17:37       ` Greg KH
2014-02-12 19:41 ` [char-misc-next 4/4] mei: revamp writing slot counting Tomas Winkler

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.