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

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

wimax/i2400m: introduce i2400m->bus_setup/release



The SDIO subdriver of the i2400m requires certain steps to be done
before we do any acces to the device, even for doing firmware upload.

This lead to a few ugly hacks, which basically involve doing those
steps in probe() before calling i2400m_setup() and undoing them in
disconnect() after claling i2400m_release(); but then, much of those
steps have to be repeated when resetting the device, suspending, etc
(in upcoming pre/post reset support).

Thus, a new pair of optional, bus-specific calls
i2400m->bus_{setup/release} are introduced. These are used to setup
basic infrastructure needed to load firmware onto the device.

This commit also updates the SDIO subdriver to use said calls.

Signed-off-by: default avatarInaky Perez-Gonzalez <inaky@linux.intel.com>
parent c2315b4e
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -41,8 +41,10 @@
 *     __i2400m_dev_start()
 *     __i2400m_dev_start()
 *
 *
 * i2400m_setup()
 * i2400m_setup()
 *   i2400m->bus_setup()
 *   i2400m_bootrom_init()
 *   i2400m_bootrom_init()
 *   register_netdev()
 *   register_netdev()
 *   wimax_dev_add()
 *   i2400m_dev_start()
 *   i2400m_dev_start()
 *     __i2400m_dev_start()
 *     __i2400m_dev_start()
 *       i2400m_dev_bootstrap()
 *       i2400m_dev_bootstrap()
@@ -50,15 +52,15 @@
 *       i2400m->bus_dev_start()
 *       i2400m->bus_dev_start()
 *       i2400m_firmware_check()
 *       i2400m_firmware_check()
 *       i2400m_check_mac_addr()
 *       i2400m_check_mac_addr()
 *   wimax_dev_add()
 *
 *
 * i2400m_release()
 * i2400m_release()
 *   wimax_dev_rm()
 *   i2400m_dev_stop()
 *   i2400m_dev_stop()
 *     __i2400m_dev_stop()
 *     __i2400m_dev_stop()
 *       i2400m_dev_shutdown()
 *       i2400m_dev_shutdown()
 *       i2400m->bus_dev_stop()
 *       i2400m->bus_dev_stop()
 *       i2400m_tx_release()
 *       i2400m_tx_release()
 *   i2400m->bus_release()
 *   wimax_dev_rm()
 *   unregister_netdev()
 *   unregister_netdev()
 */
 */
#include "i2400m.h"
#include "i2400m.h"
@@ -784,6 +786,15 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags)
	snprintf(wimax_dev->name, sizeof(wimax_dev->name),
	snprintf(wimax_dev->name, sizeof(wimax_dev->name),
		 "i2400m-%s:%s", dev->bus->name, dev_name(dev));
		 "i2400m-%s:%s", dev->bus->name, dev_name(dev));


	if (i2400m->bus_setup) {
		result = i2400m->bus_setup(i2400m);
		if (result < 0) {
			dev_err(dev, "bus-specific setup failed: %d\n",
				result);
			goto error_bus_setup;
		}
	}

	result = i2400m_bootrom_init(i2400m, bm_flags);
	result = i2400m_bootrom_init(i2400m, bm_flags);
	if (result < 0) {
	if (result < 0) {
		dev_err(dev, "read mac addr: bootrom init "
		dev_err(dev, "read mac addr: bootrom init "
@@ -846,6 +857,9 @@ error_register_netdev:
	unregister_pm_notifier(&i2400m->pm_notifier);
	unregister_pm_notifier(&i2400m->pm_notifier);
error_read_mac_addr:
error_read_mac_addr:
error_bootrom_init:
error_bootrom_init:
	if (i2400m->bus_release)
		i2400m->bus_release(i2400m);
error_bus_setup:
	d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
	d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result);
	return result;
	return result;
}
}
@@ -872,6 +886,8 @@ void i2400m_release(struct i2400m *i2400m)
	wimax_dev_rm(&i2400m->wimax_dev);
	wimax_dev_rm(&i2400m->wimax_dev);
	unregister_netdev(i2400m->wimax_dev.net_dev);
	unregister_netdev(i2400m->wimax_dev.net_dev);
	unregister_pm_notifier(&i2400m->pm_notifier);
	unregister_pm_notifier(&i2400m->pm_notifier);
	if (i2400m->bus_release)
		i2400m->bus_release(i2400m);
	i2400m_bm_buf_free(i2400m);
	i2400m_bm_buf_free(i2400m);
	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
	d_fnend(3, dev, "(i2400m %p) = void\n", i2400m);
}
}
+27 −0
Original line number Original line Diff line number Diff line
@@ -123,6 +123,7 @@
 *
 *
 * bus_probe()
 * bus_probe()
 *   i2400m_setup()
 *   i2400m_setup()
 *     i2400m->bus_setup()
 *     boot rom initialization / read mac addr
 *     boot rom initialization / read mac addr
 *     network / WiMAX stacks registration
 *     network / WiMAX stacks registration
 *     i2400m_dev_start()
 *     i2400m_dev_start()
