提交 db4756fd 编写于 作者: T Tomas Winkler 提交者: Greg Kroah-Hartman

mei: iamthif: fix device reset on mei_amthif_irq_read_msg

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: NTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 3d33ff24
...@@ -195,23 +195,26 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, ...@@ -195,23 +195,26 @@ int mei_amthif_read(struct mei_device *dev, struct file *file,
dev_dbg(dev->dev, "woke up from sleep\n"); 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_dbg(dev->dev, "Got amthif data\n");
dev->iamthif_timer = 0; dev->iamthif_timer = 0;
if (cb) { timeout = cb->read_time +
timeout = cb->read_time + mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER);
mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); dev_dbg(dev->dev, "amthif timeout = %lud\n",
dev_dbg(dev->dev, "amthif timeout = %lud\n", timeout);
timeout);
if (time_after(jiffies, timeout)) {
if (time_after(jiffies, timeout)) { dev_dbg(dev->dev, "amthif Time out\n");
dev_dbg(dev->dev, "amthif Time out\n"); /* 15 sec for the message has expired */
/* 15 sec for the message has expired */ list_del(&cb->list);
list_del(&cb->list); rets = -ETIME;
rets = -ETIME; goto free;
goto free;
}
} }
/* if the whole message will fit remove it from the list */ /* if the whole message will fit remove it from the list */
if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) 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, ...@@ -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 * mei_amthif_irq_read_msg - read routine after ISR to
* handle the read amthif message * handle the read amthif message
* *
* @dev: the device structure * @cl: mei client
* @mei_hdr: header of amthif message * @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_msg_hdr *mei_hdr,
struct mei_cl_cb *complete_list) struct mei_cl_cb *complete_list)
{ {
struct mei_device *dev;
struct mei_cl_cb *cb; struct mei_cl_cb *cb;
unsigned char *buffer; unsigned char *buffer;
int ret = 0;
BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); dev = cl->dev;
BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; if (cl->state != MEI_FILE_CONNECTED)
BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); 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); mei_read_slots(dev, buffer, mei_hdr->length);
dev->iamthif_msg_buf_index += 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, ...@@ -527,14 +547,8 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
if (!mei_hdr->msg_complete) if (!mei_hdr->msg_complete)
return 0; return 0;
dev_dbg(dev->dev, "amthif_message_buffer_index =%d\n",
mei_hdr->length);
dev_dbg(dev->dev, "completed amthif read.\n "); 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_current_cb = NULL;
dev->iamthif_stall_timer = 0; dev->iamthif_stall_timer = 0;
...@@ -543,10 +557,16 @@ int mei_amthif_irq_read_msg(struct mei_device *dev, ...@@ -543,10 +557,16 @@ int mei_amthif_irq_read_msg(struct mei_device *dev,
if (dev->iamthif_ioctl) { if (dev->iamthif_ioctl) {
/* found the iamthif cb */ /* found the iamthif cb */
dev_dbg(dev->dev, "complete the amthif read cb.\n "); 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); list_add_tail(&cb->list, &complete_list->list);
} }
return 0; 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;
} }
/** /**
......
...@@ -384,11 +384,8 @@ int mei_irq_read_handler(struct mei_device *dev, ...@@ -384,11 +384,8 @@ int mei_irq_read_handler(struct mei_device *dev,
goto end; goto end;
} }
if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && if (cl == &dev->iamthif_cl) {
MEI_FILE_CONNECTED == dev->iamthif_cl.state && ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list);
dev->iamthif_state == MEI_IAMTHIF_READING) {
ret = mei_amthif_irq_read_msg(dev, mei_hdr, cmpl_list);
if (ret) { if (ret) {
dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n", dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n",
ret); ret);
......
...@@ -685,7 +685,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, ...@@ -685,7 +685,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_cl_cb *cmpl_list); struct mei_cl_cb *cmpl_list);
void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); 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_msg_hdr *mei_hdr,
struct mei_cl_cb *complete_list); struct mei_cl_cb *complete_list);
int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); int mei_amthif_irq_read(struct mei_device *dev, s32 *slots);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册