diff options
author | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-09-16 21:23:27 -0400 |
---|---|---|
committer | Inaky Perez-Gonzalez <inaky@linux.intel.com> | 2009-10-19 02:56:08 -0400 |
commit | 0856ccf29dfbaf957e4be80dd3eb88d97810b633 (patch) | |
tree | a33cf96b010ce3814747b67eb60743554af2070f /drivers/net/wimax/i2400m | |
parent | c2315b4ea9ac9c3f8caf03c3511d86fabe4a5fcd (diff) |
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: Inaky Perez-Gonzalez <inaky@linux.intel.com>
Diffstat (limited to 'drivers/net/wimax/i2400m')
-rw-r--r-- | drivers/net/wimax/i2400m/driver.c | 20 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/i2400m.h | 27 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/sdio.c | 100 | ||||
-rw-r--r-- | drivers/net/wimax/i2400m/usb.c | 2 |
4 files changed, 111 insertions, 38 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index 6280646d7d7f..c57020f811cd 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c | |||
@@ -41,8 +41,10 @@ | |||
41 | * __i2400m_dev_start() | 41 | * __i2400m_dev_start() |
42 | * | 42 | * |
43 | * i2400m_setup() | 43 | * i2400m_setup() |
44 | * i2400m->bus_setup() | ||
44 | * i2400m_bootrom_init() | 45 | * i2400m_bootrom_init() |
45 | * register_netdev() | 46 | * register_netdev() |
47 | * wimax_dev_add() | ||
46 | * i2400m_dev_start() | 48 | * i2400m_dev_start() |
47 | * __i2400m_dev_start() | 49 | * __i2400m_dev_start() |
48 | * i2400m_dev_bootstrap() | 50 | * i2400m_dev_bootstrap() |
@@ -50,15 +52,15 @@ | |||
50 | * i2400m->bus_dev_start() | 52 | * i2400m->bus_dev_start() |
51 | * i2400m_firmware_check() | 53 | * i2400m_firmware_check() |
52 | * i2400m_check_mac_addr() | 54 | * i2400m_check_mac_addr() |
53 | * wimax_dev_add() | ||
54 | * | 55 | * |
55 | * i2400m_release() | 56 | * i2400m_release() |
56 | * wimax_dev_rm() | ||
57 | * i2400m_dev_stop() | 57 | * i2400m_dev_stop() |
58 | * __i2400m_dev_stop() | 58 | * __i2400m_dev_stop() |
59 | * i2400m_dev_shutdown() | 59 | * i2400m_dev_shutdown() |
60 | * i2400m->bus_dev_stop() | 60 | * i2400m->bus_dev_stop() |
61 | * i2400m_tx_release() | 61 | * i2400m_tx_release() |
62 | * i2400m->bus_release() | ||
63 | * wimax_dev_rm() | ||
62 | * unregister_netdev() | 64 | * unregister_netdev() |
63 | */ | 65 | */ |
64 | #include "i2400m.h" | 66 | #include "i2400m.h" |
@@ -784,6 +786,15 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) | |||
784 | snprintf(wimax_dev->name, sizeof(wimax_dev->name), | 786 | snprintf(wimax_dev->name, sizeof(wimax_dev->name), |
785 | "i2400m-%s:%s", dev->bus->name, dev_name(dev)); | 787 | "i2400m-%s:%s", dev->bus->name, dev_name(dev)); |
786 | 788 | ||
789 | if (i2400m->bus_setup) { | ||
790 | result = i2400m->bus_setup(i2400m); | ||
791 | if (result < 0) { | ||
792 | dev_err(dev, "bus-specific setup failed: %d\n", | ||
793 | result); | ||
794 | goto error_bus_setup; | ||
795 | } | ||
796 | } | ||
797 | |||
787 | result = i2400m_bootrom_init(i2400m, bm_flags); | 798 | result = i2400m_bootrom_init(i2400m, bm_flags); |
788 | if (result < 0) { | 799 | if (result < 0) { |
789 | dev_err(dev, "read mac addr: bootrom init " | 800 | dev_err(dev, "read mac addr: bootrom init " |
@@ -846,6 +857,9 @@ error_register_netdev: | |||
846 | unregister_pm_notifier(&i2400m->pm_notifier); | 857 | unregister_pm_notifier(&i2400m->pm_notifier); |
847 | error_read_mac_addr: | 858 | error_read_mac_addr: |
848 | error_bootrom_init: | 859 | error_bootrom_init: |
860 | if (i2400m->bus_release) | ||
861 | i2400m->bus_release(i2400m); | ||
862 | error_bus_setup: | ||
849 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); | 863 | d_fnend(3, dev, "(i2400m %p) = %d\n", i2400m, result); |
850 | return result; | 864 | return result; |
851 | } | 865 | } |
@@ -872,6 +886,8 @@ void i2400m_release(struct i2400m *i2400m) | |||
872 | wimax_dev_rm(&i2400m->wimax_dev); | 886 | wimax_dev_rm(&i2400m->wimax_dev); |
873 | unregister_netdev(i2400m->wimax_dev.net_dev); | 887 | unregister_netdev(i2400m->wimax_dev.net_dev); |
874 | unregister_pm_notifier(&i2400m->pm_notifier); | 888 | unregister_pm_notifier(&i2400m->pm_notifier); |
889 | if (i2400m->bus_release) | ||
890 | i2400m->bus_release(i2400m); | ||
875 | i2400m_bm_buf_free(i2400m); | 891 | i2400m_bm_buf_free(i2400m); |
876 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | 892 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); |
877 | } | 893 | } |
diff --git a/drivers/net/wimax/i2400m/i2400m.h b/drivers/net/wimax/i2400m/i2400m.h index fbc156db5bfd..407d0972f2f6 100644 --- a/drivers/net/wimax/i2400m/i2400m.h +++ b/drivers/net/wimax/i2400m/i2400m.h | |||
@@ -123,6 +123,7 @@ | |||
123 | * | 123 | * |
124 | * bus_probe() | 124 | * bus_probe() |
125 | * i2400m_setup() | 125 | * i2400m_setup() |
126 | * i2400m->bus_setup() | ||
126 | * boot rom initialization / read mac addr | 127 | * boot rom initialization / read mac addr |
127 | * network / WiMAX stacks registration | 128 | * network / WiMAX stacks registration |
128 | * i2400m_dev_start() | 129 | * i2400m_dev_start() |
@@ -137,6 +138,7 @@ | |||
137 | * i2400m_dev_shutdown() | 138 | * i2400m_dev_shutdown() |
138 | * i2400m->bus_dev_stop() | 139 | * i2400m->bus_dev_stop() |
139 | * network / WiMAX stack unregistration | 140 | * network / WiMAX stack unregistration |
141 | * i2400m->bus_release() | ||
140 | * | 142 | * |
141 | * At this point, control and data communications are possible. | 143 | * At this point, control and data communications are possible. |
142 | * | 144 | * |
@@ -214,12 +216,35 @@ struct i2400m_barker_db; | |||
214 | * Members marked with [fill] must be filled out/initialized before | 216 | * Members marked with [fill] must be filled out/initialized before |
215 | * calling i2400m_setup(). | 217 | * calling i2400m_setup(). |
216 | * | 218 | * |
219 | * Note the @bus_setup/@bus_release, @bus_dev_start/@bus_dev_release | ||
220 | * call pairs are very much doing almost the same, and depending on | ||
221 | * the underlying bus, some stuff has to be put in one or the | ||
222 | * other. The idea of setup/release is that they setup the minimal | ||
223 | * amount needed for loading firmware, where us dev_start/stop setup | ||
224 | * the rest needed to do full data/control traffic. | ||
225 | * | ||
217 | * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, | 226 | * @bus_tx_block_size: [fill] SDIO imposes a 256 block size, USB 16, |
218 | * so we have a tx_blk_size variable that the bus layer sets to | 227 | * so we have a tx_blk_size variable that the bus layer sets to |
219 | * tell the engine how much of that we need. | 228 | * tell the engine how much of that we need. |
220 | * | 229 | * |
221 | * @bus_pl_size_max: [fill] Maximum payload size. | 230 | * @bus_pl_size_max: [fill] Maximum payload size. |
222 | * | 231 | * |
232 | * @bus_setup: [optional fill] Function called by the bus-generic code | ||
233 | * [i2400m_setup()] to setup the basic bus-specific communications | ||
234 | * to the the device needed to load firmware. See LIFE CYCLE above. | ||
235 | * | ||
236 | * NOTE: Doesn't need to upload the firmware, as that is taken | ||
237 | * care of by the bus-generic code. | ||
238 | * | ||
239 | * @bus_release: [optional fill] Function called by the bus-generic | ||
240 | * code [i2400m_release()] to shutdown the basic bus-specific | ||
241 | * communications to the the device needed to load firmware. See | ||
242 | * LIFE CYCLE above. | ||
243 | * | ||
244 | * This function does not need to reset the device, just tear down | ||
245 | * all the host resources created to handle communication with | ||
246 | * the device. | ||
247 | * | ||
223 | * @bus_dev_start: [fill] Function called by the bus-generic code | 248 | * @bus_dev_start: [fill] Function called by the bus-generic code |
224 | * [i2400m_dev_start()] to setup the bus-specific communications | 249 | * [i2400m_dev_start()] to setup the bus-specific communications |
225 | * to the the device. See LIFE CYCLE above. | 250 | * to the the device. See LIFE CYCLE above. |
@@ -490,8 +515,10 @@ struct i2400m { | |||
490 | size_t bus_pl_size_max; | 515 | size_t bus_pl_size_max; |
491 | unsigned bus_bm_retries; | 516 | unsigned bus_bm_retries; |
492 | 517 | ||
518 | int (*bus_setup)(struct i2400m *); | ||
493 | int (*bus_dev_start)(struct i2400m *); | 519 | int (*bus_dev_start)(struct i2400m *); |
494 | void (*bus_dev_stop)(struct i2400m *); | 520 | void (*bus_dev_stop)(struct i2400m *); |
521 | void (*bus_release)(struct i2400m *); | ||
495 | void (*bus_tx_kick)(struct i2400m *); | 522 | void (*bus_tx_kick)(struct i2400m *); |
496 | int (*bus_reset)(struct i2400m *, enum i2400m_reset_type); | 523 | int (*bus_reset)(struct i2400m *, enum i2400m_reset_type); |
497 | ssize_t (*bus_bm_cmd_send)(struct i2400m *, | 524 | ssize_t (*bus_bm_cmd_send)(struct i2400m *, |
diff --git a/drivers/net/wimax/i2400m/sdio.c b/drivers/net/wimax/i2400m/sdio.c index de158ee0c32c..6e39665ecd89 100644 --- a/drivers/net/wimax/i2400m/sdio.c +++ b/drivers/net/wimax/i2400m/sdio.c | |||
@@ -165,6 +165,66 @@ function_enabled: | |||
165 | 165 | ||
166 | 166 | ||
167 | /* | 167 | /* |
168 | * Setup minimal device communication infrastructure needed to at | ||
169 | * least be able to update the firmware. | ||
170 | */ | ||
171 | static | ||
172 | int i2400ms_bus_setup(struct i2400m *i2400m) | ||
173 | { | ||
174 | int result; | ||
175 | struct i2400ms *i2400ms = | ||
176 | container_of(i2400m, struct i2400ms, i2400m); | ||
177 | struct device *dev = i2400m_dev(i2400m); | ||
178 | struct sdio_func *func = i2400ms->func; | ||
179 | |||
180 | sdio_claim_host(func); | ||
181 | result = sdio_set_block_size(func, I2400MS_BLK_SIZE); | ||
182 | sdio_release_host(func); | ||
183 | if (result < 0) { | ||
184 | dev_err(dev, "Failed to set block size: %d\n", result); | ||
185 | goto error_set_blk_size; | ||
186 | } | ||
187 | |||
188 | result = i2400ms_enable_function(func, 1); | ||
189 | if (result < 0) { | ||
190 | dev_err(dev, "Cannot enable SDIO function: %d\n", result); | ||
191 | goto error_func_enable; | ||
192 | } | ||
193 | |||
194 | result = i2400ms_rx_setup(i2400ms); | ||
195 | if (result < 0) | ||
196 | goto error_rx_setup; | ||
197 | return 0; | ||
198 | |||
199 | error_rx_setup: | ||
200 | sdio_claim_host(func); | ||
201 | sdio_disable_func(func); | ||
202 | sdio_release_host(func); | ||
203 | error_func_enable: | ||
204 | error_set_blk_size: | ||
205 | return result; | ||
206 | } | ||
207 | |||
208 | |||
209 | /* | ||
210 | * Tear down minimal device communication infrastructure needed to at | ||
211 | * least be able to update the firmware. | ||
212 | */ | ||
213 | static | ||
214 | void i2400ms_bus_release(struct i2400m *i2400m) | ||
215 | { | ||
216 | struct i2400ms *i2400ms = | ||
217 | container_of(i2400m, struct i2400ms, i2400m); | ||
218 | struct sdio_func *func = i2400ms->func; | ||
219 | |||
220 | i2400ms_rx_release(i2400ms); | ||
221 | sdio_claim_host(func); | ||
222 | sdio_disable_func(func); | ||
223 | sdio_release_host(func); | ||
224 | } | ||
225 | |||
226 | |||
227 | /* | ||
168 | * Setup driver resources needed to communicate with the device | 228 | * Setup driver resources needed to communicate with the device |
169 | * | 229 | * |
170 | * The fw needs some time to settle, and it was just uploaded, | 230 | * The fw needs some time to settle, and it was just uploaded, |
@@ -315,17 +375,12 @@ do_bus_reset: | |||
315 | if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED) | 375 | if (i2400m->wimax_dev.net_dev->reg_state == NETREG_REGISTERED) |
316 | netif_tx_disable(i2400m->wimax_dev.net_dev); | 376 | netif_tx_disable(i2400m->wimax_dev.net_dev); |
317 | 377 | ||
318 | i2400ms_rx_release(i2400ms); | 378 | i2400ms_bus_release(i2400m); |
319 | sdio_claim_host(i2400ms->func); | ||
320 | sdio_disable_func(i2400ms->func); | ||
321 | sdio_release_host(i2400ms->func); | ||
322 | 379 | ||
323 | /* Wait for the device to settle */ | 380 | /* Wait for the device to settle */ |
324 | msleep(40); | 381 | msleep(40); |
325 | 382 | ||
326 | result = i2400ms_enable_function(i2400ms->func, 0); | 383 | result = i2400ms_bus_setup(i2400m); |
327 | if (result >= 0) | ||
328 | i2400ms_rx_setup(i2400ms); | ||
329 | } else | 384 | } else |
330 | BUG(); | 385 | BUG(); |
331 | if (result < 0 && rt != I2400M_RT_BUS) { | 386 | if (result < 0 && rt != I2400M_RT_BUS) { |
@@ -449,8 +504,10 @@ int i2400ms_probe(struct sdio_func *func, | |||
449 | 504 | ||
450 | i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; | 505 | i2400m->bus_tx_block_size = I2400MS_BLK_SIZE; |
451 | i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; | 506 | i2400m->bus_pl_size_max = I2400MS_PL_SIZE_MAX; |
507 | i2400m->bus_setup = i2400ms_bus_setup; | ||
452 | i2400m->bus_dev_start = i2400ms_bus_dev_start; | 508 | i2400m->bus_dev_start = i2400ms_bus_dev_start; |
453 | i2400m->bus_dev_stop = i2400ms_bus_dev_stop; | 509 | i2400m->bus_dev_stop = i2400ms_bus_dev_stop; |
510 | i2400m->bus_release = i2400ms_bus_release; | ||
454 | i2400m->bus_tx_kick = i2400ms_bus_tx_kick; | 511 | i2400m->bus_tx_kick = i2400ms_bus_tx_kick; |
455 | i2400m->bus_reset = i2400ms_bus_reset; | 512 | i2400m->bus_reset = i2400ms_bus_reset; |
456 | /* The iwmc3200-wimax sometimes requires the driver to try | 513 | /* The iwmc3200-wimax sometimes requires the driver to try |
@@ -462,20 +519,6 @@ int i2400ms_probe(struct sdio_func *func, | |||
462 | i2400m->bus_bm_mac_addr_impaired = 1; | 519 | i2400m->bus_bm_mac_addr_impaired = 1; |
463 | i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; | 520 | i2400m->bus_bm_pokes_table = &i2400ms_pokes[0]; |
464 | 521 | ||
465 | sdio_claim_host(func); | ||
466 | result = sdio_set_block_size(func, I2400MS_BLK_SIZE); | ||
467 | sdio_release_host(func); | ||
468 | if (result < 0) { | ||
469 | dev_err(dev, "Failed to set block size: %d\n", result); | ||
470 | goto error_set_blk_size; | ||
471 | } | ||
472 | |||
473 | result = i2400ms_enable_function(i2400ms->func, 1); | ||
474 | if (result < 0) { | ||
475 | dev_err(dev, "Cannot enable SDIO function: %d\n", result); | ||
476 | goto error_func_enable; | ||
477 | } | ||
478 | |||
479 | /* | 522 | /* |
480 | * Before we are enabling the device interrupt register, make | 523 | * Before we are enabling the device interrupt register, make |
481 | * sure the buffer used during bootmode operation is setup so | 524 | * sure the buffer used during bootmode operation is setup so |
@@ -488,10 +531,6 @@ int i2400ms_probe(struct sdio_func *func, | |||
488 | goto error_bootmode_buf_setup; | 531 | goto error_bootmode_buf_setup; |
489 | } | 532 | } |
490 | 533 | ||
491 | result = i2400ms_rx_setup(i2400ms); | ||
492 | if (result < 0) | ||
493 | goto error_rx_setup; | ||
494 | |||
495 | result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); | 534 | result = i2400m_setup(i2400m, I2400M_BRI_NO_REBOOT); |
496 | if (result < 0) { | 535 | if (result < 0) { |
497 | dev_err(dev, "cannot setup device: %d\n", result); | 536 | dev_err(dev, "cannot setup device: %d\n", result); |
@@ -509,15 +548,8 @@ int i2400ms_probe(struct sdio_func *func, | |||
509 | error_debugfs_add: | 548 | error_debugfs_add: |
510 | i2400m_release(i2400m); | 549 | i2400m_release(i2400m); |
511 | error_setup: | 550 | error_setup: |
512 | i2400ms_rx_release(i2400ms); | ||
513 | error_rx_setup: | ||
514 | i2400m_bm_buf_free(i2400m); | 551 | i2400m_bm_buf_free(i2400m); |
515 | error_bootmode_buf_setup: | 552 | error_bootmode_buf_setup: |
516 | sdio_claim_host(func); | ||
517 | sdio_disable_func(func); | ||
518 | sdio_release_host(func); | ||
519 | error_func_enable: | ||
520 | error_set_blk_size: | ||
521 | sdio_set_drvdata(func, NULL); | 553 | sdio_set_drvdata(func, NULL); |
522 | free_netdev(net_dev); | 554 | free_netdev(net_dev); |
523 | error_alloc_netdev: | 555 | error_alloc_netdev: |
@@ -535,12 +567,8 @@ void i2400ms_remove(struct sdio_func *func) | |||
535 | 567 | ||
536 | d_fnstart(3, dev, "SDIO func %p\n", func); | 568 | d_fnstart(3, dev, "SDIO func %p\n", func); |
537 | debugfs_remove_recursive(i2400ms->debugfs_dentry); | 569 | debugfs_remove_recursive(i2400ms->debugfs_dentry); |
538 | i2400ms_rx_release(i2400ms); | ||
539 | i2400m_release(i2400m); | 570 | i2400m_release(i2400m); |
540 | sdio_set_drvdata(func, NULL); | 571 | sdio_set_drvdata(func, NULL); |
541 | sdio_claim_host(func); | ||
542 | sdio_disable_func(func); | ||
543 | sdio_release_host(func); | ||
544 | free_netdev(net_dev); | 572 | free_netdev(net_dev); |
545 | d_fnend(3, dev, "SDIO func %p\n", func); | 573 | d_fnend(3, dev, "SDIO func %p\n", func); |
546 | } | 574 | } |
diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index f4dfb60bb628..3bf3f7288fe6 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c | |||
@@ -416,8 +416,10 @@ int i2400mu_probe(struct usb_interface *iface, | |||
416 | 416 | ||
417 | i2400m->bus_tx_block_size = I2400MU_BLK_SIZE; | 417 | i2400m->bus_tx_block_size = I2400MU_BLK_SIZE; |
418 | i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX; | 418 | i2400m->bus_pl_size_max = I2400MU_PL_SIZE_MAX; |
419 | i2400m->bus_setup = NULL; | ||
419 | i2400m->bus_dev_start = i2400mu_bus_dev_start; | 420 | i2400m->bus_dev_start = i2400mu_bus_dev_start; |
420 | i2400m->bus_dev_stop = i2400mu_bus_dev_stop; | 421 | i2400m->bus_dev_stop = i2400mu_bus_dev_stop; |
422 | i2400m->bus_release = NULL; | ||
421 | i2400m->bus_tx_kick = i2400mu_bus_tx_kick; | 423 | i2400m->bus_tx_kick = i2400mu_bus_tx_kick; |
422 | i2400m->bus_reset = i2400mu_bus_reset; | 424 | i2400m->bus_reset = i2400mu_bus_reset; |
423 | i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES; | 425 | i2400m->bus_bm_retries = I2400M_USB_BOOT_RETRIES; |