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>
This commit is contained in:
parent
02eb41ef2a
commit
fae92216da
|
@ -100,6 +100,14 @@ enum {
|
||||||
* @tx_workqueue: workqeueue used for data TX; we don't use the
|
* @tx_workqueue: workqeueue used for data TX; we don't use the
|
||||||
* system's workqueue as that might cause deadlocks with code in
|
* system's workqueue as that might cause deadlocks with code in
|
||||||
* the bus-generic driver.
|
* the bus-generic driver.
|
||||||
|
*
|
||||||
|
* @debugfs_dentry: dentry for the SDIO specific debugfs files
|
||||||
|
*
|
||||||
|
* Note this value is set to NULL upon destruction; this is
|
||||||
|
* because some routinges use it to determine if we are inside the
|
||||||
|
* probe() path or some other path. When debugfs is disabled,
|
||||||
|
* creation sets the dentry to '(void*) -ENODEV', which is valid
|
||||||
|
* for the test.
|
||||||
*/
|
*/
|
||||||
struct i2400ms {
|
struct i2400ms {
|
||||||
struct i2400m i2400m; /* FIRST! See doc */
|
struct i2400m i2400m; /* FIRST! See doc */
|
||||||
|
|
|
@ -159,6 +159,10 @@ function_enabled:
|
||||||
/*
|
/*
|
||||||
* Setup minimal device communication infrastructure needed to at
|
* Setup minimal device communication infrastructure needed to at
|
||||||
* least be able to update the firmware.
|
* least be able to update the firmware.
|
||||||
|
*
|
||||||
|
* Note the ugly trick: if we are in the probe path
|
||||||
|
* (i2400ms->debugfs_dentry == NULL), we only retry function
|
||||||
|
* enablement one, to avoid racing with the iwmc3200 top controller.
|
||||||
*/
|
*/
|
||||||
static
|
static
|
||||||
int i2400ms_bus_setup(struct i2400m *i2400m)
|
int i2400ms_bus_setup(struct i2400m *i2400m)
|
||||||
|
@ -168,6 +172,7 @@ int i2400ms_bus_setup(struct i2400m *i2400m)
|
||||||
container_of(i2400m, struct i2400ms, i2400m);
|
container_of(i2400m, struct i2400ms, i2400m);
|
||||||
struct device *dev = i2400m_dev(i2400m);
|
struct device *dev = i2400m_dev(i2400m);
|
||||||
struct sdio_func *func = i2400ms->func;
|
struct sdio_func *func = i2400ms->func;
|
||||||
|
int retries;
|
||||||
|
|
||||||
sdio_claim_host(func);
|
sdio_claim_host(func);
|
||||||
result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
|
result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
|
||||||
|
@ -177,7 +182,11 @@ int i2400ms_bus_setup(struct i2400m *i2400m)
|
||||||
goto error_set_blk_size;
|
goto error_set_blk_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = i2400ms_enable_function(i2400ms, 1);
|
if (i2400ms->iwmc3200 && i2400ms->debugfs_dentry == NULL)
|
||||||
|
retries = 0;
|
||||||
|
else
|
||||||
|
retries = 1;
|
||||||
|
result = i2400ms_enable_function(i2400ms, retries);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
dev_err(dev, "Cannot enable SDIO function: %d\n", result);
|
dev_err(dev, "Cannot enable SDIO function: %d\n", result);
|
||||||
goto error_func_enable;
|
goto error_func_enable;
|
||||||
|
@ -415,6 +424,7 @@ int i2400ms_debugfs_add(struct i2400ms *i2400ms)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
debugfs_remove_recursive(i2400ms->debugfs_dentry);
|
debugfs_remove_recursive(i2400ms->debugfs_dentry);
|
||||||
|
i2400ms->debugfs_dentry = NULL;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +541,7 @@ void i2400ms_remove(struct sdio_func *func)
|
||||||
|
|
||||||
d_fnstart(3, dev, "SDIO func %p\n", func);
|
d_fnstart(3, dev, "SDIO func %p\n", func);
|
||||||
debugfs_remove_recursive(i2400ms->debugfs_dentry);
|
debugfs_remove_recursive(i2400ms->debugfs_dentry);
|
||||||
|
i2400ms->debugfs_dentry = NULL;
|
||||||
i2400m_release(i2400m);
|
i2400m_release(i2400m);
|
||||||
sdio_set_drvdata(func, NULL);
|
sdio_set_drvdata(func, NULL);
|
||||||
free_netdev(net_dev);
|
free_netdev(net_dev);
|
||||||
|
|
Loading…
Reference in New Issue