diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-06-02 07:01:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-03 14:06:13 -0400 |
commit | 19d337dff95cbf76edd3ad95c0cee2732c3e1ec5 (patch) | |
tree | 33326eeb09cb9664cc8427a5dc7cd2b08b5a57c3 /drivers/net/usb/hso.c | |
parent | 0f6399c4c525b518644a9b09f8d6fb125a418c4d (diff) |
rfkill: rewrite
This patch completely rewrites the rfkill core to address
the following deficiencies:
* all rfkill drivers need to implement polling where necessary
rather than having one central implementation
* updating the rfkill state cannot be done from arbitrary
contexts, forcing drivers to use schedule_work and requiring
lots of code
* rfkill drivers need to keep track of soft/hard blocked
internally -- the core should do this
* the rfkill API has many unexpected quirks, for example being
asymmetric wrt. alloc/free and register/unregister
* rfkill can call back into a driver from within a function the
driver called -- this is prone to deadlocks and generally
should be avoided
* rfkill-input pointlessly is a separate module
* drivers need to #ifdef rfkill functions (unless they want to
depend on or select RFKILL) -- rfkill should provide inlines
that do nothing if it isn't compiled in
* the rfkill structure is not opaque -- drivers need to initialise
it correctly (lots of sanity checking code required) -- instead
force drivers to pass the right variables to rfkill_alloc()
* the documentation is hard to read because it always assumes the
reader is completely clueless and contains way TOO MANY CAPS
* the rfkill code needlessly uses a lot of locks and atomic
operations in locked sections
* fix LED trigger to actually change the LED when the radio state
changes -- this wasn't done before
Tested-by: Alan Jenkins <alan-jenkins@tuffmail.co.uk>
Signed-off-by: Henrique de Moraes Holschuh <hmh@hmh.eng.br> [thinkpad]
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/usb/hso.c')
-rw-r--r-- | drivers/net/usb/hso.c | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 837135f0390a..5ddd8c4f9019 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
@@ -2481,10 +2481,10 @@ static int add_net_device(struct hso_device *hso_dev) | |||
2481 | return 0; | 2481 | return 0; |
2482 | } | 2482 | } |
2483 | 2483 | ||
2484 | static int hso_radio_toggle(void *data, enum rfkill_state state) | 2484 | static int hso_rfkill_set_block(void *data, bool blocked) |
2485 | { | 2485 | { |
2486 | struct hso_device *hso_dev = data; | 2486 | struct hso_device *hso_dev = data; |
2487 | int enabled = (state == RFKILL_STATE_UNBLOCKED); | 2487 | int enabled = !blocked; |
2488 | int rv; | 2488 | int rv; |
2489 | 2489 | ||
2490 | mutex_lock(&hso_dev->mutex); | 2490 | mutex_lock(&hso_dev->mutex); |
@@ -2498,6 +2498,10 @@ static int hso_radio_toggle(void *data, enum rfkill_state state) | |||
2498 | return rv; | 2498 | return rv; |
2499 | } | 2499 | } |
2500 | 2500 | ||
2501 | static const struct rfkill_ops hso_rfkill_ops = { | ||
2502 | .set_block = hso_rfkill_set_block, | ||
2503 | }; | ||
2504 | |||
2501 | /* Creates and sets up everything for rfkill */ | 2505 | /* Creates and sets up everything for rfkill */ |
2502 | static void hso_create_rfkill(struct hso_device *hso_dev, | 2506 | static void hso_create_rfkill(struct hso_device *hso_dev, |
2503 | struct usb_interface *interface) | 2507 | struct usb_interface *interface) |
@@ -2506,29 +2510,25 @@ static void hso_create_rfkill(struct hso_device *hso_dev, | |||
2506 | struct device *dev = &hso_net->net->dev; | 2510 | struct device *dev = &hso_net->net->dev; |
2507 | char *rfkn; | 2511 | char *rfkn; |
2508 | 2512 | ||
2509 | hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev, | ||
2510 | RFKILL_TYPE_WWAN); | ||
2511 | if (!hso_net->rfkill) { | ||
2512 | dev_err(dev, "%s - Out of memory\n", __func__); | ||
2513 | return; | ||
2514 | } | ||
2515 | rfkn = kzalloc(20, GFP_KERNEL); | 2513 | rfkn = kzalloc(20, GFP_KERNEL); |
2516 | if (!rfkn) { | 2514 | if (!rfkn) |
2517 | rfkill_free(hso_net->rfkill); | ||
2518 | hso_net->rfkill = NULL; | ||
2519 | dev_err(dev, "%s - Out of memory\n", __func__); | 2515 | dev_err(dev, "%s - Out of memory\n", __func__); |
2520 | return; | 2516 | |
2521 | } | ||
2522 | snprintf(rfkn, 20, "hso-%d", | 2517 | snprintf(rfkn, 20, "hso-%d", |
2523 | interface->altsetting->desc.bInterfaceNumber); | 2518 | interface->altsetting->desc.bInterfaceNumber); |
2524 | hso_net->rfkill->name = rfkn; | 2519 | |
2525 | hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED; | 2520 | hso_net->rfkill = rfkill_alloc(rfkn, |
2526 | hso_net->rfkill->data = hso_dev; | 2521 | &interface_to_usbdev(interface)->dev, |
2527 | hso_net->rfkill->toggle_radio = hso_radio_toggle; | 2522 | RFKILL_TYPE_WWAN, |
2523 | &hso_rfkill_ops, hso_dev); | ||
2524 | if (!hso_net->rfkill) { | ||
2525 | dev_err(dev, "%s - Out of memory\n", __func__); | ||
2526 | kfree(rfkn); | ||
2527 | return; | ||
2528 | } | ||
2528 | if (rfkill_register(hso_net->rfkill) < 0) { | 2529 | if (rfkill_register(hso_net->rfkill) < 0) { |
2530 | rfkill_destroy(hso_net->rfkill); | ||
2529 | kfree(rfkn); | 2531 | kfree(rfkn); |
2530 | hso_net->rfkill->name = NULL; | ||
2531 | rfkill_free(hso_net->rfkill); | ||
2532 | hso_net->rfkill = NULL; | 2532 | hso_net->rfkill = NULL; |
2533 | dev_err(dev, "%s - Failed to register rfkill\n", __func__); | 2533 | dev_err(dev, "%s - Failed to register rfkill\n", __func__); |
2534 | return; | 2534 | return; |
@@ -3165,8 +3165,10 @@ static void hso_free_interface(struct usb_interface *interface) | |||
3165 | hso_stop_net_device(network_table[i]); | 3165 | hso_stop_net_device(network_table[i]); |
3166 | cancel_work_sync(&network_table[i]->async_put_intf); | 3166 | cancel_work_sync(&network_table[i]->async_put_intf); |
3167 | cancel_work_sync(&network_table[i]->async_get_intf); | 3167 | cancel_work_sync(&network_table[i]->async_get_intf); |
3168 | if (rfk) | 3168 | if (rfk) { |
3169 | rfkill_unregister(rfk); | 3169 | rfkill_unregister(rfk); |
3170 | rfkill_destroy(rfk); | ||
3171 | } | ||
3170 | hso_free_net_device(network_table[i]); | 3172 | hso_free_net_device(network_table[i]); |
3171 | } | 3173 | } |
3172 | } | 3174 | } |