diff options
Diffstat (limited to 'drivers/net/wireless/ath9k')
28 files changed, 281 insertions, 324 deletions
diff --git a/drivers/net/wireless/ath9k/ahb.c b/drivers/net/wireless/ath9k/ahb.c index 00cc7bb01f2e..0e65c51ba176 100644 --- a/drivers/net/wireless/ath9k/ahb.c +++ b/drivers/net/wireless/ath9k/ahb.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> | 3 | * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org> |
4 | * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> | 4 | * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org> |
5 | * | 5 | * |
diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c index a39eb760cbb7..6c5e887d50d7 100644 --- a/drivers/net/wireless/ath9k/ani.c +++ b/drivers/net/wireless/ath9k/ani.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/ani.h b/drivers/net/wireless/ath9k/ani.h index 7315761f6d74..08b4e7ed5ff0 100644 --- a/drivers/net/wireless/ath9k/ani.h +++ b/drivers/net/wireless/ath9k/ani.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index b64be8e9a690..2689a08a2844 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -295,13 +295,9 @@ struct ath_tx_control { | |||
295 | enum ath9k_internal_frame_type frame_type; | 295 | enum ath9k_internal_frame_type frame_type; |
296 | }; | 296 | }; |
297 | 297 | ||
298 | struct ath_xmit_status { | ||
299 | int retries; | ||
300 | int flags; | ||
301 | #define ATH_TX_ERROR 0x01 | 298 | #define ATH_TX_ERROR 0x01 |
302 | #define ATH_TX_XRETRY 0x02 | 299 | #define ATH_TX_XRETRY 0x02 |
303 | #define ATH_TX_BAR 0x04 | 300 | #define ATH_TX_BAR 0x04 |
304 | }; | ||
305 | 301 | ||
306 | /* All RSSI values are noise floor adjusted */ | 302 | /* All RSSI values are noise floor adjusted */ |
307 | struct ath_tx_stat { | 303 | struct ath_tx_stat { |
@@ -390,6 +386,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid | |||
390 | 386 | ||
391 | struct ath_vif { | 387 | struct ath_vif { |
392 | int av_bslot; | 388 | int av_bslot; |
389 | __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ | ||
393 | enum nl80211_iftype av_opmode; | 390 | enum nl80211_iftype av_opmode; |
394 | struct ath_buf *av_bcbuf; | 391 | struct ath_buf *av_bcbuf; |
395 | struct ath_tx_control av_btxctl; | 392 | struct ath_tx_control av_btxctl; |
@@ -406,7 +403,7 @@ struct ath_vif { | |||
406 | * number of beacon intervals, the game's up. | 403 | * number of beacon intervals, the game's up. |
407 | */ | 404 | */ |
408 | #define BSTUCK_THRESH (9 * ATH_BCBUF) | 405 | #define BSTUCK_THRESH (9 * ATH_BCBUF) |
409 | #define ATH_BCBUF 1 | 406 | #define ATH_BCBUF 4 |
410 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ | 407 | #define ATH_DEFAULT_BINTVAL 100 /* TU */ |
411 | #define ATH_DEFAULT_BMISS_LIMIT 10 | 408 | #define ATH_DEFAULT_BMISS_LIMIT 10 |
412 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) | 409 | #define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) |
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index 039c78136c50..ec995730632d 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -70,7 +70,8 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
70 | ds = bf->bf_desc; | 70 | ds = bf->bf_desc; |
71 | flags = ATH9K_TXDESC_NOACK; | 71 | flags = ATH9K_TXDESC_NOACK; |
72 | 72 | ||
73 | if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC && | 73 | if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || |
74 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && | ||
74 | (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | 75 | (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { |
75 | ds->ds_link = bf->bf_daddr; /* self-linked */ | 76 | ds->ds_link = bf->bf_daddr; /* self-linked */ |
76 | flags |= ATH9K_TXDESC_VEOL; | 77 | flags |= ATH9K_TXDESC_VEOL; |
@@ -153,6 +154,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
153 | bf->bf_mpdu = skb; | 154 | bf->bf_mpdu = skb; |
154 | if (skb == NULL) | 155 | if (skb == NULL) |
155 | return NULL; | 156 | return NULL; |
157 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = | ||
158 | avp->tsf_adjust; | ||
156 | 159 | ||
157 | info = IEEE80211_SKB_CB(skb); | 160 | info = IEEE80211_SKB_CB(skb); |
158 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 161 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
@@ -253,7 +256,6 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
253 | { | 256 | { |
254 | struct ath_softc *sc = aphy->sc; | 257 | struct ath_softc *sc = aphy->sc; |
255 | struct ath_vif *avp; | 258 | struct ath_vif *avp; |
256 | struct ieee80211_hdr *hdr; | ||
257 | struct ath_buf *bf; | 259 | struct ath_buf *bf; |
258 | struct sk_buff *skb; | 260 | struct sk_buff *skb; |
259 | __le64 tstamp; | 261 | __le64 tstamp; |
@@ -316,42 +318,33 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
316 | 318 | ||
317 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; | 319 | tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; |
318 | sc->beacon.bc_tstamp = le64_to_cpu(tstamp); | 320 | sc->beacon.bc_tstamp = le64_to_cpu(tstamp); |
319 | 321 | /* Calculate a TSF adjustment factor required for staggered beacons. */ | |
320 | /* | ||
321 | * Calculate a TSF adjustment factor required for | ||
322 | * staggered beacons. Note that we assume the format | ||
323 | * of the beacon frame leaves the tstamp field immediately | ||
324 | * following the header. | ||
325 | */ | ||
326 | if (avp->av_bslot > 0) { | 322 | if (avp->av_bslot > 0) { |
327 | u64 tsfadjust; | 323 | u64 tsfadjust; |
328 | __le64 val; | ||
329 | int intval; | 324 | int intval; |
330 | 325 | ||
331 | intval = sc->hw->conf.beacon_int ? | 326 | intval = sc->hw->conf.beacon_int ? |
332 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; | 327 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; |
333 | 328 | ||
334 | /* | 329 | /* |
335 | * The beacon interval is in TU's; the TSF in usecs. | 330 | * Calculate the TSF offset for this beacon slot, i.e., the |
336 | * We figure out how many TU's to add to align the | 331 | * number of usecs that need to be added to the timestamp field |
337 | * timestamp then convert to TSF units and handle | 332 | * in Beacon and Probe Response frames. Beacon slot 0 is |
338 | * byte swapping before writing it in the frame. | 333 | * processed at the correct offset, so it does not require TSF |
339 | * The hardware will then add this each time a beacon | 334 | * adjustment. Other slots are adjusted to get the timestamp |
340 | * frame is sent. Note that we align vif's 1..N | 335 | * close to the TBTT for the BSS. |
341 | * and leave vif 0 untouched. This means vap 0 | ||
342 | * has a timestamp in one beacon interval while the | ||
343 | * others get a timestamp aligned to the next interval. | ||
344 | */ | 336 | */ |
345 | tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF; | 337 | tsfadjust = intval * avp->av_bslot / ATH_BCBUF; |
346 | val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */ | 338 | avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); |
347 | 339 | ||
348 | DPRINTF(sc, ATH_DBG_BEACON, | 340 | DPRINTF(sc, ATH_DBG_BEACON, |
349 | "stagger beacons, bslot %d intval %u tsfadjust %llu\n", | 341 | "stagger beacons, bslot %d intval %u tsfadjust %llu\n", |
350 | avp->av_bslot, intval, (unsigned long long)tsfadjust); | 342 | avp->av_bslot, intval, (unsigned long long)tsfadjust); |
351 | 343 | ||
352 | hdr = (struct ieee80211_hdr *)skb->data; | 344 | ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = |
353 | memcpy(&hdr[1], &val, sizeof(val)); | 345 | avp->tsf_adjust; |
354 | } | 346 | } else |
347 | avp->tsf_adjust = cpu_to_le64(0); | ||
355 | 348 | ||
356 | bf->bf_mpdu = skb; | 349 | bf->bf_mpdu = skb; |
357 | bf->bf_buf_addr = bf->bf_dmacontext = | 350 | bf->bf_buf_addr = bf->bf_dmacontext = |
@@ -447,8 +440,16 @@ void ath_beacon_tasklet(unsigned long data) | |||
447 | tsf = ath9k_hw_gettsf64(ah); | 440 | tsf = ath9k_hw_gettsf64(ah); |
448 | tsftu = TSF_TO_TU(tsf>>32, tsf); | 441 | tsftu = TSF_TO_TU(tsf>>32, tsf); |
449 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; | 442 | slot = ((tsftu % intval) * ATH_BCBUF) / intval; |
450 | vif = sc->beacon.bslot[(slot + 1) % ATH_BCBUF]; | 443 | /* |
451 | aphy = sc->beacon.bslot_aphy[(slot + 1) % ATH_BCBUF]; | 444 | * Reverse the slot order to get slot 0 on the TBTT offset that does |
445 | * not require TSF adjustment and other slots adding | ||
446 | * slot/ATH_BCBUF * beacon_int to timestamp. For example, with | ||
447 | * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. | ||
448 | * and slot 0 is at correct offset to TBTT. | ||
449 | */ | ||
450 | slot = ATH_BCBUF - slot - 1; | ||
451 | vif = sc->beacon.bslot[slot]; | ||
452 | aphy = sc->beacon.bslot_aphy[slot]; | ||
452 | 453 | ||
453 | DPRINTF(sc, ATH_DBG_BEACON, | 454 | DPRINTF(sc, ATH_DBG_BEACON, |
454 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", | 455 | "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", |
@@ -728,6 +729,7 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
728 | ath_beacon_config_ap(sc, &conf, avp); | 729 | ath_beacon_config_ap(sc, &conf, avp); |
729 | break; | 730 | break; |
730 | case NL80211_IFTYPE_ADHOC: | 731 | case NL80211_IFTYPE_ADHOC: |
732 | case NL80211_IFTYPE_MESH_POINT: | ||
731 | ath_beacon_config_adhoc(sc, &conf, avp, vif); | 733 | ath_beacon_config_adhoc(sc, &conf, avp, vif); |
732 | break; | 734 | break; |
733 | case NL80211_IFTYPE_STATION: | 735 | case NL80211_IFTYPE_STATION: |
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index c9446fb6b153..e2d62e97131c 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/calib.h b/drivers/net/wireless/ath9k/calib.h index 32589e0c5018..1c74bd50700d 100644 --- a/drivers/net/wireless/ath9k/calib.h +++ b/drivers/net/wireless/ath9k/calib.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c index 82573cadb1ab..fdf9528fa49b 100644 --- a/drivers/net/wireless/ath9k/debug.c +++ b/drivers/net/wireless/ath9k/debug.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/debug.h b/drivers/net/wireless/ath9k/debug.h index 065268b8568f..7b0e5419d2bc 100644 --- a/drivers/net/wireless/ath9k/debug.h +++ b/drivers/net/wireless/ath9k/debug.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c index 183c949bcca1..ffc36b0361c7 100644 --- a/drivers/net/wireless/ath9k/eeprom.c +++ b/drivers/net/wireless/ath9k/eeprom.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -342,8 +342,7 @@ static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) | |||
342 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | 342 | static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) |
343 | { | 343 | { |
344 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | 344 | #define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) |
345 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 345 | u16 *eep_data = (u16 *)&ah->eeprom.map4k; |
346 | u16 *eep_data; | ||
347 | int addr, eep_start_loc = 0; | 346 | int addr, eep_start_loc = 0; |
348 | 347 | ||
349 | eep_start_loc = 64; | 348 | eep_start_loc = 64; |
@@ -353,8 +352,6 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | |||
353 | "Reading from EEPROM, not flash\n"); | 352 | "Reading from EEPROM, not flash\n"); |
354 | } | 353 | } |
355 | 354 | ||
356 | eep_data = (u16 *)eep; | ||
357 | |||
358 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { | 355 | for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { |
359 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { | 356 | if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { |
360 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 357 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
@@ -363,6 +360,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) | |||
363 | } | 360 | } |
364 | eep_data++; | 361 | eep_data++; |
365 | } | 362 | } |
363 | |||
366 | return true; | 364 | return true; |
367 | #undef SIZE_EEPROM_4K | 365 | #undef SIZE_EEPROM_4K |
368 | } | 366 | } |
@@ -379,16 +377,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
379 | 377 | ||
380 | 378 | ||
381 | if (!ath9k_hw_use_flash(ah)) { | 379 | if (!ath9k_hw_use_flash(ah)) { |
382 | |||
383 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | 380 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, |
384 | &magic)) { | 381 | &magic)) { |
385 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 382 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
386 | "Reading Magic # failed\n"); | 383 | "Reading Magic # failed\n"); |
387 | return false; | 384 | return false; |
388 | } | 385 | } |
389 | 386 | ||
390 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 387 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
391 | "Read Magic = 0x%04X\n", magic); | 388 | "Read Magic = 0x%04X\n", magic); |
392 | 389 | ||
393 | if (magic != AR5416_EEPROM_MAGIC) { | 390 | if (magic != AR5416_EEPROM_MAGIC) { |
394 | magic2 = swab16(magic); | 391 | magic2 = swab16(magic); |
@@ -401,16 +398,9 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
401 | temp = swab16(*eepdata); | 398 | temp = swab16(*eepdata); |
402 | *eepdata = temp; | 399 | *eepdata = temp; |
403 | eepdata++; | 400 | eepdata++; |
404 | |||
405 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
406 | "0x%04X ", *eepdata); | ||
407 | |||
408 | if (((addr + 1) % 6) == 0) | ||
409 | DPRINTF(ah->ah_sc, | ||
410 | ATH_DBG_EEPROM, "\n"); | ||
411 | } | 401 | } |
412 | } else { | 402 | } else { |
413 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 403 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
414 | "Invalid EEPROM Magic. " | 404 | "Invalid EEPROM Magic. " |
415 | "endianness mismatch.\n"); | 405 | "endianness mismatch.\n"); |
416 | return -EINVAL; | 406 | return -EINVAL; |
@@ -426,7 +416,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
426 | else | 416 | else |
427 | el = ah->eeprom.map4k.baseEepHeader.length; | 417 | el = ah->eeprom.map4k.baseEepHeader.length; |
428 | 418 | ||
429 | if (el > sizeof(struct ar5416_eeprom_def)) | 419 | if (el > sizeof(struct ar5416_eeprom_4k)) |
430 | el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); | 420 | el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); |
431 | else | 421 | else |
432 | el = el / sizeof(u16); | 422 | el = el / sizeof(u16); |
@@ -441,7 +431,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
441 | u16 word; | 431 | u16 word; |
442 | 432 | ||
443 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 433 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
444 | "EEPROM Endianness is not native.. Changing \n"); | 434 | "EEPROM Endianness is not native.. Changing\n"); |
445 | 435 | ||
446 | word = swab16(eep->baseEepHeader.length); | 436 | word = swab16(eep->baseEepHeader.length); |
447 | eep->baseEepHeader.length = word; | 437 | eep->baseEepHeader.length = word; |
@@ -483,7 +473,7 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
483 | 473 | ||
484 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 474 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || |
485 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 475 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
486 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 476 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
487 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 477 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
488 | sum, ah->eep_ops->get_eeprom_ver(ah)); | 478 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
489 | return -EINVAL; | 479 | return -EINVAL; |
@@ -1203,57 +1193,63 @@ static void ath9k_hw_4k_set_addac(struct ath_hw *ah, | |||
1203 | } | 1193 | } |
1204 | } | 1194 | } |
1205 | 1195 | ||
1206 | static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, | 1196 | static void ath9k_hw_4k_set_gain(struct ath_hw *ah, |
1207 | struct ath9k_channel *chan) | 1197 | struct modal_eep_4k_header *pModal, |
1198 | struct ar5416_eeprom_4k *eep, | ||
1199 | u8 txRxAttenLocal, int regChainOffset) | ||
1208 | { | 1200 | { |
1209 | struct modal_eep_4k_header *pModal; | ||
1210 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1211 | int regChainOffset; | ||
1212 | u8 txRxAttenLocal; | ||
1213 | u8 ob[5], db1[5], db2[5]; | ||
1214 | u8 ant_div_control1, ant_div_control2; | ||
1215 | u32 regVal; | ||
1216 | |||
1217 | |||
1218 | pModal = &eep->modalHeader; | ||
1219 | |||
1220 | txRxAttenLocal = 23; | ||
1221 | |||
1222 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
1223 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
1224 | |||
1225 | regChainOffset = 0; | ||
1226 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, | 1201 | REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, |
1227 | pModal->antCtrlChain[0]); | 1202 | pModal->antCtrlChain[0]); |
1228 | 1203 | ||
1229 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | 1204 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, |
1230 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & | 1205 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & |
1231 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | 1206 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | |
1232 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | 1207 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | |
1233 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | | 1208 | SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | |
1234 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | 1209 | SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); |
1235 | 1210 | ||
1236 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= | 1211 | if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= |
1237 | AR5416_EEP_MINOR_VER_3) { | 1212 | AR5416_EEP_MINOR_VER_3) { |
1238 | txRxAttenLocal = pModal->txRxAttenCh[0]; | 1213 | txRxAttenLocal = pModal->txRxAttenCh[0]; |
1214 | |||
1239 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 1215 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
1240 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); | 1216 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); |
1241 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 1217 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
1242 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); | 1218 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); |
1243 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 1219 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
1244 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | 1220 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, |
1245 | pModal->xatten2Margin[0]); | 1221 | pModal->xatten2Margin[0]); |
1246 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | 1222 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, |
1247 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); | 1223 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); |
1248 | } | 1224 | } |
1249 | 1225 | ||
1250 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | 1226 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, |
1251 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | 1227 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); |
1252 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, | 1228 | REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, |
1253 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); | 1229 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); |
1254 | 1230 | ||
1255 | if (AR_SREV_9285_11(ah)) | 1231 | if (AR_SREV_9285_11(ah)) |
1256 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); | 1232 | REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); |
1233 | } | ||
1234 | |||
1235 | static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, | ||
1236 | struct ath9k_channel *chan) | ||
1237 | { | ||
1238 | struct modal_eep_4k_header *pModal; | ||
1239 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | ||
1240 | u8 txRxAttenLocal; | ||
1241 | u8 ob[5], db1[5], db2[5]; | ||
1242 | u8 ant_div_control1, ant_div_control2; | ||
1243 | u32 regVal; | ||
1244 | |||
1245 | pModal = &eep->modalHeader; | ||
1246 | txRxAttenLocal = 23; | ||
1247 | |||
1248 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | ||
1249 | ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); | ||
1250 | |||
1251 | /* Single chain for 4K EEPROM*/ | ||
1252 | ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal, 0); | ||
1257 | 1253 | ||
1258 | /* Initialize Ant Diversity settings from EEPROM */ | 1254 | /* Initialize Ant Diversity settings from EEPROM */ |
1259 | if (pModal->version == 3) { | 1255 | if (pModal->version == 3) { |
@@ -1295,9 +1291,6 @@ static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1295 | db2[4] = ((pModal->db2_234 >> 8) & 0xf); | 1291 | db2[4] = ((pModal->db2_234 >> 8) & 0xf); |
1296 | 1292 | ||
1297 | } else if (pModal->version == 1) { | 1293 | } else if (pModal->version == 1) { |
1298 | |||
1299 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1300 | "EEPROM Model version is set to 1 \n"); | ||
1301 | ob[0] = (pModal->ob_01 & 0xf); | 1294 | ob[0] = (pModal->ob_01 & 0xf); |
1302 | ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; | 1295 | ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf; |
1303 | db1[0] = (pModal->db1_01 & 0xf); | 1296 | db1[0] = (pModal->db1_01 & 0xf); |
@@ -1385,8 +1378,6 @@ static bool ath9k_hw_4k_set_board_values(struct ath_hw *ah, | |||
1385 | AR_PHY_SETTLING_SWITCH, | 1378 | AR_PHY_SETTLING_SWITCH, |
1386 | pModal->swSettleHt40); | 1379 | pModal->swSettleHt40); |
1387 | } | 1380 | } |
1388 | |||
1389 | return true; | ||
1390 | } | 1381 | } |
1391 | 1382 | ||
1392 | static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, | 1383 | static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, |
@@ -1464,16 +1455,13 @@ static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) | |||
1464 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | 1455 | static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) |
1465 | { | 1456 | { |
1466 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) | 1457 | #define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) |
1467 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 1458 | u16 *eep_data = (u16 *)&ah->eeprom.def; |
1468 | u16 *eep_data; | ||
1469 | int addr, ar5416_eep_start_loc = 0x100; | 1459 | int addr, ar5416_eep_start_loc = 0x100; |
1470 | 1460 | ||
1471 | eep_data = (u16 *)eep; | ||
1472 | |||
1473 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { | 1461 | for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { |
1474 | if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, | 1462 | if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, |
1475 | eep_data)) { | 1463 | eep_data)) { |
1476 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1464 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
1477 | "Unable to read eeprom region\n"); | 1465 | "Unable to read eeprom region\n"); |
1478 | return false; | 1466 | return false; |
1479 | } | 1467 | } |
@@ -1492,17 +1480,14 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
1492 | bool need_swap = false; | 1480 | bool need_swap = false; |
1493 | int i, addr, size; | 1481 | int i, addr, size; |
1494 | 1482 | ||
1495 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | 1483 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { |
1496 | &magic)) { | 1484 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); |
1497 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1498 | "Reading Magic # failed\n"); | ||
1499 | return false; | 1485 | return false; |
1500 | } | 1486 | } |
1501 | 1487 | ||
1502 | if (!ath9k_hw_use_flash(ah)) { | 1488 | if (!ath9k_hw_use_flash(ah)) { |
1503 | |||
1504 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1489 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
1505 | "Read Magic = 0x%04X\n", magic); | 1490 | "Read Magic = 0x%04X\n", magic); |
1506 | 1491 | ||
1507 | if (magic != AR5416_EEPROM_MAGIC) { | 1492 | if (magic != AR5416_EEPROM_MAGIC) { |
1508 | magic2 = swab16(magic); | 1493 | magic2 = swab16(magic); |
@@ -1516,18 +1501,11 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
1516 | temp = swab16(*eepdata); | 1501 | temp = swab16(*eepdata); |
1517 | *eepdata = temp; | 1502 | *eepdata = temp; |
1518 | eepdata++; | 1503 | eepdata++; |
1519 | |||
1520 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
1521 | "0x%04X ", *eepdata); | ||
1522 | |||
1523 | if (((addr + 1) % 6) == 0) | ||
1524 | DPRINTF(ah->ah_sc, | ||
1525 | ATH_DBG_EEPROM, "\n"); | ||
1526 | } | 1504 | } |
1527 | } else { | 1505 | } else { |
1528 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1506 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
1529 | "Invalid EEPROM Magic. " | 1507 | "Invalid EEPROM Magic. " |
1530 | "endianness mismatch.\n"); | 1508 | "Endianness mismatch.\n"); |
1531 | return -EINVAL; | 1509 | return -EINVAL; |
1532 | } | 1510 | } |
1533 | } | 1511 | } |
@@ -1556,7 +1534,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
1556 | u16 word; | 1534 | u16 word; |
1557 | 1535 | ||
1558 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1536 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
1559 | "EEPROM Endianness is not native.. Changing \n"); | 1537 | "EEPROM Endianness is not native.. Changing.\n"); |
1560 | 1538 | ||
1561 | word = swab16(eep->baseEepHeader.length); | 1539 | word = swab16(eep->baseEepHeader.length); |
1562 | eep->baseEepHeader.length = word; | 1540 | eep->baseEepHeader.length = word; |
@@ -1602,7 +1580,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
1602 | 1580 | ||
1603 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 1581 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || |
1604 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 1582 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { |
1605 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1583 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
1606 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | 1584 | "Bad EEPROM checksum 0x%x or revision 0x%04x\n", |
1607 | sum, ah->eep_ops->get_eeprom_ver(ah)); | 1585 | sum, ah->eep_ops->get_eeprom_ver(ah)); |
1608 | return -EINVAL; | 1586 | return -EINVAL; |
@@ -1614,7 +1592,6 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
1614 | static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | 1592 | static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, |
1615 | enum eeprom_param param) | 1593 | enum eeprom_param param) |
1616 | { | 1594 | { |
1617 | #define AR5416_VER_MASK (pBase->version & AR5416_EEP_VER_MINOR_MASK) | ||
1618 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 1595 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
1619 | struct modal_eep_header *pModal = eep->modalHeader; | 1596 | struct modal_eep_header *pModal = eep->modalHeader; |
1620 | struct base_eep_header *pBase = &eep->baseEepHeader; | 1597 | struct base_eep_header *pBase = &eep->baseEepHeader; |
@@ -1681,21 +1658,73 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | |||
1681 | default: | 1658 | default: |
1682 | return 0; | 1659 | return 0; |
1683 | } | 1660 | } |
1684 | #undef AR5416_VER_MASK | ||
1685 | } | 1661 | } |
1686 | 1662 | ||
1687 | /* XXX: Clean me up, make me more legible */ | 1663 | static void ath9k_hw_def_set_gain(struct ath_hw *ah, |
1688 | static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | 1664 | struct modal_eep_header *pModal, |
1665 | struct ar5416_eeprom_def *eep, | ||
1666 | u8 txRxAttenLocal, int regChainOffset, int i) | ||
1667 | { | ||
1668 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | ||
1669 | txRxAttenLocal = pModal->txRxAttenCh[i]; | ||
1670 | |||
1671 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1672 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1673 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
1674 | pModal->bswMargin[i]); | ||
1675 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1676 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
1677 | pModal->bswAtten[i]); | ||
1678 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1679 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
1680 | pModal->xatten2Margin[i]); | ||
1681 | REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1682 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
1683 | pModal->xatten2Db[i]); | ||
1684 | } else { | ||
1685 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1686 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
1687 | ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | ||
1688 | | SM(pModal-> bswMargin[i], | ||
1689 | AR_PHY_GAIN_2GHZ_BSW_MARGIN)); | ||
1690 | REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1691 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
1692 | ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | ||
1693 | | SM(pModal->bswAtten[i], | ||
1694 | AR_PHY_GAIN_2GHZ_BSW_ATTEN)); | ||
1695 | } | ||
1696 | } | ||
1697 | |||
1698 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1699 | REG_RMW_FIELD(ah, | ||
1700 | AR_PHY_RXGAIN + regChainOffset, | ||
1701 | AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); | ||
1702 | REG_RMW_FIELD(ah, | ||
1703 | AR_PHY_RXGAIN + regChainOffset, | ||
1704 | AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); | ||
1705 | } else { | ||
1706 | REG_WRITE(ah, | ||
1707 | AR_PHY_RXGAIN + regChainOffset, | ||
1708 | (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & | ||
1709 | ~AR_PHY_RXGAIN_TXRX_ATTEN) | ||
1710 | | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); | ||
1711 | REG_WRITE(ah, | ||
1712 | AR_PHY_GAIN_2GHZ + regChainOffset, | ||
1713 | (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & | ||
1714 | ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | | ||
1715 | SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); | ||
1716 | } | ||
1717 | } | ||
1718 | |||
1719 | static void ath9k_hw_def_set_board_values(struct ath_hw *ah, | ||
1689 | struct ath9k_channel *chan) | 1720 | struct ath9k_channel *chan) |
1690 | { | 1721 | { |
1691 | #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) | ||
1692 | struct modal_eep_header *pModal; | 1722 | struct modal_eep_header *pModal; |
1693 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 1723 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
1694 | int i, regChainOffset; | 1724 | int i, regChainOffset; |
1695 | u8 txRxAttenLocal; | 1725 | u8 txRxAttenLocal; |
1696 | 1726 | ||
1697 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); | 1727 | pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); |
1698 | |||
1699 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; | 1728 | txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; |
1700 | 1729 | ||
1701 | REG_WRITE(ah, AR_PHY_SWITCH_COM, | 1730 | REG_WRITE(ah, AR_PHY_SWITCH_COM, |
@@ -1708,8 +1737,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1708 | } | 1737 | } |
1709 | 1738 | ||
1710 | if (AR_SREV_5416_20_OR_LATER(ah) && | 1739 | if (AR_SREV_5416_20_OR_LATER(ah) && |
1711 | (ah->rxchainmask == 5 || ah->txchainmask == 5) | 1740 | (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) |
1712 | && (i != 0)) | ||
1713 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; | 1741 | regChainOffset = (i == 1) ? 0x2000 : 0x1000; |
1714 | else | 1742 | else |
1715 | regChainOffset = i * 0x1000; | 1743 | regChainOffset = i * 0x1000; |
@@ -1718,9 +1746,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1718 | pModal->antCtrlChain[i]); | 1746 | pModal->antCtrlChain[i]); |
1719 | 1747 | ||
1720 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, | 1748 | REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, |
1721 | (REG_READ(ah, | 1749 | (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & |
1722 | AR_PHY_TIMING_CTRL4(0) + | ||
1723 | regChainOffset) & | ||
1724 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | | 1750 | ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | |
1725 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | | 1751 | AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | |
1726 | SM(pModal->iqCalICh[i], | 1752 | SM(pModal->iqCalICh[i], |
@@ -1728,87 +1754,9 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1728 | SM(pModal->iqCalQCh[i], | 1754 | SM(pModal->iqCalQCh[i], |
1729 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); | 1755 | AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); |
1730 | 1756 | ||
1731 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { | 1757 | if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) |
1732 | if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { | 1758 | ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, |
1733 | txRxAttenLocal = pModal->txRxAttenCh[i]; | 1759 | regChainOffset, i); |
1734 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1735 | REG_RMW_FIELD(ah, | ||
1736 | AR_PHY_GAIN_2GHZ + | ||
1737 | regChainOffset, | ||
1738 | AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, | ||
1739 | pModal-> | ||
1740 | bswMargin[i]); | ||
1741 | REG_RMW_FIELD(ah, | ||
1742 | AR_PHY_GAIN_2GHZ + | ||
1743 | regChainOffset, | ||
1744 | AR_PHY_GAIN_2GHZ_XATTEN1_DB, | ||
1745 | pModal-> | ||
1746 | bswAtten[i]); | ||
1747 | REG_RMW_FIELD(ah, | ||
1748 | AR_PHY_GAIN_2GHZ + | ||
1749 | regChainOffset, | ||
1750 | AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, | ||
1751 | pModal-> | ||
1752 | xatten2Margin[i]); | ||
1753 | REG_RMW_FIELD(ah, | ||
1754 | AR_PHY_GAIN_2GHZ + | ||
1755 | regChainOffset, | ||
1756 | AR_PHY_GAIN_2GHZ_XATTEN2_DB, | ||
1757 | pModal-> | ||
1758 | xatten2Db[i]); | ||
1759 | } else { | ||
1760 | REG_WRITE(ah, | ||
1761 | AR_PHY_GAIN_2GHZ + | ||
1762 | regChainOffset, | ||
1763 | (REG_READ(ah, | ||
1764 | AR_PHY_GAIN_2GHZ + | ||
1765 | regChainOffset) & | ||
1766 | ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) | ||
1767 | | SM(pModal-> | ||
1768 | bswMargin[i], | ||
1769 | AR_PHY_GAIN_2GHZ_BSW_MARGIN)); | ||
1770 | REG_WRITE(ah, | ||
1771 | AR_PHY_GAIN_2GHZ + | ||
1772 | regChainOffset, | ||
1773 | (REG_READ(ah, | ||
1774 | AR_PHY_GAIN_2GHZ + | ||
1775 | regChainOffset) & | ||
1776 | ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) | ||
1777 | | SM(pModal->bswAtten[i], | ||
1778 | AR_PHY_GAIN_2GHZ_BSW_ATTEN)); | ||
1779 | } | ||
1780 | } | ||
1781 | if (AR_SREV_9280_10_OR_LATER(ah)) { | ||
1782 | REG_RMW_FIELD(ah, | ||
1783 | AR_PHY_RXGAIN + | ||
1784 | regChainOffset, | ||
1785 | AR9280_PHY_RXGAIN_TXRX_ATTEN, | ||
1786 | txRxAttenLocal); | ||
1787 | REG_RMW_FIELD(ah, | ||
1788 | AR_PHY_RXGAIN + | ||
1789 | regChainOffset, | ||
1790 | AR9280_PHY_RXGAIN_TXRX_MARGIN, | ||
1791 | pModal->rxTxMarginCh[i]); | ||
1792 | } else { | ||
1793 | REG_WRITE(ah, | ||
1794 | AR_PHY_RXGAIN + regChainOffset, | ||
1795 | (REG_READ(ah, | ||
1796 | AR_PHY_RXGAIN + | ||
1797 | regChainOffset) & | ||
1798 | ~AR_PHY_RXGAIN_TXRX_ATTEN) | | ||
1799 | SM(txRxAttenLocal, | ||
1800 | AR_PHY_RXGAIN_TXRX_ATTEN)); | ||
1801 | REG_WRITE(ah, | ||
1802 | AR_PHY_GAIN_2GHZ + | ||
1803 | regChainOffset, | ||
1804 | (REG_READ(ah, | ||
1805 | AR_PHY_GAIN_2GHZ + | ||
1806 | regChainOffset) & | ||
1807 | ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | | ||
1808 | SM(pModal->rxTxMarginCh[i], | ||
1809 | AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); | ||
1810 | } | ||
1811 | } | ||
1812 | } | 1760 | } |
1813 | 1761 | ||
1814 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1762 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
@@ -1855,8 +1803,6 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1855 | AR_AN_TOP2_LOCALBIAS, | 1803 | AR_AN_TOP2_LOCALBIAS, |
1856 | AR_AN_TOP2_LOCALBIAS_S, | 1804 | AR_AN_TOP2_LOCALBIAS_S, |
1857 | pModal->local_bias); | 1805 | pModal->local_bias); |
1858 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "ForceXPAon: %d\n", | ||
1859 | pModal->force_xpaon); | ||
1860 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, | 1806 | REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, |
1861 | pModal->force_xpaon); | 1807 | pModal->force_xpaon); |
1862 | } | 1808 | } |
@@ -1882,6 +1828,7 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1882 | 1828 | ||
1883 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, | 1829 | REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, |
1884 | pModal->txEndToRxOn); | 1830 | pModal->txEndToRxOn); |
1831 | |||
1885 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 1832 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
1886 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, | 1833 | REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, |
1887 | pModal->thresh62); | 1834 | pModal->thresh62); |
@@ -1912,10 +1859,10 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1912 | } | 1859 | } |
1913 | 1860 | ||
1914 | if (AR_SREV_9280_20_OR_LATER(ah) && | 1861 | if (AR_SREV_9280_20_OR_LATER(ah) && |
1915 | AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) | 1862 | AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) |
1916 | REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, | 1863 | REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, |
1917 | AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, | 1864 | AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, |
1918 | pModal->miscBits); | 1865 | pModal->miscBits); |
1919 | 1866 | ||
1920 | 1867 | ||
1921 | if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { | 1868 | if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { |
@@ -1926,18 +1873,15 @@ static bool ath9k_hw_def_set_board_values(struct ath_hw *ah, | |||
1926 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); | 1873 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); |
1927 | else | 1874 | else |
1928 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, | 1875 | REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, |
1929 | eep->baseEepHeader.dacLpMode); | 1876 | eep->baseEepHeader.dacLpMode); |
1930 | 1877 | ||
1931 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, | 1878 | REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, |
1932 | pModal->miscBits >> 2); | 1879 | pModal->miscBits >> 2); |
1933 | 1880 | ||
1934 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, | 1881 | REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, |
1935 | AR_PHY_TX_DESIRED_SCALE_CCK, | 1882 | AR_PHY_TX_DESIRED_SCALE_CCK, |
1936 | eep->baseEepHeader.desiredScaleCCK); | 1883 | eep->baseEepHeader.desiredScaleCCK); |
1937 | } | 1884 | } |
1938 | |||
1939 | return true; | ||
1940 | #undef AR5416_VER_MASK | ||
1941 | } | 1885 | } |
1942 | 1886 | ||
1943 | static void ath9k_hw_def_set_addac(struct ath_hw *ah, | 1887 | static void ath9k_hw_def_set_addac(struct ath_hw *ah, |
diff --git a/drivers/net/wireless/ath9k/eeprom.h b/drivers/net/wireless/ath9k/eeprom.h index d6f6108f63c7..25b68c881ff1 100644 --- a/drivers/net/wireless/ath9k/eeprom.h +++ b/drivers/net/wireless/ath9k/eeprom.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -95,6 +95,7 @@ | |||
95 | #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) | 95 | #define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) |
96 | #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) | 96 | #define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) |
97 | 97 | ||
98 | #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) | ||
98 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ | 99 | #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ |
99 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) | 100 | ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) |
100 | 101 | ||
@@ -489,7 +490,7 @@ struct eeprom_ops { | |||
489 | u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); | 490 | u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); |
490 | u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, | 491 | u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, |
491 | struct ath9k_channel *chan); | 492 | struct ath9k_channel *chan); |
492 | bool (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); | 493 | void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); |
493 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); | 494 | void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); |
494 | int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, | 495 | int (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, |
495 | u16 cfgCtl, u8 twiceAntennaReduction, | 496 | u16 cfgCtl, u8 twiceAntennaReduction, |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index d494e98ba971..b15eaf8417ff 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -588,6 +588,10 @@ static int ath9k_hw_post_attach(struct ath_hw *ah) | |||
588 | ecode = ath9k_hw_eeprom_attach(ah); | 588 | ecode = ath9k_hw_eeprom_attach(ah); |
589 | if (ecode != 0) | 589 | if (ecode != 0) |
590 | return ecode; | 590 | return ecode; |
591 | |||
592 | DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", | ||
593 | ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); | ||
594 | |||
591 | ecode = ath9k_hw_rfattach(ah); | 595 | ecode = ath9k_hw_rfattach(ah); |
592 | if (ecode != 0) | 596 | if (ecode != 0) |
593 | return ecode; | 597 | return ecode; |
@@ -1444,6 +1448,7 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) | |||
1444 | REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); | 1448 | REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); |
1445 | break; | 1449 | break; |
1446 | case NL80211_IFTYPE_ADHOC: | 1450 | case NL80211_IFTYPE_ADHOC: |
1451 | case NL80211_IFTYPE_MESH_POINT: | ||
1447 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC | 1452 | REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC |
1448 | | AR_STA_ID1_KSRCH_MODE); | 1453 | | AR_STA_ID1_KSRCH_MODE); |
1449 | REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); | 1454 | REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); |
@@ -2273,11 +2278,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2273 | else | 2278 | else |
2274 | ath9k_hw_spur_mitigate(ah, chan); | 2279 | ath9k_hw_spur_mitigate(ah, chan); |
2275 | 2280 | ||
2276 | if (!ah->eep_ops->set_board_values(ah, chan)) { | 2281 | ah->eep_ops->set_board_values(ah, chan); |
2277 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | ||
2278 | "error setting board options\n"); | ||
2279 | return -EIO; | ||
2280 | } | ||
2281 | 2282 | ||
2282 | ath9k_hw_decrease_chain_power(ah, chan); | 2283 | ath9k_hw_decrease_chain_power(ah, chan); |
2283 | 2284 | ||
@@ -3149,6 +3150,7 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) | |||
3149 | flags |= AR_TBTT_TIMER_EN; | 3150 | flags |= AR_TBTT_TIMER_EN; |
3150 | break; | 3151 | break; |
3151 | case NL80211_IFTYPE_ADHOC: | 3152 | case NL80211_IFTYPE_ADHOC: |
3153 | case NL80211_IFTYPE_MESH_POINT: | ||
3152 | REG_SET_BIT(ah, AR_TXCFG, | 3154 | REG_SET_BIT(ah, AR_TXCFG, |
3153 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); | 3155 | AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); |
3154 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, | 3156 | REG_WRITE(ah, AR_NEXT_NDP_TIMER, |
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h index dc681f011fdf..0b594e0ee260 100644 --- a/drivers/net/wireless/ath9k/hw.h +++ b/drivers/net/wireless/ath9k/hw.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h index 1d60c3706f1c..e2f0a34b79a1 100644 --- a/drivers/net/wireless/ath9k/initvals.h +++ b/drivers/net/wireless/ath9k/initvals.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c index f757bc7eec68..e0a6dee45839 100644 --- a/drivers/net/wireless/ath9k/mac.c +++ b/drivers/net/wireless/ath9k/mac.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/mac.h b/drivers/net/wireless/ath9k/mac.h index a75f65dae1d7..1176bce8b76c 100644 --- a/drivers/net/wireless/ath9k/mac.h +++ b/drivers/net/wireless/ath9k/mac.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 8db75f6de53e..13d4e6756c99 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -940,18 +940,25 @@ static void ath_led_blink_work(struct work_struct *work) | |||
940 | 940 | ||
941 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) | 941 | if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) |
942 | return; | 942 | return; |
943 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, | 943 | |
944 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | 944 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || |
945 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | ||
946 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); | ||
947 | else | ||
948 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, | ||
949 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | ||
945 | 950 | ||
946 | queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, | 951 | queue_delayed_work(sc->hw->workqueue, &sc->ath_led_blink_work, |
947 | (sc->sc_flags & SC_OP_LED_ON) ? | 952 | (sc->sc_flags & SC_OP_LED_ON) ? |
948 | msecs_to_jiffies(sc->led_off_duration) : | 953 | msecs_to_jiffies(sc->led_off_duration) : |
949 | msecs_to_jiffies(sc->led_on_duration)); | 954 | msecs_to_jiffies(sc->led_on_duration)); |
950 | 955 | ||
951 | sc->led_on_duration = | 956 | sc->led_on_duration = sc->led_on_cnt ? |
952 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25); | 957 | max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : |
953 | sc->led_off_duration = | 958 | ATH_LED_ON_DURATION_IDLE; |
954 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10); | 959 | sc->led_off_duration = sc->led_off_cnt ? |
960 | max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : | ||
961 | ATH_LED_OFF_DURATION_IDLE; | ||
955 | sc->led_on_cnt = sc->led_off_cnt = 0; | 962 | sc->led_on_cnt = sc->led_off_cnt = 0; |
956 | if (sc->sc_flags & SC_OP_LED_ON) | 963 | if (sc->sc_flags & SC_OP_LED_ON) |
957 | sc->sc_flags &= ~SC_OP_LED_ON; | 964 | sc->sc_flags &= ~SC_OP_LED_ON; |
@@ -1592,7 +1599,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1592 | hw->wiphy->interface_modes = | 1599 | hw->wiphy->interface_modes = |
1593 | BIT(NL80211_IFTYPE_AP) | | 1600 | BIT(NL80211_IFTYPE_AP) | |
1594 | BIT(NL80211_IFTYPE_STATION) | | 1601 | BIT(NL80211_IFTYPE_STATION) | |
1595 | BIT(NL80211_IFTYPE_ADHOC); | 1602 | BIT(NL80211_IFTYPE_ADHOC) | |
1603 | BIT(NL80211_IFTYPE_MESH_POINT); | ||
1596 | 1604 | ||
1597 | hw->wiphy->reg_notifier = ath9k_reg_notifier; | 1605 | hw->wiphy->reg_notifier = ath9k_reg_notifier; |
1598 | hw->wiphy->strict_regulatory = true; | 1606 | hw->wiphy->strict_regulatory = true; |
@@ -2200,18 +2208,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2200 | ic_opmode = NL80211_IFTYPE_STATION; | 2208 | ic_opmode = NL80211_IFTYPE_STATION; |
2201 | break; | 2209 | break; |
2202 | case NL80211_IFTYPE_ADHOC: | 2210 | case NL80211_IFTYPE_ADHOC: |
2203 | if (sc->nbcnvifs >= ATH_BCBUF) { | ||
2204 | ret = -ENOBUFS; | ||
2205 | goto out; | ||
2206 | } | ||
2207 | ic_opmode = NL80211_IFTYPE_ADHOC; | ||
2208 | break; | ||
2209 | case NL80211_IFTYPE_AP: | 2211 | case NL80211_IFTYPE_AP: |
2212 | case NL80211_IFTYPE_MESH_POINT: | ||
2210 | if (sc->nbcnvifs >= ATH_BCBUF) { | 2213 | if (sc->nbcnvifs >= ATH_BCBUF) { |
2211 | ret = -ENOBUFS; | 2214 | ret = -ENOBUFS; |
2212 | goto out; | 2215 | goto out; |
2213 | } | 2216 | } |
2214 | ic_opmode = NL80211_IFTYPE_AP; | 2217 | ic_opmode = conf->type; |
2215 | break; | 2218 | break; |
2216 | default: | 2219 | default: |
2217 | DPRINTF(sc, ATH_DBG_FATAL, | 2220 | DPRINTF(sc, ATH_DBG_FATAL, |
@@ -2247,7 +2250,8 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2247 | * Note we only do this (at the moment) for station mode. | 2250 | * Note we only do this (at the moment) for station mode. |
2248 | */ | 2251 | */ |
2249 | if ((conf->type == NL80211_IFTYPE_STATION) || | 2252 | if ((conf->type == NL80211_IFTYPE_STATION) || |
2250 | (conf->type == NL80211_IFTYPE_ADHOC)) { | 2253 | (conf->type == NL80211_IFTYPE_ADHOC) || |
2254 | (conf->type == NL80211_IFTYPE_MESH_POINT)) { | ||
2251 | if (ath9k_hw_phycounters(sc->sc_ah)) | 2255 | if (ath9k_hw_phycounters(sc->sc_ah)) |
2252 | sc->imask |= ATH9K_INT_MIB; | 2256 | sc->imask |= ATH9K_INT_MIB; |
2253 | sc->imask |= ATH9K_INT_TSFOOR; | 2257 | sc->imask |= ATH9K_INT_TSFOOR; |
@@ -2294,8 +2298,9 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2294 | del_timer_sync(&sc->ani.timer); | 2298 | del_timer_sync(&sc->ani.timer); |
2295 | 2299 | ||
2296 | /* Reclaim beacon resources */ | 2300 | /* Reclaim beacon resources */ |
2297 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || | 2301 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
2298 | sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) { | 2302 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || |
2303 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { | ||
2299 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2304 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
2300 | ath_beacon_return(sc, avp); | 2305 | ath_beacon_return(sc, avp); |
2301 | } | 2306 | } |
@@ -2428,6 +2433,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
2428 | switch (vif->type) { | 2433 | switch (vif->type) { |
2429 | case NL80211_IFTYPE_STATION: | 2434 | case NL80211_IFTYPE_STATION: |
2430 | case NL80211_IFTYPE_ADHOC: | 2435 | case NL80211_IFTYPE_ADHOC: |
2436 | case NL80211_IFTYPE_MESH_POINT: | ||
2431 | /* Set BSSID */ | 2437 | /* Set BSSID */ |
2432 | memcpy(sc->curbssid, conf->bssid, ETH_ALEN); | 2438 | memcpy(sc->curbssid, conf->bssid, ETH_ALEN); |
2433 | memcpy(avp->bssid, conf->bssid, ETH_ALEN); | 2439 | memcpy(avp->bssid, conf->bssid, ETH_ALEN); |
@@ -2451,7 +2457,8 @@ static int ath9k_config_interface(struct ieee80211_hw *hw, | |||
2451 | } | 2457 | } |
2452 | 2458 | ||
2453 | if ((vif->type == NL80211_IFTYPE_ADHOC) || | 2459 | if ((vif->type == NL80211_IFTYPE_ADHOC) || |
2454 | (vif->type == NL80211_IFTYPE_AP)) { | 2460 | (vif->type == NL80211_IFTYPE_AP) || |
2461 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | ||
2455 | if ((conf->changed & IEEE80211_IFCC_BEACON) || | 2462 | if ((conf->changed & IEEE80211_IFCC_BEACON) || |
2456 | (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && | 2463 | (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && |
2457 | conf->enable_beacon)) { | 2464 | conf->enable_beacon)) { |
@@ -2723,7 +2730,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
2723 | 2730 | ||
2724 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2731 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); |
2725 | break; | 2732 | break; |
2726 | case IEEE80211_AMPDU_TX_RESUME: | 2733 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
2727 | ath_tx_aggr_resume(sc, sta, tid); | 2734 | ath_tx_aggr_resume(sc, sta, tid); |
2728 | break; | 2735 | break; |
2729 | default: | 2736 | default: |
diff --git a/drivers/net/wireless/ath9k/pci.c b/drivers/net/wireless/ath9k/pci.c index 9a58baabb9ca..6dbc58580abb 100644 --- a/drivers/net/wireless/ath9k/pci.c +++ b/drivers/net/wireless/ath9k/pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -87,7 +87,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
87 | struct ath_softc *sc; | 87 | struct ath_softc *sc; |
88 | struct ieee80211_hw *hw; | 88 | struct ieee80211_hw *hw; |
89 | u8 csz; | 89 | u8 csz; |
90 | u32 val; | ||
91 | int ret = 0; | 90 | int ret = 0; |
92 | struct ath_hw *ah; | 91 | struct ath_hw *ah; |
93 | 92 | ||
@@ -134,14 +133,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
134 | 133 | ||
135 | pci_set_master(pdev); | 134 | pci_set_master(pdev); |
136 | 135 | ||
137 | /* | ||
138 | * Disable the RETRY_TIMEOUT register (0x41) to keep | ||
139 | * PCI Tx retries from interfering with C3 CPU state. | ||
140 | */ | ||
141 | pci_read_config_dword(pdev, 0x40, &val); | ||
142 | if ((val & 0x0000ff00) != 0) | ||
143 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
144 | |||
145 | ret = pci_request_region(pdev, 0, "ath9k"); | 136 | ret = pci_request_region(pdev, 0, "ath9k"); |
146 | if (ret) { | 137 | if (ret) { |
147 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); | 138 | dev_err(&pdev->dev, "PCI memory region reserve error\n"); |
@@ -253,21 +244,12 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
253 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); | 244 | struct ieee80211_hw *hw = pci_get_drvdata(pdev); |
254 | struct ath_wiphy *aphy = hw->priv; | 245 | struct ath_wiphy *aphy = hw->priv; |
255 | struct ath_softc *sc = aphy->sc; | 246 | struct ath_softc *sc = aphy->sc; |
256 | u32 val; | ||
257 | int err; | 247 | int err; |
258 | 248 | ||
259 | err = pci_enable_device(pdev); | 249 | err = pci_enable_device(pdev); |
260 | if (err) | 250 | if (err) |
261 | return err; | 251 | return err; |
262 | pci_restore_state(pdev); | 252 | pci_restore_state(pdev); |
263 | /* | ||
264 | * Suspend/Resume resets the PCI configuration space, so we have to | ||
265 | * re-disable the RETRY_TIMEOUT register (0x41) to keep | ||
266 | * PCI Tx retries from interfering with C3 CPU state | ||
267 | */ | ||
268 | pci_read_config_dword(pdev, 0x40, &val); | ||
269 | if ((val & 0x0000ff00) != 0) | ||
270 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | ||
271 | 253 | ||
272 | /* Enable LED */ | 254 | /* Enable LED */ |
273 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, | 255 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, |
diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c index e1494bae0f9f..8bcba906929a 100644 --- a/drivers/net/wireless/ath9k/phy.c +++ b/drivers/net/wireless/ath9k/phy.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h index 1eac8c707342..0f7f8e0c9c95 100644 --- a/drivers/net/wireless/ath9k/phy.h +++ b/drivers/net/wireless/ath9k/phy.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 832735677a46..824ccbb8b7b8 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Video54 Technologies, Inc. | 2 | * Copyright (c) 2004 Video54 Technologies, Inc. |
3 | * Copyright (c) 2004-2008 Atheros Communications, Inc. | 3 | * Copyright (c) 2004-2009 Atheros Communications, Inc. |
4 | * | 4 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | 5 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above | 6 | * purpose with or without fee is hereby granted, provided that the above |
@@ -864,6 +864,8 @@ static void ath_rc_ratefind(struct ath_softc *sc, | |||
864 | rate_table, nrix, 1, 0); | 864 | rate_table, nrix, 1, 0); |
865 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, | 865 | ath_rc_rate_set_series(rate_table, &rates[i++], txrc, |
866 | try_per_rate, nrix, 0); | 866 | try_per_rate, nrix, 0); |
867 | |||
868 | tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
867 | } else { | 869 | } else { |
868 | try_per_rate = (ATH_11N_TXMAXTRY/4); | 870 | try_per_rate = (ATH_11N_TXMAXTRY/4); |
869 | /* Set the choosen rate. No RTS for first series entry. */ | 871 | /* Set the choosen rate. No RTS for first series entry. */ |
@@ -1468,16 +1470,18 @@ static void ath_rc_init(struct ath_softc *sc, | |||
1468 | ath_rc_priv->ht_cap); | 1470 | ath_rc_priv->ht_cap); |
1469 | } | 1471 | } |
1470 | 1472 | ||
1471 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, bool is_ht, bool is_cw40, | 1473 | static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, |
1472 | bool is_sgi40) | 1474 | bool is_cw40, bool is_sgi40) |
1473 | { | 1475 | { |
1474 | u8 caps = 0; | 1476 | u8 caps = 0; |
1475 | 1477 | ||
1476 | if (is_ht) { | 1478 | if (sta->ht_cap.ht_supported) { |
1477 | caps = WLAN_RC_HT_FLAG; | 1479 | caps = WLAN_RC_HT_FLAG; |
1478 | if (sc->sc_ah->caps.tx_chainmask != 1 && | 1480 | if (sc->sc_ah->caps.tx_chainmask != 1 && |
1479 | ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) | 1481 | ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { |
1480 | caps |= WLAN_RC_DS_FLAG; | 1482 | if (sta->ht_cap.mcs.rx_mask[1]) |
1483 | caps |= WLAN_RC_DS_FLAG; | ||
1484 | } | ||
1481 | if (is_cw40) | 1485 | if (is_cw40) |
1482 | caps |= WLAN_RC_40_FLAG; | 1486 | caps |= WLAN_RC_40_FLAG; |
1483 | if (is_sgi40) | 1487 | if (is_sgi40) |
@@ -1615,6 +1619,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1615 | /* Choose rate table first */ | 1619 | /* Choose rate table first */ |
1616 | 1620 | ||
1617 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || | 1621 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || |
1622 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || | ||
1618 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { | 1623 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { |
1619 | rate_table = ath_choose_rate_table(sc, sband->band, | 1624 | rate_table = ath_choose_rate_table(sc, sband->band, |
1620 | sta->ht_cap.ht_supported, | 1625 | sta->ht_cap.ht_supported, |
@@ -1624,8 +1629,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
1624 | rate_table = sc->cur_rate_table; | 1629 | rate_table = sc->cur_rate_table; |
1625 | } | 1630 | } |
1626 | 1631 | ||
1627 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta->ht_cap.ht_supported, | 1632 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); |
1628 | is_cw40, is_sgi40); | ||
1629 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1633 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
1630 | } | 1634 | } |
1631 | 1635 | ||
@@ -1659,8 +1663,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, | |||
1659 | rate_table = ath_choose_rate_table(sc, sband->band, | 1663 | rate_table = ath_choose_rate_table(sc, sband->band, |
1660 | sta->ht_cap.ht_supported, | 1664 | sta->ht_cap.ht_supported, |
1661 | oper_cw40); | 1665 | oper_cw40); |
1662 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, | 1666 | ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, |
1663 | sta->ht_cap.ht_supported, | ||
1664 | oper_cw40, oper_sgi40); | 1667 | oper_cw40, oper_sgi40); |
1665 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); | 1668 | ath_rc_init(sc, priv_sta, sband, sta, rate_table); |
1666 | 1669 | ||
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h index db9b0b9a3431..199a3ce57d64 100644 --- a/drivers/net/wireless/ath9k/rc.h +++ b/drivers/net/wireless/ath9k/rc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2004 Sam Leffler, Errno Consulting | 2 | * Copyright (c) 2004 Sam Leffler, Errno Consulting |
3 | * Copyright (c) 2004 Video54 Technologies, Inc. | 3 | * Copyright (c) 2004 Video54 Technologies, Inc. |
4 | * Copyright (c) 2008 Atheros Communications Inc. | 4 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
5 | * | 5 | * |
6 | * Permission to use, copy, modify, and/or distribute this software for any | 6 | * Permission to use, copy, modify, and/or distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above | 7 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 0bba17662a1f..71cb18d6757d 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -344,8 +344,13 @@ void ath_rx_cleanup(struct ath_softc *sc) | |||
344 | 344 | ||
345 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { | 345 | list_for_each_entry(bf, &sc->rx.rxbuf, list) { |
346 | skb = bf->bf_mpdu; | 346 | skb = bf->bf_mpdu; |
347 | if (skb) | 347 | if (skb) { |
348 | dma_unmap_single(sc->dev, | ||
349 | bf->bf_buf_addr, | ||
350 | sc->rx.bufsize, | ||
351 | DMA_FROM_DEVICE); | ||
348 | dev_kfree_skb(skb); | 352 | dev_kfree_skb(skb); |
353 | } | ||
349 | } | 354 | } |
350 | 355 | ||
351 | if (sc->rx.rxdma.dd_desc_len != 0) | 356 | if (sc->rx.rxdma.dd_desc_len != 0) |
diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h index d86e90e38173..52605246679f 100644 --- a/drivers/net/wireless/ath9k/reg.h +++ b/drivers/net/wireless/ath9k/reg.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c index b8f9b6d6bec4..4ca625102291 100644 --- a/drivers/net/wireless/ath9k/regd.c +++ b/drivers/net/wireless/ath9k/regd.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h index 8f885f3bc8df..9f5fbd4eea7a 100644 --- a/drivers/net/wireless/ath9k/regd.h +++ b/drivers/net/wireless/ath9k/regd.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/regd_common.h b/drivers/net/wireless/ath9k/regd_common.h index b41d0002f3fe..4d0e298cd1c7 100644 --- a/drivers/net/wireless/ath9k/regd_common.h +++ b/drivers/net/wireless/ath9k/regd_common.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index e3f376611f85..689bdbf78808 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008 Atheros Communications Inc. | 2 | * Copyright (c) 2008-2009 Atheros Communications Inc. |
3 | * | 3 | * |
4 | * Permission to use, copy, modify, and/or distribute this software for any | 4 | * Permission to use, copy, modify, and/or distribute this software for any |
5 | * purpose with or without fee is hereby granted, provided that the above | 5 | * purpose with or without fee is hereby granted, provided that the above |
@@ -64,6 +64,10 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
64 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | 64 | static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, |
65 | struct list_head *head); | 65 | struct list_head *head); |
66 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); | 66 | static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); |
67 | static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | ||
68 | int txok); | ||
69 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | ||
70 | int nbad, int txok, bool update_rc); | ||
67 | 71 | ||
68 | /*********************/ | 72 | /*********************/ |
69 | /* Aggregation logic */ | 73 | /* Aggregation logic */ |
@@ -274,9 +278,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
274 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 278 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
275 | struct ath_desc *ds = bf_last->bf_desc; | 279 | struct ath_desc *ds = bf_last->bf_desc; |
276 | struct list_head bf_head, bf_pending; | 280 | struct list_head bf_head, bf_pending; |
277 | u16 seq_st = 0; | 281 | u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; |
278 | u32 ba[WME_BA_BMP_SIZE >> 5]; | 282 | u32 ba[WME_BA_BMP_SIZE >> 5]; |
279 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0; | 283 | int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; |
284 | bool rc_update = true; | ||
280 | 285 | ||
281 | skb = (struct sk_buff *)bf->bf_mpdu; | 286 | skb = (struct sk_buff *)bf->bf_mpdu; |
282 | hdr = (struct ieee80211_hdr *)skb->data; | 287 | hdr = (struct ieee80211_hdr *)skb->data; |
@@ -316,6 +321,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
316 | INIT_LIST_HEAD(&bf_pending); | 321 | INIT_LIST_HEAD(&bf_pending); |
317 | INIT_LIST_HEAD(&bf_head); | 322 | INIT_LIST_HEAD(&bf_head); |
318 | 323 | ||
324 | nbad = ath_tx_num_badfrms(sc, bf, txok); | ||
319 | while (bf) { | 325 | while (bf) { |
320 | txfail = txpending = 0; | 326 | txfail = txpending = 0; |
321 | bf_next = bf->bf_next; | 327 | bf_next = bf->bf_next; |
@@ -323,8 +329,10 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
323 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { | 329 | if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { |
324 | /* transmit completion, subframe is | 330 | /* transmit completion, subframe is |
325 | * acked by block ack */ | 331 | * acked by block ack */ |
332 | acked_cnt++; | ||
326 | } else if (!isaggr && txok) { | 333 | } else if (!isaggr && txok) { |
327 | /* transmit completion */ | 334 | /* transmit completion */ |
335 | acked_cnt++; | ||
328 | } else { | 336 | } else { |
329 | if (!(tid->state & AGGR_CLEANUP) && | 337 | if (!(tid->state & AGGR_CLEANUP) && |
330 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { | 338 | ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { |
@@ -335,6 +343,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
335 | bf->bf_state.bf_type |= BUF_XRETRY; | 343 | bf->bf_state.bf_type |= BUF_XRETRY; |
336 | txfail = 1; | 344 | txfail = 1; |
337 | sendbar = 1; | 345 | sendbar = 1; |
346 | txfail_cnt++; | ||
338 | } | 347 | } |
339 | } else { | 348 | } else { |
340 | /* | 349 | /* |
@@ -361,6 +370,13 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
361 | ath_tx_update_baw(sc, tid, bf->bf_seqno); | 370 | ath_tx_update_baw(sc, tid, bf->bf_seqno); |
362 | spin_unlock_bh(&txq->axq_lock); | 371 | spin_unlock_bh(&txq->axq_lock); |
363 | 372 | ||
373 | if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { | ||
374 | ath_tx_rc_status(bf, ds, nbad, txok, true); | ||
375 | rc_update = false; | ||
376 | } else { | ||
377 | ath_tx_rc_status(bf, ds, nbad, txok, false); | ||
378 | } | ||
379 | |||
364 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); | 380 | ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar); |
365 | } else { | 381 | } else { |
366 | /* retry the un-acked ones */ | 382 | /* retry the un-acked ones */ |
@@ -1734,7 +1750,7 @@ exit: | |||
1734 | /*****************/ | 1750 | /*****************/ |
1735 | 1751 | ||
1736 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 1752 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
1737 | struct ath_xmit_status *tx_status) | 1753 | int tx_flags) |
1738 | { | 1754 | { |
1739 | struct ieee80211_hw *hw = sc->hw; | 1755 | struct ieee80211_hw *hw = sc->hw; |
1740 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1756 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
@@ -1755,18 +1771,14 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1755 | tx_info->rate_driver_data[0] = NULL; | 1771 | tx_info->rate_driver_data[0] = NULL; |
1756 | } | 1772 | } |
1757 | 1773 | ||
1758 | if (tx_status->flags & ATH_TX_BAR) { | 1774 | if (tx_flags & ATH_TX_BAR) |
1759 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1775 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
1760 | tx_status->flags &= ~ATH_TX_BAR; | ||
1761 | } | ||
1762 | 1776 | ||
1763 | if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { | 1777 | if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { |
1764 | /* Frame was ACKed */ | 1778 | /* Frame was ACKed */ |
1765 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1779 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
1766 | } | 1780 | } |
1767 | 1781 | ||
1768 | tx_info->status.rates[0].count = tx_status->retries + 1; | ||
1769 | |||
1770 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1782 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1771 | padsize = hdrlen & 3; | 1783 | padsize = hdrlen & 3; |
1772 | if (padsize && hdrlen >= 24) { | 1784 | if (padsize && hdrlen >= 24) { |
@@ -1789,29 +1801,22 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1789 | int txok, int sendbar) | 1801 | int txok, int sendbar) |
1790 | { | 1802 | { |
1791 | struct sk_buff *skb = bf->bf_mpdu; | 1803 | struct sk_buff *skb = bf->bf_mpdu; |
1792 | struct ath_xmit_status tx_status; | ||
1793 | unsigned long flags; | 1804 | unsigned long flags; |
1805 | int tx_flags = 0; | ||
1794 | 1806 | ||
1795 | /* | ||
1796 | * Set retry information. | ||
1797 | * NB: Don't use the information in the descriptor, because the frame | ||
1798 | * could be software retried. | ||
1799 | */ | ||
1800 | tx_status.retries = bf->bf_retries; | ||
1801 | tx_status.flags = 0; | ||
1802 | 1807 | ||
1803 | if (sendbar) | 1808 | if (sendbar) |
1804 | tx_status.flags = ATH_TX_BAR; | 1809 | tx_flags = ATH_TX_BAR; |
1805 | 1810 | ||
1806 | if (!txok) { | 1811 | if (!txok) { |
1807 | tx_status.flags |= ATH_TX_ERROR; | 1812 | tx_flags |= ATH_TX_ERROR; |
1808 | 1813 | ||
1809 | if (bf_isxretried(bf)) | 1814 | if (bf_isxretried(bf)) |
1810 | tx_status.flags |= ATH_TX_XRETRY; | 1815 | tx_flags |= ATH_TX_XRETRY; |
1811 | } | 1816 | } |
1812 | 1817 | ||
1813 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1818 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1814 | ath_tx_complete(sc, skb, &tx_status); | 1819 | ath_tx_complete(sc, skb, tx_flags); |
1815 | 1820 | ||
1816 | /* | 1821 | /* |
1817 | * Return the list of ath_buf of this mpdu to free queue | 1822 | * Return the list of ath_buf of this mpdu to free queue |
@@ -1852,27 +1857,40 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, | |||
1852 | return nbad; | 1857 | return nbad; |
1853 | } | 1858 | } |
1854 | 1859 | ||
1855 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad) | 1860 | static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, |
1861 | int nbad, int txok, bool update_rc) | ||
1856 | { | 1862 | { |
1857 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; | 1863 | struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; |
1858 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1864 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1859 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1865 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1860 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 1866 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); |
1867 | struct ieee80211_hw *hw = tx_info_priv->aphy->hw; | ||
1868 | u8 i, tx_rateindex; | ||
1869 | |||
1870 | if (txok) | ||
1871 | tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; | ||
1861 | 1872 | ||
1862 | tx_info_priv->update_rc = false; | 1873 | tx_rateindex = ds->ds_txstat.ts_rateindex; |
1874 | WARN_ON(tx_rateindex >= hw->max_rates); | ||
1875 | |||
1876 | tx_info_priv->update_rc = update_rc; | ||
1863 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | 1877 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) |
1864 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1878 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1865 | 1879 | ||
1866 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | 1880 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && |
1867 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { | 1881 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
1868 | if (ieee80211_is_data(hdr->frame_control)) { | 1882 | if (ieee80211_is_data(hdr->frame_control)) { |
1869 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, | 1883 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, |
1870 | sizeof(tx_info_priv->tx)); | 1884 | sizeof(tx_info_priv->tx)); |
1871 | tx_info_priv->n_frames = bf->bf_nframes; | 1885 | tx_info_priv->n_frames = bf->bf_nframes; |
1872 | tx_info_priv->n_bad_frames = nbad; | 1886 | tx_info_priv->n_bad_frames = nbad; |
1873 | tx_info_priv->update_rc = true; | ||
1874 | } | 1887 | } |
1875 | } | 1888 | } |
1889 | |||
1890 | for (i = tx_rateindex + 1; i < hw->max_rates; i++) | ||
1891 | tx_info->status.rates[i].count = 0; | ||
1892 | |||
1893 | tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; | ||
1876 | } | 1894 | } |
1877 | 1895 | ||
1878 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) | 1896 | static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) |
@@ -1897,7 +1915,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1897 | struct ath_buf *bf, *lastbf, *bf_held = NULL; | 1915 | struct ath_buf *bf, *lastbf, *bf_held = NULL; |
1898 | struct list_head bf_head; | 1916 | struct list_head bf_head; |
1899 | struct ath_desc *ds; | 1917 | struct ath_desc *ds; |
1900 | int txok, nbad = 0; | 1918 | int txok; |
1901 | int status; | 1919 | int status; |
1902 | 1920 | ||
1903 | DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", | 1921 | DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", |
@@ -1991,13 +2009,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1991 | bf->bf_retries = ds->ds_txstat.ts_longretry; | 2009 | bf->bf_retries = ds->ds_txstat.ts_longretry; |
1992 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) | 2010 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) |
1993 | bf->bf_state.bf_type |= BUF_XRETRY; | 2011 | bf->bf_state.bf_type |= BUF_XRETRY; |
1994 | nbad = 0; | 2012 | ath_tx_rc_status(bf, ds, 0, txok, true); |
1995 | } else { | ||
1996 | nbad = ath_tx_num_badfrms(sc, bf, txok); | ||
1997 | } | 2013 | } |
1998 | 2014 | ||
1999 | ath_tx_rc_status(bf, ds, nbad); | ||
2000 | |||
2001 | if (bf_isampdu(bf)) | 2015 | if (bf_isampdu(bf)) |
2002 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); | 2016 | ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); |
2003 | else | 2017 | else |