/* * mei_wd_ops_ping - wd ping command from the watchdog core. * * @wd_dev - watchdog device struct * * returns 0 if success, negative errno code for failure */ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) { 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 (cl->state != MEI_FILE_CONNECTED) { dev_err(&dev->pdev->dev, "wd: not connected.\n"); ret = -ENODEV; goto end; } dev->wd_state = MEI_WD_RUNNING; ret = mei_cl_flow_ctrl_creds(cl); if (ret < 0) goto end; /* Check if we can send the ping to HW*/ if (ret && mei_hbuf_acquire(dev)) { dev_dbg(&dev->pdev->dev, "wd: sending ping\n"); if (mei_wd_send(dev)) { dev_err(&dev->pdev->dev, "wd: send failed.\n"); ret = -EIO; goto end; } if (mei_cl_flow_ctrl_reduce(cl)) { dev_err(&dev->pdev->dev, "wd: mei_cl_flow_ctrl_reduce() failed.\n"); ret = -EIO; goto end; } } else { dev->wd_pending = true; } end: mutex_unlock(&dev->device_lock); return ret; }
/** * 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 * -EINVAL when invalid message is to be sent */ int mei_wd_stop(struct mei_device *dev) { int ret; if (dev->wd_cl.state != MEI_FILE_CONNECTED || dev->wd_state != MEI_WD_RUNNING) return 0; memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); dev->wd_state = MEI_WD_STOPPING; ret = mei_cl_flow_ctrl_creds(&dev->wd_cl); if (ret < 0) goto out; if (ret && mei_hbuf_acquire(dev)) { ret = 0; 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"); } dev->wd_pending = false; } else { dev->wd_pending = true; } 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)); 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); } out: return ret; }
/** * mei_wd_stop - sends watchdog stop message to fw. * * @dev: the device structure * * 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 (!mei_cl_is_connected(cl) || dev->wd_state != MEI_WD_RUNNING) return 0; memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); dev->wd_state = MEI_WD_STOPPING; ret = mei_cl_flow_ctrl_creds(cl); if (ret < 0) 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; } mutex_unlock(&dev->device_lock); 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) { /* timeout */ ret = -ETIME; dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); goto err; } 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_ping - wd ping command from the watchdog core. * * @wd_dev: watchdog device struct * * Return: 0 if success, negative errno code for failure */ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) { 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 (!mei_cl_is_connected(cl)) { cl_err(dev, cl, "wd: not connected.\n"); ret = -ENODEV; goto end; } dev->wd_state = MEI_WD_RUNNING; ret = mei_cl_flow_ctrl_creds(cl); if (ret < 0) 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"); ret = mei_wd_send(dev); if (ret) goto end; dev->wd_pending = false; } else { dev->wd_pending = true; } end: mutex_unlock(&dev->device_lock); return ret; }