aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2013-07-25 13:15:53 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-26 20:54:30 -0400
commitb950ac1dabfcbf97b99f26fa75f86087e1960aef (patch)
treed9ef0e00c79acedc8eebdd3d61a460d7bbff962f /drivers/misc
parent20138d6cb838aa01bb1b382dcb5f3d3a119ff2cb (diff)
mei: don't get stuck in select during reset
Clear pending connection after hw reset but before hw start and wake up the waiting task in poll. Signal POLLERR in select when device went through reset. Add wrapper mei_cl_is_connected for checking if the device and client are connected. 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/amthif.c14
-rw-r--r--drivers/misc/mei/client.c5
-rw-r--r--drivers/misc/mei/client.h7
-rw-r--r--drivers/misc/mei/init.c13
-rw-r--r--drivers/misc/mei/main.c22
5 files changed, 42 insertions, 19 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 749452f8e2f6..d0fdc134068a 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -418,15 +418,23 @@ unsigned int mei_amthif_poll(struct mei_device *dev,
418 struct file *file, poll_table *wait) 418 struct file *file, poll_table *wait)
419{ 419{
420 unsigned int mask = 0; 420 unsigned int mask = 0;
421 mutex_unlock(&dev->device_lock); 421
422 poll_wait(file, &dev->iamthif_cl.wait, wait); 422 poll_wait(file, &dev->iamthif_cl.wait, wait);
423
423 mutex_lock(&dev->device_lock); 424 mutex_lock(&dev->device_lock);
424 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE && 425 if (!mei_cl_is_connected(&dev->iamthif_cl)) {
425 dev->iamthif_file_object == file) { 426
427 mask = POLLERR;
428
429 } else if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
430 dev->iamthif_file_object == file) {
431
426 mask |= (POLLIN | POLLRDNORM); 432 mask |= (POLLIN | POLLRDNORM);
427 dev_dbg(&dev->pdev->dev, "run next amthif cb\n"); 433 dev_dbg(&dev->pdev->dev, "run next amthif cb\n");
428 mei_amthif_run_next_cmd(dev); 434 mei_amthif_run_next_cmd(dev);
429 } 435 }
436 mutex_unlock(&dev->device_lock);
437
430 return mask; 438 return mask;
431} 439}
432 440
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index af1e60205140..e0684b4d9a08 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -635,10 +635,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length)
635 635
636 dev = cl->dev; 636 dev = cl->dev;
637 637
638 if (cl->state != MEI_FILE_CONNECTED) 638 if (!mei_cl_is_connected(cl))
639 return -ENODEV;
640
641 if (dev->dev_state != MEI_DEV_ENABLED)
642 return -ENODEV; 639 return -ENODEV;
643 640
644 if (cl->read_cb) { 641 if (cl->read_cb) {
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 9bae4c724603..9eb031e92070 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -84,6 +84,13 @@ int mei_cl_flow_ctrl_reduce(struct mei_cl *cl);
84/* 84/*
85 * MEI input output function prototype 85 * MEI input output function prototype
86 */ 86 */
87static inline bool mei_cl_is_connected(struct mei_cl *cl)
88{
89 return (cl->dev &&
90 cl->dev->dev_state == MEI_DEV_ENABLED &&
91 cl->state == MEI_FILE_CONNECTED);
92}
93
87bool mei_cl_is_other_connecting(struct mei_cl *cl); 94bool mei_cl_is_other_connecting(struct mei_cl *cl);
88int mei_cl_disconnect(struct mei_cl *cl); 95int mei_cl_disconnect(struct mei_cl *cl);
89int mei_cl_connect(struct mei_cl *cl, struct file *file); 96int mei_cl_connect(struct mei_cl *cl, struct file *file);
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 7929e14627ba..557eed2a1595 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -149,12 +149,20 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
149 dev->hbm_state = MEI_HBM_IDLE; 149 dev->hbm_state = MEI_HBM_IDLE;
150 150
151 if (dev->dev_state != MEI_DEV_INITIALIZING) { 151 if (dev->dev_state != MEI_DEV_INITIALIZING) {
152
152 if (dev->dev_state != MEI_DEV_DISABLED && 153 if (dev->dev_state != MEI_DEV_DISABLED &&
153 dev->dev_state != MEI_DEV_POWER_DOWN) 154 dev->dev_state != MEI_DEV_POWER_DOWN)
154 dev->dev_state = MEI_DEV_RESETTING; 155 dev->dev_state = MEI_DEV_RESETTING;
155 156
157
158 /* remove all waiting requests */
159 mei_cl_all_write_clear(dev);
160
156 mei_cl_all_disconnect(dev); 161 mei_cl_all_disconnect(dev);
157 162
163 /* wake up all readings so they can be interrupted */
164 mei_cl_all_wakeup(dev);
165
158 /* remove entry if already in list */ 166 /* remove entry if already in list */
159 dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); 167 dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n");
160 mei_cl_unlink(&dev->wd_cl); 168 mei_cl_unlink(&dev->wd_cl);
@@ -195,11 +203,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
195 203
196 mei_hbm_start_req(dev); 204 mei_hbm_start_req(dev);
197 205
198 /* wake up all readings so they can be interrupted */
199 mei_cl_all_wakeup(dev);
200
201 /* remove all waiting requests */
202 mei_cl_all_write_clear(dev);
203} 206}
204EXPORT_SYMBOL_GPL(mei_reset); 207EXPORT_SYMBOL_GPL(mei_reset);
205 208
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 5e11b5b9b65d..173ff095be0d 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -625,24 +625,32 @@ static unsigned int mei_poll(struct file *file, poll_table *wait)
625 unsigned int mask = 0; 625 unsigned int mask = 0;
626 626
627 if (WARN_ON(!cl || !cl->dev)) 627 if (WARN_ON(!cl || !cl->dev))
628 return mask; 628 return POLLERR;
629 629
630 dev = cl->dev; 630 dev = cl->dev;
631 631
632 mutex_lock(&dev->device_lock); 632 mutex_lock(&dev->device_lock);
633 633
634 if (dev->dev_state != MEI_DEV_ENABLED) 634 if (!mei_cl_is_connected(cl)) {
635 goto out; 635 mask = POLLERR;
636
637
638 if (cl == &dev->iamthif_cl) {
639 mask = mei_amthif_poll(dev, file, wait);
640 goto out; 636 goto out;
641 } 637 }
642 638
643 mutex_unlock(&dev->device_lock); 639 mutex_unlock(&dev->device_lock);
640
641
642 if (cl == &dev->iamthif_cl)
643 return mei_amthif_poll(dev, file, wait);
644
644 poll_wait(file, &cl->tx_wait, wait); 645 poll_wait(file, &cl->tx_wait, wait);
646
645 mutex_lock(&dev->device_lock); 647 mutex_lock(&dev->device_lock);
648
649 if (!mei_cl_is_connected(cl)) {
650 mask = POLLERR;
651 goto out;
652 }
653
646 if (MEI_WRITE_COMPLETE == cl->writing_state) 654 if (MEI_WRITE_COMPLETE == cl->writing_state)
647 mask |= (POLLIN | POLLRDNORM); 655 mask |= (POLLIN | POLLRDNORM);
648 656