| package/mac80211/patches/300-pending_work.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath9k/main.c |
| 2 | | @@ -324,7 +324,6 @@ static void ath_paprd_activate(struct at |
| 3 | | if (!caldata || !caldata->paprd_done) |
| 4 | | return; |
| 5 | | |
| 6 | | - ath9k_ps_wakeup(sc); |
| 7 | | ar9003_paprd_enable(ah, false); |
| 8 | | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
| 9 | | if (!(common->tx_chainmask & BIT(chain))) |
| 10 | | @@ -334,7 +333,6 @@ static void ath_paprd_activate(struct at |
| 11 | | } |
| 12 | | |
| 13 | | ar9003_paprd_enable(ah, true); |
| 14 | | - ath9k_ps_restore(sc); |
| 15 | | } |
| 16 | | |
| 17 | | static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) |
| 18 | | @@ -554,8 +552,11 @@ set_timer: |
| 19 | | if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { |
| 20 | | if (!ah->caldata->paprd_done) |
| 21 | | ieee80211_queue_work(sc->hw, &sc->paprd_work); |
| 22 | | - else if (!ah->paprd_table_write_done) |
| 23 | | + else if (!ah->paprd_table_write_done) { |
| 24 | | + ath9k_ps_wakeup(sc); |
| 25 | | ath_paprd_activate(sc); |
| 26 | | + ath9k_ps_restore(sc); |
| 27 | | + } |
| 28 | | } |
| 29 | | } |
| 30 | | |
| 31 | | @@ -1376,7 +1377,6 @@ static void ath9k_calculate_summary_stat |
| 32 | | |
| 33 | | ath9k_calculate_iter_data(hw, vif, &iter_data); |
| 34 | | |
| 35 | | - ath9k_ps_wakeup(sc); |
| 36 | | /* Set BSSID mask. */ |
| 37 | | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
| 38 | | ath_hw_setbssidmask(common); |
| 39 | | @@ -1411,7 +1411,6 @@ static void ath9k_calculate_summary_stat |
| 40 | | } |
| 41 | | |
| 42 | | ath9k_hw_set_interrupts(ah, ah->imask); |
| 43 | | - ath9k_ps_restore(sc); |
| 44 | | |
| 45 | | /* Set up ANI */ |
| 46 | | if ((iter_data.naps + iter_data.nadhocs) > 0) { |
| 47 | | @@ -1457,6 +1456,7 @@ static int ath9k_add_interface(struct ie |
| 48 | | struct ath_vif *avp = (void *)vif->drv_priv; |
| 49 | | int ret = 0; |
| 50 | | |
| 51 | | + ath9k_ps_wakeup(sc); |
| 52 | | mutex_lock(&sc->mutex); |
| 53 | | |
| 54 | | switch (vif->type) { |
| 55 | | @@ -1503,6 +1503,7 @@ static int ath9k_add_interface(struct ie |
| 56 | | ath9k_do_vif_add_setup(hw, vif); |
| 57 | | out: |
| 58 | | mutex_unlock(&sc->mutex); |
| 59 | | + ath9k_ps_restore(sc); |
| 60 | | return ret; |
| 61 | | } |
| 62 | | |
| 63 | | @@ -1517,6 +1518,7 @@ static int ath9k_change_interface(struct |
| 64 | | |
| 65 | | ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n"); |
| 66 | | mutex_lock(&sc->mutex); |
| 67 | | + ath9k_ps_wakeup(sc); |
| 68 | | |
| 69 | | /* See if new interface type is valid. */ |
| 70 | | if ((new_type == NL80211_IFTYPE_ADHOC) && |
| 71 | | @@ -1546,6 +1548,7 @@ static int ath9k_change_interface(struct |
| 72 | | |
| 73 | | ath9k_do_vif_add_setup(hw, vif); |
| 74 | | out: |
| 75 | | + ath9k_ps_restore(sc); |
| 76 | | mutex_unlock(&sc->mutex); |
| 77 | | return ret; |
| 78 | | } |
| 79 | | @@ -1558,6 +1561,7 @@ static void ath9k_remove_interface(struc |
| 80 | | |
| 81 | | ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
| 82 | | |
| 83 | | + ath9k_ps_wakeup(sc); |
| 84 | | mutex_lock(&sc->mutex); |
| 85 | | |
| 86 | | sc->nvifs--; |
| 87 | | @@ -1569,6 +1573,7 @@ static void ath9k_remove_interface(struc |
| 88 | | ath9k_calculate_summary_state(hw, NULL); |
| 89 | | |
| 90 | | mutex_unlock(&sc->mutex); |
| 91 | | + ath9k_ps_restore(sc); |
| 92 | | } |
| 93 | | |
| 94 | | static void ath9k_enable_ps(struct ath_softc *sc) |
| 95 | | @@ -1809,6 +1814,7 @@ static int ath9k_conf_tx(struct ieee8021 |
| 96 | | |
| 97 | | txq = sc->tx.txq_map[queue]; |
| 98 | | |
| 99 | | + ath9k_ps_wakeup(sc); |
| 100 | | mutex_lock(&sc->mutex); |
| 101 | | |
| 102 | | memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); |
| 103 | | @@ -1832,6 +1838,7 @@ static int ath9k_conf_tx(struct ieee8021 |
| 104 | | ath_beaconq_config(sc); |
| 105 | | |
| 106 | | mutex_unlock(&sc->mutex); |
| 107 | | + ath9k_ps_restore(sc); |
| 108 | | |
| 109 | | return ret; |
| 110 | | } |
| 111 | | @@ -1908,6 +1915,7 @@ static void ath9k_bss_info_changed(struc |
| 112 | | int slottime; |
| 113 | | int error; |
| 114 | | |
| 115 | | + ath9k_ps_wakeup(sc); |
| 116 | | mutex_lock(&sc->mutex); |
| 117 | | |
| 118 | | if (changed & BSS_CHANGED_BSSID) { |
| 119 | | @@ -2008,6 +2016,7 @@ static void ath9k_bss_info_changed(struc |
| 120 | | } |
| 121 | | |
| 122 | | mutex_unlock(&sc->mutex); |
| 123 | | + ath9k_ps_restore(sc); |
| 124 | | } |
| 125 | | |
| 126 | | static u64 ath9k_get_tsf(struct ieee80211_hw *hw) |
| 127 | | +++ b/drivers/net/wireless/ath/ath9k/beacon.c |
| 128 | | @@ -392,14 +392,6 @@ void ath_beacon_tasklet(unsigned long da |
| 129 | | tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); |
| 130 | | tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); |
| 131 | | slot = (tsftu % (intval * ATH_BCBUF)) / intval; |
| 132 | | - /* |
| 133 | | - * Reverse the slot order to get slot 0 on the TBTT offset that does |
| 134 | | - * not require TSF adjustment and other slots adding |
| 135 | | - * slot/ATH_BCBUF * beacon_int to timestamp. For example, with |
| 136 | | - * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. |
| 137 | | - * and slot 0 is at correct offset to TBTT. |
| 138 | | - */ |
| 139 | | - slot = ATH_BCBUF - slot - 1; |
| 140 | | vif = sc->beacon.bslot[slot]; |
| 141 | | |
| 142 | | ath_dbg(common, ATH_DBG_BEACON, |
| 143 | | @@ -708,7 +700,7 @@ void ath_beacon_config(struct ath_softc |
| 144 | | if (cur_conf->dtim_period == 0) |
| 145 | | cur_conf->dtim_period = 1; |
| 146 | | |
| 147 | | - switch (iftype) { |
| 148 | | + switch (sc->sc_ah->opmode) { |
| 149 | | case NL80211_IFTYPE_AP: |
| 150 | | ath_beacon_config_ap(sc, cur_conf); |
| 151 | | break; |
| 152 | | +++ b/net/mac80211/rx.c |
| 153 | | @@ -1585,7 +1585,7 @@ ieee80211_drop_unencrypted_mgmt(struct i |
| 154 | | } |
| 155 | | |
| 156 | | static int |
| 157 | | -__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) |
| 158 | | +__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) |
| 159 | | { |
| 160 | | struct ieee80211_sub_if_data *sdata = rx->sdata; |
| 161 | | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
| 162 | | @@ -1593,6 +1593,7 @@ __ieee80211_data_to_8023(struct ieee8021 |
| 163 | | struct ethhdr *ehdr; |
| 164 | | int ret; |
| 165 | | |
| 166 | | + *port_control = false; |
| 167 | | if (ieee80211_has_a4(hdr->frame_control) && |
| 168 | | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) |
| 169 | | return -1; |
| 170 | | @@ -1611,11 +1612,13 @@ __ieee80211_data_to_8023(struct ieee8021 |
| 171 | | return -1; |
| 172 | | |
| 173 | | ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); |
| 174 | | - if (ret < 0 || !check_port_control) |
| 175 | | + if (ret < 0) |
| 176 | | return ret; |
| 177 | | |
| 178 | | ehdr = (struct ethhdr *) rx->skb->data; |
| 179 | | - if (ehdr->h_proto != rx->sdata->control_port_protocol) |
| 180 | | + if (ehdr->h_proto == rx->sdata->control_port_protocol) |
| 181 | | + *port_control = true; |
| 182 | | + else if (check_port_control) |
| 183 | | return -1; |
| 184 | | |
| 185 | | return 0; |
| 186 | | @@ -1916,6 +1919,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_ |
| 187 | | struct net_device *dev = sdata->dev; |
| 188 | | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
| 189 | | __le16 fc = hdr->frame_control; |
| 190 | | + bool port_control; |
| 191 | | int err; |
| 192 | | |
| 193 | | if (unlikely(!ieee80211_is_data(hdr->frame_control))) |
| 194 | | @@ -1932,13 +1936,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_ |
| 195 | | sdata->vif.type == NL80211_IFTYPE_AP) |
| 196 | | return RX_DROP_MONITOR; |
| 197 | | |
| 198 | | - err = __ieee80211_data_to_8023(rx); |
| 199 | | + err = __ieee80211_data_to_8023(rx, &port_control); |
| 200 | | if (unlikely(err)) |
| 201 | | return RX_DROP_UNUSABLE; |
| 202 | | |
| 203 | | if (!ieee80211_frame_allowed(rx, fc)) |
| 204 | | return RX_DROP_MONITOR; |
| 205 | | |
| 206 | | + if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && |
| 207 | | + unlikely(port_control) && sdata->bss) { |
| 208 | | + sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, |
| 209 | | + u.ap); |
| 210 | | + dev = sdata->dev; |
| 211 | | + rx->sdata = sdata; |
| 212 | | + } |
| 213 | | + |
| 214 | | rx->skb->dev = dev; |
| 215 | | |
| 216 | | dev->stats.rx_packets++; |
| 217 | | +++ b/drivers/net/wireless/ath/ath9k/recv.c |
| 218 | | @@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_s |
| 219 | | *sc->rx.rxlink = bf->bf_daddr; |
| 220 | | |
| 221 | | sc->rx.rxlink = &ds->ds_link; |
| 222 | | - ath9k_hw_rxena(ah); |
| 223 | | } |
| 224 | | |
| 225 | | static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) |
| 226 | | @@ -426,9 +425,7 @@ u32 ath_calcrxfilter(struct ath_softc *s |
| 227 | | else |
| 228 | | rfilt |= ATH9K_RX_FILTER_BEACON; |
| 229 | | |
| 230 | | - if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) || |
| 231 | | - AR_SREV_9285_12_OR_LATER(sc->sc_ah)) && |
| 232 | | - (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && |
| 233 | | + if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
| 234 | | (sc->rx.rxfilter & FIF_PSPOLL)) |
| 235 | | rfilt |= ATH9K_RX_FILTER_PSPOLL; |
| 236 | | |
| 237 | | @@ -486,12 +483,12 @@ start_recv: |
| 238 | | bool ath_stoprecv(struct ath_softc *sc) |
| 239 | | { |
| 240 | | struct ath_hw *ah = sc->sc_ah; |
| 241 | | - bool stopped; |
| 242 | | + bool stopped, reset = false; |
| 243 | | |
| 244 | | spin_lock_bh(&sc->rx.rxbuflock); |
| 245 | | ath9k_hw_abortpcurecv(ah); |
| 246 | | ath9k_hw_setrxfilter(ah, 0); |
| 247 | | - stopped = ath9k_hw_stopdmarecv(ah); |
| 248 | | + stopped = ath9k_hw_stopdmarecv(ah, &reset); |
| 249 | | |
| 250 | | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
| 251 | | ath_edma_stop_recv(sc); |
| 252 | | @@ -506,7 +503,7 @@ bool ath_stoprecv(struct ath_softc *sc) |
| 253 | | "confusing the DMA engine when we start RX up\n"); |
| 254 | | ATH_DBG_WARN_ON_ONCE(!stopped); |
| 255 | | } |
| 256 | | - return stopped; |
| 257 | | + return stopped && !reset; |
| 258 | | } |
| 259 | | |
| 260 | | void ath_flushrecv(struct ath_softc *sc) |
| 261 | | @@ -1767,6 +1764,7 @@ requeue: |
| 262 | | } else { |
| 263 | | list_move_tail(&bf->list, &sc->rx.rxbuf); |
| 264 | | ath_rx_buf_link(sc, bf); |
| 265 | | + ath9k_hw_rxena(ah); |
| 266 | | } |
| 267 | | } while (1); |
| 268 | | |
| 269 | | +++ b/drivers/net/wireless/ath/ath9k/hw.c |
| 270 | | @@ -1249,15 +1249,6 @@ int ath9k_hw_reset(struct ath_hw *ah, st |
| 271 | | ah->txchainmask = common->tx_chainmask; |
| 272 | | ah->rxchainmask = common->rx_chainmask; |
| 273 | | |
| 274 | | - if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) { |
| 275 | | - ath9k_hw_abortpcurecv(ah); |
| 276 | | - if (!ath9k_hw_stopdmarecv(ah)) { |
| 277 | | - ath_dbg(common, ATH_DBG_XMIT, |
| 278 | | - "Failed to stop receive dma\n"); |
| 279 | | - bChannelChange = false; |
| 280 | | - } |
| 281 | | - } |
| 282 | | - |
| 283 | | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
| 284 | | return -EIO; |
| 285 | | |
| 286 | | +++ b/drivers/net/wireless/ath/ath9k/mac.c |
| 287 | | @@ -710,27 +710,46 @@ void ath9k_hw_abortpcurecv(struct ath_hw |
| 288 | | } |
| 289 | | EXPORT_SYMBOL(ath9k_hw_abortpcurecv); |
| 290 | | |
| 291 | | -bool ath9k_hw_stopdmarecv(struct ath_hw *ah) |
| 292 | | +bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) |
| 293 | | { |
| 294 | | #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ |
| 295 | | struct ath_common *common = ath9k_hw_common(ah); |
| 296 | | + u32 mac_status, last_mac_status = 0; |
| 297 | | int i; |
| 298 | | |
| 299 | | + /* Enable access to the DMA observation bus */ |
| 300 | | + REG_WRITE(ah, AR_MACMISC, |
| 301 | | + ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | |
| 302 | | + (AR_MACMISC_MISC_OBS_BUS_1 << |
| 303 | | + AR_MACMISC_MISC_OBS_BUS_MSB_S))); |
| 304 | | + |
| 305 | | REG_WRITE(ah, AR_CR, AR_CR_RXD); |
| 306 | | |
| 307 | | /* Wait for rx enable bit to go low */ |
| 308 | | for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { |
| 309 | | if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) |
| 310 | | break; |
| 311 | | + |
| 312 | | + if (!AR_SREV_9300_20_OR_LATER(ah)) { |
| 313 | | + mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0; |
| 314 | | + if (mac_status == 0x1c0 && mac_status == last_mac_status) { |
| 315 | | + *reset = true; |
| 316 | | + break; |
| 317 | | + } |
| 318 | | + |
| 319 | | + last_mac_status = mac_status; |
| 320 | | + } |
| 321 | | + |
| 322 | | udelay(AH_TIME_QUANTUM); |
| 323 | | } |
| 324 | | |
| 325 | | if (i == 0) { |
| 326 | | ath_err(common, |
| 327 | | - "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", |
| 328 | | + "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n", |
| 329 | | AH_RX_STOP_DMA_TIMEOUT / 1000, |
| 330 | | REG_READ(ah, AR_CR), |
| 331 | | - REG_READ(ah, AR_DIAG_SW)); |
| 332 | | + REG_READ(ah, AR_DIAG_SW), |
| 333 | | + REG_READ(ah, AR_DMADBG_7)); |
| 334 | | return false; |
| 335 | | } else { |
| 336 | | return true; |
| 337 | | +++ b/drivers/net/wireless/ath/ath9k/mac.h |
| 338 | | @@ -695,7 +695,7 @@ bool ath9k_hw_setrxabort(struct ath_hw * |
| 339 | | void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); |
| 340 | | void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); |
| 341 | | void ath9k_hw_abortpcurecv(struct ath_hw *ah); |
| 342 | | -bool ath9k_hw_stopdmarecv(struct ath_hw *ah); |
| 343 | | +bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset); |
| 344 | | int ath9k_hw_beaconq_setup(struct ath_hw *ah); |
| 345 | | |
| 346 | | /* Interrupt Handling */ |
| package/mac80211/patches/461-ath5k_fix_short_preamble_dur.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/ath5k.h |
| 2 | | @@ -1233,7 +1233,7 @@ int ath5k_eeprom_read_mac(struct ath5k_h |
| 3 | | /* Protocol Control Unit Functions */ |
| 4 | | /* Helpers */ |
| 5 | | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, |
| 6 | | - int len, struct ieee80211_rate *rate); |
| 7 | | + int len, struct ieee80211_rate *rate, bool shortpre); |
| 8 | | unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah); |
| 9 | | unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah); |
| 10 | | extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); |
| 11 | | +++ b/drivers/net/wireless/ath/ath5k/pcu.c |
| 12 | | @@ -75,7 +75,7 @@ static const unsigned int ack_rates_high |
| 13 | | * bwmodes. |
| 14 | | */ |
| 15 | | int ath5k_hw_get_frame_duration(struct ath5k_hw *ah, |
| 16 | | - int len, struct ieee80211_rate *rate) |
| 17 | | + int len, struct ieee80211_rate *rate, bool shortpre) |
| 18 | | { |
| 19 | | struct ath5k_softc *sc = ah->ah_sc; |
| 20 | | int sifs, preamble, plcp_bits, sym_time; |
| 21 | | @@ -84,9 +84,15 @@ int ath5k_hw_get_frame_duration(struct a |
| 22 | | |
| 23 | | /* Fallback */ |
| 24 | | if (!ah->ah_bwmode) { |
| 25 | | - dur = ieee80211_generic_frame_duration(sc->hw, |
| 26 | | - NULL, len, rate); |
| 27 | | - return le16_to_cpu(dur); |
| 28 | | + __le16 raw_dur = ieee80211_generic_frame_duration(sc->hw, |
| 29 | | + NULL, len, rate); |
| 30 | | + |
| 31 | | + /* subtract difference between long and short preamble */ |
| 32 | | + dur = le16_to_cpu(raw_dur); |
| 33 | | + if (shortpre) |
| 34 | | + dur -= 96; |
| 35 | | + |
| 36 | | + return dur; |
| 37 | | } |
| 38 | | |
| 39 | | bitrate = rate->bitrate; |
| 40 | | @@ -263,27 +269,14 @@ static inline void ath5k_hw_write_rate_d |
| 41 | | * actual rate for this rate. See mac80211 tx.c |
| 42 | | * ieee80211_duration() for a brief description of |
| 43 | | * what rate we should choose to TX ACKs. */ |
| 44 | | - tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); |
| 45 | | + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); |
| 46 | | |
| 47 | | ath5k_hw_reg_write(ah, tx_time, reg); |
| 48 | | |
| 49 | | if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) |
| 50 | | continue; |
| 51 | | |
| 52 | | - /* |
| 53 | | - * We're not distinguishing short preamble here, |
| 54 | | - * This is true, all we'll get is a longer value here |
| 55 | | - * which is not necessarilly bad. We could use |
| 56 | | - * export ieee80211_frame_duration() but that needs to be |
| 57 | | - * fixed first to be properly used by mac802111 drivers: |
| 58 | | - * |
| 59 | | - * - remove erp stuff and let the routine figure ofdm |
| 60 | | - * erp rates |
| 61 | | - * - remove passing argument ieee80211_local as |
| 62 | | - * drivers don't have access to it |
| 63 | | - * - move drivers using ieee80211_generic_frame_duration() |
| 64 | | - * to this |
| 65 | | - */ |
| 66 | | + tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, true); |
| 67 | | ath5k_hw_reg_write(ah, tx_time, |
| 68 | | reg + (AR5K_SET_SHORT_PREAMBLE << 2)); |
| 69 | | } |
| 70 | | +++ b/drivers/net/wireless/ath/ath5k/qcu.c |
| 71 | | @@ -550,7 +550,7 @@ int ath5k_hw_set_ifs_intervals(struct at |
| 72 | | else |
| 73 | | rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; |
| 74 | | |
| 75 | | - ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate); |
| 76 | | + ack_tx_time = ath5k_hw_get_frame_duration(ah, 10, rate, false); |
| 77 | | |
| 78 | | /* ack_tx_time includes an SIFS already */ |
| 79 | | eifs = ack_tx_time + sifs + 2 * slot_time; |
| package/mac80211/patches/464-ath5k_optimize_tx_desc_setup.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/desc.c |
| 2 | | @@ -184,6 +184,7 @@ static int ath5k_hw_setup_4word_tx_desc( |
| 3 | | { |
| 4 | | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
| 5 | | unsigned int frame_len; |
| 6 | | + u32 txctl0 = 0, txctl1 = 0, txctl2 = 0, txctl3 = 0; |
| 7 | | |
| 8 | | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
| 9 | | |
| 10 | | @@ -209,7 +210,8 @@ static int ath5k_hw_setup_4word_tx_desc( |
| 11 | | tx_power = AR5K_TUNE_MAX_TXPOWER; |
| 12 | | |
| 13 | | /* Clear descriptor */ |
| 14 | | - memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); |
| 15 | | + memset(&desc->ud.ds_tx5212.tx_stat, 0, |
| 16 | | + sizeof(desc->ud.ds_tx5212.tx_stat)); |
| 17 | | |
| 18 | | /* Setup control descriptor */ |
| 19 | | |
| 20 | | @@ -221,7 +223,7 @@ static int ath5k_hw_setup_4word_tx_desc( |
| 21 | | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
| 22 | | return -EINVAL; |
| 23 | | |
| 24 | | - tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; |
| 25 | | + txctl0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; |
| 26 | | |
| 27 | | /* Verify and set buffer length */ |
| 28 | | |
| 29 | | @@ -232,21 +234,17 @@ static int ath5k_hw_setup_4word_tx_desc( |
| 30 | | if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) |
| 31 | | return -EINVAL; |
| 32 | | |
| 33 | | - tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; |
| 34 | | + txctl1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; |
| 35 | | |
| 36 | | - tx_ctl->tx_control_0 |= |
| 37 | | - AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | |
| 38 | | - AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
| 39 | | - tx_ctl->tx_control_1 |= AR5K_REG_SM(type, |
| 40 | | - AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
| 41 | | - tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0, |
| 42 | | - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
| 43 | | - tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
| 44 | | + txctl0 |= AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | |
| 45 | | + AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); |
| 46 | | + txctl1 |= AR5K_REG_SM(type, AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); |
| 47 | | + txctl2 = AR5K_REG_SM(tx_tries0, AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); |
| 48 | | + txctl3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
| 49 | | |
| 50 | | #define _TX_FLAGS(_c, _flag) \ |
| 51 | | if (flags & AR5K_TXDESC_##_flag) { \ |
| 52 | | - tx_ctl->tx_control_##_c |= \ |
| 53 | | - AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ |
| 54 | | + txctl##_c |= AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ |
| 55 | | } |
| 56 | | |
| 57 | | _TX_FLAGS(0, CLRDMASK); |
| 58 | | @@ -262,8 +260,8 @@ static int ath5k_hw_setup_4word_tx_desc( |
| 59 | | * WEP crap |
| 60 | | */ |
| 61 | | if (key_index != AR5K_TXKEYIX_INVALID) { |
| 62 | | - tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
| 63 | | - tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, |
| 64 | | + txctl0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; |
| 65 | | + txctl1 |= AR5K_REG_SM(key_index, |
| 66 | | AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_IDX); |
| 67 | | } |
| 68 | | |
| 69 | | @@ -274,12 +272,16 @@ static int ath5k_hw_setup_4word_tx_desc( |
| 70 | | if ((flags & AR5K_TXDESC_RTSENA) && |
| 71 | | (flags & AR5K_TXDESC_CTSENA)) |
| 72 | | return -EINVAL; |
| 73 | | - tx_ctl->tx_control_2 |= rtscts_duration & |
| 74 | | - AR5K_4W_TX_DESC_CTL2_RTS_DURATION; |
| 75 | | - tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, |
| 76 | | + txctl2 |= rtscts_duration & AR5K_4W_TX_DESC_CTL2_RTS_DURATION; |
| 77 | | + txctl3 |= AR5K_REG_SM(rtscts_rate, |
| 78 | | AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); |
| 79 | | } |
| 80 | | |
| 81 | | + tx_ctl->tx_control_0 = txctl0; |
| 82 | | + tx_ctl->tx_control_1 = txctl1; |
| 83 | | + tx_ctl->tx_control_2 = txctl2; |
| 84 | | + tx_ctl->tx_control_3 = txctl3; |
| 85 | | + |
| 86 | | return 0; |
| 87 | | } |
| 88 | | |
| package/mac80211/patches/466-ath5k_optimize_tx_status.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/desc.c |
| 2 | | @@ -401,32 +401,38 @@ static int ath5k_hw_proc_4word_tx_status |
| 3 | | { |
| 4 | | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
| 5 | | struct ath5k_hw_tx_status *tx_status; |
| 6 | | + u32 txstat0, txstat1, txctl2; |
| 7 | | |
| 8 | | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
| 9 | | tx_status = &desc->ud.ds_tx5212.tx_stat; |
| 10 | | |
| 11 | | + txstat1 = ACCESS_ONCE(tx_status->tx_status_1); |
| 12 | | + |
| 13 | | /* No frame has been send or error */ |
| 14 | | - if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) |
| 15 | | + if (unlikely(!(txstat1 & AR5K_DESC_TX_STATUS1_DONE))) |
| 16 | | return -EINPROGRESS; |
| 17 | | |
| 18 | | + txstat0 = ACCESS_ONCE(tx_status->tx_status_0); |
| 19 | | + txctl2 = ACCESS_ONCE(tx_ctl->tx_control_2); |
| 20 | | + |
| 21 | | /* |
| 22 | | * Get descriptor status |
| 23 | | */ |
| 24 | | - ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, |
| 25 | | + ts->ts_tstamp = AR5K_REG_MS(txstat0, |
| 26 | | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
| 27 | | - ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, |
| 28 | | + ts->ts_shortretry = AR5K_REG_MS(txstat0, |
| 29 | | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
| 30 | | - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, |
| 31 | | + ts->ts_longretry = AR5K_REG_MS(txstat0, |
| 32 | | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
| 33 | | - ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, |
| 34 | | + ts->ts_seqnum = AR5K_REG_MS(txstat1, |
| 35 | | AR5K_DESC_TX_STATUS1_SEQ_NUM); |
| 36 | | - ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, |
| 37 | | + ts->ts_rssi = AR5K_REG_MS(txstat1, |
| 38 | | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
| 39 | | - ts->ts_antenna = (tx_status->tx_status_1 & |
| 40 | | + ts->ts_antenna = (txstat1 & |
| 41 | | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA_5212) ? 2 : 1; |
| 42 | | ts->ts_status = 0; |
| 43 | | |
| 44 | | - ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, |
| 45 | | + ts->ts_final_idx = AR5K_REG_MS(txstat1, |
| 46 | | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); |
| 47 | | |
| 48 | | /* The longretry counter has the number of un-acked retries |
| 49 | | @@ -437,17 +443,17 @@ static int ath5k_hw_proc_4word_tx_status |
| 50 | | ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; |
| 51 | | switch (ts->ts_final_idx) { |
| 52 | | case 3: |
| 53 | | - ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, |
| 54 | | + ts->ts_retry[2] = AR5K_REG_MS(txctl2, |
| 55 | | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); |
| 56 | | ts->ts_longretry += ts->ts_retry[2]; |
| 57 | | /* fall through */ |
| 58 | | case 2: |
| 59 | | - ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, |
| 60 | | + ts->ts_retry[1] = AR5K_REG_MS(txctl2, |
| 61 | | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); |
| 62 | | ts->ts_longretry += ts->ts_retry[1]; |
| 63 | | /* fall through */ |
| 64 | | case 1: |
| 65 | | - ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, |
| 66 | | + ts->ts_retry[0] = AR5K_REG_MS(txctl2, |
| 67 | | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); |
| 68 | | ts->ts_longretry += ts->ts_retry[0]; |
| 69 | | /* fall through */ |
| 70 | | @@ -456,15 +462,14 @@ static int ath5k_hw_proc_4word_tx_status |
| 71 | | } |
| 72 | | |
| 73 | | /* TX error */ |
| 74 | | - if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
| 75 | | - if (tx_status->tx_status_0 & |
| 76 | | - AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
| 77 | | + if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
| 78 | | + if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
| 79 | | ts->ts_status |= AR5K_TXERR_XRETRY; |
| 80 | | |
| 81 | | - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) |
| 82 | | + if (txstat0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) |
| 83 | | ts->ts_status |= AR5K_TXERR_FIFO; |
| 84 | | |
| 85 | | - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) |
| 86 | | + if (txstat0 & AR5K_DESC_TX_STATUS0_FILTERED) |
| 87 | | ts->ts_status |= AR5K_TXERR_FILT; |
| 88 | | } |
| 89 | | |
| package/mac80211/patches/467-ath5k_optimize_rx_status.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/desc.c |
| 2 | | @@ -603,37 +603,37 @@ static int ath5k_hw_proc_5212_rx_status( |
| 3 | | struct ath5k_rx_status *rs) |
| 4 | | { |
| 5 | | struct ath5k_hw_rx_status *rx_status; |
| 6 | | + u32 rxstat0, rxstat1; |
| 7 | | |
| 8 | | rx_status = &desc->ud.ds_rx.rx_stat; |
| 9 | | + rxstat1 = ACCESS_ONCE(rx_status->rx_status_1); |
| 10 | | |
| 11 | | /* No frame received / not ready */ |
| 12 | | - if (unlikely(!(rx_status->rx_status_1 & |
| 13 | | - AR5K_5212_RX_DESC_STATUS1_DONE))) |
| 14 | | + if (unlikely(!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_DONE))) |
| 15 | | return -EINPROGRESS; |
| 16 | | |
| 17 | | memset(rs, 0, sizeof(struct ath5k_rx_status)); |
| 18 | | + rxstat0 = ACCESS_ONCE(rx_status->rx_status_0); |
| 19 | | |
| 20 | | /* |
| 21 | | * Frame receive status |
| 22 | | */ |
| 23 | | - rs->rs_datalen = rx_status->rx_status_0 & |
| 24 | | - AR5K_5212_RX_DESC_STATUS0_DATA_LEN; |
| 25 | | - rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, |
| 26 | | + rs->rs_datalen = rxstat0 & AR5K_5212_RX_DESC_STATUS0_DATA_LEN; |
| 27 | | + rs->rs_rssi = AR5K_REG_MS(rxstat0, |
| 28 | | AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); |
| 29 | | - rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, |
| 30 | | + rs->rs_rate = AR5K_REG_MS(rxstat0, |
| 31 | | AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); |
| 32 | | - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, |
| 33 | | + rs->rs_antenna = AR5K_REG_MS(rxstat0, |
| 34 | | AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); |
| 35 | | - rs->rs_more = !!(rx_status->rx_status_0 & |
| 36 | | - AR5K_5212_RX_DESC_STATUS0_MORE); |
| 37 | | - rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, |
| 38 | | + rs->rs_more = !!(rxstat0 & AR5K_5212_RX_DESC_STATUS0_MORE); |
| 39 | | + rs->rs_tstamp = AR5K_REG_MS(rxstat1, |
| 40 | | AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); |
| 41 | | |
| 42 | | /* |
| 43 | | * Key table status |
| 44 | | */ |
| 45 | | - if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
| 46 | | - rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, |
| 47 | | + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) |
| 48 | | + rs->rs_keyix = AR5K_REG_MS(rxstat1, |
| 49 | | AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); |
| 50 | | else |
| 51 | | rs->rs_keyix = AR5K_RXKEYIX_INVALID; |
| 52 | | @@ -641,27 +641,22 @@ static int ath5k_hw_proc_5212_rx_status( |
| 53 | | /* |
| 54 | | * Receive/descriptor errors |
| 55 | | */ |
| 56 | | - if (!(rx_status->rx_status_1 & |
| 57 | | - AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
| 58 | | - if (rx_status->rx_status_1 & |
| 59 | | - AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
| 60 | | + if (!(rxstat1 & AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { |
| 61 | | + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) |
| 62 | | rs->rs_status |= AR5K_RXERR_CRC; |
| 63 | | |
| 64 | | - if (rx_status->rx_status_1 & |
| 65 | | - AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
| 66 | | + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { |
| 67 | | rs->rs_status |= AR5K_RXERR_PHY; |
| 68 | | - rs->rs_phyerr = AR5K_REG_MS(rx_status->rx_status_1, |
| 69 | | + rs->rs_phyerr = AR5K_REG_MS(rxstat1, |
| 70 | | AR5K_5212_RX_DESC_STATUS1_PHY_ERROR_CODE); |
| 71 | | if (!ah->ah_capabilities.cap_has_phyerr_counters) |
| 72 | | ath5k_ani_phy_error_report(ah, rs->rs_phyerr); |
| 73 | | } |
| 74 | | |
| 75 | | - if (rx_status->rx_status_1 & |
| 76 | | - AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) |
| 77 | | + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) |
| 78 | | rs->rs_status |= AR5K_RXERR_DECRYPT; |
| 79 | | |
| 80 | | - if (rx_status->rx_status_1 & |
| 81 | | - AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
| 82 | | + if (rxstat1 & AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) |
| 83 | | rs->rs_status |= AR5K_RXERR_MIC; |
| 84 | | } |
| 85 | | return 0; |
| package/mac80211/patches/468-ath5k_remove_ts_retry.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/ath5k.h |
| 2 | | @@ -452,11 +452,10 @@ struct ath5k_tx_status { |
| 3 | | u16 ts_seqnum; |
| 4 | | u16 ts_tstamp; |
| 5 | | u8 ts_status; |
| 6 | | - u8 ts_retry[4]; |
| 7 | | u8 ts_final_idx; |
| 8 | | + u8 ts_final_retry; |
| 9 | | s8 ts_rssi; |
| 10 | | u8 ts_shortretry; |
| 11 | | - u8 ts_longretry; |
| 12 | | u8 ts_virtcol; |
| 13 | | u8 ts_antenna; |
| 14 | | }; |
| 15 | | +++ b/drivers/net/wireless/ath/ath5k/base.c |
| 16 | | @@ -1573,20 +1573,27 @@ ath5k_tx_frame_completed(struct ath5k_so |
| 17 | | struct ath5k_txq *txq, struct ath5k_tx_status *ts) |
| 18 | | { |
| 19 | | struct ieee80211_tx_info *info; |
| 20 | | + u8 tries[3]; |
| 21 | | int i; |
| 22 | | |
| 23 | | sc->stats.tx_all_count++; |
| 24 | | sc->stats.tx_bytes_count += skb->len; |
| 25 | | info = IEEE80211_SKB_CB(skb); |
| 26 | | |
| 27 | | + tries[0] = info->status.rates[0].count; |
| 28 | | + tries[1] = info->status.rates[1].count; |
| 29 | | + tries[2] = info->status.rates[2].count; |
| 30 | | + |
| 31 | | ieee80211_tx_info_clear_status(info); |
| 32 | | - for (i = 0; i <= ts->ts_final_idx; i++) { |
| 33 | | + |
| 34 | | + for (i = 0; i < ts->ts_final_idx; i++) { |
| 35 | | struct ieee80211_tx_rate *r = |
| 36 | | &info->status.rates[i]; |
| 37 | | |
| 38 | | - r->count = ts->ts_retry[i]; |
| 39 | | + r->count = tries[i]; |
| 40 | | } |
| 41 | | |
| 42 | | + info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry; |
| 43 | | info->status.rates[ts->ts_final_idx + 1].idx = -1; |
| 44 | | |
| 45 | | if (unlikely(ts->ts_status)) { |
| 46 | | +++ b/drivers/net/wireless/ath/ath5k/desc.c |
| 47 | | @@ -366,7 +366,7 @@ static int ath5k_hw_proc_2word_tx_status |
| 48 | | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
| 49 | | ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, |
| 50 | | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
| 51 | | - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, |
| 52 | | + ts->ts_final_retry = AR5K_REG_MS(tx_status->tx_status_0, |
| 53 | | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
| 54 | | /*TODO: ts->ts_virtcol + test*/ |
| 55 | | ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, |
| 56 | | @@ -375,7 +375,6 @@ static int ath5k_hw_proc_2word_tx_status |
| 57 | | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
| 58 | | ts->ts_antenna = 1; |
| 59 | | ts->ts_status = 0; |
| 60 | | - ts->ts_retry[0] = ts->ts_longretry; |
| 61 | | ts->ts_final_idx = 0; |
| 62 | | |
| 63 | | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
| 64 | | @@ -401,7 +400,7 @@ static int ath5k_hw_proc_4word_tx_status |
| 65 | | { |
| 66 | | struct ath5k_hw_4w_tx_ctl *tx_ctl; |
| 67 | | struct ath5k_hw_tx_status *tx_status; |
| 68 | | - u32 txstat0, txstat1, txctl2; |
| 69 | | + u32 txstat0, txstat1; |
| 70 | | |
| 71 | | tx_ctl = &desc->ud.ds_tx5212.tx_ctl; |
| 72 | | tx_status = &desc->ud.ds_tx5212.tx_stat; |
| 73 | | @@ -413,7 +412,6 @@ static int ath5k_hw_proc_4word_tx_status |
| 74 | | return -EINPROGRESS; |
| 75 | | |
| 76 | | txstat0 = ACCESS_ONCE(tx_status->tx_status_0); |
| 77 | | - txctl2 = ACCESS_ONCE(tx_ctl->tx_control_2); |
| 78 | | |
| 79 | | /* |
| 80 | | * Get descriptor status |
| 81 | | @@ -422,7 +420,7 @@ static int ath5k_hw_proc_4word_tx_status |
| 82 | | AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); |
| 83 | | ts->ts_shortretry = AR5K_REG_MS(txstat0, |
| 84 | | AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); |
| 85 | | - ts->ts_longretry = AR5K_REG_MS(txstat0, |
| 86 | | + ts->ts_final_retry = AR5K_REG_MS(txstat0, |
| 87 | | AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); |
| 88 | | ts->ts_seqnum = AR5K_REG_MS(txstat1, |
| 89 | | AR5K_DESC_TX_STATUS1_SEQ_NUM); |
| 90 | | @@ -435,32 +433,6 @@ static int ath5k_hw_proc_4word_tx_status |
| 91 | | ts->ts_final_idx = AR5K_REG_MS(txstat1, |
| 92 | | AR5K_DESC_TX_STATUS1_FINAL_TS_IX_5212); |
| 93 | | |
| 94 | | - /* The longretry counter has the number of un-acked retries |
| 95 | | - * for the final rate. To get the total number of retries |
| 96 | | - * we have to add the retry counters for the other rates |
| 97 | | - * as well |
| 98 | | - */ |
| 99 | | - ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; |
| 100 | | - switch (ts->ts_final_idx) { |
| 101 | | - case 3: |
| 102 | | - ts->ts_retry[2] = AR5K_REG_MS(txctl2, |
| 103 | | - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); |
| 104 | | - ts->ts_longretry += ts->ts_retry[2]; |
| 105 | | - /* fall through */ |
| 106 | | - case 2: |
| 107 | | - ts->ts_retry[1] = AR5K_REG_MS(txctl2, |
| 108 | | - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); |
| 109 | | - ts->ts_longretry += ts->ts_retry[1]; |
| 110 | | - /* fall through */ |
| 111 | | - case 1: |
| 112 | | - ts->ts_retry[0] = AR5K_REG_MS(txctl2, |
| 113 | | - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); |
| 114 | | - ts->ts_longretry += ts->ts_retry[0]; |
| 115 | | - /* fall through */ |
| 116 | | - case 0: |
| 117 | | - break; |
| 118 | | - } |
| 119 | | - |
| 120 | | /* TX error */ |
| 121 | | if (!(txstat0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
| 122 | | if (txstat0 & AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) |
| package/mac80211/patches/469-ath5k_cleanup_debugfs.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/debug.c |
| 2 | | @@ -888,64 +888,37 @@ static const struct file_operations fops |
| 3 | | void |
| 4 | | ath5k_debug_init_device(struct ath5k_softc *sc) |
| 5 | | { |
| 6 | | + struct dentry *phydir; |
| 7 | | + |
| 8 | | sc->debug.level = ath5k_debug; |
| 9 | | |
| 10 | | - sc->debug.debugfs_phydir = debugfs_create_dir("ath5k", |
| 11 | | - sc->hw->wiphy->debugfsdir); |
| 12 | | + phydir = debugfs_create_dir("ath5k", sc->hw->wiphy->debugfsdir); |
| 13 | | + if (!phydir) |
| 14 | | + return; |
| 15 | | |
| 16 | | - sc->debug.debugfs_debug = debugfs_create_file("debug", |
| 17 | | - S_IWUSR | S_IRUSR, |
| 18 | | - sc->debug.debugfs_phydir, sc, &fops_debug); |
| 19 | | - |
| 20 | | - sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, |
| 21 | | - sc->debug.debugfs_phydir, sc, &fops_registers); |
| 22 | | - |
| 23 | | - sc->debug.debugfs_beacon = debugfs_create_file("beacon", |
| 24 | | - S_IWUSR | S_IRUSR, |
| 25 | | - sc->debug.debugfs_phydir, sc, &fops_beacon); |
| 26 | | - |
| 27 | | - sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, |
| 28 | | - sc->debug.debugfs_phydir, sc, &fops_reset); |
| 29 | | - |
| 30 | | - sc->debug.debugfs_antenna = debugfs_create_file("antenna", |
| 31 | | - S_IWUSR | S_IRUSR, |
| 32 | | - sc->debug.debugfs_phydir, sc, &fops_antenna); |
| 33 | | - |
| 34 | | - sc->debug.debugfs_misc = debugfs_create_file("misc", |
| 35 | | - S_IRUSR, |
| 36 | | - sc->debug.debugfs_phydir, sc, &fops_misc); |
| 37 | | - |
| 38 | | - sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", |
| 39 | | - S_IWUSR | S_IRUSR, |
| 40 | | - sc->debug.debugfs_phydir, sc, |
| 41 | | - &fops_frameerrors); |
| 42 | | - |
| 43 | | - sc->debug.debugfs_ani = debugfs_create_file("ani", |
| 44 | | - S_IWUSR | S_IRUSR, |
| 45 | | - sc->debug.debugfs_phydir, sc, |
| 46 | | - &fops_ani); |
| 47 | | - |
| 48 | | - sc->debug.debugfs_queue = debugfs_create_file("queue", |
| 49 | | - S_IWUSR | S_IRUSR, |
| 50 | | - sc->debug.debugfs_phydir, sc, |
| 51 | | - &fops_queue); |
| 52 | | -} |
| 53 | | + debugfs_create_file("debug", S_IWUSR | S_IRUSR, phydir, sc, |
| 54 | | + &fops_debug); |
| 55 | | |
| 56 | | -void |
| 57 | | -ath5k_debug_finish_device(struct ath5k_softc *sc) |
| 58 | | -{ |
| 59 | | - debugfs_remove(sc->debug.debugfs_debug); |
| 60 | | - debugfs_remove(sc->debug.debugfs_registers); |
| 61 | | - debugfs_remove(sc->debug.debugfs_beacon); |
| 62 | | - debugfs_remove(sc->debug.debugfs_reset); |
| 63 | | - debugfs_remove(sc->debug.debugfs_antenna); |
| 64 | | - debugfs_remove(sc->debug.debugfs_misc); |
| 65 | | - debugfs_remove(sc->debug.debugfs_frameerrors); |
| 66 | | - debugfs_remove(sc->debug.debugfs_ani); |
| 67 | | - debugfs_remove(sc->debug.debugfs_queue); |
| 68 | | - debugfs_remove(sc->debug.debugfs_phydir); |
| 69 | | -} |
| 70 | | + debugfs_create_file("registers", S_IRUSR, phydir, sc, &fops_registers); |
| 71 | | + |
| 72 | | + debugfs_create_file("beacon", S_IWUSR | S_IRUSR, phydir, sc, |
| 73 | | + &fops_beacon); |
| 74 | | |
| 75 | | + debugfs_create_file("reset", S_IWUSR, phydir, sc, &fops_reset); |
| 76 | | + |
| 77 | | + debugfs_create_file("antenna", S_IWUSR | S_IRUSR, phydir, sc, |
| 78 | | + &fops_antenna); |
| 79 | | + |
| 80 | | + debugfs_create_file("misc", S_IRUSR, phydir, sc, &fops_misc); |
| 81 | | + |
| 82 | | + debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, phydir, sc, |
| 83 | | + &fops_frameerrors); |
| 84 | | + |
| 85 | | + debugfs_create_file("ani", S_IWUSR | S_IRUSR, phydir, sc, &fops_ani); |
| 86 | | + |
| 87 | | + debugfs_create_file("queue", S_IWUSR | S_IRUSR, phydir, sc, |
| 88 | | + &fops_queue); |
| 89 | | +} |
| 90 | | |
| 91 | | /* functions used in other places */ |
| 92 | | |
| 93 | | +++ b/drivers/net/wireless/ath/ath5k/debug.h |
| 94 | | @@ -68,17 +68,6 @@ struct ath5k_buf; |
| 95 | | |
| 96 | | struct ath5k_dbg_info { |
| 97 | | unsigned int level; /* debug level */ |
| 98 | | - /* debugfs entries */ |
| 99 | | - struct dentry *debugfs_phydir; |
| 100 | | - struct dentry *debugfs_debug; |
| 101 | | - struct dentry *debugfs_registers; |
| 102 | | - struct dentry *debugfs_beacon; |
| 103 | | - struct dentry *debugfs_reset; |
| 104 | | - struct dentry *debugfs_antenna; |
| 105 | | - struct dentry *debugfs_misc; |
| 106 | | - struct dentry *debugfs_frameerrors; |
| 107 | | - struct dentry *debugfs_ani; |
| 108 | | - struct dentry *debugfs_queue; |
| 109 | | }; |
| 110 | | |
| 111 | | /** |
| 112 | | @@ -141,9 +130,6 @@ void |
| 113 | | ath5k_debug_init_device(struct ath5k_softc *sc); |
| 114 | | |
| 115 | | void |
| 116 | | -ath5k_debug_finish_device(struct ath5k_softc *sc); |
| 117 | | - |
| 118 | | -void |
| 119 | | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); |
| 120 | | |
| 121 | | void |
| 122 | | @@ -167,9 +153,6 @@ static inline void |
| 123 | | ath5k_debug_init_device(struct ath5k_softc *sc) {} |
| 124 | | |
| 125 | | static inline void |
| 126 | | -ath5k_debug_finish_device(struct ath5k_softc *sc) {} |
| 127 | | - |
| 128 | | -static inline void |
| 129 | | ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} |
| 130 | | |
| 131 | | static inline void |
| 132 | | +++ b/drivers/net/wireless/ath/ath5k/base.c |
| 133 | | @@ -2901,7 +2901,6 @@ ath5k_deinit_softc(struct ath5k_softc *s |
| 134 | | * XXX: ??? detach ath5k_hw ??? |
| 135 | | * Other than that, it's straightforward... |
| 136 | | */ |
| 137 | | - ath5k_debug_finish_device(sc); |
| 138 | | ieee80211_unregister_hw(hw); |
| 139 | | ath5k_desc_free(sc); |
| 140 | | ath5k_txq_release(sc); |
| package/mac80211/patches/470-ath5k_decrease_irq_load.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/ath5k.h |
| 2 | | @@ -872,6 +872,19 @@ enum ath5k_int { |
| 3 | | AR5K_INT_QTRIG = 0x40000000, /* Non common */ |
| 4 | | AR5K_INT_GLOBAL = 0x80000000, |
| 5 | | |
| 6 | | + AR5K_INT_TX_ALL = AR5K_INT_TXOK |
| 7 | | + | AR5K_INT_TXDESC |
| 8 | | + | AR5K_INT_TXERR |
| 9 | | + | AR5K_INT_TXEOL |
| 10 | | + | AR5K_INT_TXURN, |
| 11 | | + |
| 12 | | + AR5K_INT_RX_ALL = AR5K_INT_RXOK |
| 13 | | + | AR5K_INT_RXDESC |
| 14 | | + | AR5K_INT_RXERR |
| 15 | | + | AR5K_INT_RXNOFRM |
| 16 | | + | AR5K_INT_RXEOL |
| 17 | | + | AR5K_INT_RXORN, |
| 18 | | + |
| 19 | | AR5K_INT_COMMON = AR5K_INT_RXOK |
| 20 | | | AR5K_INT_RXDESC |
| 21 | | | AR5K_INT_RXERR |
| 22 | | +++ b/drivers/net/wireless/ath/ath5k/base.c |
| 23 | | @@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_soft |
| 24 | | } |
| 25 | | |
| 26 | | static void |
| 27 | | +ath5k_set_current_imask(struct ath5k_softc *sc) |
| 28 | | +{ |
| 29 | | + enum ath5k_int imask = sc->imask; |
| 30 | | + unsigned long flags; |
| 31 | | + |
| 32 | | + spin_lock_irqsave(&sc->irqlock, flags); |
| 33 | | + if (sc->rx_pending) |
| 34 | | + imask &= ~AR5K_INT_RX_ALL; |
| 35 | | + if (sc->tx_pending) |
| 36 | | + imask &= ~AR5K_INT_TX_ALL; |
| 37 | | + ath5k_hw_set_imr(sc->ah, imask); |
| 38 | | + spin_unlock_irqrestore(&sc->irqlock, flags); |
| 39 | | +} |
| 40 | | + |
| 41 | | +static void |
| 42 | | ath5k_tasklet_rx(unsigned long data) |
| 43 | | { |
| 44 | | struct ath5k_rx_status rs = {}; |
| 45 | | @@ -1506,6 +1521,8 @@ next: |
| 46 | | } while (ath5k_rxbuf_setup(sc, bf) == 0); |
| 47 | | unlock: |
| 48 | | spin_unlock(&sc->rxbuflock); |
| 49 | | + sc->rx_pending = false; |
| 50 | | + ath5k_set_current_imask(sc); |
| 51 | | } |
| 52 | | |
| 53 | | |
| 54 | | @@ -1693,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data) |
| 55 | | for (i=0; i < AR5K_NUM_TX_QUEUES; i++) |
| 56 | | if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) |
| 57 | | ath5k_tx_processq(sc, &sc->txqs[i]); |
| 58 | | + |
| 59 | | + sc->tx_pending = false; |
| 60 | | + ath5k_set_current_imask(sc); |
| 61 | | } |
| 62 | | |
| 63 | | |
| 64 | | @@ -2122,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k |
| 65 | | * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ |
| 66 | | } |
| 67 | | |
| 68 | | +static void |
| 69 | | +ath5k_schedule_rx(struct ath5k_softc *sc) |
| 70 | | +{ |
| 71 | | + sc->rx_pending = true; |
| 72 | | + tasklet_schedule(&sc->rxtq); |
| 73 | | +} |
| 74 | | + |
| 75 | | +static void |
| 76 | | +ath5k_schedule_tx(struct ath5k_softc *sc) |
| 77 | | +{ |
| 78 | | + sc->tx_pending = true; |
| 79 | | + tasklet_schedule(&sc->txtq); |
| 80 | | +} |
| 81 | | + |
| 82 | | irqreturn_t |
| 83 | | ath5k_intr(int irq, void *dev_id) |
| 84 | | { |
| 85 | | @@ -2164,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id) |
| 86 | | ieee80211_queue_work(sc->hw, &sc->reset_work); |
| 87 | | } |
| 88 | | else |
| 89 | | - tasklet_schedule(&sc->rxtq); |
| 90 | | + ath5k_schedule_rx(sc); |
| 91 | | } else { |
| 92 | | if (status & AR5K_INT_SWBA) { |
| 93 | | tasklet_hi_schedule(&sc->beacontq); |
| 94 | | @@ -2182,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id) |
| 95 | | ath5k_hw_update_tx_triglevel(ah, true); |
| 96 | | } |
| 97 | | if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) |
| 98 | | - tasklet_schedule(&sc->rxtq); |
| 99 | | + ath5k_schedule_rx(sc); |
| 100 | | if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC |
| 101 | | | AR5K_INT_TXERR | AR5K_INT_TXEOL)) |
| 102 | | - tasklet_schedule(&sc->txtq); |
| 103 | | + ath5k_schedule_tx(sc); |
| 104 | | if (status & AR5K_INT_BMISS) { |
| 105 | | /* TODO */ |
| 106 | | } |
| 107 | | @@ -2204,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id) |
| 108 | | |
| 109 | | } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); |
| 110 | | |
| 111 | | + if (sc->rx_pending || sc->tx_pending) |
| 112 | | + ath5k_set_current_imask(sc); |
| 113 | | + |
| 114 | | if (unlikely(!counter)) |
| 115 | | ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); |
| 116 | | |
| 117 | | @@ -2575,6 +2612,8 @@ done: |
| 118 | | |
| 119 | | static void stop_tasklets(struct ath5k_softc *sc) |
| 120 | | { |
| 121 | | + sc->rx_pending = false; |
| 122 | | + sc->tx_pending = false; |
| 123 | | tasklet_kill(&sc->rxtq); |
| 124 | | tasklet_kill(&sc->txtq); |
| 125 | | tasklet_kill(&sc->calib); |
| 126 | | +++ b/drivers/net/wireless/ath/ath5k/base.h |
| 127 | | @@ -207,6 +207,10 @@ struct ath5k_softc { |
| 128 | | |
| 129 | | enum ath5k_int imask; /* interrupt mask copy */ |
| 130 | | |
| 131 | | + spinlock_t irqlock; |
| 132 | | + bool rx_pending; /* rx tasklet pending */ |
| 133 | | + bool tx_pending; /* tx tasklet pending */ |
| 134 | | + |
| 135 | | u8 lladdr[ETH_ALEN]; |
| 136 | | u8 bssidmask[ETH_ALEN]; |
| 137 | | |
| package/mac80211/patches/473-ath5k_read_mac_addr.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath5k/ath5k.h |
| 2 | | @@ -1159,6 +1159,7 @@ struct ath_bus_ops { |
| 3 | | enum ath_bus_type ath_bus_type; |
| 4 | | void (*read_cachesize)(struct ath_common *common, int *csz); |
| 5 | | bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data); |
| 6 | | + int (*eeprom_read_mac)(struct ath5k_hw *ah, u8 *mac); |
| 7 | | }; |
| 8 | | |
| 9 | | /* |
| 10 | | @@ -1244,7 +1245,6 @@ int ath5k_hw_dma_stop(struct ath5k_hw *a |
| 11 | | /* EEPROM access functions */ |
| 12 | | int ath5k_eeprom_init(struct ath5k_hw *ah); |
| 13 | | void ath5k_eeprom_detach(struct ath5k_hw *ah); |
| 14 | | -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); |
| 15 | | |
| 16 | | |
| 17 | | /* Protocol Control Unit Functions */ |
| 18 | | +++ b/drivers/net/wireless/ath/ath5k/eeprom.c |
| 19 | | @@ -1723,46 +1723,6 @@ ath5k_eeprom_read_spur_chans(struct ath5 |
| 20 | | return ret; |
| 21 | | } |
| 22 | | |
| 23 | | -/* |
| 24 | | - * Read the MAC address from eeprom or platform_data |
| 25 | | - */ |
| 26 | | -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) |
| 27 | | -{ |
| 28 | | - u8 mac_d[ETH_ALEN] = {}; |
| 29 | | - u32 total, offset; |
| 30 | | - u16 data; |
| 31 | | - int octet; |
| 32 | | - struct ath5k_platform_data *pdata = NULL; |
| 33 | | - |
| 34 | | - if (ah->ah_sc->pdev) |
| 35 | | - pdata = ah->ah_sc->pdev->dev.platform_data; |
| 36 | | - |
| 37 | | - if (pdata && pdata->macaddr) |
| 38 | | - { |
| 39 | | - memcpy(mac, pdata->macaddr, ETH_ALEN); |
| 40 | | - return 0; |
| 41 | | - } |
| 42 | | - |
| 43 | | - AR5K_EEPROM_READ(0x20, data); |
| 44 | | - |
| 45 | | - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { |
| 46 | | - AR5K_EEPROM_READ(offset, data); |
| 47 | | - |
| 48 | | - total += data; |
| 49 | | - mac_d[octet + 1] = data & 0xff; |
| 50 | | - mac_d[octet] = data >> 8; |
| 51 | | - octet += 2; |
| 52 | | - } |
| 53 | | - |
| 54 | | - if (!total || total == 3 * 0xffff) |
| 55 | | - return -EINVAL; |
| 56 | | - |
| 57 | | - memcpy(mac, mac_d, ETH_ALEN); |
| 58 | | - |
| 59 | | - return 0; |
| 60 | | -} |
| 61 | | - |
| 62 | | - |
| 63 | | /***********************\ |
| 64 | | * Init/Detach functions * |
| 65 | | \***********************/ |
| 66 | | +++ b/drivers/net/wireless/ath/ath5k/pci.c |
| 67 | | @@ -18,6 +18,7 @@ |
| 68 | | #include <linux/pci.h> |
| 69 | | #include <linux/pci-aspm.h> |
| 70 | | #include <linux/ath5k_platform.h> |
| 71 | | +#include <linux/etherdevice.h> |
| 72 | | #include "../ath.h" |
| 73 | | #include "ath5k.h" |
| 74 | | #include "debug.h" |
| 75 | | @@ -122,11 +123,52 @@ int ath5k_hw_read_srev(struct ath5k_hw * |
| 76 | | return 0; |
| 77 | | } |
| 78 | | |
| 79 | | +/* |
| 80 | | + * Read the MAC address from eeprom or platform_data |
| 81 | | + */ |
| 82 | | +static int ath5k_pci_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) |
| 83 | | +{ |
| 84 | | + u8 mac_d[ETH_ALEN] = {}; |
| 85 | | + u32 total, offset; |
| 86 | | + u16 data; |
| 87 | | + int octet; |
| 88 | | + struct ath5k_platform_data *pdata = NULL; |
| 89 | | + |
| 90 | | + if (ah->ah_sc->pdev) |
| 91 | | + pdata = ah->ah_sc->pdev->dev.platform_data; |
| 92 | | + |
| 93 | | + if (pdata && pdata->macaddr) |
| 94 | | + { |
| 95 | | + memcpy(mac, pdata->macaddr, ETH_ALEN); |
| 96 | | + return 0; |
| 97 | | + } |
| 98 | | + |
| 99 | | + AR5K_EEPROM_READ(0x20, data); |
| 100 | | + |
| 101 | | + for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { |
| 102 | | + AR5K_EEPROM_READ(offset, data); |
| 103 | | + |
| 104 | | + total += data; |
| 105 | | + mac_d[octet + 1] = data & 0xff; |
| 106 | | + mac_d[octet] = data >> 8; |
| 107 | | + octet += 2; |
| 108 | | + } |
| 109 | | + |
| 110 | | + if (!total || total == 3 * 0xffff) |
| 111 | | + return -EINVAL; |
| 112 | | + |
| 113 | | + memcpy(mac, mac_d, ETH_ALEN); |
| 114 | | + |
| 115 | | + return 0; |
| 116 | | +} |
| 117 | | + |
| 118 | | + |
| 119 | | /* Common ath_bus_opts structure */ |
| 120 | | static const struct ath_bus_ops ath_pci_bus_ops = { |
| 121 | | .ath_bus_type = ATH_PCI, |
| 122 | | .read_cachesize = ath5k_pci_read_cachesize, |
| 123 | | .eeprom_read = ath5k_pci_eeprom_read, |
| 124 | | + .eeprom_read_mac = ath5k_pci_eeprom_read_mac, |
| 125 | | }; |
| 126 | | |
| 127 | | /********************\ |
| 128 | | +++ b/drivers/net/wireless/ath/ath5k/ahb.c |
| 129 | | @@ -18,6 +18,7 @@ |
| 130 | | |
| 131 | | #include <linux/nl80211.h> |
| 132 | | #include <linux/platform_device.h> |
| 133 | | +#include <linux/etherdevice.h> |
| 134 | | #include <ar231x_platform.h> |
| 135 | | #include "ath5k.h" |
| 136 | | #include "debug.h" |
| 137 | | @@ -62,10 +63,27 @@ int ath5k_hw_read_srev(struct ath5k_hw * |
| 138 | | return 0; |
| 139 | | } |
| 140 | | |
| 141 | | +static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) |
| 142 | | +{ |
| 143 | | + struct ath5k_softc *sc = ah->ah_sc; |
| 144 | | + struct platform_device *pdev = to_platform_device(sc->dev); |
| 145 | | + struct ar231x_board_config *bcfg = pdev->dev.platform_data; |
| 146 | | + u8 *cfg_mac; |
| 147 | | + |
| 148 | | + if (to_platform_device(sc->dev)->id == 0) |
| 149 | | + cfg_mac = bcfg->config->wlan0_mac; |
| 150 | | + else |
| 151 | | + cfg_mac = bcfg->config->wlan1_mac; |
| 152 | | + |
| 153 | | + memcpy(mac, cfg_mac, ETH_ALEN); |
| 154 | | + return 0; |
| 155 | | +} |
| 156 | | + |
| 157 | | static const struct ath_bus_ops ath_ahb_bus_ops = { |
| 158 | | .ath_bus_type = ATH_AHB, |
| 159 | | .read_cachesize = ath5k_ahb_read_cachesize, |
| 160 | | .eeprom_read = ath5k_ahb_eeprom_read, |
| 161 | | + .eeprom_read_mac = ath5k_ahb_eeprom_read_mac, |
| 162 | | }; |
| 163 | | |
| 164 | | /*Initialization*/ |
| 165 | | +++ b/drivers/net/wireless/ath/ath5k/base.c |
| 166 | | @@ -2880,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw) |
| 167 | | INIT_WORK(&sc->reset_work, ath5k_reset_work); |
| 168 | | INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); |
| 169 | | |
| 170 | | - ret = ath5k_eeprom_read_mac(ah, mac); |
| 171 | | + ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac); |
| 172 | | if (ret) { |
| 173 | | ATH5K_ERR(sc, "unable to read address from EEPROM\n"); |
| 174 | | goto err_queues; |
| package/mac80211/patches/520-mac80211_drv_tim_override.patch |
| 1 | | +++ b/include/net/mac80211.h |
| 2 | | @@ -2227,6 +2227,18 @@ static inline int ieee80211_sta_ps_trans |
| 3 | | #define IEEE80211_TX_STATUS_HEADROOM 13 |
| 4 | | |
| 5 | | /** |
| 6 | | + * ieee80211_sta_set_tim - set the TIM bit for a sleeping station |
| 7 | | + * |
| 8 | | + * If a driver buffers frames for a powersave station instead of passing |
| 9 | | + * them back to mac80211 for retransmission, the station needs to be told |
| 10 | | + * to wake up using the TIM bitmap in the beacon. |
| 11 | | + * |
| 12 | | + * This function sets the station's TIM bit - it will be cleared when the |
| 13 | | + * station wakes up. |
| 14 | | + */ |
| 15 | | +void ieee80211_sta_set_tim(struct ieee80211_sta *sta); |
| 16 | | + |
| 17 | | +/** |
| 18 | | * ieee80211_tx_status - transmit status callback |
| 19 | | * |
| 20 | | * Call this function for all transmitted frames after they have been |
| 21 | | +++ b/net/mac80211/sta_info.c |
| 22 | | @@ -609,7 +609,8 @@ static bool sta_info_cleanup_expire_buff |
| 23 | | #endif |
| 24 | | dev_kfree_skb(skb); |
| 25 | | |
| 26 | | - if (skb_queue_empty(&sta->ps_tx_buf)) |
| 27 | | + if (skb_queue_empty(&sta->ps_tx_buf) && |
| 28 | | + !test_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF)) |
| 29 | | sta_info_clear_tim_bit(sta); |
| 30 | | } |
| 31 | | |
| 32 | | @@ -893,6 +894,7 @@ void ieee80211_sta_ps_deliver_wakeup(str |
| 33 | | struct ieee80211_local *local = sdata->local; |
| 34 | | int sent, buffered; |
| 35 | | |
| 36 | | + clear_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); |
| 37 | | if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS)) |
| 38 | | drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta); |
| 39 | | |
| 40 | | @@ -985,3 +987,12 @@ void ieee80211_sta_block_awake(struct ie |
| 41 | | ieee80211_queue_work(hw, &sta->drv_unblock_wk); |
| 42 | | } |
| 43 | | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
| 44 | | + |
| 45 | | +void ieee80211_sta_set_tim(struct ieee80211_sta *pubsta) |
| 46 | | +{ |
| 47 | | + struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
| 48 | | + |
| 49 | | + set_sta_flags(sta, WLAN_STA_PS_DRIVER_BUF); |
| 50 | | + sta_info_set_tim_bit(sta); |
| 51 | | +} |
| 52 | | +EXPORT_SYMBOL(ieee80211_sta_set_tim); |
| 53 | | +++ b/net/mac80211/sta_info.h |
| 54 | | @@ -43,6 +43,8 @@ |
| 55 | | * be in the queues |
| 56 | | * @WLAN_STA_PSPOLL: Station sent PS-poll while driver was keeping |
| 57 | | * station in power-save mode, reply when the driver unblocks. |
| 58 | | + * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal |
| 59 | | + * buffers. Automatically cleared on station wake-up. |
| 60 | | */ |
| 61 | | enum ieee80211_sta_info_flags { |
| 62 | | WLAN_STA_AUTH = 1<<0, |
| 63 | | @@ -58,6 +60,7 @@ enum ieee80211_sta_info_flags { |
| 64 | | WLAN_STA_BLOCK_BA = 1<<11, |
| 65 | | WLAN_STA_PS_DRIVER = 1<<12, |
| 66 | | WLAN_STA_PSPOLL = 1<<13, |
| 67 | | + WLAN_STA_PS_DRIVER_BUF = 1<<14, |
| 68 | | }; |
| 69 | | |
| 70 | | #define STA_TID_NUM 16 |
| package/mac80211/patches/521-ath9k_fix_ap_ps_buffering.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
| 2 | | @@ -200,6 +200,7 @@ struct ath_atx_ac { |
| 3 | | int sched; |
| 4 | | struct list_head list; |
| 5 | | struct list_head tid_q; |
| 6 | | + bool clear_ps_filter; |
| 7 | | }; |
| 8 | | |
| 9 | | struct ath_frame_info { |
| 10 | | @@ -257,6 +258,8 @@ struct ath_node { |
| 11 | | struct ath_atx_ac ac[WME_NUM_AC]; |
| 12 | | u16 maxampdu; |
| 13 | | u8 mpdudensity; |
| 14 | | + |
| 15 | | + bool sleeping; |
| 16 | | }; |
| 17 | | |
| 18 | | #define AGGR_CLEANUP BIT(1) |
| 19 | | @@ -338,6 +341,9 @@ int ath_tx_aggr_start(struct ath_softc * |
| 20 | | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
| 21 | | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); |
| 22 | | |
| 23 | | +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an); |
| 24 | | +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an); |
| 25 | | + |
| 26 | | /********/ |
| 27 | | /* VIFs */ |
| 28 | | /********/ |
| 29 | | +++ b/drivers/net/wireless/ath/ath9k/main.c |
| 30 | | @@ -1792,6 +1792,27 @@ static int ath9k_sta_remove(struct ieee8 |
| 31 | | return 0; |
| 32 | | } |
| 33 | | |
| 34 | | +static void ath9k_sta_notify(struct ieee80211_hw *hw, |
| 35 | | + struct ieee80211_vif *vif, |
| 36 | | + enum sta_notify_cmd cmd, |
| 37 | | + struct ieee80211_sta *sta) |
| 38 | | +{ |
| 39 | | + struct ath_softc *sc = hw->priv; |
| 40 | | + struct ath_node *an = (struct ath_node *) sta->drv_priv; |
| 41 | | + |
| 42 | | + switch (cmd) { |
| 43 | | + case STA_NOTIFY_SLEEP: |
| 44 | | + an->sleeping = true; |
| 45 | | + if (ath_tx_aggr_sleep(sc, an)) |
| 46 | | + ieee80211_sta_set_tim(sta); |
| 47 | | + break; |
| 48 | | + case STA_NOTIFY_AWAKE: |
| 49 | | + an->sleeping = false; |
| 50 | | + ath_tx_aggr_wakeup(sc, an); |
| 51 | | + break; |
| 52 | | + } |
| 53 | | +} |
| 54 | | + |
| 55 | | static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
| 56 | | const struct ieee80211_tx_queue_params *params) |
| 57 | | { |
| 58 | | @@ -2198,6 +2219,7 @@ struct ieee80211_ops ath9k_ops = { |
| 59 | | .configure_filter = ath9k_configure_filter, |
| 60 | | .sta_add = ath9k_sta_add, |
| 61 | | .sta_remove = ath9k_sta_remove, |
| 62 | | + .sta_notify = ath9k_sta_notify, |
| 63 | | .conf_tx = ath9k_conf_tx, |
| 64 | | .bss_info_changed = ath9k_bss_info_changed, |
| 65 | | .set_key = ath9k_set_key, |
| 66 | | +++ b/drivers/net/wireless/ath/ath9k/xmit.c |
| 67 | | @@ -357,6 +357,7 @@ static void ath_tx_complete_aggr(struct |
| 68 | | struct ath_frame_info *fi; |
| 69 | | int nframes; |
| 70 | | u8 tidno; |
| 71 | | + bool clear_filter; |
| 72 | | |
| 73 | | skb = bf->bf_mpdu; |
| 74 | | hdr = (struct ieee80211_hdr *)skb->data; |
| 75 | | @@ -441,22 +442,24 @@ static void ath_tx_complete_aggr(struct |
| 76 | | /* transmit completion */ |
| 77 | | acked_cnt++; |
| 78 | | } else { |
| 79 | | - if (!(tid->state & AGGR_CLEANUP) && retry) { |
| 80 | | - if (fi->retries < ATH_MAX_SW_RETRIES) { |
| 81 | | - ath_tx_set_retry(sc, txq, bf->bf_mpdu); |
| 82 | | - txpending = 1; |
| 83 | | - } else { |
| 84 | | - bf->bf_state.bf_type |= BUF_XRETRY; |
| 85 | | - txfail = 1; |
| 86 | | - sendbar = 1; |
| 87 | | - txfail_cnt++; |
| 88 | | - } |
| 89 | | - } else { |
| 90 | | + if ((tid->state & AGGR_CLEANUP) || !retry) { |
| 91 | | /* |
| 92 | | * cleanup in progress, just fail |
| 93 | | * the un-acked sub-frames |
| 94 | | */ |
| 95 | | txfail = 1; |
| 96 | | + } else if (fi->retries < ATH_MAX_SW_RETRIES) { |
| 97 | | + if (!(ts->ts_status & ATH9K_TXERR_FILT) || |
| 98 | | + !an->sleeping) |
| 99 | | + ath_tx_set_retry(sc, txq, bf->bf_mpdu); |
| 100 | | + |
| 101 | | + clear_filter = true; |
| 102 | | + txpending = 1; |
| 103 | | + } else { |
| 104 | | + bf->bf_state.bf_type |= BUF_XRETRY; |
| 105 | | + txfail = 1; |
| 106 | | + sendbar = 1; |
| 107 | | + txfail_cnt++; |
| 108 | | } |
| 109 | | } |
| 110 | | |
| 111 | | @@ -496,6 +499,7 @@ static void ath_tx_complete_aggr(struct |
| 112 | | !txfail, sendbar); |
| 113 | | } else { |
| 114 | | /* retry the un-acked ones */ |
| 115 | | + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, false); |
| 116 | | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) { |
| 117 | | if (bf->bf_next == NULL && bf_last->bf_stale) { |
| 118 | | struct ath_buf *tbf; |
| 119 | | @@ -546,7 +550,12 @@ static void ath_tx_complete_aggr(struct |
| 120 | | |
| 121 | | /* prepend un-acked frames to the beginning of the pending frame queue */ |
| 122 | | if (!list_empty(&bf_pending)) { |
| 123 | | + if (an->sleeping) |
| 124 | | + ieee80211_sta_set_tim(sta); |
| 125 | | + |
| 126 | | spin_lock_bh(&txq->axq_lock); |
| 127 | | + if (clear_filter) |
| 128 | | + tid->ac->clear_ps_filter = true; |
| 129 | | list_splice(&bf_pending, &tid->buf_q); |
| 130 | | ath_tx_queue_tid(txq, tid); |
| 131 | | spin_unlock_bh(&txq->axq_lock); |
| 132 | | @@ -816,6 +825,11 @@ static void ath_tx_sched_aggr(struct ath |
| 133 | | bf = list_first_entry(&bf_q, struct ath_buf, list); |
| 134 | | bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); |
| 135 | | |
| 136 | | + if (tid->ac->clear_ps_filter) { |
| 137 | | + tid->ac->clear_ps_filter = false; |
| 138 | | + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); |
| 139 | | + } |
| 140 | | + |
| 141 | | /* if only one frame, send as non-aggregate */ |
| 142 | | if (bf == bf->bf_lastbf) { |
| 143 | | fi = get_frame_info(bf->bf_mpdu); |
| 144 | | @@ -896,6 +910,67 @@ void ath_tx_aggr_stop(struct ath_softc * |
| 145 | | ath_tx_flush_tid(sc, txtid); |
| 146 | | } |
| 147 | | |
| 148 | | +bool ath_tx_aggr_sleep(struct ath_softc *sc, struct ath_node *an) |
| 149 | | +{ |
| 150 | | + struct ath_atx_tid *tid; |
| 151 | | + struct ath_atx_ac *ac; |
| 152 | | + struct ath_txq *txq; |
| 153 | | + bool buffered = false; |
| 154 | | + int tidno; |
| 155 | | + |
| 156 | | + for (tidno = 0, tid = &an->tid[tidno]; |
| 157 | | + tidno < WME_NUM_TID; tidno++, tid++) { |
| 158 | | + |
| 159 | | + if (!tid->sched) |
| 160 | | + continue; |
| 161 | | + |
| 162 | | + ac = tid->ac; |
| 163 | | + txq = ac->txq; |
| 164 | | + |
| 165 | | + spin_lock_bh(&txq->axq_lock); |
| 166 | | + |
| 167 | | + if (!list_empty(&tid->buf_q)) |
| 168 | | + buffered = true; |
| 169 | | + |
| 170 | | + tid->sched = false; |
| 171 | | + list_del(&tid->list); |
| 172 | | + |
| 173 | | + if (ac->sched) { |
| 174 | | + ac->sched = false; |
| 175 | | + list_del(&ac->list); |
| 176 | | + } |
| 177 | | + |
| 178 | | + spin_unlock_bh(&txq->axq_lock); |
| 179 | | + } |
| 180 | | + |
| 181 | | + return buffered; |
| 182 | | +} |
| 183 | | + |
| 184 | | +void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) |
| 185 | | +{ |
| 186 | | + struct ath_atx_tid *tid; |
| 187 | | + struct ath_atx_ac *ac; |
| 188 | | + struct ath_txq *txq; |
| 189 | | + int tidno; |
| 190 | | + |
| 191 | | + for (tidno = 0, tid = &an->tid[tidno]; |
| 192 | | + tidno < WME_NUM_TID; tidno++, tid++) { |
| 193 | | + |
| 194 | | + ac = tid->ac; |
| 195 | | + txq = ac->txq; |
| 196 | | + |
| 197 | | + spin_lock_bh(&txq->axq_lock); |
| 198 | | + ac->clear_ps_filter = true; |
| 199 | | + |
| 200 | | + if (!list_empty(&tid->buf_q) && !tid->paused) { |
| 201 | | + ath_tx_queue_tid(txq, tid); |
| 202 | | + ath_txq_schedule(sc, txq); |
| 203 | | + } |
| 204 | | + |
| 205 | | + spin_unlock_bh(&txq->axq_lock); |
| 206 | | + } |
| 207 | | +} |
| 208 | | + |
| 209 | | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
| 210 | | { |
| 211 | | struct ath_atx_tid *txtid; |
| 212 | | @@ -1491,7 +1566,6 @@ static int setup_tx_flags(struct sk_buff |
| 213 | | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
| 214 | | int flags = 0; |
| 215 | | |
| 216 | | - flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ |
| 217 | | flags |= ATH9K_TXDESC_INTREQ; |
| 218 | | |
| 219 | | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) |
| 220 | | @@ -1754,6 +1828,9 @@ static void ath_tx_start_dma(struct ath_ |
| 221 | | if (txctl->paprd) |
| 222 | | bf->bf_state.bfs_paprd_timestamp = jiffies; |
| 223 | | |
| 224 | | + if (tx_info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) |
| 225 | | + ath9k_hw_set_clrdmask(sc->sc_ah, bf->bf_desc, true); |
| 226 | | + |
| 227 | | ath_tx_send_normal(sc, txctl->txq, tid, &bf_head); |
| 228 | | } |
| 229 | | |
| 230 | | +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h |
| 231 | | @@ -122,6 +122,11 @@ static inline void ath9k_hw_set11n_burst |
| 232 | | ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); |
| 233 | | } |
| 234 | | |
| 235 | | +static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) |
| 236 | | +{ |
| 237 | | + ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); |
| 238 | | +} |
| 239 | | + |
| 240 | | /* Private hardware call ops */ |
| 241 | | |
| 242 | | /* PHY ops */ |
| 243 | | +++ b/drivers/net/wireless/ath/ath9k/hw.h |
| 244 | | @@ -626,6 +626,7 @@ struct ath_hw_ops { |
| 245 | | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); |
| 246 | | void (*set11n_burstduration)(struct ath_hw *ah, void *ds, |
| 247 | | u32 burstDuration); |
| 248 | | + void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); |
| 249 | | }; |
| 250 | | |
| 251 | | struct ath_nf_limits { |
| 252 | | +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c |
| 253 | | @@ -290,7 +290,6 @@ static void ar9002_hw_set11n_txdesc(stru |
| 254 | | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
| 255 | | | SM(txPower, AR_XmitPower) |
| 256 | | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
| 257 | | - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) |
| 258 | | | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) |
| 259 | | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); |
| 260 | | |
| 261 | | @@ -311,6 +310,16 @@ static void ar9002_hw_set11n_txdesc(stru |
| 262 | | } |
| 263 | | } |
| 264 | | |
| 265 | | +static void ar9002_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) |
| 266 | | +{ |
| 267 | | + struct ar5416_desc *ads = AR5416DESC(ds); |
| 268 | | + |
| 269 | | + if (val) |
| 270 | | + ads->ds_ctl0 |= AR_ClrDestMask; |
| 271 | | + else |
| 272 | | + ads->ds_ctl0 &= ~AR_ClrDestMask; |
| 273 | | +} |
| 274 | | + |
| 275 | | static void ar9002_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, |
| 276 | | void *lastds, |
| 277 | | u32 durUpdateEn, u32 rtsctsRate, |
| 278 | | @@ -448,4 +457,5 @@ void ar9002_hw_attach_mac_ops(struct ath |
| 279 | | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; |
| 280 | | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; |
| 281 | | ops->set11n_burstduration = ar9002_hw_set11n_burstduration; |
| 282 | | + ops->set_clrdmask = ar9002_hw_set_clrdmask; |
| 283 | | } |
| 284 | | +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c |
| 285 | | @@ -329,7 +329,6 @@ static void ar9003_hw_set11n_txdesc(stru |
| 286 | | | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) |
| 287 | | | SM(txpower, AR_XmitPower) |
| 288 | | | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) |
| 289 | | - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) |
| 290 | | | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) |
| 291 | | | (flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0); |
| 292 | | |
| 293 | | @@ -350,6 +349,16 @@ static void ar9003_hw_set11n_txdesc(stru |
| 294 | | ads->ctl22 = 0; |
| 295 | | } |
| 296 | | |
| 297 | | +static void ar9003_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) |
| 298 | | +{ |
| 299 | | + struct ar9003_txc *ads = (struct ar9003_txc *) ds; |
| 300 | | + |
| 301 | | + if (val) |
| 302 | | + ads->ctl11 |= AR_ClrDestMask; |
| 303 | | + else |
| 304 | | + ads->ctl11 &= ~AR_ClrDestMask; |
| 305 | | +} |
| 306 | | + |
| 307 | | static void ar9003_hw_set11n_ratescenario(struct ath_hw *ah, void *ds, |
| 308 | | void *lastds, |
| 309 | | u32 durUpdateEn, u32 rtsctsRate, |
| 310 | | @@ -510,6 +519,7 @@ void ar9003_hw_attach_mac_ops(struct ath |
| 311 | | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; |
| 312 | | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; |
| 313 | | ops->set11n_burstduration = ar9003_hw_set11n_burstduration; |
| 314 | | + ops->set_clrdmask = ar9003_hw_set_clrdmask; |
| 315 | | } |
| 316 | | |
| 317 | | void ath9k_hw_set_rx_bufsize(struct ath_hw *ah, u16 buf_size) |
| 318 | | +++ b/drivers/net/wireless/ath/ath9k/mac.h |
| 319 | | @@ -239,7 +239,6 @@ struct ath_desc { |
| 320 | | void *ds_vdata; |
| 321 | | } __packed __aligned(4); |
| 322 | | |
| 323 | | -#define ATH9K_TXDESC_CLRDMASK 0x0001 |
| 324 | | #define ATH9K_TXDESC_NOACK 0x0002 |
| 325 | | #define ATH9K_TXDESC_RTSENA 0x0004 |
| 326 | | #define ATH9K_TXDESC_CTSENA 0x0008 |
| package/mac80211/patches/541-mac80211_fix_iftype_wds.patch |
| 1 | --- a/net/mac80211/rx.c |
| 2 | @@ -2330,13 +2330,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_ |
| 3 | |
| 4 | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
| 5 | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
| 6 | - sdata->vif.type != NL80211_IFTYPE_STATION) |
| 7 | + sdata->vif.type != NL80211_IFTYPE_STATION && |
| 8 | + sdata->vif.type != NL80211_IFTYPE_WDS) |
| 9 | return RX_DROP_MONITOR; |
| 10 | |
| 11 | switch (stype) { |
| 12 | case cpu_to_le16(IEEE80211_STYPE_BEACON): |
| 13 | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): |
| 14 | - /* process for all: mesh, mlme, ibss */ |
| 15 | + /* process for all: mesh, mlme, ibss, wds */ |
| 16 | break; |
| 17 | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): |
| 18 | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): |
| 19 | @@ -2716,7 +2717,10 @@ static int prepare_for_handlers(struct i |
| 20 | } |
| 21 | break; |
| 22 | case NL80211_IFTYPE_WDS: |
| 23 | - if (bssid || !ieee80211_is_data(hdr->frame_control)) |
| 24 | + if (bssid) { |
| 25 | + if (!ieee80211_is_beacon(hdr->frame_control)) |
| 26 | + return 0; |
| 27 | + } else if (!ieee80211_is_data(hdr->frame_control)) |
| 28 | return 0; |
| 29 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
| 30 | return 0; |
| 31 | --- a/net/mac80211/iface.c |
| 32 | @@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_ |
| 33 | { |
| 34 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 35 | struct ieee80211_local *local = sdata->local; |
| 36 | - struct sta_info *sta; |
| 37 | u32 changed = 0; |
| 38 | int res; |
| 39 | u32 hw_reconf_flags = 0; |
| 40 | @@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_ |
| 41 | |
| 42 | set_bit(SDATA_STATE_RUNNING, &sdata->state); |
| 43 | |
| 44 | - if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
| 45 | - /* Create STA entry for the WDS peer */ |
| 46 | - sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
| 47 | - GFP_KERNEL); |
| 48 | - if (!sta) { |
| 49 | - res = -ENOMEM; |
| 50 | - goto err_del_interface; |
| 51 | - } |
| 52 | - |
| 53 | - /* no locking required since STA is not live yet */ |
| 54 | - sta->flags |= WLAN_STA_AUTHORIZED; |
| 55 | - |
| 56 | - res = sta_info_insert(sta); |
| 57 | - if (res) { |
| 58 | - /* STA has been freed */ |
| 59 | - goto err_del_interface; |
| 60 | - } |
| 61 | - |
| 62 | - rate_control_rate_init(sta); |
| 63 | - } |
| 64 | - |
| 65 | /* |
| 66 | * set_multicast_list will be invoked by the networking core |
| 67 | * which will check whether any increments here were done in |
| 68 | @@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_ |
| 69 | netif_tx_start_all_queues(dev); |
| 70 | |
| 71 | return 0; |
| 72 | - err_del_interface: |
| 73 | - drv_remove_interface(local, &sdata->vif); |
| 74 | + |
| 75 | err_stop: |
| 76 | if (!local->open_count) |
| 77 | drv_stop(local); |
| 78 | @@ -717,6 +694,70 @@ static void ieee80211_if_setup(struct ne |
| 79 | dev->destructor = free_netdev; |
| 80 | } |
| 81 | |
| 82 | +static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
| 83 | + struct sk_buff *skb) |
| 84 | +{ |
| 85 | + struct ieee80211_local *local = sdata->local; |
| 86 | + struct ieee80211_rx_status *rx_status; |
| 87 | + struct ieee802_11_elems elems; |
| 88 | + struct ieee80211_mgmt *mgmt; |
| 89 | + struct sta_info *sta; |
| 90 | + size_t baselen; |
| 91 | + u32 rates = 0; |
| 92 | + u16 stype; |
| 93 | + bool new = false; |
| 94 | + enum ieee80211_band band = local->hw.conf.channel->band; |
| 95 | + struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
| 96 | + |
| 97 | + rx_status = IEEE80211_SKB_RXCB(skb); |
| 98 | + mgmt = (struct ieee80211_mgmt *) skb->data; |
| 99 | + stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; |
| 100 | + |
| 101 | + if (stype != IEEE80211_STYPE_BEACON) |
| 102 | + return; |
| 103 | + |
| 104 | + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
| 105 | + if (baselen > skb->len) |
| 106 | + return; |
| 107 | + |
| 108 | + ieee802_11_parse_elems(mgmt->u.probe_resp.variable, |
| 109 | + skb->len - baselen, &elems); |
| 110 | + |
| 111 | + rates = ieee80211_sta_get_rates(local, &elems, band); |
| 112 | + |
| 113 | + rcu_read_lock(); |
| 114 | + |
| 115 | + sta = sta_info_get(sdata, sdata->u.wds.remote_addr); |
| 116 | + |
| 117 | + if (!sta) { |
| 118 | + rcu_read_unlock(); |
| 119 | + sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
| 120 | + GFP_KERNEL); |
| 121 | + if (!sta) |
| 122 | + return; |
| 123 | + |
| 124 | + new = true; |
| 125 | + } |
| 126 | + |
| 127 | + sta->last_rx = jiffies; |
| 128 | + sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
| 129 | + |
| 130 | + if (elems.ht_cap_elem) |
| 131 | + ieee80211_ht_cap_ie_to_sta_ht_cap(sband, |
| 132 | + elems.ht_cap_elem, &sta->sta.ht_cap); |
| 133 | + |
| 134 | + if (elems.wmm_param) |
| 135 | + set_sta_flags(sta, WLAN_STA_WME); |
| 136 | + |
| 137 | + if (new) { |
| 138 | + sta->flags = WLAN_STA_AUTHORIZED; |
| 139 | + rate_control_rate_init(sta); |
| 140 | + sta_info_insert_rcu(sta); |
| 141 | + } |
| 142 | + |
| 143 | + rcu_read_unlock(); |
| 144 | +} |
| 145 | + |
| 146 | static void ieee80211_iface_work(struct work_struct *work) |
| 147 | { |
| 148 | struct ieee80211_sub_if_data *sdata = |
| 149 | @@ -821,6 +862,9 @@ static void ieee80211_iface_work(struct |
| 150 | break; |
| 151 | ieee80211_mesh_rx_queued_mgmt(sdata, skb); |
| 152 | break; |
| 153 | + case NL80211_IFTYPE_WDS: |
| 154 | + ieee80211_wds_rx_queued_mgmt(sdata, skb); |
| 155 | + break; |
| 156 | default: |
| 157 | WARN(1, "frame for unexpected interface type"); |
| 158 | break; |
| package/mac80211/patches/542-mac80211_enable_iftype_wds_aggregation.patch |
| 1 | --- a/net/mac80211/agg-tx.c |
| 2 | @@ -79,7 +79,8 @@ static void ieee80211_send_addba_request |
| 3 | memcpy(mgmt->da, da, ETH_ALEN); |
| 4 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
| 5 | if (sdata->vif.type == NL80211_IFTYPE_AP || |
| 6 | - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 7 | + sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
| 8 | + sdata->vif.type == NL80211_IFTYPE_WDS) |
| 9 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
| 10 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
| 11 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
| 12 | @@ -377,7 +378,8 @@ int ieee80211_start_tx_ba_session(struct |
| 13 | */ |
| 14 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
| 15 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
| 16 | - sdata->vif.type != NL80211_IFTYPE_AP) |
| 17 | + sdata->vif.type != NL80211_IFTYPE_AP && |
| 18 | + sdata->vif.type != NL80211_IFTYPE_WDS) |
| 19 | return -EINVAL; |
| 20 | |
| 21 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
| 22 | --- a/net/mac80211/agg-rx.c |
| 23 | @@ -160,6 +160,8 @@ static void ieee80211_send_addba_resp(st |
| 24 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
| 25 | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
| 26 | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
| 27 | + else if (sdata->vif.type == NL80211_IFTYPE_WDS) |
| 28 | + memcpy(mgmt->bssid, da, ETH_ALEN); |
| 29 | |
| 30 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
| 31 | IEEE80211_STYPE_ACTION); |
| 32 | --- a/net/mac80211/rx.c |
| 33 | @@ -2132,7 +2132,8 @@ ieee80211_rx_h_action(struct ieee80211_r |
| 34 | */ |
| 35 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
| 36 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
| 37 | - sdata->vif.type != NL80211_IFTYPE_AP) |
| 38 | + sdata->vif.type != NL80211_IFTYPE_AP && |
| 39 | + sdata->vif.type != NL80211_IFTYPE_WDS) |
| 40 | break; |
| 41 | |
| 42 | /* verify action_code is present */ |
| 43 | @@ -2717,13 +2718,16 @@ static int prepare_for_handlers(struct i |
| 44 | } |
| 45 | break; |
| 46 | case NL80211_IFTYPE_WDS: |
| 47 | - if (bssid) { |
| 48 | - if (!ieee80211_is_beacon(hdr->frame_control)) |
| 49 | - return 0; |
| 50 | - } else if (!ieee80211_is_data(hdr->frame_control)) |
| 51 | - return 0; |
| 52 | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
| 53 | return 0; |
| 54 | + |
| 55 | + if (ieee80211_is_data(hdr->frame_control) || |
| 56 | + ieee80211_is_action(hdr->frame_control)) { |
| 57 | + if (compare_ether_addr(sdata->vif.addr, hdr->addr1)) |
| 58 | + return 0; |
| 59 | + } else if (!ieee80211_is_beacon(hdr->frame_control)) |
| 60 | + return 0; |
| 61 | + |
| 62 | break; |
| 63 | default: |
| 64 | /* should never get here */ |
| package/mac80211/patches/551-mac80211_fix_iftype_wds.patch |
| 1 | | +++ b/net/mac80211/rx.c |
| 2 | | @@ -2328,13 +2328,14 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_ |
| 3 | | |
| 4 | | if (!ieee80211_vif_is_mesh(&sdata->vif) && |
| 5 | | sdata->vif.type != NL80211_IFTYPE_ADHOC && |
| 6 | | - sdata->vif.type != NL80211_IFTYPE_STATION) |
| 7 | | + sdata->vif.type != NL80211_IFTYPE_STATION && |
| 8 | | + sdata->vif.type != NL80211_IFTYPE_WDS) |
| 9 | | return RX_DROP_MONITOR; |
| 10 | | |
| 11 | | switch (stype) { |
| 12 | | case cpu_to_le16(IEEE80211_STYPE_BEACON): |
| 13 | | case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): |
| 14 | | - /* process for all: mesh, mlme, ibss */ |
| 15 | | + /* process for all: mesh, mlme, ibss, wds */ |
| 16 | | break; |
| 17 | | case cpu_to_le16(IEEE80211_STYPE_DEAUTH): |
| 18 | | case cpu_to_le16(IEEE80211_STYPE_DISASSOC): |
| 19 | | @@ -2714,7 +2715,10 @@ static int prepare_for_handlers(struct i |
| 20 | | } |
| 21 | | break; |
| 22 | | case NL80211_IFTYPE_WDS: |
| 23 | | - if (bssid || !ieee80211_is_data(hdr->frame_control)) |
| 24 | | + if (bssid) { |
| 25 | | + if (!ieee80211_is_beacon(hdr->frame_control)) |
| 26 | | + return 0; |
| 27 | | + } else if (!ieee80211_is_data(hdr->frame_control)) |
| 28 | | return 0; |
| 29 | | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
| 30 | | return 0; |
| 31 | | +++ b/net/mac80211/iface.c |
| 32 | | @@ -178,7 +178,6 @@ static int ieee80211_do_open(struct net_ |
| 33 | | { |
| 34 | | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 35 | | struct ieee80211_local *local = sdata->local; |
| 36 | | - struct sta_info *sta; |
| 37 | | u32 changed = 0; |
| 38 | | int res; |
| 39 | | u32 hw_reconf_flags = 0; |
| 40 | | @@ -290,27 +289,6 @@ static int ieee80211_do_open(struct net_ |
| 41 | | |
| 42 | | set_bit(SDATA_STATE_RUNNING, &sdata->state); |
| 43 | | |
| 44 | | - if (sdata->vif.type == NL80211_IFTYPE_WDS) { |
| 45 | | - /* Create STA entry for the WDS peer */ |
| 46 | | - sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
| 47 | | - GFP_KERNEL); |
| 48 | | - if (!sta) { |
| 49 | | - res = -ENOMEM; |
| 50 | | - goto err_del_interface; |
| 51 | | - } |
| 52 | | - |
| 53 | | - /* no locking required since STA is not live yet */ |
| 54 | | - sta->flags |= WLAN_STA_AUTHORIZED; |
| 55 | | - |
| 56 | | - res = sta_info_insert(sta); |
| 57 | | - if (res) { |
| 58 | | - /* STA has been freed */ |
| 59 | | - goto err_del_interface; |
| 60 | | - } |
| 61 | | - |
| 62 | | - rate_control_rate_init(sta); |
| 63 | | - } |
| 64 | | - |
| 65 | | /* |
| 66 | | * set_multicast_list will be invoked by the networking core |
| 67 | | * which will check whether any increments here were done in |
| 68 | | @@ -344,8 +322,7 @@ static int ieee80211_do_open(struct net_ |
| 69 | | netif_tx_start_all_queues(dev); |
| 70 | | |
| 71 | | return 0; |
| 72 | | - err_del_interface: |
| 73 | | - drv_remove_interface(local, &sdata->vif); |
| 74 | | + |
| 75 | | err_stop: |
| 76 | | if (!local->open_count) |
| 77 | | drv_stop(local); |
| 78 | | @@ -717,6 +694,70 @@ static void ieee80211_if_setup(struct ne |
| 79 | | dev->destructor = free_netdev; |
| 80 | | } |
| 81 | | |
| 82 | | +static void ieee80211_wds_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
| 83 | | + struct sk_buff *skb) |
| 84 | | +{ |
| 85 | | + struct ieee80211_local *local = sdata->local; |
| 86 | | + struct ieee80211_rx_status *rx_status; |
| 87 | | + struct ieee802_11_elems elems; |
| 88 | | + struct ieee80211_mgmt *mgmt; |
| 89 | | + struct sta_info *sta; |
| 90 | | + size_t baselen; |
| 91 | | + u32 rates = 0; |
| 92 | | + u16 stype; |
| 93 | | + bool new = false; |
| 94 | | + enum ieee80211_band band = local->hw.conf.channel->band; |
| 95 | | + struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
| 96 | | + |
| 97 | | + rx_status = IEEE80211_SKB_RXCB(skb); |
| 98 | | + mgmt = (struct ieee80211_mgmt *) skb->data; |
| 99 | | + stype = le16_to_cpu(mgmt->frame_control) & IEEE80211_FCTL_STYPE; |
| 100 | | + |
| 101 | | + if (stype != IEEE80211_STYPE_BEACON) |
| 102 | | + return; |
| 103 | | + |
| 104 | | + baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; |
| 105 | | + if (baselen > skb->len) |
| 106 | | + return; |
| 107 | | + |
| 108 | | + ieee802_11_parse_elems(mgmt->u.probe_resp.variable, |
| 109 | | + skb->len - baselen, &elems); |
| 110 | | + |
| 111 | | + rates = ieee80211_sta_get_rates(local, &elems, band); |
| 112 | | + |
| 113 | | + rcu_read_lock(); |
| 114 | | + |
| 115 | | + sta = sta_info_get(sdata, sdata->u.wds.remote_addr); |
| 116 | | + |
| 117 | | + if (!sta) { |
| 118 | | + rcu_read_unlock(); |
| 119 | | + sta = sta_info_alloc(sdata, sdata->u.wds.remote_addr, |
| 120 | | + GFP_KERNEL); |
| 121 | | + if (!sta) |
| 122 | | + return; |
| 123 | | + |
| 124 | | + new = true; |
| 125 | | + } |
| 126 | | + |
| 127 | | + sta->last_rx = jiffies; |
| 128 | | + sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
| 129 | | + |
| 130 | | + if (elems.ht_cap_elem) |
| 131 | | + ieee80211_ht_cap_ie_to_sta_ht_cap(sband, |
| 132 | | + elems.ht_cap_elem, &sta->sta.ht_cap); |
| 133 | | + |
| 134 | | + if (elems.wmm_param) |
| 135 | | + set_sta_flags(sta, WLAN_STA_WME); |
| 136 | | + |
| 137 | | + if (new) { |
| 138 | | + sta->flags = WLAN_STA_AUTHORIZED; |
| 139 | | + rate_control_rate_init(sta); |
| 140 | | + sta_info_insert_rcu(sta); |
| 141 | | + } |
| 142 | | + |
| 143 | | + rcu_read_unlock(); |
| 144 | | +} |
| 145 | | + |
| 146 | | static void ieee80211_iface_work(struct work_struct *work) |
| 147 | | { |
| 148 | | struct ieee80211_sub_if_data *sdata = |
| 149 | | @@ -821,6 +862,9 @@ static void ieee80211_iface_work(struct |
| 150 | | break; |
| 151 | | ieee80211_mesh_rx_queued_mgmt(sdata, skb); |
| 152 | | break; |
| 153 | | + case NL80211_IFTYPE_WDS: |
| 154 | | + ieee80211_wds_rx_queued_mgmt(sdata, skb); |
| 155 | | + break; |
| 156 | | default: |
| 157 | | WARN(1, "frame for unexpected interface type"); |
| 158 | | break; |
| package/mac80211/patches/552-mac80211_enable_iftype_wds_aggregation.patch |
| 1 | | +++ b/net/mac80211/agg-tx.c |
| 2 | | @@ -79,7 +79,8 @@ static void ieee80211_send_addba_request |
| 3 | | memcpy(mgmt->da, da, ETH_ALEN); |
| 4 | | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
| 5 | | if (sdata->vif.type == NL80211_IFTYPE_AP || |
| 6 | | - sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
| 7 | | + sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
| 8 | | + sdata->vif.type == NL80211_IFTYPE_WDS) |
| 9 | | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
| 10 | | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
| 11 | | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
| 12 | | @@ -377,7 +378,8 @@ int ieee80211_start_tx_ba_session(struct |
| 13 | | */ |
| 14 | | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
| 15 | | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
| 16 | | - sdata->vif.type != NL80211_IFTYPE_AP) |
| 17 | | + sdata->vif.type != NL80211_IFTYPE_AP && |
| 18 | | + sdata->vif.type != NL80211_IFTYPE_WDS) |
| 19 | | return -EINVAL; |
| 20 | | |
| 21 | | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { |
| 22 | | +++ b/net/mac80211/agg-rx.c |
| 23 | | @@ -160,6 +160,8 @@ static void ieee80211_send_addba_resp(st |
| 24 | | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
| 25 | | else if (sdata->vif.type == NL80211_IFTYPE_STATION) |
| 26 | | memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
| 27 | | + else if (sdata->vif.type == NL80211_IFTYPE_WDS) |
| 28 | | + memcpy(mgmt->bssid, da, ETH_ALEN); |
| 29 | | |
| 30 | | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
| 31 | | IEEE80211_STYPE_ACTION); |
| 32 | | +++ b/net/mac80211/rx.c |
| 33 | | @@ -2130,7 +2130,8 @@ ieee80211_rx_h_action(struct ieee80211_r |
| 34 | | */ |
| 35 | | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
| 36 | | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
| 37 | | - sdata->vif.type != NL80211_IFTYPE_AP) |
| 38 | | + sdata->vif.type != NL80211_IFTYPE_AP && |
| 39 | | + sdata->vif.type != NL80211_IFTYPE_WDS) |
| 40 | | break; |
| 41 | | |
| 42 | | /* verify action_code is present */ |
| 43 | | @@ -2715,13 +2716,16 @@ static int prepare_for_handlers(struct i |
| 44 | | } |
| 45 | | break; |
| 46 | | case NL80211_IFTYPE_WDS: |
| 47 | | - if (bssid) { |
| 48 | | - if (!ieee80211_is_beacon(hdr->frame_control)) |
| 49 | | - return 0; |
| 50 | | - } else if (!ieee80211_is_data(hdr->frame_control)) |
| 51 | | - return 0; |
| 52 | | if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2)) |
| 53 | | return 0; |
| 54 | | + |
| 55 | | + if (ieee80211_is_data(hdr->frame_control) || |
| 56 | | + ieee80211_is_action(hdr->frame_control)) { |
| 57 | | + if (compare_ether_addr(sdata->vif.addr, hdr->addr1)) |
| 58 | | + return 0; |
| 59 | | + } else if (!ieee80211_is_beacon(hdr->frame_control)) |
| 60 | | + return 0; |
| 61 | | + |
| 62 | | break; |
| 63 | | default: |
| 64 | | /* should never get here */ |
| package/mac80211/patches/571-ath9k_assign_unencrypted_ps_keyidx.patch |
| 1 | | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
| 2 | | @@ -256,6 +256,8 @@ struct ath_node { |
| 3 | | #endif |
| 4 | | struct ath_atx_tid tid[WME_NUM_TID]; |
| 5 | | struct ath_atx_ac ac[WME_NUM_AC]; |
| 6 | | + int ps_key; |
| 7 | | + |
| 8 | | u16 maxampdu; |
| 9 | | u8 mpdudensity; |
| 10 | | |
| 11 | | +++ b/drivers/net/wireless/ath/ath9k/main.c |
| 12 | | @@ -1775,18 +1775,37 @@ static int ath9k_sta_add(struct ieee8021 |
| 13 | | struct ieee80211_sta *sta) |
| 14 | | { |
| 15 | | struct ath_softc *sc = hw->priv; |
| 16 | | + struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 17 | | + struct ath_node *an = (struct ath_node *) sta->drv_priv; |
| 18 | | + struct ieee80211_key_conf ps_key = { }; |
| 19 | | |
| 20 | | ath_node_attach(sc, sta); |
| 21 | | + an->ps_key = ath_key_config(common, vif, sta, &ps_key); |
| 22 | | |
| 23 | | return 0; |
| 24 | | } |
| 25 | | |
| 26 | | +static void ath9k_del_ps_key(struct ath_softc *sc, |
| 27 | | + struct ieee80211_vif *vif, |
| 28 | | + struct ieee80211_sta *sta) |
| 29 | | +{ |
| 30 | | + struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 31 | | + struct ath_node *an = (struct ath_node *) sta->drv_priv; |
| 32 | | + struct ieee80211_key_conf ps_key = { .hw_key_idx = an->ps_key }; |
| 33 | | + |
| 34 | | + if (!an->ps_key) |
| 35 | | + return; |
| 36 | | + |
| 37 | | + ath_key_delete(common, &ps_key); |
| 38 | | +} |
| 39 | | + |
| 40 | | static int ath9k_sta_remove(struct ieee80211_hw *hw, |
| 41 | | struct ieee80211_vif *vif, |
| 42 | | struct ieee80211_sta *sta) |
| 43 | | { |
| 44 | | struct ath_softc *sc = hw->priv; |
| 45 | | |
| 46 | | + ath9k_del_ps_key(sc, vif, sta); |
| 47 | | ath_node_detach(sc, sta); |
| 48 | | |
| 49 | | return 0; |
| 50 | | @@ -1889,6 +1908,9 @@ static int ath9k_set_key(struct ieee8021 |
| 51 | | |
| 52 | | switch (cmd) { |
| 53 | | case SET_KEY: |
| 54 | | + if (sta) |
| 55 | | + ath9k_del_ps_key(sc, vif, sta); |
| 56 | | + |
| 57 | | ret = ath_key_config(common, vif, sta, key); |
| 58 | | if (ret >= 0) { |
| 59 | | key->hw_key_idx = ret; |
| 60 | | +++ b/drivers/net/wireless/ath/key.c |
| 61 | | @@ -483,6 +483,9 @@ int ath_key_config(struct ath_common *co |
| 62 | | memset(&hk, 0, sizeof(hk)); |
| 63 | | |
| 64 | | switch (key->cipher) { |
| 65 | | + case 0: |
| 66 | | + hk.kv_type = ATH_CIPHER_CLR; |
| 67 | | + break; |
| 68 | | case WLAN_CIPHER_SUITE_WEP40: |
| 69 | | case WLAN_CIPHER_SUITE_WEP104: |
| 70 | | hk.kv_type = ATH_CIPHER_WEP; |
| 71 | | @@ -498,7 +501,8 @@ int ath_key_config(struct ath_common *co |
| 72 | | } |
| 73 | | |
| 74 | | hk.kv_len = key->keylen; |
| 75 | | - memcpy(hk.kv_val, key->key, key->keylen); |
| 76 | | + if (key->keylen) |
| 77 | | + memcpy(hk.kv_val, key->key, key->keylen); |
| 78 | | |
| 79 | | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
| 80 | | switch (vif->type) { |
| 81 | | +++ b/drivers/net/wireless/ath/ath9k/xmit.c |
| 82 | | @@ -1526,7 +1526,7 @@ static void setup_frame_info(struct ieee |
| 83 | | struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; |
| 84 | | struct ieee80211_hdr *hdr; |
| 85 | | struct ath_frame_info *fi = get_frame_info(skb); |
| 86 | | - struct ath_node *an; |
| 87 | | + struct ath_node *an = NULL; |
| 88 | | struct ath_atx_tid *tid; |
| 89 | | enum ath9k_key_type keytype; |
| 90 | | u16 seqno = 0; |
| 91 | | @@ -1534,11 +1534,13 @@ static void setup_frame_info(struct ieee |
| 92 | | |
| 93 | | keytype = ath9k_cmn_get_hw_crypto_keytype(skb); |
| 94 | | |
| 95 | | + if (sta) |
| 96 | | + an = (struct ath_node *) sta->drv_priv; |
| 97 | | + |
| 98 | | hdr = (struct ieee80211_hdr *)skb->data; |
| 99 | | - if (sta && ieee80211_is_data_qos(hdr->frame_control) && |
| 100 | | + if (an && ieee80211_is_data_qos(hdr->frame_control) && |
| 101 | | conf_is_ht(&hw->conf) && (sc->sc_flags & SC_OP_TXAGGR)) { |
| 102 | | |
| 103 | | - an = (struct ath_node *) sta->drv_priv; |
| 104 | | tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; |
| 105 | | |
| 106 | | /* |
| 107 | | @@ -1554,6 +1556,8 @@ static void setup_frame_info(struct ieee |
| 108 | | memset(fi, 0, sizeof(*fi)); |
| 109 | | if (hw_key) |
| 110 | | fi->keyix = hw_key->hw_key_idx; |
| 111 | | + else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) |
| 112 | | + fi->keyix = an->ps_key; |
| 113 | | else |
| 114 | | fi->keyix = ATH9K_TXKEYIX_INVALID; |
| 115 | | fi->keytype = keytype; |
| package/mac80211/patches/620-rt2x00_soc_led_support.patch |
| 1 | | +++ b/drivers/net/wireless/rt2x00/rt2800lib.c |
| 2 | | @@ -938,6 +938,7 @@ EXPORT_SYMBOL_GPL(rt2800_rfkill_poll); |
| 3 | | static void rt2800_brightness_set(struct led_classdev *led_cdev, |
| 4 | | enum led_brightness brightness) |
| 5 | | { |
| 6 | | + u32 reg; |
| 7 | | struct rt2x00_led *led = |
| 8 | | container_of(led_cdev, struct rt2x00_led, led_dev); |
| 9 | | unsigned int enabled = brightness != LED_OFF; |
| 10 | | @@ -950,24 +951,46 @@ static void rt2800_brightness_set(struct |
| 11 | | rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, |
| 12 | | EEPROM_FREQ_LED_MODE); |
| 13 | | |
| 14 | | - if (led->type == LED_TYPE_RADIO) { |
| 15 | | - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, |
| 16 | | - enabled ? 0x20 : 0); |
| 17 | | - } else if (led->type == LED_TYPE_ASSOC) { |
| 18 | | - rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, |
| 19 | | - enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); |
| 20 | | - } else if (led->type == LED_TYPE_QUALITY) { |
| 21 | | - /* |
| 22 | | - * The brightness is divided into 6 levels (0 - 5), |
| 23 | | - * The specs tell us the following levels: |
| 24 | | - * 0, 1 ,3, 7, 15, 31 |
| 25 | | - * to determine the level in a simple way we can simply |
| 26 | | - * work with bitshifting: |
| 27 | | - * (1 << level) - 1 |
| 28 | | - */ |
| 29 | | - rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, |
| 30 | | - (1 << brightness / (LED_FULL / 6)) - 1, |
| 31 | | - polarity); |
| 32 | | + /* Check for SoC (SOC devices don't support MCU requests) */ |
| 33 | | + if (rt2x00_is_soc(led->rt2x00dev)) { |
| 34 | | + rt2800_register_read(led->rt2x00dev, LED_CFG, ®); |
| 35 | | + |
| 36 | | + /* Set LED Polarity */ |
| 37 | | + rt2x00_set_field32(®, LED_CFG_LED_POLAR, polarity); |
| 38 | | + |
| 39 | | + /* Set LED Mode */ |
| 40 | | + if (led->type == LED_TYPE_RADIO) { |
| 41 | | + rt2x00_set_field32(®, LED_CFG_G_LED_MODE, |
| 42 | | + enabled ? 3 : 0); |
| 43 | | + } else if (led->type == LED_TYPE_ASSOC) { |
| 44 | | + rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, |
| 45 | | + enabled ? 3 : 0); |
| 46 | | + } else if (led->type == LED_TYPE_QUALITY) { |
| 47 | | + rt2x00_set_field32(®, LED_CFG_R_LED_MODE, |
| 48 | | + enabled ? 3 : 0); |
| 49 | | + } |
| 50 | | + rt2800_register_write(led->rt2x00dev, LED_CFG, reg); |
| 51 | | + } |
| 52 | | + else { |
| 53 | | + if (led->type == LED_TYPE_RADIO) { |
| 54 | | + rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, |
| 55 | | + enabled ? 0x20 : 0); |
| 56 | | + } else if (led->type == LED_TYPE_ASSOC) { |
| 57 | | + rt2800_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, |
| 58 | | + enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); |
| 59 | | + } else if (led->type == LED_TYPE_QUALITY) { |
| 60 | | + /* |
| 61 | | + * The brightness is divided into 6 levels (0 - 5), |
| 62 | | + * The specs tell us the following levels: |
| 63 | | + * 0, 1 ,3, 7, 15, 31 |
| 64 | | + * to determine the level in a simple way we can simply |
| 65 | | + * work with bitshifting: |
| 66 | | + * (1 << level) - 1 |
| 67 | | + */ |
| 68 | | + rt2800_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, |
| 69 | | + (1 << brightness / (LED_FULL / 6)) - 1, |
| 70 | | + polarity); |
| 71 | | + } |
| 72 | | } |
| 73 | | } |
| 74 | | |