--- zzzz-none-000/linux-3.10.107/drivers/misc/mei/wd.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/misc/mei/wd.c 2021-02-04 17:41:59.000000000 +0000 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -25,18 +24,11 @@ #include "mei_dev.h" #include "hbm.h" -#include "hw-me.h" #include "client.h" static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; -const u8 mei_wd_state_independence_msg[3][4] = { - {0x05, 0x02, 0x51, 0x10}, - {0x05, 0x02, 0x52, 0x10}, - {0x07, 0x02, 0x01, 0x10} -}; - /* * AMT Watchdog Device */ @@ -49,7 +41,7 @@ static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) { - dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout); + dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); } @@ -58,15 +50,15 @@ * mei_wd_host_init - connect to the watchdog client * * @dev: the device structure + * @me_cl: me client * - * returns -ENENT if wd client cannot be found + * Return: -ENOTTY if wd client cannot be found * -EIO if write has failed * 0 on success */ -int mei_wd_host_init(struct mei_device *dev) +int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) { struct mei_cl *cl = &dev->wd_cl; - int i; int ret; mei_cl_init(cl, dev); @@ -74,34 +66,25 @@ dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; dev->wd_state = MEI_WD_IDLE; - - /* check for valid client id */ - i = mei_me_cl_by_uuid(dev, &mei_wd_guid); - if (i < 0) { - dev_info(&dev->pdev->dev, "wd: failed to find the client\n"); - return -ENOENT; - } - - cl->me_client_id = dev->me_clients[i].client_id; - ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); - if (ret < 0) { - dev_info(&dev->pdev->dev, "wd: failed link client\n"); - return -ENOENT; + dev_info(dev->dev, "wd: failed link client\n"); + return ret; } - 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; + ret = mei_cl_connect(cl, me_cl, NULL); + if (ret) { + dev_err(dev->dev, "wd: failed to connect = %d\n", ret); + mei_cl_unlink(cl); + return ret; } - cl->timer_count = MEI_CONNECT_TIMEOUT; - return 0; + ret = mei_watchdog_register(dev); + if (ret) { + mei_cl_disconnect(cl); + mei_cl_unlink(cl); + } + return ret; } /** @@ -109,44 +92,64 @@ * * @dev: the device structure * - * returns 0 if success, + * Return: 0 if success, * -EIO when message send fails * -EINVAL when invalid message is to be sent + * -ENODEV on flow control failure */ int mei_wd_send(struct mei_device *dev) { + struct mei_cl *cl = &dev->wd_cl; struct mei_msg_hdr hdr; + int ret; - hdr.host_addr = dev->wd_cl.host_client_id; - hdr.me_addr = dev->wd_cl.me_client_id; + hdr.host_addr = cl->host_client_id; + hdr.me_addr = mei_cl_me_id(cl); hdr.msg_complete = 1; hdr.reserved = 0; + hdr.internal = 0; if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) hdr.length = MEI_WD_START_MSG_SIZE; else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) hdr.length = MEI_WD_STOP_MSG_SIZE; - else + else { + dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); return -EINVAL; + } + + ret = mei_write_message(dev, &hdr, dev->wd_data); + if (ret) { + dev_err(dev->dev, "wd: write message failed\n"); + return ret; + } - return mei_write_message(dev, &hdr, dev->wd_data); + ret = mei_cl_flow_ctrl_reduce(cl); + if (ret) { + dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); + return ret; + } + + return 0; } /** * mei_wd_stop - sends watchdog stop message to fw. * * @dev: the device structure - * @preserve: indicate if to keep the timeout value * - * returns 0 if success, - * -EIO when message send fails + * Return: 0 if success + * on error: + * -EIO when message send fails * -EINVAL when invalid message is to be sent + * -ETIME on message timeout */ int mei_wd_stop(struct mei_device *dev) { + struct mei_cl *cl = &dev->wd_cl; int ret; - if (dev->wd_cl.state != MEI_FILE_CONNECTED || + if (!mei_cl_is_connected(cl) || dev->wd_state != MEI_WD_RUNNING) return 0; @@ -154,22 +157,14 @@ dev->wd_state = MEI_WD_STOPPING; - ret = mei_cl_flow_ctrl_creds(&dev->wd_cl); + ret = mei_cl_flow_ctrl_creds(cl); if (ret < 0) - goto out; - - if (ret && dev->hbuf_is_ready) { - ret = 0; - dev->hbuf_is_ready = false; - - if (!mei_wd_send(dev)) { - ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl); - if (ret) - goto out; - } else { - dev_err(&dev->pdev->dev, "wd: send stop failed\n"); - } + goto err; + if (ret && mei_hbuf_acquire(dev)) { + ret = mei_wd_send(dev); + if (ret) + goto err; dev->wd_pending = false; } else { dev->wd_pending = true; @@ -177,52 +172,52 @@ mutex_unlock(&dev->device_lock); - ret = wait_event_interruptible_timeout(dev->wait_stop_wd, - dev->wd_state == MEI_WD_IDLE, - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); + ret = wait_event_timeout(dev->wait_stop_wd, + dev->wd_state == MEI_WD_IDLE, + msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); mutex_lock(&dev->device_lock); - if (dev->wd_state == MEI_WD_IDLE) { - dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret); - ret = 0; - } else { - if (!ret) - ret = -ETIMEDOUT; - dev_warn(&dev->pdev->dev, - "wd: stop failed to complete ret=%d.\n", ret); + if (dev->wd_state != MEI_WD_IDLE) { + /* timeout */ + ret = -ETIME; + dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); + goto err; } - -out: + dev_dbg(dev->dev, "wd: stop completed after %u msec\n", + MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); + return 0; +err: return ret; } -/* +/** * mei_wd_ops_start - wd start command from the watchdog core. * - * @wd_dev - watchdog device struct + * @wd_dev: watchdog device struct * - * returns 0 if success, negative errno code for failure + * Return: 0 if success, negative errno code for failure */ static int mei_wd_ops_start(struct watchdog_device *wd_dev) { - int err = -ENODEV; struct mei_device *dev; + struct mei_cl *cl; + int err = -ENODEV; dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; + cl = &dev->wd_cl; + mutex_lock(&dev->device_lock); if (dev->dev_state != MEI_DEV_ENABLED) { - dev_dbg(&dev->pdev->dev, - "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", + dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", mei_dev_state_str(dev->dev_state)); goto end_unlock; } - if (dev->wd_cl.state != MEI_FILE_CONNECTED) { - dev_dbg(&dev->pdev->dev, - "MEI Driver is not connected to Watchdog Client\n"); + if (!mei_cl_is_connected(cl)) { + cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); goto end_unlock; } @@ -234,12 +229,12 @@ return err; } -/* +/** * mei_wd_ops_stop - wd stop command from the watchdog core. * - * @wd_dev - watchdog device struct + * @wd_dev: watchdog device struct * - * returns 0 if success, negative errno code for failure + * Return: 0 if success, negative errno code for failure */ static int mei_wd_ops_stop(struct watchdog_device *wd_dev) { @@ -256,51 +251,47 @@ return 0; } -/* +/** * mei_wd_ops_ping - wd ping command from the watchdog core. * - * @wd_dev - watchdog device struct + * @wd_dev: watchdog device struct * - * returns 0 if success, negative errno code for failure + * Return: 0 if success, negative errno code for failure */ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) { - int ret = 0; struct mei_device *dev; + struct mei_cl *cl; + int ret; dev = watchdog_get_drvdata(wd_dev); if (!dev) return -ENODEV; + cl = &dev->wd_cl; + mutex_lock(&dev->device_lock); - if (dev->wd_cl.state != MEI_FILE_CONNECTED) { - dev_err(&dev->pdev->dev, "wd: not connected.\n"); + if (!mei_cl_is_connected(cl)) { + cl_err(dev, cl, "wd: not connected.\n"); ret = -ENODEV; goto end; } dev->wd_state = MEI_WD_RUNNING; - /* Check if we can send the ping to HW*/ - if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { - - dev->hbuf_is_ready = false; - dev_dbg(&dev->pdev->dev, "wd: sending ping\n"); + ret = mei_cl_flow_ctrl_creds(cl); + if (ret < 0) + goto end; - if (mei_wd_send(dev)) { - dev_err(&dev->pdev->dev, "wd: send failed.\n"); - ret = -EIO; - goto end; - } + /* Check if we can send the ping to HW*/ + if (ret && mei_hbuf_acquire(dev)) { + dev_dbg(dev->dev, "wd: sending ping\n"); - if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) { - dev_err(&dev->pdev->dev, - "wd: mei_cl_flow_ctrl_reduce() failed.\n"); - ret = -EIO; + ret = mei_wd_send(dev); + if (ret) goto end; - } - + dev->wd_pending = false; } else { dev->wd_pending = true; } @@ -310,13 +301,13 @@ return ret; } -/* +/** * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. * - * @wd_dev - watchdog device struct - * @timeout - timeout value to set + * @wd_dev: watchdog device struct + * @timeout: timeout value to set * - * returns 0 if success, negative errno code for failure + * Return: 0 if success, negative errno code for failure */ static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout) @@ -368,17 +359,25 @@ }; -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; + + amt_wd_dev.parent = dev->dev; + /* 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->dev, "wd: unable to register watchdog device = %d.\n", + ret); + return ret; } - dev_dbg(&dev->pdev->dev, - "wd: successfully register watchdog interface.\n"); + dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); watchdog_set_drvdata(&amt_wd_dev, dev); + return 0; } void mei_watchdog_unregister(struct mei_device *dev)