Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c77ca950 authored by Inaky Perez-Gonzalez's avatar Inaky Perez-Gonzalez
Browse files

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: default avatarCindy H Kao <cindy.h.kao@intel.com>
Signed-off-by: default avatarInaky Perez-Gonzalez <inaky@linux.intel.com>
parent 8d8fe198
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -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 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt)
		/* 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;