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/sdio.c | |
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/sdio.c')
-rw-r--r-- | drivers/net/wimax/i2400m/sdio.c | 100 |
1 files changed, 64 insertions, 36 deletions
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 | } |