diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1251_main.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1251_main.c | 141 |
1 files changed, 119 insertions, 22 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 4c1aad33fb51..8c88fe279ec6 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -32,7 +32,6 @@ | |||
32 | #include "wl1251.h" | 32 | #include "wl1251.h" |
33 | #include "wl12xx_80211.h" | 33 | #include "wl12xx_80211.h" |
34 | #include "reg.h" | 34 | #include "reg.h" |
35 | #include "wl1251_ops.h" | ||
36 | #include "wl1251_io.h" | 35 | #include "wl1251_io.h" |
37 | #include "wl1251_cmd.h" | 36 | #include "wl1251_cmd.h" |
38 | #include "wl1251_event.h" | 37 | #include "wl1251_event.h" |
@@ -41,6 +40,7 @@ | |||
41 | #include "wl1251_ps.h" | 40 | #include "wl1251_ps.h" |
42 | #include "wl1251_init.h" | 41 | #include "wl1251_init.h" |
43 | #include "wl1251_debugfs.h" | 42 | #include "wl1251_debugfs.h" |
43 | #include "wl1251_boot.h" | ||
44 | 44 | ||
45 | void wl1251_enable_interrupts(struct wl1251 *wl) | 45 | void wl1251_enable_interrupts(struct wl1251 *wl) |
46 | { | 46 | { |
@@ -68,7 +68,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl) | |||
68 | struct device *dev = wiphy_dev(wl->hw->wiphy); | 68 | struct device *dev = wiphy_dev(wl->hw->wiphy); |
69 | int ret; | 69 | int ret; |
70 | 70 | ||
71 | ret = request_firmware(&fw, wl->chip.fw_filename, dev); | 71 | ret = request_firmware(&fw, WL1251_FW_NAME, dev); |
72 | 72 | ||
73 | if (ret < 0) { | 73 | if (ret < 0) { |
74 | wl1251_error("could not get firmware: %d", ret); | 74 | wl1251_error("could not get firmware: %d", ret); |
@@ -107,7 +107,7 @@ static int wl1251_fetch_nvs(struct wl1251 *wl) | |||
107 | struct device *dev = wiphy_dev(wl->hw->wiphy); | 107 | struct device *dev = wiphy_dev(wl->hw->wiphy); |
108 | int ret; | 108 | int ret; |
109 | 109 | ||
110 | ret = request_firmware(&fw, wl->chip.nvs_filename, dev); | 110 | ret = request_firmware(&fw, WL1251_NVS_NAME, dev); |
111 | 111 | ||
112 | if (ret < 0) { | 112 | if (ret < 0) { |
113 | wl1251_error("could not get nvs file: %d", ret); | 113 | wl1251_error("could not get nvs file: %d", ret); |
@@ -157,7 +157,7 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) | |||
157 | int ret = 0; | 157 | int ret = 0; |
158 | 158 | ||
159 | wl1251_power_on(wl); | 159 | wl1251_power_on(wl); |
160 | msleep(wl->chip.power_on_sleep); | 160 | msleep(WL1251_POWER_ON_SLEEP); |
161 | wl->if_ops->reset(wl); | 161 | wl->if_ops->reset(wl); |
162 | 162 | ||
163 | /* We don't need a real memory partition here, because we only want | 163 | /* We don't need a real memory partition here, because we only want |
@@ -174,22 +174,19 @@ static int wl1251_chip_wakeup(struct wl1251 *wl) | |||
174 | /* whal_FwCtrl_BootSm() */ | 174 | /* whal_FwCtrl_BootSm() */ |
175 | 175 | ||
176 | /* 0. read chip id from CHIP_ID */ | 176 | /* 0. read chip id from CHIP_ID */ |
177 | wl->chip.id = wl1251_reg_read32(wl, CHIP_ID_B); | 177 | wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B); |
178 | 178 | ||
179 | /* 1. check if chip id is valid */ | 179 | /* 1. check if chip id is valid */ |
180 | 180 | ||
181 | switch (wl->chip.id) { | 181 | switch (wl->chip_id) { |
182 | case CHIP_ID_1251_PG12: | 182 | case CHIP_ID_1251_PG12: |
183 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", | 183 | wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", |
184 | wl->chip.id); | 184 | wl->chip_id); |
185 | |||
186 | wl1251_setup(wl); | ||
187 | |||
188 | break; | 185 | break; |
189 | case CHIP_ID_1251_PG10: | 186 | case CHIP_ID_1251_PG10: |
190 | case CHIP_ID_1251_PG11: | 187 | case CHIP_ID_1251_PG11: |
191 | default: | 188 | default: |
192 | wl1251_error("unsupported chip id: 0x%x", wl->chip.id); | 189 | wl1251_error("unsupported chip id: 0x%x", wl->chip_id); |
193 | ret = -ENODEV; | 190 | ret = -ENODEV; |
194 | goto out; | 191 | goto out; |
195 | } | 192 | } |
@@ -211,6 +208,107 @@ out: | |||
211 | return ret; | 208 | return ret; |
212 | } | 209 | } |
213 | 210 | ||
211 | static void wl1251_irq_work(struct work_struct *work) | ||
212 | { | ||
213 | u32 intr; | ||
214 | struct wl1251 *wl = | ||
215 | container_of(work, struct wl1251, irq_work); | ||
216 | int ret; | ||
217 | |||
218 | mutex_lock(&wl->mutex); | ||
219 | |||
220 | wl1251_debug(DEBUG_IRQ, "IRQ work"); | ||
221 | |||
222 | if (wl->state == WL1251_STATE_OFF) | ||
223 | goto out; | ||
224 | |||
225 | ret = wl1251_ps_elp_wakeup(wl); | ||
226 | if (ret < 0) | ||
227 | goto out; | ||
228 | |||
229 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL); | ||
230 | |||
231 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); | ||
232 | wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); | ||
233 | |||
234 | if (wl->data_path) { | ||
235 | wl->rx_counter = | ||
236 | wl1251_mem_read32(wl, wl->data_path->rx_control_addr); | ||
237 | |||
238 | /* We handle a frmware bug here */ | ||
239 | switch ((wl->rx_counter - wl->rx_handled) & 0xf) { | ||
240 | case 0: | ||
241 | wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); | ||
242 | intr &= ~WL1251_ACX_INTR_RX0_DATA; | ||
243 | intr &= ~WL1251_ACX_INTR_RX1_DATA; | ||
244 | break; | ||
245 | case 1: | ||
246 | wl1251_debug(DEBUG_IRQ, "RX: FW +1"); | ||
247 | intr |= WL1251_ACX_INTR_RX0_DATA; | ||
248 | intr &= ~WL1251_ACX_INTR_RX1_DATA; | ||
249 | break; | ||
250 | case 2: | ||
251 | wl1251_debug(DEBUG_IRQ, "RX: FW +2"); | ||
252 | intr |= WL1251_ACX_INTR_RX0_DATA; | ||
253 | intr |= WL1251_ACX_INTR_RX1_DATA; | ||
254 | break; | ||
255 | default: | ||
256 | wl1251_warning("RX: FW and host out of sync: %d", | ||
257 | wl->rx_counter - wl->rx_handled); | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | wl->rx_handled = wl->rx_counter; | ||
262 | |||
263 | |||
264 | wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter); | ||
265 | } | ||
266 | |||
267 | intr &= wl->intr_mask; | ||
268 | |||
269 | if (intr == 0) { | ||
270 | wl1251_debug(DEBUG_IRQ, "INTR is 0"); | ||
271 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | ||
272 | ~(wl->intr_mask)); | ||
273 | |||
274 | goto out_sleep; | ||
275 | } | ||
276 | |||
277 | if (intr & WL1251_ACX_INTR_RX0_DATA) { | ||
278 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); | ||
279 | wl1251_rx(wl); | ||
280 | } | ||
281 | |||
282 | if (intr & WL1251_ACX_INTR_RX1_DATA) { | ||
283 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); | ||
284 | wl1251_rx(wl); | ||
285 | } | ||
286 | |||
287 | if (intr & WL1251_ACX_INTR_TX_RESULT) { | ||
288 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); | ||
289 | wl1251_tx_complete(wl); | ||
290 | } | ||
291 | |||
292 | if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) { | ||
293 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr); | ||
294 | if (intr & WL1251_ACX_INTR_EVENT_A) | ||
295 | wl1251_event_handle(wl, 0); | ||
296 | else | ||
297 | wl1251_event_handle(wl, 1); | ||
298 | } | ||
299 | |||
300 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) | ||
301 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); | ||
302 | |||
303 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); | ||
304 | |||
305 | out_sleep: | ||
306 | wl1251_ps_elp_sleep(wl); | ||
307 | |||
308 | out: | ||
309 | mutex_unlock(&wl->mutex); | ||
310 | } | ||
311 | |||
214 | static void wl1251_filter_work(struct work_struct *work) | 312 | static void wl1251_filter_work(struct work_struct *work) |
215 | { | 313 | { |
216 | struct wl1251 *wl = | 314 | struct wl1251 *wl = |
@@ -227,7 +325,7 @@ static void wl1251_filter_work(struct work_struct *work) | |||
227 | goto out; | 325 | goto out; |
228 | 326 | ||
229 | /* FIXME: replace the magic numbers with proper definitions */ | 327 | /* FIXME: replace the magic numbers with proper definitions */ |
230 | ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); | 328 | ret = wl1251_cmd_join(wl, wl->bss_type, 1, 100, 0); |
231 | if (ret < 0) | 329 | if (ret < 0) |
232 | goto out_sleep; | 330 | goto out_sleep; |
233 | 331 | ||
@@ -289,11 +387,11 @@ static int wl1251_op_start(struct ieee80211_hw *hw) | |||
289 | if (ret < 0) | 387 | if (ret < 0) |
290 | goto out; | 388 | goto out; |
291 | 389 | ||
292 | ret = wl->chip.op_boot(wl); | 390 | ret = wl1251_boot(wl); |
293 | if (ret < 0) | 391 | if (ret < 0) |
294 | goto out; | 392 | goto out; |
295 | 393 | ||
296 | ret = wl->chip.op_hw_init(wl); | 394 | ret = wl1251_hw_init(wl); |
297 | if (ret < 0) | 395 | if (ret < 0) |
298 | goto out; | 396 | goto out; |
299 | 397 | ||
@@ -303,7 +401,7 @@ static int wl1251_op_start(struct ieee80211_hw *hw) | |||
303 | 401 | ||
304 | wl->state = WL1251_STATE_ON; | 402 | wl->state = WL1251_STATE_ON; |
305 | 403 | ||
306 | wl1251_info("firmware booted (%s)", wl->chip.fw_ver); | 404 | wl1251_info("firmware booted (%s)", wl->fw_ver); |
307 | 405 | ||
308 | out: | 406 | out: |
309 | if (ret < 0) | 407 | if (ret < 0) |
@@ -346,7 +444,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
346 | mutex_lock(&wl->mutex); | 444 | mutex_lock(&wl->mutex); |
347 | 445 | ||
348 | /* let's notify MAC80211 about the remaining pending TX frames */ | 446 | /* let's notify MAC80211 about the remaining pending TX frames */ |
349 | wl->chip.op_tx_flush(wl); | 447 | wl1251_tx_flush(wl); |
350 | wl1251_power_off(wl); | 448 | wl1251_power_off(wl); |
351 | 449 | ||
352 | memset(wl->bssid, 0, ETH_ALEN); | 450 | memset(wl->bssid, 0, ETH_ALEN); |
@@ -467,7 +565,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) | |||
467 | 565 | ||
468 | if (channel != wl->channel) { | 566 | if (channel != wl->channel) { |
469 | /* FIXME: use beacon interval provided by mac80211 */ | 567 | /* FIXME: use beacon interval provided by mac80211 */ |
470 | ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); | 568 | ret = wl1251_cmd_join(wl, wl->bss_type, 1, 100, 0); |
471 | if (ret < 0) | 569 | if (ret < 0) |
472 | goto out_sleep; | 570 | goto out_sleep; |
473 | 571 | ||
@@ -1041,7 +1139,7 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1041 | if (ret < 0) | 1139 | if (ret < 0) |
1042 | goto out; | 1140 | goto out; |
1043 | 1141 | ||
1044 | ret = wl->chip.op_cmd_join(wl, wl->bss_type, 1, 100, 0); | 1142 | ret = wl1251_cmd_join(wl, wl->bss_type, 1, 100, 0); |
1045 | 1143 | ||
1046 | if (ret < 0) | 1144 | if (ret < 0) |
1047 | goto out; | 1145 | goto out; |
@@ -1232,15 +1330,14 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1232 | wl->tx_queue_stopped = false; | 1330 | wl->tx_queue_stopped = false; |
1233 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | 1331 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; |
1234 | 1332 | ||
1235 | /* We use the default power on sleep time until we know which chip | ||
1236 | * we're using */ | ||
1237 | wl->chip.power_on_sleep = WL1251_DEFAULT_POWER_ON_SLEEP; | ||
1238 | |||
1239 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | 1333 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) |
1240 | wl->tx_frames[i] = NULL; | 1334 | wl->tx_frames[i] = NULL; |
1241 | 1335 | ||
1242 | wl->next_tx_complete = 0; | 1336 | wl->next_tx_complete = 0; |
1243 | 1337 | ||
1338 | INIT_WORK(&wl->irq_work, wl1251_irq_work); | ||
1339 | INIT_WORK(&wl->tx_work, wl1251_tx_work); | ||
1340 | |||
1244 | /* | 1341 | /* |
1245 | * In case our MAC address is not correctly set, | 1342 | * In case our MAC address is not correctly set, |
1246 | * we use a random but Nokia MAC. | 1343 | * we use a random but Nokia MAC. |