aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/sdio.c
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-08-31 17:57:56 -0700
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-19 15:55:48 +0900
commitc77ca950abb587bcebad6dcd0b0b41d7c0255ce9 (patch)
treee60031fcfe1d4a99a54db0403bdcd3f07dd5ebe7 /drivers/net/wimax/i2400m/sdio.c
parent8d8fe198c6a756ae96617548af4776e7a86c0d3e (diff)
downloadkernel_samsung_smdk4412-c77ca950abb587bcebad6dcd0b0b41d7c0255ce9.zip
kernel_samsung_smdk4412-c77ca950abb587bcebad6dcd0b0b41d7c0255ce9.tar.gz
kernel_samsung_smdk4412-c77ca950abb587bcebad6dcd0b0b41d7c0255ce9.tar.bz2
wimax/i2400m: during probe, call sdio_disable at most once
In the Intel Wireless Multicomm 3200, the initialization is orchestrated by a component called Top. This component also monitors how many times a function is reset (via sdio_disable) to detect possible issues and will reset the whole multifunction device if any function triggers a maximum reset level. During WiMAX's probe, the driver needs to wait for Top to come up before it can enable the WiMAX function. If it cannot, it will return -ENODEV and the Top driver will rescan the SDIO bus once done loading. Currently, the WiMAX SDIO probe routine was trying a few times before returning -ENODEV, and this was triggering Top's too-many-resets detector. This is, in any case, unnecessary because the Top driver will force the bus rescan when the functions can be probed successfully. Added then a maxtries argument to i2400ms_enable_func() and set it to 1 when calling from probe. We want to reuse this function instead of flat calling out sdio_enable_func() to take advantage of hardware quirk workarounds. Reported-by: Cindy H Kao <cindy.h.kao@intel.com> Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m/sdio.c')
-rw-r--r--drivers/net/wimax/i2400m/sdio.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c
index 9d6046f..7c1b843 100644
--- a/drivers/net/wimax/i2400m/sdio.c
+++ b/drivers/net/wimax/i2400m/sdio.c
@@ -95,17 +95,23 @@ static const struct i2400m_poke_table i2400ms_pokes[] = {
* when we ask it to explicitly doing). Tries until a timeout is
* reached.
*
+ * The @maxtries argument indicates how many times (at most) it should
+ * be tried to enable the function. 0 means forever. This acts along
+ * with the timeout (ie: it'll stop trying as soon as the maximum
+ * number of tries is reached _or_ as soon as the timeout is reached).
+ *
* The reverse of this is...sdio_disable_function()
*
* Returns: 0 if the SDIO function was enabled, < 0 errno code on
* error (-ENODEV when it was unable to enable the function).
*/
static
-int i2400ms_enable_function(struct sdio_func *func)
+int i2400ms_enable_function(struct sdio_func *func, unsigned maxtries)
{
u64 timeout;
int err;
struct device *dev = &func->dev;
+ unsigned tries = 0;
d_fnstart(3, dev, "(func %p)\n", func);
/* Setup timeout (FIXME: This needs to read the CIS table to
@@ -131,6 +137,10 @@ int i2400ms_enable_function(struct sdio_func *func)
}
d_printf(2, dev, "SDIO function failed to enable: %d\n", err);
sdio_release_host(func);
+ if (maxtries > 0 && ++tries >= maxtries) {
+ err = -ETIME;
+ break;
+ }
msleep(I2400MS_INIT_SLEEP_INTERVAL);
}
/* If timed out, device is not there yet -- get -ENODEV so
@@ -305,7 +315,7 @@ do_bus_reset:
/* Wait for the device to settle */
msleep(40);
- result = i2400ms_enable_function(i2400ms->func);
+ result = i2400ms_enable_function(i2400ms->func, 0);
if (result >= 0)
i2400ms_rx_setup(i2400ms);
} else
@@ -452,7 +462,7 @@ int i2400ms_probe(struct sdio_func *func,
goto error_set_blk_size;
}
- result = i2400ms_enable_function(i2400ms->func);
+ result = i2400ms_enable_function(i2400ms->func, 1);
if (result < 0) {
dev_err(dev, "Cannot enable SDIO function: %d\n", result);
goto error_func_enable;