aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-04-18 16:03:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-04-19 13:58:21 -0400
commit9b0d5efc421ac79d9a6d97c681eff93288093784 (patch)
treefcde453f66d5eb63dcea84ba9e04f9381ecd1e08 /drivers/misc
parent3a189b3ba027d4fe79100f728e19e935377f2e60 (diff)
mei: revamp hbm state machine
1. Rename init_clients_state to hbm_state and use MEI_HBM_ prefix for HBM states 2. Remove recvd_msg and use hbm state for synchronizing hbm protocol has successful start. We can wake up the hbm event from start response handler and remove the hack from the interrupt thread 3. mei_hbm_start_wait function encapsulate start completion waiting Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/hbm.c53
-rw-r--r--drivers/misc/mei/hbm.h25
-rw-r--r--drivers/misc/mei/hw-me.c12
-rw-r--r--drivers/misc/mei/init.c22
-rw-r--r--drivers/misc/mei/interrupt.c4
-rw-r--r--drivers/misc/mei/main.c2
-rw-r--r--drivers/misc/mei/mei_dev.h13
7 files changed, 72 insertions, 59 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index de7f5ba3194f..4de80d9b7c45 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -123,12 +123,33 @@ static bool is_treat_specially_client(struct mei_cl *cl,
123 return false; 123 return false;
124} 124}
125 125
126int mei_hbm_start_wait(struct mei_device *dev)
127{
128 int ret;
129 if (dev->hbm_state > MEI_HBM_START)
130 return 0;
131
132 mutex_unlock(&dev->device_lock);
133 ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
134 dev->hbm_state == MEI_HBM_IDLE ||
135 dev->hbm_state > MEI_HBM_START,
136 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
137 mutex_lock(&dev->device_lock);
138
139 if (ret <= 0 && (dev->hbm_state <= MEI_HBM_START)) {
140 dev->hbm_state = MEI_HBM_IDLE;
141 dev_err(&dev->pdev->dev, "wating for mei start failed\n");
142 return -ETIMEDOUT;
143 }
144 return 0;
145}
146
126/** 147/**
127 * mei_hbm_start_req - sends start request message. 148 * mei_hbm_start_req - sends start request message.
128 * 149 *
129 * @dev: the device structure 150 * @dev: the device structure
130 */ 151 */
131void mei_hbm_start_req(struct mei_device *dev) 152int mei_hbm_start_req(struct mei_device *dev)
132{ 153{
133 struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; 154 struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
134 struct hbm_host_version_request *start_req; 155 struct hbm_host_version_request *start_req;
@@ -143,18 +164,19 @@ void mei_hbm_start_req(struct mei_device *dev)
143 start_req->host_version.major_version = HBM_MAJOR_VERSION; 164 start_req->host_version.major_version = HBM_MAJOR_VERSION;
144 start_req->host_version.minor_version = HBM_MINOR_VERSION; 165 start_req->host_version.minor_version = HBM_MINOR_VERSION;
145 166
146 dev->recvd_msg = false; 167 dev->hbm_state = MEI_HBM_IDLE;
147 if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) { 168 if (mei_write_message(dev, mei_hdr, dev->wr_msg.data)) {
148 dev_err(&dev->pdev->dev, "version message writet failed\n"); 169 dev_err(&dev->pdev->dev, "version message writet failed\n");
149 dev->dev_state = MEI_DEV_RESETING; 170 dev->dev_state = MEI_DEV_RESETING;
150 mei_reset(dev, 1); 171 mei_reset(dev, 1);
172 return -ENODEV;
151 } 173 }
152 dev->init_clients_state = MEI_START_MESSAGE; 174 dev->hbm_state = MEI_HBM_START;
153 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 175 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
154 return ; 176 return 0;
155} 177}
156 178
157/** 179/*
158 * mei_hbm_enum_clients_req - sends enumeration client request message. 180 * mei_hbm_enum_clients_req - sends enumeration client request message.
159 * 181 *
160 * @dev: the device structure 182 * @dev: the device structure
@@ -178,7 +200,7 @@ static void mei_hbm_enum_clients_req(struct mei_device *dev)
178 dev_err(&dev->pdev->dev, "enumeration request write failed.\n"); 200 dev_err(&dev->pdev->dev, "enumeration request write failed.\n");
179 mei_reset(dev, 1); 201 mei_reset(dev, 1);
180 } 202 }
181 dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; 203 dev->hbm_state = MEI_HBM_ENUM_CLIENTS;
182 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 204 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT;
183 return; 205 return;
184} 206}
@@ -208,6 +230,7 @@ static int mei_hbm_prop_req(struct mei_device *dev)
208 230
209 /* We got all client properties */ 231 /* We got all client properties */
210 if (next_client_index == MEI_CLIENTS_MAX) { 232 if (next_client_index == MEI_CLIENTS_MAX) {
233 dev->hbm_state = MEI_HBM_STARTED;
211 schedule_work(&dev->init_work); 234 schedule_work(&dev->init_work);
212 235
213 return 0; 236 return 0;
@@ -542,27 +565,28 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
542 dev->version = version_res->me_max_version; 565 dev->version = version_res->me_max_version;
543 dev_dbg(&dev->pdev->dev, "version mismatch.\n"); 566 dev_dbg(&dev->pdev->dev, "version mismatch.\n");
544 567
568 dev->hbm_state = MEI_HBM_STOP;
545 mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, 569 mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr,
546 dev->wr_msg.data); 570 dev->wr_msg.data);
547 mei_write_message(dev, &dev->wr_msg.hdr, 571 mei_write_message(dev, &dev->wr_msg.hdr,
548 dev->wr_msg.data); 572 dev->wr_msg.data);
573
549 return; 574 return;
550 } 575 }
551 576
552 dev->version.major_version = HBM_MAJOR_VERSION; 577 dev->version.major_version = HBM_MAJOR_VERSION;
553 dev->version.minor_version = HBM_MINOR_VERSION; 578 dev->version.minor_version = HBM_MINOR_VERSION;
554 if (dev->dev_state == MEI_DEV_INIT_CLIENTS && 579 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
555 dev->init_clients_state == MEI_START_MESSAGE) { 580 dev->hbm_state == MEI_HBM_START) {
556 dev->init_clients_timer = 0; 581 dev->init_clients_timer = 0;
557 mei_hbm_enum_clients_req(dev); 582 mei_hbm_enum_clients_req(dev);
558 } else { 583 } else {
559 dev->recvd_msg = false;
560 dev_err(&dev->pdev->dev, "reset: wrong host start response\n"); 584 dev_err(&dev->pdev->dev, "reset: wrong host start response\n");
561 mei_reset(dev, 1); 585 mei_reset(dev, 1);
562 return; 586 return;
563 } 587 }
564 588
565 dev->recvd_msg = true; 589 wake_up_interruptible(&dev->wait_recvd_msg);
566 dev_dbg(&dev->pdev->dev, "host start response message received.\n"); 590 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
567 break; 591 break;
568 592
@@ -603,7 +627,7 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
603 } 627 }
604 628
605 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 629 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
606 dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) { 630 dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) {
607 dev_err(&dev->pdev->dev, "reset: unexpected properties response\n"); 631 dev_err(&dev->pdev->dev, "reset: unexpected properties response\n");
608 mei_reset(dev, 1); 632 mei_reset(dev, 1);
609 633
@@ -623,13 +647,12 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
623 enum_res = (struct hbm_host_enum_response *) mei_msg; 647 enum_res = (struct hbm_host_enum_response *) mei_msg;
624 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); 648 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
625 if (dev->dev_state == MEI_DEV_INIT_CLIENTS && 649 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
626 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { 650 dev->hbm_state == MEI_HBM_ENUM_CLIENTS) {
627 dev->init_clients_timer = 0; 651 dev->init_clients_timer = 0;
628 dev->me_client_presentation_num = 0; 652 dev->me_client_presentation_num = 0;
629 dev->me_client_index = 0; 653 dev->me_client_index = 0;
630 mei_hbm_me_cl_allocate(dev); 654 mei_hbm_me_cl_allocate(dev);
631 dev->init_clients_state = 655 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES;
632 MEI_CLIENT_PROPERTIES_MESSAGE;
633 656
634 /* first property reqeust */ 657 /* first property reqeust */
635 mei_hbm_prop_req(dev); 658 mei_hbm_prop_req(dev);
@@ -641,6 +664,9 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
641 break; 664 break;
642 665
643 case HOST_STOP_RES_CMD: 666 case HOST_STOP_RES_CMD:
667
668 if (dev->hbm_state != MEI_HBM_STOP)
669 dev_err(&dev->pdev->dev, "unexpected stop response hbm.\n");
644 dev->dev_state = MEI_DEV_DISABLED; 670 dev->dev_state = MEI_DEV_DISABLED;
645 dev_info(&dev->pdev->dev, "reset: FW stop response.\n"); 671 dev_info(&dev->pdev->dev, "reset: FW stop response.\n");
646 mei_reset(dev, 1); 672 mei_reset(dev, 1);
@@ -654,6 +680,7 @@ void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
654 680
655 case ME_STOP_REQ_CMD: 681 case ME_STOP_REQ_CMD:
656 682
683 dev->hbm_state = MEI_HBM_STOP;
657 mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr, 684 mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr,
658 dev->wr_ext_msg.data); 685 dev->wr_ext_msg.data);
659 break; 686 break;
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h
index b552afbaf85c..e80dc24ef3e2 100644
--- a/drivers/misc/mei/hbm.h
+++ b/drivers/misc/mei/hbm.h
@@ -17,6 +17,27 @@
17#ifndef _MEI_HBM_H_ 17#ifndef _MEI_HBM_H_
18#define _MEI_HBM_H_ 18#define _MEI_HBM_H_
19 19
20struct mei_device;
21struct mei_msg_hdr;
22struct mei_cl;
23
24/**
25 * enum mei_hbm_state - host bus message protocol state
26 *
27 * @MEI_HBM_IDLE : protocol not started
28 * @MEI_HBM_START : start request message was sent
29 * @MEI_HBM_ENUM_CLIENTS : enumeration request was sent
30 * @MEI_HBM_CLIENT_PROPERTIES : acquiring clients properties
31 */
32enum mei_hbm_state {
33 MEI_HBM_IDLE = 0,
34 MEI_HBM_START,
35 MEI_HBM_ENUM_CLIENTS,
36 MEI_HBM_CLIENT_PROPERTIES,
37 MEI_HBM_STARTED,
38 MEI_HBM_STOP,
39};
40
20void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr); 41void mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr);
21 42
22static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length) 43static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length)
@@ -28,8 +49,8 @@ static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length)
28 hdr->reserved = 0; 49 hdr->reserved = 0;
29} 50}
30 51
31void mei_hbm_start_req(struct mei_device *dev); 52int mei_hbm_start_req(struct mei_device *dev);
32 53int mei_hbm_start_wait(struct mei_device *dev);
33int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); 54int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl);
34int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); 55int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl);
35int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); 56int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 5ad53ebf57b9..3d6dfa35b1d7 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -468,8 +468,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
468 struct mei_cl_cb complete_list; 468 struct mei_cl_cb complete_list;
469 s32 slots; 469 s32 slots;
470 int rets; 470 int rets;
471 bool bus_message_received;
472
473 471
474 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); 472 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
475 /* initialize our complete list */ 473 /* initialize our complete list */
@@ -525,17 +523,7 @@ end:
525 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); 523 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
526 dev->hbuf_is_ready = mei_hbuf_is_ready(dev); 524 dev->hbuf_is_ready = mei_hbuf_is_ready(dev);
527 525
528 bus_message_received = false;
529 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
530 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
531 bus_message_received = true;
532 }
533 mutex_unlock(&dev->device_lock); 526 mutex_unlock(&dev->device_lock);
534 if (bus_message_received) {
535 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
536 wake_up_interruptible(&dev->wait_recvd_msg);
537 bus_message_received = false;
538 }
539 527
540 mei_irq_compl_handler(dev, &complete_list); 528 mei_irq_compl_handler(dev, &complete_list);
541 529
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 4e102ad7ebc0..59159e05446c 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -80,8 +80,6 @@ EXPORT_SYMBOL_GPL(mei_device_init);
80 */ 80 */
81int mei_start(struct mei_device *dev) 81int mei_start(struct mei_device *dev)
82{ 82{
83 int ret = 0;
84
85 mutex_lock(&dev->device_lock); 83 mutex_lock(&dev->device_lock);
86 84
87 /* acknowledge interrupt and stop interupts */ 85 /* acknowledge interrupt and stop interupts */
@@ -89,29 +87,15 @@ int mei_start(struct mei_device *dev)
89 87
90 mei_hw_config(dev); 88 mei_hw_config(dev);
91 89
92 dev->recvd_msg = false;
93 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); 90 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
94 91
95 mei_reset(dev, 1); 92 mei_reset(dev, 1);
96 93
97 /* wait for ME to turn on ME_RDY */ 94 if (mei_hbm_start_wait(dev)) {
98 if (!dev->recvd_msg) { 95 dev_err(&dev->pdev->dev, "HBM haven't started");
99 mutex_unlock(&dev->device_lock);
100 ret = wait_event_interruptible_timeout(dev->wait_recvd_msg,
101 dev->recvd_msg,
102 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT));
103 mutex_lock(&dev->device_lock);
104 }
105
106 if (ret <= 0 && !dev->recvd_msg) {
107 dev->dev_state = MEI_DEV_DISABLED;
108 dev_dbg(&dev->pdev->dev,
109 "wait_event_interruptible_timeout failed"
110 "on wait for ME to turn on ME_RDY.\n");
111 goto err; 96 goto err;
112 } 97 }
113 98
114
115 if (!mei_host_is_ready(dev)) { 99 if (!mei_host_is_ready(dev)) {
116 dev_err(&dev->pdev->dev, "host is not ready.\n"); 100 dev_err(&dev->pdev->dev, "host is not ready.\n");
117 goto err; 101 goto err;
@@ -128,7 +112,6 @@ int mei_start(struct mei_device *dev)
128 goto err; 112 goto err;
129 } 113 }
130 114
131 dev->recvd_msg = false;
132 dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); 115 dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
133 116
134 mutex_unlock(&dev->device_lock); 117 mutex_unlock(&dev->device_lock);
@@ -158,6 +141,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
158 141
159 mei_hw_reset(dev, interrupts_enabled); 142 mei_hw_reset(dev, interrupts_enabled);
160 143
144 dev->hbm_state = MEI_HBM_IDLE;
161 145
162 if (dev->dev_state != MEI_DEV_INITIALIZING) { 146 if (dev->dev_state != MEI_DEV_INITIALIZING) {
163 if (dev->dev_state != MEI_DEV_DISABLED && 147 if (dev->dev_state != MEI_DEV_DISABLED &&
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 9ff8c61fe457..c1cc462cce0e 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -623,8 +623,8 @@ void mei_timer(struct work_struct *work)
623 if (dev->dev_state == MEI_DEV_INIT_CLIENTS) { 623 if (dev->dev_state == MEI_DEV_INIT_CLIENTS) {
624 if (dev->init_clients_timer) { 624 if (dev->init_clients_timer) {
625 if (--dev->init_clients_timer == 0) { 625 if (--dev->init_clients_timer == 0) {
626 dev_err(&dev->pdev->dev, "reset: init clients timeout ,init clients state = %d.\n", 626 dev_err(&dev->pdev->dev, "reset: init clients timeout hbm_state = %d.\n",
627 dev->init_clients_state); 627 dev->hbm_state);
628 mei_reset(dev, 1); 628 mei_reset(dev, 1);
629 } 629 }
630 } 630 }
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index cb11b36512b5..78b4da5ed96c 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -48,7 +48,7 @@
48 * 48 *
49 * @inode: pointer to inode structure 49 * @inode: pointer to inode structure
50 * @file: pointer to file structure 50 * @file: pointer to file structure
51 * 51 e
52 * returns 0 on success, <0 on error 52 * returns 0 on success, <0 on error
53 */ 53 */
54static int mei_open(struct inode *inode, struct file *file) 54static int mei_open(struct inode *inode, struct file *file)
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index cd5b6d4bbbd4..56dee56ab9cc 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -25,6 +25,7 @@
25 25
26#include "hw.h" 26#include "hw.h"
27#include "hw-me-regs.h" 27#include "hw-me-regs.h"
28#include "hbm.h"
28 29
29/* 30/*
30 * watch dog definition 31 * watch dog definition
@@ -104,13 +105,6 @@ enum mei_dev_state {
104 105
105const char *mei_dev_state_str(int state); 106const char *mei_dev_state_str(int state);
106 107
107/* init clients states*/
108enum mei_init_clients_states {
109 MEI_START_MESSAGE = 0,
110 MEI_ENUM_CLIENTS_MESSAGE,
111 MEI_CLIENT_PROPERTIES_MESSAGE
112};
113
114enum iamthif_states { 108enum iamthif_states {
115 MEI_IAMTHIF_IDLE, 109 MEI_IAMTHIF_IDLE,
116 MEI_IAMTHIF_WRITING, 110 MEI_IAMTHIF_WRITING,
@@ -338,6 +332,7 @@ struct mei_cl_device {
338/** 332/**
339 * struct mei_device - MEI private device struct 333 * struct mei_device - MEI private device struct
340 334
335 * @hbm_state - state of host bus message protocol
341 * @mem_addr - mem mapped base register address 336 * @mem_addr - mem mapped base register address
342 337
343 * @hbuf_depth - depth of hardware host/write buffer is slots 338 * @hbuf_depth - depth of hardware host/write buffer is slots
@@ -370,8 +365,6 @@ struct mei_device {
370 struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */ 365 struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
371 366
372 bool recvd_hw_ready; 367 bool recvd_hw_ready;
373 bool recvd_msg;
374
375 /* 368 /*
376 * waiting queue for receive message from FW 369 * waiting queue for receive message from FW
377 */ 370 */
@@ -383,7 +376,7 @@ struct mei_device {
383 * mei device states 376 * mei device states
384 */ 377 */
385 enum mei_dev_state dev_state; 378 enum mei_dev_state dev_state;
386 enum mei_init_clients_states init_clients_state; 379 enum mei_hbm_state hbm_state;
387 u16 init_clients_timer; 380 u16 init_clients_timer;
388 381
389 unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */ 382 unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */