diff options
author | David S. Miller <davem@davemloft.net> | 2011-03-04 15:48:25 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-03-04 15:48:25 -0500 |
commit | d72751ede1b9bf993d7bd3377305c8e9e36a3cc4 (patch) | |
tree | 27abaa49de7ff666dbf6bbcb0d7bae2b9f029a2d /drivers/net/wireless/ath | |
parent | 0a0e9ae1bd788bc19adc4d4ae08c98b233697402 (diff) | |
parent | 85a7045a90052749885e166f40af5e9140032287 (diff) |
Merge branch 'for-davem' of ssh://master.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/ath')
21 files changed, 769 insertions, 403 deletions
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 4f845f80c098..371e4ce49528 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -224,7 +224,7 @@ void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); | |||
224 | int ar9170_nag_limiter(struct ar9170 *ar); | 224 | int ar9170_nag_limiter(struct ar9170 *ar); |
225 | 225 | ||
226 | /* MAC */ | 226 | /* MAC */ |
227 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | 227 | void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); |
228 | int ar9170_init_mac(struct ar9170 *ar); | 228 | int ar9170_init_mac(struct ar9170 *ar); |
229 | int ar9170_set_qos(struct ar9170 *ar); | 229 | int ar9170_set_qos(struct ar9170 *ar); |
230 | int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); | 230 | int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index a9111e1161fd..b761fec0d721 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1475,7 +1475,7 @@ static void ar9170_tx(struct ar9170 *ar) | |||
1475 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); | 1475 | msecs_to_jiffies(AR9170_JANITOR_DELAY)); |
1476 | } | 1476 | } |
1477 | 1477 | ||
1478 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1478 | void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1479 | { | 1479 | { |
1480 | struct ar9170 *ar = hw->priv; | 1480 | struct ar9170 *ar = hw->priv; |
1481 | struct ieee80211_tx_info *info; | 1481 | struct ieee80211_tx_info *info; |
@@ -1493,11 +1493,10 @@ int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1493 | skb_queue_tail(&ar->tx_pending[queue], skb); | 1493 | skb_queue_tail(&ar->tx_pending[queue], skb); |
1494 | 1494 | ||
1495 | ar9170_tx(ar); | 1495 | ar9170_tx(ar); |
1496 | return NETDEV_TX_OK; | 1496 | return; |
1497 | 1497 | ||
1498 | err_free: | 1498 | err_free: |
1499 | dev_kfree_skb_any(skb); | 1499 | dev_kfree_skb_any(skb); |
1500 | return NETDEV_TX_OK; | ||
1501 | } | 1500 | } |
1502 | 1501 | ||
1503 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, | 1502 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index 70abb61e9eff..0ee54eb333de 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -1164,8 +1164,8 @@ struct ath5k_txq; | |||
1164 | 1164 | ||
1165 | void set_beacon_filter(struct ieee80211_hw *hw, bool enable); | 1165 | void set_beacon_filter(struct ieee80211_hw *hw, bool enable); |
1166 | bool ath_any_vif_assoc(struct ath5k_softc *sc); | 1166 | bool ath_any_vif_assoc(struct ath5k_softc *sc); |
1167 | int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | 1167 | void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, |
1168 | struct ath5k_txq *txq); | 1168 | struct ath5k_txq *txq); |
1169 | int ath5k_init_hw(struct ath5k_softc *sc); | 1169 | int ath5k_init_hw(struct ath5k_softc *sc); |
1170 | int ath5k_stop_hw(struct ath5k_softc *sc); | 1170 | int ath5k_stop_hw(struct ath5k_softc *sc); |
1171 | void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif); | 1171 | void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index dbc45e085434..91411e9b4b68 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1361,7 +1361,7 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1361 | * right now, so it's not too bad... | 1361 | * right now, so it's not too bad... |
1362 | */ | 1362 | */ |
1363 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); | 1363 | rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp); |
1364 | rxs->flag |= RX_FLAG_TSFT; | 1364 | rxs->flag |= RX_FLAG_MACTIME_MPDU; |
1365 | 1365 | ||
1366 | rxs->freq = sc->curchan->center_freq; | 1366 | rxs->freq = sc->curchan->center_freq; |
1367 | rxs->band = sc->curchan->band; | 1367 | rxs->band = sc->curchan->band; |
@@ -1518,7 +1518,7 @@ unlock: | |||
1518 | * TX Handling * | 1518 | * TX Handling * |
1519 | \*************/ | 1519 | \*************/ |
1520 | 1520 | ||
1521 | int | 1521 | void |
1522 | ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | 1522 | ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, |
1523 | struct ath5k_txq *txq) | 1523 | struct ath5k_txq *txq) |
1524 | { | 1524 | { |
@@ -1567,11 +1567,10 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1567 | spin_unlock_irqrestore(&sc->txbuflock, flags); | 1567 | spin_unlock_irqrestore(&sc->txbuflock, flags); |
1568 | goto drop_packet; | 1568 | goto drop_packet; |
1569 | } | 1569 | } |
1570 | return NETDEV_TX_OK; | 1570 | return; |
1571 | 1571 | ||
1572 | drop_packet: | 1572 | drop_packet: |
1573 | dev_kfree_skb_any(skb); | 1573 | dev_kfree_skb_any(skb); |
1574 | return NETDEV_TX_OK; | ||
1575 | } | 1574 | } |
1576 | 1575 | ||
1577 | static void | 1576 | static void |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index a60a726a140c..1fbe3c0b9f08 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -52,7 +52,7 @@ extern int ath5k_modparam_nohwcrypt; | |||
52 | * Mac80211 functions * | 52 | * Mac80211 functions * |
53 | \********************/ | 53 | \********************/ |
54 | 54 | ||
55 | static int | 55 | static void |
56 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 56 | ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
57 | { | 57 | { |
58 | struct ath5k_softc *sc = hw->priv; | 58 | struct ath5k_softc *sc = hw->priv; |
@@ -60,10 +60,10 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
60 | 60 | ||
61 | if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { | 61 | if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) { |
62 | dev_kfree_skb_any(skb); | 62 | dev_kfree_skb_any(skb); |
63 | return 0; | 63 | return; |
64 | } | 64 | } |
65 | 65 | ||
66 | return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); | 66 | ath5k_tx_queue(hw, skb, &sc->txqs[qnum]); |
67 | } | 67 | } |
68 | 68 | ||
69 | 69 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 6fa3c24af2da..7f5de6e4448b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -78,15 +78,15 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
78 | /* Awake Setting */ | 78 | /* Awake Setting */ |
79 | 79 | ||
80 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 80 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
81 | ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1, | 81 | ar9485_1_1_pcie_phy_clkreq_disable_L1, |
82 | ARRAY_SIZE(ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1), | 82 | ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), |
83 | 2); | 83 | 2); |
84 | 84 | ||
85 | /* Sleep Setting */ | 85 | /* Sleep Setting */ |
86 | 86 | ||
87 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 87 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
88 | ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1, | 88 | ar9485_1_1_pcie_phy_clkreq_disable_L1, |
89 | ARRAY_SIZE(ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1), | 89 | ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1), |
90 | 2); | 90 | 2); |
91 | } else if (AR_SREV_9485(ah)) { | 91 | } else if (AR_SREV_9485(ah)) { |
92 | /* mac */ | 92 | /* mac */ |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index f9f0389b92ab..c718ab512a97 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -449,26 +449,21 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); | |||
449 | 449 | ||
450 | #define ATH_LED_PIN_DEF 1 | 450 | #define ATH_LED_PIN_DEF 1 |
451 | #define ATH_LED_PIN_9287 8 | 451 | #define ATH_LED_PIN_9287 8 |
452 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ | 452 | #define ATH_LED_PIN_9485 6 |
453 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ | ||
454 | |||
455 | enum ath_led_type { | ||
456 | ATH_LED_RADIO, | ||
457 | ATH_LED_ASSOC, | ||
458 | ATH_LED_TX, | ||
459 | ATH_LED_RX | ||
460 | }; | ||
461 | |||
462 | struct ath_led { | ||
463 | struct ath_softc *sc; | ||
464 | struct led_classdev led_cdev; | ||
465 | enum ath_led_type led_type; | ||
466 | char name[32]; | ||
467 | bool registered; | ||
468 | }; | ||
469 | 453 | ||
454 | #ifdef CONFIG_MAC80211_LEDS | ||
470 | void ath_init_leds(struct ath_softc *sc); | 455 | void ath_init_leds(struct ath_softc *sc); |
471 | void ath_deinit_leds(struct ath_softc *sc); | 456 | void ath_deinit_leds(struct ath_softc *sc); |
457 | #else | ||
458 | static inline void ath_init_leds(struct ath_softc *sc) | ||
459 | { | ||
460 | } | ||
461 | |||
462 | static inline void ath_deinit_leds(struct ath_softc *sc) | ||
463 | { | ||
464 | } | ||
465 | #endif | ||
466 | |||
472 | 467 | ||
473 | /* Antenna diversity/combining */ | 468 | /* Antenna diversity/combining */ |
474 | #define ATH_ANT_RX_CURRENT_SHIFT 4 | 469 | #define ATH_ANT_RX_CURRENT_SHIFT 4 |
@@ -620,15 +615,11 @@ struct ath_softc { | |||
620 | struct ath_beacon beacon; | 615 | struct ath_beacon beacon; |
621 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 616 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
622 | 617 | ||
623 | struct ath_led radio_led; | 618 | #ifdef CONFIG_MAC80211_LEDS |
624 | struct ath_led assoc_led; | 619 | bool led_registered; |
625 | struct ath_led tx_led; | 620 | char led_name[32]; |
626 | struct ath_led rx_led; | 621 | struct led_classdev led_cdev; |
627 | struct delayed_work ath_led_blink_work; | 622 | #endif |
628 | int led_on_duration; | ||
629 | int led_off_duration; | ||
630 | int led_on_cnt; | ||
631 | int led_off_cnt; | ||
632 | 623 | ||
633 | struct ath9k_hw_cal_data caldata; | 624 | struct ath9k_hw_cal_data caldata; |
634 | int last_rssi; | 625 | int last_rssi; |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index fb4f17a5183d..0fb8f8ac275a 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -20,121 +20,31 @@ | |||
20 | /* LED functions */ | 20 | /* LED functions */ |
21 | /********************************/ | 21 | /********************************/ |
22 | 22 | ||
23 | static void ath_led_blink_work(struct work_struct *work) | 23 | #ifdef CONFIG_MAC80211_LEDS |
24 | { | ||
25 | struct ath_softc *sc = container_of(work, struct ath_softc, | ||
26 | ath_led_blink_work.work); | ||
27 | |||
28 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) | ||
29 | return; | ||
30 | |||
31 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | ||
32 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
33 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
34 | else | ||
35 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
36 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | ||
37 | |||
38 | ieee80211_queue_delayed_work(sc->hw, | ||
39 | &sc->ath_led_blink_work, | ||
40 | (sc->sc_flags & SC_OP_LED_ON) ? | ||
41 | msecs_to_jiffies(sc->led_off_duration) : | ||
42 | msecs_to_jiffies(sc->led_on_duration)); | ||
43 | |||
44 | sc->led_on_duration = sc->led_on_cnt ? | ||
45 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : | ||
46 | ATH_LED_ON_DURATION_IDLE; | ||
47 | sc->led_off_duration = sc->led_off_cnt ? | ||
48 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : | ||
49 | ATH_LED_OFF_DURATION_IDLE; | ||
50 | sc->led_on_cnt = sc->led_off_cnt = 0; | ||
51 | if (sc->sc_flags & SC_OP_LED_ON) | ||
52 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
53 | else | ||
54 | sc->sc_flags |= SC_OP_LED_ON; | ||
55 | } | ||
56 | |||
57 | static void ath_led_brightness(struct led_classdev *led_cdev, | 24 | static void ath_led_brightness(struct led_classdev *led_cdev, |
58 | enum led_brightness brightness) | 25 | enum led_brightness brightness) |
59 | { | 26 | { |
60 | struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); | 27 | struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); |
61 | struct ath_softc *sc = led->sc; | 28 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF)); |
62 | |||
63 | switch (brightness) { | ||
64 | case LED_OFF: | ||
65 | if (led->led_type == ATH_LED_ASSOC || | ||
66 | led->led_type == ATH_LED_RADIO) { | ||
67 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, | ||
68 | (led->led_type == ATH_LED_RADIO)); | ||
69 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | ||
70 | if (led->led_type == ATH_LED_RADIO) | ||
71 | sc->sc_flags &= ~SC_OP_LED_ON; | ||
72 | } else { | ||
73 | sc->led_off_cnt++; | ||
74 | } | ||
75 | break; | ||
76 | case LED_FULL: | ||
77 | if (led->led_type == ATH_LED_ASSOC) { | ||
78 | sc->sc_flags |= SC_OP_LED_ASSOCIATED; | ||
79 | if (led_blink) | ||
80 | ieee80211_queue_delayed_work(sc->hw, | ||
81 | &sc->ath_led_blink_work, 0); | ||
82 | } else if (led->led_type == ATH_LED_RADIO) { | ||
83 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); | ||
84 | sc->sc_flags |= SC_OP_LED_ON; | ||
85 | } else { | ||
86 | sc->led_on_cnt++; | ||
87 | } | ||
88 | break; | ||
89 | default: | ||
90 | break; | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static int ath_register_led(struct ath_softc *sc, struct ath_led *led, | ||
95 | char *trigger) | ||
96 | { | ||
97 | int ret; | ||
98 | |||
99 | led->sc = sc; | ||
100 | led->led_cdev.name = led->name; | ||
101 | led->led_cdev.default_trigger = trigger; | ||
102 | led->led_cdev.brightness_set = ath_led_brightness; | ||
103 | |||
104 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); | ||
105 | if (ret) | ||
106 | ath_err(ath9k_hw_common(sc->sc_ah), | ||
107 | "Failed to register led:%s", led->name); | ||
108 | else | ||
109 | led->registered = 1; | ||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static void ath_unregister_led(struct ath_led *led) | ||
114 | { | ||
115 | if (led->registered) { | ||
116 | led_classdev_unregister(&led->led_cdev); | ||
117 | led->registered = 0; | ||
118 | } | ||
119 | } | 29 | } |
120 | 30 | ||
121 | void ath_deinit_leds(struct ath_softc *sc) | 31 | void ath_deinit_leds(struct ath_softc *sc) |
122 | { | 32 | { |
123 | ath_unregister_led(&sc->assoc_led); | 33 | if (!sc->led_registered) |
124 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | 34 | return; |
125 | ath_unregister_led(&sc->tx_led); | 35 | |
126 | ath_unregister_led(&sc->rx_led); | 36 | ath_led_brightness(&sc->led_cdev, LED_OFF); |
127 | ath_unregister_led(&sc->radio_led); | 37 | led_classdev_unregister(&sc->led_cdev); |
128 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | ||
129 | } | 38 | } |
130 | 39 | ||
131 | void ath_init_leds(struct ath_softc *sc) | 40 | void ath_init_leds(struct ath_softc *sc) |
132 | { | 41 | { |
133 | char *trigger; | ||
134 | int ret; | 42 | int ret; |
135 | 43 | ||
136 | if (AR_SREV_9287(sc->sc_ah)) | 44 | if (AR_SREV_9287(sc->sc_ah)) |
137 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | 45 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; |
46 | else if (AR_SREV_9485(sc->sc_ah)) | ||
47 | sc->sc_ah->led_pin = ATH_LED_PIN_9485; | ||
138 | else | 48 | else |
139 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | 49 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; |
140 | 50 | ||
@@ -144,48 +54,22 @@ void ath_init_leds(struct ath_softc *sc) | |||
144 | /* LED off, active low */ | 54 | /* LED off, active low */ |
145 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); | 55 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
146 | 56 | ||
147 | if (led_blink) | 57 | if (!led_blink) |
148 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | 58 | sc->led_cdev.default_trigger = |
149 | 59 | ieee80211_get_radio_led_name(sc->hw); | |
150 | trigger = ieee80211_get_radio_led_name(sc->hw); | 60 | |
151 | snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), | 61 | snprintf(sc->led_name, sizeof(sc->led_name), |
152 | "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); | 62 | "ath9k-%s", wiphy_name(sc->hw->wiphy)); |
153 | ret = ath_register_led(sc, &sc->radio_led, trigger); | 63 | sc->led_cdev.name = sc->led_name; |
154 | sc->radio_led.led_type = ATH_LED_RADIO; | 64 | sc->led_cdev.brightness_set = ath_led_brightness; |
155 | if (ret) | 65 | |
156 | goto fail; | 66 | ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev); |
157 | 67 | if (ret < 0) | |
158 | trigger = ieee80211_get_assoc_led_name(sc->hw); | 68 | return; |
159 | snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), | 69 | |
160 | "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); | 70 | sc->led_registered = true; |
161 | ret = ath_register_led(sc, &sc->assoc_led, trigger); | ||
162 | sc->assoc_led.led_type = ATH_LED_ASSOC; | ||
163 | if (ret) | ||
164 | goto fail; | ||
165 | |||
166 | trigger = ieee80211_get_tx_led_name(sc->hw); | ||
167 | snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), | ||
168 | "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); | ||
169 | ret = ath_register_led(sc, &sc->tx_led, trigger); | ||
170 | sc->tx_led.led_type = ATH_LED_TX; | ||
171 | if (ret) | ||
172 | goto fail; | ||
173 | |||
174 | trigger = ieee80211_get_rx_led_name(sc->hw); | ||
175 | snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), | ||
176 | "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); | ||
177 | ret = ath_register_led(sc, &sc->rx_led, trigger); | ||
178 | sc->rx_led.led_type = ATH_LED_RX; | ||
179 | if (ret) | ||
180 | goto fail; | ||
181 | |||
182 | return; | ||
183 | |||
184 | fail: | ||
185 | if (led_blink) | ||
186 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
187 | ath_deinit_leds(sc); | ||
188 | } | 71 | } |
72 | #endif | ||
189 | 73 | ||
190 | /*******************/ | 74 | /*******************/ |
191 | /* Rfkill */ | 75 | /* Rfkill */ |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 07b1633b7f3f..f1b8af64569c 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -52,6 +52,9 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { | |||
52 | { USB_DEVICE(0x083A, 0xA704), | 52 | { USB_DEVICE(0x083A, 0xA704), |
53 | .driver_info = AR9280_USB }, /* SMC Networks */ | 53 | .driver_info = AR9280_USB }, /* SMC Networks */ |
54 | 54 | ||
55 | { USB_DEVICE(0x0cf3, 0x20ff), | ||
56 | .driver_info = STORAGE_DEVICE }, | ||
57 | |||
55 | { }, | 58 | { }, |
56 | }; | 59 | }; |
57 | 60 | ||
@@ -914,13 +917,11 @@ static int ath9k_hif_usb_dev_init(struct hif_device_usb *hif_dev, u32 drv_info) | |||
914 | if (ret) { | 917 | if (ret) { |
915 | dev_err(&hif_dev->udev->dev, | 918 | dev_err(&hif_dev->udev->dev, |
916 | "ath9k_htc: Unable to allocate URBs\n"); | 919 | "ath9k_htc: Unable to allocate URBs\n"); |
917 | goto err_urb; | 920 | goto err_fw_download; |
918 | } | 921 | } |
919 | 922 | ||
920 | return 0; | 923 | return 0; |
921 | 924 | ||
922 | err_urb: | ||
923 | ath9k_hif_usb_dealloc_urbs(hif_dev); | ||
924 | err_fw_download: | 925 | err_fw_download: |
925 | release_firmware(hif_dev->firmware); | 926 | release_firmware(hif_dev->firmware); |
926 | err_fw_req: | 927 | err_fw_req: |
@@ -935,6 +936,61 @@ static void ath9k_hif_usb_dev_deinit(struct hif_device_usb *hif_dev) | |||
935 | release_firmware(hif_dev->firmware); | 936 | release_firmware(hif_dev->firmware); |
936 | } | 937 | } |
937 | 938 | ||
939 | /* | ||
940 | * An exact copy of the function from zd1211rw. | ||
941 | */ | ||
942 | static int send_eject_command(struct usb_interface *interface) | ||
943 | { | ||
944 | struct usb_device *udev = interface_to_usbdev(interface); | ||
945 | struct usb_host_interface *iface_desc = &interface->altsetting[0]; | ||
946 | struct usb_endpoint_descriptor *endpoint; | ||
947 | unsigned char *cmd; | ||
948 | u8 bulk_out_ep; | ||
949 | int r; | ||
950 | |||
951 | /* Find bulk out endpoint */ | ||
952 | for (r = 1; r >= 0; r--) { | ||
953 | endpoint = &iface_desc->endpoint[r].desc; | ||
954 | if (usb_endpoint_dir_out(endpoint) && | ||
955 | usb_endpoint_xfer_bulk(endpoint)) { | ||
956 | bulk_out_ep = endpoint->bEndpointAddress; | ||
957 | break; | ||
958 | } | ||
959 | } | ||
960 | if (r == -1) { | ||
961 | dev_err(&udev->dev, | ||
962 | "ath9k_htc: Could not find bulk out endpoint\n"); | ||
963 | return -ENODEV; | ||
964 | } | ||
965 | |||
966 | cmd = kzalloc(31, GFP_KERNEL); | ||
967 | if (cmd == NULL) | ||
968 | return -ENODEV; | ||
969 | |||
970 | /* USB bulk command block */ | ||
971 | cmd[0] = 0x55; /* bulk command signature */ | ||
972 | cmd[1] = 0x53; /* bulk command signature */ | ||
973 | cmd[2] = 0x42; /* bulk command signature */ | ||
974 | cmd[3] = 0x43; /* bulk command signature */ | ||
975 | cmd[14] = 6; /* command length */ | ||
976 | |||
977 | cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */ | ||
978 | cmd[19] = 0x2; /* eject disc */ | ||
979 | |||
980 | dev_info(&udev->dev, "Ejecting storage device...\n"); | ||
981 | r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), | ||
982 | cmd, 31, NULL, 2000); | ||
983 | kfree(cmd); | ||
984 | if (r) | ||
985 | return r; | ||
986 | |||
987 | /* At this point, the device disconnects and reconnects with the real | ||
988 | * ID numbers. */ | ||
989 | |||
990 | usb_set_intfdata(interface, NULL); | ||
991 | return 0; | ||
992 | } | ||
993 | |||
938 | static int ath9k_hif_usb_probe(struct usb_interface *interface, | 994 | static int ath9k_hif_usb_probe(struct usb_interface *interface, |
939 | const struct usb_device_id *id) | 995 | const struct usb_device_id *id) |
940 | { | 996 | { |
@@ -942,6 +998,9 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
942 | struct hif_device_usb *hif_dev; | 998 | struct hif_device_usb *hif_dev; |
943 | int ret = 0; | 999 | int ret = 0; |
944 | 1000 | ||
1001 | if (id->driver_info == STORAGE_DEVICE) | ||
1002 | return send_eject_command(interface); | ||
1003 | |||
945 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); | 1004 | hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL); |
946 | if (!hif_dev) { | 1005 | if (!hif_dev) { |
947 | ret = -ENOMEM; | 1006 | ret = -ENOMEM; |
@@ -1028,12 +1087,13 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface) | |||
1028 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); | 1087 | struct hif_device_usb *hif_dev = usb_get_intfdata(interface); |
1029 | bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; | 1088 | bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false; |
1030 | 1089 | ||
1031 | if (hif_dev) { | 1090 | if (!hif_dev) |
1032 | ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); | 1091 | return; |
1033 | ath9k_htc_hw_free(hif_dev->htc_handle); | 1092 | |
1034 | ath9k_hif_usb_dev_deinit(hif_dev); | 1093 | ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged); |
1035 | usb_set_intfdata(interface, NULL); | 1094 | ath9k_htc_hw_free(hif_dev->htc_handle); |
1036 | } | 1095 | ath9k_hif_usb_dev_deinit(hif_dev); |
1096 | usb_set_intfdata(interface, NULL); | ||
1037 | 1097 | ||
1038 | if (!unplugged && (hif_dev->flags & HIF_USB_START)) | 1098 | if (!unplugged && (hif_dev->flags & HIF_USB_START)) |
1039 | ath9k_hif_usb_reboot(udev); | 1099 | ath9k_hif_usb_reboot(udev); |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 0cb504d7b8c4..753a245c5ad1 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "wmi.h" | 32 | #include "wmi.h" |
33 | 33 | ||
34 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ | 34 | #define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ |
35 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | ||
35 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ | 36 | #define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ |
36 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 37 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
37 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 38 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
@@ -204,8 +205,50 @@ struct ath9k_htc_target_stats { | |||
204 | __be32 ht_tx_xretries; | 205 | __be32 ht_tx_xretries; |
205 | } __packed; | 206 | } __packed; |
206 | 207 | ||
208 | #define ATH9K_HTC_MAX_VIF 2 | ||
209 | #define ATH9K_HTC_MAX_BCN_VIF 2 | ||
210 | |||
211 | #define INC_VIF(_priv, _type) do { \ | ||
212 | switch (_type) { \ | ||
213 | case NL80211_IFTYPE_STATION: \ | ||
214 | _priv->num_sta_vif++; \ | ||
215 | break; \ | ||
216 | case NL80211_IFTYPE_ADHOC: \ | ||
217 | _priv->num_ibss_vif++; \ | ||
218 | break; \ | ||
219 | case NL80211_IFTYPE_AP: \ | ||
220 | _priv->num_ap_vif++; \ | ||
221 | break; \ | ||
222 | default: \ | ||
223 | break; \ | ||
224 | } \ | ||
225 | } while (0) | ||
226 | |||
227 | #define DEC_VIF(_priv, _type) do { \ | ||
228 | switch (_type) { \ | ||
229 | case NL80211_IFTYPE_STATION: \ | ||
230 | _priv->num_sta_vif--; \ | ||
231 | break; \ | ||
232 | case NL80211_IFTYPE_ADHOC: \ | ||
233 | _priv->num_ibss_vif--; \ | ||
234 | break; \ | ||
235 | case NL80211_IFTYPE_AP: \ | ||
236 | _priv->num_ap_vif--; \ | ||
237 | break; \ | ||
238 | default: \ | ||
239 | break; \ | ||
240 | } \ | ||
241 | } while (0) | ||
242 | |||
207 | struct ath9k_htc_vif { | 243 | struct ath9k_htc_vif { |
208 | u8 index; | 244 | u8 index; |
245 | u16 seq_no; | ||
246 | bool beacon_configured; | ||
247 | }; | ||
248 | |||
249 | struct ath9k_vif_iter_data { | ||
250 | const u8 *hw_macaddr; | ||
251 | u8 mask[ETH_ALEN]; | ||
209 | }; | 252 | }; |
210 | 253 | ||
211 | #define ATH9K_HTC_MAX_STA 8 | 254 | #define ATH9K_HTC_MAX_STA 8 |
@@ -310,10 +353,8 @@ struct ath_led { | |||
310 | 353 | ||
311 | struct htc_beacon_config { | 354 | struct htc_beacon_config { |
312 | u16 beacon_interval; | 355 | u16 beacon_interval; |
313 | u16 listen_interval; | ||
314 | u16 dtim_period; | 356 | u16 dtim_period; |
315 | u16 bmiss_timeout; | 357 | u16 bmiss_timeout; |
316 | u8 dtim_count; | ||
317 | }; | 358 | }; |
318 | 359 | ||
319 | struct ath_btcoex { | 360 | struct ath_btcoex { |
@@ -333,13 +374,12 @@ void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); | |||
333 | #define OP_SCANNING BIT(1) | 374 | #define OP_SCANNING BIT(1) |
334 | #define OP_LED_ASSOCIATED BIT(2) | 375 | #define OP_LED_ASSOCIATED BIT(2) |
335 | #define OP_LED_ON BIT(3) | 376 | #define OP_LED_ON BIT(3) |
336 | #define OP_PREAMBLE_SHORT BIT(4) | 377 | #define OP_ENABLE_BEACON BIT(4) |
337 | #define OP_PROTECT_ENABLE BIT(5) | 378 | #define OP_LED_DEINIT BIT(5) |
338 | #define OP_ASSOCIATED BIT(6) | 379 | #define OP_BT_PRIORITY_DETECTED BIT(6) |
339 | #define OP_ENABLE_BEACON BIT(7) | 380 | #define OP_BT_SCAN BIT(7) |
340 | #define OP_LED_DEINIT BIT(8) | 381 | #define OP_ANI_RUNNING BIT(8) |
341 | #define OP_BT_PRIORITY_DETECTED BIT(9) | 382 | #define OP_TSF_RESET BIT(9) |
342 | #define OP_BT_SCAN BIT(10) | ||
343 | 383 | ||
344 | struct ath9k_htc_priv { | 384 | struct ath9k_htc_priv { |
345 | struct device *dev; | 385 | struct device *dev; |
@@ -358,13 +398,22 @@ struct ath9k_htc_priv { | |||
358 | enum htc_endpoint_id data_vi_ep; | 398 | enum htc_endpoint_id data_vi_ep; |
359 | enum htc_endpoint_id data_vo_ep; | 399 | enum htc_endpoint_id data_vo_ep; |
360 | 400 | ||
401 | u8 vif_slot; | ||
402 | u8 mon_vif_idx; | ||
403 | u8 sta_slot; | ||
404 | u8 vif_sta_pos[ATH9K_HTC_MAX_VIF]; | ||
405 | u8 num_ibss_vif; | ||
406 | u8 num_sta_vif; | ||
407 | u8 num_ap_vif; | ||
408 | |||
361 | u16 op_flags; | 409 | u16 op_flags; |
362 | u16 curtxpow; | 410 | u16 curtxpow; |
363 | u16 txpowlimit; | 411 | u16 txpowlimit; |
364 | u16 nvifs; | 412 | u16 nvifs; |
365 | u16 nstations; | 413 | u16 nstations; |
366 | u16 seq_no; | ||
367 | u32 bmiss_cnt; | 414 | u32 bmiss_cnt; |
415 | bool rearm_ani; | ||
416 | bool reconfig_beacon; | ||
368 | 417 | ||
369 | struct ath9k_hw_cal_data caldata; | 418 | struct ath9k_hw_cal_data caldata; |
370 | 419 | ||
@@ -382,7 +431,7 @@ struct ath9k_htc_priv { | |||
382 | struct ath9k_htc_rx rx; | 431 | struct ath9k_htc_rx rx; |
383 | struct tasklet_struct tx_tasklet; | 432 | struct tasklet_struct tx_tasklet; |
384 | struct sk_buff_head tx_queue; | 433 | struct sk_buff_head tx_queue; |
385 | struct delayed_work ath9k_ani_work; | 434 | struct delayed_work ani_work; |
386 | struct work_struct ps_work; | 435 | struct work_struct ps_work; |
387 | struct work_struct fatal_work; | 436 | struct work_struct fatal_work; |
388 | 437 | ||
@@ -424,6 +473,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv); | |||
424 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); | 473 | void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv); |
425 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 474 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
426 | struct ieee80211_vif *vif); | 475 | struct ieee80211_vif *vif); |
476 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv); | ||
427 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); | 477 | void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending); |
428 | 478 | ||
429 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, | 479 | void ath9k_htc_rxep(void *priv, struct sk_buff *skb, |
@@ -436,8 +486,9 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb, | |||
436 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv); | 486 | int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv); |
437 | void ath9k_htc_station_work(struct work_struct *work); | 487 | void ath9k_htc_station_work(struct work_struct *work); |
438 | void ath9k_htc_aggr_work(struct work_struct *work); | 488 | void ath9k_htc_aggr_work(struct work_struct *work); |
439 | void ath9k_ani_work(struct work_struct *work);; | 489 | void ath9k_htc_ani_work(struct work_struct *work); |
440 | void ath_start_ani(struct ath9k_htc_priv *priv); | 490 | void ath9k_htc_start_ani(struct ath9k_htc_priv *priv); |
491 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); | ||
441 | 492 | ||
442 | int ath9k_tx_init(struct ath9k_htc_priv *priv); | 493 | int ath9k_tx_init(struct ath9k_htc_priv *priv); |
443 | void ath9k_tx_tasklet(unsigned long data); | 494 | void ath9k_tx_tasklet(unsigned long data); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index 87cc65a78a3f..8d1d8792436d 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c | |||
@@ -123,8 +123,9 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
123 | /* TSF out of range threshold fixed at 1 second */ | 123 | /* TSF out of range threshold fixed at 1 second */ |
124 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; | 124 | bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; |
125 | 125 | ||
126 | ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); | 126 | ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n", |
127 | ath_dbg(common, ATH_DBG_BEACON, | 127 | intval, tsf, tsftu); |
128 | ath_dbg(common, ATH_DBG_CONFIG, | ||
128 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", | 129 | "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", |
129 | bs.bs_bmissthreshold, bs.bs_sleepduration, | 130 | bs.bs_bmissthreshold, bs.bs_sleepduration, |
130 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); | 131 | bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); |
@@ -138,25 +139,81 @@ static void ath9k_htc_beacon_config_sta(struct ath9k_htc_priv *priv, | |||
138 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | 139 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); |
139 | } | 140 | } |
140 | 141 | ||
142 | static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv, | ||
143 | struct htc_beacon_config *bss_conf) | ||
144 | { | ||
145 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
146 | enum ath9k_int imask = 0; | ||
147 | u32 nexttbtt, intval, tsftu; | ||
148 | __be32 htc_imask = 0; | ||
149 | int ret; | ||
150 | u8 cmd_rsp; | ||
151 | u64 tsf; | ||
152 | |||
153 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; | ||
154 | intval /= ATH9K_HTC_MAX_BCN_VIF; | ||
155 | nexttbtt = intval; | ||
156 | |||
157 | if (priv->op_flags & OP_TSF_RESET) { | ||
158 | intval |= ATH9K_BEACON_RESET_TSF; | ||
159 | priv->op_flags &= ~OP_TSF_RESET; | ||
160 | } else { | ||
161 | /* | ||
162 | * Pull nexttbtt forward to reflect the current TSF. | ||
163 | */ | ||
164 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
165 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
166 | do { | ||
167 | nexttbtt += intval; | ||
168 | } while (nexttbtt < tsftu); | ||
169 | } | ||
170 | |||
171 | intval |= ATH9K_BEACON_ENA; | ||
172 | |||
173 | if (priv->op_flags & OP_ENABLE_BEACON) | ||
174 | imask |= ATH9K_INT_SWBA; | ||
175 | |||
176 | ath_dbg(common, ATH_DBG_CONFIG, | ||
177 | "AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n", | ||
178 | bss_conf->beacon_interval, nexttbtt, imask); | ||
179 | |||
180 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | ||
181 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); | ||
182 | priv->bmiss_cnt = 0; | ||
183 | htc_imask = cpu_to_be32(imask); | ||
184 | WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask); | ||
185 | } | ||
186 | |||
141 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, | 187 | static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv, |
142 | struct htc_beacon_config *bss_conf) | 188 | struct htc_beacon_config *bss_conf) |
143 | { | 189 | { |
144 | struct ath_common *common = ath9k_hw_common(priv->ah); | 190 | struct ath_common *common = ath9k_hw_common(priv->ah); |
145 | enum ath9k_int imask = 0; | 191 | enum ath9k_int imask = 0; |
146 | u32 nexttbtt, intval; | 192 | u32 nexttbtt, intval, tsftu; |
147 | __be32 htc_imask = 0; | 193 | __be32 htc_imask = 0; |
148 | int ret; | 194 | int ret; |
149 | u8 cmd_rsp; | 195 | u8 cmd_rsp; |
196 | u64 tsf; | ||
150 | 197 | ||
151 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; | 198 | intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD; |
152 | nexttbtt = intval; | 199 | nexttbtt = intval; |
200 | |||
201 | /* | ||
202 | * Pull nexttbtt forward to reflect the current TSF. | ||
203 | */ | ||
204 | tsf = ath9k_hw_gettsf64(priv->ah); | ||
205 | tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE; | ||
206 | do { | ||
207 | nexttbtt += intval; | ||
208 | } while (nexttbtt < tsftu); | ||
209 | |||
153 | intval |= ATH9K_BEACON_ENA; | 210 | intval |= ATH9K_BEACON_ENA; |
154 | if (priv->op_flags & OP_ENABLE_BEACON) | 211 | if (priv->op_flags & OP_ENABLE_BEACON) |
155 | imask |= ATH9K_INT_SWBA; | 212 | imask |= ATH9K_INT_SWBA; |
156 | 213 | ||
157 | ath_dbg(common, ATH_DBG_BEACON, | 214 | ath_dbg(common, ATH_DBG_CONFIG, |
158 | "IBSS Beacon config, intval: %d, imask: 0x%x\n", | 215 | "IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n", |
159 | bss_conf->beacon_interval, imask); | 216 | bss_conf->beacon_interval, nexttbtt, imask); |
160 | 217 | ||
161 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 218 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
162 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); | 219 | ath9k_hw_beaconinit(priv->ah, nexttbtt, intval); |
@@ -207,9 +264,9 @@ void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending) | |||
207 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 264 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
208 | struct ieee80211_hdr *hdr = | 265 | struct ieee80211_hdr *hdr = |
209 | (struct ieee80211_hdr *) beacon->data; | 266 | (struct ieee80211_hdr *) beacon->data; |
210 | priv->seq_no += 0x10; | 267 | avp->seq_no += 0x10; |
211 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 268 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
212 | hdr->seq_ctrl |= cpu_to_le16(priv->seq_no); | 269 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); |
213 | } | 270 | } |
214 | 271 | ||
215 | tx_ctl.type = ATH9K_HTC_NORMAL; | 272 | tx_ctl.type = ATH9K_HTC_NORMAL; |
@@ -253,30 +310,123 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) | |||
253 | } | 310 | } |
254 | } | 311 | } |
255 | 312 | ||
313 | static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
314 | { | ||
315 | bool *beacon_configured = (bool *)data; | ||
316 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
317 | |||
318 | if (vif->type == NL80211_IFTYPE_STATION && | ||
319 | avp->beacon_configured) | ||
320 | *beacon_configured = true; | ||
321 | } | ||
322 | |||
323 | static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv, | ||
324 | struct ieee80211_vif *vif) | ||
325 | { | ||
326 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
327 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
328 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
329 | bool beacon_configured; | ||
330 | |||
331 | /* | ||
332 | * Changing the beacon interval when multiple AP interfaces | ||
333 | * are configured will affect beacon transmission of all | ||
334 | * of them. | ||
335 | */ | ||
336 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | ||
337 | (priv->num_ap_vif > 1) && | ||
338 | (vif->type == NL80211_IFTYPE_AP) && | ||
339 | (cur_conf->beacon_interval != bss_conf->beacon_int)) { | ||
340 | ath_dbg(common, ATH_DBG_CONFIG, | ||
341 | "Changing beacon interval of multiple AP interfaces !\n"); | ||
342 | return false; | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * If the HW is operating in AP mode, any new station interfaces that | ||
347 | * are added cannot change the beacon parameters. | ||
348 | */ | ||
349 | if (priv->num_ap_vif && | ||
350 | (vif->type != NL80211_IFTYPE_AP)) { | ||
351 | ath_dbg(common, ATH_DBG_CONFIG, | ||
352 | "HW in AP mode, cannot set STA beacon parameters\n"); | ||
353 | return false; | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * The beacon parameters are configured only for the first | ||
358 | * station interface. | ||
359 | */ | ||
360 | if ((priv->ah->opmode == NL80211_IFTYPE_STATION) && | ||
361 | (priv->num_sta_vif > 1) && | ||
362 | (vif->type == NL80211_IFTYPE_STATION)) { | ||
363 | beacon_configured = false; | ||
364 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
365 | ath9k_htc_beacon_iter, | ||
366 | &beacon_configured); | ||
367 | |||
368 | if (beacon_configured) { | ||
369 | ath_dbg(common, ATH_DBG_CONFIG, | ||
370 | "Beacon already configured for a station interface\n"); | ||
371 | return false; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | return true; | ||
376 | } | ||
377 | |||
256 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, | 378 | void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv, |
257 | struct ieee80211_vif *vif) | 379 | struct ieee80211_vif *vif) |
258 | { | 380 | { |
259 | struct ath_common *common = ath9k_hw_common(priv->ah); | 381 | struct ath_common *common = ath9k_hw_common(priv->ah); |
260 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | 382 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; |
261 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 383 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
384 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
385 | |||
386 | if (!ath9k_htc_check_beacon_config(priv, vif)) | ||
387 | return; | ||
262 | 388 | ||
263 | cur_conf->beacon_interval = bss_conf->beacon_int; | 389 | cur_conf->beacon_interval = bss_conf->beacon_int; |
264 | if (cur_conf->beacon_interval == 0) | 390 | if (cur_conf->beacon_interval == 0) |
265 | cur_conf->beacon_interval = 100; | 391 | cur_conf->beacon_interval = 100; |
266 | 392 | ||
267 | cur_conf->dtim_period = bss_conf->dtim_period; | 393 | cur_conf->dtim_period = bss_conf->dtim_period; |
268 | cur_conf->listen_interval = 1; | ||
269 | cur_conf->dtim_count = 1; | ||
270 | cur_conf->bmiss_timeout = | 394 | cur_conf->bmiss_timeout = |
271 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; | 395 | ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; |
272 | 396 | ||
273 | switch (vif->type) { | 397 | switch (vif->type) { |
274 | case NL80211_IFTYPE_STATION: | 398 | case NL80211_IFTYPE_STATION: |
275 | ath9k_htc_beacon_config_sta(priv, cur_conf); | 399 | ath9k_htc_beacon_config_sta(priv, cur_conf); |
400 | avp->beacon_configured = true; | ||
401 | break; | ||
402 | case NL80211_IFTYPE_ADHOC: | ||
403 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); | ||
404 | break; | ||
405 | case NL80211_IFTYPE_AP: | ||
406 | ath9k_htc_beacon_config_ap(priv, cur_conf); | ||
407 | break; | ||
408 | default: | ||
409 | ath_dbg(common, ATH_DBG_CONFIG, | ||
410 | "Unsupported beaconing mode\n"); | ||
411 | return; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv) | ||
416 | { | ||
417 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
418 | struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf; | ||
419 | |||
420 | switch (priv->ah->opmode) { | ||
421 | case NL80211_IFTYPE_STATION: | ||
422 | ath9k_htc_beacon_config_sta(priv, cur_conf); | ||
276 | break; | 423 | break; |
277 | case NL80211_IFTYPE_ADHOC: | 424 | case NL80211_IFTYPE_ADHOC: |
278 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); | 425 | ath9k_htc_beacon_config_adhoc(priv, cur_conf); |
279 | break; | 426 | break; |
427 | case NL80211_IFTYPE_AP: | ||
428 | ath9k_htc_beacon_config_ap(priv, cur_conf); | ||
429 | break; | ||
280 | default: | 430 | default: |
281 | ath_dbg(common, ATH_DBG_CONFIG, | 431 | ath_dbg(common, ATH_DBG_CONFIG, |
282 | "Unsupported beaconing mode\n"); | 432 | "Unsupported beaconing mode\n"); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index a7bc26d1bd66..fc67c937e172 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -679,7 +679,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
679 | (unsigned long)priv); | 679 | (unsigned long)priv); |
680 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, | 680 | tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet, |
681 | (unsigned long)priv); | 681 | (unsigned long)priv); |
682 | INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work); | 682 | INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work); |
683 | INIT_WORK(&priv->ps_work, ath9k_ps_work); | 683 | INIT_WORK(&priv->ps_work, ath9k_ps_work); |
684 | INIT_WORK(&priv->fatal_work, ath9k_fatal_work); | 684 | INIT_WORK(&priv->fatal_work, ath9k_fatal_work); |
685 | 685 | ||
@@ -787,6 +787,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, | |||
787 | struct ath_hw *ah; | 787 | struct ath_hw *ah; |
788 | int error = 0; | 788 | int error = 0; |
789 | struct ath_regulatory *reg; | 789 | struct ath_regulatory *reg; |
790 | char hw_name[64]; | ||
790 | 791 | ||
791 | /* Bring up device */ | 792 | /* Bring up device */ |
792 | error = ath9k_init_priv(priv, devid, product, drv_info); | 793 | error = ath9k_init_priv(priv, devid, product, drv_info); |
@@ -827,6 +828,22 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, | |||
827 | goto err_world; | 828 | goto err_world; |
828 | } | 829 | } |
829 | 830 | ||
831 | ath_dbg(common, ATH_DBG_CONFIG, | ||
832 | "WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, " | ||
833 | "BE:%d, BK:%d, VI:%d, VO:%d\n", | ||
834 | priv->wmi_cmd_ep, | ||
835 | priv->beacon_ep, | ||
836 | priv->cab_ep, | ||
837 | priv->uapsd_ep, | ||
838 | priv->mgmt_ep, | ||
839 | priv->data_be_ep, | ||
840 | priv->data_bk_ep, | ||
841 | priv->data_vi_ep, | ||
842 | priv->data_vo_ep); | ||
843 | |||
844 | ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name)); | ||
845 | wiphy_info(hw->wiphy, "%s\n", hw_name); | ||
846 | |||
830 | ath9k_init_leds(priv); | 847 | ath9k_init_leds(priv); |
831 | ath9k_start_rfkill_poll(priv); | 848 | ath9k_start_rfkill_poll(priv); |
832 | 849 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 50fde0e10595..db8c0c044e9e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -105,6 +105,82 @@ void ath9k_ps_work(struct work_struct *work) | |||
105 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); | 105 | ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP); |
106 | } | 106 | } |
107 | 107 | ||
108 | static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
109 | { | ||
110 | struct ath9k_htc_priv *priv = data; | ||
111 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | ||
112 | |||
113 | if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon) | ||
114 | priv->reconfig_beacon = true; | ||
115 | |||
116 | if (bss_conf->assoc) { | ||
117 | priv->rearm_ani = true; | ||
118 | priv->reconfig_beacon = true; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv) | ||
123 | { | ||
124 | priv->rearm_ani = false; | ||
125 | priv->reconfig_beacon = false; | ||
126 | |||
127 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
128 | ath9k_htc_vif_iter, priv); | ||
129 | if (priv->rearm_ani) | ||
130 | ath9k_htc_start_ani(priv); | ||
131 | |||
132 | if (priv->reconfig_beacon) { | ||
133 | ath9k_htc_ps_wakeup(priv); | ||
134 | ath9k_htc_beacon_reconfig(priv); | ||
135 | ath9k_htc_ps_restore(priv); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | ||
140 | { | ||
141 | struct ath9k_vif_iter_data *iter_data = data; | ||
142 | int i; | ||
143 | |||
144 | for (i = 0; i < ETH_ALEN; i++) | ||
145 | iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); | ||
146 | } | ||
147 | |||
148 | static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, | ||
149 | struct ieee80211_vif *vif) | ||
150 | { | ||
151 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
152 | struct ath9k_vif_iter_data iter_data; | ||
153 | |||
154 | /* | ||
155 | * Use the hardware MAC address as reference, the hardware uses it | ||
156 | * together with the BSSID mask when matching addresses. | ||
157 | */ | ||
158 | iter_data.hw_macaddr = common->macaddr; | ||
159 | memset(&iter_data.mask, 0xff, ETH_ALEN); | ||
160 | |||
161 | if (vif) | ||
162 | ath9k_htc_bssid_iter(&iter_data, vif->addr, vif); | ||
163 | |||
164 | /* Get list of all active MAC addresses */ | ||
165 | ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter, | ||
166 | &iter_data); | ||
167 | |||
168 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | ||
169 | ath_hw_setbssidmask(common); | ||
170 | } | ||
171 | |||
172 | static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv) | ||
173 | { | ||
174 | if (priv->num_ibss_vif) | ||
175 | priv->ah->opmode = NL80211_IFTYPE_ADHOC; | ||
176 | else if (priv->num_ap_vif) | ||
177 | priv->ah->opmode = NL80211_IFTYPE_AP; | ||
178 | else | ||
179 | priv->ah->opmode = NL80211_IFTYPE_STATION; | ||
180 | |||
181 | ath9k_hw_setopmode(priv->ah); | ||
182 | } | ||
183 | |||
108 | void ath9k_htc_reset(struct ath9k_htc_priv *priv) | 184 | void ath9k_htc_reset(struct ath9k_htc_priv *priv) |
109 | { | 185 | { |
110 | struct ath_hw *ah = priv->ah; | 186 | struct ath_hw *ah = priv->ah; |
@@ -119,9 +195,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
119 | mutex_lock(&priv->mutex); | 195 | mutex_lock(&priv->mutex); |
120 | ath9k_htc_ps_wakeup(priv); | 196 | ath9k_htc_ps_wakeup(priv); |
121 | 197 | ||
122 | if (priv->op_flags & OP_ASSOCIATED) | 198 | ath9k_htc_stop_ani(priv); |
123 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
124 | |||
125 | ieee80211_stop_queues(priv->hw); | 199 | ieee80211_stop_queues(priv->hw); |
126 | htc_stop(priv->htc); | 200 | htc_stop(priv->htc); |
127 | WMI_CMD(WMI_DISABLE_INTR_CMDID); | 201 | WMI_CMD(WMI_DISABLE_INTR_CMDID); |
@@ -148,12 +222,7 @@ void ath9k_htc_reset(struct ath9k_htc_priv *priv) | |||
148 | 222 | ||
149 | WMI_CMD(WMI_ENABLE_INTR_CMDID); | 223 | WMI_CMD(WMI_ENABLE_INTR_CMDID); |
150 | htc_start(priv->htc); | 224 | htc_start(priv->htc); |
151 | 225 | ath9k_htc_vif_reconfig(priv); | |
152 | if (priv->op_flags & OP_ASSOCIATED) { | ||
153 | ath9k_htc_beacon_config(priv, priv->vif); | ||
154 | ath_start_ani(priv); | ||
155 | } | ||
156 | |||
157 | ieee80211_wake_queues(priv->hw); | 226 | ieee80211_wake_queues(priv->hw); |
158 | 227 | ||
159 | ath9k_htc_ps_restore(priv); | 228 | ath9k_htc_ps_restore(priv); |
@@ -222,11 +291,23 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
222 | goto err; | 291 | goto err; |
223 | 292 | ||
224 | htc_start(priv->htc); | 293 | htc_start(priv->htc); |
294 | |||
295 | if (!(priv->op_flags & OP_SCANNING) && | ||
296 | !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | ||
297 | ath9k_htc_vif_reconfig(priv); | ||
298 | |||
225 | err: | 299 | err: |
226 | ath9k_htc_ps_restore(priv); | 300 | ath9k_htc_ps_restore(priv); |
227 | return ret; | 301 | return ret; |
228 | } | 302 | } |
229 | 303 | ||
304 | /* | ||
305 | * Monitor mode handling is a tad complicated because the firmware requires | ||
306 | * an interface to be created exclusively, while mac80211 doesn't associate | ||
307 | * an interface with the mode. | ||
308 | * | ||
309 | * So, for now, only one monitor interface can be configured. | ||
310 | */ | ||
230 | static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | 311 | static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) |
231 | { | 312 | { |
232 | struct ath_common *common = ath9k_hw_common(priv->ah); | 313 | struct ath_common *common = ath9k_hw_common(priv->ah); |
@@ -236,9 +317,10 @@ static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | |||
236 | 317 | ||
237 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 318 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
238 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 319 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
239 | hvif.index = 0; /* Should do for now */ | 320 | hvif.index = priv->mon_vif_idx; |
240 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 321 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
241 | priv->nvifs--; | 322 | priv->nvifs--; |
323 | priv->vif_slot &= ~(1 << priv->mon_vif_idx); | ||
242 | } | 324 | } |
243 | 325 | ||
244 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | 326 | static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) |
@@ -246,70 +328,87 @@ static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv) | |||
246 | struct ath_common *common = ath9k_hw_common(priv->ah); | 328 | struct ath_common *common = ath9k_hw_common(priv->ah); |
247 | struct ath9k_htc_target_vif hvif; | 329 | struct ath9k_htc_target_vif hvif; |
248 | struct ath9k_htc_target_sta tsta; | 330 | struct ath9k_htc_target_sta tsta; |
249 | int ret = 0; | 331 | int ret = 0, sta_idx; |
250 | u8 cmd_rsp; | 332 | u8 cmd_rsp; |
251 | 333 | ||
252 | if (priv->nvifs > 0) | 334 | if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) || |
253 | return -ENOBUFS; | 335 | (priv->nstations >= ATH9K_HTC_MAX_STA)) { |
336 | ret = -ENOBUFS; | ||
337 | goto err_vif; | ||
338 | } | ||
254 | 339 | ||
255 | if (priv->nstations >= ATH9K_HTC_MAX_STA) | 340 | sta_idx = ffz(priv->sta_slot); |
256 | return -ENOBUFS; | 341 | if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) { |
342 | ret = -ENOBUFS; | ||
343 | goto err_vif; | ||
344 | } | ||
257 | 345 | ||
258 | /* | 346 | /* |
259 | * Add an interface. | 347 | * Add an interface. |
260 | */ | 348 | */ |
261 | |||
262 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 349 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
263 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); | 350 | memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN); |
264 | 351 | ||
265 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); | 352 | hvif.opmode = cpu_to_be32(HTC_M_MONITOR); |
266 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | 353 | hvif.index = ffz(priv->vif_slot); |
267 | hvif.index = priv->nvifs; | ||
268 | 354 | ||
269 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | 355 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
270 | if (ret) | 356 | if (ret) |
271 | return ret; | 357 | goto err_vif; |
358 | |||
359 | /* | ||
360 | * Assign the monitor interface index as a special case here. | ||
361 | * This is needed when the interface is brought down. | ||
362 | */ | ||
363 | priv->mon_vif_idx = hvif.index; | ||
364 | priv->vif_slot |= (1 << hvif.index); | ||
365 | |||
366 | /* | ||
367 | * Set the hardware mode to monitor only if there are no | ||
368 | * other interfaces. | ||
369 | */ | ||
370 | if (!priv->nvifs) | ||
371 | priv->ah->opmode = NL80211_IFTYPE_MONITOR; | ||
272 | 372 | ||
273 | priv->nvifs++; | 373 | priv->nvifs++; |
274 | 374 | ||
275 | /* | 375 | /* |
276 | * Associate a station with the interface for packet injection. | 376 | * Associate a station with the interface for packet injection. |
277 | */ | 377 | */ |
278 | |||
279 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); | 378 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); |
280 | 379 | ||
281 | memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN); | 380 | memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN); |
282 | 381 | ||
283 | tsta.is_vif_sta = 1; | 382 | tsta.is_vif_sta = 1; |
284 | tsta.sta_index = priv->nstations; | 383 | tsta.sta_index = sta_idx; |
285 | tsta.vif_index = hvif.index; | 384 | tsta.vif_index = hvif.index; |
286 | tsta.maxampdu = 0xffff; | 385 | tsta.maxampdu = 0xffff; |
287 | 386 | ||
288 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); | 387 | WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta); |
289 | if (ret) { | 388 | if (ret) { |
290 | ath_err(common, "Unable to add station entry for monitor mode\n"); | 389 | ath_err(common, "Unable to add station entry for monitor mode\n"); |
291 | goto err_vif; | 390 | goto err_sta; |
292 | } | 391 | } |
293 | 392 | ||
393 | priv->sta_slot |= (1 << sta_idx); | ||
294 | priv->nstations++; | 394 | priv->nstations++; |
295 | 395 | priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx; | |
296 | /* | ||
297 | * Set chainmask etc. on the target. | ||
298 | */ | ||
299 | ret = ath9k_htc_update_cap_target(priv); | ||
300 | if (ret) | ||
301 | ath_dbg(common, ATH_DBG_CONFIG, | ||
302 | "Failed to update capability in target\n"); | ||
303 | |||
304 | priv->ah->is_monitoring = true; | 396 | priv->ah->is_monitoring = true; |
305 | 397 | ||
398 | ath_dbg(common, ATH_DBG_CONFIG, | ||
399 | "Attached a monitor interface at idx: %d, sta idx: %d\n", | ||
400 | priv->mon_vif_idx, sta_idx); | ||
401 | |||
306 | return 0; | 402 | return 0; |
307 | 403 | ||
308 | err_vif: | 404 | err_sta: |
309 | /* | 405 | /* |
310 | * Remove the interface from the target. | 406 | * Remove the interface from the target. |
311 | */ | 407 | */ |
312 | __ath9k_htc_remove_monitor_interface(priv); | 408 | __ath9k_htc_remove_monitor_interface(priv); |
409 | err_vif: | ||
410 | ath_dbg(common, ATH_DBG_FATAL, "Unable to attach a monitor interface\n"); | ||
411 | |||
313 | return ret; | 412 | return ret; |
314 | } | 413 | } |
315 | 414 | ||
@@ -321,7 +420,7 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | |||
321 | 420 | ||
322 | __ath9k_htc_remove_monitor_interface(priv); | 421 | __ath9k_htc_remove_monitor_interface(priv); |
323 | 422 | ||
324 | sta_idx = 0; /* Only single interface, for now */ | 423 | sta_idx = priv->vif_sta_pos[priv->mon_vif_idx]; |
325 | 424 | ||
326 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); | 425 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); |
327 | if (ret) { | 426 | if (ret) { |
@@ -329,9 +428,14 @@ static int ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv) | |||
329 | return ret; | 428 | return ret; |
330 | } | 429 | } |
331 | 430 | ||
431 | priv->sta_slot &= ~(1 << sta_idx); | ||
332 | priv->nstations--; | 432 | priv->nstations--; |
333 | priv->ah->is_monitoring = false; | 433 | priv->ah->is_monitoring = false; |
334 | 434 | ||
435 | ath_dbg(common, ATH_DBG_CONFIG, | ||
436 | "Removed a monitor interface at idx: %d, sta idx: %d\n", | ||
437 | priv->mon_vif_idx, sta_idx); | ||
438 | |||
335 | return 0; | 439 | return 0; |
336 | } | 440 | } |
337 | 441 | ||
@@ -343,12 +447,16 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
343 | struct ath9k_htc_target_sta tsta; | 447 | struct ath9k_htc_target_sta tsta; |
344 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | 448 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; |
345 | struct ath9k_htc_sta *ista; | 449 | struct ath9k_htc_sta *ista; |
346 | int ret; | 450 | int ret, sta_idx; |
347 | u8 cmd_rsp; | 451 | u8 cmd_rsp; |
348 | 452 | ||
349 | if (priv->nstations >= ATH9K_HTC_MAX_STA) | 453 | if (priv->nstations >= ATH9K_HTC_MAX_STA) |
350 | return -ENOBUFS; | 454 | return -ENOBUFS; |
351 | 455 | ||
456 | sta_idx = ffz(priv->sta_slot); | ||
457 | if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) | ||
458 | return -ENOBUFS; | ||
459 | |||
352 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); | 460 | memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta)); |
353 | 461 | ||
354 | if (sta) { | 462 | if (sta) { |
@@ -358,13 +466,13 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
358 | tsta.associd = common->curaid; | 466 | tsta.associd = common->curaid; |
359 | tsta.is_vif_sta = 0; | 467 | tsta.is_vif_sta = 0; |
360 | tsta.valid = true; | 468 | tsta.valid = true; |
361 | ista->index = priv->nstations; | 469 | ista->index = sta_idx; |
362 | } else { | 470 | } else { |
363 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); | 471 | memcpy(&tsta.macaddr, vif->addr, ETH_ALEN); |
364 | tsta.is_vif_sta = 1; | 472 | tsta.is_vif_sta = 1; |
365 | } | 473 | } |
366 | 474 | ||
367 | tsta.sta_index = priv->nstations; | 475 | tsta.sta_index = sta_idx; |
368 | tsta.vif_index = avp->index; | 476 | tsta.vif_index = avp->index; |
369 | tsta.maxampdu = 0xffff; | 477 | tsta.maxampdu = 0xffff; |
370 | if (sta && sta->ht_cap.ht_supported) | 478 | if (sta && sta->ht_cap.ht_supported) |
@@ -379,12 +487,21 @@ static int ath9k_htc_add_station(struct ath9k_htc_priv *priv, | |||
379 | return ret; | 487 | return ret; |
380 | } | 488 | } |
381 | 489 | ||
382 | if (sta) | 490 | if (sta) { |
383 | ath_dbg(common, ATH_DBG_CONFIG, | 491 | ath_dbg(common, ATH_DBG_CONFIG, |
384 | "Added a station entry for: %pM (idx: %d)\n", | 492 | "Added a station entry for: %pM (idx: %d)\n", |
385 | sta->addr, tsta.sta_index); | 493 | sta->addr, tsta.sta_index); |
494 | } else { | ||
495 | ath_dbg(common, ATH_DBG_CONFIG, | ||
496 | "Added a station entry for VIF %d (idx: %d)\n", | ||
497 | avp->index, tsta.sta_index); | ||
498 | } | ||
386 | 499 | ||
500 | priv->sta_slot |= (1 << sta_idx); | ||
387 | priv->nstations++; | 501 | priv->nstations++; |
502 | if (!sta) | ||
503 | priv->vif_sta_pos[avp->index] = sta_idx; | ||
504 | |||
388 | return 0; | 505 | return 0; |
389 | } | 506 | } |
390 | 507 | ||
@@ -393,6 +510,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
393 | struct ieee80211_sta *sta) | 510 | struct ieee80211_sta *sta) |
394 | { | 511 | { |
395 | struct ath_common *common = ath9k_hw_common(priv->ah); | 512 | struct ath_common *common = ath9k_hw_common(priv->ah); |
513 | struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv; | ||
396 | struct ath9k_htc_sta *ista; | 514 | struct ath9k_htc_sta *ista; |
397 | int ret; | 515 | int ret; |
398 | u8 cmd_rsp, sta_idx; | 516 | u8 cmd_rsp, sta_idx; |
@@ -401,7 +519,7 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
401 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 519 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
402 | sta_idx = ista->index; | 520 | sta_idx = ista->index; |
403 | } else { | 521 | } else { |
404 | sta_idx = 0; | 522 | sta_idx = priv->vif_sta_pos[avp->index]; |
405 | } | 523 | } |
406 | 524 | ||
407 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); | 525 | WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx); |
@@ -413,12 +531,19 @@ static int ath9k_htc_remove_station(struct ath9k_htc_priv *priv, | |||
413 | return ret; | 531 | return ret; |
414 | } | 532 | } |
415 | 533 | ||
416 | if (sta) | 534 | if (sta) { |
417 | ath_dbg(common, ATH_DBG_CONFIG, | 535 | ath_dbg(common, ATH_DBG_CONFIG, |
418 | "Removed a station entry for: %pM (idx: %d)\n", | 536 | "Removed a station entry for: %pM (idx: %d)\n", |
419 | sta->addr, sta_idx); | 537 | sta->addr, sta_idx); |
538 | } else { | ||
539 | ath_dbg(common, ATH_DBG_CONFIG, | ||
540 | "Removed a station entry for VIF %d (idx: %d)\n", | ||
541 | avp->index, sta_idx); | ||
542 | } | ||
420 | 543 | ||
544 | priv->sta_slot &= ~(1 << sta_idx); | ||
421 | priv->nstations--; | 545 | priv->nstations--; |
546 | |||
422 | return 0; | 547 | return 0; |
423 | } | 548 | } |
424 | 549 | ||
@@ -800,7 +925,7 @@ void ath9k_htc_debug_remove_root(void) | |||
800 | /* ANI */ | 925 | /* ANI */ |
801 | /*******/ | 926 | /*******/ |
802 | 927 | ||
803 | void ath_start_ani(struct ath9k_htc_priv *priv) | 928 | void ath9k_htc_start_ani(struct ath9k_htc_priv *priv) |
804 | { | 929 | { |
805 | struct ath_common *common = ath9k_hw_common(priv->ah); | 930 | struct ath_common *common = ath9k_hw_common(priv->ah); |
806 | unsigned long timestamp = jiffies_to_msecs(jiffies); | 931 | unsigned long timestamp = jiffies_to_msecs(jiffies); |
@@ -809,15 +934,22 @@ void ath_start_ani(struct ath9k_htc_priv *priv) | |||
809 | common->ani.shortcal_timer = timestamp; | 934 | common->ani.shortcal_timer = timestamp; |
810 | common->ani.checkani_timer = timestamp; | 935 | common->ani.checkani_timer = timestamp; |
811 | 936 | ||
812 | ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, | 937 | priv->op_flags |= OP_ANI_RUNNING; |
938 | |||
939 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, | ||
813 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 940 | msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
814 | } | 941 | } |
815 | 942 | ||
816 | void ath9k_ani_work(struct work_struct *work) | 943 | void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv) |
944 | { | ||
945 | cancel_delayed_work_sync(&priv->ani_work); | ||
946 | priv->op_flags &= ~OP_ANI_RUNNING; | ||
947 | } | ||
948 | |||
949 | void ath9k_htc_ani_work(struct work_struct *work) | ||
817 | { | 950 | { |
818 | struct ath9k_htc_priv *priv = | 951 | struct ath9k_htc_priv *priv = |
819 | container_of(work, struct ath9k_htc_priv, | 952 | container_of(work, struct ath9k_htc_priv, ani_work.work); |
820 | ath9k_ani_work.work); | ||
821 | struct ath_hw *ah = priv->ah; | 953 | struct ath_hw *ah = priv->ah; |
822 | struct ath_common *common = ath9k_hw_common(ah); | 954 | struct ath_common *common = ath9k_hw_common(ah); |
823 | bool longcal = false; | 955 | bool longcal = false; |
@@ -826,7 +958,8 @@ void ath9k_ani_work(struct work_struct *work) | |||
826 | unsigned int timestamp = jiffies_to_msecs(jiffies); | 958 | unsigned int timestamp = jiffies_to_msecs(jiffies); |
827 | u32 cal_interval, short_cal_interval; | 959 | u32 cal_interval, short_cal_interval; |
828 | 960 | ||
829 | short_cal_interval = ATH_STA_SHORT_CALINTERVAL; | 961 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
962 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | ||
830 | 963 | ||
831 | /* Only calibrate if awake */ | 964 | /* Only calibrate if awake */ |
832 | if (ah->power_mode != ATH9K_PM_AWAKE) | 965 | if (ah->power_mode != ATH9K_PM_AWAKE) |
@@ -895,7 +1028,7 @@ set_timer: | |||
895 | if (!common->ani.caldone) | 1028 | if (!common->ani.caldone) |
896 | cal_interval = min(cal_interval, (u32)short_cal_interval); | 1029 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
897 | 1030 | ||
898 | ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work, | 1031 | ieee80211_queue_delayed_work(common->hw, &priv->ani_work, |
899 | msecs_to_jiffies(cal_interval)); | 1032 | msecs_to_jiffies(cal_interval)); |
900 | } | 1033 | } |
901 | 1034 | ||
@@ -903,7 +1036,7 @@ set_timer: | |||
903 | /* mac80211 Callbacks */ | 1036 | /* mac80211 Callbacks */ |
904 | /**********************/ | 1037 | /**********************/ |
905 | 1038 | ||
906 | static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1039 | static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
907 | { | 1040 | { |
908 | struct ieee80211_hdr *hdr; | 1041 | struct ieee80211_hdr *hdr; |
909 | struct ath9k_htc_priv *priv = hw->priv; | 1042 | struct ath9k_htc_priv *priv = hw->priv; |
@@ -916,7 +1049,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
916 | padsize = padpos & 3; | 1049 | padsize = padpos & 3; |
917 | if (padsize && skb->len > padpos) { | 1050 | if (padsize && skb->len > padpos) { |
918 | if (skb_headroom(skb) < padsize) | 1051 | if (skb_headroom(skb) < padsize) |
919 | return -1; | 1052 | goto fail_tx; |
920 | skb_push(skb, padsize); | 1053 | skb_push(skb, padsize); |
921 | memmove(skb->data, skb->data + padsize, padpos); | 1054 | memmove(skb->data, skb->data + padsize, padpos); |
922 | } | 1055 | } |
@@ -937,11 +1070,10 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
937 | goto fail_tx; | 1070 | goto fail_tx; |
938 | } | 1071 | } |
939 | 1072 | ||
940 | return 0; | 1073 | return; |
941 | 1074 | ||
942 | fail_tx: | 1075 | fail_tx: |
943 | dev_kfree_skb_any(skb); | 1076 | dev_kfree_skb_any(skb); |
944 | return 0; | ||
945 | } | 1077 | } |
946 | 1078 | ||
947 | static int ath9k_htc_start(struct ieee80211_hw *hw) | 1079 | static int ath9k_htc_start(struct ieee80211_hw *hw) |
@@ -990,6 +1122,11 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
990 | 1122 | ||
991 | ath9k_host_rx_init(priv); | 1123 | ath9k_host_rx_init(priv); |
992 | 1124 | ||
1125 | ret = ath9k_htc_update_cap_target(priv); | ||
1126 | if (ret) | ||
1127 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1128 | "Failed to update capability in target\n"); | ||
1129 | |||
993 | priv->op_flags &= ~OP_INVALID; | 1130 | priv->op_flags &= ~OP_INVALID; |
994 | htc_start(priv->htc); | 1131 | htc_start(priv->htc); |
995 | 1132 | ||
@@ -1044,26 +1181,21 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1044 | cancel_work_sync(&priv->fatal_work); | 1181 | cancel_work_sync(&priv->fatal_work); |
1045 | cancel_work_sync(&priv->ps_work); | 1182 | cancel_work_sync(&priv->ps_work); |
1046 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); | 1183 | cancel_delayed_work_sync(&priv->ath9k_led_blink_work); |
1047 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1184 | ath9k_htc_stop_ani(priv); |
1048 | ath9k_led_stop_brightness(priv); | 1185 | ath9k_led_stop_brightness(priv); |
1049 | 1186 | ||
1050 | mutex_lock(&priv->mutex); | 1187 | mutex_lock(&priv->mutex); |
1051 | 1188 | ||
1052 | /* Remove monitor interface here */ | ||
1053 | if (ah->opmode == NL80211_IFTYPE_MONITOR) { | ||
1054 | if (ath9k_htc_remove_monitor_interface(priv)) | ||
1055 | ath_err(common, "Unable to remove monitor interface\n"); | ||
1056 | else | ||
1057 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1058 | "Monitor interface removed\n"); | ||
1059 | } | ||
1060 | |||
1061 | if (ah->btcoex_hw.enabled) { | 1189 | if (ah->btcoex_hw.enabled) { |
1062 | ath9k_hw_btcoex_disable(ah); | 1190 | ath9k_hw_btcoex_disable(ah); |
1063 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 1191 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
1064 | ath_htc_cancel_btcoex_work(priv); | 1192 | ath_htc_cancel_btcoex_work(priv); |
1065 | } | 1193 | } |
1066 | 1194 | ||
1195 | /* Remove a monitor interface if it's present. */ | ||
1196 | if (priv->ah->is_monitoring) | ||
1197 | ath9k_htc_remove_monitor_interface(priv); | ||
1198 | |||
1067 | ath9k_hw_phy_disable(ah); | 1199 | ath9k_hw_phy_disable(ah); |
1068 | ath9k_hw_disable(ah); | 1200 | ath9k_hw_disable(ah); |
1069 | ath9k_htc_ps_restore(priv); | 1201 | ath9k_htc_ps_restore(priv); |
@@ -1087,10 +1219,24 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1087 | 1219 | ||
1088 | mutex_lock(&priv->mutex); | 1220 | mutex_lock(&priv->mutex); |
1089 | 1221 | ||
1090 | /* Only one interface for now */ | 1222 | if (priv->nvifs >= ATH9K_HTC_MAX_VIF) { |
1091 | if (priv->nvifs > 0) { | 1223 | mutex_unlock(&priv->mutex); |
1092 | ret = -ENOBUFS; | 1224 | return -ENOBUFS; |
1093 | goto out; | 1225 | } |
1226 | |||
1227 | if (priv->num_ibss_vif || | ||
1228 | (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { | ||
1229 | ath_err(common, "IBSS coexistence with other modes is not allowed\n"); | ||
1230 | mutex_unlock(&priv->mutex); | ||
1231 | return -ENOBUFS; | ||
1232 | } | ||
1233 | |||
1234 | if (((vif->type == NL80211_IFTYPE_AP) || | ||
1235 | (vif->type == NL80211_IFTYPE_ADHOC)) && | ||
1236 | ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) { | ||
1237 | ath_err(common, "Max. number of beaconing interfaces reached\n"); | ||
1238 | mutex_unlock(&priv->mutex); | ||
1239 | return -ENOBUFS; | ||
1094 | } | 1240 | } |
1095 | 1241 | ||
1096 | ath9k_htc_ps_wakeup(priv); | 1242 | ath9k_htc_ps_wakeup(priv); |
@@ -1104,6 +1250,9 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1104 | case NL80211_IFTYPE_ADHOC: | 1250 | case NL80211_IFTYPE_ADHOC: |
1105 | hvif.opmode = cpu_to_be32(HTC_M_IBSS); | 1251 | hvif.opmode = cpu_to_be32(HTC_M_IBSS); |
1106 | break; | 1252 | break; |
1253 | case NL80211_IFTYPE_AP: | ||
1254 | hvif.opmode = cpu_to_be32(HTC_M_HOSTAP); | ||
1255 | break; | ||
1107 | default: | 1256 | default: |
1108 | ath_err(common, | 1257 | ath_err(common, |
1109 | "Interface type %d not yet supported\n", vif->type); | 1258 | "Interface type %d not yet supported\n", vif->type); |
@@ -1111,34 +1260,39 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1111 | goto out; | 1260 | goto out; |
1112 | } | 1261 | } |
1113 | 1262 | ||
1114 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1115 | "Attach a VIF of type: %d\n", vif->type); | ||
1116 | |||
1117 | priv->ah->opmode = vif->type; | ||
1118 | |||
1119 | /* Index starts from zero on the target */ | 1263 | /* Index starts from zero on the target */ |
1120 | avp->index = hvif.index = priv->nvifs; | 1264 | avp->index = hvif.index = ffz(priv->vif_slot); |
1121 | hvif.rtsthreshold = cpu_to_be16(2304); | 1265 | hvif.rtsthreshold = cpu_to_be16(2304); |
1122 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); | 1266 | WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif); |
1123 | if (ret) | 1267 | if (ret) |
1124 | goto out; | 1268 | goto out; |
1125 | 1269 | ||
1126 | priv->nvifs++; | ||
1127 | |||
1128 | /* | 1270 | /* |
1129 | * We need a node in target to tx mgmt frames | 1271 | * We need a node in target to tx mgmt frames |
1130 | * before association. | 1272 | * before association. |
1131 | */ | 1273 | */ |
1132 | ret = ath9k_htc_add_station(priv, vif, NULL); | 1274 | ret = ath9k_htc_add_station(priv, vif, NULL); |
1133 | if (ret) | 1275 | if (ret) { |
1276 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | ||
1134 | goto out; | 1277 | goto out; |
1278 | } | ||
1135 | 1279 | ||
1136 | ret = ath9k_htc_update_cap_target(priv); | 1280 | ath9k_htc_set_bssid_mask(priv, vif); |
1137 | if (ret) | ||
1138 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1139 | "Failed to update capability in target\n"); | ||
1140 | 1281 | ||
1282 | priv->vif_slot |= (1 << avp->index); | ||
1283 | priv->nvifs++; | ||
1141 | priv->vif = vif; | 1284 | priv->vif = vif; |
1285 | |||
1286 | INC_VIF(priv, vif->type); | ||
1287 | ath9k_htc_set_opmode(priv); | ||
1288 | |||
1289 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && | ||
1290 | !(priv->op_flags & OP_ANI_RUNNING)) | ||
1291 | ath9k_htc_start_ani(priv); | ||
1292 | |||
1293 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1294 | "Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index); | ||
1295 | |||
1142 | out: | 1296 | out: |
1143 | ath9k_htc_ps_restore(priv); | 1297 | ath9k_htc_ps_restore(priv); |
1144 | mutex_unlock(&priv->mutex); | 1298 | mutex_unlock(&priv->mutex); |
@@ -1156,8 +1310,6 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1156 | int ret = 0; | 1310 | int ret = 0; |
1157 | u8 cmd_rsp; | 1311 | u8 cmd_rsp; |
1158 | 1312 | ||
1159 | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); | ||
1160 | |||
1161 | mutex_lock(&priv->mutex); | 1313 | mutex_lock(&priv->mutex); |
1162 | ath9k_htc_ps_wakeup(priv); | 1314 | ath9k_htc_ps_wakeup(priv); |
1163 | 1315 | ||
@@ -1166,10 +1318,27 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, | |||
1166 | hvif.index = avp->index; | 1318 | hvif.index = avp->index; |
1167 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); | 1319 | WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif); |
1168 | priv->nvifs--; | 1320 | priv->nvifs--; |
1321 | priv->vif_slot &= ~(1 << avp->index); | ||
1169 | 1322 | ||
1170 | ath9k_htc_remove_station(priv, vif, NULL); | 1323 | ath9k_htc_remove_station(priv, vif, NULL); |
1171 | priv->vif = NULL; | 1324 | priv->vif = NULL; |
1172 | 1325 | ||
1326 | DEC_VIF(priv, vif->type); | ||
1327 | ath9k_htc_set_opmode(priv); | ||
1328 | |||
1329 | /* | ||
1330 | * Stop ANI only if there are no associated station interfaces. | ||
1331 | */ | ||
1332 | if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) { | ||
1333 | priv->rearm_ani = false; | ||
1334 | ieee80211_iterate_active_interfaces_atomic(priv->hw, | ||
1335 | ath9k_htc_vif_iter, priv); | ||
1336 | if (!priv->rearm_ani) | ||
1337 | ath9k_htc_stop_ani(priv); | ||
1338 | } | ||
1339 | |||
1340 | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface at idx: %d\n", avp->index); | ||
1341 | |||
1173 | ath9k_htc_ps_restore(priv); | 1342 | ath9k_htc_ps_restore(priv); |
1174 | mutex_unlock(&priv->mutex); | 1343 | mutex_unlock(&priv->mutex); |
1175 | } | 1344 | } |
@@ -1205,13 +1374,11 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed) | |||
1205 | * IEEE80211_CONF_CHANGE_CHANNEL is handled. | 1374 | * IEEE80211_CONF_CHANGE_CHANNEL is handled. |
1206 | */ | 1375 | */ |
1207 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { | 1376 | if (changed & IEEE80211_CONF_CHANGE_MONITOR) { |
1208 | if (conf->flags & IEEE80211_CONF_MONITOR) { | 1377 | if ((conf->flags & IEEE80211_CONF_MONITOR) && |
1209 | if (ath9k_htc_add_monitor_interface(priv)) | 1378 | !priv->ah->is_monitoring) |
1210 | ath_err(common, "Failed to set monitor mode\n"); | 1379 | ath9k_htc_add_monitor_interface(priv); |
1211 | else | 1380 | else if (priv->ah->is_monitoring) |
1212 | ath_dbg(common, ATH_DBG_CONFIG, | 1381 | ath9k_htc_remove_monitor_interface(priv); |
1213 | "HW opmode set to Monitor mode\n"); | ||
1214 | } | ||
1215 | } | 1382 | } |
1216 | 1383 | ||
1217 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1384 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
@@ -1434,66 +1601,81 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, | |||
1434 | struct ath9k_htc_priv *priv = hw->priv; | 1601 | struct ath9k_htc_priv *priv = hw->priv; |
1435 | struct ath_hw *ah = priv->ah; | 1602 | struct ath_hw *ah = priv->ah; |
1436 | struct ath_common *common = ath9k_hw_common(ah); | 1603 | struct ath_common *common = ath9k_hw_common(ah); |
1604 | bool set_assoc; | ||
1437 | 1605 | ||
1438 | mutex_lock(&priv->mutex); | 1606 | mutex_lock(&priv->mutex); |
1439 | ath9k_htc_ps_wakeup(priv); | 1607 | ath9k_htc_ps_wakeup(priv); |
1440 | 1608 | ||
1609 | /* | ||
1610 | * Set the HW AID/BSSID only for the first station interface | ||
1611 | * or in IBSS mode. | ||
1612 | */ | ||
1613 | set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) || | ||
1614 | ((priv->ah->opmode == NL80211_IFTYPE_STATION) && | ||
1615 | (priv->num_sta_vif == 1))); | ||
1616 | |||
1617 | |||
1441 | if (changed & BSS_CHANGED_ASSOC) { | 1618 | if (changed & BSS_CHANGED_ASSOC) { |
1442 | common->curaid = bss_conf->assoc ? | 1619 | if (set_assoc) { |
1443 | bss_conf->aid : 0; | 1620 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", |
1444 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | 1621 | bss_conf->assoc); |
1445 | bss_conf->assoc); | 1622 | |
1446 | 1623 | common->curaid = bss_conf->assoc ? | |
1447 | if (bss_conf->assoc) { | 1624 | bss_conf->aid : 0; |
1448 | priv->op_flags |= OP_ASSOCIATED; | 1625 | |
1449 | ath_start_ani(priv); | 1626 | if (bss_conf->assoc) |
1450 | } else { | 1627 | ath9k_htc_start_ani(priv); |
1451 | priv->op_flags &= ~OP_ASSOCIATED; | 1628 | else |
1452 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | 1629 | ath9k_htc_stop_ani(priv); |
1453 | } | 1630 | } |
1454 | } | 1631 | } |
1455 | 1632 | ||
1456 | if (changed & BSS_CHANGED_BSSID) { | 1633 | if (changed & BSS_CHANGED_BSSID) { |
1457 | /* Set BSSID */ | 1634 | if (set_assoc) { |
1458 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 1635 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
1459 | ath9k_hw_write_associd(ah); | 1636 | ath9k_hw_write_associd(ah); |
1460 | 1637 | ||
1461 | ath_dbg(common, ATH_DBG_CONFIG, | 1638 | ath_dbg(common, ATH_DBG_CONFIG, |
1462 | "BSSID: %pM aid: 0x%x\n", | 1639 | "BSSID: %pM aid: 0x%x\n", |
1463 | common->curbssid, common->curaid); | 1640 | common->curbssid, common->curaid); |
1641 | } | ||
1464 | } | 1642 | } |
1465 | 1643 | ||
1466 | if ((changed & BSS_CHANGED_BEACON_INT) || | 1644 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) { |
1467 | (changed & BSS_CHANGED_BEACON) || | 1645 | ath_dbg(common, ATH_DBG_CONFIG, |
1468 | ((changed & BSS_CHANGED_BEACON_ENABLED) && | 1646 | "Beacon enabled for BSS: %pM\n", bss_conf->bssid); |
1469 | bss_conf->enable_beacon)) { | ||
1470 | priv->op_flags |= OP_ENABLE_BEACON; | 1647 | priv->op_flags |= OP_ENABLE_BEACON; |
1471 | ath9k_htc_beacon_config(priv, vif); | 1648 | ath9k_htc_beacon_config(priv, vif); |
1472 | } | 1649 | } |
1473 | 1650 | ||
1474 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && | 1651 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) { |
1475 | !bss_conf->enable_beacon) { | 1652 | /* |
1476 | priv->op_flags &= ~OP_ENABLE_BEACON; | 1653 | * Disable SWBA interrupt only if there are no |
1477 | ath9k_htc_beacon_config(priv, vif); | 1654 | * AP/IBSS interfaces. |
1478 | } | 1655 | */ |
1479 | 1656 | if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) { | |
1480 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 1657 | ath_dbg(common, ATH_DBG_CONFIG, |
1481 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | 1658 | "Beacon disabled for BSS: %pM\n", |
1482 | bss_conf->use_short_preamble); | 1659 | bss_conf->bssid); |
1483 | if (bss_conf->use_short_preamble) | 1660 | priv->op_flags &= ~OP_ENABLE_BEACON; |
1484 | priv->op_flags |= OP_PREAMBLE_SHORT; | 1661 | ath9k_htc_beacon_config(priv, vif); |
1485 | else | 1662 | } |
1486 | priv->op_flags &= ~OP_PREAMBLE_SHORT; | ||
1487 | } | 1663 | } |
1488 | 1664 | ||
1489 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | 1665 | if (changed & BSS_CHANGED_BEACON_INT) { |
1490 | ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", | 1666 | /* |
1491 | bss_conf->use_cts_prot); | 1667 | * Reset the HW TSF for the first AP interface. |
1492 | if (bss_conf->use_cts_prot && | 1668 | */ |
1493 | hw->conf.channel->band != IEEE80211_BAND_5GHZ) | 1669 | if ((priv->ah->opmode == NL80211_IFTYPE_AP) && |
1494 | priv->op_flags |= OP_PROTECT_ENABLE; | 1670 | (priv->nvifs == 1) && |
1495 | else | 1671 | (priv->num_ap_vif == 1) && |
1496 | priv->op_flags &= ~OP_PROTECT_ENABLE; | 1672 | (vif->type == NL80211_IFTYPE_AP)) { |
1673 | priv->op_flags |= OP_TSF_RESET; | ||
1674 | } | ||
1675 | ath_dbg(common, ATH_DBG_CONFIG, | ||
1676 | "Beacon interval changed for BSS: %pM\n", | ||
1677 | bss_conf->bssid); | ||
1678 | ath9k_htc_beacon_config(priv, vif); | ||
1497 | } | 1679 | } |
1498 | 1680 | ||
1499 | if (changed & BSS_CHANGED_ERP_SLOT) { | 1681 | if (changed & BSS_CHANGED_ERP_SLOT) { |
@@ -1558,6 +1740,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1558 | struct ath9k_htc_sta *ista; | 1740 | struct ath9k_htc_sta *ista; |
1559 | int ret = 0; | 1741 | int ret = 0; |
1560 | 1742 | ||
1743 | mutex_lock(&priv->mutex); | ||
1744 | |||
1561 | switch (action) { | 1745 | switch (action) { |
1562 | case IEEE80211_AMPDU_RX_START: | 1746 | case IEEE80211_AMPDU_RX_START: |
1563 | break; | 1747 | break; |
@@ -1582,6 +1766,8 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1582 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); | 1766 | ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n"); |
1583 | } | 1767 | } |
1584 | 1768 | ||
1769 | mutex_unlock(&priv->mutex); | ||
1770 | |||
1585 | return ret; | 1771 | return ret; |
1586 | } | 1772 | } |
1587 | 1773 | ||
@@ -1594,8 +1780,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | |||
1594 | priv->op_flags |= OP_SCANNING; | 1780 | priv->op_flags |= OP_SCANNING; |
1595 | spin_unlock_bh(&priv->beacon_lock); | 1781 | spin_unlock_bh(&priv->beacon_lock); |
1596 | cancel_work_sync(&priv->ps_work); | 1782 | cancel_work_sync(&priv->ps_work); |
1597 | if (priv->op_flags & OP_ASSOCIATED) | 1783 | ath9k_htc_stop_ani(priv); |
1598 | cancel_delayed_work_sync(&priv->ath9k_ani_work); | ||
1599 | mutex_unlock(&priv->mutex); | 1784 | mutex_unlock(&priv->mutex); |
1600 | } | 1785 | } |
1601 | 1786 | ||
@@ -1604,14 +1789,11 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | |||
1604 | struct ath9k_htc_priv *priv = hw->priv; | 1789 | struct ath9k_htc_priv *priv = hw->priv; |
1605 | 1790 | ||
1606 | mutex_lock(&priv->mutex); | 1791 | mutex_lock(&priv->mutex); |
1607 | ath9k_htc_ps_wakeup(priv); | ||
1608 | spin_lock_bh(&priv->beacon_lock); | 1792 | spin_lock_bh(&priv->beacon_lock); |
1609 | priv->op_flags &= ~OP_SCANNING; | 1793 | priv->op_flags &= ~OP_SCANNING; |
1610 | spin_unlock_bh(&priv->beacon_lock); | 1794 | spin_unlock_bh(&priv->beacon_lock); |
1611 | if (priv->op_flags & OP_ASSOCIATED) { | 1795 | ath9k_htc_ps_wakeup(priv); |
1612 | ath9k_htc_beacon_config(priv, priv->vif); | 1796 | ath9k_htc_vif_reconfig(priv); |
1613 | ath_start_ani(priv); | ||
1614 | } | ||
1615 | ath9k_htc_ps_restore(priv); | 1797 | ath9k_htc_ps_restore(priv); |
1616 | mutex_unlock(&priv->mutex); | 1798 | mutex_unlock(&priv->mutex); |
1617 | } | 1799 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 7a5ffca21958..4a4f27ba96af 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -84,7 +84,9 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
84 | struct ieee80211_hdr *hdr; | 84 | struct ieee80211_hdr *hdr; |
85 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 85 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
86 | struct ieee80211_sta *sta = tx_info->control.sta; | 86 | struct ieee80211_sta *sta = tx_info->control.sta; |
87 | struct ieee80211_vif *vif = tx_info->control.vif; | ||
87 | struct ath9k_htc_sta *ista; | 88 | struct ath9k_htc_sta *ista; |
89 | struct ath9k_htc_vif *avp; | ||
88 | struct ath9k_htc_tx_ctl tx_ctl; | 90 | struct ath9k_htc_tx_ctl tx_ctl; |
89 | enum htc_endpoint_id epid; | 91 | enum htc_endpoint_id epid; |
90 | u16 qnum; | 92 | u16 qnum; |
@@ -95,18 +97,31 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
95 | hdr = (struct ieee80211_hdr *) skb->data; | 97 | hdr = (struct ieee80211_hdr *) skb->data; |
96 | fc = hdr->frame_control; | 98 | fc = hdr->frame_control; |
97 | 99 | ||
98 | if (tx_info->control.vif && | 100 | /* |
99 | (struct ath9k_htc_vif *) tx_info->control.vif->drv_priv) | 101 | * Find out on which interface this packet has to be |
100 | vif_idx = ((struct ath9k_htc_vif *) | 102 | * sent out. |
101 | tx_info->control.vif->drv_priv)->index; | 103 | */ |
102 | else | 104 | if (vif) { |
103 | vif_idx = priv->nvifs; | 105 | avp = (struct ath9k_htc_vif *) vif->drv_priv; |
106 | vif_idx = avp->index; | ||
107 | } else { | ||
108 | if (!priv->ah->is_monitoring) { | ||
109 | ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, | ||
110 | "VIF is null, but no monitor interface !\n"); | ||
111 | return -EINVAL; | ||
112 | } | ||
104 | 113 | ||
114 | vif_idx = priv->mon_vif_idx; | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * Find out which station this packet is destined for. | ||
119 | */ | ||
105 | if (sta) { | 120 | if (sta) { |
106 | ista = (struct ath9k_htc_sta *) sta->drv_priv; | 121 | ista = (struct ath9k_htc_sta *) sta->drv_priv; |
107 | sta_idx = ista->index; | 122 | sta_idx = ista->index; |
108 | } else { | 123 | } else { |
109 | sta_idx = 0; | 124 | sta_idx = priv->vif_sta_pos[vif_idx]; |
110 | } | 125 | } |
111 | 126 | ||
112 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); | 127 | memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl)); |
@@ -141,7 +156,7 @@ int ath9k_htc_tx_start(struct ath9k_htc_priv *priv, struct sk_buff *skb) | |||
141 | 156 | ||
142 | /* CTS-to-self */ | 157 | /* CTS-to-self */ |
143 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && | 158 | if (!(flags & ATH9K_HTC_TX_RTSCTS) && |
144 | (priv->op_flags & OP_PROTECT_ENABLE)) | 159 | (vif && vif->bss_conf.use_cts_prot)) |
145 | flags |= ATH9K_HTC_TX_CTSONLY; | 160 | flags |= ATH9K_HTC_TX_CTSONLY; |
146 | 161 | ||
147 | tx_hdr.flags = cpu_to_be32(flags); | 162 | tx_hdr.flags = cpu_to_be32(flags); |
@@ -217,6 +232,7 @@ static bool ath9k_htc_check_tx_aggr(struct ath9k_htc_priv *priv, | |||
217 | void ath9k_tx_tasklet(unsigned long data) | 232 | void ath9k_tx_tasklet(unsigned long data) |
218 | { | 233 | { |
219 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 234 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
235 | struct ieee80211_vif *vif; | ||
220 | struct ieee80211_sta *sta; | 236 | struct ieee80211_sta *sta; |
221 | struct ieee80211_hdr *hdr; | 237 | struct ieee80211_hdr *hdr; |
222 | struct ieee80211_tx_info *tx_info; | 238 | struct ieee80211_tx_info *tx_info; |
@@ -228,12 +244,16 @@ void ath9k_tx_tasklet(unsigned long data) | |||
228 | hdr = (struct ieee80211_hdr *) skb->data; | 244 | hdr = (struct ieee80211_hdr *) skb->data; |
229 | fc = hdr->frame_control; | 245 | fc = hdr->frame_control; |
230 | tx_info = IEEE80211_SKB_CB(skb); | 246 | tx_info = IEEE80211_SKB_CB(skb); |
247 | vif = tx_info->control.vif; | ||
231 | 248 | ||
232 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | 249 | memset(&tx_info->status, 0, sizeof(tx_info->status)); |
233 | 250 | ||
251 | if (!vif) | ||
252 | goto send_mac80211; | ||
253 | |||
234 | rcu_read_lock(); | 254 | rcu_read_lock(); |
235 | 255 | ||
236 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | 256 | sta = ieee80211_find_sta(vif, hdr->addr1); |
237 | if (!sta) { | 257 | if (!sta) { |
238 | rcu_read_unlock(); | 258 | rcu_read_unlock(); |
239 | ieee80211_tx_status(priv->hw, skb); | 259 | ieee80211_tx_status(priv->hw, skb); |
@@ -263,6 +283,7 @@ void ath9k_tx_tasklet(unsigned long data) | |||
263 | 283 | ||
264 | rcu_read_unlock(); | 284 | rcu_read_unlock(); |
265 | 285 | ||
286 | send_mac80211: | ||
266 | /* Send status to mac80211 */ | 287 | /* Send status to mac80211 */ |
267 | ieee80211_tx_status(priv->hw, skb); | 288 | ieee80211_tx_status(priv->hw, skb); |
268 | } | 289 | } |
@@ -386,7 +407,7 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | |||
386 | */ | 407 | */ |
387 | if (((ah->opmode != NL80211_IFTYPE_AP) && | 408 | if (((ah->opmode != NL80211_IFTYPE_AP) && |
388 | (priv->rxfilter & FIF_PROMISC_IN_BSS)) || | 409 | (priv->rxfilter & FIF_PROMISC_IN_BSS)) || |
389 | (ah->opmode == NL80211_IFTYPE_MONITOR)) | 410 | ah->is_monitoring) |
390 | rfilt |= ATH9K_RX_FILTER_PROM; | 411 | rfilt |= ATH9K_RX_FILTER_PROM; |
391 | 412 | ||
392 | if (priv->rxfilter & FIF_CONTROL) | 413 | if (priv->rxfilter & FIF_CONTROL) |
@@ -398,8 +419,13 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | |||
398 | else | 419 | else |
399 | rfilt |= ATH9K_RX_FILTER_BEACON; | 420 | rfilt |= ATH9K_RX_FILTER_BEACON; |
400 | 421 | ||
401 | if (conf_is_ht(&priv->hw->conf)) | 422 | if (conf_is_ht(&priv->hw->conf)) { |
402 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; | 423 | rfilt |= ATH9K_RX_FILTER_COMP_BAR; |
424 | rfilt |= ATH9K_RX_FILTER_UNCOMP_BA_BAR; | ||
425 | } | ||
426 | |||
427 | if (priv->rxfilter & FIF_PSPOLL) | ||
428 | rfilt |= ATH9K_RX_FILTER_PSPOLL; | ||
403 | 429 | ||
404 | return rfilt; | 430 | return rfilt; |
405 | 431 | ||
@@ -412,20 +438,12 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv) | |||
412 | static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) | 438 | static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv) |
413 | { | 439 | { |
414 | struct ath_hw *ah = priv->ah; | 440 | struct ath_hw *ah = priv->ah; |
415 | struct ath_common *common = ath9k_hw_common(ah); | ||
416 | |||
417 | u32 rfilt, mfilt[2]; | 441 | u32 rfilt, mfilt[2]; |
418 | 442 | ||
419 | /* configure rx filter */ | 443 | /* configure rx filter */ |
420 | rfilt = ath9k_htc_calcrxfilter(priv); | 444 | rfilt = ath9k_htc_calcrxfilter(priv); |
421 | ath9k_hw_setrxfilter(ah, rfilt); | 445 | ath9k_hw_setrxfilter(ah, rfilt); |
422 | 446 | ||
423 | /* configure bssid mask */ | ||
424 | ath_hw_setbssidmask(common); | ||
425 | |||
426 | /* configure operational mode */ | ||
427 | ath9k_hw_setopmode(ah); | ||
428 | |||
429 | /* calculate and install multicast filter */ | 447 | /* calculate and install multicast filter */ |
430 | mfilt[0] = mfilt[1] = ~0; | 448 | mfilt[0] = mfilt[1] = ~0; |
431 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); | 449 | ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); |
@@ -576,31 +594,29 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
576 | ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, | 594 | ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate, |
577 | rxbuf->rxstatus.rs_flags); | 595 | rxbuf->rxstatus.rs_flags); |
578 | 596 | ||
579 | if (priv->op_flags & OP_ASSOCIATED) { | 597 | if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && |
580 | if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD && | 598 | !rxbuf->rxstatus.rs_moreaggr) |
581 | !rxbuf->rxstatus.rs_moreaggr) | 599 | ATH_RSSI_LPF(priv->rx.last_rssi, |
582 | ATH_RSSI_LPF(priv->rx.last_rssi, | 600 | rxbuf->rxstatus.rs_rssi); |
583 | rxbuf->rxstatus.rs_rssi); | ||
584 | 601 | ||
585 | last_rssi = priv->rx.last_rssi; | 602 | last_rssi = priv->rx.last_rssi; |
586 | 603 | ||
587 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 604 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
588 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | 605 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, |
589 | ATH_RSSI_EP_MULTIPLIER); | 606 | ATH_RSSI_EP_MULTIPLIER); |
590 | 607 | ||
591 | if (rxbuf->rxstatus.rs_rssi < 0) | 608 | if (rxbuf->rxstatus.rs_rssi < 0) |
592 | rxbuf->rxstatus.rs_rssi = 0; | 609 | rxbuf->rxstatus.rs_rssi = 0; |
593 | 610 | ||
594 | if (ieee80211_is_beacon(fc)) | 611 | if (ieee80211_is_beacon(fc)) |
595 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | 612 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; |
596 | } | ||
597 | 613 | ||
598 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); | 614 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); |
599 | rx_status->band = hw->conf.channel->band; | 615 | rx_status->band = hw->conf.channel->band; |
600 | rx_status->freq = hw->conf.channel->center_freq; | 616 | rx_status->freq = hw->conf.channel->center_freq; |
601 | rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; | 617 | rx_status->signal = rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; |
602 | rx_status->antenna = rxbuf->rxstatus.rs_antenna; | 618 | rx_status->antenna = rxbuf->rxstatus.rs_antenna; |
603 | rx_status->flag |= RX_FLAG_TSFT; | 619 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; |
604 | 620 | ||
605 | return true; | 621 | return true; |
606 | 622 | ||
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index f66c882a39e2..79aec983279f 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -140,6 +140,21 @@ static struct ieee80211_rate ath9k_legacy_rates[] = { | |||
140 | RATE(540, 0x0c, 0), | 140 | RATE(540, 0x0c, 0), |
141 | }; | 141 | }; |
142 | 142 | ||
143 | #ifdef CONFIG_MAC80211_LEDS | ||
144 | static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = { | ||
145 | { .throughput = 0 * 1024, .blink_time = 334 }, | ||
146 | { .throughput = 1 * 1024, .blink_time = 260 }, | ||
147 | { .throughput = 5 * 1024, .blink_time = 220 }, | ||
148 | { .throughput = 10 * 1024, .blink_time = 190 }, | ||
149 | { .throughput = 20 * 1024, .blink_time = 170 }, | ||
150 | { .throughput = 50 * 1024, .blink_time = 150 }, | ||
151 | { .throughput = 70 * 1024, .blink_time = 130 }, | ||
152 | { .throughput = 100 * 1024, .blink_time = 110 }, | ||
153 | { .throughput = 200 * 1024, .blink_time = 80 }, | ||
154 | { .throughput = 300 * 1024, .blink_time = 50 }, | ||
155 | }; | ||
156 | #endif | ||
157 | |||
143 | static void ath9k_deinit_softc(struct ath_softc *sc); | 158 | static void ath9k_deinit_softc(struct ath_softc *sc); |
144 | 159 | ||
145 | /* | 160 | /* |
@@ -731,6 +746,13 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, | |||
731 | 746 | ||
732 | ath9k_init_txpower_limits(sc); | 747 | ath9k_init_txpower_limits(sc); |
733 | 748 | ||
749 | #ifdef CONFIG_MAC80211_LEDS | ||
750 | /* must be initialized before ieee80211_register_hw */ | ||
751 | sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw, | ||
752 | IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink, | ||
753 | ARRAY_SIZE(ath9k_tpt_blink)); | ||
754 | #endif | ||
755 | |||
734 | /* Register with mac80211 */ | 756 | /* Register with mac80211 */ |
735 | error = ieee80211_register_hw(hw); | 757 | error = ieee80211_register_hw(hw); |
736 | if (error) | 758 | if (error) |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a71550049d84..2e228aada1a9 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -910,6 +910,8 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
910 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | 910 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); |
911 | 911 | ||
912 | ieee80211_wake_queues(hw); | 912 | ieee80211_wake_queues(hw); |
913 | ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2); | ||
914 | |||
913 | out: | 915 | out: |
914 | spin_unlock_bh(&sc->sc_pcu_lock); | 916 | spin_unlock_bh(&sc->sc_pcu_lock); |
915 | 917 | ||
@@ -923,6 +925,8 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
923 | int r; | 925 | int r; |
924 | 926 | ||
925 | ath9k_ps_wakeup(sc); | 927 | ath9k_ps_wakeup(sc); |
928 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
929 | |||
926 | spin_lock_bh(&sc->sc_pcu_lock); | 930 | spin_lock_bh(&sc->sc_pcu_lock); |
927 | 931 | ||
928 | ieee80211_stop_queues(hw); | 932 | ieee80211_stop_queues(hw); |
@@ -1142,8 +1146,7 @@ mutex_unlock: | |||
1142 | return r; | 1146 | return r; |
1143 | } | 1147 | } |
1144 | 1148 | ||
1145 | static int ath9k_tx(struct ieee80211_hw *hw, | 1149 | static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1146 | struct sk_buff *skb) | ||
1147 | { | 1150 | { |
1148 | struct ath_softc *sc = hw->priv; | 1151 | struct ath_softc *sc = hw->priv; |
1149 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1152 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -1200,10 +1203,9 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
1200 | goto exit; | 1203 | goto exit; |
1201 | } | 1204 | } |
1202 | 1205 | ||
1203 | return 0; | 1206 | return; |
1204 | exit: | 1207 | exit: |
1205 | dev_kfree_skb_any(skb); | 1208 | dev_kfree_skb_any(skb); |
1206 | return 0; | ||
1207 | } | 1209 | } |
1208 | 1210 | ||
1209 | static void ath9k_stop(struct ieee80211_hw *hw) | 1211 | static void ath9k_stop(struct ieee80211_hw *hw) |
@@ -1214,9 +1216,6 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1214 | 1216 | ||
1215 | mutex_lock(&sc->mutex); | 1217 | mutex_lock(&sc->mutex); |
1216 | 1218 | ||
1217 | if (led_blink) | ||
1218 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | ||
1219 | |||
1220 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1219 | cancel_delayed_work_sync(&sc->tx_complete_work); |
1221 | cancel_delayed_work_sync(&sc->hw_pll_work); | 1220 | cancel_delayed_work_sync(&sc->hw_pll_work); |
1222 | cancel_work_sync(&sc->paprd_work); | 1221 | cancel_work_sync(&sc->paprd_work); |
@@ -2131,7 +2130,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2131 | { | 2130 | { |
2132 | #define ATH_FLUSH_TIMEOUT 60 /* ms */ | 2131 | #define ATH_FLUSH_TIMEOUT 60 /* ms */ |
2133 | struct ath_softc *sc = hw->priv; | 2132 | struct ath_softc *sc = hw->priv; |
2134 | struct ath_txq *txq; | 2133 | struct ath_txq *txq = NULL; |
2135 | struct ath_hw *ah = sc->sc_ah; | 2134 | struct ath_hw *ah = sc->sc_ah; |
2136 | struct ath_common *common = ath9k_hw_common(ah); | 2135 | struct ath_common *common = ath9k_hw_common(ah); |
2137 | int i, j, npend = 0; | 2136 | int i, j, npend = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index daf171d2f610..cb559e345b86 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -983,7 +983,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common, | |||
983 | rx_status->freq = hw->conf.channel->center_freq; | 983 | rx_status->freq = hw->conf.channel->center_freq; |
984 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; | 984 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; |
985 | rx_status->antenna = rx_stats->rs_antenna; | 985 | rx_status->antenna = rx_stats->rs_antenna; |
986 | rx_status->flag |= RX_FLAG_TSFT; | 986 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; |
987 | 987 | ||
988 | return 0; | 988 | return 0; |
989 | } | 989 | } |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 64b226a78b2e..8fa8acfde62e 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -878,6 +878,7 @@ | |||
878 | enum ath_usb_dev { | 878 | enum ath_usb_dev { |
879 | AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ | 879 | AR9280_USB = 1, /* AR7010 + AR9280, UB94 */ |
880 | AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ | 880 | AR9287_USB = 2, /* AR7010 + AR9287, UB95 */ |
881 | STORAGE_DEVICE = 3, | ||
881 | }; | 882 | }; |
882 | 883 | ||
883 | #define AR_DEVID_7010(_ah) \ | 884 | #define AR_DEVID_7010(_ah) \ |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index dc862f5e1162..d3d24904f62f 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -123,12 +123,8 @@ void ath9k_deinit_wmi(struct ath9k_htc_priv *priv) | |||
123 | void ath9k_swba_tasklet(unsigned long data) | 123 | void ath9k_swba_tasklet(unsigned long data) |
124 | { | 124 | { |
125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; | 125 | struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data; |
126 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
127 | |||
128 | ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n"); | ||
129 | 126 | ||
130 | ath9k_htc_swba(priv, priv->wmi->beacon_pending); | 127 | ath9k_htc_swba(priv, priv->wmi->beacon_pending); |
131 | |||
132 | } | 128 | } |
133 | 129 | ||
134 | void ath9k_fatal_work(struct work_struct *work) | 130 | void ath9k_fatal_work(struct work_struct *work) |
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index 420d437f9580..c6a5fae634a0 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h | |||
@@ -534,7 +534,7 @@ void carl9170_rx(struct ar9170 *ar, void *buf, unsigned int len); | |||
534 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); | 534 | void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); |
535 | 535 | ||
536 | /* TX */ | 536 | /* TX */ |
537 | int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | 537 | void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); |
538 | void carl9170_tx_janitor(struct work_struct *work); | 538 | void carl9170_tx_janitor(struct work_struct *work); |
539 | void carl9170_tx_process_status(struct ar9170 *ar, | 539 | void carl9170_tx_process_status(struct ar9170 *ar, |
540 | const struct carl9170_rsp *cmd); | 540 | const struct carl9170_rsp *cmd); |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 6f41e21d3a1c..0ef70b6fc512 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -1339,7 +1339,7 @@ err_unlock_rcu: | |||
1339 | return false; | 1339 | return false; |
1340 | } | 1340 | } |
1341 | 1341 | ||
1342 | int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 1342 | void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
1343 | { | 1343 | { |
1344 | struct ar9170 *ar = hw->priv; | 1344 | struct ar9170 *ar = hw->priv; |
1345 | struct ieee80211_tx_info *info; | 1345 | struct ieee80211_tx_info *info; |
@@ -1373,12 +1373,11 @@ int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1373 | } | 1373 | } |
1374 | 1374 | ||
1375 | carl9170_tx(ar); | 1375 | carl9170_tx(ar); |
1376 | return NETDEV_TX_OK; | 1376 | return; |
1377 | 1377 | ||
1378 | err_free: | 1378 | err_free: |
1379 | ar->tx_dropped++; | 1379 | ar->tx_dropped++; |
1380 | dev_kfree_skb_any(skb); | 1380 | dev_kfree_skb_any(skb); |
1381 | return NETDEV_TX_OK; | ||
1382 | } | 1381 | } |
1383 | 1382 | ||
1384 | void carl9170_tx_scheduler(struct ar9170 *ar) | 1383 | void carl9170_tx_scheduler(struct ar9170 *ar) |