diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/mei/hbm.c | 64 | ||||
-rw-r--r-- | drivers/misc/mei/hbm.h | 1 | ||||
-rw-r--r-- | drivers/misc/mei/hw-me.c | 3 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 1 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 47 | ||||
-rw-r--r-- | 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 0c770255bf89..d3fcb23bb081 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 5f92188a5cd7..20e8782711c0 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 54286f304939..847c9e5746cb 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 95a7180c75ea..214dcef9750a 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 3f0b0b9ce951..75ff4092953e 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 f2c949ef3f28..21e52496bc6e 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 */ |