diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 415 |
1 files changed, 155 insertions, 260 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index db8c0c044e9e..5aa104fe7eeb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -16,10 +16,6 @@ | |||
16 | 16 | ||
17 | #include "htc.h" | 17 | #include "htc.h" |
18 | 18 | ||
19 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
20 | static struct dentry *ath9k_debugfs_root; | ||
21 | #endif | ||
22 | |||
23 | /*************/ | 19 | /*************/ |
24 | /* Utilities */ | 20 | /* Utilities */ |
25 | /*************/ | 21 | /*************/ |
@@ -197,11 +193,16 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
197 | 193 | ||
198 | ath9k_htc_stop_ani(priv); | 194 | ath9k_htc_stop_ani(priv); |
199 | ieee80211_stop_queues(priv->hw); | 195 | ieee80211_stop_queues(priv->hw); |
200 | htc_stop(priv->htc); | 196 | |
197 | del_timer_sync(&priv->tx.cleanup_timer); | ||
198 | ath9k_htc_tx_drain(priv); | ||
199 | |||
201 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 200 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
202 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 201 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
203 | WMI_CMD(WMI_STOP_RECV_CMDID); | 202 | WMI_CMD(WMI_STOP_RECV_CMDID); |
204 | 203 | ||
204 | ath9k_wmi_event_drain(priv); | ||
205 | |||
205 | caldata = &priv->caldata; | 206 | caldata = &priv->caldata; |
206 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); | 207 | ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); |
207 | if (ret) { | 208 | if (ret) { |
@@ -225,6 +226,9 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
225 | ath9k_htc_vif_reconfig(priv); | 226 | ath9k_htc_vif_reconfig(priv); |
226 | ieee80211_wake_queues(priv->hw); | 227 | ieee80211_wake_queues(priv->hw); |
227 | 228 | ||
229 | mod_timer(&priv->tx.cleanup_timer, | ||
230 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
231 | |||
228 | ath9k_htc_ps_restore(priv); | 232 | ath9k_htc_ps_restore(priv); |
229 | mutex_unlock(&priv->mutex); | 233 | mutex_unlock(&priv->mutex); |
230 | } | 234 | } |
@@ -250,11 +254,16 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
250 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); | 254 | fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); |
251 | 255 | ||
252 | ath9k_htc_ps_wakeup(priv); | 256 | ath9k_htc_ps_wakeup(priv); |
253 | htc_stop(priv->htc); | 257 | |
258 | del_timer_sync(&priv->tx.cleanup_timer); | ||
259 | ath9k_htc_tx_drain(priv); | ||
260 | |||
254 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 261 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
255 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 262 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
256 | WMI_CMD(WMI_STOP_RECV_CMDID); | 263 | WMI_CMD(WMI_STOP_RECV_CMDID); |
257 | 264 | ||
265 | ath9k_wmi_event_drain(priv); | ||
266 | |||
258 | ath_dbg(common, ATH_DBG_CONFIG, | 267 | ath_dbg(common, ATH_DBG_CONFIG, |
259 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", | 268 | "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", |
260 | priv->ah->curchan->channel, | 269 | priv->ah->curchan->channel, |
@@ -263,6 +272,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
263 | 272 | ||
264 | if (!fastcc) | 273 | if (!fastcc) |
265 | caldata = &priv->caldata; | 274 | caldata = &priv->caldata; |
275 | |||
266 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 276 | ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
267 | if (ret) { | 277 | if (ret) { |
268 | ath_err(common, | 278 | ath_err(common, |
@@ -296,6 +306,9 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
296 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | 306 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) |
297 | ath9k_htc_vif_reconfig(priv); | 307 | ath9k_htc_vif_reconfig(priv); |
298 | 308 | ||
309 | mod_timer(&priv->tx.cleanup_timer, | ||
310 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
311 | |||
299 | err: | 312 | err: |
300 | ath9k_htc_ps_restore(priv); | 313 | ath9k_htc_ps_restore(priv); |
301 | return ret; | 314 | return ret; |
@@ -319,6 +332,11 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | |||
319 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 332 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
320 | hvif.index = priv->mon_vif_idx; | 333 | hvif.index = priv->mon_vif_idx; |
321 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 334 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
335 | if (ret) { | ||
336 | ath_err(common, "Unable to remove monitor interface at idx: %d\n", | ||
337 | priv->mon_vif_idx); | ||
338 | } | ||
339 | |||
322 | priv->nvifs--; | 340 | priv->nvifs--; |
323 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); | 341 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); |
324 | } | 342 | } |
@@ -349,7 +367,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | |||
349 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 367 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
350 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 368 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
351 | 369 | ||
352 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); | 370 | hvif.opmode = HTC_M_MONITOR; |
353 | hvif.index = ffz(priv->vif_slot); | 371 | hvif.index = ffz(priv->vif_slot); |
354 | 372 | ||
355 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | 373 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
@@ -382,7 +400,7 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | |||
382 | tsta.is_vif_sta = 1; | 400 | tsta.is_vif_sta = 1; |
383 | tsta.sta_index = sta_idx; | 401 | tsta.sta_index = sta_idx; |
384 | tsta.vif_index = hvif.index; | 402 | tsta.vif_index = hvif.index; |
385 | tsta.maxampdu = 0xffff; | 403 | tsta.maxampdu = cpu_to_be16(0xffff); |
386 | 404 | ||
387 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); | 405 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); |
388 | if (ret) { | 406 | if (ret) { |
@@ -449,6 +467,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
449 | struct ath9k_htc_sta *ista; | 467 | struct ath9k_htc_sta *ista; |
450 | int ret, sta_idx; | 468 | int ret, sta_idx; |
451 | u8 cmd_rsp; | 469 | u8 cmd_rsp; |
470 | u16 maxampdu; | ||
452 | 471 | ||
453 | if (priv->nstations >= ATH9K_HTC_MAX_STA) | 472 | if (priv->nstations >= ATH9K_HTC_MAX_STA) |
454 | return -ENOBUFS; | 473 | return -ENOBUFS; |
@@ -463,9 +482,7 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
463 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 482 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
464 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); | 483 | memcpy(&tsta.macaddr, sta->addr, ETH_ALEN); |
465 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); | 484 | memcpy(&tsta.bssid, common->curbssid, ETH_ALEN); |
466 | tsta.associd = common->curaid; | ||
467 | tsta.is_vif_sta = 0; | 485 | tsta.is_vif_sta = 0; |
468 | tsta.valid = true; | ||
469 | ista->index = sta_idx; | 486 | ista->index = sta_idx; |
470 | } else { | 487 | } else { |
471 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); | 488 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); |
@@ -474,7 +491,15 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
474 | 491 | ||
475 | tsta.sta_index = sta_idx; | 492 | tsta.sta_index = sta_idx; |
476 | tsta.vif_index = avp->index; | 493 | tsta.vif_index = avp->index; |
477 | tsta.maxampdu = 0xffff; | 494 | |
495 | if (!sta) { | ||
496 | tsta.maxampdu = cpu_to_be16(0xffff); | ||
497 | } else { | ||
498 | maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + | ||
499 | sta->ht_cap.ampdu_factor); | ||
500 | tsta.maxampdu = cpu_to_be16(maxampdu); | ||
501 | } | ||
502 | |||
478 | if (sta && sta->ht_cap.ht_supported) | 503 | if (sta && sta->ht_cap.ht_supported) |
479 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); | 504 | tsta.flags = cpu_to_be16(ATH_HTC_STA_HT); |
480 | 505 | ||
@@ -547,7 +572,8 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
547 | return 0; | 572 | return 0; |
548 | } | 573 | } |
549 | 574 | ||
550 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | 575 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, |
576 | u8 enable_coex) | ||
551 | { | 577 | { |
552 | struct ath9k_htc_cap_target tcap; | 578 | struct ath9k_htc_cap_target tcap; |
553 | int ret; | 579 | int ret; |
@@ -555,13 +581,9 @@ int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv) | |||
555 | 581 | ||
556 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); | 582 | memset(&tcap, 0, sizeof(struct ath9k_htc_cap_target)); |
557 | 583 | ||
558 | /* FIXME: Values are hardcoded */ | 584 | tcap.ampdu_limit = cpu_to_be32(0xffff); |
559 | tcap.flags = 0x240c40; | 585 | tcap.ampdu_subframes = priv->hw->max_tx_aggregation_subframes; |
560 | tcap.flags_ext = 0x80601000; | 586 | tcap.enable_coex = enable_coex; |
561 | tcap.ampdu_limit = 0xffff0000; | ||
562 | tcap.ampdu_subframes = 20; | ||
563 | tcap.tx_chainmask_legacy = priv->ah->caps.tx_chainmask; | ||
564 | tcap.protmode = 1; | ||
565 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; | 587 | tcap.tx_chainmask = priv->ah->caps.tx_chainmask; |
566 | 588 | ||
567 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); | 589 | WMI_CMD_BUF(WMI_TARGET_IC_UPDATE_CMDID, &tcap); |
@@ -709,218 +731,13 @@ static int ath9k_htc_tx_aggr_oper(struct ath9k_htc_priv *priv, | |||
709 | (aggr.aggr_enable) ? "Starting" : "Stopping", | 731 | (aggr.aggr_enable) ? "Starting" : "Stopping", |
710 | sta->addr, tid); | 732 | sta->addr, tid); |
711 | 733 | ||
712 | spin_lock_bh(&priv->tx_lock); | 734 | spin_lock_bh(&priv->tx.tx_lock); |
713 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; | 735 | ista->tid_state[tid] = (aggr.aggr_enable && !ret) ? AGGR_START : AGGR_STOP; |
714 | spin_unlock_bh(&priv->tx_lock); | 736 | spin_unlock_bh(&priv->tx.tx_lock); |
715 | 737 | ||
716 | return ret; | 738 | return ret; |
717 | } | 739 | } |
718 | 740 | ||
719 | /*********/ | ||
720 | /* DEBUG */ | ||
721 | /*********/ | ||
722 | |||
723 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | ||
724 | |||
725 | static int ath9k_debugfs_open(struct inode *inode, struct file *file) | ||
726 | { | ||
727 | file->private_data = inode->i_private; | ||
728 | return 0; | ||
729 | } | ||
730 | |||
731 | static ssize_t read_file_tgt_stats(struct file *file, char __user *user_buf, | ||
732 | size_t count, loff_t *ppos) | ||
733 | { | ||
734 | struct ath9k_htc_priv *priv = file->private_data; | ||
735 | struct ath9k_htc_target_stats cmd_rsp; | ||
736 | char buf[512]; | ||
737 | unsigned int len = 0; | ||
738 | int ret = 0; | ||
739 | |||
740 | memset(&cmd_rsp, 0, sizeof(cmd_rsp)); | ||
741 | |||
742 | WMI_CMD(WMI_TGT_STATS_CMDID); | ||
743 | if (ret) | ||
744 | return -EINVAL; | ||
745 | |||
746 | |||
747 | len += snprintf(buf + len, sizeof(buf) - len, | ||
748 | "%19s : %10u\n", "TX Short Retries", | ||
749 | be32_to_cpu(cmd_rsp.tx_shortretry)); | ||
750 | len += snprintf(buf + len, sizeof(buf) - len, | ||
751 | "%19s : %10u\n", "TX Long Retries", | ||
752 | be32_to_cpu(cmd_rsp.tx_longretry)); | ||
753 | len += snprintf(buf + len, sizeof(buf) - len, | ||
754 | "%19s : %10u\n", "TX Xretries", | ||
755 | be32_to_cpu(cmd_rsp.tx_xretries)); | ||
756 | len += snprintf(buf + len, sizeof(buf) - len, | ||
757 | "%19s : %10u\n", "TX Unaggr. Xretries", | ||
758 | be32_to_cpu(cmd_rsp.ht_txunaggr_xretry)); | ||
759 | len += snprintf(buf + len, sizeof(buf) - len, | ||
760 | "%19s : %10u\n", "TX Xretries (HT)", | ||
761 | be32_to_cpu(cmd_rsp.ht_tx_xretries)); | ||
762 | len += snprintf(buf + len, sizeof(buf) - len, | ||
763 | "%19s : %10u\n", "TX Rate", priv->debug.txrate); | ||
764 | |||
765 | if (len > sizeof(buf)) | ||
766 | len = sizeof(buf); | ||
767 | |||
768 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
769 | } | ||
770 | |||
771 | static const struct file_operations fops_tgt_stats = { | ||
772 | .read = read_file_tgt_stats, | ||
773 | .open = ath9k_debugfs_open, | ||
774 | .owner = THIS_MODULE, | ||
775 | .llseek = default_llseek, | ||
776 | }; | ||
777 | |||
778 | static ssize_t read_file_xmit(struct file *file, char __user *user_buf, | ||
779 | size_t count, loff_t *ppos) | ||
780 | { | ||
781 | struct ath9k_htc_priv *priv = file->private_data; | ||
782 | char buf[512]; | ||
783 | unsigned int len = 0; | ||
784 | |||
785 | len += snprintf(buf + len, sizeof(buf) - len, | ||
786 | "%20s : %10u\n", "Buffers queued", | ||
787 | priv->debug.tx_stats.buf_queued); | ||
788 | len += snprintf(buf + len, sizeof(buf) - len, | ||
789 | "%20s : %10u\n", "Buffers completed", | ||
790 | priv->debug.tx_stats.buf_completed); | ||
791 | len += snprintf(buf + len, sizeof(buf) - len, | ||
792 | "%20s : %10u\n", "SKBs queued", | ||
793 | priv->debug.tx_stats.skb_queued); | ||
794 | len += snprintf(buf + len, sizeof(buf) - len, | ||
795 | "%20s : %10u\n", "SKBs completed", | ||
796 | priv->debug.tx_stats.skb_completed); | ||
797 | len += snprintf(buf + len, sizeof(buf) - len, | ||
798 | "%20s : %10u\n", "SKBs dropped", | ||
799 | priv->debug.tx_stats.skb_dropped); | ||
800 | |||
801 | len += snprintf(buf + len, sizeof(buf) - len, | ||
802 | "%20s : %10u\n", "BE queued", | ||
803 | priv->debug.tx_stats.queue_stats[WME_AC_BE]); | ||
804 | len += snprintf(buf + len, sizeof(buf) - len, | ||
805 | "%20s : %10u\n", "BK queued", | ||
806 | priv->debug.tx_stats.queue_stats[WME_AC_BK]); | ||
807 | len += snprintf(buf + len, sizeof(buf) - len, | ||
808 | "%20s : %10u\n", "VI queued", | ||
809 | priv->debug.tx_stats.queue_stats[WME_AC_VI]); | ||
810 | len += snprintf(buf + len, sizeof(buf) - len, | ||
811 | "%20s : %10u\n", "VO queued", | ||
812 | priv->debug.tx_stats.queue_stats[WME_AC_VO]); | ||
813 | |||
814 | if (len > sizeof(buf)) | ||
815 | len = sizeof(buf); | ||
816 | |||
817 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
818 | } | ||
819 | |||
820 | static const struct file_operations fops_xmit = { | ||
821 | .read = read_file_xmit, | ||
822 | .open = ath9k_debugfs_open, | ||
823 | .owner = THIS_MODULE, | ||
824 | .llseek = default_llseek, | ||
825 | }; | ||
826 | |||
827 | static ssize_t read_file_recv(struct file *file, char __user *user_buf, | ||
828 | size_t count, loff_t *ppos) | ||
829 | { | ||
830 | struct ath9k_htc_priv *priv = file->private_data; | ||
831 | char buf[512]; | ||
832 | unsigned int len = 0; | ||
833 | |||
834 | len += snprintf(buf + len, sizeof(buf) - len, | ||
835 | "%20s : %10u\n", "SKBs allocated", | ||
836 | priv->debug.rx_stats.skb_allocated); | ||
837 | len += snprintf(buf + len, sizeof(buf) - len, | ||
838 | "%20s : %10u\n", "SKBs completed", | ||
839 | priv->debug.rx_stats.skb_completed); | ||
840 | len += snprintf(buf + len, sizeof(buf) - len, | ||
841 | "%20s : %10u\n", "SKBs Dropped", | ||
842 | priv->debug.rx_stats.skb_dropped); | ||
843 | |||
844 | if (len > sizeof(buf)) | ||
845 | len = sizeof(buf); | ||
846 | |||
847 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
848 | } | ||
849 | |||
850 | static const struct file_operations fops_recv = { | ||
851 | .read = read_file_recv, | ||
852 | .open = ath9k_debugfs_open, | ||
853 | .owner = THIS_MODULE, | ||
854 | .llseek = default_llseek, | ||
855 | }; | ||
856 | |||
857 | int ath9k_htc_init_debug(struct ath_hw *ah) | ||
858 | { | ||
859 | struct ath_common *common = ath9k_hw_common(ah); | ||
860 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
861 | |||
862 | if (!ath9k_debugfs_root) | ||
863 | return -ENOENT; | ||
864 | |||
865 | priv->debug.debugfs_phy = debugfs_create_dir(wiphy_name(priv->hw->wiphy), | ||
866 | ath9k_debugfs_root); | ||
867 | if (!priv->debug.debugfs_phy) | ||
868 | goto err; | ||
869 | |||
870 | priv->debug.debugfs_tgt_stats = debugfs_create_file("tgt_stats", S_IRUSR, | ||
871 | priv->debug.debugfs_phy, | ||
872 | priv, &fops_tgt_stats); | ||
873 | if (!priv->debug.debugfs_tgt_stats) | ||
874 | goto err; | ||
875 | |||
876 | |||
877 | priv->debug.debugfs_xmit = debugfs_create_file("xmit", S_IRUSR, | ||
878 | priv->debug.debugfs_phy, | ||
879 | priv, &fops_xmit); | ||
880 | if (!priv->debug.debugfs_xmit) | ||
881 | goto err; | ||
882 | |||
883 | priv->debug.debugfs_recv = debugfs_create_file("recv", S_IRUSR, | ||
884 | priv->debug.debugfs_phy, | ||
885 | priv, &fops_recv); | ||
886 | if (!priv->debug.debugfs_recv) | ||
887 | goto err; | ||
888 | |||
889 | return 0; | ||
890 | |||
891 | err: | ||
892 | ath9k_htc_exit_debug(ah); | ||
893 | return -ENOMEM; | ||
894 | } | ||
895 | |||
896 | void ath9k_htc_exit_debug(struct ath_hw *ah) | ||
897 | { | ||
898 | struct ath_common *common = ath9k_hw_common(ah); | ||
899 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv; | ||
900 | |||
901 | debugfs_remove(priv->debug.debugfs_recv); | ||
902 | debugfs_remove(priv->debug.debugfs_xmit); | ||
903 | debugfs_remove(priv->debug.debugfs_tgt_stats); | ||
904 | debugfs_remove(priv->debug.debugfs_phy); | ||
905 | } | ||
906 | |||
907 | int ath9k_htc_debug_create_root(void) | ||
908 | { | ||
909 | ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); | ||
910 | if (!ath9k_debugfs_root) | ||
911 | return -ENOENT; | ||
912 | |||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | void ath9k_htc_debug_remove_root(void) | ||
917 | { | ||
918 | debugfs_remove(ath9k_debugfs_root); | ||
919 | ath9k_debugfs_root = NULL; | ||
920 | } | ||
921 | |||
922 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | ||
923 | |||
924 | /*******/ | 741 | /*******/ |
925 | /* ANI */ | 742 | /* ANI */ |
926 | /*******/ | 743 | /*******/ |
@@ -1040,7 +857,8 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1040 | { | 857 | { |
1041 | struct ieee80211_hdr *hdr; | 858 | struct ieee80211_hdr *hdr; |
1042 | struct ath9k_htc_priv *priv = hw->priv; | 859 | struct ath9k_htc_priv *priv = hw->priv; |
1043 | int padpos, padsize, ret; | 860 | struct ath_common *common = ath9k_hw_common(priv->ah); |
861 | int padpos, padsize, ret, slot; | ||
1044 | 862 | ||
1045 | hdr = (struct ieee80211_hdr *) skb->data; | 863 | hdr = (struct ieee80211_hdr *) skb->data; |
1046 | 864 | ||
@@ -1048,30 +866,32 @@ static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1048 | padpos = ath9k_cmn_padpos(hdr->frame_control); | 866 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1049 | padsize = padpos & 3; | 867 | padsize = padpos & 3; |
1050 | if (padsize && skb->len > padpos) { | 868 | if (padsize && skb->len > padpos) { |
1051 | if (skb_headroom(skb) < padsize) | 869 | if (skb_headroom(skb) < padsize) { |
870 | ath_dbg(common, ATH_DBG_XMIT, "No room for padding\n"); | ||
1052 | goto fail_tx; | 871 | goto fail_tx; |
872 | } | ||
1053 | skb_push(skb, padsize); | 873 | skb_push(skb, padsize); |
1054 | memmove(skb->data, skb->data + padsize, padpos); | 874 | memmove(skb->data, skb->data + padsize, padpos); |
1055 | } | 875 | } |
1056 | 876 | ||
1057 | ret = ath9k_htc_tx_start(priv, skb); | 877 | slot = ath9k_htc_tx_get_slot(priv); |
1058 | if (ret != 0) { | 878 | if (slot < 0) { |
1059 | if (ret == -ENOMEM) { | 879 | ath_dbg(common, ATH_DBG_XMIT, "No free TX slot\n"); |
1060 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1061 | "Stopping TX queues\n"); | ||
1062 | ieee80211_stop_queues(hw); | ||
1063 | spin_lock_bh(&priv->tx_lock); | ||
1064 | priv->tx_queues_stop = true; | ||
1065 | spin_unlock_bh(&priv->tx_lock); | ||
1066 | } else { | ||
1067 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
1068 | "Tx failed\n"); | ||
1069 | } | ||
1070 | goto fail_tx; | 880 | goto fail_tx; |
1071 | } | 881 | } |
1072 | 882 | ||
883 | ret = ath9k_htc_tx_start(priv, skb, slot, false); | ||
884 | if (ret != 0) { | ||
885 | ath_dbg(common, ATH_DBG_XMIT, "Tx failed\n"); | ||
886 | goto clear_slot; | ||
887 | } | ||
888 | |||
889 | ath9k_htc_check_stop_queues(priv); | ||
890 | |||
1073 | return; | 891 | return; |
1074 | 892 | ||
893 | clear_slot: | ||
894 | ath9k_htc_tx_clear_slot(priv, slot); | ||
1075 | fail_tx: | 895 | fail_tx: |
1076 | dev_kfree_skb_any(skb); | 896 | dev_kfree_skb_any(skb); |
1077 | } | 897 | } |
@@ -1122,7 +942,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1122 | 942 | ||
1123 | ath9k_host_rx_init(priv); | 943 | ath9k_host_rx_init(priv); |
1124 | 944 | ||
1125 | ret = ath9k_htc_update_cap_target(priv); | 945 | ret = ath9k_htc_update_cap_target(priv, 0); |
1126 | if (ret) | 946 | if (ret) |
1127 | ath_dbg(common, ATH_DBG_CONFIG, | 947 | ath_dbg(common, ATH_DBG_CONFIG, |
1128 | "Failed to update capability in target\n"); | 948 | "Failed to update capability in target\n"); |
@@ -1130,12 +950,15 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1130 | priv->op_flags &= ~OP_INVALID; | 950 | priv->op_flags &= ~OP_INVALID; |
1131 | htc_start(priv->htc); | 951 | htc_start(priv->htc); |
1132 | 952 | ||
1133 | spin_lock_bh(&priv->tx_lock); | 953 | spin_lock_bh(&priv->tx.tx_lock); |
1134 | priv->tx_queues_stop = false; | 954 | priv->tx.flags &= ~ATH9K_HTC_OP_TX_QUEUES_STOP; |
1135 | spin_unlock_bh(&priv->tx_lock); | 955 | spin_unlock_bh(&priv->tx.tx_lock); |
1136 | 956 | ||
1137 | ieee80211_wake_queues(hw); | 957 | ieee80211_wake_queues(hw); |
1138 | 958 | ||
959 | mod_timer(&priv->tx.cleanup_timer, | ||
960 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | ||
961 | |||
1139 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { | 962 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { |
1140 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | 963 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, |
1141 | AR_STOMP_LOW_WLAN_WGHT); | 964 | AR_STOMP_LOW_WLAN_WGHT); |
@@ -1152,7 +975,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1152 | struct ath9k_htc_priv *priv = hw->priv; | 975 | struct ath9k_htc_priv *priv = hw->priv; |
1153 | struct ath_hw *ah = priv->ah; | 976 | struct ath_hw *ah = priv->ah; |
1154 | struct ath_common *common = ath9k_hw_common(ah); | 977 | struct ath_common *common = ath9k_hw_common(ah); |
1155 | int ret = 0; | 978 | int ret __attribute__ ((unused)); |
1156 | u8 cmd_rsp; | 979 | u8 cmd_rsp; |
1157 | 980 | ||
1158 | mutex_lock(&priv->mutex); | 981 | mutex_lock(&priv->mutex); |
@@ -1164,25 +987,27 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1164 | } | 987 | } |
1165 | 988 | ||
1166 | ath9k_htc_ps_wakeup(priv); | 989 | ath9k_htc_ps_wakeup(priv); |
1167 | htc_stop(priv->htc); | 990 | |
1168 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 991 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
1169 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); | 992 | WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); |
1170 | WMI_CMD(WMI_STOP_RECV_CMDID); | 993 | WMI_CMD(WMI_STOP_RECV_CMDID); |
1171 | 994 | ||
1172 | tasklet_kill(&priv->swba_tasklet); | ||
1173 | tasklet_kill(&priv->rx_tasklet); | 995 | tasklet_kill(&priv->rx_tasklet); |
1174 | tasklet_kill(&priv->tx_tasklet); | ||
1175 | 996 | ||
1176 | skb_queue_purge(&priv->tx_queue); | 997 | del_timer_sync(&priv->tx.cleanup_timer); |
998 | ath9k_htc_tx_drain(priv); | ||
999 | ath9k_wmi_event_drain(priv); | ||
1177 | 1000 | ||
1178 | mutex_unlock(&priv->mutex); | 1001 | mutex_unlock(&priv->mutex); |
1179 | 1002 | ||
1180 | /* Cancel all the running timers/work .. */ | 1003 | /* Cancel all the running timers/work .. */ |
1181 | cancel_work_sync(&priv->fatal_work); | 1004 | cancel_work_sync(&priv->fatal_work); |
1182 | cancel_work_sync(&priv->ps_work); | 1005 | cancel_work_sync(&priv->ps_work); |
1183 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1006 | |
1007 | #ifdef CONFIG_MAC80211_LEDS | ||
1008 | cancel_work_sync(&priv->led_work); | ||
1009 | #endif | ||
1184 | ath9k_htc_stop_ani(priv); | 1010 | ath9k_htc_stop_ani(priv); |
1185 | ath9k_led_stop_brightness(priv); | ||
1186 | 1011 | ||
1187 | mutex_lock(&priv->mutex); | 1012 | mutex_lock(&priv->mutex); |
1188 | 1013 | ||
@@ -1245,13 +1070,13 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1245 | 1070 | ||
1246 | switch (vif->type) { | 1071 | switch (vif->type) { |
1247 | case NL80211_IFTYPE_STATION: | 1072 | case NL80211_IFTYPE_STATION: |
1248 | hvif.opmode = cpu_to_be32(HTC_M_STA); | 1073 | hvif.opmode = HTC_M_STA; |
1249 | break; | 1074 | break; |
1250 | case NL80211_IFTYPE_ADHOC: | 1075 | case NL80211_IFTYPE_ADHOC: |
1251 | hvif.opmode = cpu_to_be32(HTC_M_IBSS); | 1076 | hvif.opmode = HTC_M_IBSS; |
1252 | break; | 1077 | break; |
1253 | case NL80211_IFTYPE_AP: | 1078 | case NL80211_IFTYPE_AP: |
1254 | hvif.opmode = cpu_to_be32(HTC_M_HOSTAP); | 1079 | hvif.opmode = HTC_M_HOSTAP; |
1255 | break; | 1080 | break; |
1256 | default: | 1081 | default: |
1257 | ath_err(common, | 1082 | ath_err(common, |
@@ -1281,14 +1106,20 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1281 | 1106 | ||
1282 | priv->vif_slot |= (1 << avp->index); | 1107 | priv->vif_slot |= (1 << avp->index); |
1283 | priv->nvifs++; | 1108 | priv->nvifs++; |
1284 | priv->vif = vif; | ||
1285 | 1109 | ||
1286 | INC_VIF(priv, vif->type); | 1110 | INC_VIF(priv, vif->type); |
1111 | |||
1112 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1113 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1114 | ath9k_htc_assign_bslot(priv, vif); | ||
1115 | |||
1287 | ath9k_htc_set_opmode(priv); | 1116 | ath9k_htc_set_opmode(priv); |
1288 | 1117 | ||
1289 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | 1118 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1290 | !(priv->op_flags & OP_ANI_RUNNING)) | 1119 | !(priv->op_flags & OP_ANI_RUNNING)) { |
1120 | ath9k_hw_set_tsfadjust(priv->ah, 1); | ||
1291 | ath9k_htc_start_ani(priv); | 1121 | ath9k_htc_start_ani(priv); |
1122 | } | ||
1292 | 1123 | ||
1293 | ath_dbg(common, ATH_DBG_CONFIG, | 1124 | ath_dbg(common, ATH_DBG_CONFIG, |
1294 | "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); | 1125 | "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); |
@@ -1317,13 +1148,21 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1317 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | 1148 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
1318 | hvif.index = avp->index; | 1149 | hvif.index = avp->index; |
1319 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 1150 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
1151 | if (ret) { | ||
1152 | ath_err(common, "Unable to remove interface at idx: %d\n", | ||
1153 | avp->index); | ||
1154 | } | ||
1320 | priv->nvifs--; | 1155 | priv->nvifs--; |
1321 | priv->vif_slot &= ~(1 << avp->index); | 1156 | priv->vif_slot &= ~(1 << avp->index); |
1322 | 1157 | ||
1323 | ath9k_htc_remove_station(priv, vif, NULL); | 1158 | ath9k_htc_remove_station(priv, vif, NULL); |
1324 | priv->vif = NULL; | ||
1325 | 1159 | ||
1326 | DEC_VIF(priv, vif->type); | 1160 | DEC_VIF(priv, vif->type); |
1161 | |||
1162 | if ((vif->type == NL80211_IFTYPE_AP) || | ||
1163 | (vif->type == NL80211_IFTYPE_ADHOC)) | ||
1164 | ath9k_htc_remove_bslot(priv, vif); | ||
1165 | |||
1327 | ath9k_htc_set_opmode(priv); | 1166 | ath9k_htc_set_opmode(priv); |
1328 | 1167 | ||
1329 | /* | 1168 | /* |
@@ -1493,10 +1332,13 @@ static int ath9k_htc_sta_remove(struct ieee80211_hw *hw, | |||
1493 | struct ieee80211_sta *sta) | 1332 | struct ieee80211_sta *sta) |
1494 | { | 1333 | { |
1495 | struct ath9k_htc_priv *priv = hw->priv; | 1334 | struct ath9k_htc_priv *priv = hw->priv; |
1335 | struct ath9k_htc_sta *ista; | ||
1496 | int ret; | 1336 | int ret; |
1497 | 1337 | ||
1498 | mutex_lock(&priv->mutex); | 1338 | mutex_lock(&priv->mutex); |
1499 | ath9k_htc_ps_wakeup(priv); | 1339 | ath9k_htc_ps_wakeup(priv); |
1340 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | ||
1341 | htc_sta_drain(priv->htc, ista->index); | ||
1500 | ret = ath9k_htc_remove_station(priv, vif, sta); | 1342 | ret = ath9k_htc_remove_station(priv, vif, sta); |
1501 | ath9k_htc_ps_restore(priv); | 1343 | ath9k_htc_ps_restore(priv); |
1502 | mutex_unlock(&priv->mutex); | 1344 | mutex_unlock(&priv->mutex); |
@@ -1644,6 +1486,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1644 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { | 1486 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { |
1645 | ath_dbg(common, ATH_DBG_CONFIG, | 1487 | ath_dbg(common, ATH_DBG_CONFIG, |
1646 | "Beacon enabled for BSS: %pM\n", bss_conf->bssid); | 1488 | "Beacon enabled for BSS: %pM\n", bss_conf->bssid); |
1489 | ath9k_htc_set_tsfadjust(priv, vif); | ||
1647 | priv->op_flags |= OP_ENABLE_BEACON; | 1490 | priv->op_flags |= OP_ENABLE_BEACON; |
1648 | ath9k_htc_beacon_config(priv, vif); | 1491 | ath9k_htc_beacon_config(priv, vif); |
1649 | } | 1492 | } |
@@ -1741,6 +1584,7 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1741 | int ret = 0; | 1584 | int ret = 0; |
1742 | 1585 | ||
1743 | mutex_lock(&priv->mutex); | 1586 | mutex_lock(&priv->mutex); |
1587 | ath9k_htc_ps_wakeup(priv); | ||
1744 | 1588 | ||
1745 | switch (action) { | 1589 | switch (action) { |
1746 | case IEEE80211_AMPDU_RX_START: | 1590 | case IEEE80211_AMPDU_RX_START: |
@@ -1758,14 +1602,15 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1758 | break; | 1602 | break; |
1759 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 1603 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
1760 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 1604 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
1761 | spin_lock_bh(&priv->tx_lock); | 1605 | spin_lock_bh(&priv->tx.tx_lock); |
1762 | ista->tid_state[tid] = AGGR_OPERATIONAL; | 1606 | ista->tid_state[tid] = AGGR_OPERATIONAL; |
1763 | spin_unlock_bh(&priv->tx_lock); | 1607 | spin_unlock_bh(&priv->tx.tx_lock); |
1764 | break; | 1608 | break; |
1765 | default: | 1609 | default: |
1766 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); | 1610 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); |
1767 | } | 1611 | } |
1768 | 1612 | ||
1613 | ath9k_htc_ps_restore(priv); | ||
1769 | mutex_unlock(&priv->mutex); | 1614 | mutex_unlock(&priv->mutex); |
1770 | 1615 | ||
1771 | return ret; | 1616 | return ret; |
@@ -1816,6 +1661,55 @@ static void ath9k_htc_set_coverage_class(struct ieee80211_hw *hw, | |||
1816 | mutex_unlock(&priv->mutex); | 1661 | mutex_unlock(&priv->mutex); |
1817 | } | 1662 | } |
1818 | 1663 | ||
1664 | /* | ||
1665 | * Currently, this is used only for selecting the minimum rate | ||
1666 | * for management frames, rate selection for data frames remain | ||
1667 | * unaffected. | ||
1668 | */ | ||
1669 | static int ath9k_htc_set_bitrate_mask(struct ieee80211_hw *hw, | ||
1670 | struct ieee80211_vif *vif, | ||
1671 | const struct cfg80211_bitrate_mask *mask) | ||
1672 | { | ||
1673 | struct ath9k_htc_priv *priv = hw->priv; | ||
1674 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
1675 | struct ath9k_htc_target_rate_mask tmask; | ||
1676 | struct ath9k_htc_vif *avp = (void *)vif->drv_priv; | ||
1677 | int ret = 0; | ||
1678 | u8 cmd_rsp; | ||
1679 | |||
1680 | memset(&tmask, 0, sizeof(struct ath9k_htc_target_rate_mask)); | ||
1681 | |||
1682 | tmask.vif_index = avp->index; | ||
1683 | tmask.band = IEEE80211_BAND_2GHZ; | ||
1684 | tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_2GHZ].legacy); | ||
1685 | |||
1686 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); | ||
1687 | if (ret) { | ||
1688 | ath_err(common, | ||
1689 | "Unable to set 2G rate mask for " | ||
1690 | "interface at idx: %d\n", avp->index); | ||
1691 | goto out; | ||
1692 | } | ||
1693 | |||
1694 | tmask.band = IEEE80211_BAND_5GHZ; | ||
1695 | tmask.mask = cpu_to_be32(mask->control[IEEE80211_BAND_5GHZ].legacy); | ||
1696 | |||
1697 | WMI_CMD_BUF(WMI_BITRATE_MASK_CMDID, &tmask); | ||
1698 | if (ret) { | ||
1699 | ath_err(common, | ||
1700 | "Unable to set 5G rate mask for " | ||
1701 | "interface at idx: %d\n", avp->index); | ||
1702 | goto out; | ||
1703 | } | ||
1704 | |||
1705 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1706 | "Set bitrate masks: 0x%x, 0x%x\n", | ||
1707 | mask->control[IEEE80211_BAND_2GHZ].legacy, | ||
1708 | mask->control[IEEE80211_BAND_5GHZ].legacy); | ||
1709 | out: | ||
1710 | return ret; | ||
1711 | } | ||
1712 | |||
1819 | struct ieee80211_ops ath9k_htc_ops = { | 1713 | struct ieee80211_ops ath9k_htc_ops = { |
1820 | .tx = ath9k_htc_tx, | 1714 | .tx = ath9k_htc_tx, |
1821 | .start = ath9k_htc_start, | 1715 | .start = ath9k_htc_start, |
@@ -1838,4 +1732,5 @@ struct ieee80211_ops ath9k_htc_ops = { | |||
1838 | .set_rts_threshold = ath9k_htc_set_rts_threshold, | 1732 | .set_rts_threshold = ath9k_htc_set_rts_threshold, |
1839 | .rfkill_poll = ath9k_htc_rfkill_poll_state, | 1733 | .rfkill_poll = ath9k_htc_rfkill_poll_state, |
1840 | .set_coverage_class = ath9k_htc_set_coverage_class, | 1734 | .set_coverage_class = ath9k_htc_set_coverage_class, |
1735 | .set_bitrate_mask = ath9k_htc_set_bitrate_mask, | ||
1841 | }; | 1736 | }; |