aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wimax/i2400m/driver.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-06-11 20:11:33 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-11 20:11:33 -0400
commit3ee40c376ad3252d13946141588db7e2f435f958 (patch)
tree65bd16c024edab1ff74ad165779443edfaa26467 /drivers/net/wimax/i2400m/driver.c
parent670025478c2a687453cd1bac697d7d765843f59d (diff)
parent98eb0f53e2fc66482e2ea8033c58b20a079e5260 (diff)
Merge branch 'linux-2.6.31.y' of git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax
Diffstat (limited to 'drivers/net/wimax/i2400m/driver.c')
-rw-r--r--drivers/net/wimax/i2400m/driver.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c
index ef16c573bb22..304f0443ca4b 100644
--- a/drivers/net/wimax/i2400m/driver.c
+++ b/drivers/net/wimax/i2400m/driver.c
@@ -82,6 +82,14 @@ module_param_named(rx_reorder_disabled, i2400m_rx_reorder_disabled, int, 0644);
82MODULE_PARM_DESC(rx_reorder_disabled, 82MODULE_PARM_DESC(rx_reorder_disabled,
83 "If true, RX reordering will be disabled."); 83 "If true, RX reordering will be disabled.");
84 84
85int i2400m_power_save_disabled; /* 0 (power saving enabled) by default */
86module_param_named(power_save_disabled, i2400m_power_save_disabled, int, 0644);
87MODULE_PARM_DESC(power_save_disabled,
88 "If true, the driver will not tell the device to enter "
89 "power saving mode when it reports it is ready for it. "
90 "False by default (so the device is told to do power "
91 "saving).");
92
85/** 93/**
86 * i2400m_queue_work - schedule work on a i2400m's queue 94 * i2400m_queue_work - schedule work on a i2400m's queue
87 * 95 *
@@ -172,7 +180,6 @@ int i2400m_schedule_work(struct i2400m *i2400m,
172 int result; 180 int result;
173 struct i2400m_work *iw; 181 struct i2400m_work *iw;
174 182
175 BUG_ON(i2400m->work_queue == NULL);
176 result = -ENOMEM; 183 result = -ENOMEM;
177 iw = kzalloc(sizeof(*iw), gfp_flags); 184 iw = kzalloc(sizeof(*iw), gfp_flags);
178 if (iw == NULL) 185 if (iw == NULL)
@@ -377,6 +384,11 @@ error:
377 * Uploads firmware and brings up all the resources needed to be able 384 * Uploads firmware and brings up all the resources needed to be able
378 * to communicate with the device. 385 * to communicate with the device.
379 * 386 *
387 * The workqueue has to be setup early, at least before RX handling
388 * (it's only real user for now) so it can process reports as they
389 * arrive. We also want to destroy it if we retry, to make sure it is
390 * flushed...easier like this.
391 *
380 * TX needs to be setup before the bus-specific code (otherwise on 392 * TX needs to be setup before the bus-specific code (otherwise on
381 * shutdown, the bus-tx code could try to access it). 393 * shutdown, the bus-tx code could try to access it).
382 */ 394 */
@@ -387,7 +399,7 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)
387 struct wimax_dev *wimax_dev = &i2400m->wimax_dev; 399 struct wimax_dev *wimax_dev = &i2400m->wimax_dev;
388 struct net_device *net_dev = wimax_dev->net_dev; 400 struct net_device *net_dev = wimax_dev->net_dev;
389 struct device *dev = i2400m_dev(i2400m); 401 struct device *dev = i2400m_dev(i2400m);
390 int times = 3; 402 int times = i2400m->bus_bm_retries;
391 403
392 d_fnstart(3, dev, "(i2400m %p)\n", i2400m); 404 d_fnstart(3, dev, "(i2400m %p)\n", i2400m);
393retry: 405retry:
@@ -402,15 +414,15 @@ retry:
402 result = i2400m_rx_setup(i2400m); 414 result = i2400m_rx_setup(i2400m);
403 if (result < 0) 415 if (result < 0)
404 goto error_rx_setup; 416 goto error_rx_setup;
405 result = i2400m->bus_dev_start(i2400m);
406 if (result < 0)
407 goto error_bus_dev_start;
408 i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name); 417 i2400m->work_queue = create_singlethread_workqueue(wimax_dev->name);
409 if (i2400m->work_queue == NULL) { 418 if (i2400m->work_queue == NULL) {
410 result = -ENOMEM; 419 result = -ENOMEM;
411 dev_err(dev, "cannot create workqueue\n"); 420 dev_err(dev, "cannot create workqueue\n");
412 goto error_create_workqueue; 421 goto error_create_workqueue;
413 } 422 }
423 result = i2400m->bus_dev_start(i2400m);
424 if (result < 0)
425 goto error_bus_dev_start;
414 result = i2400m_firmware_check(i2400m); /* fw versions ok? */ 426 result = i2400m_firmware_check(i2400m); /* fw versions ok? */
415 if (result < 0) 427 if (result < 0)
416 goto error_fw_check; 428 goto error_fw_check;
@@ -432,17 +444,17 @@ retry:
432error_dev_initialize: 444error_dev_initialize:
433error_check_mac_addr: 445error_check_mac_addr:
434error_fw_check: 446error_fw_check:
435 destroy_workqueue(i2400m->work_queue);
436error_create_workqueue:
437 i2400m->bus_dev_stop(i2400m); 447 i2400m->bus_dev_stop(i2400m);
438error_bus_dev_start: 448error_bus_dev_start:
449 destroy_workqueue(i2400m->work_queue);
450error_create_workqueue:
439 i2400m_rx_release(i2400m); 451 i2400m_rx_release(i2400m);
440error_rx_setup: 452error_rx_setup:
441 i2400m_tx_release(i2400m); 453 i2400m_tx_release(i2400m);
442error_tx_setup: 454error_tx_setup:
443error_bootstrap: 455error_bootstrap:
444 if (result == -ERESTARTSYS && times-- > 0) { 456 if (result == -EL3RST && times-- > 0) {
445 flags = I2400M_BRI_SOFT; 457 flags = I2400M_BRI_SOFT|I2400M_BRI_MAC_REINIT;
446 goto retry; 458 goto retry;
447 } 459 }
448 d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n", 460 d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
@@ -471,7 +483,9 @@ int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags)
471 * 483 *
472 * Returns: 0 if ok, < 0 errno code on error. 484 * Returns: 0 if ok, < 0 errno code on error.
473 * 485 *
474 * Releases all the resources allocated to communicate with the device. 486 * Releases all the resources allocated to communicate with the
487 * device. Note we cannot destroy the workqueue earlier as until RX is
488 * fully destroyed, it could still try to schedule jobs.
475 */ 489 */
476static 490static
477void __i2400m_dev_stop(struct i2400m *i2400m) 491void __i2400m_dev_stop(struct i2400m *i2400m)
@@ -483,8 +497,8 @@ void __i2400m_dev_stop(struct i2400m *i2400m)
483 wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING); 497 wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
484 i2400m_dev_shutdown(i2400m); 498 i2400m_dev_shutdown(i2400m);
485 i2400m->ready = 0; 499 i2400m->ready = 0;
486 destroy_workqueue(i2400m->work_queue);
487 i2400m->bus_dev_stop(i2400m); 500 i2400m->bus_dev_stop(i2400m);
501 destroy_workqueue(i2400m->work_queue);
488 i2400m_rx_release(i2400m); 502 i2400m_rx_release(i2400m);
489 i2400m_tx_release(i2400m); 503 i2400m_tx_release(i2400m);
490 wimax_state_change(wimax_dev, WIMAX_ST_DOWN); 504 wimax_state_change(wimax_dev, WIMAX_ST_DOWN);
@@ -546,7 +560,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)
546 * i2400m_dev_stop() [we are shutting down anyway, so 560 * i2400m_dev_stop() [we are shutting down anyway, so
547 * ignore it] or we are resetting somewhere else. */ 561 * ignore it] or we are resetting somewhere else. */
548 dev_err(dev, "device rebooted\n"); 562 dev_err(dev, "device rebooted\n");
549 i2400m_msg_to_dev_cancel_wait(i2400m, -ERESTARTSYS); 563 i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST);
550 complete(&i2400m->msg_completion); 564 complete(&i2400m->msg_completion);
551 goto out; 565 goto out;
552 } 566 }
@@ -596,6 +610,8 @@ out:
596 */ 610 */
597int i2400m_dev_reset_handle(struct i2400m *i2400m) 611int i2400m_dev_reset_handle(struct i2400m *i2400m)
598{ 612{
613 i2400m->boot_mode = 1;
614 wmb(); /* Make sure i2400m_msg_to_dev() sees boot_mode */
599 return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle, 615 return i2400m_schedule_work(i2400m, __i2400m_dev_reset_handle,
600 GFP_ATOMIC); 616 GFP_ATOMIC);
601} 617}