]>
Commit | Line | Data |
---|---|---|
016e29c0 DM |
1 | From fdd9b8655933c3eb3154fe1ed351c17b654258bd Mon Sep 17 00:00:00 2001 |
2 | From: Alexander Usyskin <alexander.usyskin@intel.com> | |
3 | Date: Fri, 8 Jan 2016 00:49:21 +0200 | |
4 | Subject: mei: wd: drop the watchdog code from the core mei driver | |
5 | ||
6 | Instead of integrating the iAMT watchdog in the mei core driver | |
7 | we will create a watchdog device on the mei client bus and | |
8 | create a driver for it. | |
9 | ||
10 | This patch removes the watchdog code from the mei core driver. | |
11 | ||
12 | Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> | |
13 | Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> | |
14 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
15 | --- | |
16 | drivers/misc/mei/Kconfig | 6 +- | |
17 | drivers/misc/mei/Makefile | 1 - | |
18 | drivers/misc/mei/client.c | 12 +- | |
19 | drivers/misc/mei/client.h | 4 - | |
20 | drivers/misc/mei/init.c | 10 +- | |
21 | drivers/misc/mei/interrupt.c | 15 -- | |
22 | drivers/misc/mei/mei_dev.h | 61 +------ | |
23 | drivers/misc/mei/wd.c | 391 ------------------------------------------- | |
24 | 8 files changed, 9 insertions(+), 491 deletions(-) | |
25 | delete mode 100644 drivers/misc/mei/wd.c | |
26 | ||
27 | diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig | |
28 | index d23384d..c49e1d2 100644 | |
29 | --- a/drivers/misc/mei/Kconfig | |
30 | +++ b/drivers/misc/mei/Kconfig | |
31 | @@ -1,6 +1,6 @@ | |
32 | config INTEL_MEI | |
33 | tristate "Intel Management Engine Interface" | |
34 | - depends on X86 && PCI && WATCHDOG_CORE | |
35 | + depends on X86 && PCI | |
36 | help | |
37 | The Intel Management Engine (Intel ME) provides Manageability, | |
38 | Security and Media services for system containing Intel chipsets. | |
39 | @@ -12,7 +12,7 @@ config INTEL_MEI | |
40 | config INTEL_MEI_ME | |
41 | tristate "ME Enabled Intel Chipsets" | |
42 | select INTEL_MEI | |
43 | - depends on X86 && PCI && WATCHDOG_CORE | |
44 | + depends on X86 && PCI | |
45 | help | |
46 | MEI support for ME Enabled Intel chipsets. | |
47 | ||
48 | @@ -37,7 +37,7 @@ config INTEL_MEI_ME | |
49 | config INTEL_MEI_TXE | |
50 | tristate "Intel Trusted Execution Environment with ME Interface" | |
51 | select INTEL_MEI | |
52 | - depends on X86 && PCI && WATCHDOG_CORE | |
53 | + depends on X86 && PCI | |
54 | help | |
55 | MEI Support for Trusted Execution Environment device on Intel SoCs | |
56 | ||
57 | diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile | |
58 | index 01447ca..59e6b0a 100644 | |
59 | --- a/drivers/misc/mei/Makefile | |
60 | +++ b/drivers/misc/mei/Makefile | |
61 | @@ -9,7 +9,6 @@ mei-objs += interrupt.o | |
62 | mei-objs += client.o | |
63 | mei-objs += main.o | |
64 | mei-objs += amthif.o | |
65 | -mei-objs += wd.o | |
66 | mei-objs += bus.o | |
67 | mei-objs += bus-fixup.o | |
68 | mei-$(CONFIG_DEBUG_FS) += debugfs.o | |
69 | diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c | |
70 | index 72e3261..e069fca 100644 | |
71 | --- a/drivers/misc/mei/client.c | |
72 | +++ b/drivers/misc/mei/client.c | |
73 | @@ -648,7 +648,7 @@ int mei_cl_unlink(struct mei_cl *cl) | |
74 | if (!cl) | |
75 | return 0; | |
76 | ||
77 | - /* wd and amthif might not be initialized */ | |
78 | + /* amthif might not be initialized */ | |
79 | if (!cl->dev) | |
80 | return 0; | |
81 | ||
82 | @@ -679,17 +679,11 @@ void mei_host_client_init(struct work_struct *work) | |
83 | ||
84 | mutex_lock(&dev->device_lock); | |
85 | ||
86 | - | |
87 | me_cl = mei_me_cl_by_uuid(dev, &mei_amthif_guid); | |
88 | if (me_cl) | |
89 | mei_amthif_host_init(dev, me_cl); | |
90 | mei_me_cl_put(me_cl); | |
91 | ||
92 | - me_cl = mei_me_cl_by_uuid(dev, &mei_wd_guid); | |
93 | - if (me_cl) | |
94 | - mei_wd_host_init(dev, me_cl); | |
95 | - mei_me_cl_put(me_cl); | |
96 | - | |
97 | dev->dev_state = MEI_DEV_ENABLED; | |
98 | dev->reset_count = 0; | |
99 | mutex_unlock(&dev->device_lock); | |
100 | @@ -1153,7 +1147,7 @@ err: | |
101 | * | |
102 | * Return: 1 if mei_flow_ctrl_creds >0, 0 - otherwise. | |
103 | */ | |
104 | -int mei_cl_flow_ctrl_creds(struct mei_cl *cl) | |
105 | +static int mei_cl_flow_ctrl_creds(struct mei_cl *cl) | |
106 | { | |
107 | int rets; | |
108 | ||
109 | @@ -1186,7 +1180,7 @@ int mei_cl_flow_ctrl_creds(struct mei_cl *cl) | |
110 | * 0 on success | |
111 | * -EINVAL when ctrl credits are <= 0 | |
112 | */ | |
113 | -int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) | |
114 | +static int mei_cl_flow_ctrl_reduce(struct mei_cl *cl) | |
115 | { | |
116 | if (WARN_ON(!cl || !cl->me_cl)) | |
117 | return -EINVAL; | |
118 | diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h | |
119 | index 04e1aa3..2e90a25 100644 | |
120 | --- a/drivers/misc/mei/client.h | |
121 | +++ b/drivers/misc/mei/client.h | |
122 | @@ -18,7 +18,6 @@ | |
123 | #define _MEI_CLIENT_H_ | |
124 | ||
125 | #include <linux/types.h> | |
126 | -#include <linux/watchdog.h> | |
127 | #include <linux/poll.h> | |
128 | #include <linux/mei.h> | |
129 | ||
130 | @@ -120,9 +119,6 @@ struct mei_cl_cb *mei_cl_alloc_cb(struct mei_cl *cl, size_t length, | |
131 | enum mei_cb_file_ops type, struct file *fp); | |
132 | int mei_cl_flush_queues(struct mei_cl *cl, const struct file *fp); | |
133 | ||
134 | -int mei_cl_flow_ctrl_creds(struct mei_cl *cl); | |
135 | - | |
136 | -int mei_cl_flow_ctrl_reduce(struct mei_cl *cl); | |
137 | /* | |
138 | * MEI input output function prototype | |
139 | */ | |
140 | diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c | |
141 | index 3edafc8..46a4302 100644 | |
142 | --- a/drivers/misc/mei/init.c | |
143 | +++ b/drivers/misc/mei/init.c | |
144 | @@ -156,8 +156,7 @@ int mei_reset(struct mei_device *dev) | |
145 | mei_cl_all_wakeup(dev); | |
146 | ||
147 | /* remove entry if already in list */ | |
148 | - dev_dbg(dev->dev, "remove iamthif and wd from the file list.\n"); | |
149 | - mei_cl_unlink(&dev->wd_cl); | |
150 | + dev_dbg(dev->dev, "remove iamthif from the file list.\n"); | |
151 | mei_cl_unlink(&dev->iamthif_cl); | |
152 | mei_amthif_reset_params(dev); | |
153 | } | |
154 | @@ -165,7 +164,6 @@ int mei_reset(struct mei_device *dev) | |
155 | mei_hbm_reset(dev); | |
156 | ||
157 | dev->rd_msg_hdr = 0; | |
158 | - dev->wd_pending = false; | |
159 | ||
160 | if (ret) { | |
161 | dev_err(dev->dev, "hw_reset failed ret = %d\n", ret); | |
162 | @@ -335,16 +333,12 @@ void mei_stop(struct mei_device *dev) | |
163 | ||
164 | mutex_lock(&dev->device_lock); | |
165 | ||
166 | - mei_wd_stop(dev); | |
167 | - | |
168 | dev->dev_state = MEI_DEV_POWER_DOWN; | |
169 | mei_reset(dev); | |
170 | /* move device to disabled state unconditionally */ | |
171 | dev->dev_state = MEI_DEV_DISABLED; | |
172 | ||
173 | mutex_unlock(&dev->device_lock); | |
174 | - | |
175 | - mei_watchdog_unregister(dev); | |
176 | } | |
177 | EXPORT_SYMBOL_GPL(mei_stop); | |
178 | ||
179 | @@ -394,7 +388,6 @@ void mei_device_init(struct mei_device *dev, | |
180 | init_waitqueue_head(&dev->wait_hw_ready); | |
181 | init_waitqueue_head(&dev->wait_pg); | |
182 | init_waitqueue_head(&dev->wait_hbm_start); | |
183 | - init_waitqueue_head(&dev->wait_stop_wd); | |
184 | dev->dev_state = MEI_DEV_INITIALIZING; | |
185 | dev->reset_count = 0; | |
186 | ||
187 | @@ -407,7 +400,6 @@ void mei_device_init(struct mei_device *dev, | |
188 | INIT_WORK(&dev->init_work, mei_host_client_init); | |
189 | INIT_WORK(&dev->reset_work, mei_reset_work); | |
190 | ||
191 | - INIT_LIST_HEAD(&dev->wd_cl.link); | |
192 | INIT_LIST_HEAD(&dev->iamthif_cl.link); | |
193 | mei_io_list_init(&dev->amthif_cmd_list); | |
194 | mei_io_list_init(&dev->amthif_rd_complete_list); | |
195 | diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c | |
196 | index 64b568a..6340dee 100644 | |
197 | --- a/drivers/misc/mei/interrupt.c | |
198 | +++ b/drivers/misc/mei/interrupt.c | |
199 | @@ -360,21 +360,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |
200 | list_move_tail(&cb->list, &cmpl_list->list); | |
201 | } | |
202 | ||
203 | - if (dev->wd_state == MEI_WD_STOPPING) { | |
204 | - dev->wd_state = MEI_WD_IDLE; | |
205 | - wake_up(&dev->wait_stop_wd); | |
206 | - } | |
207 | - | |
208 | - if (mei_cl_is_connected(&dev->wd_cl)) { | |
209 | - if (dev->wd_pending && | |
210 | - mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { | |
211 | - ret = mei_wd_send(dev); | |
212 | - if (ret) | |
213 | - return ret; | |
214 | - dev->wd_pending = false; | |
215 | - } | |
216 | - } | |
217 | - | |
218 | /* complete control write list CB */ | |
219 | dev_dbg(dev->dev, "complete control write list cb.\n"); | |
220 | list_for_each_entry_safe(cb, next, &dev->ctrl_wr_list.list, list) { | |
221 | diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h | |
222 | index b54d9d9..da61326 100644 | |
223 | --- a/drivers/misc/mei/mei_dev.h | |
224 | +++ b/drivers/misc/mei/mei_dev.h | |
225 | @@ -18,7 +18,7 @@ | |
226 | #define _MEI_DEV_H_ | |
227 | ||
228 | #include <linux/types.h> | |
229 | -#include <linux/watchdog.h> | |
230 | +#include <linux/cdev.h> | |
231 | #include <linux/poll.h> | |
232 | #include <linux/mei.h> | |
233 | #include <linux/mei_cl_bus.h> | |
234 | @@ -26,33 +26,13 @@ | |
235 | #include "hw.h" | |
236 | #include "hbm.h" | |
237 | ||
238 | -/* | |
239 | - * watch dog definition | |
240 | - */ | |
241 | -#define MEI_WD_HDR_SIZE 4 | |
242 | -#define MEI_WD_STOP_MSG_SIZE MEI_WD_HDR_SIZE | |
243 | -#define MEI_WD_START_MSG_SIZE (MEI_WD_HDR_SIZE + 16) | |
244 | - | |
245 | -#define MEI_WD_DEFAULT_TIMEOUT 120 /* seconds */ | |
246 | -#define MEI_WD_MIN_TIMEOUT 120 /* seconds */ | |
247 | -#define MEI_WD_MAX_TIMEOUT 65535 /* seconds */ | |
248 | - | |
249 | -#define MEI_WD_STOP_TIMEOUT 10 /* msecs */ | |
250 | - | |
251 | -#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0) | |
252 | - | |
253 | -#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) | |
254 | - | |
255 | ||
256 | /* | |
257 | * AMTHI Client UUID | |
258 | */ | |
259 | extern const uuid_le mei_amthif_guid; | |
260 | ||
261 | -/* | |
262 | - * Watchdog Client UUID | |
263 | - */ | |
264 | -extern const uuid_le mei_wd_guid; | |
265 | +#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) | |
266 | ||
267 | /* | |
268 | * Number of Maximum MEI Clients | |
269 | @@ -78,7 +58,6 @@ extern const uuid_le mei_wd_guid; | |
270 | */ | |
271 | #define MEI_HOST_CLIENT_ID_ANY (-1) | |
272 | #define MEI_HBM_HOST_CLIENT_ID 0 /* not used, just for documentation */ | |
273 | -#define MEI_WD_HOST_CLIENT_ID 1 | |
274 | #define MEI_IAMTHIF_HOST_CLIENT_ID 2 | |
275 | ||
276 | ||
277 | @@ -123,12 +102,6 @@ enum mei_file_transaction_states { | |
278 | MEI_READ_COMPLETE | |
279 | }; | |
280 | ||
281 | -enum mei_wd_states { | |
282 | - MEI_WD_IDLE, | |
283 | - MEI_WD_RUNNING, | |
284 | - MEI_WD_STOPPING, | |
285 | -}; | |
286 | - | |
287 | /** | |
288 | * enum mei_cb_file_ops - file operation associated with the callback | |
289 | * @MEI_FOP_READ: read | |
290 | @@ -404,7 +377,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); | |
291 | * @wait_hw_ready : wait queue for receive HW ready message form FW | |
292 | * @wait_pg : wait queue for receive PG message from FW | |
293 | * @wait_hbm_start : wait queue for receive HBM start message from FW | |
294 | - * @wait_stop_wd : wait queue for receive WD stop message from FW | |
295 | * | |
296 | * @reset_count : number of consecutive resets | |
297 | * @dev_state : device state | |
298 | @@ -435,12 +407,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); | |
299 | * | |
300 | * @allow_fixed_address: allow user space to connect a fixed client | |
301 | * | |
302 | - * @wd_cl : watchdog client | |
303 | - * @wd_state : watchdog client state | |
304 | - * @wd_pending : watchdog command is pending | |
305 | - * @wd_timeout : watchdog expiration timeout | |
306 | - * @wd_data : watchdog message buffer | |
307 | - * | |
308 | * @amthif_cmd_list : amthif list for cmd waiting | |
309 | * @amthif_rd_complete_list : amthif list for reading completed cmd data | |
310 | * @iamthif_file_object : file for current amthif operation | |
311 | @@ -486,7 +452,6 @@ struct mei_device { | |
312 | wait_queue_head_t wait_hw_ready; | |
313 | wait_queue_head_t wait_pg; | |
314 | wait_queue_head_t wait_hbm_start; | |
315 | - wait_queue_head_t wait_stop_wd; | |
316 | ||
317 | /* | |
318 | * mei device states | |
319 | @@ -531,13 +496,6 @@ struct mei_device { | |
320 | ||
321 | bool allow_fixed_address; | |
322 | ||
323 | - struct mei_cl wd_cl; | |
324 | - enum mei_wd_states wd_state; | |
325 | - bool wd_pending; | |
326 | - u16 wd_timeout; | |
327 | - unsigned char wd_data[MEI_WD_START_MSG_SIZE]; | |
328 | - | |
329 | - | |
330 | /* amthif list for cmd waiting */ | |
331 | struct mei_cl_cb amthif_cmd_list; | |
332 | /* driver managed amthif list for reading completed amthif cmd data */ | |
333 | @@ -649,21 +607,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, | |
334 | struct mei_cl_cb *complete_list); | |
335 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); | |
336 | ||
337 | -int mei_wd_send(struct mei_device *dev); | |
338 | -int mei_wd_stop(struct mei_device *dev); | |
339 | -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl); | |
340 | -/* | |
341 | - * mei_watchdog_register - Registering watchdog interface | |
342 | - * once we got connection to the WD Client | |
343 | - * @dev: mei device | |
344 | - */ | |
345 | -int mei_watchdog_register(struct mei_device *dev); | |
346 | -/* | |
347 | - * mei_watchdog_unregister - Unregistering watchdog interface | |
348 | - * @dev: mei device | |
349 | - */ | |
350 | -void mei_watchdog_unregister(struct mei_device *dev); | |
351 | - | |
352 | /* | |
353 | * Register Access Function | |
354 | */ | |
355 | diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c | |
356 | deleted file mode 100644 | |
357 | index b346638..0000000 | |
358 | --- a/drivers/misc/mei/wd.c | |
359 | +++ /dev/null | |
360 | @@ -1,391 +0,0 @@ | |
361 | -/* | |
362 | - * | |
363 | - * Intel Management Engine Interface (Intel MEI) Linux driver | |
364 | - * Copyright (c) 2003-2012, Intel Corporation. | |
365 | - * | |
366 | - * This program is free software; you can redistribute it and/or modify it | |
367 | - * under the terms and conditions of the GNU General Public License, | |
368 | - * version 2, as published by the Free Software Foundation. | |
369 | - * | |
370 | - * This program is distributed in the hope it will be useful, but WITHOUT | |
371 | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
372 | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
373 | - * more details. | |
374 | - * | |
375 | - */ | |
376 | -#include <linux/kernel.h> | |
377 | -#include <linux/module.h> | |
378 | -#include <linux/moduleparam.h> | |
379 | -#include <linux/device.h> | |
380 | -#include <linux/sched.h> | |
381 | -#include <linux/watchdog.h> | |
382 | - | |
383 | -#include <linux/mei.h> | |
384 | - | |
385 | -#include "mei_dev.h" | |
386 | -#include "hbm.h" | |
387 | -#include "client.h" | |
388 | - | |
389 | -static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 }; | |
390 | -static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 }; | |
391 | - | |
392 | -/* | |
393 | - * AMT Watchdog Device | |
394 | - */ | |
395 | -#define INTEL_AMT_WATCHDOG_ID "INTCAMT" | |
396 | - | |
397 | -/* UUIDs for AMT F/W clients */ | |
398 | -const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89, | |
399 | - 0x9D, 0xA9, 0x15, 0x14, 0xCB, | |
400 | - 0x32, 0xAB); | |
401 | - | |
402 | -static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout) | |
403 | -{ | |
404 | - dev_dbg(dev->dev, "wd: set timeout=%d.\n", timeout); | |
405 | - memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE); | |
406 | - memcpy(dev->wd_data + MEI_WD_HDR_SIZE, &timeout, sizeof(u16)); | |
407 | -} | |
408 | - | |
409 | -/** | |
410 | - * mei_wd_host_init - connect to the watchdog client | |
411 | - * | |
412 | - * @dev: the device structure | |
413 | - * @me_cl: me client | |
414 | - * | |
415 | - * Return: -ENOTTY if wd client cannot be found | |
416 | - * -EIO if write has failed | |
417 | - * 0 on success | |
418 | - */ | |
419 | -int mei_wd_host_init(struct mei_device *dev, struct mei_me_client *me_cl) | |
420 | -{ | |
421 | - struct mei_cl *cl = &dev->wd_cl; | |
422 | - int ret; | |
423 | - | |
424 | - mei_cl_init(cl, dev); | |
425 | - | |
426 | - dev->wd_timeout = MEI_WD_DEFAULT_TIMEOUT; | |
427 | - dev->wd_state = MEI_WD_IDLE; | |
428 | - | |
429 | - ret = mei_cl_link(cl, MEI_WD_HOST_CLIENT_ID); | |
430 | - if (ret < 0) { | |
431 | - dev_info(dev->dev, "wd: failed link client\n"); | |
432 | - return ret; | |
433 | - } | |
434 | - | |
435 | - ret = mei_cl_connect(cl, me_cl, NULL); | |
436 | - if (ret) { | |
437 | - dev_err(dev->dev, "wd: failed to connect = %d\n", ret); | |
438 | - mei_cl_unlink(cl); | |
439 | - return ret; | |
440 | - } | |
441 | - | |
442 | - ret = mei_watchdog_register(dev); | |
443 | - if (ret) { | |
444 | - mei_cl_disconnect(cl); | |
445 | - mei_cl_unlink(cl); | |
446 | - } | |
447 | - return ret; | |
448 | -} | |
449 | - | |
450 | -/** | |
451 | - * mei_wd_send - sends watch dog message to fw. | |
452 | - * | |
453 | - * @dev: the device structure | |
454 | - * | |
455 | - * Return: 0 if success, | |
456 | - * -EIO when message send fails | |
457 | - * -EINVAL when invalid message is to be sent | |
458 | - * -ENODEV on flow control failure | |
459 | - */ | |
460 | -int mei_wd_send(struct mei_device *dev) | |
461 | -{ | |
462 | - struct mei_cl *cl = &dev->wd_cl; | |
463 | - struct mei_msg_hdr hdr; | |
464 | - int ret; | |
465 | - | |
466 | - hdr.host_addr = cl->host_client_id; | |
467 | - hdr.me_addr = mei_cl_me_id(cl); | |
468 | - hdr.msg_complete = 1; | |
469 | - hdr.reserved = 0; | |
470 | - hdr.internal = 0; | |
471 | - | |
472 | - if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_HDR_SIZE)) | |
473 | - hdr.length = MEI_WD_START_MSG_SIZE; | |
474 | - else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_HDR_SIZE)) | |
475 | - hdr.length = MEI_WD_STOP_MSG_SIZE; | |
476 | - else { | |
477 | - dev_err(dev->dev, "wd: invalid message is to be sent, aborting\n"); | |
478 | - return -EINVAL; | |
479 | - } | |
480 | - | |
481 | - ret = mei_write_message(dev, &hdr, dev->wd_data); | |
482 | - if (ret) { | |
483 | - dev_err(dev->dev, "wd: write message failed\n"); | |
484 | - return ret; | |
485 | - } | |
486 | - | |
487 | - ret = mei_cl_flow_ctrl_reduce(cl); | |
488 | - if (ret) { | |
489 | - dev_err(dev->dev, "wd: flow_ctrl_reduce failed.\n"); | |
490 | - return ret; | |
491 | - } | |
492 | - | |
493 | - return 0; | |
494 | -} | |
495 | - | |
496 | -/** | |
497 | - * mei_wd_stop - sends watchdog stop message to fw. | |
498 | - * | |
499 | - * @dev: the device structure | |
500 | - * | |
501 | - * Return: 0 if success | |
502 | - * on error: | |
503 | - * -EIO when message send fails | |
504 | - * -EINVAL when invalid message is to be sent | |
505 | - * -ETIME on message timeout | |
506 | - */ | |
507 | -int mei_wd_stop(struct mei_device *dev) | |
508 | -{ | |
509 | - struct mei_cl *cl = &dev->wd_cl; | |
510 | - int ret; | |
511 | - | |
512 | - if (!mei_cl_is_connected(cl) || | |
513 | - dev->wd_state != MEI_WD_RUNNING) | |
514 | - return 0; | |
515 | - | |
516 | - memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_STOP_MSG_SIZE); | |
517 | - | |
518 | - dev->wd_state = MEI_WD_STOPPING; | |
519 | - | |
520 | - ret = mei_cl_flow_ctrl_creds(cl); | |
521 | - if (ret < 0) | |
522 | - goto err; | |
523 | - | |
524 | - if (ret && mei_hbuf_acquire(dev)) { | |
525 | - ret = mei_wd_send(dev); | |
526 | - if (ret) | |
527 | - goto err; | |
528 | - dev->wd_pending = false; | |
529 | - } else { | |
530 | - dev->wd_pending = true; | |
531 | - } | |
532 | - | |
533 | - mutex_unlock(&dev->device_lock); | |
534 | - | |
535 | - ret = wait_event_timeout(dev->wait_stop_wd, | |
536 | - dev->wd_state == MEI_WD_IDLE, | |
537 | - msecs_to_jiffies(MEI_WD_STOP_TIMEOUT)); | |
538 | - mutex_lock(&dev->device_lock); | |
539 | - if (dev->wd_state != MEI_WD_IDLE) { | |
540 | - /* timeout */ | |
541 | - ret = -ETIME; | |
542 | - dev_warn(dev->dev, "wd: stop failed to complete ret=%d\n", ret); | |
543 | - goto err; | |
544 | - } | |
545 | - dev_dbg(dev->dev, "wd: stop completed after %u msec\n", | |
546 | - MEI_WD_STOP_TIMEOUT - jiffies_to_msecs(ret)); | |
547 | - return 0; | |
548 | -err: | |
549 | - return ret; | |
550 | -} | |
551 | - | |
552 | -/** | |
553 | - * mei_wd_ops_start - wd start command from the watchdog core. | |
554 | - * | |
555 | - * @wd_dev: watchdog device struct | |
556 | - * | |
557 | - * Return: 0 if success, negative errno code for failure | |
558 | - */ | |
559 | -static int mei_wd_ops_start(struct watchdog_device *wd_dev) | |
560 | -{ | |
561 | - struct mei_device *dev; | |
562 | - struct mei_cl *cl; | |
563 | - int err = -ENODEV; | |
564 | - | |
565 | - dev = watchdog_get_drvdata(wd_dev); | |
566 | - if (!dev) | |
567 | - return -ENODEV; | |
568 | - | |
569 | - cl = &dev->wd_cl; | |
570 | - | |
571 | - mutex_lock(&dev->device_lock); | |
572 | - | |
573 | - if (dev->dev_state != MEI_DEV_ENABLED) { | |
574 | - dev_dbg(dev->dev, "wd: dev_state != MEI_DEV_ENABLED dev_state = %s\n", | |
575 | - mei_dev_state_str(dev->dev_state)); | |
576 | - goto end_unlock; | |
577 | - } | |
578 | - | |
579 | - if (!mei_cl_is_connected(cl)) { | |
580 | - cl_dbg(dev, cl, "MEI Driver is not connected to Watchdog Client\n"); | |
581 | - goto end_unlock; | |
582 | - } | |
583 | - | |
584 | - mei_wd_set_start_timeout(dev, dev->wd_timeout); | |
585 | - | |
586 | - err = 0; | |
587 | -end_unlock: | |
588 | - mutex_unlock(&dev->device_lock); | |
589 | - return err; | |
590 | -} | |
591 | - | |
592 | -/** | |
593 | - * mei_wd_ops_stop - wd stop command from the watchdog core. | |
594 | - * | |
595 | - * @wd_dev: watchdog device struct | |
596 | - * | |
597 | - * Return: 0 if success, negative errno code for failure | |
598 | - */ | |
599 | -static int mei_wd_ops_stop(struct watchdog_device *wd_dev) | |
600 | -{ | |
601 | - struct mei_device *dev; | |
602 | - | |
603 | - dev = watchdog_get_drvdata(wd_dev); | |
604 | - if (!dev) | |
605 | - return -ENODEV; | |
606 | - | |
607 | - mutex_lock(&dev->device_lock); | |
608 | - mei_wd_stop(dev); | |
609 | - mutex_unlock(&dev->device_lock); | |
610 | - | |
611 | - return 0; | |
612 | -} | |
613 | - | |
614 | -/** | |
615 | - * mei_wd_ops_ping - wd ping command from the watchdog core. | |
616 | - * | |
617 | - * @wd_dev: watchdog device struct | |
618 | - * | |
619 | - * Return: 0 if success, negative errno code for failure | |
620 | - */ | |
621 | -static int mei_wd_ops_ping(struct watchdog_device *wd_dev) | |
622 | -{ | |
623 | - struct mei_device *dev; | |
624 | - struct mei_cl *cl; | |
625 | - int ret; | |
626 | - | |
627 | - dev = watchdog_get_drvdata(wd_dev); | |
628 | - if (!dev) | |
629 | - return -ENODEV; | |
630 | - | |
631 | - cl = &dev->wd_cl; | |
632 | - | |
633 | - mutex_lock(&dev->device_lock); | |
634 | - | |
635 | - if (!mei_cl_is_connected(cl)) { | |
636 | - cl_err(dev, cl, "wd: not connected.\n"); | |
637 | - ret = -ENODEV; | |
638 | - goto end; | |
639 | - } | |
640 | - | |
641 | - dev->wd_state = MEI_WD_RUNNING; | |
642 | - | |
643 | - ret = mei_cl_flow_ctrl_creds(cl); | |
644 | - if (ret < 0) | |
645 | - goto end; | |
646 | - | |
647 | - /* Check if we can send the ping to HW*/ | |
648 | - if (ret && mei_hbuf_acquire(dev)) { | |
649 | - dev_dbg(dev->dev, "wd: sending ping\n"); | |
650 | - | |
651 | - ret = mei_wd_send(dev); | |
652 | - if (ret) | |
653 | - goto end; | |
654 | - dev->wd_pending = false; | |
655 | - } else { | |
656 | - dev->wd_pending = true; | |
657 | - } | |
658 | - | |
659 | -end: | |
660 | - mutex_unlock(&dev->device_lock); | |
661 | - return ret; | |
662 | -} | |
663 | - | |
664 | -/** | |
665 | - * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core. | |
666 | - * | |
667 | - * @wd_dev: watchdog device struct | |
668 | - * @timeout: timeout value to set | |
669 | - * | |
670 | - * Return: 0 if success, negative errno code for failure | |
671 | - */ | |
672 | -static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, | |
673 | - unsigned int timeout) | |
674 | -{ | |
675 | - struct mei_device *dev; | |
676 | - | |
677 | - dev = watchdog_get_drvdata(wd_dev); | |
678 | - if (!dev) | |
679 | - return -ENODEV; | |
680 | - | |
681 | - /* Check Timeout value */ | |
682 | - if (timeout < MEI_WD_MIN_TIMEOUT || timeout > MEI_WD_MAX_TIMEOUT) | |
683 | - return -EINVAL; | |
684 | - | |
685 | - mutex_lock(&dev->device_lock); | |
686 | - | |
687 | - dev->wd_timeout = timeout; | |
688 | - wd_dev->timeout = timeout; | |
689 | - mei_wd_set_start_timeout(dev, dev->wd_timeout); | |
690 | - | |
691 | - mutex_unlock(&dev->device_lock); | |
692 | - | |
693 | - return 0; | |
694 | -} | |
695 | - | |
696 | -/* | |
697 | - * Watchdog Device structs | |
698 | - */ | |
699 | -static const struct watchdog_ops wd_ops = { | |
700 | - .owner = THIS_MODULE, | |
701 | - .start = mei_wd_ops_start, | |
702 | - .stop = mei_wd_ops_stop, | |
703 | - .ping = mei_wd_ops_ping, | |
704 | - .set_timeout = mei_wd_ops_set_timeout, | |
705 | -}; | |
706 | -static const struct watchdog_info wd_info = { | |
707 | - .identity = INTEL_AMT_WATCHDOG_ID, | |
708 | - .options = WDIOF_KEEPALIVEPING | | |
709 | - WDIOF_SETTIMEOUT | | |
710 | - WDIOF_ALARMONLY, | |
711 | -}; | |
712 | - | |
713 | -static struct watchdog_device amt_wd_dev = { | |
714 | - .info = &wd_info, | |
715 | - .ops = &wd_ops, | |
716 | - .timeout = MEI_WD_DEFAULT_TIMEOUT, | |
717 | - .min_timeout = MEI_WD_MIN_TIMEOUT, | |
718 | - .max_timeout = MEI_WD_MAX_TIMEOUT, | |
719 | -}; | |
720 | - | |
721 | - | |
722 | -int mei_watchdog_register(struct mei_device *dev) | |
723 | -{ | |
724 | - | |
725 | - int ret; | |
726 | - | |
727 | - amt_wd_dev.parent = dev->dev; | |
728 | - /* unlock to perserve correct locking order */ | |
729 | - mutex_unlock(&dev->device_lock); | |
730 | - ret = watchdog_register_device(&amt_wd_dev); | |
731 | - mutex_lock(&dev->device_lock); | |
732 | - if (ret) { | |
733 | - dev_err(dev->dev, "wd: unable to register watchdog device = %d.\n", | |
734 | - ret); | |
735 | - return ret; | |
736 | - } | |
737 | - | |
738 | - dev_dbg(dev->dev, "wd: successfully register watchdog interface.\n"); | |
739 | - watchdog_set_drvdata(&amt_wd_dev, dev); | |
740 | - return 0; | |
741 | -} | |
742 | - | |
743 | -void mei_watchdog_unregister(struct mei_device *dev) | |
744 | -{ | |
745 | - if (watchdog_get_drvdata(&amt_wd_dev) == NULL) | |
746 | - return; | |
747 | - | |
748 | - watchdog_set_drvdata(&amt_wd_dev, NULL); | |
749 | - watchdog_unregister_device(&amt_wd_dev); | |
750 | -} | |
751 | - | |
752 | -- | |
753 | cgit v0.12 | |
754 |