aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/driver.c
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-06 23:34:13 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-19 02:56:18 -0400
commitb9ee95010bee6c0e17d18bc9d9c0cfab6e8cb73a (patch)
treed1fd6706e054bb337d3ac79e96e32d2ec5145047 /drivers/net/wimax/i2400m/driver.c
parent5eeae35b9a2e304fc4ae3d9eed63afeea23b482c (diff)
wimax/i2400m: fix deadlock: don't do BUS reset under i2400m->init_mutex
Since the addition of the pre/post reset handlers, it became clear that we cannot do a I2400M-RT-BUS type reset while holding the init_mutex, as in the case of USB, it will deadlock when trying to call i2400m_pre_reset(). Thus, the following changes: - clarify the fact that calling bus_reset() w/ I2400M_RT_BUS while holding init_mutex is a no-no. - i2400m_dev_reset_handle() will do a BUS reset to recover a gone device after unlocking init_mutex. - in the USB reset implementation, when cold and warm reset fails, fallback to QUEUING a usb reset, not executing a USB reset, so it happens from another context and does not deadlock. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m/driver.c')
-rw-r--r--drivers/net/wimax/i2400m/driver.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index 810eda7dbdba..10673af5a7f0 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -765,9 +765,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)
765 wmb(); /* see i2400m->updown's documentation */ 765 wmb(); /* see i2400m->updown's documentation */
766 dev_err(dev, "%s: cannot start the device: %d\n", 766 dev_err(dev, "%s: cannot start the device: %d\n",
767 reason, result); 767 reason, result);
768 result = i2400m->bus_reset(i2400m, I2400M_RT_BUS); 768 result = -EUCLEAN;
769 if (result >= 0)
770 result = -ENODEV;
771 } 769 }
772out_unlock: 770out_unlock:
773 if (i2400m->reset_ctx) { 771 if (i2400m->reset_ctx) {
@@ -775,6 +773,12 @@ out_unlock:
775 complete(&ctx->completion); 773 complete(&ctx->completion);
776 } 774 }
777 mutex_unlock(&i2400m->init_mutex); 775 mutex_unlock(&i2400m->init_mutex);
776 if (result == -EUCLEAN) {
777 /* ops, need to clean up [w/ init_mutex not held] */
778 result = i2400m->bus_reset(i2400m, I2400M_RT_BUS);
779 if (result >= 0)
780 result = -ENODEV;
781 }
778out: 782out:
779 i2400m_put(i2400m); 783 i2400m_put(i2400m);
780 kfree(iw); 784 kfree(iw);