diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-06-29 12:42:14 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-29 12:42:14 -0400 |
commit | 8732baafc3f19e69df683c3f0f36c13cec746fb9 (patch) | |
tree | 9059d0fe8f2a49425edab88ea8e7d5337e13e66c /drivers/net/wireless/ti | |
parent | 7a9bc9b81a5bc6e44ebc80ef781332e4385083f2 (diff) | |
parent | 42fb0b0278e6b9a44bee8adec051de5f43e10b2b (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Conflicts:
drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
Diffstat (limited to 'drivers/net/wireless/ti')
33 files changed, 1617 insertions, 633 deletions
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index d14d69d733a0..6822b845efc1 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c | |||
@@ -277,15 +277,6 @@ int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, | |||
277 | join->rx_config_options = wl->rx_config; | 277 | join->rx_config_options = wl->rx_config; |
278 | join->rx_filter_options = wl->rx_filter; | 278 | join->rx_filter_options = wl->rx_filter; |
279 | 279 | ||
280 | /* | ||
281 | * FIXME: disable temporarily all filters because after commit | ||
282 | * 9cef8737 "mac80211: fix managed mode BSSID handling" broke | ||
283 | * association. The filter logic needs to be implemented properly | ||
284 | * and once that is done, this hack can be removed. | ||
285 | */ | ||
286 | join->rx_config_options = 0; | ||
287 | join->rx_filter_options = WL1251_DEFAULT_RX_FILTER; | ||
288 | |||
289 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | | 280 | join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | |
290 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; | 281 | RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; |
291 | 282 | ||
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index d1afb8e3b2ef..3118c425bcf1 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -334,6 +334,12 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, | |||
334 | if (ret < 0) | 334 | if (ret < 0) |
335 | goto out; | 335 | goto out; |
336 | 336 | ||
337 | /* | ||
338 | * Join command applies filters, and if we are not associated, | ||
339 | * BSSID filter must be disabled for association to work. | ||
340 | */ | ||
341 | if (is_zero_ether_addr(wl->bssid)) | ||
342 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
337 | 343 | ||
338 | ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, | 344 | ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, |
339 | dtim_period); | 345 | dtim_period); |
@@ -348,33 +354,6 @@ out: | |||
348 | return ret; | 354 | return ret; |
349 | } | 355 | } |
350 | 356 | ||
351 | static void wl1251_filter_work(struct work_struct *work) | ||
352 | { | ||
353 | struct wl1251 *wl = | ||
354 | container_of(work, struct wl1251, filter_work); | ||
355 | int ret; | ||
356 | |||
357 | mutex_lock(&wl->mutex); | ||
358 | |||
359 | if (wl->state == WL1251_STATE_OFF) | ||
360 | goto out; | ||
361 | |||
362 | ret = wl1251_ps_elp_wakeup(wl); | ||
363 | if (ret < 0) | ||
364 | goto out; | ||
365 | |||
366 | ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, | ||
367 | wl->dtim_period); | ||
368 | if (ret < 0) | ||
369 | goto out_sleep; | ||
370 | |||
371 | out_sleep: | ||
372 | wl1251_ps_elp_sleep(wl); | ||
373 | |||
374 | out: | ||
375 | mutex_unlock(&wl->mutex); | ||
376 | } | ||
377 | |||
378 | static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 357 | static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
379 | { | 358 | { |
380 | struct wl1251 *wl = hw->priv; | 359 | struct wl1251 *wl = hw->priv; |
@@ -478,7 +457,6 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
478 | 457 | ||
479 | cancel_work_sync(&wl->irq_work); | 458 | cancel_work_sync(&wl->irq_work); |
480 | cancel_work_sync(&wl->tx_work); | 459 | cancel_work_sync(&wl->tx_work); |
481 | cancel_work_sync(&wl->filter_work); | ||
482 | cancel_delayed_work_sync(&wl->elp_work); | 460 | cancel_delayed_work_sync(&wl->elp_work); |
483 | 461 | ||
484 | mutex_lock(&wl->mutex); | 462 | mutex_lock(&wl->mutex); |
@@ -681,13 +659,15 @@ out: | |||
681 | FIF_FCSFAIL | \ | 659 | FIF_FCSFAIL | \ |
682 | FIF_BCN_PRBRESP_PROMISC | \ | 660 | FIF_BCN_PRBRESP_PROMISC | \ |
683 | FIF_CONTROL | \ | 661 | FIF_CONTROL | \ |
684 | FIF_OTHER_BSS) | 662 | FIF_OTHER_BSS | \ |
663 | FIF_PROBE_REQ) | ||
685 | 664 | ||
686 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | 665 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, |
687 | unsigned int changed, | 666 | unsigned int changed, |
688 | unsigned int *total,u64 multicast) | 667 | unsigned int *total,u64 multicast) |
689 | { | 668 | { |
690 | struct wl1251 *wl = hw->priv; | 669 | struct wl1251 *wl = hw->priv; |
670 | int ret; | ||
691 | 671 | ||
692 | wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); | 672 | wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); |
693 | 673 | ||
@@ -698,7 +678,7 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
698 | /* no filters which we support changed */ | 678 | /* no filters which we support changed */ |
699 | return; | 679 | return; |
700 | 680 | ||
701 | /* FIXME: wl->rx_config and wl->rx_filter are not protected */ | 681 | mutex_lock(&wl->mutex); |
702 | 682 | ||
703 | wl->rx_config = WL1251_DEFAULT_RX_CONFIG; | 683 | wl->rx_config = WL1251_DEFAULT_RX_CONFIG; |
704 | wl->rx_filter = WL1251_DEFAULT_RX_FILTER; | 684 | wl->rx_filter = WL1251_DEFAULT_RX_FILTER; |
@@ -721,15 +701,25 @@ static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | |||
721 | } | 701 | } |
722 | if (*total & FIF_CONTROL) | 702 | if (*total & FIF_CONTROL) |
723 | wl->rx_filter |= CFG_RX_CTL_EN; | 703 | wl->rx_filter |= CFG_RX_CTL_EN; |
724 | if (*total & FIF_OTHER_BSS) | 704 | if (*total & FIF_OTHER_BSS || is_zero_ether_addr(wl->bssid)) |
725 | wl->rx_filter &= ~CFG_BSSID_FILTER_EN; | 705 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; |
706 | if (*total & FIF_PROBE_REQ) | ||
707 | wl->rx_filter |= CFG_RX_PREQ_EN; | ||
726 | 708 | ||
727 | /* | 709 | if (wl->state == WL1251_STATE_OFF) |
728 | * FIXME: workqueues need to be properly cancelled on stop(), for | 710 | goto out; |
729 | * now let's just disable changing the filter settings. They will | 711 | |
730 | * be updated any on config(). | 712 | ret = wl1251_ps_elp_wakeup(wl); |
731 | */ | 713 | if (ret < 0) |
732 | /* schedule_work(&wl->filter_work); */ | 714 | goto out; |
715 | |||
716 | /* send filters to firmware */ | ||
717 | wl1251_acx_rx_config(wl, wl->rx_config, wl->rx_filter); | ||
718 | |||
719 | wl1251_ps_elp_sleep(wl); | ||
720 | |||
721 | out: | ||
722 | mutex_unlock(&wl->mutex); | ||
733 | } | 723 | } |
734 | 724 | ||
735 | /* HW encryption */ | 725 | /* HW encryption */ |
@@ -1390,7 +1380,6 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1390 | 1380 | ||
1391 | skb_queue_head_init(&wl->tx_queue); | 1381 | skb_queue_head_init(&wl->tx_queue); |
1392 | 1382 | ||
1393 | INIT_WORK(&wl->filter_work, wl1251_filter_work); | ||
1394 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); | 1383 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); |
1395 | wl->channel = WL1251_DEFAULT_CHANNEL; | 1384 | wl->channel = WL1251_DEFAULT_CHANNEL; |
1396 | wl->scanning = false; | 1385 | wl->scanning = false; |
diff --git a/drivers/net/wireless/ti/wl1251/wl1251.h b/drivers/net/wireless/ti/wl1251/wl1251.h index 9d8f5816c6f9..fd02060038de 100644 --- a/drivers/net/wireless/ti/wl1251/wl1251.h +++ b/drivers/net/wireless/ti/wl1251/wl1251.h | |||
@@ -315,7 +315,6 @@ struct wl1251 { | |||
315 | bool tx_queue_stopped; | 315 | bool tx_queue_stopped; |
316 | 316 | ||
317 | struct work_struct tx_work; | 317 | struct work_struct tx_work; |
318 | struct work_struct filter_work; | ||
319 | 318 | ||
320 | /* Pending TX frames */ | 319 | /* Pending TX frames */ |
321 | struct sk_buff *tx_frames[16]; | 320 | struct sk_buff *tx_frames[16]; |
diff --git a/drivers/net/wireless/ti/wl12xx/cmd.c b/drivers/net/wireless/ti/wl12xx/cmd.c index 50ba7480b790..30be784a40d8 100644 --- a/drivers/net/wireless/ti/wl12xx/cmd.c +++ b/drivers/net/wireless/ti/wl12xx/cmd.c | |||
@@ -174,7 +174,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
174 | struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; | 174 | struct wl1271_nvs_file *nvs = (struct wl1271_nvs_file *)wl->nvs; |
175 | struct wl1271_radio_parms_cmd *radio_parms; | 175 | struct wl1271_radio_parms_cmd *radio_parms; |
176 | struct wl1271_ini_general_params *gp = &nvs->general_params; | 176 | struct wl1271_ini_general_params *gp = &nvs->general_params; |
177 | int ret; | 177 | int ret, fem_idx; |
178 | 178 | ||
179 | if (!wl->nvs) | 179 | if (!wl->nvs) |
180 | return -ENODEV; | 180 | return -ENODEV; |
@@ -185,11 +185,13 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
185 | 185 | ||
186 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 186 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
187 | 187 | ||
188 | fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer); | ||
189 | |||
188 | /* 2.4GHz parameters */ | 190 | /* 2.4GHz parameters */ |
189 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | 191 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, |
190 | sizeof(struct wl1271_ini_band_params_2)); | 192 | sizeof(struct wl1271_ini_band_params_2)); |
191 | memcpy(&radio_parms->dyn_params_2, | 193 | memcpy(&radio_parms->dyn_params_2, |
192 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | 194 | &nvs->dyn_radio_params_2[fem_idx].params, |
193 | sizeof(struct wl1271_ini_fem_params_2)); | 195 | sizeof(struct wl1271_ini_fem_params_2)); |
194 | 196 | ||
195 | /* 5GHz parameters */ | 197 | /* 5GHz parameters */ |
@@ -197,7 +199,7 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
197 | &nvs->stat_radio_params_5, | 199 | &nvs->stat_radio_params_5, |
198 | sizeof(struct wl1271_ini_band_params_5)); | 200 | sizeof(struct wl1271_ini_band_params_5)); |
199 | memcpy(&radio_parms->dyn_params_5, | 201 | memcpy(&radio_parms->dyn_params_5, |
200 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | 202 | &nvs->dyn_radio_params_5[fem_idx].params, |
201 | sizeof(struct wl1271_ini_fem_params_5)); | 203 | sizeof(struct wl1271_ini_fem_params_5)); |
202 | 204 | ||
203 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 205 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
@@ -216,7 +218,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
216 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; | 218 | struct wl128x_nvs_file *nvs = (struct wl128x_nvs_file *)wl->nvs; |
217 | struct wl128x_radio_parms_cmd *radio_parms; | 219 | struct wl128x_radio_parms_cmd *radio_parms; |
218 | struct wl128x_ini_general_params *gp = &nvs->general_params; | 220 | struct wl128x_ini_general_params *gp = &nvs->general_params; |
219 | int ret; | 221 | int ret, fem_idx; |
220 | 222 | ||
221 | if (!wl->nvs) | 223 | if (!wl->nvs) |
222 | return -ENODEV; | 224 | return -ENODEV; |
@@ -227,11 +229,13 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
227 | 229 | ||
228 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; | 230 | radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM; |
229 | 231 | ||
232 | fem_idx = WL12XX_FEM_TO_NVS_ENTRY(gp->tx_bip_fem_manufacturer); | ||
233 | |||
230 | /* 2.4GHz parameters */ | 234 | /* 2.4GHz parameters */ |
231 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, | 235 | memcpy(&radio_parms->static_params_2, &nvs->stat_radio_params_2, |
232 | sizeof(struct wl128x_ini_band_params_2)); | 236 | sizeof(struct wl128x_ini_band_params_2)); |
233 | memcpy(&radio_parms->dyn_params_2, | 237 | memcpy(&radio_parms->dyn_params_2, |
234 | &nvs->dyn_radio_params_2[gp->tx_bip_fem_manufacturer].params, | 238 | &nvs->dyn_radio_params_2[fem_idx].params, |
235 | sizeof(struct wl128x_ini_fem_params_2)); | 239 | sizeof(struct wl128x_ini_fem_params_2)); |
236 | 240 | ||
237 | /* 5GHz parameters */ | 241 | /* 5GHz parameters */ |
@@ -239,7 +243,7 @@ int wl128x_cmd_radio_parms(struct wl1271 *wl) | |||
239 | &nvs->stat_radio_params_5, | 243 | &nvs->stat_radio_params_5, |
240 | sizeof(struct wl128x_ini_band_params_5)); | 244 | sizeof(struct wl128x_ini_band_params_5)); |
241 | memcpy(&radio_parms->dyn_params_5, | 245 | memcpy(&radio_parms->dyn_params_5, |
242 | &nvs->dyn_radio_params_5[gp->tx_bip_fem_manufacturer].params, | 246 | &nvs->dyn_radio_params_5[fem_idx].params, |
243 | sizeof(struct wl128x_ini_fem_params_5)); | 247 | sizeof(struct wl128x_ini_fem_params_5)); |
244 | 248 | ||
245 | radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; | 249 | radio_parms->fem_vendor_and_options = nvs->fem_vendor_and_options; |
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 85d1600ee340..47ba2e0017f4 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c | |||
@@ -246,6 +246,7 @@ static struct wlcore_conf wl12xx_conf = { | |||
246 | .forced_ps = false, | 246 | .forced_ps = false, |
247 | .keep_alive_interval = 55000, | 247 | .keep_alive_interval = 55000, |
248 | .max_listen_interval = 20, | 248 | .max_listen_interval = 20, |
249 | .sta_sleep_auth = WL1271_PSM_ILLEGAL, | ||
249 | }, | 250 | }, |
250 | .itrim = { | 251 | .itrim = { |
251 | .enable = false, | 252 | .enable = false, |
@@ -597,8 +598,10 @@ static const int wl12xx_rtable[REG_TABLE_LEN] = { | |||
597 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" | 598 | #define WL128X_FW_NAME_SINGLE "ti-connectivity/wl128x-fw-4-sr.bin" |
598 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" | 599 | #define WL128X_PLT_FW_NAME "ti-connectivity/wl128x-fw-4-plt.bin" |
599 | 600 | ||
600 | static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | 601 | static int wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
601 | { | 602 | { |
603 | int ret; | ||
604 | |||
602 | if (wl->chip.id != CHIP_ID_1283_PG20) { | 605 | if (wl->chip.id != CHIP_ID_1283_PG20) { |
603 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; | 606 | struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; |
604 | struct wl127x_rx_mem_pool_addr rx_mem_addr; | 607 | struct wl127x_rx_mem_pool_addr rx_mem_addr; |
@@ -615,9 +618,13 @@ static void wl127x_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | |||
615 | 618 | ||
616 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; | 619 | rx_mem_addr.addr_extra = rx_mem_addr.addr + 4; |
617 | 620 | ||
618 | wl1271_write(wl, WL1271_SLV_REG_DATA, | 621 | ret = wlcore_write(wl, WL1271_SLV_REG_DATA, &rx_mem_addr, |
619 | &rx_mem_addr, sizeof(rx_mem_addr), false); | 622 | sizeof(rx_mem_addr), false); |
623 | if (ret < 0) | ||
624 | return ret; | ||
620 | } | 625 | } |
626 | |||
627 | return 0; | ||
621 | } | 628 | } |
622 | 629 | ||
623 | static int wl12xx_identify_chip(struct wl1271 *wl) | 630 | static int wl12xx_identify_chip(struct wl1271 *wl) |
@@ -681,64 +688,95 @@ out: | |||
681 | return ret; | 688 | return ret; |
682 | } | 689 | } |
683 | 690 | ||
684 | static void wl12xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 691 | static int __must_check wl12xx_top_reg_write(struct wl1271 *wl, int addr, |
692 | u16 val) | ||
685 | { | 693 | { |
694 | int ret; | ||
695 | |||
686 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | 696 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
687 | addr = (addr >> 1) + 0x30000; | 697 | addr = (addr >> 1) + 0x30000; |
688 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | 698 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr); |
699 | if (ret < 0) | ||
700 | goto out; | ||
689 | 701 | ||
690 | /* write value to OCP_POR_WDATA */ | 702 | /* write value to OCP_POR_WDATA */ |
691 | wl1271_write32(wl, WL12XX_OCP_DATA_WRITE, val); | 703 | ret = wlcore_write32(wl, WL12XX_OCP_DATA_WRITE, val); |
704 | if (ret < 0) | ||
705 | goto out; | ||
692 | 706 | ||
693 | /* write 1 to OCP_CMD */ | 707 | /* write 1 to OCP_CMD */ |
694 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); | 708 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_WRITE); |
709 | if (ret < 0) | ||
710 | goto out; | ||
711 | |||
712 | out: | ||
713 | return ret; | ||
695 | } | 714 | } |
696 | 715 | ||
697 | static u16 wl12xx_top_reg_read(struct wl1271 *wl, int addr) | 716 | static int __must_check wl12xx_top_reg_read(struct wl1271 *wl, int addr, |
717 | u16 *out) | ||
698 | { | 718 | { |
699 | u32 val; | 719 | u32 val; |
700 | int timeout = OCP_CMD_LOOP; | 720 | int timeout = OCP_CMD_LOOP; |
721 | int ret; | ||
701 | 722 | ||
702 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ | 723 | /* write address >> 1 + 0x30000 to OCP_POR_CTR */ |
703 | addr = (addr >> 1) + 0x30000; | 724 | addr = (addr >> 1) + 0x30000; |
704 | wl1271_write32(wl, WL12XX_OCP_POR_CTR, addr); | 725 | ret = wlcore_write32(wl, WL12XX_OCP_POR_CTR, addr); |
726 | if (ret < 0) | ||
727 | return ret; | ||
705 | 728 | ||
706 | /* write 2 to OCP_CMD */ | 729 | /* write 2 to OCP_CMD */ |
707 | wl1271_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); | 730 | ret = wlcore_write32(wl, WL12XX_OCP_CMD, OCP_CMD_READ); |
731 | if (ret < 0) | ||
732 | return ret; | ||
708 | 733 | ||
709 | /* poll for data ready */ | 734 | /* poll for data ready */ |
710 | do { | 735 | do { |
711 | val = wl1271_read32(wl, WL12XX_OCP_DATA_READ); | 736 | ret = wlcore_read32(wl, WL12XX_OCP_DATA_READ, &val); |
737 | if (ret < 0) | ||
738 | return ret; | ||
712 | } while (!(val & OCP_READY_MASK) && --timeout); | 739 | } while (!(val & OCP_READY_MASK) && --timeout); |
713 | 740 | ||
714 | if (!timeout) { | 741 | if (!timeout) { |
715 | wl1271_warning("Top register access timed out."); | 742 | wl1271_warning("Top register access timed out."); |
716 | return 0xffff; | 743 | return -ETIMEDOUT; |
717 | } | 744 | } |
718 | 745 | ||
719 | /* check data status and return if OK */ | 746 | /* check data status and return if OK */ |
720 | if ((val & OCP_STATUS_MASK) == OCP_STATUS_OK) | 747 | if ((val & OCP_STATUS_MASK) != OCP_STATUS_OK) { |
721 | return val & 0xffff; | ||
722 | else { | ||
723 | wl1271_warning("Top register access returned error."); | 748 | wl1271_warning("Top register access returned error."); |
724 | return 0xffff; | 749 | return -EIO; |
725 | } | 750 | } |
751 | |||
752 | if (out) | ||
753 | *out = val & 0xffff; | ||
754 | |||
755 | return 0; | ||
726 | } | 756 | } |
727 | 757 | ||
728 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | 758 | static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) |
729 | { | 759 | { |
730 | u16 spare_reg; | 760 | u16 spare_reg; |
761 | int ret; | ||
731 | 762 | ||
732 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ | 763 | /* Mask bits [2] & [8:4] in the sys_clk_cfg register */ |
733 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 764 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg); |
765 | if (ret < 0) | ||
766 | return ret; | ||
767 | |||
734 | if (spare_reg == 0xFFFF) | 768 | if (spare_reg == 0xFFFF) |
735 | return -EFAULT; | 769 | return -EFAULT; |
736 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); | 770 | spare_reg |= (BIT(3) | BIT(5) | BIT(6)); |
737 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 771 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
772 | if (ret < 0) | ||
773 | return ret; | ||
738 | 774 | ||
739 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ | 775 | /* Enable FREF_CLK_REQ & mux MCS and coex PLLs to FREF */ |
740 | wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, | 776 | ret = wl12xx_top_reg_write(wl, SYS_CLK_CFG_REG, |
741 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); | 777 | WL_CLK_REQ_TYPE_PG2 | MCS_PLL_CLK_SEL_FREF); |
778 | if (ret < 0) | ||
779 | return ret; | ||
742 | 780 | ||
743 | /* Delay execution for 15msec, to let the HW settle */ | 781 | /* Delay execution for 15msec, to let the HW settle */ |
744 | mdelay(15); | 782 | mdelay(15); |
@@ -749,8 +787,12 @@ static int wl128x_switch_tcxo_to_fref(struct wl1271 *wl) | |||
749 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | 787 | static bool wl128x_is_tcxo_valid(struct wl1271 *wl) |
750 | { | 788 | { |
751 | u16 tcxo_detection; | 789 | u16 tcxo_detection; |
790 | int ret; | ||
791 | |||
792 | ret = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG, &tcxo_detection); | ||
793 | if (ret < 0) | ||
794 | return false; | ||
752 | 795 | ||
753 | tcxo_detection = wl12xx_top_reg_read(wl, TCXO_CLK_DETECT_REG); | ||
754 | if (tcxo_detection & TCXO_DET_FAILED) | 796 | if (tcxo_detection & TCXO_DET_FAILED) |
755 | return false; | 797 | return false; |
756 | 798 | ||
@@ -760,8 +802,12 @@ static bool wl128x_is_tcxo_valid(struct wl1271 *wl) | |||
760 | static bool wl128x_is_fref_valid(struct wl1271 *wl) | 802 | static bool wl128x_is_fref_valid(struct wl1271 *wl) |
761 | { | 803 | { |
762 | u16 fref_detection; | 804 | u16 fref_detection; |
805 | int ret; | ||
806 | |||
807 | ret = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG, &fref_detection); | ||
808 | if (ret < 0) | ||
809 | return false; | ||
763 | 810 | ||
764 | fref_detection = wl12xx_top_reg_read(wl, FREF_CLK_DETECT_REG); | ||
765 | if (fref_detection & FREF_CLK_DETECT_FAIL) | 811 | if (fref_detection & FREF_CLK_DETECT_FAIL) |
766 | return false; | 812 | return false; |
767 | 813 | ||
@@ -770,11 +816,21 @@ static bool wl128x_is_fref_valid(struct wl1271 *wl) | |||
770 | 816 | ||
771 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) | 817 | static int wl128x_manually_configure_mcs_pll(struct wl1271 *wl) |
772 | { | 818 | { |
773 | wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); | 819 | int ret; |
774 | wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
775 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, MCS_PLL_CONFIG_REG_VAL); | ||
776 | 820 | ||
777 | return 0; | 821 | ret = wl12xx_top_reg_write(wl, MCS_PLL_M_REG, MCS_PLL_M_REG_VAL); |
822 | if (ret < 0) | ||
823 | goto out; | ||
824 | |||
825 | ret = wl12xx_top_reg_write(wl, MCS_PLL_N_REG, MCS_PLL_N_REG_VAL); | ||
826 | if (ret < 0) | ||
827 | goto out; | ||
828 | |||
829 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, | ||
830 | MCS_PLL_CONFIG_REG_VAL); | ||
831 | |||
832 | out: | ||
833 | return ret; | ||
778 | } | 834 | } |
779 | 835 | ||
780 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | 836 | static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) |
@@ -783,13 +839,19 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
783 | u16 pll_config; | 839 | u16 pll_config; |
784 | u8 input_freq; | 840 | u8 input_freq; |
785 | struct wl12xx_priv *priv = wl->priv; | 841 | struct wl12xx_priv *priv = wl->priv; |
842 | int ret; | ||
786 | 843 | ||
787 | /* Mask bits [3:1] in the sys_clk_cfg register */ | 844 | /* Mask bits [3:1] in the sys_clk_cfg register */ |
788 | spare_reg = wl12xx_top_reg_read(wl, WL_SPARE_REG); | 845 | ret = wl12xx_top_reg_read(wl, WL_SPARE_REG, &spare_reg); |
846 | if (ret < 0) | ||
847 | return ret; | ||
848 | |||
789 | if (spare_reg == 0xFFFF) | 849 | if (spare_reg == 0xFFFF) |
790 | return -EFAULT; | 850 | return -EFAULT; |
791 | spare_reg |= BIT(2); | 851 | spare_reg |= BIT(2); |
792 | wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); | 852 | ret = wl12xx_top_reg_write(wl, WL_SPARE_REG, spare_reg); |
853 | if (ret < 0) | ||
854 | return ret; | ||
793 | 855 | ||
794 | /* Handle special cases of the TCXO clock */ | 856 | /* Handle special cases of the TCXO clock */ |
795 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || | 857 | if (priv->tcxo_clock == WL12XX_TCXOCLOCK_16_8 || |
@@ -799,14 +861,17 @@ static int wl128x_configure_mcs_pll(struct wl1271 *wl, int clk) | |||
799 | /* Set the input frequency according to the selected clock source */ | 861 | /* Set the input frequency according to the selected clock source */ |
800 | input_freq = (clk & 1) + 1; | 862 | input_freq = (clk & 1) + 1; |
801 | 863 | ||
802 | pll_config = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG); | 864 | ret = wl12xx_top_reg_read(wl, MCS_PLL_CONFIG_REG, &pll_config); |
865 | if (ret < 0) | ||
866 | return ret; | ||
867 | |||
803 | if (pll_config == 0xFFFF) | 868 | if (pll_config == 0xFFFF) |
804 | return -EFAULT; | 869 | return -EFAULT; |
805 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); | 870 | pll_config |= (input_freq << MCS_SEL_IN_FREQ_SHIFT); |
806 | pll_config |= MCS_PLL_ENABLE_HP; | 871 | pll_config |= MCS_PLL_ENABLE_HP; |
807 | wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); | 872 | ret = wl12xx_top_reg_write(wl, MCS_PLL_CONFIG_REG, pll_config); |
808 | 873 | ||
809 | return 0; | 874 | return ret; |
810 | } | 875 | } |
811 | 876 | ||
812 | /* | 877 | /* |
@@ -820,6 +885,7 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
820 | { | 885 | { |
821 | struct wl12xx_priv *priv = wl->priv; | 886 | struct wl12xx_priv *priv = wl->priv; |
822 | u16 sys_clk_cfg; | 887 | u16 sys_clk_cfg; |
888 | int ret; | ||
823 | 889 | ||
824 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ | 890 | /* For XTAL-only modes, FREF will be used after switching from TCXO */ |
825 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || | 891 | if (priv->ref_clock == WL12XX_REFCLOCK_26_XTAL || |
@@ -830,7 +896,10 @@ static int wl128x_boot_clk(struct wl1271 *wl, int *selected_clock) | |||
830 | } | 896 | } |
831 | 897 | ||
832 | /* Query the HW, to determine which clock source we should use */ | 898 | /* Query the HW, to determine which clock source we should use */ |
833 | sys_clk_cfg = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG); | 899 | ret = wl12xx_top_reg_read(wl, SYS_CLK_CFG_REG, &sys_clk_cfg); |
900 | if (ret < 0) | ||
901 | return ret; | ||
902 | |||
834 | if (sys_clk_cfg == 0xFFFF) | 903 | if (sys_clk_cfg == 0xFFFF) |
835 | return -EINVAL; | 904 | return -EINVAL; |
836 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) | 905 | if (sys_clk_cfg & PRCM_CM_EN_MUX_WLAN_FREF) |
@@ -865,6 +934,7 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
865 | struct wl12xx_priv *priv = wl->priv; | 934 | struct wl12xx_priv *priv = wl->priv; |
866 | u32 pause; | 935 | u32 pause; |
867 | u32 clk; | 936 | u32 clk; |
937 | int ret; | ||
868 | 938 | ||
869 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) | 939 | if (WL127X_PG_GET_MAJOR(wl->hw_pg_ver) < 3) |
870 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; | 940 | wl->quirks |= WLCORE_QUIRK_END_OF_TRANSACTION; |
@@ -885,48 +955,74 @@ static int wl127x_boot_clk(struct wl1271 *wl) | |||
885 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { | 955 | if (priv->ref_clock != CONF_REF_CLK_19_2_E) { |
886 | u16 val; | 956 | u16 val; |
887 | /* Set clock type (open drain) */ | 957 | /* Set clock type (open drain) */ |
888 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE); | 958 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_TYPE, &val); |
959 | if (ret < 0) | ||
960 | goto out; | ||
961 | |||
889 | val &= FREF_CLK_TYPE_BITS; | 962 | val &= FREF_CLK_TYPE_BITS; |
890 | wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); | 963 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_TYPE, val); |
964 | if (ret < 0) | ||
965 | goto out; | ||
891 | 966 | ||
892 | /* Set clock pull mode (no pull) */ | 967 | /* Set clock pull mode (no pull) */ |
893 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL); | 968 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_PULL, &val); |
969 | if (ret < 0) | ||
970 | goto out; | ||
971 | |||
894 | val |= NO_PULL; | 972 | val |= NO_PULL; |
895 | wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); | 973 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_PULL, val); |
974 | if (ret < 0) | ||
975 | goto out; | ||
896 | } else { | 976 | } else { |
897 | u16 val; | 977 | u16 val; |
898 | /* Set clock polarity */ | 978 | /* Set clock polarity */ |
899 | val = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY); | 979 | ret = wl12xx_top_reg_read(wl, OCP_REG_CLK_POLARITY, &val); |
980 | if (ret < 0) | ||
981 | goto out; | ||
982 | |||
900 | val &= FREF_CLK_POLARITY_BITS; | 983 | val &= FREF_CLK_POLARITY_BITS; |
901 | val |= CLK_REQ_OUTN_SEL; | 984 | val |= CLK_REQ_OUTN_SEL; |
902 | wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); | 985 | ret = wl12xx_top_reg_write(wl, OCP_REG_CLK_POLARITY, val); |
986 | if (ret < 0) | ||
987 | goto out; | ||
903 | } | 988 | } |
904 | 989 | ||
905 | wl1271_write32(wl, WL12XX_PLL_PARAMETERS, clk); | 990 | ret = wlcore_write32(wl, WL12XX_PLL_PARAMETERS, clk); |
991 | if (ret < 0) | ||
992 | goto out; | ||
906 | 993 | ||
907 | pause = wl1271_read32(wl, WL12XX_PLL_PARAMETERS); | 994 | ret = wlcore_read32(wl, WL12XX_PLL_PARAMETERS, &pause); |
995 | if (ret < 0) | ||
996 | goto out; | ||
908 | 997 | ||
909 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); | 998 | wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); |
910 | 999 | ||
911 | pause &= ~(WU_COUNTER_PAUSE_VAL); | 1000 | pause &= ~(WU_COUNTER_PAUSE_VAL); |
912 | pause |= WU_COUNTER_PAUSE_VAL; | 1001 | pause |= WU_COUNTER_PAUSE_VAL; |
913 | wl1271_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); | 1002 | ret = wlcore_write32(wl, WL12XX_WU_COUNTER_PAUSE, pause); |
914 | 1003 | ||
915 | return 0; | 1004 | out: |
1005 | return ret; | ||
916 | } | 1006 | } |
917 | 1007 | ||
918 | static int wl1271_boot_soft_reset(struct wl1271 *wl) | 1008 | static int wl1271_boot_soft_reset(struct wl1271 *wl) |
919 | { | 1009 | { |
920 | unsigned long timeout; | 1010 | unsigned long timeout; |
921 | u32 boot_data; | 1011 | u32 boot_data; |
1012 | int ret = 0; | ||
922 | 1013 | ||
923 | /* perform soft reset */ | 1014 | /* perform soft reset */ |
924 | wl1271_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); | 1015 | ret = wlcore_write32(wl, WL12XX_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); |
1016 | if (ret < 0) | ||
1017 | goto out; | ||
925 | 1018 | ||
926 | /* SOFT_RESET is self clearing */ | 1019 | /* SOFT_RESET is self clearing */ |
927 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); | 1020 | timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); |
928 | while (1) { | 1021 | while (1) { |
929 | boot_data = wl1271_read32(wl, WL12XX_SLV_SOFT_RESET); | 1022 | ret = wlcore_read32(wl, WL12XX_SLV_SOFT_RESET, &boot_data); |
1023 | if (ret < 0) | ||
1024 | goto out; | ||
1025 | |||
930 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); | 1026 | wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); |
931 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) | 1027 | if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) |
932 | break; | 1028 | break; |
@@ -942,12 +1038,15 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl) | |||
942 | } | 1038 | } |
943 | 1039 | ||
944 | /* disable Rx/Tx */ | 1040 | /* disable Rx/Tx */ |
945 | wl1271_write32(wl, WL12XX_ENABLE, 0x0); | 1041 | ret = wlcore_write32(wl, WL12XX_ENABLE, 0x0); |
1042 | if (ret < 0) | ||
1043 | goto out; | ||
946 | 1044 | ||
947 | /* disable auto calibration on start*/ | 1045 | /* disable auto calibration on start*/ |
948 | wl1271_write32(wl, WL12XX_SPARE_A2, 0xffff); | 1046 | ret = wlcore_write32(wl, WL12XX_SPARE_A2, 0xffff); |
949 | 1047 | ||
950 | return 0; | 1048 | out: |
1049 | return ret; | ||
951 | } | 1050 | } |
952 | 1051 | ||
953 | static int wl12xx_pre_boot(struct wl1271 *wl) | 1052 | static int wl12xx_pre_boot(struct wl1271 *wl) |
@@ -968,16 +1067,23 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
968 | } | 1067 | } |
969 | 1068 | ||
970 | /* Continue the ELP wake up sequence */ | 1069 | /* Continue the ELP wake up sequence */ |
971 | wl1271_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 1070 | ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
1071 | if (ret < 0) | ||
1072 | goto out; | ||
1073 | |||
972 | udelay(500); | 1074 | udelay(500); |
973 | 1075 | ||
974 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | 1076 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); |
1077 | if (ret < 0) | ||
1078 | goto out; | ||
975 | 1079 | ||
976 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) | 1080 | /* Read-modify-write DRPW_SCRATCH_START register (see next state) |
977 | to be used by DRPw FW. The RTRIM value will be added by the FW | 1081 | to be used by DRPw FW. The RTRIM value will be added by the FW |
978 | before taking DRPw out of reset */ | 1082 | before taking DRPw out of reset */ |
979 | 1083 | ||
980 | clk = wl1271_read32(wl, WL12XX_DRPW_SCRATCH_START); | 1084 | ret = wlcore_read32(wl, WL12XX_DRPW_SCRATCH_START, &clk); |
1085 | if (ret < 0) | ||
1086 | goto out; | ||
981 | 1087 | ||
982 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); | 1088 | wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); |
983 | 1089 | ||
@@ -986,12 +1092,18 @@ static int wl12xx_pre_boot(struct wl1271 *wl) | |||
986 | else | 1092 | else |
987 | clk |= (priv->ref_clock << 1) << 4; | 1093 | clk |= (priv->ref_clock << 1) << 4; |
988 | 1094 | ||
989 | wl1271_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); | 1095 | ret = wlcore_write32(wl, WL12XX_DRPW_SCRATCH_START, clk); |
1096 | if (ret < 0) | ||
1097 | goto out; | ||
990 | 1098 | ||
991 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 1099 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
1100 | if (ret < 0) | ||
1101 | goto out; | ||
992 | 1102 | ||
993 | /* Disable interrupts */ | 1103 | /* Disable interrupts */ |
994 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 1104 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
1105 | if (ret < 0) | ||
1106 | goto out; | ||
995 | 1107 | ||
996 | ret = wl1271_boot_soft_reset(wl); | 1108 | ret = wl1271_boot_soft_reset(wl); |
997 | if (ret < 0) | 1109 | if (ret < 0) |
@@ -1001,47 +1113,72 @@ out: | |||
1001 | return ret; | 1113 | return ret; |
1002 | } | 1114 | } |
1003 | 1115 | ||
1004 | static void wl12xx_pre_upload(struct wl1271 *wl) | 1116 | static int wl12xx_pre_upload(struct wl1271 *wl) |
1005 | { | 1117 | { |
1006 | u32 tmp, polarity; | 1118 | u32 tmp; |
1119 | u16 polarity; | ||
1120 | int ret; | ||
1007 | 1121 | ||
1008 | /* write firmware's last address (ie. it's length) to | 1122 | /* write firmware's last address (ie. it's length) to |
1009 | * ACX_EEPROMLESS_IND_REG */ | 1123 | * ACX_EEPROMLESS_IND_REG */ |
1010 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); | 1124 | wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); |
1011 | 1125 | ||
1012 | wl1271_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); | 1126 | ret = wlcore_write32(wl, WL12XX_EEPROMLESS_IND, WL12XX_EEPROMLESS_IND); |
1127 | if (ret < 0) | ||
1128 | goto out; | ||
1013 | 1129 | ||
1014 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | 1130 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp); |
1131 | if (ret < 0) | ||
1132 | goto out; | ||
1015 | 1133 | ||
1016 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 1134 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
1017 | 1135 | ||
1018 | /* 6. read the EEPROM parameters */ | 1136 | /* 6. read the EEPROM parameters */ |
1019 | tmp = wl1271_read32(wl, WL12XX_SCR_PAD2); | 1137 | ret = wlcore_read32(wl, WL12XX_SCR_PAD2, &tmp); |
1138 | if (ret < 0) | ||
1139 | goto out; | ||
1020 | 1140 | ||
1021 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly | 1141 | /* WL1271: The reference driver skips steps 7 to 10 (jumps directly |
1022 | * to upload_fw) */ | 1142 | * to upload_fw) */ |
1023 | 1143 | ||
1024 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1144 | if (wl->chip.id == CHIP_ID_1283_PG20) { |
1025 | wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); | 1145 | ret = wl12xx_top_reg_write(wl, SDIO_IO_DS, HCI_IO_DS_6MA); |
1146 | if (ret < 0) | ||
1147 | goto out; | ||
1148 | } | ||
1026 | 1149 | ||
1027 | /* polarity must be set before the firmware is loaded */ | 1150 | /* polarity must be set before the firmware is loaded */ |
1028 | polarity = wl12xx_top_reg_read(wl, OCP_REG_POLARITY); | 1151 | ret = wl12xx_top_reg_read(wl, OCP_REG_POLARITY, &polarity); |
1152 | if (ret < 0) | ||
1153 | goto out; | ||
1029 | 1154 | ||
1030 | /* We use HIGH polarity, so unset the LOW bit */ | 1155 | /* We use HIGH polarity, so unset the LOW bit */ |
1031 | polarity &= ~POLARITY_LOW; | 1156 | polarity &= ~POLARITY_LOW; |
1032 | wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); | 1157 | ret = wl12xx_top_reg_write(wl, OCP_REG_POLARITY, polarity); |
1033 | 1158 | ||
1159 | out: | ||
1160 | return ret; | ||
1034 | } | 1161 | } |
1035 | 1162 | ||
1036 | static void wl12xx_enable_interrupts(struct wl1271 *wl) | 1163 | static int wl12xx_enable_interrupts(struct wl1271 *wl) |
1037 | { | 1164 | { |
1038 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL12XX_ACX_ALL_EVENTS_VECTOR); | 1165 | int ret; |
1166 | |||
1167 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, | ||
1168 | WL12XX_ACX_ALL_EVENTS_VECTOR); | ||
1169 | if (ret < 0) | ||
1170 | goto out; | ||
1039 | 1171 | ||
1040 | wlcore_enable_interrupts(wl); | 1172 | wlcore_enable_interrupts(wl); |
1041 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 1173 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
1042 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); | 1174 | WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); |
1175 | if (ret < 0) | ||
1176 | goto out; | ||
1043 | 1177 | ||
1044 | wl1271_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); | 1178 | ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); |
1179 | |||
1180 | out: | ||
1181 | return ret; | ||
1045 | } | 1182 | } |
1046 | 1183 | ||
1047 | static int wl12xx_boot(struct wl1271 *wl) | 1184 | static int wl12xx_boot(struct wl1271 *wl) |
@@ -1056,7 +1193,9 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
1056 | if (ret < 0) | 1193 | if (ret < 0) |
1057 | goto out; | 1194 | goto out; |
1058 | 1195 | ||
1059 | wl12xx_pre_upload(wl); | 1196 | ret = wl12xx_pre_upload(wl); |
1197 | if (ret < 0) | ||
1198 | goto out; | ||
1060 | 1199 | ||
1061 | ret = wlcore_boot_upload_firmware(wl); | 1200 | ret = wlcore_boot_upload_firmware(wl); |
1062 | if (ret < 0) | 1201 | if (ret < 0) |
@@ -1066,22 +1205,30 @@ static int wl12xx_boot(struct wl1271 *wl) | |||
1066 | if (ret < 0) | 1205 | if (ret < 0) |
1067 | goto out; | 1206 | goto out; |
1068 | 1207 | ||
1069 | wl12xx_enable_interrupts(wl); | 1208 | ret = wl12xx_enable_interrupts(wl); |
1070 | 1209 | ||
1071 | out: | 1210 | out: |
1072 | return ret; | 1211 | return ret; |
1073 | } | 1212 | } |
1074 | 1213 | ||
1075 | static void wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | 1214 | static int wl12xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
1076 | void *buf, size_t len) | 1215 | void *buf, size_t len) |
1077 | { | 1216 | { |
1078 | wl1271_write(wl, cmd_box_addr, buf, len, false); | 1217 | int ret; |
1079 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | 1218 | |
1219 | ret = wlcore_write(wl, cmd_box_addr, buf, len, false); | ||
1220 | if (ret < 0) | ||
1221 | return ret; | ||
1222 | |||
1223 | ret = wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_CMD); | ||
1224 | |||
1225 | return ret; | ||
1080 | } | 1226 | } |
1081 | 1227 | ||
1082 | static void wl12xx_ack_event(struct wl1271 *wl) | 1228 | static int wl12xx_ack_event(struct wl1271 *wl) |
1083 | { | 1229 | { |
1084 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL12XX_INTR_TRIG_EVENT_ACK); | 1230 | return wlcore_write_reg(wl, REG_INTERRUPT_TRIG, |
1231 | WL12XX_INTR_TRIG_EVENT_ACK); | ||
1085 | } | 1232 | } |
1086 | 1233 | ||
1087 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | 1234 | static u32 wl12xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
@@ -1161,13 +1308,13 @@ static u32 wl12xx_get_rx_packet_len(struct wl1271 *wl, void *rx_data, | |||
1161 | return data_len - sizeof(*desc) - desc->pad_len; | 1308 | return data_len - sizeof(*desc) - desc->pad_len; |
1162 | } | 1309 | } |
1163 | 1310 | ||
1164 | static void wl12xx_tx_delayed_compl(struct wl1271 *wl) | 1311 | static int wl12xx_tx_delayed_compl(struct wl1271 *wl) |
1165 | { | 1312 | { |
1166 | if (wl->fw_status_1->tx_results_counter == | 1313 | if (wl->fw_status_1->tx_results_counter == |
1167 | (wl->tx_results_count & 0xff)) | 1314 | (wl->tx_results_count & 0xff)) |
1168 | return; | 1315 | return 0; |
1169 | 1316 | ||
1170 | wl1271_tx_complete(wl); | 1317 | return wlcore_tx_complete(wl); |
1171 | } | 1318 | } |
1172 | 1319 | ||
1173 | static int wl12xx_hw_init(struct wl1271 *wl) | 1320 | static int wl12xx_hw_init(struct wl1271 *wl) |
@@ -1268,39 +1415,58 @@ static bool wl12xx_mac_in_fuse(struct wl1271 *wl) | |||
1268 | return supported; | 1415 | return supported; |
1269 | } | 1416 | } |
1270 | 1417 | ||
1271 | static void wl12xx_get_fuse_mac(struct wl1271 *wl) | 1418 | static int wl12xx_get_fuse_mac(struct wl1271 *wl) |
1272 | { | 1419 | { |
1273 | u32 mac1, mac2; | 1420 | u32 mac1, mac2; |
1421 | int ret; | ||
1274 | 1422 | ||
1275 | wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); | 1423 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); |
1424 | if (ret < 0) | ||
1425 | goto out; | ||
1276 | 1426 | ||
1277 | mac1 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1); | 1427 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_1, &mac1); |
1278 | mac2 = wl1271_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2); | 1428 | if (ret < 0) |
1429 | goto out; | ||
1430 | |||
1431 | ret = wlcore_read32(wl, WL12XX_REG_FUSE_BD_ADDR_2, &mac2); | ||
1432 | if (ret < 0) | ||
1433 | goto out; | ||
1279 | 1434 | ||
1280 | /* these are the two parts of the BD_ADDR */ | 1435 | /* these are the two parts of the BD_ADDR */ |
1281 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | 1436 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
1282 | ((mac1 & 0xff000000) >> 24); | 1437 | ((mac1 & 0xff000000) >> 24); |
1283 | wl->fuse_nic_addr = mac1 & 0xffffff; | 1438 | wl->fuse_nic_addr = mac1 & 0xffffff; |
1284 | 1439 | ||
1285 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | 1440 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); |
1441 | |||
1442 | out: | ||
1443 | return ret; | ||
1286 | } | 1444 | } |
1287 | 1445 | ||
1288 | static s8 wl12xx_get_pg_ver(struct wl1271 *wl) | 1446 | static int wl12xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
1289 | { | 1447 | { |
1290 | u32 die_info; | 1448 | u16 die_info; |
1449 | int ret; | ||
1291 | 1450 | ||
1292 | if (wl->chip.id == CHIP_ID_1283_PG20) | 1451 | if (wl->chip.id == CHIP_ID_1283_PG20) |
1293 | die_info = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1); | 1452 | ret = wl12xx_top_reg_read(wl, WL128X_REG_FUSE_DATA_2_1, |
1453 | &die_info); | ||
1294 | else | 1454 | else |
1295 | die_info = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1); | 1455 | ret = wl12xx_top_reg_read(wl, WL127X_REG_FUSE_DATA_2_1, |
1456 | &die_info); | ||
1296 | 1457 | ||
1297 | return (s8) (die_info & PG_VER_MASK) >> PG_VER_OFFSET; | 1458 | if (ret >= 0 && ver) |
1459 | *ver = (s8)((die_info & PG_VER_MASK) >> PG_VER_OFFSET); | ||
1460 | |||
1461 | return ret; | ||
1298 | } | 1462 | } |
1299 | 1463 | ||
1300 | static void wl12xx_get_mac(struct wl1271 *wl) | 1464 | static int wl12xx_get_mac(struct wl1271 *wl) |
1301 | { | 1465 | { |
1302 | if (wl12xx_mac_in_fuse(wl)) | 1466 | if (wl12xx_mac_in_fuse(wl)) |
1303 | wl12xx_get_fuse_mac(wl); | 1467 | return wl12xx_get_fuse_mac(wl); |
1468 | |||
1469 | return 0; | ||
1304 | } | 1470 | } |
1305 | 1471 | ||
1306 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, | 1472 | static void wl12xx_set_tx_desc_csum(struct wl1271 *wl, |
@@ -1448,10 +1614,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) | |||
1448 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; | 1614 | wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; |
1449 | wl->fw_status_priv_len = 0; | 1615 | wl->fw_status_priv_len = 0; |
1450 | wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); | 1616 | wl->stats.fw_stats_len = sizeof(struct wl12xx_acx_statistics); |
1451 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], &wl12xx_ht_cap, | 1617 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl12xx_ht_cap); |
1452 | sizeof(wl12xx_ht_cap)); | 1618 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, &wl12xx_ht_cap); |
1453 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], &wl12xx_ht_cap, | ||
1454 | sizeof(wl12xx_ht_cap)); | ||
1455 | wl12xx_conf_init(wl); | 1619 | wl12xx_conf_init(wl); |
1456 | 1620 | ||
1457 | if (!fref_param) { | 1621 | if (!fref_param) { |
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h index ebbaf611e97b..e2609a6b7341 100644 --- a/drivers/net/wireless/ti/wl18xx/acx.h +++ b/drivers/net/wireless/ti/wl18xx/acx.h | |||
@@ -32,25 +32,21 @@ enum { | |||
32 | /* numbers of bits the length field takes (add 1 for the actual number) */ | 32 | /* numbers of bits the length field takes (add 1 for the actual number) */ |
33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 | 33 | #define WL18XX_HOST_IF_LEN_SIZE_FIELD 15 |
34 | 34 | ||
35 | #define WL18XX_ACX_EVENTS_VECTOR_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | 35 | #define WL18XX_ACX_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ |
36 | WL1271_ACX_INTR_INIT_COMPLETE | \ | 36 | WL1271_ACX_INTR_INIT_COMPLETE | \ |
37 | WL1271_ACX_INTR_EVENT_A | \ | 37 | WL1271_ACX_INTR_EVENT_A | \ |
38 | WL1271_ACX_INTR_EVENT_B | \ | 38 | WL1271_ACX_INTR_EVENT_B | \ |
39 | WL1271_ACX_INTR_CMD_COMPLETE | \ | 39 | WL1271_ACX_INTR_CMD_COMPLETE | \ |
40 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 40 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
41 | WL1271_ACX_INTR_DATA) | 41 | WL1271_ACX_INTR_DATA | \ |
42 | 42 | WL1271_ACX_SW_INTR_WATCHDOG) | |
43 | #define WL18XX_ACX_EVENTS_VECTOR_PG2 (WL18XX_ACX_EVENTS_VECTOR_PG1 | \ | 43 | |
44 | WL1271_ACX_SW_INTR_WATCHDOG) | 44 | #define WL18XX_INTR_MASK (WL1271_ACX_INTR_WATCHDOG | \ |
45 | 45 | WL1271_ACX_INTR_EVENT_A | \ | |
46 | #define WL18XX_INTR_MASK_PG1 (WL1271_ACX_INTR_WATCHDOG | \ | 46 | WL1271_ACX_INTR_EVENT_B | \ |
47 | WL1271_ACX_INTR_EVENT_A | \ | 47 | WL1271_ACX_INTR_HW_AVAILABLE | \ |
48 | WL1271_ACX_INTR_EVENT_B | \ | 48 | WL1271_ACX_INTR_DATA | \ |
49 | WL1271_ACX_INTR_HW_AVAILABLE | \ | 49 | WL1271_ACX_SW_INTR_WATCHDOG) |
50 | WL1271_ACX_INTR_DATA) | ||
51 | |||
52 | #define WL18XX_INTR_MASK_PG2 (WL18XX_INTR_MASK_PG1 | \ | ||
53 | WL1271_ACX_SW_INTR_WATCHDOG) | ||
54 | 50 | ||
55 | struct wl18xx_acx_host_config_bitmap { | 51 | struct wl18xx_acx_host_config_bitmap { |
56 | struct acx_header header; | 52 | struct acx_header header; |
diff --git a/drivers/net/wireless/ti/wl18xx/io.c b/drivers/net/wireless/ti/wl18xx/io.c index 598c057e722b..0c06ccfd1b8c 100644 --- a/drivers/net/wireless/ti/wl18xx/io.c +++ b/drivers/net/wireless/ti/wl18xx/io.c | |||
@@ -24,37 +24,52 @@ | |||
24 | 24 | ||
25 | #include "io.h" | 25 | #include "io.h" |
26 | 26 | ||
27 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) | 27 | int wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val) |
28 | { | 28 | { |
29 | u32 tmp; | 29 | u32 tmp; |
30 | int ret; | ||
30 | 31 | ||
31 | if (WARN_ON(addr % 2)) | 32 | if (WARN_ON(addr % 2)) |
32 | return; | 33 | return -EINVAL; |
33 | 34 | ||
34 | if ((addr % 4) == 0) { | 35 | if ((addr % 4) == 0) { |
35 | tmp = wl1271_read32(wl, addr); | 36 | ret = wlcore_read32(wl, addr, &tmp); |
37 | if (ret < 0) | ||
38 | goto out; | ||
39 | |||
36 | tmp = (tmp & 0xffff0000) | val; | 40 | tmp = (tmp & 0xffff0000) | val; |
37 | wl1271_write32(wl, addr, tmp); | 41 | ret = wlcore_write32(wl, addr, tmp); |
38 | } else { | 42 | } else { |
39 | tmp = wl1271_read32(wl, addr - 2); | 43 | ret = wlcore_read32(wl, addr - 2, &tmp); |
44 | if (ret < 0) | ||
45 | goto out; | ||
46 | |||
40 | tmp = (tmp & 0xffff) | (val << 16); | 47 | tmp = (tmp & 0xffff) | (val << 16); |
41 | wl1271_write32(wl, addr - 2, tmp); | 48 | ret = wlcore_write32(wl, addr - 2, tmp); |
42 | } | 49 | } |
50 | |||
51 | out: | ||
52 | return ret; | ||
43 | } | 53 | } |
44 | 54 | ||
45 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr) | 55 | int wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out) |
46 | { | 56 | { |
47 | u32 val; | 57 | u32 val; |
58 | int ret; | ||
48 | 59 | ||
49 | if (WARN_ON(addr % 2)) | 60 | if (WARN_ON(addr % 2)) |
50 | return 0; | 61 | return -EINVAL; |
51 | 62 | ||
52 | if ((addr % 4) == 0) { | 63 | if ((addr % 4) == 0) { |
53 | /* address is 4-bytes aligned */ | 64 | /* address is 4-bytes aligned */ |
54 | val = wl1271_read32(wl, addr); | 65 | ret = wlcore_read32(wl, addr, &val); |
55 | return val & 0xffff; | 66 | if (ret >= 0 && out) |
67 | *out = val & 0xffff; | ||
56 | } else { | 68 | } else { |
57 | val = wl1271_read32(wl, addr - 2); | 69 | ret = wlcore_read32(wl, addr - 2, &val); |
58 | return (val & 0xffff0000) >> 16; | 70 | if (ret >= 0 && out) |
71 | *out = (val & 0xffff0000) >> 16; | ||
59 | } | 72 | } |
73 | |||
74 | return ret; | ||
60 | } | 75 | } |
diff --git a/drivers/net/wireless/ti/wl18xx/io.h b/drivers/net/wireless/ti/wl18xx/io.h index be4e126ff617..c32ae30277df 100644 --- a/drivers/net/wireless/ti/wl18xx/io.h +++ b/drivers/net/wireless/ti/wl18xx/io.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #ifndef __WL18XX_IO_H__ | 22 | #ifndef __WL18XX_IO_H__ |
23 | #define __WL18XX_IO_H__ | 23 | #define __WL18XX_IO_H__ |
24 | 24 | ||
25 | void wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); | 25 | int __must_check wl18xx_top_reg_write(struct wl1271 *wl, int addr, u16 val); |
26 | u16 wl18xx_top_reg_read(struct wl1271 *wl, int addr); | 26 | int __must_check wl18xx_top_reg_read(struct wl1271 *wl, int addr, u16 *out); |
27 | 27 | ||
28 | #endif /* __WL18XX_IO_H__ */ | 28 | #endif /* __WL18XX_IO_H__ */ |
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index ed9c3650e08a..5e583be8f674 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c | |||
@@ -43,10 +43,11 @@ | |||
43 | 43 | ||
44 | #define WL18XX_RX_CHECKSUM_MASK 0x40 | 44 | #define WL18XX_RX_CHECKSUM_MASK 0x40 |
45 | 45 | ||
46 | static char *ht_mode_param = "wide"; | 46 | static char *ht_mode_param = "default"; |
47 | static char *board_type_param = "hdk"; | 47 | static char *board_type_param = "hdk"; |
48 | static bool checksum_param = false; | 48 | static bool checksum_param = false; |
49 | static bool enable_11a_param = true; | 49 | static bool enable_11a_param = true; |
50 | static int num_rx_desc_param = -1; | ||
50 | 51 | ||
51 | /* phy paramters */ | 52 | /* phy paramters */ |
52 | static int dc2dc_param = -1; | 53 | static int dc2dc_param = -1; |
@@ -372,6 +373,7 @@ static struct wlcore_conf wl18xx_conf = { | |||
372 | .forced_ps = false, | 373 | .forced_ps = false, |
373 | .keep_alive_interval = 55000, | 374 | .keep_alive_interval = 55000, |
374 | .max_listen_interval = 20, | 375 | .max_listen_interval = 20, |
376 | .sta_sleep_auth = WL1271_PSM_ILLEGAL, | ||
375 | }, | 377 | }, |
376 | .itrim = { | 378 | .itrim = { |
377 | .enable = false, | 379 | .enable = false, |
@@ -606,24 +608,15 @@ static int wl18xx_identify_chip(struct wl1271 *wl) | |||
606 | wl->plt_fw_name = WL18XX_FW_NAME; | 608 | wl->plt_fw_name = WL18XX_FW_NAME; |
607 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | 609 | wl->quirks |= WLCORE_QUIRK_NO_ELP | |
608 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | 610 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | |
611 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN | | ||
609 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; | 612 | WLCORE_QUIRK_TX_PAD_LAST_FRAME; |
610 | |||
611 | break; | 613 | break; |
612 | case CHIP_ID_185x_PG10: | 614 | case CHIP_ID_185x_PG10: |
613 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (185x PG10)", | 615 | wl1271_warning("chip id 0x%x (185x PG10) is deprecated", |
614 | wl->chip.id); | 616 | wl->chip.id); |
615 | wl->sr_fw_name = WL18XX_FW_NAME; | 617 | ret = -ENODEV; |
616 | /* wl18xx uses the same firmware for PLT */ | 618 | goto out; |
617 | wl->plt_fw_name = WL18XX_FW_NAME; | ||
618 | wl->quirks |= WLCORE_QUIRK_NO_ELP | | ||
619 | WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED | | ||
620 | WLCORE_QUIRK_RX_BLOCKSIZE_ALIGN | | ||
621 | WLCORE_QUIRK_TX_BLOCKSIZE_ALIGN; | ||
622 | |||
623 | /* PG 1.0 has some problems with MCS_13, so disable it */ | ||
624 | wl->ht_cap[IEEE80211_BAND_2GHZ].mcs.rx_mask[1] &= ~BIT(5); | ||
625 | 619 | ||
626 | break; | ||
627 | default: | 620 | default: |
628 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); | 621 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
629 | ret = -ENODEV; | 622 | ret = -ENODEV; |
@@ -634,123 +627,178 @@ out: | |||
634 | return ret; | 627 | return ret; |
635 | } | 628 | } |
636 | 629 | ||
637 | static void wl18xx_set_clk(struct wl1271 *wl) | 630 | static int wl18xx_set_clk(struct wl1271 *wl) |
638 | { | 631 | { |
639 | u32 clk_freq; | 632 | u16 clk_freq; |
633 | int ret; | ||
640 | 634 | ||
641 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 635 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
636 | if (ret < 0) | ||
637 | goto out; | ||
642 | 638 | ||
643 | /* TODO: PG2: apparently we need to read the clk type */ | 639 | /* TODO: PG2: apparently we need to read the clk type */ |
644 | 640 | ||
645 | clk_freq = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT); | 641 | ret = wl18xx_top_reg_read(wl, PRIMARY_CLK_DETECT, &clk_freq); |
642 | if (ret < 0) | ||
643 | goto out; | ||
644 | |||
646 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, | 645 | wl1271_debug(DEBUG_BOOT, "clock freq %d (%d, %d, %d, %d, %s)", clk_freq, |
647 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, | 646 | wl18xx_clk_table[clk_freq].n, wl18xx_clk_table[clk_freq].m, |
648 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, | 647 | wl18xx_clk_table[clk_freq].p, wl18xx_clk_table[clk_freq].q, |
649 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); | 648 | wl18xx_clk_table[clk_freq].swallow ? "swallow" : "spit"); |
650 | 649 | ||
651 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, wl18xx_clk_table[clk_freq].n); | 650 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_N, |
652 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, wl18xx_clk_table[clk_freq].m); | 651 | wl18xx_clk_table[clk_freq].n); |
652 | if (ret < 0) | ||
653 | goto out; | ||
654 | |||
655 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_M, | ||
656 | wl18xx_clk_table[clk_freq].m); | ||
657 | if (ret < 0) | ||
658 | goto out; | ||
653 | 659 | ||
654 | if (wl18xx_clk_table[clk_freq].swallow) { | 660 | if (wl18xx_clk_table[clk_freq].swallow) { |
655 | /* first the 16 lower bits */ | 661 | /* first the 16 lower bits */ |
656 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, | 662 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_1, |
657 | wl18xx_clk_table[clk_freq].q & | 663 | wl18xx_clk_table[clk_freq].q & |
658 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); | 664 | PLLSH_WCS_PLL_Q_FACTOR_CFG_1_MASK); |
665 | if (ret < 0) | ||
666 | goto out; | ||
667 | |||
659 | /* then the 16 higher bits, masked out */ | 668 | /* then the 16 higher bits, masked out */ |
660 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, | 669 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_Q_FACTOR_CFG_2, |
661 | (wl18xx_clk_table[clk_freq].q >> 16) & | 670 | (wl18xx_clk_table[clk_freq].q >> 16) & |
662 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); | 671 | PLLSH_WCS_PLL_Q_FACTOR_CFG_2_MASK); |
672 | if (ret < 0) | ||
673 | goto out; | ||
663 | 674 | ||
664 | /* first the 16 lower bits */ | 675 | /* first the 16 lower bits */ |
665 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, | 676 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_1, |
666 | wl18xx_clk_table[clk_freq].p & | 677 | wl18xx_clk_table[clk_freq].p & |
667 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); | 678 | PLLSH_WCS_PLL_P_FACTOR_CFG_1_MASK); |
679 | if (ret < 0) | ||
680 | goto out; | ||
681 | |||
668 | /* then the 16 higher bits, masked out */ | 682 | /* then the 16 higher bits, masked out */ |
669 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, | 683 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_P_FACTOR_CFG_2, |
670 | (wl18xx_clk_table[clk_freq].p >> 16) & | 684 | (wl18xx_clk_table[clk_freq].p >> 16) & |
671 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); | 685 | PLLSH_WCS_PLL_P_FACTOR_CFG_2_MASK); |
672 | } else { | 686 | } else { |
673 | wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, | 687 | ret = wl18xx_top_reg_write(wl, PLLSH_WCS_PLL_SWALLOW_EN, |
674 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); | 688 | PLLSH_WCS_PLL_SWALLOW_EN_VAL2); |
675 | } | 689 | } |
690 | |||
691 | out: | ||
692 | return ret; | ||
676 | } | 693 | } |
677 | 694 | ||
678 | static void wl18xx_boot_soft_reset(struct wl1271 *wl) | 695 | static int wl18xx_boot_soft_reset(struct wl1271 *wl) |
679 | { | 696 | { |
697 | int ret; | ||
698 | |||
680 | /* disable Rx/Tx */ | 699 | /* disable Rx/Tx */ |
681 | wl1271_write32(wl, WL18XX_ENABLE, 0x0); | 700 | ret = wlcore_write32(wl, WL18XX_ENABLE, 0x0); |
701 | if (ret < 0) | ||
702 | goto out; | ||
682 | 703 | ||
683 | /* disable auto calibration on start*/ | 704 | /* disable auto calibration on start*/ |
684 | wl1271_write32(wl, WL18XX_SPARE_A2, 0xffff); | 705 | ret = wlcore_write32(wl, WL18XX_SPARE_A2, 0xffff); |
706 | |||
707 | out: | ||
708 | return ret; | ||
685 | } | 709 | } |
686 | 710 | ||
687 | static int wl18xx_pre_boot(struct wl1271 *wl) | 711 | static int wl18xx_pre_boot(struct wl1271 *wl) |
688 | { | 712 | { |
689 | wl18xx_set_clk(wl); | 713 | int ret; |
714 | |||
715 | ret = wl18xx_set_clk(wl); | ||
716 | if (ret < 0) | ||
717 | goto out; | ||
690 | 718 | ||
691 | /* Continue the ELP wake up sequence */ | 719 | /* Continue the ELP wake up sequence */ |
692 | wl1271_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); | 720 | ret = wlcore_write32(wl, WL18XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); |
721 | if (ret < 0) | ||
722 | goto out; | ||
723 | |||
693 | udelay(500); | 724 | udelay(500); |
694 | 725 | ||
695 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 726 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
727 | if (ret < 0) | ||
728 | goto out; | ||
696 | 729 | ||
697 | /* Disable interrupts */ | 730 | /* Disable interrupts */ |
698 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); | 731 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); |
732 | if (ret < 0) | ||
733 | goto out; | ||
699 | 734 | ||
700 | wl18xx_boot_soft_reset(wl); | 735 | ret = wl18xx_boot_soft_reset(wl); |
701 | 736 | ||
702 | return 0; | 737 | out: |
738 | return ret; | ||
703 | } | 739 | } |
704 | 740 | ||
705 | static void wl18xx_pre_upload(struct wl1271 *wl) | 741 | static int wl18xx_pre_upload(struct wl1271 *wl) |
706 | { | 742 | { |
707 | u32 tmp; | 743 | u32 tmp; |
744 | int ret; | ||
708 | 745 | ||
709 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 746 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
747 | if (ret < 0) | ||
748 | goto out; | ||
710 | 749 | ||
711 | /* TODO: check if this is all needed */ | 750 | /* TODO: check if this is all needed */ |
712 | wl1271_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); | 751 | ret = wlcore_write32(wl, WL18XX_EEPROMLESS_IND, WL18XX_EEPROMLESS_IND); |
752 | if (ret < 0) | ||
753 | goto out; | ||
713 | 754 | ||
714 | tmp = wlcore_read_reg(wl, REG_CHIP_ID_B); | 755 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &tmp); |
756 | if (ret < 0) | ||
757 | goto out; | ||
715 | 758 | ||
716 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); | 759 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); |
717 | 760 | ||
718 | tmp = wl1271_read32(wl, WL18XX_SCR_PAD2); | 761 | ret = wlcore_read32(wl, WL18XX_SCR_PAD2, &tmp); |
762 | |||
763 | out: | ||
764 | return ret; | ||
719 | } | 765 | } |
720 | 766 | ||
721 | static void wl18xx_set_mac_and_phy(struct wl1271 *wl) | 767 | static int wl18xx_set_mac_and_phy(struct wl1271 *wl) |
722 | { | 768 | { |
723 | struct wl18xx_priv *priv = wl->priv; | 769 | struct wl18xx_priv *priv = wl->priv; |
724 | size_t len; | 770 | int ret; |
725 | 771 | ||
726 | /* the parameters struct is smaller for PG1 */ | 772 | ret = wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); |
727 | if (wl->chip.id == CHIP_ID_185x_PG10) | 773 | if (ret < 0) |
728 | len = offsetof(struct wl18xx_mac_and_phy_params, psat) + 1; | 774 | goto out; |
729 | else | 775 | |
730 | len = sizeof(struct wl18xx_mac_and_phy_params); | 776 | ret = wlcore_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, |
777 | sizeof(struct wl18xx_mac_and_phy_params), false); | ||
731 | 778 | ||
732 | wlcore_set_partition(wl, &wl->ptable[PART_PHY_INIT]); | 779 | out: |
733 | wl1271_write(wl, WL18XX_PHY_INIT_MEM_ADDR, (u8 *)&priv->conf.phy, len, | 780 | return ret; |
734 | false); | ||
735 | } | 781 | } |
736 | 782 | ||
737 | static void wl18xx_enable_interrupts(struct wl1271 *wl) | 783 | static int wl18xx_enable_interrupts(struct wl1271 *wl) |
738 | { | 784 | { |
739 | u32 event_mask, intr_mask; | 785 | u32 event_mask, intr_mask; |
786 | int ret; | ||
740 | 787 | ||
741 | if (wl->chip.id == CHIP_ID_185x_PG10) { | 788 | event_mask = WL18XX_ACX_EVENTS_VECTOR; |
742 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG1; | 789 | intr_mask = WL18XX_INTR_MASK; |
743 | intr_mask = WL18XX_INTR_MASK_PG1; | ||
744 | } else { | ||
745 | event_mask = WL18XX_ACX_EVENTS_VECTOR_PG2; | ||
746 | intr_mask = WL18XX_INTR_MASK_PG2; | ||
747 | } | ||
748 | 790 | ||
749 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); | 791 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, event_mask); |
792 | if (ret < 0) | ||
793 | goto out; | ||
750 | 794 | ||
751 | wlcore_enable_interrupts(wl); | 795 | wlcore_enable_interrupts(wl); |
752 | wlcore_write_reg(wl, REG_INTERRUPT_MASK, | 796 | |
753 | WL1271_ACX_INTR_ALL & ~intr_mask); | 797 | ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, |
798 | WL1271_ACX_INTR_ALL & ~intr_mask); | ||
799 | |||
800 | out: | ||
801 | return ret; | ||
754 | } | 802 | } |
755 | 803 | ||
756 | static int wl18xx_boot(struct wl1271 *wl) | 804 | static int wl18xx_boot(struct wl1271 *wl) |
@@ -761,25 +809,29 @@ static int wl18xx_boot(struct wl1271 *wl) | |||
761 | if (ret < 0) | 809 | if (ret < 0) |
762 | goto out; | 810 | goto out; |
763 | 811 | ||
764 | wl18xx_pre_upload(wl); | 812 | ret = wl18xx_pre_upload(wl); |
813 | if (ret < 0) | ||
814 | goto out; | ||
765 | 815 | ||
766 | ret = wlcore_boot_upload_firmware(wl); | 816 | ret = wlcore_boot_upload_firmware(wl); |
767 | if (ret < 0) | 817 | if (ret < 0) |
768 | goto out; | 818 | goto out; |
769 | 819 | ||
770 | wl18xx_set_mac_and_phy(wl); | 820 | ret = wl18xx_set_mac_and_phy(wl); |
821 | if (ret < 0) | ||
822 | goto out; | ||
771 | 823 | ||
772 | ret = wlcore_boot_run_firmware(wl); | 824 | ret = wlcore_boot_run_firmware(wl); |
773 | if (ret < 0) | 825 | if (ret < 0) |
774 | goto out; | 826 | goto out; |
775 | 827 | ||
776 | wl18xx_enable_interrupts(wl); | 828 | ret = wl18xx_enable_interrupts(wl); |
777 | 829 | ||
778 | out: | 830 | out: |
779 | return ret; | 831 | return ret; |
780 | } | 832 | } |
781 | 833 | ||
782 | static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | 834 | static int wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, |
783 | void *buf, size_t len) | 835 | void *buf, size_t len) |
784 | { | 836 | { |
785 | struct wl18xx_priv *priv = wl->priv; | 837 | struct wl18xx_priv *priv = wl->priv; |
@@ -787,13 +839,14 @@ static void wl18xx_trigger_cmd(struct wl1271 *wl, int cmd_box_addr, | |||
787 | memcpy(priv->cmd_buf, buf, len); | 839 | memcpy(priv->cmd_buf, buf, len); |
788 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); | 840 | memset(priv->cmd_buf + len, 0, WL18XX_CMD_MAX_SIZE - len); |
789 | 841 | ||
790 | wl1271_write(wl, cmd_box_addr, priv->cmd_buf, WL18XX_CMD_MAX_SIZE, | 842 | return wlcore_write(wl, cmd_box_addr, priv->cmd_buf, |
791 | false); | 843 | WL18XX_CMD_MAX_SIZE, false); |
792 | } | 844 | } |
793 | 845 | ||
794 | static void wl18xx_ack_event(struct wl1271 *wl) | 846 | static int wl18xx_ack_event(struct wl1271 *wl) |
795 | { | 847 | { |
796 | wlcore_write_reg(wl, REG_INTERRUPT_TRIG, WL18XX_INTR_TRIG_EVENT_ACK); | 848 | return wlcore_write_reg(wl, REG_INTERRUPT_TRIG, |
849 | WL18XX_INTR_TRIG_EVENT_ACK); | ||
797 | } | 850 | } |
798 | 851 | ||
799 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) | 852 | static u32 wl18xx_calc_tx_blocks(struct wl1271 *wl, u32 len, u32 spare_blks) |
@@ -975,34 +1028,32 @@ static u32 wl18xx_ap_get_mimo_wide_rate_mask(struct wl1271 *wl, | |||
975 | } else if (!strcmp(ht_mode_param, "mimo")) { | 1028 | } else if (!strcmp(ht_mode_param, "mimo")) { |
976 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); | 1029 | wl1271_debug(DEBUG_ACX, "using MIMO rate mask"); |
977 | 1030 | ||
978 | /* | ||
979 | * PG 1.0 has some problems with MCS_13, so disable it | ||
980 | * | ||
981 | * TODO: instead of hacking this in here, we should | ||
982 | * make it more general and change a bit in the | ||
983 | * wlvif->rate_set instead. | ||
984 | */ | ||
985 | if (wl->chip.id == CHIP_ID_185x_PG10) | ||
986 | return CONF_TX_MIMO_RATES & ~CONF_HW_BIT_RATE_MCS_13; | ||
987 | |||
988 | return CONF_TX_MIMO_RATES; | 1031 | return CONF_TX_MIMO_RATES; |
989 | } else { | 1032 | } else { |
990 | return 0; | 1033 | return 0; |
991 | } | 1034 | } |
992 | } | 1035 | } |
993 | 1036 | ||
994 | static s8 wl18xx_get_pg_ver(struct wl1271 *wl) | 1037 | static int wl18xx_get_pg_ver(struct wl1271 *wl, s8 *ver) |
995 | { | 1038 | { |
996 | u32 fuse; | 1039 | u32 fuse; |
1040 | int ret; | ||
997 | 1041 | ||
998 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1042 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); |
1043 | if (ret < 0) | ||
1044 | goto out; | ||
1045 | |||
1046 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_DATA_1_3, &fuse); | ||
1047 | if (ret < 0) | ||
1048 | goto out; | ||
999 | 1049 | ||
1000 | fuse = wl1271_read32(wl, WL18XX_REG_FUSE_DATA_1_3); | 1050 | if (ver) |
1001 | fuse = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; | 1051 | *ver = (fuse & WL18XX_PG_VER_MASK) >> WL18XX_PG_VER_OFFSET; |
1002 | 1052 | ||
1003 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1053 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1004 | 1054 | ||
1005 | return (s8)fuse; | 1055 | out: |
1056 | return ret; | ||
1006 | } | 1057 | } |
1007 | 1058 | ||
1008 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" | 1059 | #define WL18XX_CONF_FILE_NAME "ti-connectivity/wl18xx-conf.bin" |
@@ -1021,8 +1072,7 @@ static int wl18xx_conf_init(struct wl1271 *wl, struct device *dev) | |||
1021 | } | 1072 | } |
1022 | 1073 | ||
1023 | if (fw->size != WL18XX_CONF_SIZE) { | 1074 | if (fw->size != WL18XX_CONF_SIZE) { |
1024 | wl1271_error("configuration binary file size is wrong, " | 1075 | wl1271_error("configuration binary file size is wrong, expected %zu got %zu", |
1025 | "expected %ld got %zd", | ||
1026 | WL18XX_CONF_SIZE, fw->size); | 1076 | WL18XX_CONF_SIZE, fw->size); |
1027 | ret = -EINVAL; | 1077 | ret = -EINVAL; |
1028 | goto out; | 1078 | goto out; |
@@ -1069,26 +1119,41 @@ out: | |||
1069 | 1119 | ||
1070 | static int wl18xx_plt_init(struct wl1271 *wl) | 1120 | static int wl18xx_plt_init(struct wl1271 *wl) |
1071 | { | 1121 | { |
1072 | wl1271_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | 1122 | int ret; |
1123 | |||
1124 | ret = wlcore_write32(wl, WL18XX_SCR_PAD8, WL18XX_SCR_PAD8_PLT); | ||
1125 | if (ret < 0) | ||
1126 | return ret; | ||
1073 | 1127 | ||
1074 | return wl->ops->boot(wl); | 1128 | return wl->ops->boot(wl); |
1075 | } | 1129 | } |
1076 | 1130 | ||
1077 | static void wl18xx_get_mac(struct wl1271 *wl) | 1131 | static int wl18xx_get_mac(struct wl1271 *wl) |
1078 | { | 1132 | { |
1079 | u32 mac1, mac2; | 1133 | u32 mac1, mac2; |
1134 | int ret; | ||
1135 | |||
1136 | ret = wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | ||
1137 | if (ret < 0) | ||
1138 | goto out; | ||
1080 | 1139 | ||
1081 | wlcore_set_partition(wl, &wl->ptable[PART_TOP_PRCM_ELP_SOC]); | 1140 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1, &mac1); |
1141 | if (ret < 0) | ||
1142 | goto out; | ||
1082 | 1143 | ||
1083 | mac1 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_1); | 1144 | ret = wlcore_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2, &mac2); |
1084 | mac2 = wl1271_read32(wl, WL18XX_REG_FUSE_BD_ADDR_2); | 1145 | if (ret < 0) |
1146 | goto out; | ||
1085 | 1147 | ||
1086 | /* these are the two parts of the BD_ADDR */ | 1148 | /* these are the two parts of the BD_ADDR */ |
1087 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + | 1149 | wl->fuse_oui_addr = ((mac2 & 0xffff) << 8) + |
1088 | ((mac1 & 0xff000000) >> 24); | 1150 | ((mac1 & 0xff000000) >> 24); |
1089 | wl->fuse_nic_addr = (mac1 & 0xffffff); | 1151 | wl->fuse_nic_addr = (mac1 & 0xffffff); |
1090 | 1152 | ||
1091 | wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); | 1153 | ret = wlcore_set_partition(wl, &wl->ptable[PART_DOWN]); |
1154 | |||
1155 | out: | ||
1156 | return ret; | ||
1092 | } | 1157 | } |
1093 | 1158 | ||
1094 | static int wl18xx_handle_static_data(struct wl1271 *wl, | 1159 | static int wl18xx_handle_static_data(struct wl1271 *wl, |
@@ -1214,8 +1279,8 @@ static struct wlcore_ops wl18xx_ops = { | |||
1214 | .pre_pkt_send = wl18xx_pre_pkt_send, | 1279 | .pre_pkt_send = wl18xx_pre_pkt_send, |
1215 | }; | 1280 | }; |
1216 | 1281 | ||
1217 | /* HT cap appropriate for wide channels */ | 1282 | /* HT cap appropriate for wide channels in 2Ghz */ |
1218 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = { | 1283 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_2ghz = { |
1219 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | | 1284 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1220 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, | 1285 | IEEE80211_HT_CAP_SUP_WIDTH_20_40 | IEEE80211_HT_CAP_DSSSCCK40, |
1221 | .ht_supported = true, | 1286 | .ht_supported = true, |
@@ -1228,40 +1293,42 @@ static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap = { | |||
1228 | }, | 1293 | }, |
1229 | }; | 1294 | }; |
1230 | 1295 | ||
1231 | /* HT cap appropriate for SISO 20 */ | 1296 | /* HT cap appropriate for wide channels in 5Ghz */ |
1232 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { | 1297 | static struct ieee80211_sta_ht_cap wl18xx_siso40_ht_cap_5ghz = { |
1233 | .cap = IEEE80211_HT_CAP_SGI_20, | 1298 | .cap = IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_SGI_40 | |
1299 | IEEE80211_HT_CAP_SUP_WIDTH_20_40, | ||
1234 | .ht_supported = true, | 1300 | .ht_supported = true, |
1235 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1301 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1236 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1302 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
1237 | .mcs = { | 1303 | .mcs = { |
1238 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | 1304 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1239 | .rx_highest = cpu_to_le16(72), | 1305 | .rx_highest = cpu_to_le16(150), |
1240 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | 1306 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1241 | }, | 1307 | }, |
1242 | }; | 1308 | }; |
1243 | 1309 | ||
1244 | /* HT cap appropriate for MIMO rates in 20mhz channel */ | 1310 | /* HT cap appropriate for SISO 20 */ |
1245 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | 1311 | static struct ieee80211_sta_ht_cap wl18xx_siso20_ht_cap = { |
1246 | .cap = IEEE80211_HT_CAP_SGI_20, | 1312 | .cap = IEEE80211_HT_CAP_SGI_20, |
1247 | .ht_supported = true, | 1313 | .ht_supported = true, |
1248 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1314 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1249 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1315 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
1250 | .mcs = { | 1316 | .mcs = { |
1251 | .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, }, | 1317 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1252 | .rx_highest = cpu_to_le16(144), | 1318 | .rx_highest = cpu_to_le16(72), |
1253 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | 1319 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1254 | }, | 1320 | }, |
1255 | }; | 1321 | }; |
1256 | 1322 | ||
1257 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_5ghz = { | 1323 | /* HT cap appropriate for MIMO rates in 20mhz channel */ |
1324 | static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { | ||
1258 | .cap = IEEE80211_HT_CAP_SGI_20, | 1325 | .cap = IEEE80211_HT_CAP_SGI_20, |
1259 | .ht_supported = true, | 1326 | .ht_supported = true, |
1260 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, | 1327 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_16K, |
1261 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, | 1328 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, |
1262 | .mcs = { | 1329 | .mcs = { |
1263 | .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, | 1330 | .rx_mask = { 0xff, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, }, |
1264 | .rx_highest = cpu_to_le16(72), | 1331 | .rx_highest = cpu_to_le16(144), |
1265 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, | 1332 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, |
1266 | }, | 1333 | }, |
1267 | }; | 1334 | }; |
@@ -1286,7 +1353,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) | |||
1286 | wl->ptable = wl18xx_ptable; | 1353 | wl->ptable = wl18xx_ptable; |
1287 | wl->rtable = wl18xx_rtable; | 1354 | wl->rtable = wl18xx_rtable; |
1288 | wl->num_tx_desc = 32; | 1355 | wl->num_tx_desc = 32; |
1289 | wl->num_rx_desc = 16; | 1356 | wl->num_rx_desc = 32; |
1290 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; | 1357 | wl->band_rate_to_idx = wl18xx_band_rate_to_idx; |
1291 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; | 1358 | wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; |
1292 | wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; | 1359 | wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; |
@@ -1294,32 +1361,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) | |||
1294 | wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); | 1361 | wl->stats.fw_stats_len = sizeof(struct wl18xx_acx_statistics); |
1295 | wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); | 1362 | wl->static_data_priv_len = sizeof(struct wl18xx_static_data_priv); |
1296 | 1363 | ||
1297 | if (!strcmp(ht_mode_param, "wide")) { | 1364 | if (num_rx_desc_param != -1) |
1298 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | 1365 | wl->num_rx_desc = num_rx_desc_param; |
1299 | &wl18xx_siso40_ht_cap, | ||
1300 | sizeof(wl18xx_siso40_ht_cap)); | ||
1301 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1302 | &wl18xx_siso40_ht_cap, | ||
1303 | sizeof(wl18xx_siso40_ht_cap)); | ||
1304 | } else if (!strcmp(ht_mode_param, "mimo")) { | ||
1305 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1306 | &wl18xx_mimo_ht_cap_2ghz, | ||
1307 | sizeof(wl18xx_mimo_ht_cap_2ghz)); | ||
1308 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1309 | &wl18xx_mimo_ht_cap_5ghz, | ||
1310 | sizeof(wl18xx_mimo_ht_cap_5ghz)); | ||
1311 | } else if (!strcmp(ht_mode_param, "siso20")) { | ||
1312 | memcpy(&wl->ht_cap[IEEE80211_BAND_2GHZ], | ||
1313 | &wl18xx_siso20_ht_cap, | ||
1314 | sizeof(wl18xx_siso20_ht_cap)); | ||
1315 | memcpy(&wl->ht_cap[IEEE80211_BAND_5GHZ], | ||
1316 | &wl18xx_siso20_ht_cap, | ||
1317 | sizeof(wl18xx_siso20_ht_cap)); | ||
1318 | } else { | ||
1319 | wl1271_error("invalid ht_mode '%s'", ht_mode_param); | ||
1320 | ret = -EINVAL; | ||
1321 | goto out_free; | ||
1322 | } | ||
1323 | 1366 | ||
1324 | ret = wl18xx_conf_init(wl, &pdev->dev); | 1367 | ret = wl18xx_conf_init(wl, &pdev->dev); |
1325 | if (ret < 0) | 1368 | if (ret < 0) |
@@ -1366,6 +1409,37 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) | |||
1366 | if (dc2dc_param != -1) | 1409 | if (dc2dc_param != -1) |
1367 | priv->conf.phy.external_pa_dc2dc = dc2dc_param; | 1410 | priv->conf.phy.external_pa_dc2dc = dc2dc_param; |
1368 | 1411 | ||
1412 | if (!strcmp(ht_mode_param, "default")) { | ||
1413 | /* | ||
1414 | * Only support mimo with multiple antennas. Fall back to | ||
1415 | * siso20. | ||
1416 | */ | ||
1417 | if (priv->conf.phy.number_of_assembled_ant2_4 >= 2) | ||
1418 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1419 | &wl18xx_mimo_ht_cap_2ghz); | ||
1420 | else | ||
1421 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1422 | &wl18xx_siso20_ht_cap); | ||
1423 | |||
1424 | /* 5Ghz is always wide */ | ||
1425 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, | ||
1426 | &wl18xx_siso40_ht_cap_5ghz); | ||
1427 | } else if (!strcmp(ht_mode_param, "wide")) { | ||
1428 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1429 | &wl18xx_siso40_ht_cap_2ghz); | ||
1430 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, | ||
1431 | &wl18xx_siso40_ht_cap_5ghz); | ||
1432 | } else if (!strcmp(ht_mode_param, "siso20")) { | ||
1433 | wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, | ||
1434 | &wl18xx_siso20_ht_cap); | ||
1435 | wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, | ||
1436 | &wl18xx_siso20_ht_cap); | ||
1437 | } else { | ||
1438 | wl1271_error("invalid ht_mode '%s'", ht_mode_param); | ||
1439 | ret = -EINVAL; | ||
1440 | goto out_free; | ||
1441 | } | ||
1442 | |||
1369 | if (!checksum_param) { | 1443 | if (!checksum_param) { |
1370 | wl18xx_ops.set_rx_csum = NULL; | 1444 | wl18xx_ops.set_rx_csum = NULL; |
1371 | wl18xx_ops.init_vif = NULL; | 1445 | wl18xx_ops.init_vif = NULL; |
@@ -1410,7 +1484,7 @@ static void __exit wl18xx_exit(void) | |||
1410 | module_exit(wl18xx_exit); | 1484 | module_exit(wl18xx_exit); |
1411 | 1485 | ||
1412 | module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); | 1486 | module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); |
1413 | MODULE_PARM_DESC(ht_mode, "Force HT mode: wide (default), mimo or siso20"); | 1487 | MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20"); |
1414 | 1488 | ||
1415 | module_param_named(board_type, board_type_param, charp, S_IRUSR); | 1489 | module_param_named(board_type, board_type_param, charp, S_IRUSR); |
1416 | MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " | 1490 | MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " |
@@ -1458,6 +1532,11 @@ module_param_named(pwr_limit_reference_11_abg, | |||
1458 | MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 " | 1532 | MODULE_PARM_DESC(pwr_limit_reference_11_abg, "Power limit reference: u8 " |
1459 | "(default is 0xc8)"); | 1533 | "(default is 0xc8)"); |
1460 | 1534 | ||
1535 | module_param_named(num_rx_desc, | ||
1536 | num_rx_desc_param, int, S_IRUSR); | ||
1537 | MODULE_PARM_DESC(num_rx_desc_param, | ||
1538 | "Number of Rx descriptors: u8 (default is 32)"); | ||
1539 | |||
1461 | MODULE_LICENSE("GPL v2"); | 1540 | MODULE_LICENSE("GPL v2"); |
1462 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); | 1541 | MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>"); |
1463 | MODULE_FIRMWARE(WL18XX_FW_NAME); | 1542 | MODULE_FIRMWARE(WL18XX_FW_NAME); |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index b9ec42c83757..ce108a736bd0 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -70,7 +70,7 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) | |||
70 | struct acx_sleep_auth *auth; | 70 | struct acx_sleep_auth *auth; |
71 | int ret; | 71 | int ret; |
72 | 72 | ||
73 | wl1271_debug(DEBUG_ACX, "acx sleep auth"); | 73 | wl1271_debug(DEBUG_ACX, "acx sleep auth %d", sleep_auth); |
74 | 74 | ||
75 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); | 75 | auth = kzalloc(sizeof(*auth), GFP_KERNEL); |
76 | if (!auth) { | 76 | if (!auth) { |
@@ -81,7 +81,13 @@ int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) | |||
81 | auth->sleep_auth = sleep_auth; | 81 | auth->sleep_auth = sleep_auth; |
82 | 82 | ||
83 | ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); | 83 | ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); |
84 | if (ret < 0) { | ||
85 | wl1271_error("could not configure sleep_auth to %d: %d", | ||
86 | sleep_auth, ret); | ||
87 | goto out; | ||
88 | } | ||
84 | 89 | ||
90 | wl->sleep_auth = sleep_auth; | ||
85 | out: | 91 | out: |
86 | kfree(auth); | 92 | kfree(auth); |
87 | return ret; | 93 | return ret; |
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index c0181258b722..d03215d6b3bd 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -118,6 +118,11 @@ enum wl1271_psm_mode { | |||
118 | 118 | ||
119 | /* Extreme low power */ | 119 | /* Extreme low power */ |
120 | WL1271_PSM_ELP = 2, | 120 | WL1271_PSM_ELP = 2, |
121 | |||
122 | WL1271_PSM_MAX = WL1271_PSM_ELP, | ||
123 | |||
124 | /* illegal out of band value of PSM mode */ | ||
125 | WL1271_PSM_ILLEGAL = 0xff | ||
121 | }; | 126 | }; |
122 | 127 | ||
123 | struct acx_sleep_auth { | 128 | struct acx_sleep_auth { |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 0fda500c01c9..8965960b841a 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -33,16 +33,22 @@ | |||
33 | #include "rx.h" | 33 | #include "rx.h" |
34 | #include "hw_ops.h" | 34 | #include "hw_ops.h" |
35 | 35 | ||
36 | static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) | 36 | static int wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) |
37 | { | 37 | { |
38 | u32 cpu_ctrl; | 38 | u32 cpu_ctrl; |
39 | int ret; | ||
39 | 40 | ||
40 | /* 10.5.0 run the firmware (I) */ | 41 | /* 10.5.0 run the firmware (I) */ |
41 | cpu_ctrl = wlcore_read_reg(wl, REG_ECPU_CONTROL); | 42 | ret = wlcore_read_reg(wl, REG_ECPU_CONTROL, &cpu_ctrl); |
43 | if (ret < 0) | ||
44 | goto out; | ||
42 | 45 | ||
43 | /* 10.5.1 run the firmware (II) */ | 46 | /* 10.5.1 run the firmware (II) */ |
44 | cpu_ctrl |= flag; | 47 | cpu_ctrl |= flag; |
45 | wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); | 48 | ret = wlcore_write_reg(wl, REG_ECPU_CONTROL, cpu_ctrl); |
49 | |||
50 | out: | ||
51 | return ret; | ||
46 | } | 52 | } |
47 | 53 | ||
48 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, | 54 | static int wlcore_boot_parse_fw_ver(struct wl1271 *wl, |
@@ -87,7 +93,9 @@ static int wlcore_boot_static_data(struct wl1271 *wl) | |||
87 | goto out; | 93 | goto out; |
88 | } | 94 | } |
89 | 95 | ||
90 | wl1271_read(wl, wl->cmd_box_addr, static_data, len, false); | 96 | ret = wlcore_read(wl, wl->cmd_box_addr, static_data, len, false); |
97 | if (ret < 0) | ||
98 | goto out_free; | ||
91 | 99 | ||
92 | ret = wlcore_boot_parse_fw_ver(wl, static_data); | 100 | ret = wlcore_boot_parse_fw_ver(wl, static_data); |
93 | if (ret < 0) | 101 | if (ret < 0) |
@@ -109,6 +117,7 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
109 | struct wlcore_partition_set partition; | 117 | struct wlcore_partition_set partition; |
110 | int addr, chunk_num, partition_limit; | 118 | int addr, chunk_num, partition_limit; |
111 | u8 *p, *chunk; | 119 | u8 *p, *chunk; |
120 | int ret; | ||
112 | 121 | ||
113 | /* whal_FwCtrl_LoadFwImageSm() */ | 122 | /* whal_FwCtrl_LoadFwImageSm() */ |
114 | 123 | ||
@@ -130,7 +139,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
130 | 139 | ||
131 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); | 140 | memcpy(&partition, &wl->ptable[PART_DOWN], sizeof(partition)); |
132 | partition.mem.start = dest; | 141 | partition.mem.start = dest; |
133 | wlcore_set_partition(wl, &partition); | 142 | ret = wlcore_set_partition(wl, &partition); |
143 | if (ret < 0) | ||
144 | return ret; | ||
134 | 145 | ||
135 | /* 10.1 set partition limit and chunk num */ | 146 | /* 10.1 set partition limit and chunk num */ |
136 | chunk_num = 0; | 147 | chunk_num = 0; |
@@ -144,7 +155,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
144 | partition_limit = chunk_num * CHUNK_SIZE + | 155 | partition_limit = chunk_num * CHUNK_SIZE + |
145 | wl->ptable[PART_DOWN].mem.size; | 156 | wl->ptable[PART_DOWN].mem.size; |
146 | partition.mem.start = addr; | 157 | partition.mem.start = addr; |
147 | wlcore_set_partition(wl, &partition); | 158 | ret = wlcore_set_partition(wl, &partition); |
159 | if (ret < 0) | ||
160 | return ret; | ||
148 | } | 161 | } |
149 | 162 | ||
150 | /* 10.3 upload the chunk */ | 163 | /* 10.3 upload the chunk */ |
@@ -153,7 +166,9 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
153 | memcpy(chunk, p, CHUNK_SIZE); | 166 | memcpy(chunk, p, CHUNK_SIZE); |
154 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 167 | wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
155 | p, addr); | 168 | p, addr); |
156 | wl1271_write(wl, addr, chunk, CHUNK_SIZE, false); | 169 | ret = wlcore_write(wl, addr, chunk, CHUNK_SIZE, false); |
170 | if (ret < 0) | ||
171 | goto out; | ||
157 | 172 | ||
158 | chunk_num++; | 173 | chunk_num++; |
159 | } | 174 | } |
@@ -164,10 +179,11 @@ static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, | |||
164 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); | 179 | memcpy(chunk, p, fw_data_len % CHUNK_SIZE); |
165 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", | 180 | wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", |
166 | fw_data_len % CHUNK_SIZE, p, addr); | 181 | fw_data_len % CHUNK_SIZE, p, addr); |
167 | wl1271_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); | 182 | ret = wlcore_write(wl, addr, chunk, fw_data_len % CHUNK_SIZE, false); |
168 | 183 | ||
184 | out: | ||
169 | kfree(chunk); | 185 | kfree(chunk); |
170 | return 0; | 186 | return ret; |
171 | } | 187 | } |
172 | 188 | ||
173 | int wlcore_boot_upload_firmware(struct wl1271 *wl) | 189 | int wlcore_boot_upload_firmware(struct wl1271 *wl) |
@@ -210,6 +226,7 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
210 | int i; | 226 | int i; |
211 | u32 dest_addr, val; | 227 | u32 dest_addr, val; |
212 | u8 *nvs_ptr, *nvs_aligned; | 228 | u8 *nvs_ptr, *nvs_aligned; |
229 | int ret; | ||
213 | 230 | ||
214 | if (wl->nvs == NULL) { | 231 | if (wl->nvs == NULL) { |
215 | wl1271_error("NVS file is needed during boot"); | 232 | wl1271_error("NVS file is needed during boot"); |
@@ -307,7 +324,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
307 | wl1271_debug(DEBUG_BOOT, | 324 | wl1271_debug(DEBUG_BOOT, |
308 | "nvs burst write 0x%x: 0x%x", | 325 | "nvs burst write 0x%x: 0x%x", |
309 | dest_addr, val); | 326 | dest_addr, val); |
310 | wl1271_write32(wl, dest_addr, val); | 327 | ret = wlcore_write32(wl, dest_addr, val); |
328 | if (ret < 0) | ||
329 | return ret; | ||
311 | 330 | ||
312 | nvs_ptr += 4; | 331 | nvs_ptr += 4; |
313 | dest_addr += 4; | 332 | dest_addr += 4; |
@@ -333,7 +352,9 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
333 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; | 352 | nvs_len -= nvs_ptr - (u8 *)wl->nvs; |
334 | 353 | ||
335 | /* Now we must set the partition correctly */ | 354 | /* Now we must set the partition correctly */ |
336 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 355 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
356 | if (ret < 0) | ||
357 | return ret; | ||
337 | 358 | ||
338 | /* Copy the NVS tables to a new block to ensure alignment */ | 359 | /* Copy the NVS tables to a new block to ensure alignment */ |
339 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); | 360 | nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); |
@@ -341,11 +362,11 @@ int wlcore_boot_upload_nvs(struct wl1271 *wl) | |||
341 | return -ENOMEM; | 362 | return -ENOMEM; |
342 | 363 | ||
343 | /* And finally we upload the NVS tables */ | 364 | /* And finally we upload the NVS tables */ |
344 | wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, | 365 | ret = wlcore_write_data(wl, REG_CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, |
345 | nvs_aligned, nvs_len, false); | 366 | false); |
346 | 367 | ||
347 | kfree(nvs_aligned); | 368 | kfree(nvs_aligned); |
348 | return 0; | 369 | return ret; |
349 | 370 | ||
350 | out_badnvs: | 371 | out_badnvs: |
351 | wl1271_error("nvs data is malformed"); | 372 | wl1271_error("nvs data is malformed"); |
@@ -359,11 +380,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
359 | u32 chip_id, intr; | 380 | u32 chip_id, intr; |
360 | 381 | ||
361 | /* Make sure we have the boot partition */ | 382 | /* Make sure we have the boot partition */ |
362 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 383 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
384 | if (ret < 0) | ||
385 | return ret; | ||
363 | 386 | ||
364 | wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); | 387 | ret = wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); |
388 | if (ret < 0) | ||
389 | return ret; | ||
365 | 390 | ||
366 | chip_id = wlcore_read_reg(wl, REG_CHIP_ID_B); | 391 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &chip_id); |
392 | if (ret < 0) | ||
393 | return ret; | ||
367 | 394 | ||
368 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); | 395 | wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); |
369 | 396 | ||
@@ -376,7 +403,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
376 | loop = 0; | 403 | loop = 0; |
377 | while (loop++ < INIT_LOOP) { | 404 | while (loop++ < INIT_LOOP) { |
378 | udelay(INIT_LOOP_DELAY); | 405 | udelay(INIT_LOOP_DELAY); |
379 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 406 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
407 | if (ret < 0) | ||
408 | return ret; | ||
380 | 409 | ||
381 | if (intr == 0xffffffff) { | 410 | if (intr == 0xffffffff) { |
382 | wl1271_error("error reading hardware complete " | 411 | wl1271_error("error reading hardware complete " |
@@ -385,8 +414,10 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
385 | } | 414 | } |
386 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ | 415 | /* check that ACX_INTR_INIT_COMPLETE is enabled */ |
387 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { | 416 | else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) { |
388 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, | 417 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
389 | WL1271_ACX_INTR_INIT_COMPLETE); | 418 | WL1271_ACX_INTR_INIT_COMPLETE); |
419 | if (ret < 0) | ||
420 | return ret; | ||
390 | break; | 421 | break; |
391 | } | 422 | } |
392 | } | 423 | } |
@@ -398,12 +429,17 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
398 | } | 429 | } |
399 | 430 | ||
400 | /* get hardware config command mail box */ | 431 | /* get hardware config command mail box */ |
401 | wl->cmd_box_addr = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR); | 432 | ret = wlcore_read_reg(wl, REG_COMMAND_MAILBOX_PTR, &wl->cmd_box_addr); |
433 | if (ret < 0) | ||
434 | return ret; | ||
402 | 435 | ||
403 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); | 436 | wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x", wl->cmd_box_addr); |
404 | 437 | ||
405 | /* get hardware config event mail box */ | 438 | /* get hardware config event mail box */ |
406 | wl->mbox_ptr[0] = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR); | 439 | ret = wlcore_read_reg(wl, REG_EVENT_MAILBOX_PTR, &wl->mbox_ptr[0]); |
440 | if (ret < 0) | ||
441 | return ret; | ||
442 | |||
407 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); | 443 | wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); |
408 | 444 | ||
409 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", | 445 | wl1271_debug(DEBUG_MAILBOX, "MBOX ptrs: 0x%x 0x%x", |
@@ -445,9 +481,9 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
445 | } | 481 | } |
446 | 482 | ||
447 | /* set the working partition to its "running" mode offset */ | 483 | /* set the working partition to its "running" mode offset */ |
448 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | 484 | ret = wlcore_set_partition(wl, &wl->ptable[PART_WORK]); |
449 | 485 | ||
450 | /* firmware startup completed */ | 486 | /* firmware startup completed */ |
451 | return 0; | 487 | return ret; |
452 | } | 488 | } |
453 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); | 489 | EXPORT_SYMBOL_GPL(wlcore_boot_run_firmware); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 885364ca4344..56c7a2342fdf 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -65,17 +65,24 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
65 | WARN_ON(len % 4 != 0); | 65 | WARN_ON(len % 4 != 0); |
66 | WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); | 66 | WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags)); |
67 | 67 | ||
68 | wl1271_write(wl, wl->cmd_box_addr, buf, len, false); | 68 | ret = wlcore_write(wl, wl->cmd_box_addr, buf, len, false); |
69 | if (ret < 0) | ||
70 | goto fail; | ||
69 | 71 | ||
70 | /* | 72 | /* |
71 | * TODO: we just need this because one bit is in a different | 73 | * TODO: we just need this because one bit is in a different |
72 | * place. Is there any better way? | 74 | * place. Is there any better way? |
73 | */ | 75 | */ |
74 | wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); | 76 | ret = wl->ops->trigger_cmd(wl, wl->cmd_box_addr, buf, len); |
77 | if (ret < 0) | ||
78 | goto fail; | ||
75 | 79 | ||
76 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); | 80 | timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); |
77 | 81 | ||
78 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 82 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
83 | if (ret < 0) | ||
84 | goto fail; | ||
85 | |||
79 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { | 86 | while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { |
80 | if (time_after(jiffies, timeout)) { | 87 | if (time_after(jiffies, timeout)) { |
81 | wl1271_error("command complete timeout"); | 88 | wl1271_error("command complete timeout"); |
@@ -89,13 +96,18 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
89 | else | 96 | else |
90 | msleep(1); | 97 | msleep(1); |
91 | 98 | ||
92 | intr = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR); | 99 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &intr); |
100 | if (ret < 0) | ||
101 | goto fail; | ||
93 | } | 102 | } |
94 | 103 | ||
95 | /* read back the status code of the command */ | 104 | /* read back the status code of the command */ |
96 | if (res_len == 0) | 105 | if (res_len == 0) |
97 | res_len = sizeof(struct wl1271_cmd_header); | 106 | res_len = sizeof(struct wl1271_cmd_header); |
98 | wl1271_read(wl, wl->cmd_box_addr, cmd, res_len, false); | 107 | |
108 | ret = wlcore_read(wl, wl->cmd_box_addr, cmd, res_len, false); | ||
109 | if (ret < 0) | ||
110 | goto fail; | ||
99 | 111 | ||
100 | status = le16_to_cpu(cmd->status); | 112 | status = le16_to_cpu(cmd->status); |
101 | if (status != CMD_STATUS_SUCCESS) { | 113 | if (status != CMD_STATUS_SUCCESS) { |
@@ -104,11 +116,14 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
104 | goto fail; | 116 | goto fail; |
105 | } | 117 | } |
106 | 118 | ||
107 | wlcore_write_reg(wl, REG_INTERRUPT_ACK, WL1271_ACX_INTR_CMD_COMPLETE); | 119 | ret = wlcore_write_reg(wl, REG_INTERRUPT_ACK, |
120 | WL1271_ACX_INTR_CMD_COMPLETE); | ||
121 | if (ret < 0) | ||
122 | goto fail; | ||
123 | |||
108 | return 0; | 124 | return 0; |
109 | 125 | ||
110 | fail: | 126 | fail: |
111 | WARN_ON(1); | ||
112 | wl12xx_queue_recovery_work(wl); | 127 | wl12xx_queue_recovery_work(wl); |
113 | return ret; | 128 | return ret; |
114 | } | 129 | } |
@@ -117,35 +132,45 @@ fail: | |||
117 | * Poll the mailbox event field until any of the bits in the mask is set or a | 132 | * Poll the mailbox event field until any of the bits in the mask is set or a |
118 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) | 133 | * timeout occurs (WL1271_EVENT_TIMEOUT in msecs) |
119 | */ | 134 | */ |
120 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | 135 | static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, |
136 | u32 mask, bool *timeout) | ||
121 | { | 137 | { |
122 | u32 *events_vector; | 138 | u32 *events_vector; |
123 | u32 event; | 139 | u32 event; |
124 | unsigned long timeout; | 140 | unsigned long timeout_time; |
125 | int ret = 0; | 141 | int ret = 0; |
126 | 142 | ||
143 | *timeout = false; | ||
144 | |||
127 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); | 145 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); |
128 | if (!events_vector) | 146 | if (!events_vector) |
129 | return -ENOMEM; | 147 | return -ENOMEM; |
130 | 148 | ||
131 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 149 | timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
132 | 150 | ||
133 | do { | 151 | do { |
134 | if (time_after(jiffies, timeout)) { | 152 | if (time_after(jiffies, timeout_time)) { |
135 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", | 153 | wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", |
136 | (int)mask); | 154 | (int)mask); |
137 | ret = -ETIMEDOUT; | 155 | *timeout = true; |
138 | goto out; | 156 | goto out; |
139 | } | 157 | } |
140 | 158 | ||
141 | msleep(1); | 159 | msleep(1); |
142 | 160 | ||
143 | /* read from both event fields */ | 161 | /* read from both event fields */ |
144 | wl1271_read(wl, wl->mbox_ptr[0], events_vector, | 162 | ret = wlcore_read(wl, wl->mbox_ptr[0], events_vector, |
145 | sizeof(*events_vector), false); | 163 | sizeof(*events_vector), false); |
164 | if (ret < 0) | ||
165 | goto out; | ||
166 | |||
146 | event = *events_vector & mask; | 167 | event = *events_vector & mask; |
147 | wl1271_read(wl, wl->mbox_ptr[1], events_vector, | 168 | |
148 | sizeof(*events_vector), false); | 169 | ret = wlcore_read(wl, wl->mbox_ptr[1], events_vector, |
170 | sizeof(*events_vector), false); | ||
171 | if (ret < 0) | ||
172 | goto out; | ||
173 | |||
149 | event |= *events_vector & mask; | 174 | event |= *events_vector & mask; |
150 | } while (!event); | 175 | } while (!event); |
151 | 176 | ||
@@ -157,9 +182,10 @@ out: | |||
157 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) | 182 | static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask) |
158 | { | 183 | { |
159 | int ret; | 184 | int ret; |
185 | bool timeout = false; | ||
160 | 186 | ||
161 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask); | 187 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask, &timeout); |
162 | if (ret != 0) { | 188 | if (ret != 0 || timeout) { |
163 | wl12xx_queue_recovery_work(wl); | 189 | wl12xx_queue_recovery_work(wl); |
164 | return ret; | 190 | return ret; |
165 | } | 191 | } |
@@ -1412,6 +1438,7 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
1412 | { | 1438 | { |
1413 | struct wl12xx_cmd_remove_peer *cmd; | 1439 | struct wl12xx_cmd_remove_peer *cmd; |
1414 | int ret; | 1440 | int ret; |
1441 | bool timeout = false; | ||
1415 | 1442 | ||
1416 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); | 1443 | wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid); |
1417 | 1444 | ||
@@ -1432,12 +1459,16 @@ int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid) | |||
1432 | goto out_free; | 1459 | goto out_free; |
1433 | } | 1460 | } |
1434 | 1461 | ||
1462 | ret = wl1271_cmd_wait_for_event_or_timeout(wl, | ||
1463 | PEER_REMOVE_COMPLETE_EVENT_ID, | ||
1464 | &timeout); | ||
1435 | /* | 1465 | /* |
1436 | * We are ok with a timeout here. The event is sometimes not sent | 1466 | * We are ok with a timeout here. The event is sometimes not sent |
1437 | * due to a firmware bug. | 1467 | * due to a firmware bug. In case of another error (like SDIO timeout) |
1468 | * queue a recovery. | ||
1438 | */ | 1469 | */ |
1439 | wl1271_cmd_wait_for_event_or_timeout(wl, | 1470 | if (ret) |
1440 | PEER_REMOVE_COMPLETE_EVENT_ID); | 1471 | wl12xx_queue_recovery_work(wl); |
1441 | 1472 | ||
1442 | out_free: | 1473 | out_free: |
1443 | kfree(cmd); | 1474 | kfree(cmd); |
@@ -1754,7 +1785,9 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1754 | return -EINVAL; | 1785 | return -EINVAL; |
1755 | 1786 | ||
1756 | /* flush all pending packets */ | 1787 | /* flush all pending packets */ |
1757 | wl1271_tx_work_locked(wl); | 1788 | ret = wlcore_tx_work_locked(wl); |
1789 | if (ret < 0) | ||
1790 | goto out; | ||
1758 | 1791 | ||
1759 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { | 1792 | if (test_bit(wlvif->dev_role_id, wl->roc_map)) { |
1760 | ret = wl12xx_croc(wl, wlvif->dev_role_id); | 1793 | ret = wl12xx_croc(wl, wlvif->dev_role_id); |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 85171f2bf68e..c8a6510c72cb 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -652,4 +652,25 @@ struct wl12xx_cmd_stop_channel_switch { | |||
652 | struct wl1271_cmd_header header; | 652 | struct wl1271_cmd_header header; |
653 | } __packed; | 653 | } __packed; |
654 | 654 | ||
655 | /* Used to check radio status after calibration */ | ||
656 | #define MAX_TLV_LENGTH 500 | ||
657 | #define TEST_CMD_P2G_CAL 2 /* TX BiP */ | ||
658 | |||
659 | struct wl1271_cmd_cal_p2g { | ||
660 | struct wl1271_cmd_header header; | ||
661 | |||
662 | struct wl1271_cmd_test_header test; | ||
663 | |||
664 | __le32 ver; | ||
665 | __le16 len; | ||
666 | u8 buf[MAX_TLV_LENGTH]; | ||
667 | u8 type; | ||
668 | u8 padding; | ||
669 | |||
670 | __le16 radio_status; | ||
671 | |||
672 | u8 sub_band_mask; | ||
673 | u8 padding2; | ||
674 | } __packed; | ||
675 | |||
655 | #endif /* __WL1271_CMD_H__ */ | 676 | #endif /* __WL1271_CMD_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index 03c635872335..d77224f2ac6b 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h | |||
@@ -951,6 +951,12 @@ struct conf_conn_settings { | |||
951 | * Range: u16 | 951 | * Range: u16 |
952 | */ | 952 | */ |
953 | u8 max_listen_interval; | 953 | u8 max_listen_interval; |
954 | |||
955 | /* | ||
956 | * Default sleep authorization for a new STA interface. This determines | ||
957 | * whether we can go to ELP. | ||
958 | */ | ||
959 | u8 sta_sleep_auth; | ||
954 | } __packed; | 960 | } __packed; |
955 | 961 | ||
956 | enum { | 962 | enum { |
@@ -1276,7 +1282,7 @@ struct conf_hangover_settings { | |||
1276 | * version, the two LSB are the lower driver's private conf | 1282 | * version, the two LSB are the lower driver's private conf |
1277 | * version. | 1283 | * version. |
1278 | */ | 1284 | */ |
1279 | #define WLCORE_CONF_VERSION (0x0001 << 16) | 1285 | #define WLCORE_CONF_VERSION (0x0002 << 16) |
1280 | #define WLCORE_CONF_MASK 0xffff0000 | 1286 | #define WLCORE_CONF_MASK 0xffff0000 |
1281 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ | 1287 | #define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \ |
1282 | sizeof(struct wlcore_conf)) | 1288 | sizeof(struct wlcore_conf)) |
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 689a847005c9..80dbc5304fac 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c | |||
@@ -38,6 +38,8 @@ | |||
38 | /* ms */ | 38 | /* ms */ |
39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 | 39 | #define WL1271_DEBUGFS_STATS_LIFETIME 1000 |
40 | 40 | ||
41 | #define WLCORE_MAX_BLOCK_SIZE ((size_t)(4*PAGE_SIZE)) | ||
42 | |||
41 | /* debugfs macros idea from mac80211 */ | 43 | /* debugfs macros idea from mac80211 */ |
42 | int wl1271_format_buffer(char __user *userbuf, size_t count, | 44 | int wl1271_format_buffer(char __user *userbuf, size_t count, |
43 | loff_t *ppos, char *fmt, ...) | 45 | loff_t *ppos, char *fmt, ...) |
@@ -963,6 +965,257 @@ static const struct file_operations fw_stats_raw_ops = { | |||
963 | .llseek = default_llseek, | 965 | .llseek = default_llseek, |
964 | }; | 966 | }; |
965 | 967 | ||
968 | static ssize_t sleep_auth_read(struct file *file, char __user *user_buf, | ||
969 | size_t count, loff_t *ppos) | ||
970 | { | ||
971 | struct wl1271 *wl = file->private_data; | ||
972 | |||
973 | return wl1271_format_buffer(user_buf, count, | ||
974 | ppos, "%d\n", | ||
975 | wl->sleep_auth); | ||
976 | } | ||
977 | |||
978 | static ssize_t sleep_auth_write(struct file *file, | ||
979 | const char __user *user_buf, | ||
980 | size_t count, loff_t *ppos) | ||
981 | { | ||
982 | struct wl1271 *wl = file->private_data; | ||
983 | unsigned long value; | ||
984 | int ret; | ||
985 | |||
986 | ret = kstrtoul_from_user(user_buf, count, 0, &value); | ||
987 | if (ret < 0) { | ||
988 | wl1271_warning("illegal value in sleep_auth"); | ||
989 | return -EINVAL; | ||
990 | } | ||
991 | |||
992 | if (value < 0 || value > WL1271_PSM_MAX) { | ||
993 | wl1271_warning("sleep_auth must be between 0 and %d", | ||
994 | WL1271_PSM_MAX); | ||
995 | return -ERANGE; | ||
996 | } | ||
997 | |||
998 | mutex_lock(&wl->mutex); | ||
999 | |||
1000 | wl->conf.conn.sta_sleep_auth = value; | ||
1001 | |||
1002 | if (wl->state == WL1271_STATE_OFF) { | ||
1003 | /* this will show up on "read" in case we are off */ | ||
1004 | wl->sleep_auth = value; | ||
1005 | goto out; | ||
1006 | } | ||
1007 | |||
1008 | ret = wl1271_ps_elp_wakeup(wl); | ||
1009 | if (ret < 0) | ||
1010 | goto out; | ||
1011 | |||
1012 | ret = wl1271_acx_sleep_auth(wl, value); | ||
1013 | if (ret < 0) | ||
1014 | goto out_sleep; | ||
1015 | |||
1016 | out_sleep: | ||
1017 | wl1271_ps_elp_sleep(wl); | ||
1018 | out: | ||
1019 | mutex_unlock(&wl->mutex); | ||
1020 | return count; | ||
1021 | } | ||
1022 | |||
1023 | static const struct file_operations sleep_auth_ops = { | ||
1024 | .read = sleep_auth_read, | ||
1025 | .write = sleep_auth_write, | ||
1026 | .open = simple_open, | ||
1027 | .llseek = default_llseek, | ||
1028 | }; | ||
1029 | |||
1030 | static ssize_t dev_mem_read(struct file *file, | ||
1031 | char __user *user_buf, size_t count, | ||
1032 | loff_t *ppos) | ||
1033 | { | ||
1034 | struct wl1271 *wl = file->private_data; | ||
1035 | struct wlcore_partition_set part, old_part; | ||
1036 | size_t bytes = count; | ||
1037 | int ret; | ||
1038 | char *buf; | ||
1039 | |||
1040 | /* only requests of dword-aligned size and offset are supported */ | ||
1041 | if (bytes % 4) | ||
1042 | return -EINVAL; | ||
1043 | |||
1044 | if (*ppos % 4) | ||
1045 | return -EINVAL; | ||
1046 | |||
1047 | /* function should return in reasonable time */ | ||
1048 | bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); | ||
1049 | |||
1050 | if (bytes == 0) | ||
1051 | return -EINVAL; | ||
1052 | |||
1053 | memset(&part, 0, sizeof(part)); | ||
1054 | part.mem.start = file->f_pos; | ||
1055 | part.mem.size = bytes; | ||
1056 | |||
1057 | buf = kmalloc(bytes, GFP_KERNEL); | ||
1058 | if (!buf) | ||
1059 | return -ENOMEM; | ||
1060 | |||
1061 | mutex_lock(&wl->mutex); | ||
1062 | |||
1063 | if (wl->state == WL1271_STATE_OFF) { | ||
1064 | ret = -EFAULT; | ||
1065 | goto skip_read; | ||
1066 | } | ||
1067 | |||
1068 | ret = wl1271_ps_elp_wakeup(wl); | ||
1069 | if (ret < 0) | ||
1070 | goto skip_read; | ||
1071 | |||
1072 | /* store current partition and switch partition */ | ||
1073 | memcpy(&old_part, &wl->curr_part, sizeof(old_part)); | ||
1074 | ret = wlcore_set_partition(wl, &part); | ||
1075 | if (ret < 0) | ||
1076 | goto part_err; | ||
1077 | |||
1078 | ret = wlcore_raw_read(wl, 0, buf, bytes, false); | ||
1079 | if (ret < 0) | ||
1080 | goto read_err; | ||
1081 | |||
1082 | read_err: | ||
1083 | /* recover partition */ | ||
1084 | ret = wlcore_set_partition(wl, &old_part); | ||
1085 | if (ret < 0) | ||
1086 | goto part_err; | ||
1087 | |||
1088 | part_err: | ||
1089 | wl1271_ps_elp_sleep(wl); | ||
1090 | |||
1091 | skip_read: | ||
1092 | mutex_unlock(&wl->mutex); | ||
1093 | |||
1094 | if (ret == 0) { | ||
1095 | ret = copy_to_user(user_buf, buf, bytes); | ||
1096 | if (ret < bytes) { | ||
1097 | bytes -= ret; | ||
1098 | *ppos += bytes; | ||
1099 | ret = 0; | ||
1100 | } else { | ||
1101 | ret = -EFAULT; | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | kfree(buf); | ||
1106 | |||
1107 | return ((ret == 0) ? bytes : ret); | ||
1108 | } | ||
1109 | |||
1110 | static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, | ||
1111 | size_t count, loff_t *ppos) | ||
1112 | { | ||
1113 | struct wl1271 *wl = file->private_data; | ||
1114 | struct wlcore_partition_set part, old_part; | ||
1115 | size_t bytes = count; | ||
1116 | int ret; | ||
1117 | char *buf; | ||
1118 | |||
1119 | /* only requests of dword-aligned size and offset are supported */ | ||
1120 | if (bytes % 4) | ||
1121 | return -EINVAL; | ||
1122 | |||
1123 | if (*ppos % 4) | ||
1124 | return -EINVAL; | ||
1125 | |||
1126 | /* function should return in reasonable time */ | ||
1127 | bytes = min(bytes, WLCORE_MAX_BLOCK_SIZE); | ||
1128 | |||
1129 | if (bytes == 0) | ||
1130 | return -EINVAL; | ||
1131 | |||
1132 | memset(&part, 0, sizeof(part)); | ||
1133 | part.mem.start = file->f_pos; | ||
1134 | part.mem.size = bytes; | ||
1135 | |||
1136 | buf = kmalloc(bytes, GFP_KERNEL); | ||
1137 | if (!buf) | ||
1138 | return -ENOMEM; | ||
1139 | |||
1140 | ret = copy_from_user(buf, user_buf, bytes); | ||
1141 | if (ret) { | ||
1142 | ret = -EFAULT; | ||
1143 | goto err_out; | ||
1144 | } | ||
1145 | |||
1146 | mutex_lock(&wl->mutex); | ||
1147 | |||
1148 | if (wl->state == WL1271_STATE_OFF) { | ||
1149 | ret = -EFAULT; | ||
1150 | goto skip_write; | ||
1151 | } | ||
1152 | |||
1153 | ret = wl1271_ps_elp_wakeup(wl); | ||
1154 | if (ret < 0) | ||
1155 | goto skip_write; | ||
1156 | |||
1157 | /* store current partition and switch partition */ | ||
1158 | memcpy(&old_part, &wl->curr_part, sizeof(old_part)); | ||
1159 | ret = wlcore_set_partition(wl, &part); | ||
1160 | if (ret < 0) | ||
1161 | goto part_err; | ||
1162 | |||
1163 | ret = wlcore_raw_write(wl, 0, buf, bytes, false); | ||
1164 | if (ret < 0) | ||
1165 | goto write_err; | ||
1166 | |||
1167 | write_err: | ||
1168 | /* recover partition */ | ||
1169 | ret = wlcore_set_partition(wl, &old_part); | ||
1170 | if (ret < 0) | ||
1171 | goto part_err; | ||
1172 | |||
1173 | part_err: | ||
1174 | wl1271_ps_elp_sleep(wl); | ||
1175 | |||
1176 | skip_write: | ||
1177 | mutex_unlock(&wl->mutex); | ||
1178 | |||
1179 | if (ret == 0) | ||
1180 | *ppos += bytes; | ||
1181 | |||
1182 | err_out: | ||
1183 | kfree(buf); | ||
1184 | |||
1185 | return ((ret == 0) ? bytes : ret); | ||
1186 | } | ||
1187 | |||
1188 | static loff_t dev_mem_seek(struct file *file, loff_t offset, int orig) | ||
1189 | { | ||
1190 | loff_t ret; | ||
1191 | |||
1192 | /* only requests of dword-aligned size and offset are supported */ | ||
1193 | if (offset % 4) | ||
1194 | return -EINVAL; | ||
1195 | |||
1196 | switch (orig) { | ||
1197 | case SEEK_SET: | ||
1198 | file->f_pos = offset; | ||
1199 | ret = file->f_pos; | ||
1200 | break; | ||
1201 | case SEEK_CUR: | ||
1202 | file->f_pos += offset; | ||
1203 | ret = file->f_pos; | ||
1204 | break; | ||
1205 | default: | ||
1206 | ret = -EINVAL; | ||
1207 | } | ||
1208 | |||
1209 | return ret; | ||
1210 | } | ||
1211 | |||
1212 | static const struct file_operations dev_mem_ops = { | ||
1213 | .open = simple_open, | ||
1214 | .read = dev_mem_read, | ||
1215 | .write = dev_mem_write, | ||
1216 | .llseek = dev_mem_seek, | ||
1217 | }; | ||
1218 | |||
966 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 1219 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
967 | struct dentry *rootdir) | 1220 | struct dentry *rootdir) |
968 | { | 1221 | { |
@@ -988,6 +1241,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
988 | DEBUGFS_ADD(irq_blk_threshold, rootdir); | 1241 | DEBUGFS_ADD(irq_blk_threshold, rootdir); |
989 | DEBUGFS_ADD(irq_timeout, rootdir); | 1242 | DEBUGFS_ADD(irq_timeout, rootdir); |
990 | DEBUGFS_ADD(fw_stats_raw, rootdir); | 1243 | DEBUGFS_ADD(fw_stats_raw, rootdir); |
1244 | DEBUGFS_ADD(sleep_auth, rootdir); | ||
991 | 1245 | ||
992 | streaming = debugfs_create_dir("rx_streaming", rootdir); | 1246 | streaming = debugfs_create_dir("rx_streaming", rootdir); |
993 | if (!streaming || IS_ERR(streaming)) | 1247 | if (!streaming || IS_ERR(streaming)) |
@@ -996,6 +1250,7 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
996 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); | 1250 | DEBUGFS_ADD_PREFIX(rx_streaming, interval, streaming); |
997 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); | 1251 | DEBUGFS_ADD_PREFIX(rx_streaming, always, streaming); |
998 | 1252 | ||
1253 | DEBUGFS_ADD_PREFIX(dev, mem, rootdir); | ||
999 | 1254 | ||
1000 | return 0; | 1255 | return 0; |
1001 | 1256 | ||
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index c976f0409865..48907054d493 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -105,6 +105,7 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
105 | u32 vector; | 105 | u32 vector; |
106 | bool disconnect_sta = false; | 106 | bool disconnect_sta = false; |
107 | unsigned long sta_bitmap = 0; | 107 | unsigned long sta_bitmap = 0; |
108 | int ret; | ||
108 | 109 | ||
109 | wl1271_event_mbox_dump(mbox); | 110 | wl1271_event_mbox_dump(mbox); |
110 | 111 | ||
@@ -228,7 +229,9 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
228 | 229 | ||
229 | if ((vector & DUMMY_PACKET_EVENT_ID)) { | 230 | if ((vector & DUMMY_PACKET_EVENT_ID)) { |
230 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); | 231 | wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); |
231 | wl1271_tx_dummy_packet(wl); | 232 | ret = wl1271_tx_dummy_packet(wl); |
233 | if (ret < 0) | ||
234 | return ret; | ||
232 | } | 235 | } |
233 | 236 | ||
234 | /* | 237 | /* |
@@ -301,8 +304,10 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
301 | return -EINVAL; | 304 | return -EINVAL; |
302 | 305 | ||
303 | /* first we read the mbox descriptor */ | 306 | /* first we read the mbox descriptor */ |
304 | wl1271_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, | 307 | ret = wlcore_read(wl, wl->mbox_ptr[mbox_num], wl->mbox, |
305 | sizeof(*wl->mbox), false); | 308 | sizeof(*wl->mbox), false); |
309 | if (ret < 0) | ||
310 | return ret; | ||
306 | 311 | ||
307 | /* process the descriptor */ | 312 | /* process the descriptor */ |
308 | ret = wl1271_event_process(wl); | 313 | ret = wl1271_event_process(wl); |
@@ -313,7 +318,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) | |||
313 | * TODO: we just need this because one bit is in a different | 318 | * TODO: we just need this because one bit is in a different |
314 | * place. Is there any better way? | 319 | * place. Is there any better way? |
315 | */ | 320 | */ |
316 | wl->ops->ack_event(wl); | 321 | ret = wl->ops->ack_event(wl); |
317 | 322 | ||
318 | return 0; | 323 | return ret; |
319 | } | 324 | } |
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h index 9e7787ba9610..2673d783ec1e 100644 --- a/drivers/net/wireless/ti/wlcore/hw_ops.h +++ b/drivers/net/wireless/ti/wlcore/hw_ops.h | |||
@@ -65,11 +65,13 @@ wlcore_hw_get_rx_buf_align(struct wl1271 *wl, u32 rx_desc) | |||
65 | return wl->ops->get_rx_buf_align(wl, rx_desc); | 65 | return wl->ops->get_rx_buf_align(wl, rx_desc); |
66 | } | 66 | } |
67 | 67 | ||
68 | static inline void | 68 | static inline int |
69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) | 69 | wlcore_hw_prepare_read(struct wl1271 *wl, u32 rx_desc, u32 len) |
70 | { | 70 | { |
71 | if (wl->ops->prepare_read) | 71 | if (wl->ops->prepare_read) |
72 | wl->ops->prepare_read(wl, rx_desc, len); | 72 | return wl->ops->prepare_read(wl, rx_desc, len); |
73 | |||
74 | return 0; | ||
73 | } | 75 | } |
74 | 76 | ||
75 | static inline u32 | 77 | static inline u32 |
@@ -81,10 +83,12 @@ wlcore_hw_get_rx_packet_len(struct wl1271 *wl, void *rx_data, u32 data_len) | |||
81 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); | 83 | return wl->ops->get_rx_packet_len(wl, rx_data, data_len); |
82 | } | 84 | } |
83 | 85 | ||
84 | static inline void wlcore_hw_tx_delayed_compl(struct wl1271 *wl) | 86 | static inline int wlcore_hw_tx_delayed_compl(struct wl1271 *wl) |
85 | { | 87 | { |
86 | if (wl->ops->tx_delayed_compl) | 88 | if (wl->ops->tx_delayed_compl) |
87 | wl->ops->tx_delayed_compl(wl); | 89 | return wl->ops->tx_delayed_compl(wl); |
90 | |||
91 | return 0; | ||
88 | } | 92 | } |
89 | 93 | ||
90 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) | 94 | static inline void wlcore_hw_tx_immediate_compl(struct wl1271 *wl) |
diff --git a/drivers/net/wireless/ti/wlcore/ini.h b/drivers/net/wireless/ti/wlcore/ini.h index 4cf9ecc56212..d24fe3bbc672 100644 --- a/drivers/net/wireless/ti/wlcore/ini.h +++ b/drivers/net/wireless/ti/wlcore/ini.h | |||
@@ -172,7 +172,19 @@ struct wl128x_ini_fem_params_5 { | |||
172 | 172 | ||
173 | /* NVS data structure */ | 173 | /* NVS data structure */ |
174 | #define WL1271_INI_NVS_SECTION_SIZE 468 | 174 | #define WL1271_INI_NVS_SECTION_SIZE 468 |
175 | #define WL1271_INI_FEM_MODULE_COUNT 2 | 175 | |
176 | /* We have four FEM module types: 0-RFMD, 1-TQS, 2-SKW, 3-TQS_HP */ | ||
177 | #define WL1271_INI_FEM_MODULE_COUNT 4 | ||
178 | |||
179 | /* | ||
180 | * In NVS we only store two FEM module entries - | ||
181 | * FEM modules 0,2,3 are stored in entry 0 | ||
182 | * FEM module 1 is stored in entry 1 | ||
183 | */ | ||
184 | #define WL12XX_NVS_FEM_MODULE_COUNT 2 | ||
185 | |||
186 | #define WL12XX_FEM_TO_NVS_ENTRY(ini_fem_module) \ | ||
187 | ((ini_fem_module) == 1 ? 1 : 0) | ||
176 | 188 | ||
177 | #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 | 189 | #define WL1271_INI_LEGACY_NVS_FILE_SIZE 800 |
178 | 190 | ||
@@ -188,13 +200,13 @@ struct wl1271_nvs_file { | |||
188 | struct { | 200 | struct { |
189 | struct wl1271_ini_fem_params_2 params; | 201 | struct wl1271_ini_fem_params_2 params; |
190 | u8 padding; | 202 | u8 padding; |
191 | } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; | 203 | } dyn_radio_params_2[WL12XX_NVS_FEM_MODULE_COUNT]; |
192 | struct wl1271_ini_band_params_5 stat_radio_params_5; | 204 | struct wl1271_ini_band_params_5 stat_radio_params_5; |
193 | u8 padding3; | 205 | u8 padding3; |
194 | struct { | 206 | struct { |
195 | struct wl1271_ini_fem_params_5 params; | 207 | struct wl1271_ini_fem_params_5 params; |
196 | u8 padding; | 208 | u8 padding; |
197 | } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; | 209 | } dyn_radio_params_5[WL12XX_NVS_FEM_MODULE_COUNT]; |
198 | } __packed; | 210 | } __packed; |
199 | 211 | ||
200 | struct wl128x_nvs_file { | 212 | struct wl128x_nvs_file { |
@@ -209,12 +221,12 @@ struct wl128x_nvs_file { | |||
209 | struct { | 221 | struct { |
210 | struct wl128x_ini_fem_params_2 params; | 222 | struct wl128x_ini_fem_params_2 params; |
211 | u8 padding; | 223 | u8 padding; |
212 | } dyn_radio_params_2[WL1271_INI_FEM_MODULE_COUNT]; | 224 | } dyn_radio_params_2[WL12XX_NVS_FEM_MODULE_COUNT]; |
213 | struct wl128x_ini_band_params_5 stat_radio_params_5; | 225 | struct wl128x_ini_band_params_5 stat_radio_params_5; |
214 | u8 padding3; | 226 | u8 padding3; |
215 | struct { | 227 | struct { |
216 | struct wl128x_ini_fem_params_5 params; | 228 | struct wl128x_ini_fem_params_5 params; |
217 | u8 padding; | 229 | u8 padding; |
218 | } dyn_radio_params_5[WL1271_INI_FEM_MODULE_COUNT]; | 230 | } dyn_radio_params_5[WL12XX_NVS_FEM_MODULE_COUNT]; |
219 | } __packed; | 231 | } __packed; |
220 | #endif | 232 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index 645abd4b660d..8a8a8971befa 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c | |||
@@ -554,29 +554,28 @@ int wl1271_init_vif_specific(struct wl1271 *wl, struct ieee80211_vif *vif) | |||
554 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | 554 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); |
555 | int ret, i; | 555 | int ret, i; |
556 | 556 | ||
557 | /* | 557 | /* consider all existing roles before configuring psm. */ |
558 | * consider all existing roles before configuring psm. | 558 | |
559 | * TODO: reconfigure on interface removal. | 559 | if (wl->ap_count == 0 && is_ap) { /* first AP */ |
560 | */ | 560 | /* Configure for power always on */ |
561 | if (!wl->ap_count) { | 561 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
562 | if (is_ap) { | 562 | if (ret < 0) |
563 | /* Configure for power always on */ | 563 | return ret; |
564 | /* first STA, no APs */ | ||
565 | } else if (wl->sta_count == 0 && wl->ap_count == 0 && !is_ap) { | ||
566 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | ||
567 | /* Configure for power according to debugfs */ | ||
568 | if (sta_auth != WL1271_PSM_ILLEGAL) | ||
569 | ret = wl1271_acx_sleep_auth(wl, sta_auth); | ||
570 | /* Configure for power always on */ | ||
571 | else if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
564 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 572 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); |
565 | if (ret < 0) | 573 | /* Configure for ELP power saving */ |
566 | return ret; | 574 | else |
567 | } else if (!wl->sta_count) { | 575 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); |
568 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) { | 576 | |
569 | /* Configure for power always on */ | 577 | if (ret < 0) |
570 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 578 | return ret; |
571 | if (ret < 0) | ||
572 | return ret; | ||
573 | } else { | ||
574 | /* Configure for ELP power saving */ | ||
575 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
576 | if (ret < 0) | ||
577 | return ret; | ||
578 | } | ||
579 | } | ||
580 | } | 579 | } |
581 | 580 | ||
582 | /* Mode specific init */ | 581 | /* Mode specific init */ |
diff --git a/drivers/net/wireless/ti/wlcore/io.c b/drivers/net/wireless/ti/wlcore/io.c index 7cd0081aede5..9976219c4e49 100644 --- a/drivers/net/wireless/ti/wlcore/io.c +++ b/drivers/net/wireless/ti/wlcore/io.c | |||
@@ -48,6 +48,12 @@ void wlcore_disable_interrupts(struct wl1271 *wl) | |||
48 | } | 48 | } |
49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); | 49 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts); |
50 | 50 | ||
51 | void wlcore_disable_interrupts_nosync(struct wl1271 *wl) | ||
52 | { | ||
53 | disable_irq_nosync(wl->irq); | ||
54 | } | ||
55 | EXPORT_SYMBOL_GPL(wlcore_disable_interrupts_nosync); | ||
56 | |||
51 | void wlcore_enable_interrupts(struct wl1271 *wl) | 57 | void wlcore_enable_interrupts(struct wl1271 *wl) |
52 | { | 58 | { |
53 | enable_irq(wl->irq); | 59 | enable_irq(wl->irq); |
@@ -122,9 +128,11 @@ EXPORT_SYMBOL_GPL(wlcore_translate_addr); | |||
122 | * | | | 128 | * | | |
123 | * | 129 | * |
124 | */ | 130 | */ |
125 | void wlcore_set_partition(struct wl1271 *wl, | 131 | int wlcore_set_partition(struct wl1271 *wl, |
126 | const struct wlcore_partition_set *p) | 132 | const struct wlcore_partition_set *p) |
127 | { | 133 | { |
134 | int ret; | ||
135 | |||
128 | /* copy partition info */ | 136 | /* copy partition info */ |
129 | memcpy(&wl->curr_part, p, sizeof(*p)); | 137 | memcpy(&wl->curr_part, p, sizeof(*p)); |
130 | 138 | ||
@@ -137,28 +145,41 @@ void wlcore_set_partition(struct wl1271 *wl, | |||
137 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", | 145 | wl1271_debug(DEBUG_IO, "mem3_start %08X mem3_size %08X", |
138 | p->mem3.start, p->mem3.size); | 146 | p->mem3.start, p->mem3.size); |
139 | 147 | ||
140 | wl1271_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); | 148 | ret = wlcore_raw_write32(wl, HW_PART0_START_ADDR, p->mem.start); |
141 | wl1271_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); | 149 | if (ret < 0) |
142 | wl1271_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | 150 | goto out; |
143 | wl1271_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | 151 | |
144 | wl1271_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | 152 | ret = wlcore_raw_write32(wl, HW_PART0_SIZE_ADDR, p->mem.size); |
145 | wl1271_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | 153 | if (ret < 0) |
154 | goto out; | ||
155 | |||
156 | ret = wlcore_raw_write32(wl, HW_PART1_START_ADDR, p->reg.start); | ||
157 | if (ret < 0) | ||
158 | goto out; | ||
159 | |||
160 | ret = wlcore_raw_write32(wl, HW_PART1_SIZE_ADDR, p->reg.size); | ||
161 | if (ret < 0) | ||
162 | goto out; | ||
163 | |||
164 | ret = wlcore_raw_write32(wl, HW_PART2_START_ADDR, p->mem2.start); | ||
165 | if (ret < 0) | ||
166 | goto out; | ||
167 | |||
168 | ret = wlcore_raw_write32(wl, HW_PART2_SIZE_ADDR, p->mem2.size); | ||
169 | if (ret < 0) | ||
170 | goto out; | ||
171 | |||
146 | /* | 172 | /* |
147 | * We don't need the size of the last partition, as it is | 173 | * We don't need the size of the last partition, as it is |
148 | * automatically calculated based on the total memory size and | 174 | * automatically calculated based on the total memory size and |
149 | * the sizes of the previous partitions. | 175 | * the sizes of the previous partitions. |
150 | */ | 176 | */ |
151 | wl1271_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); | 177 | ret = wlcore_raw_write32(wl, HW_PART3_START_ADDR, p->mem3.start); |
152 | } | ||
153 | EXPORT_SYMBOL_GPL(wlcore_set_partition); | ||
154 | 178 | ||
155 | void wlcore_select_partition(struct wl1271 *wl, u8 part) | 179 | out: |
156 | { | 180 | return ret; |
157 | wl1271_debug(DEBUG_IO, "setting partition %d", part); | ||
158 | |||
159 | wlcore_set_partition(wl, &wl->ptable[part]); | ||
160 | } | 181 | } |
161 | EXPORT_SYMBOL_GPL(wlcore_select_partition); | 182 | EXPORT_SYMBOL_GPL(wlcore_set_partition); |
162 | 183 | ||
163 | void wl1271_io_reset(struct wl1271 *wl) | 184 | void wl1271_io_reset(struct wl1271 *wl) |
164 | { | 185 | { |
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index 8942954b56a0..fef80adc8bf5 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h | |||
@@ -45,6 +45,7 @@ | |||
45 | struct wl1271; | 45 | struct wl1271; |
46 | 46 | ||
47 | void wlcore_disable_interrupts(struct wl1271 *wl); | 47 | void wlcore_disable_interrupts(struct wl1271 *wl); |
48 | void wlcore_disable_interrupts_nosync(struct wl1271 *wl); | ||
48 | void wlcore_enable_interrupts(struct wl1271 *wl); | 49 | void wlcore_enable_interrupts(struct wl1271 *wl); |
49 | 50 | ||
50 | void wl1271_io_reset(struct wl1271 *wl); | 51 | void wl1271_io_reset(struct wl1271 *wl); |
@@ -52,79 +53,113 @@ void wl1271_io_init(struct wl1271 *wl); | |||
52 | int wlcore_translate_addr(struct wl1271 *wl, int addr); | 53 | int wlcore_translate_addr(struct wl1271 *wl, int addr); |
53 | 54 | ||
54 | /* Raw target IO, address is not translated */ | 55 | /* Raw target IO, address is not translated */ |
55 | static inline void wl1271_raw_write(struct wl1271 *wl, int addr, void *buf, | 56 | static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr, |
56 | size_t len, bool fixed) | 57 | void *buf, size_t len, |
58 | bool fixed) | ||
57 | { | 59 | { |
58 | wl->if_ops->write(wl->dev, addr, buf, len, fixed); | 60 | int ret; |
61 | |||
62 | if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) | ||
63 | return -EIO; | ||
64 | |||
65 | ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); | ||
66 | if (ret) | ||
67 | set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); | ||
68 | |||
69 | return ret; | ||
59 | } | 70 | } |
60 | 71 | ||
61 | static inline void wl1271_raw_read(struct wl1271 *wl, int addr, void *buf, | 72 | static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, |
62 | size_t len, bool fixed) | 73 | void *buf, size_t len, |
74 | bool fixed) | ||
63 | { | 75 | { |
64 | wl->if_ops->read(wl->dev, addr, buf, len, fixed); | 76 | int ret; |
77 | |||
78 | if (test_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags)) | ||
79 | return -EIO; | ||
80 | |||
81 | ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); | ||
82 | if (ret) | ||
83 | set_bit(WL1271_FLAG_SDIO_FAILED, &wl->flags); | ||
84 | |||
85 | return ret; | ||
65 | } | 86 | } |
66 | 87 | ||
67 | static inline void wlcore_raw_read_data(struct wl1271 *wl, int reg, void *buf, | 88 | static inline int __must_check wlcore_raw_read_data(struct wl1271 *wl, int reg, |
68 | size_t len, bool fixed) | 89 | void *buf, size_t len, |
90 | bool fixed) | ||
69 | { | 91 | { |
70 | wl1271_raw_read(wl, wl->rtable[reg], buf, len, fixed); | 92 | return wlcore_raw_read(wl, wl->rtable[reg], buf, len, fixed); |
71 | } | 93 | } |
72 | 94 | ||
73 | static inline void wlcore_raw_write_data(struct wl1271 *wl, int reg, void *buf, | 95 | static inline int __must_check wlcore_raw_write_data(struct wl1271 *wl, int reg, |
74 | size_t len, bool fixed) | 96 | void *buf, size_t len, |
97 | bool fixed) | ||
75 | { | 98 | { |
76 | wl1271_raw_write(wl, wl->rtable[reg], buf, len, fixed); | 99 | return wlcore_raw_write(wl, wl->rtable[reg], buf, len, fixed); |
77 | } | 100 | } |
78 | 101 | ||
79 | static inline u32 wl1271_raw_read32(struct wl1271 *wl, int addr) | 102 | static inline int __must_check wlcore_raw_read32(struct wl1271 *wl, int addr, |
103 | u32 *val) | ||
80 | { | 104 | { |
81 | wl1271_raw_read(wl, addr, &wl->buffer_32, | 105 | int ret; |
82 | sizeof(wl->buffer_32), false); | 106 | |
107 | ret = wlcore_raw_read(wl, addr, &wl->buffer_32, | ||
108 | sizeof(wl->buffer_32), false); | ||
109 | if (ret < 0) | ||
110 | return ret; | ||
111 | |||
112 | if (val) | ||
113 | *val = le32_to_cpu(wl->buffer_32); | ||
83 | 114 | ||
84 | return le32_to_cpu(wl->buffer_32); | 115 | return 0; |
85 | } | 116 | } |
86 | 117 | ||
87 | static inline void wl1271_raw_write32(struct wl1271 *wl, int addr, u32 val) | 118 | static inline int __must_check wlcore_raw_write32(struct wl1271 *wl, int addr, |
119 | u32 val) | ||
88 | { | 120 | { |
89 | wl->buffer_32 = cpu_to_le32(val); | 121 | wl->buffer_32 = cpu_to_le32(val); |
90 | wl1271_raw_write(wl, addr, &wl->buffer_32, | 122 | return wlcore_raw_write(wl, addr, &wl->buffer_32, |
91 | sizeof(wl->buffer_32), false); | 123 | sizeof(wl->buffer_32), false); |
92 | } | 124 | } |
93 | 125 | ||
94 | static inline void wl1271_read(struct wl1271 *wl, int addr, void *buf, | 126 | static inline int __must_check wlcore_read(struct wl1271 *wl, int addr, |
95 | size_t len, bool fixed) | 127 | void *buf, size_t len, bool fixed) |
96 | { | 128 | { |
97 | int physical; | 129 | int physical; |
98 | 130 | ||
99 | physical = wlcore_translate_addr(wl, addr); | 131 | physical = wlcore_translate_addr(wl, addr); |
100 | 132 | ||
101 | wl1271_raw_read(wl, physical, buf, len, fixed); | 133 | return wlcore_raw_read(wl, physical, buf, len, fixed); |
102 | } | 134 | } |
103 | 135 | ||
104 | static inline void wl1271_write(struct wl1271 *wl, int addr, void *buf, | 136 | static inline int __must_check wlcore_write(struct wl1271 *wl, int addr, |
105 | size_t len, bool fixed) | 137 | void *buf, size_t len, bool fixed) |
106 | { | 138 | { |
107 | int physical; | 139 | int physical; |
108 | 140 | ||
109 | physical = wlcore_translate_addr(wl, addr); | 141 | physical = wlcore_translate_addr(wl, addr); |
110 | 142 | ||
111 | wl1271_raw_write(wl, physical, buf, len, fixed); | 143 | return wlcore_raw_write(wl, physical, buf, len, fixed); |
112 | } | 144 | } |
113 | 145 | ||
114 | static inline void wlcore_write_data(struct wl1271 *wl, int reg, void *buf, | 146 | static inline int __must_check wlcore_write_data(struct wl1271 *wl, int reg, |
115 | size_t len, bool fixed) | 147 | void *buf, size_t len, |
148 | bool fixed) | ||
116 | { | 149 | { |
117 | wl1271_write(wl, wl->rtable[reg], buf, len, fixed); | 150 | return wlcore_write(wl, wl->rtable[reg], buf, len, fixed); |
118 | } | 151 | } |
119 | 152 | ||
120 | static inline void wlcore_read_data(struct wl1271 *wl, int reg, void *buf, | 153 | static inline int __must_check wlcore_read_data(struct wl1271 *wl, int reg, |
121 | size_t len, bool fixed) | 154 | void *buf, size_t len, |
155 | bool fixed) | ||
122 | { | 156 | { |
123 | wl1271_read(wl, wl->rtable[reg], buf, len, fixed); | 157 | return wlcore_read(wl, wl->rtable[reg], buf, len, fixed); |
124 | } | 158 | } |
125 | 159 | ||
126 | static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | 160 | static inline int __must_check wlcore_read_hwaddr(struct wl1271 *wl, int hwaddr, |
127 | void *buf, size_t len, bool fixed) | 161 | void *buf, size_t len, |
162 | bool fixed) | ||
128 | { | 163 | { |
129 | int physical; | 164 | int physical; |
130 | int addr; | 165 | int addr; |
@@ -134,34 +169,47 @@ static inline void wl1271_read_hwaddr(struct wl1271 *wl, int hwaddr, | |||
134 | 169 | ||
135 | physical = wlcore_translate_addr(wl, addr); | 170 | physical = wlcore_translate_addr(wl, addr); |
136 | 171 | ||
137 | wl1271_raw_read(wl, physical, buf, len, fixed); | 172 | return wlcore_raw_read(wl, physical, buf, len, fixed); |
138 | } | 173 | } |
139 | 174 | ||
140 | static inline u32 wl1271_read32(struct wl1271 *wl, int addr) | 175 | static inline int __must_check wlcore_read32(struct wl1271 *wl, int addr, |
176 | u32 *val) | ||
141 | { | 177 | { |
142 | return wl1271_raw_read32(wl, wlcore_translate_addr(wl, addr)); | 178 | return wlcore_raw_read32(wl, wlcore_translate_addr(wl, addr), val); |
143 | } | 179 | } |
144 | 180 | ||
145 | static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) | 181 | static inline int __must_check wlcore_write32(struct wl1271 *wl, int addr, |
182 | u32 val) | ||
146 | { | 183 | { |
147 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, addr), val); | 184 | return wlcore_raw_write32(wl, wlcore_translate_addr(wl, addr), val); |
148 | } | 185 | } |
149 | 186 | ||
150 | static inline u32 wlcore_read_reg(struct wl1271 *wl, int reg) | 187 | static inline int __must_check wlcore_read_reg(struct wl1271 *wl, int reg, |
188 | u32 *val) | ||
151 | { | 189 | { |
152 | return wl1271_raw_read32(wl, | 190 | return wlcore_raw_read32(wl, |
153 | wlcore_translate_addr(wl, wl->rtable[reg])); | 191 | wlcore_translate_addr(wl, wl->rtable[reg]), |
192 | val); | ||
154 | } | 193 | } |
155 | 194 | ||
156 | static inline void wlcore_write_reg(struct wl1271 *wl, int reg, u32 val) | 195 | static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg, |
196 | u32 val) | ||
157 | { | 197 | { |
158 | wl1271_raw_write32(wl, wlcore_translate_addr(wl, wl->rtable[reg]), val); | 198 | return wlcore_raw_write32(wl, |
199 | wlcore_translate_addr(wl, wl->rtable[reg]), | ||
200 | val); | ||
159 | } | 201 | } |
160 | 202 | ||
161 | static inline void wl1271_power_off(struct wl1271 *wl) | 203 | static inline void wl1271_power_off(struct wl1271 *wl) |
162 | { | 204 | { |
163 | wl->if_ops->power(wl->dev, false); | 205 | int ret; |
164 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | 206 | |
207 | if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags)) | ||
208 | return; | ||
209 | |||
210 | ret = wl->if_ops->power(wl->dev, false); | ||
211 | if (!ret) | ||
212 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
165 | } | 213 | } |
166 | 214 | ||
167 | static inline int wl1271_power_on(struct wl1271 *wl) | 215 | static inline int wl1271_power_on(struct wl1271 *wl) |
@@ -173,8 +221,8 @@ static inline int wl1271_power_on(struct wl1271 *wl) | |||
173 | return ret; | 221 | return ret; |
174 | } | 222 | } |
175 | 223 | ||
176 | void wlcore_set_partition(struct wl1271 *wl, | 224 | int wlcore_set_partition(struct wl1271 *wl, |
177 | const struct wlcore_partition_set *p); | 225 | const struct wlcore_partition_set *p); |
178 | 226 | ||
179 | bool wl1271_set_block_size(struct wl1271 *wl); | 227 | bool wl1271_set_block_size(struct wl1271 *wl); |
180 | 228 | ||
@@ -182,6 +230,4 @@ bool wl1271_set_block_size(struct wl1271 *wl); | |||
182 | 230 | ||
183 | int wl1271_tx_dummy_packet(struct wl1271 *wl); | 231 | int wl1271_tx_dummy_packet(struct wl1271 *wl); |
184 | 232 | ||
185 | void wlcore_select_partition(struct wl1271 *wl, u8 part); | ||
186 | |||
187 | #endif | 233 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 1156e3f578c1..2240cca597ac 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -378,9 +378,9 @@ static void wl12xx_irq_update_links_status(struct wl1271 *wl, | |||
378 | } | 378 | } |
379 | } | 379 | } |
380 | 380 | ||
381 | static void wl12xx_fw_status(struct wl1271 *wl, | 381 | static int wlcore_fw_status(struct wl1271 *wl, |
382 | struct wl_fw_status_1 *status_1, | 382 | struct wl_fw_status_1 *status_1, |
383 | struct wl_fw_status_2 *status_2) | 383 | struct wl_fw_status_2 *status_2) |
384 | { | 384 | { |
385 | struct wl12xx_vif *wlvif; | 385 | struct wl12xx_vif *wlvif; |
386 | struct timespec ts; | 386 | struct timespec ts; |
@@ -388,12 +388,15 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
388 | int avail, freed_blocks; | 388 | int avail, freed_blocks; |
389 | int i; | 389 | int i; |
390 | size_t status_len; | 390 | size_t status_len; |
391 | int ret; | ||
391 | 392 | ||
392 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + | 393 | status_len = WLCORE_FW_STATUS_1_LEN(wl->num_rx_desc) + |
393 | sizeof(*status_2) + wl->fw_status_priv_len; | 394 | sizeof(*status_2) + wl->fw_status_priv_len; |
394 | 395 | ||
395 | wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, | 396 | ret = wlcore_raw_read_data(wl, REG_RAW_FW_STATUS_ADDR, status_1, |
396 | status_len, false); | 397 | status_len, false); |
398 | if (ret < 0) | ||
399 | return ret; | ||
397 | 400 | ||
398 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " | 401 | wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " |
399 | "drv_rx_counter = %d, tx_results_counter = %d)", | 402 | "drv_rx_counter = %d, tx_results_counter = %d)", |
@@ -462,6 +465,8 @@ static void wl12xx_fw_status(struct wl1271 *wl, | |||
462 | getnstimeofday(&ts); | 465 | getnstimeofday(&ts); |
463 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - | 466 | wl->time_offset = (timespec_to_ns(&ts) >> 10) - |
464 | (s64)le32_to_cpu(status_2->fw_localtime); | 467 | (s64)le32_to_cpu(status_2->fw_localtime); |
468 | |||
469 | return 0; | ||
465 | } | 470 | } |
466 | 471 | ||
467 | static void wl1271_flush_deferred_work(struct wl1271 *wl) | 472 | static void wl1271_flush_deferred_work(struct wl1271 *wl) |
@@ -489,20 +494,15 @@ static void wl1271_netstack_work(struct work_struct *work) | |||
489 | 494 | ||
490 | #define WL1271_IRQ_MAX_LOOPS 256 | 495 | #define WL1271_IRQ_MAX_LOOPS 256 |
491 | 496 | ||
492 | static irqreturn_t wl1271_irq(int irq, void *cookie) | 497 | static int wlcore_irq_locked(struct wl1271 *wl) |
493 | { | 498 | { |
494 | int ret; | 499 | int ret = 0; |
495 | u32 intr; | 500 | u32 intr; |
496 | int loopcount = WL1271_IRQ_MAX_LOOPS; | 501 | int loopcount = WL1271_IRQ_MAX_LOOPS; |
497 | struct wl1271 *wl = (struct wl1271 *)cookie; | ||
498 | bool done = false; | 502 | bool done = false; |
499 | unsigned int defer_count; | 503 | unsigned int defer_count; |
500 | unsigned long flags; | 504 | unsigned long flags; |
501 | 505 | ||
502 | /* TX might be handled here, avoid redundant work */ | ||
503 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | ||
504 | cancel_work_sync(&wl->tx_work); | ||
505 | |||
506 | /* | 506 | /* |
507 | * In case edge triggered interrupt must be used, we cannot iterate | 507 | * In case edge triggered interrupt must be used, we cannot iterate |
508 | * more than once without introducing race conditions with the hardirq. | 508 | * more than once without introducing race conditions with the hardirq. |
@@ -510,8 +510,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
510 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) | 510 | if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) |
511 | loopcount = 1; | 511 | loopcount = 1; |
512 | 512 | ||
513 | mutex_lock(&wl->mutex); | ||
514 | |||
515 | wl1271_debug(DEBUG_IRQ, "IRQ work"); | 513 | wl1271_debug(DEBUG_IRQ, "IRQ work"); |
516 | 514 | ||
517 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 515 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
@@ -530,7 +528,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
530 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); | 528 | clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags); |
531 | smp_mb__after_clear_bit(); | 529 | smp_mb__after_clear_bit(); |
532 | 530 | ||
533 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); | 531 | ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
532 | if (ret < 0) | ||
533 | goto out; | ||
534 | 534 | ||
535 | wlcore_hw_tx_immediate_compl(wl); | 535 | wlcore_hw_tx_immediate_compl(wl); |
536 | 536 | ||
@@ -544,7 +544,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { | 544 | if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) { |
545 | wl1271_error("HW watchdog interrupt received! starting recovery."); | 545 | wl1271_error("HW watchdog interrupt received! starting recovery."); |
546 | wl->watchdog_recovery = true; | 546 | wl->watchdog_recovery = true; |
547 | wl12xx_queue_recovery_work(wl); | 547 | ret = -EIO; |
548 | 548 | ||
549 | /* restarting the chip. ignore any other interrupt. */ | 549 | /* restarting the chip. ignore any other interrupt. */ |
550 | goto out; | 550 | goto out; |
@@ -554,7 +554,7 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
554 | wl1271_error("SW watchdog interrupt received! " | 554 | wl1271_error("SW watchdog interrupt received! " |
555 | "starting recovery."); | 555 | "starting recovery."); |
556 | wl->watchdog_recovery = true; | 556 | wl->watchdog_recovery = true; |
557 | wl12xx_queue_recovery_work(wl); | 557 | ret = -EIO; |
558 | 558 | ||
559 | /* restarting the chip. ignore any other interrupt. */ | 559 | /* restarting the chip. ignore any other interrupt. */ |
560 | goto out; | 560 | goto out; |
@@ -563,7 +563,9 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { | 563 | if (likely(intr & WL1271_ACX_INTR_DATA)) { |
564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); | 564 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); |
565 | 565 | ||
566 | wl12xx_rx(wl, wl->fw_status_1); | 566 | ret = wlcore_rx(wl, wl->fw_status_1); |
567 | if (ret < 0) | ||
568 | goto out; | ||
567 | 569 | ||
568 | /* Check if any tx blocks were freed */ | 570 | /* Check if any tx blocks were freed */ |
569 | spin_lock_irqsave(&wl->wl_lock, flags); | 571 | spin_lock_irqsave(&wl->wl_lock, flags); |
@@ -574,13 +576,17 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
574 | * In order to avoid starvation of the TX path, | 576 | * In order to avoid starvation of the TX path, |
575 | * call the work function directly. | 577 | * call the work function directly. |
576 | */ | 578 | */ |
577 | wl1271_tx_work_locked(wl); | 579 | ret = wlcore_tx_work_locked(wl); |
580 | if (ret < 0) | ||
581 | goto out; | ||
578 | } else { | 582 | } else { |
579 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 583 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
580 | } | 584 | } |
581 | 585 | ||
582 | /* check for tx results */ | 586 | /* check for tx results */ |
583 | wlcore_hw_tx_delayed_compl(wl); | 587 | ret = wlcore_hw_tx_delayed_compl(wl); |
588 | if (ret < 0) | ||
589 | goto out; | ||
584 | 590 | ||
585 | /* Make sure the deferred queues don't get too long */ | 591 | /* Make sure the deferred queues don't get too long */ |
586 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + | 592 | defer_count = skb_queue_len(&wl->deferred_tx_queue) + |
@@ -591,12 +597,16 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
591 | 597 | ||
592 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 598 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
593 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 599 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
594 | wl1271_event_handle(wl, 0); | 600 | ret = wl1271_event_handle(wl, 0); |
601 | if (ret < 0) | ||
602 | goto out; | ||
595 | } | 603 | } |
596 | 604 | ||
597 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 605 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
598 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 606 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
599 | wl1271_event_handle(wl, 1); | 607 | ret = wl1271_event_handle(wl, 1); |
608 | if (ret < 0) | ||
609 | goto out; | ||
600 | } | 610 | } |
601 | 611 | ||
602 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 612 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -610,6 +620,25 @@ static irqreturn_t wl1271_irq(int irq, void *cookie) | |||
610 | wl1271_ps_elp_sleep(wl); | 620 | wl1271_ps_elp_sleep(wl); |
611 | 621 | ||
612 | out: | 622 | out: |
623 | return ret; | ||
624 | } | ||
625 | |||
626 | static irqreturn_t wlcore_irq(int irq, void *cookie) | ||
627 | { | ||
628 | int ret; | ||
629 | unsigned long flags; | ||
630 | struct wl1271 *wl = cookie; | ||
631 | |||
632 | /* TX might be handled here, avoid redundant work */ | ||
633 | set_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | ||
634 | cancel_work_sync(&wl->tx_work); | ||
635 | |||
636 | mutex_lock(&wl->mutex); | ||
637 | |||
638 | ret = wlcore_irq_locked(wl); | ||
639 | if (ret) | ||
640 | wl12xx_queue_recovery_work(wl); | ||
641 | |||
613 | spin_lock_irqsave(&wl->wl_lock, flags); | 642 | spin_lock_irqsave(&wl->wl_lock, flags); |
614 | /* In case TX was not handled here, queue TX work */ | 643 | /* In case TX was not handled here, queue TX work */ |
615 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); | 644 | clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags); |
@@ -743,8 +772,13 @@ out: | |||
743 | 772 | ||
744 | void wl12xx_queue_recovery_work(struct wl1271 *wl) | 773 | void wl12xx_queue_recovery_work(struct wl1271 *wl) |
745 | { | 774 | { |
746 | if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | 775 | WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
776 | |||
777 | /* Avoid a recursive recovery */ | ||
778 | if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | ||
779 | wlcore_disable_interrupts_nosync(wl); | ||
747 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | 780 | ieee80211_queue_work(wl->hw, &wl->recovery_work); |
781 | } | ||
748 | } | 782 | } |
749 | 783 | ||
750 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | 784 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) |
@@ -770,14 +804,17 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen) | |||
770 | return len; | 804 | return len; |
771 | } | 805 | } |
772 | 806 | ||
807 | #define WLCORE_FW_LOG_END 0x2000000 | ||
808 | |||
773 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | 809 | static void wl12xx_read_fwlog_panic(struct wl1271 *wl) |
774 | { | 810 | { |
775 | u32 addr; | 811 | u32 addr; |
776 | u32 first_addr; | 812 | u32 offset; |
813 | u32 end_of_log; | ||
777 | u8 *block; | 814 | u8 *block; |
815 | int ret; | ||
778 | 816 | ||
779 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || | 817 | if ((wl->quirks & WLCORE_QUIRK_FWLOG_NOT_IMPLEMENTED) || |
780 | (wl->conf.fwlog.mode != WL12XX_FWLOG_ON_DEMAND) || | ||
781 | (wl->conf.fwlog.mem_blocks == 0)) | 818 | (wl->conf.fwlog.mem_blocks == 0)) |
782 | return; | 819 | return; |
783 | 820 | ||
@@ -791,34 +828,47 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl) | |||
791 | * Make sure the chip is awake and the logger isn't active. | 828 | * Make sure the chip is awake and the logger isn't active. |
792 | * Do not send a stop fwlog command if the fw is hanged. | 829 | * Do not send a stop fwlog command if the fw is hanged. |
793 | */ | 830 | */ |
794 | if (!wl1271_ps_elp_wakeup(wl) && !wl->watchdog_recovery) | 831 | if (wl1271_ps_elp_wakeup(wl)) |
795 | wl12xx_cmd_stop_fwlog(wl); | ||
796 | else | ||
797 | goto out; | 832 | goto out; |
833 | if (!wl->watchdog_recovery) | ||
834 | wl12xx_cmd_stop_fwlog(wl); | ||
798 | 835 | ||
799 | /* Read the first memory block address */ | 836 | /* Read the first memory block address */ |
800 | wl12xx_fw_status(wl, wl->fw_status_1, wl->fw_status_2); | 837 | ret = wlcore_fw_status(wl, wl->fw_status_1, wl->fw_status_2); |
801 | first_addr = le32_to_cpu(wl->fw_status_2->log_start_addr); | 838 | if (ret < 0) |
802 | if (!first_addr) | 839 | goto out; |
840 | |||
841 | addr = le32_to_cpu(wl->fw_status_2->log_start_addr); | ||
842 | if (!addr) | ||
803 | goto out; | 843 | goto out; |
804 | 844 | ||
845 | if (wl->conf.fwlog.mode == WL12XX_FWLOG_CONTINUOUS) { | ||
846 | offset = sizeof(addr) + sizeof(struct wl1271_rx_descriptor); | ||
847 | end_of_log = WLCORE_FW_LOG_END; | ||
848 | } else { | ||
849 | offset = sizeof(addr); | ||
850 | end_of_log = addr; | ||
851 | } | ||
852 | |||
805 | /* Traverse the memory blocks linked list */ | 853 | /* Traverse the memory blocks linked list */ |
806 | addr = first_addr; | ||
807 | do { | 854 | do { |
808 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); | 855 | memset(block, 0, WL12XX_HW_BLOCK_SIZE); |
809 | wl1271_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, | 856 | ret = wlcore_read_hwaddr(wl, addr, block, WL12XX_HW_BLOCK_SIZE, |
810 | false); | 857 | false); |
858 | if (ret < 0) | ||
859 | goto out; | ||
811 | 860 | ||
812 | /* | 861 | /* |
813 | * Memory blocks are linked to one another. The first 4 bytes | 862 | * Memory blocks are linked to one another. The first 4 bytes |
814 | * of each memory block hold the hardware address of the next | 863 | * of each memory block hold the hardware address of the next |
815 | * one. The last memory block points to the first one. | 864 | * one. The last memory block points to the first one in |
865 | * on demand mode and is equal to 0x2000000 in continuous mode. | ||
816 | */ | 866 | */ |
817 | addr = le32_to_cpup((__le32 *)block); | 867 | addr = le32_to_cpup((__le32 *)block); |
818 | if (!wl12xx_copy_fwlog(wl, block + sizeof(addr), | 868 | if (!wl12xx_copy_fwlog(wl, block + offset, |
819 | WL12XX_HW_BLOCK_SIZE - sizeof(addr))) | 869 | WL12XX_HW_BLOCK_SIZE - offset)) |
820 | break; | 870 | break; |
821 | } while (addr && (addr != first_addr)); | 871 | } while (addr && (addr != end_of_log)); |
822 | 872 | ||
823 | wake_up_interruptible(&wl->fwlog_waitq); | 873 | wake_up_interruptible(&wl->fwlog_waitq); |
824 | 874 | ||
@@ -826,6 +876,34 @@ out: | |||
826 | kfree(block); | 876 | kfree(block); |
827 | } | 877 | } |
828 | 878 | ||
879 | static void wlcore_print_recovery(struct wl1271 *wl) | ||
880 | { | ||
881 | u32 pc = 0; | ||
882 | u32 hint_sts = 0; | ||
883 | int ret; | ||
884 | |||
885 | wl1271_info("Hardware recovery in progress. FW ver: %s", | ||
886 | wl->chip.fw_ver_str); | ||
887 | |||
888 | /* change partitions momentarily so we can read the FW pc */ | ||
889 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
890 | if (ret < 0) | ||
891 | return; | ||
892 | |||
893 | ret = wlcore_read_reg(wl, REG_PC_ON_RECOVERY, &pc); | ||
894 | if (ret < 0) | ||
895 | return; | ||
896 | |||
897 | ret = wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR, &hint_sts); | ||
898 | if (ret < 0) | ||
899 | return; | ||
900 | |||
901 | wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts); | ||
902 | |||
903 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
904 | } | ||
905 | |||
906 | |||
829 | static void wl1271_recovery_work(struct work_struct *work) | 907 | static void wl1271_recovery_work(struct work_struct *work) |
830 | { | 908 | { |
831 | struct wl1271 *wl = | 909 | struct wl1271 *wl = |
@@ -838,19 +916,9 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
838 | if (wl->state != WL1271_STATE_ON || wl->plt) | 916 | if (wl->state != WL1271_STATE_ON || wl->plt) |
839 | goto out_unlock; | 917 | goto out_unlock; |
840 | 918 | ||
841 | /* Avoid a recursive recovery */ | ||
842 | set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
843 | |||
844 | wl12xx_read_fwlog_panic(wl); | 919 | wl12xx_read_fwlog_panic(wl); |
845 | 920 | ||
846 | /* change partitions momentarily so we can read the FW pc */ | 921 | wlcore_print_recovery(wl); |
847 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | ||
848 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x " | ||
849 | "hint_sts: 0x%08x", | ||
850 | wl->chip.fw_ver_str, | ||
851 | wlcore_read_reg(wl, REG_PC_ON_RECOVERY), | ||
852 | wlcore_read_reg(wl, REG_INTERRUPT_NO_CLEAR)); | ||
853 | wlcore_set_partition(wl, &wl->ptable[PART_WORK]); | ||
854 | 922 | ||
855 | BUG_ON(bug_on_recovery && | 923 | BUG_ON(bug_on_recovery && |
856 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); | 924 | !test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); |
@@ -892,8 +960,6 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
892 | mutex_unlock(&wl->mutex); | 960 | mutex_unlock(&wl->mutex); |
893 | wl1271_op_stop(wl->hw); | 961 | wl1271_op_stop(wl->hw); |
894 | 962 | ||
895 | clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); | ||
896 | |||
897 | ieee80211_restart_hw(wl->hw); | 963 | ieee80211_restart_hw(wl->hw); |
898 | 964 | ||
899 | /* | 965 | /* |
@@ -907,9 +973,9 @@ out_unlock: | |||
907 | mutex_unlock(&wl->mutex); | 973 | mutex_unlock(&wl->mutex); |
908 | } | 974 | } |
909 | 975 | ||
910 | static void wl1271_fw_wakeup(struct wl1271 *wl) | 976 | static int wlcore_fw_wakeup(struct wl1271 *wl) |
911 | { | 977 | { |
912 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); | 978 | return wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
913 | } | 979 | } |
914 | 980 | ||
915 | static int wl1271_setup(struct wl1271 *wl) | 981 | static int wl1271_setup(struct wl1271 *wl) |
@@ -945,13 +1011,21 @@ static int wl12xx_set_power_on(struct wl1271 *wl) | |||
945 | wl1271_io_reset(wl); | 1011 | wl1271_io_reset(wl); |
946 | wl1271_io_init(wl); | 1012 | wl1271_io_init(wl); |
947 | 1013 | ||
948 | wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); | 1014 | ret = wlcore_set_partition(wl, &wl->ptable[PART_BOOT]); |
1015 | if (ret < 0) | ||
1016 | goto fail; | ||
949 | 1017 | ||
950 | /* ELP module wake up */ | 1018 | /* ELP module wake up */ |
951 | wl1271_fw_wakeup(wl); | 1019 | ret = wlcore_fw_wakeup(wl); |
1020 | if (ret < 0) | ||
1021 | goto fail; | ||
952 | 1022 | ||
953 | out: | 1023 | out: |
954 | return ret; | 1024 | return ret; |
1025 | |||
1026 | fail: | ||
1027 | wl1271_power_off(wl); | ||
1028 | return ret; | ||
955 | } | 1029 | } |
956 | 1030 | ||
957 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) | 1031 | static int wl12xx_chip_wakeup(struct wl1271 *wl, bool plt) |
@@ -1082,6 +1156,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1082 | mutex_lock(&wl->mutex); | 1156 | mutex_lock(&wl->mutex); |
1083 | wl1271_power_off(wl); | 1157 | wl1271_power_off(wl); |
1084 | wl->flags = 0; | 1158 | wl->flags = 0; |
1159 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | ||
1085 | wl->state = WL1271_STATE_OFF; | 1160 | wl->state = WL1271_STATE_OFF; |
1086 | wl->plt = false; | 1161 | wl->plt = false; |
1087 | wl->rx_counter = 0; | 1162 | wl->rx_counter = 0; |
@@ -1173,7 +1248,7 @@ int wl1271_tx_dummy_packet(struct wl1271 *wl) | |||
1173 | 1248 | ||
1174 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ | 1249 | /* The FW is low on RX memory blocks, so send the dummy packet asap */ |
1175 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) | 1250 | if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags)) |
1176 | wl1271_tx_work_locked(wl); | 1251 | return wlcore_tx_work_locked(wl); |
1177 | 1252 | ||
1178 | /* | 1253 | /* |
1179 | * If the FW TX is busy, TX work will be scheduled by the threaded | 1254 | * If the FW TX is busy, TX work will be scheduled by the threaded |
@@ -1440,8 +1515,15 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
1440 | int i, ret; | 1515 | int i, ret; |
1441 | 1516 | ||
1442 | if (!wow || wow->any || !wow->n_patterns) { | 1517 | if (!wow || wow->any || !wow->n_patterns) { |
1443 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | 1518 | ret = wl1271_acx_default_rx_filter_enable(wl, 0, |
1444 | wl1271_rx_filter_clear_all(wl); | 1519 | FILTER_SIGNAL); |
1520 | if (ret) | ||
1521 | goto out; | ||
1522 | |||
1523 | ret = wl1271_rx_filter_clear_all(wl); | ||
1524 | if (ret) | ||
1525 | goto out; | ||
1526 | |||
1445 | return 0; | 1527 | return 0; |
1446 | } | 1528 | } |
1447 | 1529 | ||
@@ -1457,8 +1539,13 @@ static int wl1271_configure_wowlan(struct wl1271 *wl, | |||
1457 | } | 1539 | } |
1458 | } | 1540 | } |
1459 | 1541 | ||
1460 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | 1542 | ret = wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); |
1461 | wl1271_rx_filter_clear_all(wl); | 1543 | if (ret) |
1544 | goto out; | ||
1545 | |||
1546 | ret = wl1271_rx_filter_clear_all(wl); | ||
1547 | if (ret) | ||
1548 | goto out; | ||
1462 | 1549 | ||
1463 | /* Translate WoWLAN patterns into filters */ | 1550 | /* Translate WoWLAN patterns into filters */ |
1464 | for (i = 0; i < wow->n_patterns; i++) { | 1551 | for (i = 0; i < wow->n_patterns; i++) { |
@@ -1500,7 +1587,10 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1500 | if (ret < 0) | 1587 | if (ret < 0) |
1501 | goto out; | 1588 | goto out; |
1502 | 1589 | ||
1503 | wl1271_configure_wowlan(wl, wow); | 1590 | ret = wl1271_configure_wowlan(wl, wow); |
1591 | if (ret < 0) | ||
1592 | goto out_sleep; | ||
1593 | |||
1504 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1594 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1505 | wl->conf.conn.suspend_wake_up_event, | 1595 | wl->conf.conn.suspend_wake_up_event, |
1506 | wl->conf.conn.suspend_listen_interval); | 1596 | wl->conf.conn.suspend_listen_interval); |
@@ -1508,8 +1598,8 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1508 | if (ret < 0) | 1598 | if (ret < 0) |
1509 | wl1271_error("suspend: set wake up conditions failed: %d", ret); | 1599 | wl1271_error("suspend: set wake up conditions failed: %d", ret); |
1510 | 1600 | ||
1601 | out_sleep: | ||
1511 | wl1271_ps_elp_sleep(wl); | 1602 | wl1271_ps_elp_sleep(wl); |
1512 | |||
1513 | out: | 1603 | out: |
1514 | return ret; | 1604 | return ret; |
1515 | 1605 | ||
@@ -1588,6 +1678,12 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1588 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | 1678 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); |
1589 | WARN_ON(!wow); | 1679 | WARN_ON(!wow); |
1590 | 1680 | ||
1681 | /* we want to perform the recovery before suspending */ | ||
1682 | if (test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { | ||
1683 | wl1271_warning("postponing suspend to perform recovery"); | ||
1684 | return -EBUSY; | ||
1685 | } | ||
1686 | |||
1591 | wl1271_tx_flush(wl); | 1687 | wl1271_tx_flush(wl); |
1592 | 1688 | ||
1593 | mutex_lock(&wl->mutex); | 1689 | mutex_lock(&wl->mutex); |
@@ -1628,7 +1724,8 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
1628 | struct wl1271 *wl = hw->priv; | 1724 | struct wl1271 *wl = hw->priv; |
1629 | struct wl12xx_vif *wlvif; | 1725 | struct wl12xx_vif *wlvif; |
1630 | unsigned long flags; | 1726 | unsigned long flags; |
1631 | bool run_irq_work = false; | 1727 | bool run_irq_work = false, pending_recovery; |
1728 | int ret; | ||
1632 | 1729 | ||
1633 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", | 1730 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", |
1634 | wl->wow_enabled); | 1731 | wl->wow_enabled); |
@@ -1644,17 +1741,37 @@ static int wl1271_op_resume(struct ieee80211_hw *hw) | |||
1644 | run_irq_work = true; | 1741 | run_irq_work = true; |
1645 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 1742 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
1646 | 1743 | ||
1744 | mutex_lock(&wl->mutex); | ||
1745 | |||
1746 | /* test the recovery flag before calling any SDIO functions */ | ||
1747 | pending_recovery = test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, | ||
1748 | &wl->flags); | ||
1749 | |||
1647 | if (run_irq_work) { | 1750 | if (run_irq_work) { |
1648 | wl1271_debug(DEBUG_MAC80211, | 1751 | wl1271_debug(DEBUG_MAC80211, |
1649 | "run postponed irq_work directly"); | 1752 | "run postponed irq_work directly"); |
1650 | wl1271_irq(0, wl); | 1753 | |
1754 | /* don't talk to the HW if recovery is pending */ | ||
1755 | if (!pending_recovery) { | ||
1756 | ret = wlcore_irq_locked(wl); | ||
1757 | if (ret) | ||
1758 | wl12xx_queue_recovery_work(wl); | ||
1759 | } | ||
1760 | |||
1651 | wlcore_enable_interrupts(wl); | 1761 | wlcore_enable_interrupts(wl); |
1652 | } | 1762 | } |
1653 | 1763 | ||
1654 | mutex_lock(&wl->mutex); | 1764 | if (pending_recovery) { |
1765 | wl1271_warning("queuing forgotten recovery on resume"); | ||
1766 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
1767 | goto out; | ||
1768 | } | ||
1769 | |||
1655 | wl12xx_for_each_wlvif(wl, wlvif) { | 1770 | wl12xx_for_each_wlvif(wl, wlvif) { |
1656 | wl1271_configure_resume(wl, wlvif); | 1771 | wl1271_configure_resume(wl, wlvif); |
1657 | } | 1772 | } |
1773 | |||
1774 | out: | ||
1658 | wl->wow_enabled = false; | 1775 | wl->wow_enabled = false; |
1659 | mutex_unlock(&wl->mutex); | 1776 | mutex_unlock(&wl->mutex); |
1660 | 1777 | ||
@@ -1695,6 +1812,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1695 | wlcore_disable_interrupts(wl); | 1812 | wlcore_disable_interrupts(wl); |
1696 | mutex_lock(&wl->mutex); | 1813 | mutex_lock(&wl->mutex); |
1697 | if (wl->state == WL1271_STATE_OFF) { | 1814 | if (wl->state == WL1271_STATE_OFF) { |
1815 | if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, | ||
1816 | &wl->flags)) | ||
1817 | wlcore_enable_interrupts(wl); | ||
1818 | |||
1698 | mutex_unlock(&wl->mutex); | 1819 | mutex_unlock(&wl->mutex); |
1699 | 1820 | ||
1700 | /* | 1821 | /* |
@@ -1726,6 +1847,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1726 | mutex_lock(&wl->mutex); | 1847 | mutex_lock(&wl->mutex); |
1727 | 1848 | ||
1728 | wl1271_power_off(wl); | 1849 | wl1271_power_off(wl); |
1850 | /* | ||
1851 | * In case a recovery was scheduled, interrupts were disabled to avoid | ||
1852 | * an interrupt storm. Now that the power is down, it is safe to | ||
1853 | * re-enable interrupts to balance the disable depth | ||
1854 | */ | ||
1855 | if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) | ||
1856 | wlcore_enable_interrupts(wl); | ||
1729 | 1857 | ||
1730 | wl->band = IEEE80211_BAND_2GHZ; | 1858 | wl->band = IEEE80211_BAND_2GHZ; |
1731 | 1859 | ||
@@ -1740,6 +1868,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1740 | wl->ap_fw_ps_map = 0; | 1868 | wl->ap_fw_ps_map = 0; |
1741 | wl->ap_ps_map = 0; | 1869 | wl->ap_ps_map = 0; |
1742 | wl->sched_scanning = false; | 1870 | wl->sched_scanning = false; |
1871 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | ||
1743 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); | 1872 | memset(wl->roles_map, 0, sizeof(wl->roles_map)); |
1744 | memset(wl->links_map, 0, sizeof(wl->links_map)); | 1873 | memset(wl->links_map, 0, sizeof(wl->links_map)); |
1745 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); | 1874 | memset(wl->roc_map, 0, sizeof(wl->roc_map)); |
@@ -2146,6 +2275,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, | |||
2146 | { | 2275 | { |
2147 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); | 2276 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
2148 | int i, ret; | 2277 | int i, ret; |
2278 | bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS); | ||
2149 | 2279 | ||
2150 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 2280 | wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
2151 | 2281 | ||
@@ -2226,11 +2356,25 @@ deinit: | |||
2226 | wlvif->role_id = WL12XX_INVALID_ROLE_ID; | 2356 | wlvif->role_id = WL12XX_INVALID_ROLE_ID; |
2227 | wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; | 2357 | wlvif->dev_role_id = WL12XX_INVALID_ROLE_ID; |
2228 | 2358 | ||
2229 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 2359 | if (is_ap) |
2230 | wl->ap_count--; | 2360 | wl->ap_count--; |
2231 | else | 2361 | else |
2232 | wl->sta_count--; | 2362 | wl->sta_count--; |
2233 | 2363 | ||
2364 | /* Last AP, have more stations. Configure according to STA. */ | ||
2365 | if (wl->ap_count == 0 && is_ap && wl->sta_count) { | ||
2366 | u8 sta_auth = wl->conf.conn.sta_sleep_auth; | ||
2367 | /* Configure for power according to debugfs */ | ||
2368 | if (sta_auth != WL1271_PSM_ILLEGAL) | ||
2369 | wl1271_acx_sleep_auth(wl, sta_auth); | ||
2370 | /* Configure for power always on */ | ||
2371 | else if (wl->quirks & WLCORE_QUIRK_NO_ELP) | ||
2372 | wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
2373 | /* Configure for ELP power saving */ | ||
2374 | else | ||
2375 | wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); | ||
2376 | } | ||
2377 | |||
2234 | mutex_unlock(&wl->mutex); | 2378 | mutex_unlock(&wl->mutex); |
2235 | 2379 | ||
2236 | del_timer_sync(&wlvif->rx_streaming_timer); | 2380 | del_timer_sync(&wlvif->rx_streaming_timer); |
@@ -2448,12 +2592,16 @@ static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
2448 | (wlvif->channel != channel) || | 2592 | (wlvif->channel != channel) || |
2449 | (wlvif->channel_type != conf->channel_type))) { | 2593 | (wlvif->channel_type != conf->channel_type))) { |
2450 | /* send all pending packets */ | 2594 | /* send all pending packets */ |
2451 | wl1271_tx_work_locked(wl); | 2595 | ret = wlcore_tx_work_locked(wl); |
2596 | if (ret < 0) | ||
2597 | return ret; | ||
2598 | |||
2452 | wlvif->band = conf->channel->band; | 2599 | wlvif->band = conf->channel->band; |
2453 | wlvif->channel = channel; | 2600 | wlvif->channel = channel; |
2454 | wlvif->channel_type = conf->channel_type; | 2601 | wlvif->channel_type = conf->channel_type; |
2455 | 2602 | ||
2456 | if (is_ap) { | 2603 | if (is_ap) { |
2604 | wl1271_set_band_rate(wl, wlvif); | ||
2457 | ret = wl1271_init_ap_rates(wl, wlvif); | 2605 | ret = wl1271_init_ap_rates(wl, wlvif); |
2458 | if (ret < 0) | 2606 | if (ret < 0) |
2459 | wl1271_error("AP rate policy change failed %d", | 2607 | wl1271_error("AP rate policy change failed %d", |
@@ -4090,16 +4238,13 @@ out: | |||
4090 | static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, | 4238 | static int wl1271_op_get_survey(struct ieee80211_hw *hw, int idx, |
4091 | struct survey_info *survey) | 4239 | struct survey_info *survey) |
4092 | { | 4240 | { |
4093 | struct wl1271 *wl = hw->priv; | ||
4094 | struct ieee80211_conf *conf = &hw->conf; | 4241 | struct ieee80211_conf *conf = &hw->conf; |
4095 | 4242 | ||
4096 | if (idx != 0) | 4243 | if (idx != 0) |
4097 | return -ENOENT; | 4244 | return -ENOENT; |
4098 | 4245 | ||
4099 | survey->channel = conf->channel; | 4246 | survey->channel = conf->channel; |
4100 | survey->filled = SURVEY_INFO_NOISE_DBM; | 4247 | survey->filled = 0; |
4101 | survey->noise = wl->noise; | ||
4102 | |||
4103 | return 0; | 4248 | return 0; |
4104 | } | 4249 | } |
4105 | 4250 | ||
@@ -4365,9 +4510,14 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, | |||
4365 | 4510 | ||
4366 | case IEEE80211_AMPDU_RX_STOP: | 4511 | case IEEE80211_AMPDU_RX_STOP: |
4367 | if (!(*ba_bitmap & BIT(tid))) { | 4512 | if (!(*ba_bitmap & BIT(tid))) { |
4368 | ret = -EINVAL; | 4513 | /* |
4369 | wl1271_error("no active RX BA session on tid: %d", | 4514 | * this happens on reconfig - so only output a debug |
4515 | * message for now, and don't fail the function. | ||
4516 | */ | ||
4517 | wl1271_debug(DEBUG_MAC80211, | ||
4518 | "no active RX BA session on tid: %d", | ||
4370 | tid); | 4519 | tid); |
4520 | ret = 0; | ||
4371 | break; | 4521 | break; |
4372 | } | 4522 | } |
4373 | 4523 | ||
@@ -4904,18 +5054,22 @@ static int wl12xx_get_hw_info(struct wl1271 *wl) | |||
4904 | if (ret < 0) | 5054 | if (ret < 0) |
4905 | goto out; | 5055 | goto out; |
4906 | 5056 | ||
4907 | wl->chip.id = wlcore_read_reg(wl, REG_CHIP_ID_B); | 5057 | ret = wlcore_read_reg(wl, REG_CHIP_ID_B, &wl->chip.id); |
5058 | if (ret < 0) | ||
5059 | goto out; | ||
4908 | 5060 | ||
4909 | wl->fuse_oui_addr = 0; | 5061 | wl->fuse_oui_addr = 0; |
4910 | wl->fuse_nic_addr = 0; | 5062 | wl->fuse_nic_addr = 0; |
4911 | 5063 | ||
4912 | wl->hw_pg_ver = wl->ops->get_pg_ver(wl); | 5064 | ret = wl->ops->get_pg_ver(wl, &wl->hw_pg_ver); |
5065 | if (ret < 0) | ||
5066 | goto out; | ||
4913 | 5067 | ||
4914 | if (wl->ops->get_mac) | 5068 | if (wl->ops->get_mac) |
4915 | wl->ops->get_mac(wl); | 5069 | ret = wl->ops->get_mac(wl); |
4916 | 5070 | ||
4917 | wl1271_power_off(wl); | ||
4918 | out: | 5071 | out: |
5072 | wl1271_power_off(wl); | ||
4919 | return ret; | 5073 | return ret; |
4920 | } | 5074 | } |
4921 | 5075 | ||
@@ -4976,6 +5130,29 @@ static void wl1271_unregister_hw(struct wl1271 *wl) | |||
4976 | 5130 | ||
4977 | } | 5131 | } |
4978 | 5132 | ||
5133 | static const struct ieee80211_iface_limit wlcore_iface_limits[] = { | ||
5134 | { | ||
5135 | .max = 2, | ||
5136 | .types = BIT(NL80211_IFTYPE_STATION), | ||
5137 | }, | ||
5138 | { | ||
5139 | .max = 1, | ||
5140 | .types = BIT(NL80211_IFTYPE_AP) | | ||
5141 | BIT(NL80211_IFTYPE_P2P_GO) | | ||
5142 | BIT(NL80211_IFTYPE_P2P_CLIENT), | ||
5143 | }, | ||
5144 | }; | ||
5145 | |||
5146 | static const struct ieee80211_iface_combination | ||
5147 | wlcore_iface_combinations[] = { | ||
5148 | { | ||
5149 | .num_different_channels = 1, | ||
5150 | .max_interfaces = 2, | ||
5151 | .limits = wlcore_iface_limits, | ||
5152 | .n_limits = ARRAY_SIZE(wlcore_iface_limits), | ||
5153 | }, | ||
5154 | }; | ||
5155 | |||
4979 | static int wl1271_init_ieee80211(struct wl1271 *wl) | 5156 | static int wl1271_init_ieee80211(struct wl1271 *wl) |
4980 | { | 5157 | { |
4981 | static const u32 cipher_suites[] = { | 5158 | static const u32 cipher_suites[] = { |
@@ -5069,6 +5246,11 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
5069 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 5246 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
5070 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | 5247 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
5071 | 5248 | ||
5249 | /* allowed interface combinations */ | ||
5250 | wl->hw->wiphy->iface_combinations = wlcore_iface_combinations; | ||
5251 | wl->hw->wiphy->n_iface_combinations = | ||
5252 | ARRAY_SIZE(wlcore_iface_combinations); | ||
5253 | |||
5072 | SET_IEEE80211_DEV(wl->hw, wl->dev); | 5254 | SET_IEEE80211_DEV(wl->hw, wl->dev); |
5073 | 5255 | ||
5074 | wl->hw->sta_data_size = sizeof(struct wl1271_station); | 5256 | wl->hw->sta_data_size = sizeof(struct wl1271_station); |
@@ -5140,6 +5322,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
5140 | wl->channel_type = NL80211_CHAN_NO_HT; | 5322 | wl->channel_type = NL80211_CHAN_NO_HT; |
5141 | wl->flags = 0; | 5323 | wl->flags = 0; |
5142 | wl->sg_enabled = true; | 5324 | wl->sg_enabled = true; |
5325 | wl->sleep_auth = WL1271_PSM_ILLEGAL; | ||
5143 | wl->hw_pg_ver = -1; | 5326 | wl->hw_pg_ver = -1; |
5144 | wl->ap_ps_map = 0; | 5327 | wl->ap_ps_map = 0; |
5145 | wl->ap_fw_ps_map = 0; | 5328 | wl->ap_fw_ps_map = 0; |
@@ -5313,7 +5496,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5313 | else | 5496 | else |
5314 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; | 5497 | irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; |
5315 | 5498 | ||
5316 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wl1271_irq, | 5499 | ret = request_threaded_irq(wl->irq, wl12xx_hardirq, wlcore_irq, |
5317 | irqflags, | 5500 | irqflags, |
5318 | pdev->name, wl); | 5501 | pdev->name, wl); |
5319 | if (ret < 0) { | 5502 | if (ret < 0) { |
@@ -5339,12 +5522,12 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5339 | ret = wl12xx_get_hw_info(wl); | 5522 | ret = wl12xx_get_hw_info(wl); |
5340 | if (ret < 0) { | 5523 | if (ret < 0) { |
5341 | wl1271_error("couldn't get hw info"); | 5524 | wl1271_error("couldn't get hw info"); |
5342 | goto out; | 5525 | goto out_irq; |
5343 | } | 5526 | } |
5344 | 5527 | ||
5345 | ret = wl->ops->identify_chip(wl); | 5528 | ret = wl->ops->identify_chip(wl); |
5346 | if (ret < 0) | 5529 | if (ret < 0) |
5347 | goto out; | 5530 | goto out_irq; |
5348 | 5531 | ||
5349 | ret = wl1271_init_ieee80211(wl); | 5532 | ret = wl1271_init_ieee80211(wl); |
5350 | if (ret) | 5533 | if (ret) |
@@ -5358,7 +5541,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5358 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); | 5541 | ret = device_create_file(wl->dev, &dev_attr_bt_coex_state); |
5359 | if (ret < 0) { | 5542 | if (ret < 0) { |
5360 | wl1271_error("failed to create sysfs file bt_coex_state"); | 5543 | wl1271_error("failed to create sysfs file bt_coex_state"); |
5361 | goto out_irq; | 5544 | goto out_unreg; |
5362 | } | 5545 | } |
5363 | 5546 | ||
5364 | /* Create sysfs file to get HW PG version */ | 5547 | /* Create sysfs file to get HW PG version */ |
@@ -5383,6 +5566,9 @@ out_hw_pg_ver: | |||
5383 | out_bt_coex_state: | 5566 | out_bt_coex_state: |
5384 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); | 5567 | device_remove_file(wl->dev, &dev_attr_bt_coex_state); |
5385 | 5568 | ||
5569 | out_unreg: | ||
5570 | wl1271_unregister_hw(wl); | ||
5571 | |||
5386 | out_irq: | 5572 | out_irq: |
5387 | free_irq(wl->irq, wl); | 5573 | free_irq(wl->irq, wl); |
5388 | 5574 | ||
diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 47e81b32f7da..46d36fd30eba 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c | |||
@@ -35,6 +35,7 @@ void wl1271_elp_work(struct work_struct *work) | |||
35 | struct delayed_work *dwork; | 35 | struct delayed_work *dwork; |
36 | struct wl1271 *wl; | 36 | struct wl1271 *wl; |
37 | struct wl12xx_vif *wlvif; | 37 | struct wl12xx_vif *wlvif; |
38 | int ret; | ||
38 | 39 | ||
39 | dwork = container_of(work, struct delayed_work, work); | 40 | dwork = container_of(work, struct delayed_work, work); |
40 | wl = container_of(dwork, struct wl1271, elp_work); | 41 | wl = container_of(dwork, struct wl1271, elp_work); |
@@ -63,7 +64,12 @@ void wl1271_elp_work(struct work_struct *work) | |||
63 | } | 64 | } |
64 | 65 | ||
65 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 66 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
66 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); | 67 | ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_SLEEP); |
68 | if (ret < 0) { | ||
69 | wl12xx_queue_recovery_work(wl); | ||
70 | goto out; | ||
71 | } | ||
72 | |||
67 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); | 73 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
68 | 74 | ||
69 | out: | 75 | out: |
@@ -76,7 +82,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) | |||
76 | struct wl12xx_vif *wlvif; | 82 | struct wl12xx_vif *wlvif; |
77 | u32 timeout; | 83 | u32 timeout; |
78 | 84 | ||
79 | if (wl->quirks & WLCORE_QUIRK_NO_ELP) | 85 | if (wl->sleep_auth != WL1271_PSM_ELP) |
80 | return; | 86 | return; |
81 | 87 | ||
82 | /* we shouldn't get consecutive sleep requests */ | 88 | /* we shouldn't get consecutive sleep requests */ |
@@ -135,7 +141,11 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
135 | wl->elp_compl = &compl; | 141 | wl->elp_compl = &compl; |
136 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 142 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
137 | 143 | ||
138 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); | 144 | ret = wlcore_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG, ELPCTRL_WAKE_UP); |
145 | if (ret < 0) { | ||
146 | wl12xx_queue_recovery_work(wl); | ||
147 | goto err; | ||
148 | } | ||
139 | 149 | ||
140 | if (!pending) { | 150 | if (!pending) { |
141 | ret = wait_for_completion_timeout( | 151 | ret = wait_for_completion_timeout( |
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 78200dcacfca..f55e2f9e7ac5 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
@@ -127,7 +127,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
127 | } | 127 | } |
128 | 128 | ||
129 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) | 129 | if (rx_align == WLCORE_RX_BUF_UNALIGNED) |
130 | reserved = NET_IP_ALIGN; | 130 | reserved = RX_BUF_ALIGN; |
131 | 131 | ||
132 | /* the data read starts with the descriptor */ | 132 | /* the data read starts with the descriptor */ |
133 | desc = (struct wl1271_rx_descriptor *) data; | 133 | desc = (struct wl1271_rx_descriptor *) data; |
@@ -175,7 +175,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
175 | */ | 175 | */ |
176 | memcpy(buf, data + sizeof(*desc), pkt_data_len); | 176 | memcpy(buf, data + sizeof(*desc), pkt_data_len); |
177 | if (rx_align == WLCORE_RX_BUF_PADDED) | 177 | if (rx_align == WLCORE_RX_BUF_PADDED) |
178 | skb_pull(skb, NET_IP_ALIGN); | 178 | skb_pull(skb, RX_BUF_ALIGN); |
179 | 179 | ||
180 | *hlid = desc->hlid; | 180 | *hlid = desc->hlid; |
181 | 181 | ||
@@ -200,7 +200,7 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length, | |||
200 | return is_data; | 200 | return is_data; |
201 | } | 201 | } |
202 | 202 | ||
203 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | 203 | int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) |
204 | { | 204 | { |
205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 205 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
206 | u32 buf_size; | 206 | u32 buf_size; |
@@ -211,6 +211,7 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
211 | u32 pkt_offset, des; | 211 | u32 pkt_offset, des; |
212 | u8 hlid; | 212 | u8 hlid; |
213 | enum wl_rx_buf_align rx_align; | 213 | enum wl_rx_buf_align rx_align; |
214 | int ret = 0; | ||
214 | 215 | ||
215 | while (drv_rx_counter != fw_rx_counter) { | 216 | while (drv_rx_counter != fw_rx_counter) { |
216 | buf_size = 0; | 217 | buf_size = 0; |
@@ -234,9 +235,14 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
234 | 235 | ||
235 | /* Read all available packets at once */ | 236 | /* Read all available packets at once */ |
236 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); | 237 | des = le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]); |
237 | wlcore_hw_prepare_read(wl, des, buf_size); | 238 | ret = wlcore_hw_prepare_read(wl, des, buf_size); |
238 | wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 239 | if (ret < 0) |
239 | buf_size, true); | 240 | goto out; |
241 | |||
242 | ret = wlcore_read_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | ||
243 | buf_size, true); | ||
244 | if (ret < 0) | ||
245 | goto out; | ||
240 | 246 | ||
241 | /* Split data into separate packets */ | 247 | /* Split data into separate packets */ |
242 | pkt_offset = 0; | 248 | pkt_offset = 0; |
@@ -273,11 +279,17 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) | |||
273 | * Write the driver's packet counter to the FW. This is only required | 279 | * Write the driver's packet counter to the FW. This is only required |
274 | * for older hardware revisions | 280 | * for older hardware revisions |
275 | */ | 281 | */ |
276 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) | 282 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) { |
277 | wl1271_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, | 283 | ret = wlcore_write32(wl, WL12XX_REG_RX_DRIVER_COUNTER, |
278 | wl->rx_counter); | 284 | wl->rx_counter); |
285 | if (ret < 0) | ||
286 | goto out; | ||
287 | } | ||
279 | 288 | ||
280 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 289 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
290 | |||
291 | out: | ||
292 | return ret; | ||
281 | } | 293 | } |
282 | 294 | ||
283 | #ifdef CONFIG_PM | 295 | #ifdef CONFIG_PM |
@@ -306,14 +318,19 @@ int wl1271_rx_filter_enable(struct wl1271 *wl, | |||
306 | return 0; | 318 | return 0; |
307 | } | 319 | } |
308 | 320 | ||
309 | void wl1271_rx_filter_clear_all(struct wl1271 *wl) | 321 | int wl1271_rx_filter_clear_all(struct wl1271 *wl) |
310 | { | 322 | { |
311 | int i; | 323 | int i, ret = 0; |
312 | 324 | ||
313 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { | 325 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { |
314 | if (!wl->rx_filter_enabled[i]) | 326 | if (!wl->rx_filter_enabled[i]) |
315 | continue; | 327 | continue; |
316 | wl1271_rx_filter_enable(wl, i, 0, NULL); | 328 | ret = wl1271_rx_filter_enable(wl, i, 0, NULL); |
329 | if (ret) | ||
330 | goto out; | ||
317 | } | 331 | } |
332 | |||
333 | out: | ||
334 | return ret; | ||
318 | } | 335 | } |
319 | #endif /* CONFIG_PM */ | 336 | #endif /* CONFIG_PM */ |
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 9be780179456..71eba1899915 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
@@ -103,6 +103,12 @@ | |||
103 | /* If set, the buffer was padded by the FW to be 4 bytes aligned */ | 103 | /* If set, the buffer was padded by the FW to be 4 bytes aligned */ |
104 | #define RX_BUF_PADDED_PAYLOAD BIT(30) | 104 | #define RX_BUF_PADDED_PAYLOAD BIT(30) |
105 | 105 | ||
106 | /* | ||
107 | * Account for the padding inserted by the FW in case of RX_ALIGNMENT | ||
108 | * or for fixing alignment in case the packet wasn't aligned. | ||
109 | */ | ||
110 | #define RX_BUF_ALIGN 2 | ||
111 | |||
106 | /* Describes the alignment state of a Rx buffer */ | 112 | /* Describes the alignment state of a Rx buffer */ |
107 | enum wl_rx_buf_align { | 113 | enum wl_rx_buf_align { |
108 | WLCORE_RX_BUF_ALIGNED, | 114 | WLCORE_RX_BUF_ALIGNED, |
@@ -137,11 +143,11 @@ struct wl1271_rx_descriptor { | |||
137 | u8 reserved; | 143 | u8 reserved; |
138 | } __packed; | 144 | } __packed; |
139 | 145 | ||
140 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); | 146 | int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status); |
141 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 147 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
142 | int wl1271_rx_filter_enable(struct wl1271 *wl, | 148 | int wl1271_rx_filter_enable(struct wl1271 *wl, |
143 | int index, bool enable, | 149 | int index, bool enable, |
144 | struct wl12xx_rx_filter *filter); | 150 | struct wl12xx_rx_filter *filter); |
145 | void wl1271_rx_filter_clear_all(struct wl1271 *wl); | 151 | int wl1271_rx_filter_clear_all(struct wl1271 *wl); |
146 | 152 | ||
147 | #endif | 153 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index c67ec482e445..204e69fa9327 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c | |||
@@ -71,8 +71,8 @@ static void wl1271_sdio_set_block_size(struct device *child, | |||
71 | sdio_release_host(func); | 71 | sdio_release_host(func); |
72 | } | 72 | } |
73 | 73 | ||
74 | static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | 74 | static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr, |
75 | size_t len, bool fixed) | 75 | void *buf, size_t len, bool fixed) |
76 | { | 76 | { |
77 | int ret; | 77 | int ret; |
78 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 78 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
@@ -103,12 +103,14 @@ static void wl12xx_sdio_raw_read(struct device *child, int addr, void *buf, | |||
103 | 103 | ||
104 | sdio_release_host(func); | 104 | sdio_release_host(func); |
105 | 105 | ||
106 | if (ret) | 106 | if (WARN_ON(ret)) |
107 | dev_err(child->parent, "sdio read failed (%d)\n", ret); | 107 | dev_err(child->parent, "sdio read failed (%d)\n", ret); |
108 | |||
109 | return ret; | ||
108 | } | 110 | } |
109 | 111 | ||
110 | static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | 112 | static int __must_check wl12xx_sdio_raw_write(struct device *child, int addr, |
111 | size_t len, bool fixed) | 113 | void *buf, size_t len, bool fixed) |
112 | { | 114 | { |
113 | int ret; | 115 | int ret; |
114 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); | 116 | struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent); |
@@ -139,25 +141,30 @@ static void wl12xx_sdio_raw_write(struct device *child, int addr, void *buf, | |||
139 | 141 | ||
140 | sdio_release_host(func); | 142 | sdio_release_host(func); |
141 | 143 | ||
142 | if (ret) | 144 | if (WARN_ON(ret)) |
143 | dev_err(child->parent, "sdio write failed (%d)\n", ret); | 145 | dev_err(child->parent, "sdio write failed (%d)\n", ret); |
146 | |||
147 | return ret; | ||
144 | } | 148 | } |
145 | 149 | ||
146 | static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) | 150 | static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue) |
147 | { | 151 | { |
148 | int ret; | 152 | int ret; |
149 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 153 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
154 | struct mmc_card *card = func->card; | ||
150 | 155 | ||
151 | /* If enabled, tell runtime PM not to power off the card */ | 156 | ret = pm_runtime_get_sync(&card->dev); |
152 | if (pm_runtime_enabled(&func->dev)) { | 157 | if (ret) { |
153 | ret = pm_runtime_get_sync(&func->dev); | 158 | /* |
154 | if (ret < 0) | 159 | * Runtime PM might be temporarily disabled, or the device |
155 | goto out; | 160 | * might have a positive reference counter. Make sure it is |
156 | } else { | 161 | * really powered on. |
157 | /* Runtime PM is disabled: power up the card manually */ | 162 | */ |
158 | ret = mmc_power_restore_host(func->card->host); | 163 | ret = mmc_power_restore_host(card->host); |
159 | if (ret < 0) | 164 | if (ret < 0) { |
165 | pm_runtime_put_sync(&card->dev); | ||
160 | goto out; | 166 | goto out; |
167 | } | ||
161 | } | 168 | } |
162 | 169 | ||
163 | sdio_claim_host(func); | 170 | sdio_claim_host(func); |
@@ -172,20 +179,21 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue) | |||
172 | { | 179 | { |
173 | int ret; | 180 | int ret; |
174 | struct sdio_func *func = dev_to_sdio_func(glue->dev); | 181 | struct sdio_func *func = dev_to_sdio_func(glue->dev); |
182 | struct mmc_card *card = func->card; | ||
175 | 183 | ||
176 | sdio_claim_host(func); | 184 | sdio_claim_host(func); |
177 | sdio_disable_func(func); | 185 | sdio_disable_func(func); |
178 | sdio_release_host(func); | 186 | sdio_release_host(func); |
179 | 187 | ||
180 | /* Power off the card manually, even if runtime PM is enabled. */ | 188 | /* Power off the card manually in case it wasn't powered off above */ |
181 | ret = mmc_power_save_host(func->card->host); | 189 | ret = mmc_power_save_host(card->host); |
182 | if (ret < 0) | 190 | if (ret < 0) |
183 | return ret; | 191 | goto out; |
184 | 192 | ||
185 | /* If enabled, let runtime PM know the card is powered off */ | 193 | /* Let runtime PM know the card is powered off */ |
186 | if (pm_runtime_enabled(&func->dev)) | 194 | pm_runtime_put_sync(&card->dev); |
187 | ret = pm_runtime_put_sync(&func->dev); | ||
188 | 195 | ||
196 | out: | ||
189 | return ret; | 197 | return ret; |
190 | } | 198 | } |
191 | 199 | ||
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 553cd3cbb98c..6420abae40ee 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c | |||
@@ -193,8 +193,8 @@ static int wl12xx_spi_read_busy(struct device *child) | |||
193 | return -ETIMEDOUT; | 193 | return -ETIMEDOUT; |
194 | } | 194 | } |
195 | 195 | ||
196 | static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | 196 | static int __must_check wl12xx_spi_raw_read(struct device *child, int addr, |
197 | size_t len, bool fixed) | 197 | void *buf, size_t len, bool fixed) |
198 | { | 198 | { |
199 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 199 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
200 | struct wl1271 *wl = dev_get_drvdata(child); | 200 | struct wl1271 *wl = dev_get_drvdata(child); |
@@ -238,7 +238,7 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | |||
238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && | 238 | if (!(busy_buf[WL1271_BUSY_WORD_CNT - 1] & 0x1) && |
239 | wl12xx_spi_read_busy(child)) { | 239 | wl12xx_spi_read_busy(child)) { |
240 | memset(buf, 0, chunk_len); | 240 | memset(buf, 0, chunk_len); |
241 | return; | 241 | return 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | spi_message_init(&m); | 244 | spi_message_init(&m); |
@@ -256,10 +256,12 @@ static void wl12xx_spi_raw_read(struct device *child, int addr, void *buf, | |||
256 | buf += chunk_len; | 256 | buf += chunk_len; |
257 | len -= chunk_len; | 257 | len -= chunk_len; |
258 | } | 258 | } |
259 | |||
260 | return 0; | ||
259 | } | 261 | } |
260 | 262 | ||
261 | static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, | 263 | static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, |
262 | size_t len, bool fixed) | 264 | void *buf, size_t len, bool fixed) |
263 | { | 265 | { |
264 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); | 266 | struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent); |
265 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; | 267 | struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS]; |
@@ -304,6 +306,8 @@ static void wl12xx_spi_raw_write(struct device *child, int addr, void *buf, | |||
304 | } | 306 | } |
305 | 307 | ||
306 | spi_sync(to_spi_device(glue->dev), &m); | 308 | spi_sync(to_spi_device(glue->dev), &m); |
309 | |||
310 | return 0; | ||
307 | } | 311 | } |
308 | 312 | ||
309 | static struct wl1271_if_operations spi_ops = { | 313 | static struct wl1271_if_operations spi_ops = { |
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index 0e59ea2cdd39..eeb339d61d1e 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c | |||
@@ -108,6 +108,20 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | if (answer) { | 110 | if (answer) { |
111 | /* If we got bip calibration answer print radio status */ | ||
112 | struct wl1271_cmd_cal_p2g *params = | ||
113 | (struct wl1271_cmd_cal_p2g *) buf; | ||
114 | |||
115 | s16 radio_status = (s16) le16_to_cpu(params->radio_status); | ||
116 | |||
117 | if (params->test.id == TEST_CMD_P2G_CAL && | ||
118 | radio_status < 0) | ||
119 | wl1271_warning("testmode cmd: radio status=%d", | ||
120 | radio_status); | ||
121 | else | ||
122 | wl1271_info("testmode cmd: radio status=%d", | ||
123 | radio_status); | ||
124 | |||
111 | len = nla_total_size(buf_len); | 125 | len = nla_total_size(buf_len); |
112 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); | 126 | skb = cfg80211_testmode_alloc_reply_skb(wl->hw->wiphy, len); |
113 | if (!skb) { | 127 | if (!skb) { |
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 9273fdb3aaec..8038a5026933 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c | |||
@@ -305,11 +305,15 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
305 | if (is_dummy || !wlvif) | 305 | if (is_dummy || !wlvif) |
306 | rate_idx = 0; | 306 | rate_idx = 0; |
307 | else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { | 307 | else if (wlvif->bss_type != BSS_TYPE_AP_BSS) { |
308 | /* if the packets are destined for AP (have a STA entry) | 308 | /* |
309 | send them with AP rate policies, otherwise use default | 309 | * if the packets are destined for AP (have a STA entry) |
310 | basic rates */ | 310 | * send them with AP rate policies (EAPOLs are an exception), |
311 | * otherwise use default basic rates | ||
312 | */ | ||
311 | if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) | 313 | if (control->flags & IEEE80211_TX_CTL_NO_CCK_RATE) |
312 | rate_idx = wlvif->sta.p2p_rate_idx; | 314 | rate_idx = wlvif->sta.p2p_rate_idx; |
315 | else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) | ||
316 | rate_idx = wlvif->sta.basic_rate_idx; | ||
313 | else if (control->control.sta) | 317 | else if (control->control.sta) |
314 | rate_idx = wlvif->sta.ap_rate_idx; | 318 | rate_idx = wlvif->sta.ap_rate_idx; |
315 | else | 319 | else |
@@ -348,8 +352,10 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
348 | bool is_dummy; | 352 | bool is_dummy; |
349 | bool is_gem = false; | 353 | bool is_gem = false; |
350 | 354 | ||
351 | if (!skb) | 355 | if (!skb) { |
356 | wl1271_error("discarding null skb"); | ||
352 | return -EINVAL; | 357 | return -EINVAL; |
358 | } | ||
353 | 359 | ||
354 | info = IEEE80211_SKB_CB(skb); | 360 | info = IEEE80211_SKB_CB(skb); |
355 | 361 | ||
@@ -658,7 +664,17 @@ void wl12xx_rearm_rx_streaming(struct wl1271 *wl, unsigned long *active_hlids) | |||
658 | } | 664 | } |
659 | } | 665 | } |
660 | 666 | ||
661 | void wl1271_tx_work_locked(struct wl1271 *wl) | 667 | /* |
668 | * Returns failure values only in case of failed bus ops within this function. | ||
669 | * wl1271_prepare_tx_frame retvals won't be returned in order to avoid | ||
670 | * triggering recovery by higher layers when not necessary. | ||
671 | * In case a FW command fails within wl1271_prepare_tx_frame fails a recovery | ||
672 | * will be queued in wl1271_cmd_send. -EAGAIN/-EBUSY from prepare_tx_frame | ||
673 | * can occur and are legitimate so don't propagate. -EINVAL will emit a WARNING | ||
674 | * within prepare_tx_frame code but there's nothing we should do about those | ||
675 | * as well. | ||
676 | */ | ||
677 | int wlcore_tx_work_locked(struct wl1271 *wl) | ||
662 | { | 678 | { |
663 | struct wl12xx_vif *wlvif; | 679 | struct wl12xx_vif *wlvif; |
664 | struct sk_buff *skb; | 680 | struct sk_buff *skb; |
@@ -666,10 +682,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
666 | u32 buf_offset = 0, last_len = 0; | 682 | u32 buf_offset = 0, last_len = 0; |
667 | bool sent_packets = false; | 683 | bool sent_packets = false; |
668 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; | 684 | unsigned long active_hlids[BITS_TO_LONGS(WL12XX_MAX_LINKS)] = {0}; |
669 | int ret; | 685 | int ret = 0; |
686 | int bus_ret = 0; | ||
670 | 687 | ||
671 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 688 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
672 | return; | 689 | return 0; |
673 | 690 | ||
674 | while ((skb = wl1271_skb_dequeue(wl))) { | 691 | while ((skb = wl1271_skb_dequeue(wl))) { |
675 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 692 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
@@ -690,8 +707,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
690 | 707 | ||
691 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, | 708 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, |
692 | last_len); | 709 | last_len); |
693 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 710 | bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, |
694 | buf_offset, true); | 711 | wl->aggr_buf, buf_offset, true); |
712 | if (bus_ret < 0) | ||
713 | goto out; | ||
714 | |||
695 | sent_packets = true; | 715 | sent_packets = true; |
696 | buf_offset = 0; | 716 | buf_offset = 0; |
697 | continue; | 717 | continue; |
@@ -727,8 +747,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl) | |||
727 | out_ack: | 747 | out_ack: |
728 | if (buf_offset) { | 748 | if (buf_offset) { |
729 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); | 749 | buf_offset = wlcore_hw_pre_pkt_send(wl, buf_offset, last_len); |
730 | wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, | 750 | bus_ret = wlcore_write_data(wl, REG_SLV_MEM_DATA, wl->aggr_buf, |
731 | buf_offset, true); | 751 | buf_offset, true); |
752 | if (bus_ret < 0) | ||
753 | goto out; | ||
754 | |||
732 | sent_packets = true; | 755 | sent_packets = true; |
733 | } | 756 | } |
734 | if (sent_packets) { | 757 | if (sent_packets) { |
@@ -736,13 +759,19 @@ out_ack: | |||
736 | * Interrupt the firmware with the new packets. This is only | 759 | * Interrupt the firmware with the new packets. This is only |
737 | * required for older hardware revisions | 760 | * required for older hardware revisions |
738 | */ | 761 | */ |
739 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) | 762 | if (wl->quirks & WLCORE_QUIRK_END_OF_TRANSACTION) { |
740 | wl1271_write32(wl, WL12XX_HOST_WR_ACCESS, | 763 | bus_ret = wlcore_write32(wl, WL12XX_HOST_WR_ACCESS, |
741 | wl->tx_packets_count); | 764 | wl->tx_packets_count); |
765 | if (bus_ret < 0) | ||
766 | goto out; | ||
767 | } | ||
742 | 768 | ||
743 | wl1271_handle_tx_low_watermark(wl); | 769 | wl1271_handle_tx_low_watermark(wl); |
744 | } | 770 | } |
745 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 771 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
772 | |||
773 | out: | ||
774 | return bus_ret; | ||
746 | } | 775 | } |
747 | 776 | ||
748 | void wl1271_tx_work(struct work_struct *work) | 777 | void wl1271_tx_work(struct work_struct *work) |
@@ -755,7 +784,11 @@ void wl1271_tx_work(struct work_struct *work) | |||
755 | if (ret < 0) | 784 | if (ret < 0) |
756 | goto out; | 785 | goto out; |
757 | 786 | ||
758 | wl1271_tx_work_locked(wl); | 787 | ret = wlcore_tx_work_locked(wl); |
788 | if (ret < 0) { | ||
789 | wl12xx_queue_recovery_work(wl); | ||
790 | goto out; | ||
791 | } | ||
759 | 792 | ||
760 | wl1271_ps_elp_sleep(wl); | 793 | wl1271_ps_elp_sleep(wl); |
761 | out: | 794 | out: |
@@ -877,21 +910,27 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
877 | } | 910 | } |
878 | 911 | ||
879 | /* Called upon reception of a TX complete interrupt */ | 912 | /* Called upon reception of a TX complete interrupt */ |
880 | void wl1271_tx_complete(struct wl1271 *wl) | 913 | int wlcore_tx_complete(struct wl1271 *wl) |
881 | { | 914 | { |
882 | struct wl1271_acx_mem_map *memmap = wl->target_mem_map; | 915 | struct wl1271_acx_mem_map *memmap = wl->target_mem_map; |
883 | u32 count, fw_counter; | 916 | u32 count, fw_counter; |
884 | u32 i; | 917 | u32 i; |
918 | int ret; | ||
885 | 919 | ||
886 | /* read the tx results from the chipset */ | 920 | /* read the tx results from the chipset */ |
887 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 921 | ret = wlcore_read(wl, le32_to_cpu(memmap->tx_result), |
888 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 922 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
923 | if (ret < 0) | ||
924 | goto out; | ||
925 | |||
889 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | 926 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); |
890 | 927 | ||
891 | /* write host counter to chipset (to ack) */ | 928 | /* write host counter to chipset (to ack) */ |
892 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 929 | ret = wlcore_write32(wl, le32_to_cpu(memmap->tx_result) + |
893 | offsetof(struct wl1271_tx_hw_res_if, | 930 | offsetof(struct wl1271_tx_hw_res_if, |
894 | tx_result_host_counter), fw_counter); | 931 | tx_result_host_counter), fw_counter); |
932 | if (ret < 0) | ||
933 | goto out; | ||
895 | 934 | ||
896 | count = fw_counter - wl->tx_results_count; | 935 | count = fw_counter - wl->tx_results_count; |
897 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | 936 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); |
@@ -911,8 +950,11 @@ void wl1271_tx_complete(struct wl1271 *wl) | |||
911 | 950 | ||
912 | wl->tx_results_count++; | 951 | wl->tx_results_count++; |
913 | } | 952 | } |
953 | |||
954 | out: | ||
955 | return ret; | ||
914 | } | 956 | } |
915 | EXPORT_SYMBOL(wl1271_tx_complete); | 957 | EXPORT_SYMBOL(wlcore_tx_complete); |
916 | 958 | ||
917 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | 959 | void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) |
918 | { | 960 | { |
diff --git a/drivers/net/wireless/ti/wlcore/tx.h b/drivers/net/wireless/ti/wlcore/tx.h index fa4be1b91135..1e939b016155 100644 --- a/drivers/net/wireless/ti/wlcore/tx.h +++ b/drivers/net/wireless/ti/wlcore/tx.h | |||
@@ -234,8 +234,8 @@ static inline int wl1271_tx_total_queue_count(struct wl1271 *wl) | |||
234 | } | 234 | } |
235 | 235 | ||
236 | void wl1271_tx_work(struct work_struct *work); | 236 | void wl1271_tx_work(struct work_struct *work); |
237 | void wl1271_tx_work_locked(struct wl1271 *wl); | 237 | int wlcore_tx_work_locked(struct wl1271 *wl); |
238 | void wl1271_tx_complete(struct wl1271 *wl); | 238 | int wlcore_tx_complete(struct wl1271 *wl); |
239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 239 | void wl12xx_tx_reset_wlvif(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
240 | void wl12xx_tx_reset(struct wl1271 *wl); | 240 | void wl12xx_tx_reset(struct wl1271 *wl); |
241 | void wl1271_tx_flush(struct wl1271 *wl); | 241 | void wl1271_tx_flush(struct wl1271 *wl); |
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 761a72f4b8d1..e796974df59b 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -41,9 +41,9 @@ struct wlcore_ops { | |||
41 | int (*identify_fw)(struct wl1271 *wl); | 41 | int (*identify_fw)(struct wl1271 *wl); |
42 | int (*boot)(struct wl1271 *wl); | 42 | int (*boot)(struct wl1271 *wl); |
43 | int (*plt_init)(struct wl1271 *wl); | 43 | int (*plt_init)(struct wl1271 *wl); |
44 | void (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, | 44 | int (*trigger_cmd)(struct wl1271 *wl, int cmd_box_addr, |
45 | void *buf, size_t len); | 45 | void *buf, size_t len); |
46 | void (*ack_event)(struct wl1271 *wl); | 46 | int (*ack_event)(struct wl1271 *wl); |
47 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); | 47 | u32 (*calc_tx_blocks)(struct wl1271 *wl, u32 len, u32 spare_blks); |
48 | void (*set_tx_desc_blocks)(struct wl1271 *wl, | 48 | void (*set_tx_desc_blocks)(struct wl1271 *wl, |
49 | struct wl1271_tx_hw_descr *desc, | 49 | struct wl1271_tx_hw_descr *desc, |
@@ -53,17 +53,17 @@ struct wlcore_ops { | |||
53 | struct sk_buff *skb); | 53 | struct sk_buff *skb); |
54 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, | 54 | enum wl_rx_buf_align (*get_rx_buf_align)(struct wl1271 *wl, |
55 | u32 rx_desc); | 55 | u32 rx_desc); |
56 | void (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); | 56 | int (*prepare_read)(struct wl1271 *wl, u32 rx_desc, u32 len); |
57 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, | 57 | u32 (*get_rx_packet_len)(struct wl1271 *wl, void *rx_data, |
58 | u32 data_len); | 58 | u32 data_len); |
59 | void (*tx_delayed_compl)(struct wl1271 *wl); | 59 | int (*tx_delayed_compl)(struct wl1271 *wl); |
60 | void (*tx_immediate_compl)(struct wl1271 *wl); | 60 | void (*tx_immediate_compl)(struct wl1271 *wl); |
61 | int (*hw_init)(struct wl1271 *wl); | 61 | int (*hw_init)(struct wl1271 *wl); |
62 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 62 | int (*init_vif)(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
63 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, | 63 | u32 (*sta_get_ap_rate_mask)(struct wl1271 *wl, |
64 | struct wl12xx_vif *wlvif); | 64 | struct wl12xx_vif *wlvif); |
65 | s8 (*get_pg_ver)(struct wl1271 *wl); | 65 | int (*get_pg_ver)(struct wl1271 *wl, s8 *ver); |
66 | void (*get_mac)(struct wl1271 *wl); | 66 | int (*get_mac)(struct wl1271 *wl); |
67 | void (*set_tx_desc_csum)(struct wl1271 *wl, | 67 | void (*set_tx_desc_csum)(struct wl1271 *wl, |
68 | struct wl1271_tx_hw_descr *desc, | 68 | struct wl1271_tx_hw_descr *desc, |
69 | struct sk_buff *skb); | 69 | struct sk_buff *skb); |
@@ -387,6 +387,9 @@ struct wl1271 { | |||
387 | 387 | ||
388 | /* mutex for protecting the tx_flush function */ | 388 | /* mutex for protecting the tx_flush function */ |
389 | struct mutex flush_mutex; | 389 | struct mutex flush_mutex; |
390 | |||
391 | /* sleep auth value currently configured to FW */ | ||
392 | int sleep_auth; | ||
390 | }; | 393 | }; |
391 | 394 | ||
392 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 395 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
@@ -398,6 +401,13 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, | |||
398 | struct ieee80211_sta *sta, | 401 | struct ieee80211_sta *sta, |
399 | struct ieee80211_key_conf *key_conf); | 402 | struct ieee80211_key_conf *key_conf); |
400 | 403 | ||
404 | static inline void | ||
405 | wlcore_set_ht_cap(struct wl1271 *wl, enum ieee80211_band band, | ||
406 | struct ieee80211_sta_ht_cap *ht_cap) | ||
407 | { | ||
408 | memcpy(&wl->ht_cap[band], ht_cap, sizeof(*ht_cap)); | ||
409 | } | ||
410 | |||
401 | /* Firmware image load chunk size */ | 411 | /* Firmware image load chunk size */ |
402 | #define CHUNK_SIZE 16384 | 412 | #define CHUNK_SIZE 16384 |
403 | 413 | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 8260b1e9288a..4273a21cdde1 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h | |||
@@ -209,10 +209,10 @@ struct wl1271_scan { | |||
209 | }; | 209 | }; |
210 | 210 | ||
211 | struct wl1271_if_operations { | 211 | struct wl1271_if_operations { |
212 | void (*read)(struct device *child, int addr, void *buf, size_t len, | 212 | int __must_check (*read)(struct device *child, int addr, void *buf, |
213 | bool fixed); | 213 | size_t len, bool fixed); |
214 | void (*write)(struct device *child, int addr, void *buf, size_t len, | 214 | int __must_check (*write)(struct device *child, int addr, void *buf, |
215 | bool fixed); | 215 | size_t len, bool fixed); |
216 | void (*reset)(struct device *child); | 216 | void (*reset)(struct device *child); |
217 | void (*init)(struct device *child); | 217 | void (*init)(struct device *child); |
218 | int (*power)(struct device *child, bool enable); | 218 | int (*power)(struct device *child, bool enable); |
@@ -247,6 +247,7 @@ enum wl12xx_flags { | |||
247 | WL1271_FLAG_RECOVERY_IN_PROGRESS, | 247 | WL1271_FLAG_RECOVERY_IN_PROGRESS, |
248 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, | 248 | WL1271_FLAG_VIF_CHANGE_IN_PROGRESS, |
249 | WL1271_FLAG_INTENDED_FW_RECOVERY, | 249 | WL1271_FLAG_INTENDED_FW_RECOVERY, |
250 | WL1271_FLAG_SDIO_FAILED, | ||
250 | }; | 251 | }; |
251 | 252 | ||
252 | enum wl12xx_vif_flags { | 253 | enum wl12xx_vif_flags { |