aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-23 20:48:36 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-11-03 15:49:39 -0500
commitfae92216da87d1c78aa51c4503acb312a47266e9 (patch)
tree0df0784e265e6ec55eb0ed5566b8bf99e1dd2ba7 /drivers/net/wimax
parent02eb41ef2a8631022fd90e096c57562dec9e7a9a (diff)
wimax/i2400m: don't retry SDIO enable in probe() paths
The iwmc3200 has a quirk where retrying SDIO enable during the probe() path causes bad interactions with the TOP function controller that causes a reset storm. The workaround is simply not to retry an SDIO enable in said path (and still do in the reset / reinitialization paths). The driver does so by checking i2400ms->debugfs_dentry to see if it has been initialized; if not, it is in the probe() path. Document said fact in i2400ms->debugfs_entry. Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax')
-rw-r--r--drivers/net/wimax/i2400m/i2400m-sdio.h8
-rw-r--r--drivers/net/wimax/i2400m/sdio.c13
2 files changed, 20 insertions, 1 deletions
diff --git a/drivers/net/wimax/i2400m/i2400m-sdio.h b/drivers/net/wimax/i2400m/i2400m-sdio.h
index fba482c08d66..b9c4bed3b457 100644
--- a/drivers/net/wimax/i2400m/i2400m-sdio.h
+++ b/drivers/net/wimax/i2400m/i2400m-sdio.h
@@ -100,6 +100,14 @@ enum {
100 * @tx_workqueue: workqeueue used for data TX; we don't use the 100 * @tx_workqueue: workqeueue used for data TX; we don't use the
101 * system's workqueue as that might cause deadlocks with code in 101 * system's workqueue as that might cause deadlocks with code in
102 * the bus-generic driver. 102 * the bus-generic driver.
103 *
104 * @debugfs_dentry: dentry for the SDIO specific debugfs files
105 *
106 * Note this value is set to NULL upon destruction; this is
107 * because some routinges use it to determine if we are inside the
108 * probe() path or some other path. When debugfs is disabled,
109 * creation sets the dentry to '(void*) -ENODEV', which is valid
110 * for the test.
103 */ 111 */
104struct i2400ms { 112struct i2400ms {
105 struct i2400m i2400m; /* FIRST! See doc */ 113 struct i2400m i2400m; /* FIRST! See doc */
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 079f900e9ae5..e8ad85c7a799 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -159,6 +159,10 @@ function_enabled:
159/* 159/*
160 * Setup minimal device communication infrastructure needed to at 160 * Setup minimal device communication infrastructure needed to at
161 * least be able to update the firmware. 161 * least be able to update the firmware.
162 *
163 * Note the ugly trick: if we are in the probe path
164 * (i2400ms->debugfs_dentry == NULL), we only retry function
165 * enablement one, to avoid racing with the iwmc3200 top controller.
162 */ 166 */
163static 167static
164int i2400ms_bus_setup(struct i2400m *i2400m) 168int i2400ms_bus_setup(struct i2400m *i2400m)
@@ -168,6 +172,7 @@ int i2400ms_bus_setup(struct i2400m *i2400m)
168 container_of(i2400m, struct i2400ms, i2400m); 172 container_of(i2400m, struct i2400ms, i2400m);
169 struct device *dev = i2400m_dev(i2400m); 173 struct device *dev = i2400m_dev(i2400m);
170 struct sdio_func *func = i2400ms->func; 174 struct sdio_func *func = i2400ms->func;
175 int retries;
171 176
172 sdio_claim_host(func); 177 sdio_claim_host(func);
173 result = sdio_set_block_size(func, I2400MS_BLK_SIZE); 178 result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
@@ -177,7 +182,11 @@ int i2400ms_bus_setup(struct i2400m *i2400m)
177 goto error_set_blk_size; 182 goto error_set_blk_size;
178 } 183 }
179 184
180 result = i2400ms_enable_function(i2400ms, 1); 185 if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL)
186 retries = 0;
187 else
188 retries = 1;
189 result = i2400ms_enable_function(i2400ms, retries);
181 if (result < 0) { 190 if (result < 0) {
182 dev_err(dev, "Cannot enable SDIO function: %d\n", result); 191 dev_err(dev, "Cannot enable SDIO function: %d\n", result);
183 goto error_func_enable; 192 goto error_func_enable;
@@ -415,6 +424,7 @@ int i2400ms_debugfs_add(struct i2400ms *i2400ms)
415 424
416error: 425error:
417 debugfs_remove_recursive(i2400ms->debugfs_dentry); 426 debugfs_remove_recursive(i2400ms->debugfs_dentry);
427 i2400ms->debugfs_dentry = NULL;
418 return result; 428 return result;
419} 429}
420 430
@@ -531,6 +541,7 @@ void i2400ms_remove(struct sdio_func *func)
531 541
532 d_fnstart(3, dev, "SDIO func %p\n", func); 542 d_fnstart(3, dev, "SDIO func %p\n", func);
533 debugfs_remove_recursive(i2400ms->debugfs_dentry); 543 debugfs_remove_recursive(i2400ms->debugfs_dentry);
544 i2400ms->debugfs_dentry = NULL;
534 i2400m_release(i2400m); 545 i2400m_release(i2400m);
535 sdio_set_drvdata(func, NULL); 546 sdio_set_drvdata(func, NULL);
536 free_netdev(net_dev); 547 free_netdev(net_dev);