@@ -137,6 +138,7 @@
 *       i2400m_dev_shutdown()
 *       i2400m_dev_shutdown()
 *       i2400m->bus_dev_stop()
 *       i2400m->bus_dev_stop()
 *     network / WiMAX stack unregistration
 *     network / WiMAX stack unregistration
 *     i2400m->bus_release()
 *
 *
 * At this point, control and data communications are possible.
 * At this point, control and data communications are possible.
 *
 *
@@ -214,12 +216,35 @@ struct i2400m_barker_db;
 * Members marked with [fill] must be filled out/initialized before
 * Members marked with [fill] must be filled out/initialized before
 * calling i2400m_setup().
 * calling i2400m_setup().
 *
 *
 * Note the @bus_setup/@bus_release, @bus_dev_start/@bus_dev_release
 * call pairs are very much doing almost the same, and depending on
 * the underlying bus, some stuff has to be put in one or the
 * other. The idea of setup/release is that they setup the minimal
 * amount needed for loading firmware, where us dev_start/stop setup
 * the rest needed to do full data/control traffic.
 *
 * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16,
 * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16,
 *     so we have a tx_blk_size variable that the bus layer sets to
 *     so we have a tx_blk_size variable that the bus layer sets to
 *     tell the engine how much of that we need.
 *     tell the engine how much of that we need.
 *
 *
 * @bus_pl_size_max: [fill] Maximum payload size.
 * @bus_pl_size_max: [fill] Maximum payload size.
 *
 *
 * @bus_setup: [optional fill] Function called by the bus-generic code
 *     [i2400m_setup()] to setup the basic bus-specific communications
 *     to the the device needed to load firmware. See LIFE CYCLE above.
 *
 *     NOTE: Doesn't need to upload the firmware, as that is taken
 *     care of by the bus-generic code.
 *
 * @bus_release: [optional fill] Function called by the bus-generic
 *     code [i2400m_release()] to shutdown the basic bus-specific
 *     communications to the the device needed to load firmware. See
 *     LIFE CYCLE above.
 *
 *     This function does not need to reset the device, just tear down
 *     all the host resources created to  handle communication with
 *     the device.
 *
 * @bus_dev_start: [fill] Function called by the bus-generic code
 * @bus_dev_start: [fill] Function called by the bus-generic code
 *     [i2400m_dev_start()] to setup the bus-specific communications
 *     [i2400m_dev_start()] to setup the bus-specific communications
 *     to the the device. See LIFE CYCLE above.
 *     to the the device. See LIFE CYCLE above.
