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>
This commit is contained in:

committed by
John W. Linville

parent
0f6399c4c5
commit
19d337dff9
@@ -2481,10 +2481,10 @@ static int add_net_device(struct hso_device *hso_dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hso_radio_toggle(void *data, enum rfkill_state state)
|
||||
static int hso_rfkill_set_block(void *data, bool blocked)
|
||||
{
|
||||
struct hso_device *hso_dev = data;
|
||||
int enabled = (state == RFKILL_STATE_UNBLOCKED);
|
||||
int enabled = !blocked;
|
||||
int rv;
|
||||
|
||||
mutex_lock(&hso_dev->mutex);
|
||||
@@ -2498,6 +2498,10 @@ static int hso_radio_toggle(void *data, enum rfkill_state state)
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const struct rfkill_ops hso_rfkill_ops = {
|
||||
.set_block = hso_rfkill_set_block,
|
||||
};
|
||||
|
||||
/* Creates and sets up everything for rfkill */
|
||||
static void hso_create_rfkill(struct hso_device *hso_dev,
|
||||
struct usb_interface *interface)
|
||||
@@ -2506,29 +2510,25 @@ static void hso_create_rfkill(struct hso_device *hso_dev,
|
||||
struct device *dev = &hso_net->net->dev;
|
||||
char *rfkn;
|
||||
|
||||
hso_net->rfkill = rfkill_allocate(&interface_to_usbdev(interface)->dev,
|
||||
RFKILL_TYPE_WWAN);
|
||||
if (!hso_net->rfkill) {
|
||||
dev_err(dev, "%s - Out of memory\n", __func__);
|
||||
return;
|
||||
}
|
||||
rfkn = kzalloc(20, GFP_KERNEL);
|
||||
if (!rfkn) {
|
||||
rfkill_free(hso_net->rfkill);
|
||||
hso_net->rfkill = NULL;
|
||||
if (!rfkn)
|
||||
dev_err(dev, "%s - Out of memory\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(rfkn, 20, "hso-%d",
|
||||
interface->altsetting->desc.bInterfaceNumber);
|
||||
hso_net->rfkill->name = rfkn;
|
||||
hso_net->rfkill->state = RFKILL_STATE_UNBLOCKED;
|
||||
hso_net->rfkill->data = hso_dev;
|
||||
hso_net->rfkill->toggle_radio = hso_radio_toggle;
|
||||
if (rfkill_register(hso_net->rfkill) < 0) {
|
||||
|
||||
hso_net->rfkill = rfkill_alloc(rfkn,
|
||||
&interface_to_usbdev(interface)->dev,
|
||||
RFKILL_TYPE_WWAN,
|
||||
&hso_rfkill_ops, hso_dev);
|
||||
if (!hso_net->rfkill) {
|
||||
dev_err(dev, "%s - Out of memory\n", __func__);
|
||||
kfree(rfkn);
|
||||
return;
|
||||
}
|
||||
if (rfkill_register(hso_net->rfkill) < 0) {
|
||||
rfkill_destroy(hso_net->rfkill);
|
||||
kfree(rfkn);
|
||||
hso_net->rfkill->name = NULL;
|
||||
rfkill_free(hso_net->rfkill);
|
||||
hso_net->rfkill = NULL;
|
||||
dev_err(dev, "%s - Failed to register rfkill\n", __func__);
|
||||
return;
|
||||
@@ -3165,8 +3165,10 @@ static void hso_free_interface(struct usb_interface *interface)
|
||||
hso_stop_net_device(network_table[i]);
|
||||
cancel_work_sync(&network_table[i]->async_put_intf);
|
||||
cancel_work_sync(&network_table[i]->async_get_intf);
|
||||
if (rfk)
|
||||
if (rfk) {
|
||||
rfkill_unregister(rfk);
|
||||
rfkill_destroy(rfk);
|
||||
}
|
||||
hso_free_net_device(network_table[i]);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user