aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-03-11 12:27:03 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-15 14:10:49 -0400
commitaafae7ecd80181983403de13db0b4895acdc233d (patch)
treed806144f3b33681fca6f7944f96c9d1aba2dd63e /drivers/misc/mei
parentc8c8d080ed94cea6757f2d781b6e360a74b256fd (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.c45
-rw-r--r--drivers/misc/mei/init.c16
-rw-r--r--drivers/misc/mei/mei_dev.h16
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
225static 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
245static 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}
522static const struct mei_hw_ops mei_me_hw_ops = { 549static 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
27const char *mei_dev_state_str(int state) 28const 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 */
238struct mei_hw_ops { 238struct 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
471static inline void mei_hw_start(struct mei_device *dev)
472{
473 dev->ops->hw_start(dev);
474}
475
468static inline void mei_clear_interrupts(struct mei_device *dev) 476static 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
483static inline void mei_host_set_ready(struct mei_device *dev)
484{
485 dev->ops->host_set_ready(dev);
486}
487static inline bool mei_host_is_ready(struct mei_device *dev) 491static 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);