@@ -490,8 +515,10 @@ struct i2400m {
	size_t bus_pl_size_max;
	size_t bus_pl_size_max;
	unsigned bus_bm_retries;
	unsigned bus_bm_retries;


	int (*bus_setup)(struct i2400m *);
	int (*bus_dev_start)(struct i2400m *);
	int (*bus_dev_start)(struct i2400m *);
	void (*bus_dev_stop)(struct i2400m *);
	void (*bus_dev_stop)(struct i2400m *);
	void (*bus_release)(struct i2400m *);
	void (*bus_tx_kick)(struct i2400m *);
	void (*bus_tx_kick)(struct i2400m *);
	int (*bus_reset)(struct i2400m *, enum i2400m_reset_type);
	int (*bus_reset)(struct i2400m *, enum i2400m_reset_type);
	ssize_t (*bus_bm_cmd_send)(struct i2400m *,
	ssize_t (*bus_bm_cmd_send)(struct i2400m *,
+64 −36
Original line number Original line Diff line number Diff line
@@ -164,6 +164,66 @@ function_enabled:
}
}




/*
 * Setup minimal device communication infrastructure needed to at
 * least be able to update the firmware.
 */
static
int i2400ms_bus_setup(struct i2400m *i2400m)
{
	int result;
	struct i2400ms *i2400ms =
		container_of(i2400m, struct i2400ms, i2400m);
	struct device *dev = i2400m_dev(i2400m);
	struct sdio_func *func = i2400ms->func;

	sdio_claim_host(func);
	result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
	sdio_release_host(func);
	if (result < 0) {
		dev_err(dev, "Failed to set block size: %d\n", result);
		goto error_set_blk_size;
	}

	result = i2400ms_enable_function(func, 1);
	if (result < 0) {
		dev_err(dev, "Cannot enable SDIO function: %d\n", result);
		goto error_func_enable;
	}

	result = i2400ms_rx_setup(i2400ms);
	if (result < 0)
		goto error_rx_setup;
	return 0;

error_rx_setup:
	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
error_func_enable:
error_set_blk_size:
	return result;
}


/*
 * Tear down minimal device communication infrastructure needed to at
 * least be able to update the firmware.
 */
static
void i2400ms_bus_release(struct i2400m *i2400m)
{
	struct i2400ms *i2400ms =
		container_of(i2400m, struct i2400ms, i2400m);
	struct sdio_func *func = i2400ms->func;

	i2400ms_rx_release(i2400ms);
	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
}


/*
/*
 * Setup driver resources needed to communicate with the device
 * Setup driver resources needed to communicate with the device
 *
 *
@@ -315,17 +375,12 @@ do_bus_reset:
		if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED)
		if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED)
			netif_tx_disable(i2400m->wimax_dev.net_dev);
			netif_tx_disable(i2400m->wimax_dev.net_dev);


		i2400ms_rx_release(i2400ms);
		i2400ms_bus_release(i2400m);
		sdio_claim_host(i2400ms->func);
		sdio_disable_func(i2400ms->func);
		sdio_release_host(i2400ms->func);


		/* Wait for the device to settle */
		/* Wait for the device to settle */
		msleep(40);
		msleep(40);


		result = i2400ms_enable_function(i2400ms->func, 0);
		result =  i2400ms_bus_setup(i2400m);
		if (result >= 0)
			i2400ms_rx_setup(i2400ms);
	} else
	} else
		BUG();
		BUG();
	if (result < 0 && rt != I2400M_RT_BUS) {
	if (result < 0 && rt != I2400M_RT_BUS) {
@@ -449,8 +504,10 @@ int i2400ms_probe(struct sdio_func *func,


	i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
	i2400m->bus_tx_block_size = I2400MS_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
	i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX;
	i2400m->bus_setup = i2400ms_bus_setup;
	i2400m->bus_dev_start = i2400ms_bus_dev_start;
	i2400m->bus_dev_start = i2400ms_bus_dev_start;
	i2400m->bus_dev_stop = i2400ms_bus_dev_stop;
	i2400m->bus_dev_stop = i2400ms_bus_dev_stop;
	i2400m->bus_release = i2400ms_bus_release;
	i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
	i2400m->bus_tx_kick = i2400ms_bus_tx_kick;
	i2400m->bus_reset = i2400ms_bus_reset;
	i2400m->bus_reset = i2400ms_bus_reset;
	/* The iwmc3200-wimax sometimes requires the driver to try
	/* The iwmc3200-wimax sometimes requires the driver to try
@@ -462,20 +519,6 @@ int i2400ms_probe(struct sdio_func *func,
	i2400m->bus_bm_mac_addr_impaired = 1;
	i2400m->bus_bm_mac_addr_impaired = 1;
	i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];
	i2400m->bus_bm_pokes_table = &i2400ms_pokes[0];


	sdio_claim_host(func);
	result = sdio_set_block_size(func, I2400MS_BLK_SIZE);
	sdio_release_host(func);
	if (result < 0) {
		dev_err(dev, "Failed to set block size: %d\n", result);
		goto error_set_blk_size;
	}

	result = i2400ms_enable_function(i2400ms->func, 1);
	if (result < 0) {
		dev_err(dev, "Cannot enable SDIO function: %d\n", result);
		goto error_func_enable;
	}

	/*
	/*
	 * Before we are enabling the device interrupt register, make
	 * Before we are enabling the device interrupt register, make
	 * sure the buffer used during bootmode operation is setup so
	 * sure the buffer used during bootmode operation is setup so
@@ -488,10 +531,6 @@ int i2400ms_probe(struct sdio_func *func,
		goto error_bootmode_buf_setup;
		goto error_bootmode_buf_setup;
	}
	}


	result = i2400ms_rx_setup(i2400ms);
	if (result < 0)
		goto error_rx_setup;

	result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
	result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT);
	if (result < 0) {
	if (result < 0) {
		dev_err(dev, "cannot setup device: %d\n", result);
		dev_err(dev, "cannot setup device: %d\n", result);
@@ -509,15 +548,8 @@ int i2400ms_probe(struct sdio_func *func,
error_debugfs_add:
error_debugfs_add:
	i2400m_release(i2400m);
	i2400m_release(i2400m);
error_setup:
error_setup:
	i2400ms_rx_release(i2400ms);
error_rx_setup:
	i2400m_bm_buf_free(i2400m);
	i2400m_bm_buf_free(i2400m);
error_bootmode_buf_setup:
error_bootmode_buf_setup:
	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
error_func_enable:
error_set_blk_size:
	sdio_set_drvdata(func, NULL);
	sdio_set_drvdata(func, NULL);
	free_netdev(net_dev);
	free_netdev(net_dev);
error_alloc_netdev:
error_alloc_netdev:
@@ -535,12 +567,8 @@ 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_rx_release(i2400ms);
	i2400m_release(i2400m);
	i2400m_release(i2400m);
	sdio_set_drvdata(func, NULL);
	sdio_set_drvdata(func, NULL);
	sdio_claim_host(func);
	sdio_disable_func(func);
	sdio_release_host(func);
	free_netdev(net_dev);
	free_netdev(net_dev);
	d_fnend(3, dev, "SDIO func %p\n", func);
	d_fnend(3, dev, "SDIO func %p\n", func);
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -416,8 +416,10 @@ int i2400mu_probe(struct usb_interface *iface,


	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	i2400m->bus_tx_block_size = I2400MU_BLK_SIZE;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX;
	i2400m->bus_setup = NULL;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_start = i2400mu_bus_dev_start;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_dev_stop = i2400mu_bus_dev_stop;
	i2400m->bus_release = NULL;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_tx_kick = i2400mu_bus_tx_kick;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_reset = i2400mu_bus_reset;
	i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES;
	i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES;