aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2009-09-16 21:23:27 -0400
committerInaky Perez-Gonzalez <inaky@linux.intel.com>2009-10-19 02:56:08 -0400
commit0856ccf29dfbaf957e4be80dd3eb88d97810b633 (patch)
treea33cf96b010ce3814747b67eb60743554af2070f /drivers/net/wimax
parentc2315b4ea9ac9c3f8caf03c3511d86fabe4a5fcd (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')
-rw-r--r--drivers/net/wimax/i2400m/driver.c20
-rw-r--r--drivers/net/wimax/i2400m/i2400m.h27
-rw-r--r--drivers/net/wimax/i2400m/sdio.c100
-rw-r--r--drivers/net/wimax/i2400m/usb.c2
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);
847error_read_mac_addr: 858error_read_mac_addr:
848error_bootrom_init: 859error_bootrom_init:
860 if (i2400m->bus_release)
861 i2400m->bus_release(i2400m);
862error_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 */
171static
172int 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
199error_rx_setup:
200 sdio_claim_host(func);
201 sdio_disable_func(func);
202 sdio_release_host(func);
203error_func_enable:
204error_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 */
213static
214void 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,
509error_debugfs_add: 548error_debugfs_add:
510 i2400m_release(i2400m); 549 i2400m_release(i2400m);
511error_setup: 550error_setup:
512 i2400ms_rx_release(i2400ms);
513error_rx_setup:
514 i2400m_bm_buf_free(i2400m); 551 i2400m_bm_buf_free(i2400m);
515error_bootmode_buf_setup: 552error_bootmode_buf_setup:
516 sdio_claim_host(func);
517 sdio_disable_func(func);
518 sdio_release_host(func);
519error_func_enable:
520error_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);
523error_alloc_netdev: 555error_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;