diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2013-03-11 12:27:03 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-03-15 14:10:49 -0400 |
commit | aafae7ecd80181983403de13db0b4895acdc233d (patch) | |
tree | d806144f3b33681fca6f7944f96c9d1aba2dd63e /drivers/misc/mei | |
parent | c8c8d080ed94cea6757f2d781b6e360a74b256fd (diff) |
mei: add hw start callback
This callback wraps up hardware dependent details
of the hardware initialization.
This callback also contains host ready setting
so we can remove host_set_ready callback
In ME we switch to waiting on event so
we can streamline the initialization flow.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/hw-me.c | 45 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 16 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 16 |
3 files changed, 62 insertions, 15 deletions
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index d21e5a761f2c..df9b43d81eea 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -222,6 +222,38 @@ static bool mei_me_hw_is_ready(struct mei_device *dev) | |||
222 | return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; | 222 | return (hw->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA; |
223 | } | 223 | } |
224 | 224 | ||
225 | static int mei_me_hw_ready_wait(struct mei_device *dev) | ||
226 | { | ||
227 | int err; | ||
228 | if (mei_me_hw_is_ready(dev)) | ||
229 | return 0; | ||
230 | |||
231 | mutex_unlock(&dev->device_lock); | ||
232 | err = wait_event_interruptible_timeout(dev->wait_hw_ready, | ||
233 | dev->recvd_hw_ready, MEI_INTEROP_TIMEOUT); | ||
234 | mutex_lock(&dev->device_lock); | ||
235 | if (!err && !dev->recvd_hw_ready) { | ||
236 | dev_err(&dev->pdev->dev, | ||
237 | "wait hw ready failed. status = 0x%x\n", err); | ||
238 | return -ETIMEDOUT; | ||
239 | } | ||
240 | |||
241 | dev->recvd_hw_ready = false; | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | static int mei_me_hw_start(struct mei_device *dev) | ||
246 | { | ||
247 | int ret = mei_me_hw_ready_wait(dev); | ||
248 | if (ret) | ||
249 | return ret; | ||
250 | dev_dbg(&dev->pdev->dev, "hw is ready\n"); | ||
251 | |||
252 | mei_me_host_set_ready(dev); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | |||
225 | /** | 257 | /** |
226 | * mei_hbuf_filled_slots - gets number of device filled buffer slots | 258 | * mei_hbuf_filled_slots - gets number of device filled buffer slots |
227 | * | 259 | * |
@@ -456,14 +488,9 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) | |||
456 | if (mei_hw_is_ready(dev)) { | 488 | if (mei_hw_is_ready(dev)) { |
457 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); | 489 | dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); |
458 | 490 | ||
459 | mei_host_set_ready(dev); | 491 | dev->recvd_hw_ready = true; |
460 | 492 | wake_up_interruptible(&dev->wait_hw_ready); | |
461 | dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); | ||
462 | /* link is established * start sending messages. */ | ||
463 | |||
464 | dev->dev_state = MEI_DEV_INIT_CLIENTS; | ||
465 | 493 | ||
466 | mei_hbm_start_req(dev); | ||
467 | mutex_unlock(&dev->device_lock); | 494 | mutex_unlock(&dev->device_lock); |
468 | return IRQ_HANDLED; | 495 | return IRQ_HANDLED; |
469 | } else { | 496 | } else { |
@@ -521,12 +548,12 @@ end: | |||
521 | } | 548 | } |
522 | static const struct mei_hw_ops mei_me_hw_ops = { | 549 | static const struct mei_hw_ops mei_me_hw_ops = { |
523 | 550 | ||
524 | .host_set_ready = mei_me_host_set_ready, | ||
525 | .host_is_ready = mei_me_host_is_ready, | 551 | .host_is_ready = mei_me_host_is_ready, |
526 | 552 | ||
527 | .hw_is_ready = mei_me_hw_is_ready, | 553 | .hw_is_ready = mei_me_hw_is_ready, |
528 | .hw_reset = mei_me_hw_reset, | 554 | .hw_reset = mei_me_hw_reset, |
529 | .hw_config = mei_me_hw_config, | 555 | .hw_config = mei_me_hw_config, |
556 | .hw_start = mei_me_hw_start, | ||
530 | 557 | ||
531 | .intr_clear = mei_me_intr_clear, | 558 | .intr_clear = mei_me_intr_clear, |
532 | .intr_enable = mei_me_intr_enable, | 559 | .intr_enable = mei_me_intr_enable, |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 6ec530168afb..fc3d97ce8300 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mei.h> | 22 | #include <linux/mei.h> |
23 | 23 | ||
24 | #include "mei_dev.h" | 24 | #include "mei_dev.h" |
25 | #include "hbm.h" | ||
25 | #include "client.h" | 26 | #include "client.h" |
26 | 27 | ||
27 | const char *mei_dev_state_str(int state) | 28 | const char *mei_dev_state_str(int state) |
@@ -47,6 +48,7 @@ void mei_device_init(struct mei_device *dev) | |||
47 | /* setup our list array */ | 48 | /* setup our list array */ |
48 | INIT_LIST_HEAD(&dev->file_list); | 49 | INIT_LIST_HEAD(&dev->file_list); |
49 | mutex_init(&dev->device_lock); | 50 | mutex_init(&dev->device_lock); |
51 | init_waitqueue_head(&dev->wait_hw_ready); | ||
50 | init_waitqueue_head(&dev->wait_recvd_msg); | 52 | init_waitqueue_head(&dev->wait_recvd_msg); |
51 | init_waitqueue_head(&dev->wait_stop_wd); | 53 | init_waitqueue_head(&dev->wait_stop_wd); |
52 | dev->dev_state = MEI_DEV_INITIALIZING; | 54 | dev->dev_state = MEI_DEV_INITIALIZING; |
@@ -176,6 +178,20 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
176 | dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", | 178 | dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", |
177 | mei_dev_state_str(dev->dev_state)); | 179 | mei_dev_state_str(dev->dev_state)); |
178 | 180 | ||
181 | if (!interrupts_enabled) { | ||
182 | dev_dbg(&dev->pdev->dev, "intr not enabled end of reset\n"); | ||
183 | return; | ||
184 | } | ||
185 | |||
186 | mei_hw_start(dev); | ||
187 | |||
188 | dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); | ||
189 | /* link is established * start sending messages. */ | ||
190 | |||
191 | dev->dev_state = MEI_DEV_INIT_CLIENTS; | ||
192 | |||
193 | mei_hbm_start_req(dev); | ||
194 | |||
179 | /* wake up all readings so they can be interrupted */ | 195 | /* wake up all readings so they can be interrupted */ |
180 | mei_cl_all_read_wakeup(dev); | 196 | mei_cl_all_read_wakeup(dev); |
181 | 197 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 09a2af4294a6..5c30857e91d5 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -213,11 +213,11 @@ struct mei_cl { | |||
213 | 213 | ||
214 | /** struct mei_hw_ops | 214 | /** struct mei_hw_ops |
215 | * | 215 | * |
216 | * @host_set_ready - notify FW that host side is ready | ||
217 | * @host_is_ready - query for host readiness | 216 | * @host_is_ready - query for host readiness |
218 | 217 | ||
219 | * @hw_is_ready - query if hw is ready | 218 | * @hw_is_ready - query if hw is ready |
220 | * @hw_reset - reset hw | 219 | * @hw_reset - reset hw |
220 | * @hw_start - start hw after reset | ||
221 | * @hw_config - configure hw | 221 | * @hw_config - configure hw |
222 | 222 | ||
223 | * @intr_clear - clear pending interrupts | 223 | * @intr_clear - clear pending interrupts |
@@ -237,11 +237,11 @@ struct mei_cl { | |||
237 | */ | 237 | */ |
238 | struct mei_hw_ops { | 238 | struct mei_hw_ops { |
239 | 239 | ||
240 | void (*host_set_ready) (struct mei_device *dev); | ||
241 | bool (*host_is_ready) (struct mei_device *dev); | 240 | bool (*host_is_ready) (struct mei_device *dev); |
242 | 241 | ||
243 | bool (*hw_is_ready) (struct mei_device *dev); | 242 | bool (*hw_is_ready) (struct mei_device *dev); |
244 | void (*hw_reset) (struct mei_device *dev, bool enable); | 243 | void (*hw_reset) (struct mei_device *dev, bool enable); |
244 | int (*hw_start) (struct mei_device *dev); | ||
245 | void (*hw_config) (struct mei_device *dev); | 245 | void (*hw_config) (struct mei_device *dev); |
246 | 246 | ||
247 | void (*intr_clear) (struct mei_device *dev); | 247 | void (*intr_clear) (struct mei_device *dev); |
@@ -296,11 +296,14 @@ struct mei_device { | |||
296 | */ | 296 | */ |
297 | struct mutex device_lock; /* device lock */ | 297 | struct mutex device_lock; /* device lock */ |
298 | struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */ | 298 | struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */ |
299 | |||
300 | bool recvd_hw_ready; | ||
299 | bool recvd_msg; | 301 | bool recvd_msg; |
300 | 302 | ||
301 | /* | 303 | /* |
302 | * waiting queue for receive message from FW | 304 | * waiting queue for receive message from FW |
303 | */ | 305 | */ |
306 | wait_queue_head_t wait_hw_ready; | ||
304 | wait_queue_head_t wait_recvd_msg; | 307 | wait_queue_head_t wait_recvd_msg; |
305 | wait_queue_head_t wait_stop_wd; | 308 | wait_queue_head_t wait_stop_wd; |
306 | 309 | ||
@@ -465,6 +468,11 @@ static inline void mei_hw_reset(struct mei_device *dev, bool enable) | |||
465 | dev->ops->hw_reset(dev, enable); | 468 | dev->ops->hw_reset(dev, enable); |
466 | } | 469 | } |
467 | 470 | ||
471 | static inline void mei_hw_start(struct mei_device *dev) | ||
472 | { | ||
473 | dev->ops->hw_start(dev); | ||
474 | } | ||
475 | |||
468 | static inline void mei_clear_interrupts(struct mei_device *dev) | 476 | static inline void mei_clear_interrupts(struct mei_device *dev) |
469 | { | 477 | { |
470 | dev->ops->intr_clear(dev); | 478 | dev->ops->intr_clear(dev); |
@@ -480,10 +488,6 @@ static inline void mei_disable_interrupts(struct mei_device *dev) | |||
480 | dev->ops->intr_disable(dev); | 488 | dev->ops->intr_disable(dev); |
481 | } | 489 | } |
482 | 490 | ||
483 | static inline void mei_host_set_ready(struct mei_device *dev) | ||
484 | { | ||
485 | dev->ops->host_set_ready(dev); | ||
486 | } | ||
487 | static inline bool mei_host_is_ready(struct mei_device *dev) | 491 | static inline bool mei_host_is_ready(struct mei_device *dev) |
488 | { | 492 | { |
489 | return dev->ops->host_is_ready(dev); | 493 | return dev->ops->host_is_ready(dev); |