diff options
author | David S. Miller <davem@davemloft.net> | 2009-06-11 20:11:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-06-11 20:11:33 -0400 |
commit | 3ee40c376ad3252d13946141588db7e2f435f958 (patch) | |
tree | 65bd16c024edab1ff74ad165779443edfaa26467 /drivers/net/wimax/i2400m/driver.c | |
parent | 670025478c2a687453cd1bac697d7d765843f59d (diff) | |
parent | 98eb0f53e2fc66482e2ea8033c58b20a079e5260 (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.c | 40 |
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); | |||
82 | MODULE_PARM_DESC(rx_reorder_disabled, | 82 | MODULE_PARM_DESC(rx_reorder_disabled, |
83 | "If true, RX reordering will be disabled."); | 83 | "If true, RX reordering will be disabled."); |
84 | 84 | ||
85 | int i2400m_power_save_disabled; /* 0 (power saving enabled) by default */ | ||
86 | module_param_named(power_save_disabled, i2400m_power_save_disabled, int, 0644); | ||
87 | MODULE_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); |
393 | retry: | 405 | retry: |
@@ -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: | |||
432 | error_dev_initialize: | 444 | error_dev_initialize: |
433 | error_check_mac_addr: | 445 | error_check_mac_addr: |
434 | error_fw_check: | 446 | error_fw_check: |
435 | destroy_workqueue(i2400m->work_queue); | ||
436 | error_create_workqueue: | ||
437 | i2400m->bus_dev_stop(i2400m); | 447 | i2400m->bus_dev_stop(i2400m); |
438 | error_bus_dev_start: | 448 | error_bus_dev_start: |
449 | destroy_workqueue(i2400m->work_queue); | ||
450 | error_create_workqueue: | ||
439 | i2400m_rx_release(i2400m); | 451 | i2400m_rx_release(i2400m); |
440 | error_rx_setup: | 452 | error_rx_setup: |
441 | i2400m_tx_release(i2400m); | 453 | i2400m_tx_release(i2400m); |
442 | error_tx_setup: | 454 | error_tx_setup: |
443 | error_bootstrap: | 455 | error_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 | */ |
476 | static | 490 | static |
477 | void __i2400m_dev_stop(struct i2400m *i2400m) | 491 | void __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 | */ |
597 | int i2400m_dev_reset_handle(struct i2400m *i2400m) | 611 | int 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 | } |