From 64092858acfd995fae0def466126692423c30828 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Mon, 17 Feb 2014 15:13:21 +0200 Subject: [PATCH] mei: wd and amthif use mei_cl_ api for dis/connection Connect wd and amthif through regular mei_cl_connect API as there is no reason to connect in asynchronous mode. Also use mei_cl_is_connected in order to protect flows instead of depending on wd_pending and amthif_timer Now we can remove all the special handling in hbm layer Signed-off-by: Tomas Winkler Signed-off-by: Alexander Usyskin Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/amthif.c | 13 ++---- drivers/misc/mei/hbm.c | 91 +++++++++++++----------------------- drivers/misc/mei/interrupt.c | 5 +- drivers/misc/mei/mei_dev.h | 2 +- drivers/misc/mei/wd.c | 39 ++++++++++------ 5 files changed, 68 insertions(+), 82 deletions(-) diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index f88cb26364f5..c0fc23f16496 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c @@ -115,14 +115,11 @@ int mei_amthif_host_init(struct mei_device *dev) cl->state = MEI_FILE_CONNECTING; - if (mei_hbm_cl_connect_req(dev, cl)) { - dev_dbg(&dev->pdev->dev, "amthif: Failed to connect to ME client\n"); - cl->state = MEI_FILE_DISCONNECTED; - cl->host_client_id = 0; - } else { - cl->timer_count = MEI_CONNECT_TIMEOUT; - } - return 0; + ret = mei_cl_connect(cl, NULL); + + dev->iamthif_state = MEI_IAMTHIF_IDLE; + + return ret; } /** diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index d360e9a5a1a5..46743e2349b1 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -133,30 +133,6 @@ bool mei_hbm_cl_addr_equal(struct mei_cl *cl, void *buf) } -/** - * is_treat_specially_client - checks if the message belongs - * to the file private data. - * - * @cl: private data of the file object - * @rs: connect response bus message - * - */ -static bool is_treat_specially_client(struct mei_cl *cl, - struct hbm_client_connect_response *rs) -{ - if (mei_hbm_cl_addr_equal(cl, rs)) { - if (rs->status == MEI_CL_CONN_SUCCESS) - cl->state = MEI_FILE_CONNECTED; - else - cl->state = MEI_FILE_DISCONNECTED; - cl->status = mei_cl_conn_status_to_errno(rs->status); - cl->timer_count = 0; - - return true; - } - return false; -} - /** * mei_hbm_idle - set hbm to idle state * @@ -467,22 +443,22 @@ static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct hbm_client_connect_response *rs) { struct mei_cl *cl; - struct mei_cl_cb *pos = NULL, *next = NULL; + struct mei_cl_cb *cb, *next; dev_dbg(&dev->pdev->dev, "hbm: disconnect response cl:host=%02d me=%02d status=%d\n", rs->me_addr, rs->host_addr, rs->status); - list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) { - cl = pos->cl; + list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) { + cl = cb->cl; - if (!cl) { - list_del(&pos->list); + /* this should not happen */ + if (WARN_ON(!cl)) { + list_del(&cb->list); return; } - dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n"); if (mei_hbm_cl_addr_equal(cl, rs)) { - list_del(&pos->list); + list_del(&cb->list); if (rs->status == MEI_CL_DISCONN_SUCCESS) cl->state = MEI_FILE_DISCONNECTED; @@ -523,40 +499,41 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev, { struct mei_cl *cl; - struct mei_cl_cb *pos = NULL, *next = NULL; + struct mei_cl_cb *cb, *next; dev_dbg(&dev->pdev->dev, "hbm: connect response cl:host=%02d me=%02d status=%s\n", rs->me_addr, rs->host_addr, mei_cl_conn_status_str(rs->status)); - /* if WD or iamthif client treat specially */ + cl = NULL; - if (is_treat_specially_client(&dev->wd_cl, rs)) { - dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); - mei_watchdog_register(dev); + list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list.list, list) { - return; - } - - if (is_treat_specially_client(&dev->iamthif_cl, rs)) { - dev->iamthif_state = MEI_IAMTHIF_IDLE; - return; - } - list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) { - - cl = pos->cl; - if (!cl) { - list_del(&pos->list); - return; + cl = cb->cl; + /* this should not happen */ + if (WARN_ON(!cl)) { + list_del_init(&cb->list); + continue; } - if (pos->fop_type == MEI_FOP_CONNECT) { - if (is_treat_specially_client(cl, rs)) { - list_del(&pos->list); - cl->timer_count = 0; - break; - } + + if (cb->fop_type != MEI_FOP_CONNECT) + continue; + + if (mei_hbm_cl_addr_equal(cl, rs)) { + list_del(&cb->list); + break; } } + + if (!cl) + return; + + cl->timer_count = 0; + if (rs->status == MEI_CL_CONN_SUCCESS) + cl->state = MEI_FILE_CONNECTED; + else + cl->state = MEI_FILE_DISCONNECTED; + cl->status = mei_cl_conn_status_to_errno(rs->status); } @@ -582,10 +559,6 @@ static int mei_hbm_fw_disconnect_req(struct mei_device *dev, disconnect_req->me_addr); cl->state = MEI_FILE_DISCONNECTED; cl->timer_count = 0; - if (cl == &dev->wd_cl) - dev->wd_pending = false; - else if (cl == &dev->iamthif_cl) - dev->iamthif_timer = 0; cb = mei_io_cb_init(cl, NULL); if (!cb) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 75ff4092953e..61ceb781cd20 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -487,7 +487,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) wake_up_interruptible(&dev->wait_stop_wd); } - if (dev->dev_state == MEI_DEV_ENABLED) { + if (mei_cl_is_connected(&dev->wd_cl)) { if (dev->wd_pending && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { if (mei_wd_send(dev)) @@ -613,6 +613,9 @@ void mei_timer(struct work_struct *work) } } + if (!mei_cl_is_connected(&dev->iamthif_cl)) + goto out; + if (dev->iamthif_stall_timer) { if (--dev->iamthif_stall_timer == 0) { dev_err(&dev->pdev->dev, "timer: amthif hanged.\n"); diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 49025fa202ae..030b29e1c92e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -543,7 +543,7 @@ int mei_wd_host_init(struct mei_device *dev); * once we got connection to the WD Client * @dev - mei device */ -void mei_watchdog_register(struct mei_device *dev); +int mei_watchdog_register(struct mei_device *dev); /* * mei_watchdog_unregister - Unregistering watchdog interface * @dev - mei device diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index f70945ed96f6..8c302829a194 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c @@ -87,15 +87,20 @@ int mei_wd_host_init(struct mei_device *dev) cl->state = MEI_FILE_CONNECTING; - if (mei_hbm_cl_connect_req(dev, cl)) { - dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n"); - cl->state = MEI_FILE_DISCONNECTED; - cl->host_client_id = 0; - return -EIO; - } - cl->timer_count = MEI_CONNECT_TIMEOUT; + ret = mei_cl_connect(cl, NULL); - return 0; + if (ret) { + dev_err(&dev->pdev->dev, "wd: failed to connect = %d\n", ret); + mei_cl_unlink(cl); + return ret; + } + + ret = mei_watchdog_register(dev); + if (ret) { + mei_cl_disconnect(cl); + mei_cl_unlink(cl); + } + return ret; } /** @@ -363,17 +368,25 @@ static struct watchdog_device amt_wd_dev = { }; -void mei_watchdog_register(struct mei_device *dev) +int mei_watchdog_register(struct mei_device *dev) { - if (watchdog_register_device(&amt_wd_dev)) { - dev_err(&dev->pdev->dev, - "wd: unable to register watchdog device.\n"); - return; + + int ret; + + /* unlock to perserve correct locking order */ + mutex_unlock(&dev->device_lock); + ret = watchdog_register_device(&amt_wd_dev); + mutex_lock(&dev->device_lock); + if (ret) { + dev_err(&dev->pdev->dev, "wd: unable to register watchdog device = %d.\n", + ret); + return ret; } dev_dbg(&dev->pdev->dev, "wd: successfully register watchdog interface.\n"); watchdog_set_drvdata(&amt_wd_dev, dev); + return 0; } void mei_watchdog_unregister(struct mei_device *dev)