aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKalle Valo <kvalo@qca.qualcomm.com>2011-10-30 15:16:15 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2011-11-11 05:58:59 -0500
commit5fe4dffbc12b22507d2416667720cbd4b27c693b (patch)
tree4504c6eb6420b663227884c7f71dda66027a3e0f
parent32a07e4448f78158a75f7c1f0056289647d83946 (diff)
ath6kl: power down hardware when interface is down
The benefit from this is that user space can control hardware's power state by putting interface up and down. This is handy if firmware gets to some weird state. The downside will be that putting interface up takes a bit longer, I was measuring ~500 ms during interface up. Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.c5
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.h2
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h4
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.c3
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c35
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c22
6 files changed, 64 insertions, 7 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c
index 5a4c24d9c2da..a962fe4c6b7e 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.c
+++ b/drivers/net/wireless/ath/ath6kl/bmi.c
@@ -670,6 +670,11 @@ int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
670 return ret; 670 return ret;
671} 671}
672 672
673void ath6kl_bmi_reset(struct ath6kl *ar)
674{
675 ar->bmi.done_sent = false;
676}
677
673int ath6kl_bmi_init(struct ath6kl *ar) 678int ath6kl_bmi_init(struct ath6kl *ar)
674{ 679{
675 ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC); 680 ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
index 96851d5df24b..009e8f650ab1 100644
--- a/drivers/net/wireless/ath/ath6kl/bmi.h
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -230,6 +230,8 @@ struct ath6kl_bmi_target_info {
230 230
231int ath6kl_bmi_init(struct ath6kl *ar); 231int ath6kl_bmi_init(struct ath6kl *ar);
232void ath6kl_bmi_cleanup(struct ath6kl *ar); 232void ath6kl_bmi_cleanup(struct ath6kl *ar);
233void ath6kl_bmi_reset(struct ath6kl *ar);
234
233int ath6kl_bmi_done(struct ath6kl *ar); 235int ath6kl_bmi_done(struct ath6kl *ar);
234int ath6kl_bmi_get_target_info(struct ath6kl *ar, 236int ath6kl_bmi_get_target_info(struct ath6kl *ar,
235 struct ath6kl_bmi_target_info *targ_info); 237 struct ath6kl_bmi_target_info *targ_info);
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 5ac415ee9243..1ac0dd1a035b 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -447,6 +447,7 @@ enum ath6kl_dev_state {
447 DESTROY_IN_PROGRESS, 447 DESTROY_IN_PROGRESS,
448 SKIP_SCAN, 448 SKIP_SCAN,
449 ROAM_TBL_PEND, 449 ROAM_TBL_PEND,
450 FIRST_BOOT,
450}; 451};
451 452
452struct ath6kl { 453struct ath6kl {
@@ -662,4 +663,7 @@ void ath6kl_deinit_if_data(struct ath6kl_vif *vif);
662void ath6kl_core_free(struct ath6kl *ar); 663void ath6kl_core_free(struct ath6kl *ar);
663struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); 664struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar);
664void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); 665void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready);
666int ath6kl_init_hw_start(struct ath6kl *ar);
667int ath6kl_init_hw_stop(struct ath6kl *ar);
668
665#endif /* CORE_H */ 669#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 04b4070240aa..99220d437670 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -2622,6 +2622,9 @@ int ath6kl_htc_start(struct htc_target *target)
2622 struct htc_packet *packet; 2622 struct htc_packet *packet;
2623 int status; 2623 int status;
2624 2624
2625 memset(&target->dev->irq_proc_reg, 0,
2626 sizeof(target->dev->irq_proc_reg));
2627
2625 /* Disable interrupts at the chip level */ 2628 /* Disable interrupts at the chip level */
2626 ath6kl_hif_disable_intrs(target->dev); 2629 ath6kl_hif_disable_intrs(target->dev);
2627 2630
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
index 2ee6a5eced65..237b73c6f42a 100644
--- a/drivers/net/wireless/ath/ath6kl/init.c
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -1421,11 +1421,13 @@ static int ath6kl_init_hw_params(struct ath6kl *ar)
1421 return 0; 1421 return 0;
1422} 1422}
1423 1423
1424static int ath6kl_hw_start(struct ath6kl *ar) 1424int ath6kl_init_hw_start(struct ath6kl *ar)
1425{ 1425{
1426 long timeleft; 1426 long timeleft;
1427 int ret, i; 1427 int ret, i;
1428 1428
1429 ath6kl_dbg(ATH6KL_DBG_BOOT, "hw start\n");
1430
1429 ret = ath6kl_hif_power_on(ar); 1431 ret = ath6kl_hif_power_on(ar);
1430 if (ret) 1432 if (ret)
1431 return ret; 1433 return ret;
@@ -1517,6 +1519,25 @@ err_power_off:
1517 return ret; 1519 return ret;
1518} 1520}
1519 1521
1522int ath6kl_init_hw_stop(struct ath6kl *ar)
1523{
1524 int ret;
1525
1526 ath6kl_dbg(ATH6KL_DBG_BOOT, "hw stop\n");
1527
1528 ath6kl_htc_stop(ar->htc_target);
1529
1530 ath6kl_hif_stop(ar);
1531
1532 ath6kl_bmi_reset(ar);
1533
1534 ret = ath6kl_hif_power_off(ar);
1535 if (ret)
1536 ath6kl_warn("failed to power off hif: %d\n", ret);
1537
1538 return 0;
1539}
1540
1520int ath6kl_core_init(struct ath6kl *ar) 1541int ath6kl_core_init(struct ath6kl *ar)
1521{ 1542{
1522 struct ath6kl_bmi_target_info targ_info; 1543 struct ath6kl_bmi_target_info targ_info;
@@ -1629,9 +1650,11 @@ int ath6kl_core_init(struct ath6kl *ar)
1629 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | 1650 ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM |
1630 WIPHY_FLAG_HAVE_AP_SME; 1651 WIPHY_FLAG_HAVE_AP_SME;
1631 1652
1632 ret = ath6kl_hw_start(ar); 1653 set_bit(FIRST_BOOT, &ar->flag);
1654
1655 ret = ath6kl_init_hw_start(ar);
1633 if (ret) { 1656 if (ret) {
1634 ath6kl_err("Failed to boot hardware: %d\n", ret); 1657 ath6kl_err("Failed to start hardware: %d\n", ret);
1635 goto err_rxbuf_cleanup; 1658 goto err_rxbuf_cleanup;
1636 } 1659 }
1637 1660
@@ -1641,6 +1664,12 @@ int ath6kl_core_init(struct ath6kl *ar)
1641 */ 1664 */
1642 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); 1665 memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN);
1643 1666
1667 ret = ath6kl_init_hw_stop(ar);
1668 if (ret) {
1669 ath6kl_err("Failed to stop hardware: %d\n", ret);
1670 goto err_htc_cleanup;
1671 }
1672
1644 return ret; 1673 return ret;
1645 1674
1646err_rxbuf_cleanup: 1675err_rxbuf_cleanup:
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
index 3b2a7e8a24b9..717ed22abc31 100644
--- a/drivers/net/wireless/ath/ath6kl/main.c
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -673,10 +673,12 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
673 set_bit(WMI_READY, &ar->flag); 673 set_bit(WMI_READY, &ar->flag);
674 wake_up(&ar->event_wq); 674 wake_up(&ar->event_wq);
675 675
676 ath6kl_info("hw %s fw %s%s\n", 676 if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) {
677 get_hw_id_string(ar->wiphy->hw_version), 677 ath6kl_info("hw %s fw %s%s\n",
678 ar->wiphy->fw_version, 678 get_hw_id_string(ar->wiphy->hw_version),
679 test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); 679 ar->wiphy->fw_version,
680 test_bit(TESTMODE, &ar->flag) ? " testmode" : "");
681 }
680} 682}
681 683
682void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status) 684void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status)
@@ -1112,6 +1114,12 @@ struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar)
1112static int ath6kl_open(struct net_device *dev) 1114static int ath6kl_open(struct net_device *dev)
1113{ 1115{
1114 struct ath6kl_vif *vif = netdev_priv(dev); 1116 struct ath6kl_vif *vif = netdev_priv(dev);
1117 int ret;
1118
1119 /* FIXME: how to handle multi vif support? */
1120 ret = ath6kl_init_hw_start(vif->ar);
1121 if (ret)
1122 return ret;
1115 1123
1116 set_bit(WLAN_ENABLED, &vif->flags); 1124 set_bit(WLAN_ENABLED, &vif->flags);
1117 1125
@@ -1128,6 +1136,7 @@ static int ath6kl_close(struct net_device *dev)
1128{ 1136{
1129 struct ath6kl *ar = ath6kl_priv(dev); 1137 struct ath6kl *ar = ath6kl_priv(dev);
1130 struct ath6kl_vif *vif = netdev_priv(dev); 1138 struct ath6kl_vif *vif = netdev_priv(dev);
1139 int ret;
1131 1140
1132 netif_stop_queue(dev); 1141 netif_stop_queue(dev);
1133 1142
@@ -1143,6 +1152,11 @@ static int ath6kl_close(struct net_device *dev)
1143 1152
1144 ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED); 1153 ath6kl_cfg80211_scan_complete_event(vif, -ECANCELED);
1145 1154
1155 /* FIXME: how to handle multi vif support? */
1156 ret = ath6kl_init_hw_stop(ar);
1157 if (ret)
1158 return ret;
1159
1146 return 0; 1160 return 0;
1147} 1161}
1148 1162