Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mei: wd: drop AGAIN the watchdog code from the core mei driver

The file wd.c was remove from the driver by commit
commit fdd9b8655933 ("mei: wd: drop the watchdog code from the core mei
driver")

Unfortunately it came back by mistake in rebasing in the commit
commit 06ee536bcb15 ("mei: fill file pointer in read cb for fixed
address client")

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Tomas Winkler and committed by
Greg Kroah-Hartman
4ddbdbb9 ececdc02

-391
-391
drivers/misc/mei/wd.c
··· 1 - /* 2 - * 3 - * Intel Management Engine Interface (Intel MEI) Linux driver 4 - * Copyright (c) 2003-2012, Intel Corporation. 5 - * 6 - * This program is free software; you can redistribute it and/or modify it 7 - * under the terms and conditions of the GNU General Public License, 8 - * version 2, as published by the Free Software Foundation. 9 - * 10 - * This program is distributed in the hope it will be useful, but WITHOUT 11 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 - * more details. 14 - * 15 - */ 16 - #include <linux/kernel.h> 17 - #include <linux/module.h> 18 - #include <linux/moduleparam.h> 19 - #include <linux/device.h> 20 - #include <linux/sched.h> 21 - #include <linux/watchdog.h> 22 - 23 - #include <linux/mei.h> 24 - 25 - #include "mei_dev.h" 26 - #include "hbm.h" 27 - #include "client.h" 28 - 29 - static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; 30 - static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; 31 - 32 - /* 33 - * AMT Watchdog Device 34 - */ 35 - #define INTEL_AMT_WATCHDOG_ID "INTCAMT" 36 - 37 - /* UUIDs for AMT F/W clients */ 38 - const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, 39 - 0x9D, 0xA9, 0x15, 0x14, 0xCB, 40 - 0x32, 0xAB); 41 - 42 - static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) 43 - { 44 - dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); 45 - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); 46 - memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); 47 - } 48 - 49 - /** 50 - * mei_wd_host_init - connect to the watchdog client 51 - * 52 - * @dev: the device structure 53 - * @me_cl: me client 54 - * 55 - * Return: -ENOTTY if wd client cannot be found 56 - * -EIO if write has failed 57 - * 0 on success 58 - */ 59 - int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) 60 - { 61 - struct mei_cl *cl = &dev->wd_cl; 62 - int ret; 63 - 64 - mei_cl_init(cl, dev); 65 - 66 - dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; 67 - dev->wd_state = MEI_WD_IDLE; 68 - 69 - ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); 70 - if (ret < 0) { 71 - dev_info(dev->dev, "wd: failed link client\n"); 72 - return ret; 73 - } 74 - 75 - ret = mei_cl_connect(cl, me_cl, NULL); 76 - if (ret) { 77 - dev_err(dev->dev, "wd: failed to connect = %d\n", ret); 78 - mei_cl_unlink(cl); 79 - return ret; 80 - } 81 - 82 - ret = mei_watchdog_register(dev); 83 - if (ret) { 84 - mei_cl_disconnect(cl); 85 - mei_cl_unlink(cl); 86 - } 87 - return ret; 88 - } 89 - 90 - /** 91 - * mei_wd_send - sends watch dog message to fw. 92 - * 93 - * @dev: the device structure 94 - * 95 - * Return: 0 if success, 96 - * -EIO when message send fails 97 - * -EINVAL when invalid message is to be sent 98 - * -ENODEV on flow control failure 99 - */ 100 - int mei_wd_send(struct mei_device *dev) 101 - { 102 - struct mei_cl *cl = &dev->wd_cl; 103 - struct mei_msg_hdr hdr; 104 - int ret; 105 - 106 - hdr.host_addr = cl->host_client_id; 107 - hdr.me_addr = mei_cl_me_id(cl); 108 - hdr.msg_complete = 1; 109 - hdr.reserved = 0; 110 - hdr.internal = 0; 111 - 112 - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) 113 - hdr.length = MEI_WD_START_MSG_SIZE; 114 - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) 115 - hdr.length = MEI_WD_STOP_MSG_SIZE; 116 - else { 117 - dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); 118 - return -EINVAL; 119 - } 120 - 121 - ret = mei_write_message(dev, &hdr, dev->wd_data); 122 - if (ret) { 123 - dev_err(dev->dev, "wd: write message failed\n"); 124 - return ret; 125 - } 126 - 127 - ret = mei_cl_flow_ctrl_reduce(cl); 128 - if (ret) { 129 - dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); 130 - return ret; 131 - } 132 - 133 - return 0; 134 - } 135 - 136 - /** 137 - * mei_wd_stop - sends watchdog stop message to fw. 138 - * 139 - * @dev: the device structure 140 - * 141 - * Return: 0 if success 142 - * on error: 143 - * -EIO when message send fails 144 - * -EINVAL when invalid message is to be sent 145 - * -ETIME on message timeout 146 - */ 147 - int mei_wd_stop(struct mei_device *dev) 148 - { 149 - struct mei_cl *cl = &dev->wd_cl; 150 - int ret; 151 - 152 - if (!mei_cl_is_connected(cl) || 153 - dev->wd_state != MEI_WD_RUNNING) 154 - return 0; 155 - 156 - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); 157 - 158 - dev->wd_state = MEI_WD_STOPPING; 159 - 160 - ret = mei_cl_flow_ctrl_creds(cl, NULL); 161 - if (ret < 0) 162 - goto err; 163 - 164 - if (ret && mei_hbuf_acquire(dev)) { 165 - ret = mei_wd_send(dev); 166 - if (ret) 167 - goto err; 168 - dev->wd_pending = false; 169 - } else { 170 - dev->wd_pending = true; 171 - } 172 - 173 - mutex_unlock(&dev->device_lock); 174 - 175 - ret = wait_event_timeout(dev->wait_stop_wd, 176 - dev->wd_state == MEI_WD_IDLE, 177 - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); 178 - mutex_lock(&dev->device_lock); 179 - if (dev->wd_state != MEI_WD_IDLE) { 180 - /* timeout */ 181 - ret = -ETIME; 182 - dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); 183 - goto err; 184 - } 185 - dev_dbg(dev->dev, "wd: stop completed after %u msec\n", 186 - MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); 187 - return 0; 188 - err: 189 - return ret; 190 - } 191 - 192 - /** 193 - * mei_wd_ops_start - wd start command from the watchdog core. 194 - * 195 - * @wd_dev: watchdog device struct 196 - * 197 - * Return: 0 if success, negative errno code for failure 198 - */ 199 - static int mei_wd_ops_start(struct watchdog_device *wd_dev) 200 - { 201 - struct mei_device *dev; 202 - struct mei_cl *cl; 203 - int err = -ENODEV; 204 - 205 - dev = watchdog_get_drvdata(wd_dev); 206 - if (!dev) 207 - return -ENODEV; 208 - 209 - cl = &dev->wd_cl; 210 - 211 - mutex_lock(&dev->device_lock); 212 - 213 - if (dev->dev_state != MEI_DEV_ENABLED) { 214 - dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", 215 - mei_dev_state_str(dev->dev_state)); 216 - goto end_unlock; 217 - } 218 - 219 - if (!mei_cl_is_connected(cl)) { 220 - cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); 221 - goto end_unlock; 222 - } 223 - 224 - mei_wd_set_start_timeout(dev, dev->wd_timeout); 225 - 226 - err = 0; 227 - end_unlock: 228 - mutex_unlock(&dev->device_lock); 229 - return err; 230 - } 231 - 232 - /** 233 - * mei_wd_ops_stop - wd stop command from the watchdog core. 234 - * 235 - * @wd_dev: watchdog device struct 236 - * 237 - * Return: 0 if success, negative errno code for failure 238 - */ 239 - static int mei_wd_ops_stop(struct watchdog_device *wd_dev) 240 - { 241 - struct mei_device *dev; 242 - 243 - dev = watchdog_get_drvdata(wd_dev); 244 - if (!dev) 245 - return -ENODEV; 246 - 247 - mutex_lock(&dev->device_lock); 248 - mei_wd_stop(dev); 249 - mutex_unlock(&dev->device_lock); 250 - 251 - return 0; 252 - } 253 - 254 - /** 255 - * mei_wd_ops_ping - wd ping command from the watchdog core. 256 - * 257 - * @wd_dev: watchdog device struct 258 - * 259 - * Return: 0 if success, negative errno code for failure 260 - */ 261 - static int mei_wd_ops_ping(struct watchdog_device *wd_dev) 262 - { 263 - struct mei_device *dev; 264 - struct mei_cl *cl; 265 - int ret; 266 - 267 - dev = watchdog_get_drvdata(wd_dev); 268 - if (!dev) 269 - return -ENODEV; 270 - 271 - cl = &dev->wd_cl; 272 - 273 - mutex_lock(&dev->device_lock); 274 - 275 - if (!mei_cl_is_connected(cl)) { 276 - cl_err(dev, cl, "wd: not connected.\n"); 277 - ret = -ENODEV; 278 - goto end; 279 - } 280 - 281 - dev->wd_state = MEI_WD_RUNNING; 282 - 283 - ret = mei_cl_flow_ctrl_creds(cl, NULL); 284 - if (ret < 0) 285 - goto end; 286 - 287 - /* Check if we can send the ping to HW*/ 288 - if (ret && mei_hbuf_acquire(dev)) { 289 - dev_dbg(dev->dev, "wd: sending ping\n"); 290 - 291 - ret = mei_wd_send(dev); 292 - if (ret) 293 - goto end; 294 - dev->wd_pending = false; 295 - } else { 296 - dev->wd_pending = true; 297 - } 298 - 299 - end: 300 - mutex_unlock(&dev->device_lock); 301 - return ret; 302 - } 303 - 304 - /** 305 - * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. 306 - * 307 - * @wd_dev: watchdog device struct 308 - * @timeout: timeout value to set 309 - * 310 - * Return: 0 if success, negative errno code for failure 311 - */ 312 - static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, 313 - unsigned int timeout) 314 - { 315 - struct mei_device *dev; 316 - 317 - dev = watchdog_get_drvdata(wd_dev); 318 - if (!dev) 319 - return -ENODEV; 320 - 321 - /* Check Timeout value */ 322 - if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) 323 - return -EINVAL; 324 - 325 - mutex_lock(&dev->device_lock); 326 - 327 - dev->wd_timeout = timeout; 328 - wd_dev->timeout = timeout; 329 - mei_wd_set_start_timeout(dev, dev->wd_timeout); 330 - 331 - mutex_unlock(&dev->device_lock); 332 - 333 - return 0; 334 - } 335 - 336 - /* 337 - * Watchdog Device structs 338 - */ 339 - static const struct watchdog_ops wd_ops = { 340 - .owner = THIS_MODULE, 341 - .start = mei_wd_ops_start, 342 - .stop = mei_wd_ops_stop, 343 - .ping = mei_wd_ops_ping, 344 - .set_timeout = mei_wd_ops_set_timeout, 345 - }; 346 - static const struct watchdog_info wd_info = { 347 - .identity = INTEL_AMT_WATCHDOG_ID, 348 - .options = WDIOF_KEEPALIVEPING | 349 - WDIOF_SETTIMEOUT | 350 - WDIOF_ALARMONLY, 351 - }; 352 - 353 - static struct watchdog_device amt_wd_dev = { 354 - .info = &wd_info, 355 - .ops = &wd_ops, 356 - .timeout = MEI_WD_DEFAULT_TIMEOUT, 357 - .min_timeout = MEI_WD_MIN_TIMEOUT, 358 - .max_timeout = MEI_WD_MAX_TIMEOUT, 359 - }; 360 - 361 - 362 - int mei_watchdog_register(struct mei_device *dev) 363 - { 364 - 365 - int ret; 366 - 367 - amt_wd_dev.parent = dev->dev; 368 - /* unlock to perserve correct locking order */ 369 - mutex_unlock(&dev->device_lock); 370 - ret = watchdog_register_device(&amt_wd_dev); 371 - mutex_lock(&dev->device_lock); 372 - if (ret) { 373 - dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", 374 - ret); 375 - return ret; 376 - } 377 - 378 - dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); 379 - watchdog_set_drvdata(&amt_wd_dev, dev); 380 - return 0; 381 - } 382 - 383 - void mei_watchdog_unregister(struct mei_device *dev) 384 - { 385 - if (watchdog_get_drvdata(&amt_wd_dev) == NULL) 386 - return; 387 - 388 - watchdog_set_drvdata(&amt_wd_dev, NULL); 389 - watchdog_unregister_device(&amt_wd_dev); 390 - } 391 -