diff options
| -rw-r--r-- | drivers/net/wireless/b43/main.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/rfkill.c | 119 | ||||
| -rw-r--r-- | drivers/net/wireless/b43/rfkill.h | 14 |
3 files changed, 55 insertions, 80 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5058e60e5703..c9778c6cf2e8 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
| @@ -3661,7 +3661,6 @@ static int b43_setup_modes(struct b43_wldev *dev, | |||
| 3661 | 3661 | ||
| 3662 | static void b43_wireless_core_detach(struct b43_wldev *dev) | 3662 | static void b43_wireless_core_detach(struct b43_wldev *dev) |
| 3663 | { | 3663 | { |
| 3664 | b43_rfkill_free(dev); | ||
| 3665 | /* We release firmware that late to not be required to re-request | 3664 | /* We release firmware that late to not be required to re-request |
| 3666 | * is all the time when we reinit the core. */ | 3665 | * is all the time when we reinit the core. */ |
| 3667 | b43_release_firmware(dev); | 3666 | b43_release_firmware(dev); |
| @@ -3747,7 +3746,6 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
| 3747 | if (!wl->current_dev) | 3746 | if (!wl->current_dev) |
| 3748 | wl->current_dev = dev; | 3747 | wl->current_dev = dev; |
| 3749 | INIT_WORK(&dev->restart_work, b43_chip_reset); | 3748 | INIT_WORK(&dev->restart_work, b43_chip_reset); |
| 3750 | b43_rfkill_alloc(dev); | ||
| 3751 | 3749 | ||
| 3752 | b43_radio_turn_off(dev, 1); | 3750 | b43_radio_turn_off(dev, 1); |
| 3753 | b43_switch_analog(dev, 0); | 3751 | b43_switch_analog(dev, 0); |
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c index 456930ffef2d..9b1f905ffbf4 100644 --- a/drivers/net/wireless/b43/rfkill.c +++ b/drivers/net/wireless/b43/rfkill.c | |||
| @@ -47,18 +47,21 @@ static void b43_rfkill_poll(struct input_polled_dev *poll_dev) | |||
| 47 | struct b43_wldev *dev = poll_dev->private; | 47 | struct b43_wldev *dev = poll_dev->private; |
| 48 | struct b43_wl *wl = dev->wl; | 48 | struct b43_wl *wl = dev->wl; |
| 49 | bool enabled; | 49 | bool enabled; |
| 50 | bool report_change = 0; | ||
| 50 | 51 | ||
| 51 | mutex_lock(&wl->mutex); | 52 | mutex_lock(&wl->mutex); |
| 52 | B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); | 53 | B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); |
| 53 | enabled = b43_is_hw_radio_enabled(dev); | 54 | enabled = b43_is_hw_radio_enabled(dev); |
| 54 | if (unlikely(enabled != dev->radio_hw_enable)) { | 55 | if (unlikely(enabled != dev->radio_hw_enable)) { |
| 55 | dev->radio_hw_enable = enabled; | 56 | dev->radio_hw_enable = enabled; |
| 57 | report_change = 1; | ||
| 56 | b43info(wl, "Radio hardware status changed to %s\n", | 58 | b43info(wl, "Radio hardware status changed to %s\n", |
| 57 | enabled ? "ENABLED" : "DISABLED"); | 59 | enabled ? "ENABLED" : "DISABLED"); |
| 58 | mutex_unlock(&wl->mutex); | 60 | } |
| 61 | mutex_unlock(&wl->mutex); | ||
| 62 | |||
| 63 | if (unlikely(report_change)) | ||
| 59 | input_report_key(poll_dev->input, KEY_WLAN, enabled); | 64 | input_report_key(poll_dev->input, KEY_WLAN, enabled); |
| 60 | } else | ||
| 61 | mutex_unlock(&wl->mutex); | ||
| 62 | } | 65 | } |
| 63 | 66 | ||
| 64 | /* Called when the RFKILL toggled in software. */ | 67 | /* Called when the RFKILL toggled in software. */ |
| @@ -68,18 +71,11 @@ static int b43_rfkill_soft_toggle(void *data, enum rfkill_state state) | |||
| 68 | struct b43_wl *wl = dev->wl; | 71 | struct b43_wl *wl = dev->wl; |
| 69 | int err = 0; | 72 | int err = 0; |
| 70 | 73 | ||
| 71 | /* When RFKILL is registered, it will call back into this callback. | 74 | if (!wl->rfkill.registered) |
| 72 | * wl->mutex will already be locked when this happens. | 75 | return 0; |
| 73 | * So first trylock. On contention check if we are in initialization. | ||
| 74 | * Silently return if that happens to avoid a deadlock. */ | ||
| 75 | if (mutex_trylock(&wl->mutex) == 0) { | ||
| 76 | if (b43_status(dev) < B43_STAT_INITIALIZED) | ||
| 77 | return 0; | ||
| 78 | mutex_lock(&wl->mutex); | ||
| 79 | } | ||
| 80 | if (b43_status(dev) < B43_STAT_INITIALIZED) | ||
| 81 | goto out_unlock; | ||
| 82 | 76 | ||
| 77 | mutex_lock(&wl->mutex); | ||
| 78 | B43_WARN_ON(b43_status(dev) < B43_STAT_INITIALIZED); | ||
| 83 | switch (state) { | 79 | switch (state) { |
| 84 | case RFKILL_STATE_ON: | 80 | case RFKILL_STATE_ON: |
| 85 | if (!dev->radio_hw_enable) { | 81 | if (!dev->radio_hw_enable) { |
| @@ -104,11 +100,11 @@ out_unlock: | |||
| 104 | 100 | ||
| 105 | char * b43_rfkill_led_name(struct b43_wldev *dev) | 101 | char * b43_rfkill_led_name(struct b43_wldev *dev) |
| 106 | { | 102 | { |
| 107 | struct b43_wl *wl = dev->wl; | 103 | struct b43_rfkill *rfk = &(dev->wl->rfkill); |
| 108 | 104 | ||
| 109 | if (!wl->rfkill.rfkill) | 105 | if (!rfk->registered) |
| 110 | return NULL; | 106 | return NULL; |
| 111 | return rfkill_get_led_name(wl->rfkill.rfkill); | 107 | return rfkill_get_led_name(rfk->rfkill); |
| 112 | } | 108 | } |
| 113 | 109 | ||
| 114 | void b43_rfkill_init(struct b43_wldev *dev) | 110 | void b43_rfkill_init(struct b43_wldev *dev) |
| @@ -117,53 +113,13 @@ void b43_rfkill_init(struct b43_wldev *dev) | |||
| 117 | struct b43_rfkill *rfk = &(wl->rfkill); | 113 | struct b43_rfkill *rfk = &(wl->rfkill); |
| 118 | int err; | 114 | int err; |
| 119 | 115 | ||
| 120 | if (rfk->rfkill) { | 116 | rfk->registered = 0; |
| 121 | err = rfkill_register(rfk->rfkill); | ||
| 122 | if (err) { | ||
| 123 | b43warn(wl, "Failed to register RF-kill button\n"); | ||
| 124 | goto err_free_rfk; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | if (rfk->poll_dev) { | ||
| 128 | err = input_register_polled_device(rfk->poll_dev); | ||
| 129 | if (err) { | ||
| 130 | b43warn(wl, "Failed to register RF-kill polldev\n"); | ||
| 131 | goto err_free_polldev; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | return; | ||
| 136 | err_free_rfk: | ||
| 137 | rfkill_free(rfk->rfkill); | ||
| 138 | rfk->rfkill = NULL; | ||
| 139 | err_free_polldev: | ||
| 140 | input_free_polled_device(rfk->poll_dev); | ||
| 141 | rfk->poll_dev = NULL; | ||
| 142 | } | ||
| 143 | |||
| 144 | void b43_rfkill_exit(struct b43_wldev *dev) | ||
| 145 | { | ||
| 146 | struct b43_rfkill *rfk = &(dev->wl->rfkill); | ||
| 147 | |||
| 148 | if (rfk->poll_dev) | ||
| 149 | input_unregister_polled_device(rfk->poll_dev); | ||
| 150 | if (rfk->rfkill) | ||
| 151 | rfkill_unregister(rfk->rfkill); | ||
| 152 | } | ||
| 153 | |||
| 154 | void b43_rfkill_alloc(struct b43_wldev *dev) | ||
| 155 | { | ||
| 156 | struct b43_wl *wl = dev->wl; | ||
| 157 | struct b43_rfkill *rfk = &(wl->rfkill); | ||
| 158 | 117 | ||
| 118 | rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); | ||
| 119 | if (!rfk->rfkill) | ||
| 120 | goto out_error; | ||
| 159 | snprintf(rfk->name, sizeof(rfk->name), | 121 | snprintf(rfk->name, sizeof(rfk->name), |
| 160 | "b43-%s", wiphy_name(wl->hw->wiphy)); | 122 | "b43-%s", wiphy_name(wl->hw->wiphy)); |
| 161 | |||
| 162 | rfk->rfkill = rfkill_allocate(dev->dev->dev, RFKILL_TYPE_WLAN); | ||
| 163 | if (!rfk->rfkill) { | ||
| 164 | b43warn(wl, "Failed to allocate RF-kill button\n"); | ||
| 165 | return; | ||
| 166 | } | ||
| 167 | rfk->rfkill->name = rfk->name; | 123 | rfk->rfkill->name = rfk->name; |
| 168 | rfk->rfkill->state = RFKILL_STATE_ON; | 124 | rfk->rfkill->state = RFKILL_STATE_ON; |
| 169 | rfk->rfkill->data = dev; | 125 | rfk->rfkill->data = dev; |
| @@ -171,18 +127,45 @@ void b43_rfkill_alloc(struct b43_wldev *dev) | |||
| 171 | rfk->rfkill->user_claim_unsupported = 1; | 127 | rfk->rfkill->user_claim_unsupported = 1; |
| 172 | 128 | ||
| 173 | rfk->poll_dev = input_allocate_polled_device(); | 129 | rfk->poll_dev = input_allocate_polled_device(); |
| 174 | if (rfk->poll_dev) { | 130 | if (!rfk->poll_dev) |
| 175 | rfk->poll_dev->private = dev; | 131 | goto err_free_rfk; |
| 176 | rfk->poll_dev->poll = b43_rfkill_poll; | 132 | rfk->poll_dev->private = dev; |
| 177 | rfk->poll_dev->poll_interval = 1000; /* msecs */ | 133 | rfk->poll_dev->poll = b43_rfkill_poll; |
| 178 | } else | 134 | rfk->poll_dev->poll_interval = 1000; /* msecs */ |
| 179 | b43warn(wl, "Failed to allocate RF-kill polldev\n"); | 135 | |
| 136 | err = rfkill_register(rfk->rfkill); | ||
| 137 | if (err) | ||
| 138 | goto err_free_polldev; | ||
| 139 | err = input_register_polled_device(rfk->poll_dev); | ||
| 140 | if (err) | ||
| 141 | goto err_unreg_rfk; | ||
| 142 | |||
| 143 | rfk->registered = 1; | ||
| 144 | |||
| 145 | return; | ||
| 146 | err_unreg_rfk: | ||
| 147 | rfkill_unregister(rfk->rfkill); | ||
| 148 | err_free_polldev: | ||
| 149 | input_free_polled_device(rfk->poll_dev); | ||
| 150 | rfk->poll_dev = NULL; | ||
| 151 | err_free_rfk: | ||
| 152 | rfkill_free(rfk->rfkill); | ||
| 153 | rfk->rfkill = NULL; | ||
| 154 | out_error: | ||
| 155 | rfk->registered = 0; | ||
| 156 | b43warn(wl, "RF-kill button init failed\n"); | ||
| 180 | } | 157 | } |
| 181 | 158 | ||
| 182 | void b43_rfkill_free(struct b43_wldev *dev) | 159 | void b43_rfkill_exit(struct b43_wldev *dev) |
| 183 | { | 160 | { |
| 184 | struct b43_rfkill *rfk = &(dev->wl->rfkill); | 161 | struct b43_rfkill *rfk = &(dev->wl->rfkill); |
| 185 | 162 | ||
| 163 | if (!rfk->registered) | ||
| 164 | return; | ||
| 165 | rfk->registered = 0; | ||
| 166 | |||
| 167 | input_unregister_polled_device(rfk->poll_dev); | ||
| 168 | rfkill_unregister(rfk->rfkill); | ||
| 186 | input_free_polled_device(rfk->poll_dev); | 169 | input_free_polled_device(rfk->poll_dev); |
| 187 | rfk->poll_dev = NULL; | 170 | rfk->poll_dev = NULL; |
| 188 | rfkill_free(rfk->rfkill); | 171 | rfkill_free(rfk->rfkill); |
diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h index 29544e8c9e5f..adacf936d815 100644 --- a/drivers/net/wireless/b43/rfkill.h +++ b/drivers/net/wireless/b43/rfkill.h | |||
| @@ -15,14 +15,14 @@ struct b43_rfkill { | |||
| 15 | struct rfkill *rfkill; | 15 | struct rfkill *rfkill; |
| 16 | /* The poll device for the RFKILL input button */ | 16 | /* The poll device for the RFKILL input button */ |
| 17 | struct input_polled_dev *poll_dev; | 17 | struct input_polled_dev *poll_dev; |
| 18 | /* Did initialization succeed? Used for freeing. */ | ||
| 19 | bool registered; | ||
| 18 | /* The unique name of this rfkill switch */ | 20 | /* The unique name of this rfkill switch */ |
| 19 | char name[32]; | 21 | char name[sizeof("b43-phy4294967295")]; |
| 20 | }; | 22 | }; |
| 21 | 23 | ||
| 22 | /* All the init functions return void, because we are not interested | 24 | /* The init function returns void, because we are not interested |
| 23 | * in failing the b43 init process when rfkill init failed. */ | 25 | * in failing the b43 init process when rfkill init failed. */ |
| 24 | void b43_rfkill_alloc(struct b43_wldev *dev); | ||
| 25 | void b43_rfkill_free(struct b43_wldev *dev); | ||
| 26 | void b43_rfkill_init(struct b43_wldev *dev); | 26 | void b43_rfkill_init(struct b43_wldev *dev); |
| 27 | void b43_rfkill_exit(struct b43_wldev *dev); | 27 | void b43_rfkill_exit(struct b43_wldev *dev); |
| 28 | 28 | ||
| @@ -36,12 +36,6 @@ struct b43_rfkill { | |||
| 36 | /* empty */ | 36 | /* empty */ |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | static inline void b43_rfkill_alloc(struct b43_wldev *dev) | ||
| 40 | { | ||
| 41 | } | ||
| 42 | static inline void b43_rfkill_free(struct b43_wldev *dev) | ||
| 43 | { | ||
| 44 | } | ||
| 45 | static inline void b43_rfkill_init(struct b43_wldev *dev) | 39 | static inline void b43_rfkill_init(struct b43_wldev *dev) |
| 46 | { | 40 | { |
| 47 | } | 41 | } |
