diff options
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00rfkill.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00rfkill.c | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 8a2fefb365b7..55eff58f1889 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -45,16 +45,15 @@ static int rt2x00rfkill_toggle_radio(void *data, enum rfkill_state state) | |||
45 | return 0; | 45 | return 0; |
46 | 46 | ||
47 | if (state == RFKILL_STATE_UNBLOCKED) { | 47 | if (state == RFKILL_STATE_UNBLOCKED) { |
48 | INFO(rt2x00dev, "Hardware button pressed, enabling radio.\n"); | 48 | INFO(rt2x00dev, "RFKILL event: enabling radio.\n"); |
49 | clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); | 49 | clear_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); |
50 | retval = rt2x00lib_enable_radio(rt2x00dev); | 50 | retval = rt2x00lib_enable_radio(rt2x00dev); |
51 | } else if (state == RFKILL_STATE_SOFT_BLOCKED) { | 51 | } else if (state == RFKILL_STATE_SOFT_BLOCKED) { |
52 | INFO(rt2x00dev, "Hardware button pressed, disabling radio.\n"); | 52 | INFO(rt2x00dev, "RFKILL event: disabling radio.\n"); |
53 | set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); | 53 | set_bit(DEVICE_STATE_DISABLED_RADIO_HW, &rt2x00dev->flags); |
54 | rt2x00lib_disable_radio(rt2x00dev); | 54 | rt2x00lib_disable_radio(rt2x00dev); |
55 | } else { | 55 | } else { |
56 | WARNING(rt2x00dev, "Received unexpected rfkill state %d.\n", | 56 | WARNING(rt2x00dev, "RFKILL event: unknown state %d.\n", state); |
57 | state); | ||
58 | } | 57 | } |
59 | 58 | ||
60 | return retval; | 59 | return retval; |
@@ -64,7 +63,12 @@ static int rt2x00rfkill_get_state(void *data, enum rfkill_state *state) | |||
64 | { | 63 | { |
65 | struct rt2x00_dev *rt2x00dev = data; | 64 | struct rt2x00_dev *rt2x00dev = data; |
66 | 65 | ||
67 | *state = rt2x00dev->rfkill->state; | 66 | /* |
67 | * rfkill_poll reports 1 when the key has been pressed and the | ||
68 | * radio should be blocked. | ||
69 | */ | ||
70 | *state = rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? | ||
71 | RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; | ||
68 | 72 | ||
69 | return 0; | 73 | return 0; |
70 | } | 74 | } |
@@ -73,19 +77,18 @@ static void rt2x00rfkill_poll(struct work_struct *work) | |||
73 | { | 77 | { |
74 | struct rt2x00_dev *rt2x00dev = | 78 | struct rt2x00_dev *rt2x00dev = |
75 | container_of(work, struct rt2x00_dev, rfkill_work.work); | 79 | container_of(work, struct rt2x00_dev, rfkill_work.work); |
76 | int state; | 80 | enum rfkill_state state; |
77 | 81 | ||
78 | if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) | 82 | if (!test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state) || |
83 | !test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) | ||
79 | return; | 84 | return; |
80 | 85 | ||
81 | /* | 86 | /* |
82 | * rfkill_poll reports 1 when the key has been pressed and the | 87 | * Poll latest state and report it to rfkill who should sort |
83 | * radio should be blocked. | 88 | * out if the state should be toggled or not. |
84 | */ | 89 | */ |
85 | state = !rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? | 90 | if (!rt2x00rfkill_get_state(rt2x00dev, &state)) |
86 | RFKILL_STATE_UNBLOCKED : RFKILL_STATE_SOFT_BLOCKED; | 91 | rfkill_force_state(rt2x00dev->rfkill, state); |
87 | |||
88 | rfkill_force_state(rt2x00dev->rfkill, state); | ||
89 | 92 | ||
90 | queue_delayed_work(rt2x00dev->hw->workqueue, | 93 | queue_delayed_work(rt2x00dev->hw->workqueue, |
91 | &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); | 94 | &rt2x00dev->rfkill_work, RFKILL_POLL_INTERVAL); |
@@ -93,8 +96,8 @@ static void rt2x00rfkill_poll(struct work_struct *work) | |||
93 | 96 | ||
94 | void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | 97 | void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) |
95 | { | 98 | { |
96 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || | 99 | if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) || |
97 | !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | 100 | test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) |
98 | return; | 101 | return; |
99 | 102 | ||
100 | if (rfkill_register(rt2x00dev->rfkill)) { | 103 | if (rfkill_register(rt2x00dev->rfkill)) { |
@@ -114,7 +117,7 @@ void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) | |||
114 | 117 | ||
115 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) | 118 | void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) |
116 | { | 119 | { |
117 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || | 120 | if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state) || |
118 | !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) | 121 | !test_bit(RFKILL_STATE_REGISTERED, &rt2x00dev->rfkill_state)) |
119 | return; | 122 | return; |
120 | 123 | ||
@@ -127,21 +130,25 @@ void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) | |||
127 | 130 | ||
128 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | 131 | void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) |
129 | { | 132 | { |
130 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) | 133 | struct device *dev = wiphy_dev(rt2x00dev->hw->wiphy); |
134 | |||
135 | if (test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | ||
131 | return; | 136 | return; |
132 | 137 | ||
133 | rt2x00dev->rfkill = | 138 | rt2x00dev->rfkill = rfkill_allocate(dev, RFKILL_TYPE_WLAN); |
134 | rfkill_allocate(wiphy_dev(rt2x00dev->hw->wiphy), RFKILL_TYPE_WLAN); | ||
135 | if (!rt2x00dev->rfkill) { | 139 | if (!rt2x00dev->rfkill) { |
136 | ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); | 140 | ERROR(rt2x00dev, "Failed to allocate rfkill handler.\n"); |
137 | return; | 141 | return; |
138 | } | 142 | } |
139 | 143 | ||
144 | __set_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state); | ||
145 | |||
140 | rt2x00dev->rfkill->name = rt2x00dev->ops->name; | 146 | rt2x00dev->rfkill->name = rt2x00dev->ops->name; |
141 | rt2x00dev->rfkill->data = rt2x00dev; | 147 | rt2x00dev->rfkill->data = rt2x00dev; |
142 | rt2x00dev->rfkill->state = -1; | 148 | rt2x00dev->rfkill->state = -1; |
143 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; | 149 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; |
144 | rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; | 150 | if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) |
151 | rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; | ||
145 | 152 | ||
146 | INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); | 153 | INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); |
147 | 154 | ||
@@ -150,8 +157,7 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | |||
150 | 157 | ||
151 | void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) | 158 | void rt2x00rfkill_free(struct rt2x00_dev *rt2x00dev) |
152 | { | 159 | { |
153 | if (!test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags) || | 160 | if (!test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->flags)) |
154 | !test_bit(RFKILL_STATE_ALLOCATED, &rt2x00dev->rfkill_state)) | ||
155 | return; | 161 | return; |
156 | 162 | ||
157 | cancel_delayed_work_sync(&rt2x00dev->rfkill_work); | 163 | cancel_delayed_work_sync(&rt2x00dev->rfkill_work); |