aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb/hso.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-06-02 07:01:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-06-03 14:06:13 -0400
commit19d337dff95cbf76edd3ad95c0cee2732c3e1ec5 (patch)
tree33326eeb09cb9664cc8427a5dc7cd2b08b5a57c3 /drivers/net/usb/hso.c
parent0f6399c4c525b518644a9b09f8d6fb125a418c4d (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.c42
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
2484static int hso_radio_toggle(void *data, enum rfkill_state state) 2484static 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
2501static 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 */
2502static void hso_create_rfkill(struct hso_device *hso_dev, 2506static 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 }