diff options
Diffstat (limited to 'drivers/net/wireless/ath5k/base.c')
-rw-r--r-- | drivers/net/wireless/ath5k/base.c | 174 |
1 files changed, 112 insertions, 62 deletions
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index a533ed60bb4d..bd2c580d1f19 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -232,13 +232,14 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
232 | int mc_count, struct dev_mc_list *mclist); | 232 | int mc_count, struct dev_mc_list *mclist); |
233 | static int ath5k_set_key(struct ieee80211_hw *hw, | 233 | static int ath5k_set_key(struct ieee80211_hw *hw, |
234 | enum set_key_cmd cmd, | 234 | enum set_key_cmd cmd, |
235 | const u8 *local_addr, const u8 *addr, | 235 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
236 | struct ieee80211_key_conf *key); | 236 | struct ieee80211_key_conf *key); |
237 | static int ath5k_get_stats(struct ieee80211_hw *hw, | 237 | static int ath5k_get_stats(struct ieee80211_hw *hw, |
238 | struct ieee80211_low_level_stats *stats); | 238 | struct ieee80211_low_level_stats *stats); |
239 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, | 239 | static int ath5k_get_tx_stats(struct ieee80211_hw *hw, |
240 | struct ieee80211_tx_queue_stats *stats); | 240 | struct ieee80211_tx_queue_stats *stats); |
241 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); | 241 | static u64 ath5k_get_tsf(struct ieee80211_hw *hw); |
242 | static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); | ||
242 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); | 243 | static void ath5k_reset_tsf(struct ieee80211_hw *hw); |
243 | static int ath5k_beacon_update(struct ath5k_softc *sc, | 244 | static int ath5k_beacon_update(struct ath5k_softc *sc, |
244 | struct sk_buff *skb); | 245 | struct sk_buff *skb); |
@@ -261,6 +262,7 @@ static struct ieee80211_ops ath5k_hw_ops = { | |||
261 | .conf_tx = NULL, | 262 | .conf_tx = NULL, |
262 | .get_tx_stats = ath5k_get_tx_stats, | 263 | .get_tx_stats = ath5k_get_tx_stats, |
263 | .get_tsf = ath5k_get_tsf, | 264 | .get_tsf = ath5k_get_tsf, |
265 | .set_tsf = ath5k_set_tsf, | ||
264 | .reset_tsf = ath5k_reset_tsf, | 266 | .reset_tsf = ath5k_reset_tsf, |
265 | .bss_info_changed = ath5k_bss_info_changed, | 267 | .bss_info_changed = ath5k_bss_info_changed, |
266 | }; | 268 | }; |
@@ -347,9 +349,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) | |||
347 | } | 349 | } |
348 | 350 | ||
349 | /* Interrupt handling */ | 351 | /* Interrupt handling */ |
350 | static int ath5k_init(struct ath5k_softc *sc, bool is_resume); | 352 | static int ath5k_init(struct ath5k_softc *sc); |
351 | static int ath5k_stop_locked(struct ath5k_softc *sc); | 353 | static int ath5k_stop_locked(struct ath5k_softc *sc); |
352 | static int ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend); | 354 | static int ath5k_stop_hw(struct ath5k_softc *sc); |
353 | static irqreturn_t ath5k_intr(int irq, void *dev_id); | 355 | static irqreturn_t ath5k_intr(int irq, void *dev_id); |
354 | static void ath5k_tasklet_reset(unsigned long data); | 356 | static void ath5k_tasklet_reset(unsigned long data); |
355 | 357 | ||
@@ -653,8 +655,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
653 | 655 | ||
654 | ath5k_led_off(sc); | 656 | ath5k_led_off(sc); |
655 | 657 | ||
656 | ath5k_stop_hw(sc, true); | ||
657 | |||
658 | free_irq(pdev->irq, sc); | 658 | free_irq(pdev->irq, sc); |
659 | pci_save_state(pdev); | 659 | pci_save_state(pdev); |
660 | pci_disable_device(pdev); | 660 | pci_disable_device(pdev); |
@@ -689,14 +689,9 @@ ath5k_pci_resume(struct pci_dev *pdev) | |||
689 | goto err_no_irq; | 689 | goto err_no_irq; |
690 | } | 690 | } |
691 | 691 | ||
692 | err = ath5k_init(sc, true); | ||
693 | if (err) | ||
694 | goto err_irq; | ||
695 | ath5k_led_enable(sc); | 692 | ath5k_led_enable(sc); |
696 | |||
697 | return 0; | 693 | return 0; |
698 | err_irq: | 694 | |
699 | free_irq(pdev->irq, sc); | ||
700 | err_no_irq: | 695 | err_no_irq: |
701 | pci_disable_device(pdev); | 696 | pci_disable_device(pdev); |
702 | return err; | 697 | return err; |
@@ -1098,6 +1093,42 @@ ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) | |||
1098 | * Buffers setup * | 1093 | * Buffers setup * |
1099 | \***************/ | 1094 | \***************/ |
1100 | 1095 | ||
1096 | static | ||
1097 | struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) | ||
1098 | { | ||
1099 | struct sk_buff *skb; | ||
1100 | unsigned int off; | ||
1101 | |||
1102 | /* | ||
1103 | * Allocate buffer with headroom_needed space for the | ||
1104 | * fake physical layer header at the start. | ||
1105 | */ | ||
1106 | skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); | ||
1107 | |||
1108 | if (!skb) { | ||
1109 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | ||
1110 | sc->rxbufsize + sc->cachelsz - 1); | ||
1111 | return NULL; | ||
1112 | } | ||
1113 | /* | ||
1114 | * Cache-line-align. This is important (for the | ||
1115 | * 5210 at least) as not doing so causes bogus data | ||
1116 | * in rx'd frames. | ||
1117 | */ | ||
1118 | off = ((unsigned long)skb->data) % sc->cachelsz; | ||
1119 | if (off != 0) | ||
1120 | skb_reserve(skb, sc->cachelsz - off); | ||
1121 | |||
1122 | *skb_addr = pci_map_single(sc->pdev, | ||
1123 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | ||
1124 | if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { | ||
1125 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | ||
1126 | dev_kfree_skb(skb); | ||
1127 | return NULL; | ||
1128 | } | ||
1129 | return skb; | ||
1130 | } | ||
1131 | |||
1101 | static int | 1132 | static int |
1102 | ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | 1133 | ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) |
1103 | { | 1134 | { |
@@ -1105,37 +1136,11 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1105 | struct sk_buff *skb = bf->skb; | 1136 | struct sk_buff *skb = bf->skb; |
1106 | struct ath5k_desc *ds; | 1137 | struct ath5k_desc *ds; |
1107 | 1138 | ||
1108 | if (likely(skb == NULL)) { | 1139 | if (!skb) { |
1109 | unsigned int off; | 1140 | skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); |
1110 | 1141 | if (!skb) | |
1111 | /* | ||
1112 | * Allocate buffer with headroom_needed space for the | ||
1113 | * fake physical layer header at the start. | ||
1114 | */ | ||
1115 | skb = dev_alloc_skb(sc->rxbufsize + sc->cachelsz - 1); | ||
1116 | if (unlikely(skb == NULL)) { | ||
1117 | ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", | ||
1118 | sc->rxbufsize + sc->cachelsz - 1); | ||
1119 | return -ENOMEM; | 1142 | return -ENOMEM; |
1120 | } | ||
1121 | /* | ||
1122 | * Cache-line-align. This is important (for the | ||
1123 | * 5210 at least) as not doing so causes bogus data | ||
1124 | * in rx'd frames. | ||
1125 | */ | ||
1126 | off = ((unsigned long)skb->data) % sc->cachelsz; | ||
1127 | if (off != 0) | ||
1128 | skb_reserve(skb, sc->cachelsz - off); | ||
1129 | |||
1130 | bf->skb = skb; | 1143 | bf->skb = skb; |
1131 | bf->skbaddr = pci_map_single(sc->pdev, | ||
1132 | skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); | ||
1133 | if (unlikely(pci_dma_mapping_error(sc->pdev, bf->skbaddr))) { | ||
1134 | ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); | ||
1135 | dev_kfree_skb(skb); | ||
1136 | bf->skb = NULL; | ||
1137 | return -ENOMEM; | ||
1138 | } | ||
1139 | } | 1144 | } |
1140 | 1145 | ||
1141 | /* | 1146 | /* |
@@ -1178,6 +1183,10 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1178 | struct ieee80211_rate *rate; | 1183 | struct ieee80211_rate *rate; |
1179 | unsigned int mrr_rate[3], mrr_tries[3]; | 1184 | unsigned int mrr_rate[3], mrr_tries[3]; |
1180 | int i, ret; | 1185 | int i, ret; |
1186 | u16 hw_rate; | ||
1187 | u16 cts_rate = 0; | ||
1188 | u16 duration = 0; | ||
1189 | u8 rc_flags; | ||
1181 | 1190 | ||
1182 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; | 1191 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; |
1183 | 1192 | ||
@@ -1185,11 +1194,30 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1185 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, | 1194 | bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, |
1186 | PCI_DMA_TODEVICE); | 1195 | PCI_DMA_TODEVICE); |
1187 | 1196 | ||
1197 | rate = ieee80211_get_tx_rate(sc->hw, info); | ||
1198 | |||
1188 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | 1199 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) |
1189 | flags |= AR5K_TXDESC_NOACK; | 1200 | flags |= AR5K_TXDESC_NOACK; |
1190 | 1201 | ||
1202 | rc_flags = info->control.rates[0].flags; | ||
1203 | hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? | ||
1204 | rate->hw_value_short : rate->hw_value; | ||
1205 | |||
1191 | pktlen = skb->len; | 1206 | pktlen = skb->len; |
1192 | 1207 | ||
1208 | if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { | ||
1209 | flags |= AR5K_TXDESC_RTSENA; | ||
1210 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | ||
1211 | duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, | ||
1212 | sc->vif, pktlen, info)); | ||
1213 | } | ||
1214 | if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | ||
1215 | flags |= AR5K_TXDESC_CTSENA; | ||
1216 | cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; | ||
1217 | duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, | ||
1218 | sc->vif, pktlen, info)); | ||
1219 | } | ||
1220 | |||
1193 | if (info->control.hw_key) { | 1221 | if (info->control.hw_key) { |
1194 | keyidx = info->control.hw_key->hw_key_idx; | 1222 | keyidx = info->control.hw_key->hw_key_idx; |
1195 | pktlen += info->control.hw_key->icv_len; | 1223 | pktlen += info->control.hw_key->icv_len; |
@@ -1197,8 +1225,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1197 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1225 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1198 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1226 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, |
1199 | (sc->power_level * 2), | 1227 | (sc->power_level * 2), |
1200 | ieee80211_get_tx_rate(sc->hw, info)->hw_value, | 1228 | hw_rate, |
1201 | info->control.rates[0].count, keyidx, 0, flags, 0, 0); | 1229 | info->control.rates[0].count, keyidx, 0, flags, |
1230 | cts_rate, duration); | ||
1202 | if (ret) | 1231 | if (ret) |
1203 | goto err_unmap; | 1232 | goto err_unmap; |
1204 | 1233 | ||
@@ -1664,7 +1693,8 @@ ath5k_tasklet_rx(unsigned long data) | |||
1664 | { | 1693 | { |
1665 | struct ieee80211_rx_status rxs = {}; | 1694 | struct ieee80211_rx_status rxs = {}; |
1666 | struct ath5k_rx_status rs = {}; | 1695 | struct ath5k_rx_status rs = {}; |
1667 | struct sk_buff *skb; | 1696 | struct sk_buff *skb, *next_skb; |
1697 | dma_addr_t next_skb_addr; | ||
1668 | struct ath5k_softc *sc = (void *)data; | 1698 | struct ath5k_softc *sc = (void *)data; |
1669 | struct ath5k_buf *bf, *bf_last; | 1699 | struct ath5k_buf *bf, *bf_last; |
1670 | struct ath5k_desc *ds; | 1700 | struct ath5k_desc *ds; |
@@ -1749,10 +1779,17 @@ ath5k_tasklet_rx(unsigned long data) | |||
1749 | goto next; | 1779 | goto next; |
1750 | } | 1780 | } |
1751 | accept: | 1781 | accept: |
1782 | next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); | ||
1783 | |||
1784 | /* | ||
1785 | * If we can't replace bf->skb with a new skb under memory | ||
1786 | * pressure, just skip this packet | ||
1787 | */ | ||
1788 | if (!next_skb) | ||
1789 | goto next; | ||
1790 | |||
1752 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, | 1791 | pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, |
1753 | PCI_DMA_FROMDEVICE); | 1792 | PCI_DMA_FROMDEVICE); |
1754 | bf->skb = NULL; | ||
1755 | |||
1756 | skb_put(skb, rs.rs_datalen); | 1793 | skb_put(skb, rs.rs_datalen); |
1757 | 1794 | ||
1758 | /* The MAC header is padded to have 32-bit boundary if the | 1795 | /* The MAC header is padded to have 32-bit boundary if the |
@@ -1825,6 +1862,9 @@ accept: | |||
1825 | ath5k_check_ibss_tsf(sc, skb, &rxs); | 1862 | ath5k_check_ibss_tsf(sc, skb, &rxs); |
1826 | 1863 | ||
1827 | __ieee80211_rx(sc->hw, skb, &rxs); | 1864 | __ieee80211_rx(sc->hw, skb, &rxs); |
1865 | |||
1866 | bf->skb = next_skb; | ||
1867 | bf->skbaddr = next_skb_addr; | ||
1828 | next: | 1868 | next: |
1829 | list_move_tail(&bf->list, &sc->rxbuf); | 1869 | list_move_tail(&bf->list, &sc->rxbuf); |
1830 | } while (ath5k_rxbuf_setup(sc, bf) == 0); | 1870 | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
@@ -2207,18 +2247,13 @@ ath5k_beacon_config(struct ath5k_softc *sc) | |||
2207 | \********************/ | 2247 | \********************/ |
2208 | 2248 | ||
2209 | static int | 2249 | static int |
2210 | ath5k_init(struct ath5k_softc *sc, bool is_resume) | 2250 | ath5k_init(struct ath5k_softc *sc) |
2211 | { | 2251 | { |
2212 | struct ath5k_hw *ah = sc->ah; | 2252 | struct ath5k_hw *ah = sc->ah; |
2213 | int ret, i; | 2253 | int ret, i; |
2214 | 2254 | ||
2215 | mutex_lock(&sc->lock); | 2255 | mutex_lock(&sc->lock); |
2216 | 2256 | ||
2217 | if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status)) | ||
2218 | goto out_ok; | ||
2219 | |||
2220 | __clear_bit(ATH_STAT_STARTED, sc->status); | ||
2221 | |||
2222 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); | 2257 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); |
2223 | 2258 | ||
2224 | /* | 2259 | /* |
@@ -2250,15 +2285,12 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume) | |||
2250 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) | 2285 | for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) |
2251 | ath5k_hw_reset_key(ah, i); | 2286 | ath5k_hw_reset_key(ah, i); |
2252 | 2287 | ||
2253 | __set_bit(ATH_STAT_STARTED, sc->status); | ||
2254 | |||
2255 | /* Set ack to be sent at low bit-rates */ | 2288 | /* Set ack to be sent at low bit-rates */ |
2256 | ath5k_hw_set_ack_bitrate_high(ah, false); | 2289 | ath5k_hw_set_ack_bitrate_high(ah, false); |
2257 | 2290 | ||
2258 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + | 2291 | mod_timer(&sc->calib_tim, round_jiffies(jiffies + |
2259 | msecs_to_jiffies(ath5k_calinterval * 1000))); | 2292 | msecs_to_jiffies(ath5k_calinterval * 1000))); |
2260 | 2293 | ||
2261 | out_ok: | ||
2262 | ret = 0; | 2294 | ret = 0; |
2263 | done: | 2295 | done: |
2264 | mmiowb(); | 2296 | mmiowb(); |
@@ -2313,7 +2345,7 @@ ath5k_stop_locked(struct ath5k_softc *sc) | |||
2313 | * stop is preempted). | 2345 | * stop is preempted). |
2314 | */ | 2346 | */ |
2315 | static int | 2347 | static int |
2316 | ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend) | 2348 | ath5k_stop_hw(struct ath5k_softc *sc) |
2317 | { | 2349 | { |
2318 | int ret; | 2350 | int ret; |
2319 | 2351 | ||
@@ -2344,8 +2376,6 @@ ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend) | |||
2344 | } | 2376 | } |
2345 | } | 2377 | } |
2346 | ath5k_txbuf_free(sc, sc->bbuf); | 2378 | ath5k_txbuf_free(sc, sc->bbuf); |
2347 | if (!is_suspend) | ||
2348 | __clear_bit(ATH_STAT_STARTED, sc->status); | ||
2349 | 2379 | ||
2350 | mmiowb(); | 2380 | mmiowb(); |
2351 | mutex_unlock(&sc->lock); | 2381 | mutex_unlock(&sc->lock); |
@@ -2598,6 +2628,17 @@ ath5k_init_leds(struct ath5k_softc *sc) | |||
2598 | sc->led_pin = 1; | 2628 | sc->led_pin = 1; |
2599 | sc->led_on = 1; /* active high */ | 2629 | sc->led_on = 1; /* active high */ |
2600 | } | 2630 | } |
2631 | /* | ||
2632 | * Pin 3 on Foxconn chips used in Acer Aspire One (0x105b:e008) and | ||
2633 | * in emachines notebooks with AMBIT subsystem. | ||
2634 | */ | ||
2635 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_FOXCONN || | ||
2636 | pdev->subsystem_vendor == PCI_VENDOR_ID_AMBIT) { | ||
2637 | __set_bit(ATH_STAT_LEDSOFT, sc->status); | ||
2638 | sc->led_pin = 3; | ||
2639 | sc->led_on = 0; /* active low */ | ||
2640 | } | ||
2641 | |||
2601 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) | 2642 | if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) |
2602 | goto out; | 2643 | goto out; |
2603 | 2644 | ||
@@ -2745,12 +2786,12 @@ ath5k_reset_wake(struct ath5k_softc *sc) | |||
2745 | 2786 | ||
2746 | static int ath5k_start(struct ieee80211_hw *hw) | 2787 | static int ath5k_start(struct ieee80211_hw *hw) |
2747 | { | 2788 | { |
2748 | return ath5k_init(hw->priv, false); | 2789 | return ath5k_init(hw->priv); |
2749 | } | 2790 | } |
2750 | 2791 | ||
2751 | static void ath5k_stop(struct ieee80211_hw *hw) | 2792 | static void ath5k_stop(struct ieee80211_hw *hw) |
2752 | { | 2793 | { |
2753 | ath5k_stop_hw(hw->priv, false); | 2794 | ath5k_stop_hw(hw->priv); |
2754 | } | 2795 | } |
2755 | 2796 | ||
2756 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2797 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
@@ -2999,8 +3040,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
2999 | 3040 | ||
3000 | static int | 3041 | static int |
3001 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 3042 | ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
3002 | const u8 *local_addr, const u8 *addr, | 3043 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
3003 | struct ieee80211_key_conf *key) | 3044 | struct ieee80211_key_conf *key) |
3004 | { | 3045 | { |
3005 | struct ath5k_softc *sc = hw->priv; | 3046 | struct ath5k_softc *sc = hw->priv; |
3006 | int ret = 0; | 3047 | int ret = 0; |
@@ -3023,7 +3064,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3023 | 3064 | ||
3024 | switch (cmd) { | 3065 | switch (cmd) { |
3025 | case SET_KEY: | 3066 | case SET_KEY: |
3026 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, addr); | 3067 | ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, |
3068 | sta ? sta->addr : NULL); | ||
3027 | if (ret) { | 3069 | if (ret) { |
3028 | ATH5K_ERR(sc, "can't set the key\n"); | 3070 | ATH5K_ERR(sc, "can't set the key\n"); |
3029 | goto unlock; | 3071 | goto unlock; |
@@ -3083,6 +3125,14 @@ ath5k_get_tsf(struct ieee80211_hw *hw) | |||
3083 | } | 3125 | } |
3084 | 3126 | ||
3085 | static void | 3127 | static void |
3128 | ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) | ||
3129 | { | ||
3130 | struct ath5k_softc *sc = hw->priv; | ||
3131 | |||
3132 | ath5k_hw_set_tsf64(sc->ah, tsf); | ||
3133 | } | ||
3134 | |||
3135 | static void | ||
3086 | ath5k_reset_tsf(struct ieee80211_hw *hw) | 3136 | ath5k_reset_tsf(struct ieee80211_hw *hw) |
3087 | { | 3137 | { |
3088 | struct ath5k_softc *sc = hw->priv; | 3138 | struct ath5k_softc *sc = hw->priv; |