diff options
Diffstat (limited to 'drivers/net/wireless/ath')
30 files changed, 357 insertions, 253 deletions
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index b96bb985b56d..0cba2e315d9a 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h @@ -1041,7 +1041,6 @@ struct ath5k_hw { #define ah_modes ah_capabilities.cap_mode #define ah_ee_version ah_capabilities.cap_eeprom.ee_version - u32 ah_atim_window; u32 ah_limit_tx_retries; u8 ah_coverage_class; @@ -1196,6 +1195,7 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); void ath5k_hw_reset_tsf(struct ath5k_hw *ah); void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); +bool ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval); /* ACK bit rate */ void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); /* Clock rate related functions */ diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index 6e02de311cdd..cd0b14a0a93a 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c @@ -118,7 +118,6 @@ int ath5k_hw_attach(struct ath5k_softc *sc) ah->ah_turbo = false; ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; ah->ah_imr = 0; - ah->ah_atim_window = 0; ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; ah->ah_software_retry = false; ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT; diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 95072db0ec21..94cc3354f3a6 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -1191,6 +1191,15 @@ ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, */ if (hw_tu >= sc->nexttbtt) ath5k_beacon_update_timers(sc, bc_tstamp); + + /* Check if the beacon timers are still correct, because a TSF + * update might have created a window between them - for a + * longer description see the comment of this function: */ + if (!ath5k_hw_check_beacon_timers(sc->ah, sc->bintval)) { + ath5k_beacon_update_timers(sc, bc_tstamp); + ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, + "fixed beacon timers after beacon receive\n"); + } } } @@ -1877,8 +1886,11 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) hw_tsf = ath5k_hw_get_tsf64(ah); hw_tu = TSF_TO_TU(hw_tsf); -#define FUDGE 3 - /* we use FUDGE to make sure the next TBTT is ahead of the current TU */ +#define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3 + /* We use FUDGE to make sure the next TBTT is ahead of the current TU. + * Since we later substract AR5K_TUNE_SW_BEACON_RESP (10) in the timer + * configuration we need to make sure it is bigger than that. */ + if (bc_tsf == -1) { /* * no beacons received, called internally. diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c index 6583a82a0783..0f06e8490314 100644 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ b/drivers/net/wireless/ath/ath5k/debug.c @@ -483,6 +483,59 @@ static const struct file_operations fops_antenna = { .owner = THIS_MODULE, }; +/* debugfs: misc */ + +static ssize_t read_file_misc(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath5k_softc *sc = file->private_data; + char buf[700]; + unsigned int len = 0; + u32 filt = ath5k_hw_get_rx_filter(sc->ah); + + len += snprintf(buf+len, sizeof(buf)-len, "bssid-mask: %pM\n", + sc->bssidmask); + len += snprintf(buf+len, sizeof(buf)-len, "filter-flags: 0x%x ", + filt); + if (filt & AR5K_RX_FILTER_UCAST) + len += snprintf(buf+len, sizeof(buf)-len, " UCAST"); + if (filt & AR5K_RX_FILTER_MCAST) + len += snprintf(buf+len, sizeof(buf)-len, " MCAST"); + if (filt & AR5K_RX_FILTER_BCAST) + len += snprintf(buf+len, sizeof(buf)-len, " BCAST"); + if (filt & AR5K_RX_FILTER_CONTROL) + len += snprintf(buf+len, sizeof(buf)-len, " CONTROL"); + if (filt & AR5K_RX_FILTER_BEACON) + len += snprintf(buf+len, sizeof(buf)-len, " BEACON"); + if (filt & AR5K_RX_FILTER_PROM) + len += snprintf(buf+len, sizeof(buf)-len, " PROM"); + if (filt & AR5K_RX_FILTER_XRPOLL) + len += snprintf(buf+len, sizeof(buf)-len, " XRPOLL"); + if (filt & AR5K_RX_FILTER_PROBEREQ) + len += snprintf(buf+len, sizeof(buf)-len, " PROBEREQ"); + if (filt & AR5K_RX_FILTER_PHYERR_5212) + len += snprintf(buf+len, sizeof(buf)-len, " PHYERR-5212"); + if (filt & AR5K_RX_FILTER_RADARERR_5212) + len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5212"); + if (filt & AR5K_RX_FILTER_PHYERR_5211) + snprintf(buf+len, sizeof(buf)-len, " PHYERR-5211"); + if (filt & AR5K_RX_FILTER_RADARERR_5211) + len += snprintf(buf+len, sizeof(buf)-len, " RADARERR-5211\n"); + else + len += snprintf(buf+len, sizeof(buf)-len, "\n"); + + if (len > sizeof(buf)) + len = sizeof(buf); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static const struct file_operations fops_misc = { + .read = read_file_misc, + .open = ath5k_debugfs_open, + .owner = THIS_MODULE, +}; + /* debugfs: frameerrors */ @@ -856,6 +909,10 @@ ath5k_debug_init_device(struct ath5k_softc *sc) S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, &fops_antenna); + sc->debug.debugfs_misc = debugfs_create_file("misc", + S_IRUSR, + sc->debug.debugfs_phydir, sc, &fops_misc); + sc->debug.debugfs_frameerrors = debugfs_create_file("frameerrors", S_IWUSR | S_IRUSR, sc->debug.debugfs_phydir, sc, @@ -886,6 +943,7 @@ ath5k_debug_finish_device(struct ath5k_softc *sc) debugfs_remove(sc->debug.debugfs_beacon); debugfs_remove(sc->debug.debugfs_reset); debugfs_remove(sc->debug.debugfs_antenna); + debugfs_remove(sc->debug.debugfs_misc); debugfs_remove(sc->debug.debugfs_frameerrors); debugfs_remove(sc->debug.debugfs_ani); debugfs_remove(sc->debug.debugfs_queue); diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h index 9b22722a95f0..4f078b134015 100644 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ b/drivers/net/wireless/ath/ath5k/debug.h @@ -75,6 +75,7 @@ struct ath5k_dbg_info { struct dentry *debugfs_beacon; struct dentry *debugfs_reset; struct dentry *debugfs_antenna; + struct dentry *debugfs_misc; struct dentry *debugfs_frameerrors; struct dentry *debugfs_ani; struct dentry *debugfs_queue; diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 58bb6c5dda7b..923c9ca5c4f0 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c @@ -244,7 +244,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) /* Force channel idle high */ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_CHANEL_IDLE_HIGH); + AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); /* Wait a while and disable mechanism */ udelay(200); @@ -261,7 +261,7 @@ int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) } while (--i && pending); AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_CHANEL_IDLE_HIGH); + AR5K_DIAG_SW_CHANNEL_IDLE_HIGH); } /* Clear register */ diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 6a891c4484a0..095d30b50ec7 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c @@ -495,6 +495,10 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) { u32 tsf_lower, tsf_upper1, tsf_upper2; int i; + unsigned long flags; + + /* This code is time critical - we don't want to be interrupted here */ + local_irq_save(flags); /* * While reading TSF upper and then lower part, the clock is still @@ -517,6 +521,8 @@ u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) tsf_upper1 = tsf_upper2; } + local_irq_restore(flags); + WARN_ON( i == ATH5K_MAX_TSF_READ ); return (((u64)tsf_upper1 << 32) | tsf_lower); @@ -600,7 +606,7 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) /* Timer3 marks the end of our ATIM window * a zero length window is not allowed because * we 'll get no beacons */ - timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); + timer3 = next_beacon + 1; /* * Set the beacon register and enable all timers. @@ -641,6 +647,97 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) } /** + * ath5k_check_timer_win - Check if timer B is timer A + window + * + * @a: timer a (before b) + * @b: timer b (after a) + * @window: difference between a and b + * @intval: timers are increased by this interval + * + * This helper function checks if timer B is timer A + window and covers + * cases where timer A or B might have already been updated or wrapped + * around (Timers are 16 bit). + * + * Returns true if O.K. + */ +static inline bool +ath5k_check_timer_win(int a, int b, int window, int intval) +{ + /* + * 1.) usually B should be A + window + * 2.) A already updated, B not updated yet + * 3.) A already updated and has wrapped around + * 4.) B has wrapped around + */ + if ((b - a == window) || /* 1.) */ + (a - b == intval - window) || /* 2.) */ + ((a | 0x10000) - b == intval - window) || /* 3.) */ + ((b | 0x10000) - a == window)) /* 4.) */ + return true; /* O.K. */ + return false; +} + +/** + * ath5k_hw_check_beacon_timers - Check if the beacon timers are correct + * + * @ah: The &struct ath5k_hw + * @intval: beacon interval + * + * This is a workaround for IBSS mode: + * + * The need for this function arises from the fact that we have 4 separate + * HW timer registers (TIMER0 - TIMER3), which are closely related to the + * next beacon target time (NBTT), and that the HW updates these timers + * seperately based on the current TSF value. The hardware increments each + * timer by the beacon interval, when the local TSF coverted to TU is equal + * to the value stored in the timer. + * + * The reception of a beacon with the same BSSID can update the local HW TSF + * at any time - this is something we can't avoid. If the TSF jumps to a + * time which is later than the time stored in a timer, this timer will not + * be updated until the TSF in TU wraps around at 16 bit (the size of the + * timers) and reaches the time which is stored in the timer. + * + * The problem is that these timers are closely related to TIMER0 (NBTT) and + * that they define a time "window". When the TSF jumps between two timers + * (e.g. ATIM and NBTT), the one in the past will be left behind (not + * updated), while the one in the future will be updated every beacon + * interval. This causes the window to get larger, until the TSF wraps + * around as described above and the timer which was left behind gets + * updated again. But - because the beacon interval is usually not an exact + * divisor of the size of the timers (16 bit), an unwanted "window" between + * these timers has developed! + * + * This is especially important with the ATIM window, because during + * the ATIM window only ATIM frames and no data frames are allowed to be + * sent, which creates transmission pauses after each beacon. This symptom + * has been described as "ramping ping" because ping times increase linearly + * for some time and then drop down again. A wrong window on the DMA beacon + * timer has the same effect, so we check for these two conditions. + * + * Returns true if O.K. + */ +bool +ath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) +{ + unsigned int nbtt, atim, dma; + + nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0); + atim = ath5k_hw_reg_read(ah, AR5K_TIMER3); + dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3; + + /* NOTE: SWBA is different. Having a wrong window there does not + * stop us from sending data and this condition is catched thru + * other means (SWBA interrupt) */ + + if (ath5k_check_timer_win(nbtt, atim, 1, intval) && + ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP, + intval)) + return true; /* O.K. */ + return false; +} + +/** * ath5k_hw_set_coverage_class - Set IEEE 802.11 coverage class * * @ah: The &struct ath5k_hw diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 4932bf2f35eb..61da913e7c8f 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1257,7 +1257,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, * Disable beacons and RX/TX queues, wait */ AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); + AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); @@ -1336,7 +1336,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, * Re-enable RX/TX and beacons */ AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); + AR5K_DIAG_SW_DIS_TX_5210 | AR5K_DIAG_SW_DIS_RX_5210); ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); return 0; diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 67d63081705a..a34929f06533 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -1387,10 +1387,9 @@ /* - * PCU control register + * PCU Diagnostic register * - * Only DIS_RX is used in the code, the rest i guess are - * for tweaking/diagnostics. + * Used for tweaking/diagnostics. */ #define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ #define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ @@ -1399,22 +1398,22 @@ #define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ #define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ #define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ -#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ -#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ -#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ -#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ +#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable HW encryption */ +#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable HW decryption */ +#define AR5K_DIAG_SW_DIS_TX_5210 0x00000020 /* Disable transmit [5210] */ +#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable receive */ #define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 #define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) -#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */ +#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* TX Data Loopback (i guess it goes with DIS_TX) [5210] */ #define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 #define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) -#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */ +#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Generate invalid TX FCS */ #define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 #define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) -#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */ +#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Add 56 bytes of channel info before the frame data in the RX buffer */ #define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 #define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) @@ -1426,17 +1425,17 @@ #define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ #define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ #define AR5K_DIAG_SW_SCRAM_SEED_S 10 -#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ +#define AR5K_DIAG_SW_DIS_SEQ_INC_5210 0x00040000 /* Disable seqnum increment (?)[5210] */ #define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 #define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ #define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) #define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ #define AR5K_DIAG_SW_OBSPT_S 18 -#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ -#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ -#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ -#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ +#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x00100000 /* Ignore carrier sense */ +#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x00200000 /* Ignore virtual carrier sense */ +#define AR5K_DIAG_SW_CHANNEL_IDLE_HIGH 0x00400000 /* Force channel idle high */ +#define AR5K_DIAG_SW_PHEAR_ME 0x00800000 /* ??? */ /* * TSF (clock) register (lower 32 bits) diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index 3d2c8679bc85..525671f52b45 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c @@ -118,7 +118,7 @@ static void ar5008_hw_force_bias(struct ath_hw *ah, u16 synth_freq) if (!AR_SREV_5416(ah) || synth_freq >= 3000) return; - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); if (synth_freq < 2412) new_bias = 0; @@ -454,7 +454,7 @@ static int ar5008_hw_rf_alloc_ext_banks(struct ath_hw *ah) struct ath_common *common = ath9k_hw_common(ah); - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); ATH_ALLOC_BANK(ah->analogBank0Data, ah->iniBank0.ia_rows); ATH_ALLOC_BANK(ah->analogBank1Data, ah->iniBank1.ia_rows); @@ -484,7 +484,7 @@ static void ar5008_hw_rf_free_ext_banks(struct ath_hw *ah) bank = NULL; \ } while (0); - BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); + BUG_ON(AR_SREV_9280_20_OR_LATER(ah)); ATH_FREE_BANK(ah->analogBank0Data); ATH_FREE_BANK(ah->analogBank1Data); @@ -525,7 +525,7 @@ static bool ar5008_hw_set_rf_regs(struct ath_hw *ah, * for single chip devices, that is AR9280 or anything * after that. */ - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) return true; /* Setup rf parameters */ @@ -663,20 +663,20 @@ static void ar5008_hw_override_ini(struct ath_hw *ah, */ REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { val = REG_READ(ah, AR_PCU_MISC_MODE2); if (!AR_SREV_9271(ah)) val &= ~AR_PCU_MISC_MODE2_HWWAR1; - if (AR_SREV_9287_10_OR_LATER(ah)) + if (AR_SREV_9287_11_OR_LATER(ah)) val = val & (~AR_PCU_MISC_MODE2_HWWAR2); REG_WRITE(ah, AR_PCU_MISC_MODE2, val); } if (!AR_SREV_5416_20_OR_LATER(ah) || - AR_SREV_9280_10_OR_LATER(ah)) + AR_SREV_9280_20_OR_LATER(ah)) return; /* * Disable BB clock gating @@ -701,7 +701,7 @@ static void ar5008_hw_set_channel_regs(struct ath_hw *ah, u32 phymode; u32 enableDacFifo = 0; - if (AR_SREV_9285_10_OR_LATER(ah)) + if (AR_SREV_9285_12_OR_LATER(ah)) enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & AR_PHY_FC_ENABLE_DAC_FIFO); @@ -820,11 +820,11 @@ static int ar5008_hw_process_ini(struct ath_hw *ah, REGWRITE_BUFFER_FLUSH(ah); DISABLE_REGWRITE_BUFFER(ah); - if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) + if (AR_SREV_9280(ah) || AR_SREV_9287_11_OR_LATER(ah)) REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || - AR_SREV_9287_10_OR_LATER(ah)) + AR_SREV_9287_11_OR_LATER(ah)) REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); if (AR_SREV_9271_10(ah)) @@ -900,7 +900,7 @@ static void ar5008_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - if (!AR_SREV_9280_10_OR_LATER(ah)) + if (!AR_SREV_9280_20_OR_LATER(ah)) rfMode |= (IS_CHAN_5GHZ(chan)) ? AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index fe7418aefc4a..d7d1d55362e6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c @@ -567,11 +567,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) AR5416_EEP_TXGAIN_HIGH_POWER) return; - if (AR_SREV_9285_11(ah)) { - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); - udelay(10); - } - for (i = 0; i < ARRAY_SIZE(regList); i++) regList[i][1] = REG_READ(ah, regList[i][0]); @@ -651,10 +646,6 @@ static inline void ar9285_hw_pa_cal(struct ath_hw *ah, bool is_reset) REG_WRITE(ah, regList[i][0], regList[i][1]); REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - } static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) @@ -664,7 +655,7 @@ static void ar9002_hw_pa_cal(struct ath_hw *ah, bool is_reset) ar9271_hw_pa_cal(ah, is_reset); else ah->pacal_info.skipcount--; - } else if (AR_SREV_9285_11_OR_LATER(ah)) { + } else if (AR_SREV_9285_12_OR_LATER(ah)) { if (is_reset || !ah->pacal_info.skipcount) ar9285_hw_pa_cal(ah, is_reset); else @@ -841,8 +832,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) if (!ar9285_hw_clc(ah, chan)) return false; } else { - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!AR_SREV_9287_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) { + if (!AR_SREV_9287_11_OR_LATER(ah)) REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, @@ -864,8 +855,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) return false; } - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!AR_SREV_9287_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) { + if (!AR_SREV_9287_11_OR_LATER(ah)) REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, @@ -976,7 +967,7 @@ static void ar9002_hw_init_cal_settings(struct ath_hw *ah) } if (AR_SREV_9160_10_OR_LATER(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { ah->iq_caldata.calData = &iq_cal_single_sample; ah->adcgain_caldata.calData = &adc_gain_cal_single_sample; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c index 94392daebaa0..fde45082a13b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c @@ -569,7 +569,7 @@ void ar9002_hw_attach_ops(struct ath_hw *ah) ops->config_pci_powersave = ar9002_hw_configpcipowersave; ar5008_hw_attach_phy_ops(ah); - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) ar9002_hw_attach_phy_ops(ah); ar9002_hw_attach_calib_ops(ah); diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 3030564a0f21..dacb45e1b906 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h @@ -101,7 +101,7 @@ #define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) #define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) -#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \ +#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_11_OR_LATER(ah) && \ ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) #define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index ead8b0dd3b53..d6eed1f02e84 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -333,7 +333,7 @@ static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, } if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) ss = (int16_t)(0 - (minPwrT4[i] / 2)); else ss = 0; @@ -761,7 +761,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, regulatory->max_power_level = ratesArray[i]; - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; } @@ -909,9 +909,6 @@ static void ath9k_hw_4k_set_gain(struct ath_hw *ah, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); } /* @@ -1109,9 +1106,6 @@ static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, } - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, pModal->switchSettling); REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index e6186515d05b..966b9496a9dd 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -324,7 +324,7 @@ static void ath9k_hw_get_ar9287_gain_boundaries_pdadcs(struct ath_hw *ah, minDelta = 0; if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) ss = (int16_t)(0 - (minPwrT4[i] / 2)); else ss = 0; @@ -883,7 +883,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, ratesArray[i] = AR9287_MAX_RATE_POWER; } - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; } @@ -977,7 +977,7 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah, else i = rate6mb; - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) regulatory->max_power_level = ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; else diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 23f480d4c770..76b4d65472dd 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -223,7 +223,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) } /* Enable fixup for AR_AN_TOP2 if necessary */ - if (AR_SREV_9280_10_OR_LATER(ah) && + if (AR_SREV_9280_20_OR_LATER(ah) && (eep->baseEepHeader.version & 0xff) > 0x0a && eep->baseEepHeader.pwdclkind == 0) ah->need_an_top2_fixup = 1; @@ -317,7 +317,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { txRxAttenLocal = pModal->txRxAttenCh[i]; - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[i]); @@ -344,7 +344,7 @@ static void ath9k_hw_def_set_gain(struct ath_hw *ah, } } - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); @@ -408,7 +408,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, regChainOffset, i); } - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { if (IS_CHAN_2GHZ(chan)) { ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, AR_AN_RF2G1_CH0_OB, @@ -461,7 +461,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); - if (!AR_SREV_9280_10_OR_LATER(ah)) + if (!AR_SREV_9280_20_OR_LATER(ah)) REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_PGA, pModal->pgaDesiredSize); @@ -478,7 +478,7 @@ static void ath9k_hw_def_set_board_values(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, pModal->thresh62); REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, @@ -696,7 +696,7 @@ static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, } if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) ss = (int16_t)(0 - (minPwrT4[i] / 2)); else ss = 0; @@ -1291,7 +1291,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, ratesArray[i] = AR5416_MAX_RATE_POWER; } - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { for (i = 0; i < Ar5416RateSize; i++) { int8_t pwr_table_offset; @@ -1395,7 +1395,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, else if (IS_CHAN_HT20(chan)) i = rateHt20_0; - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) regulatory->max_power_level = ratesArray[i] + AR5416_PWR_TABLE_OFFSET_DB * 2; else diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c index bd1506e69105..1b72aa482ac7 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c @@ -235,7 +235,14 @@ void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv) ath9k_hw_get_txq_props(ah, qnum, &qi_be); qi.tqi_aifs = qi_be.tqi_aifs; - qi.tqi_cwmin = 4*qi_be.tqi_cwmin; + /* For WIFI Beacon Distribution + * Long slot time : 2x cwmin + * Short slot time : 4x cwmin + */ + if (ah->slottime == ATH9K_SLOT_TIME_20) + qi.tqi_cwmin = 2*qi_be.tqi_cwmin; + else + qi.tqi_cwmin = 4*qi_be.tqi_cwmin; qi.tqi_cwmax = qi_be.tqi_cwmax; if (!ath9k_hw_set_txq_props(ah, priv->beaconq, &qi)) { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 33850c952314..b100db2766cf 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -561,6 +561,9 @@ static void ath9k_init_crypto(struct ath9k_htc_priv *priv) common->keymax = ATH_KEYMAX; } + if (priv->ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) + common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; + /* * Reset the key cache since some parts do not * reset the contents on initial power up. diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 0b2ff98b6f33..25ed65ac992c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -565,7 +565,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) ath9k_hw_init_cal_settings(ah); ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah) && !AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; if (!AR_SREV_9300_20_OR_LATER(ah)) ah->ani_function &= ~ATH9K_ANI_MRC_CCK; @@ -1190,7 +1190,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) int count = 50; u32 reg; - if (AR_SREV_9285_10_OR_LATER(ah)) + if (AR_SREV_9285_12_OR_LATER(ah)) return true; do { @@ -1312,7 +1312,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, if (tsf) ath9k_hw_settsf64(ah, tsf); - if (AR_SREV_9280_10_OR_LATER(ah)) + if (AR_SREV_9280_20_OR_LATER(ah)) REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); if (!AR_SREV_9300_20_OR_LATER(ah)) @@ -1787,7 +1787,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) regulatory->current_rd = eeval; eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); - if (AR_SREV_9285_10_OR_LATER(ah)) + if (AR_SREV_9285_12_OR_LATER(ah)) eeval |= AR9285_RDEXT_DEFAULT; regulatory->current_rd_ext = eeval; @@ -1857,8 +1857,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) /* Use rx_chainmask from EEPROM. */ pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); - if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) - ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; + ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; pCap->low_2ghz_chan = 2312; pCap->high_2ghz_chan = 2732; @@ -1894,9 +1893,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->num_gpio_pins = AR9271_NUM_GPIO; else if (AR_DEVID_7010(ah)) pCap->num_gpio_pins = AR7010_NUM_GPIO; - else if (AR_SREV_9285_10_OR_LATER(ah)) + else if (AR_SREV_9285_12_OR_LATER(ah)) pCap->num_gpio_pins = AR9285_NUM_GPIO; - else if (AR_SREV_9280_10_OR_LATER(ah)) + else if (AR_SREV_9280_20_OR_LATER(ah)) pCap->num_gpio_pins = AR928X_NUM_GPIO; else pCap->num_gpio_pins = AR_NUM_GPIO; @@ -1953,7 +1952,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) pCap->num_antcfg_2ghz = ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); - if (AR_SREV_9280_10_OR_LATER(ah) && + if (AR_SREV_9280_20_OR_LATER(ah) && ath9k_hw_btcoex_supported(ah)) { btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO; btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO; @@ -1990,7 +1989,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) if (AR_SREV_9300_20_OR_LATER(ah)) pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED; - if (AR_SREV_9287_10_OR_LATER(ah) || AR_SREV_9271(ah)) + if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah)) pCap->hw_caps |= ATH9K_HW_CAP_SGI_20; if (AR_SREV_9285(ah)) @@ -2074,11 +2073,11 @@ u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) return MS_REG_READ(AR9300, gpio) != 0; else if (AR_SREV_9271(ah)) return MS_REG_READ(AR9271, gpio) != 0; - else if (AR_SREV_9287_10_OR_LATER(ah)) + else if (AR_SREV_9287_11_OR_LATER(ah)) return MS_REG_READ(AR9287, gpio) != 0; - else if (AR_SREV_9285_10_OR_LATER(ah)) + else if (AR_SREV_9285_12_OR_LATER(ah)) return MS_REG_READ(AR9285, gpio) != 0; - else if (AR_SREV_9280_10_OR_LATER(ah)) + else if (AR_SREV_9280_20_OR_LATER(ah)) return MS_REG_READ(AR928X, gpio) != 0; else return MS_REG_READ(AR, gpio) != 0; @@ -2575,7 +2574,7 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len) int used; /* chipsets >= AR9280 are single-chip */ - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { used = snprintf(hw_name, len, "Atheros AR%s Rev:%x", ath9k_hw_mac_bb_name(ah->hw_version.macVersion), diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 573899e27b3d..de3393867e37 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -211,7 +211,7 @@ static void setup_ht_cap(struct ath_softc *sc, else max_streams = 2; - if (AR_SREV_9280_10_OR_LATER(ah)) { + if (AR_SREV_9280_20_OR_LATER(ah)) { if (max_streams >= 2) ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; ht_info->cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8b327bcad695..a13387882636 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -270,6 +270,7 @@ static void ath_paprd_activate(struct ath_softc *sc) { struct ath_hw *ah = sc->sc_ah; struct ath9k_hw_cal_data *caldata = ah->caldata; + struct ath_common *common = ath9k_hw_common(ah); int chain; if (!caldata || !caldata->paprd_done) @@ -278,7 +279,7 @@ static void ath_paprd_activate(struct ath_softc *sc) ath9k_ps_wakeup(sc); ar9003_paprd_enable(ah, false); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(ah->caps.tx_chainmask & BIT(chain))) + if (!(common->tx_chainmask & BIT(chain))) continue; ar9003_paprd_populate_single_table(ah, caldata, chain); @@ -300,6 +301,7 @@ void ath_paprd_calibrate(struct work_struct *work) struct ieee80211_supported_band *sband = &sc->sbands[band]; struct ath_tx_control txctl; struct ath9k_hw_cal_data *caldata = ah->caldata; + struct ath_common *common = ath9k_hw_common(ah); int qnum, ftype; int chain_ok = 0; int chain; @@ -333,7 +335,7 @@ void ath_paprd_calibrate(struct work_struct *work) ath9k_ps_wakeup(sc); ar9003_paprd_init_table(ah); for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(ah->caps.tx_chainmask & BIT(chain))) + if (!(common->tx_chainmask & BIT(chain))) continue; chain_ok = 0; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c5e7af4f51ab..9c166f3804ab 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -454,8 +454,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) else rfilt |= ATH9K_RX_FILTER_BEACON; - if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) || - AR_SREV_9285_10_OR_LATER(sc->sc_ah)) && + if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) || + AR_SREV_9285_12_OR_LATER(sc->sc_ah)) && (sc->sc_ah->opmode == NL80211_IFTYPE_AP) && (sc->rx.rxfilter & FIF_PSPOLL)) rfilt |= ATH9K_RX_FILTER_PSPOLL; @@ -977,7 +977,11 @@ static void ath9k_process_rssi(struct ath_common *common, * at least one sdata of a wiphy on mac80211 but with ath9k virtual * wiphy you'd have to iterate over every wiphy and each sdata. */ - sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); + if (is_multicast_ether_addr(hdr->addr1)) + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL); + else + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1); + if (sta) { an = (struct ath_node *) sta->drv_priv; if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index d01c4adab8d6..6d01e501b9b4 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -819,49 +819,23 @@ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) #define AR_SREV_9280(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) -#define AR_SREV_9280_10_OR_LATER(_ah) \ +#define AR_SREV_9280_20_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280)) #define AR_SREV_9280_20(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)) -#define AR_SREV_9280_20_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))) + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) #define AR_SREV_9285(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) -#define AR_SREV_9285_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) -#define AR_SREV_9285_11(_ah) \ - (AR_SREV_9285(ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) -#define AR_SREV_9285_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ - (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ - AR_SREV_REVISION_9285_11))) -#define AR_SREV_9285_12(_ah) \ - (AR_SREV_9285(ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) #define AR_SREV_9285_12_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ - (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ - AR_SREV_REVISION_9285_12))) + (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) #define AR_SREV_9287(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) -#define AR_SREV_9287_10_OR_LATER(_ah) \ +#define AR_SREV_9287_11_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287)) -#define AR_SREV_9287_10(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10)) #define AR_SREV_9287_11(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11)) -#define AR_SREV_9287_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) #define AR_SREV_9287_12(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12)) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 85a7323a04ef..f7da6b20a925 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -328,8 +328,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, rcu_read_lock(); - /* XXX: use ieee80211_find_sta! */ - sta = ieee80211_find_sta_by_hw(hw, hdr->addr1); + sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); if (!sta) { rcu_read_unlock(); diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig index c5d3a3f2e55b..2d1b821b440d 100644 --- a/drivers/net/wireless/ath/carl9170/Kconfig +++ b/drivers/net/wireless/ath/carl9170/Kconfig @@ -10,7 +10,7 @@ config CARL9170 but it needs a special firmware (carl9170-1.fw) to do that. The firmware can be downloaded from our wiki here: - http://wireless.kernel.org/en/users/Drivers/carl9170 + <http://wireless.kernel.org/en/users/Drivers/carl9170> If you choose to build a module, it'll be called carl9170. diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index d7c5482d74ce..20f2a77e54d2 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -364,7 +364,6 @@ struct ar9170 { unsigned int tx_dropped; unsigned int tx_ack_failures; unsigned int tx_fcs_errors; - unsigned int tx_ampdu_timeout; unsigned int rx_dropped; /* EEPROM */ diff --git a/drivers/net/wireless/ath/carl9170/debug.c b/drivers/net/wireless/ath/carl9170/debug.c index 19b48369ffed..0ac1124c2a0b 100644 --- a/drivers/net/wireless/ath/carl9170/debug.c +++ b/drivers/net/wireless/ath/carl9170/debug.c @@ -798,8 +798,6 @@ DEBUGFS_READONLY_FILE(tx_total_queued, 20, "%d", atomic_read(&ar->tx_total_queued)); DEBUGFS_READONLY_FILE(tx_ampdu_scheduler, 20, "%d", atomic_read(&ar->tx_ampdu_scheduler)); -DEBUGFS_READONLY_FILE(tx_ampdu_timeout, 20, "%d", - ar->tx_ampdu_timeout); DEBUGFS_READONLY_FILE(tx_total_pending, 20, "%d", atomic_read(&ar->tx_total_pending)); @@ -872,8 +870,6 @@ void carl9170_debugfs_register(struct ar9170 *ar) DEBUGFS_ADD(ampdu_density); DEBUGFS_ADD(ampdu_factor); - DEBUGFS_ADD(tx_ampdu_timeout); - DEBUGFS_ADD(tx_janitor_last_run); DEBUGFS_ADD(tx_status_0); diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 43de9dfa5820..84bd38e9961c 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -230,8 +230,15 @@ static void carl9170_flush(struct ar9170 *ar, bool drop_queued) for (i = 0; i < ar->hw->queues; i++) { struct sk_buff *skb; - while ((skb = skb_dequeue(&ar->tx_pending[i]))) + while ((skb = skb_dequeue(&ar->tx_pending[i]))) { + struct ieee80211_tx_info *info; + + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + atomic_dec(&ar->tx_ampdu_upload); + carl9170_tx_status(ar, skb, false); + } } } @@ -1241,7 +1248,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_TX_START: - if (WARN_ON_ONCE(!sta_info->ht_sta)) + if (!sta_info->ht_sta) return -EOPNOTSUPP; rcu_read_lock(); @@ -1453,9 +1460,6 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw, while ((skb = __skb_dequeue(&tid_info->queue))) __skb_queue_tail(&free, skb); spin_unlock_bh(&tid_info->lock); - - ieee80211_stop_tx_ba_session(sta, - tid_info->tid); } rcu_read_unlock(); } @@ -1465,6 +1469,7 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw, skb_queue_walk_safe(&ar->tx_pending[i], skb, tmp) { struct _carl9170_tx_superframe *super; struct ieee80211_hdr *hdr; + struct ieee80211_tx_info *info; super = (void *) skb->data; hdr = (void *) super->frame_data; @@ -1473,6 +1478,11 @@ static void carl9170_op_sta_notify(struct ieee80211_hw *hw, continue; __skb_unlink(skb, &ar->tx_pending[i]); + + info = IEEE80211_SKB_CB(skb); + if (info->flags & IEEE80211_TX_CTL_AMPDU) + atomic_dec(&ar->tx_ampdu_upload); + carl9170_tx_status(ar, skb, false); } spin_unlock_bh(&ar->tx_pending[i].lock); diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index e0d2374e0c77..b575c865142d 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -760,8 +760,8 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) struct carl9170_tx_info *arinfo; unsigned int hw_queue; int i; - u16 keytype = 0; - u16 len, icv = 0; + __le16 mac_tmp; + u16 len; bool ampdu, no_ack; BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); @@ -773,6 +773,10 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) BUILD_BUG_ON(IEEE80211_TX_MAX_RATES < CARL9170_TX_MAX_RATES); + BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > + ((CARL9170_TX_SUPER_MISC_VIF_ID >> + CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); + hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)]; hdr = (void *)skb->data; @@ -793,20 +797,37 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) txc = (void *)skb_push(skb, sizeof(*txc)); memset(txc, 0, sizeof(*txc)); - ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); + SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue); + + if (likely(cvif)) + SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, cvif->id); + + if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM)) + txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; + + if (unlikely(ieee80211_is_probe_resp(hdr->frame_control))) + txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; + + mac_tmp = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | + AR9170_TX_MAC_BACKOFF); + mac_tmp |= cpu_to_le16((hw_queue << AR9170_TX_MAC_QOS_S) && + AR9170_TX_MAC_QOS); + no_ack = !!(info->flags & IEEE80211_TX_CTL_NO_ACK); + if (unlikely(no_ack)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); if (info->control.hw_key) { - icv = info->control.hw_key->icv_len; + len += info->control.hw_key->icv_len; switch (info->control.hw_key->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: case WLAN_CIPHER_SUITE_TKIP: - keytype = AR9170_TX_MAC_ENCR_RC4; + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_RC4); break; case WLAN_CIPHER_SUITE_CCMP: - keytype = AR9170_TX_MAC_ENCR_AES; + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_ENCR_AES); break; default: WARN_ON(1); @@ -814,48 +835,58 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) } } - BUILD_BUG_ON(AR9170_MAX_VIRTUAL_MAC > - ((CARL9170_TX_SUPER_MISC_VIF_ID >> - CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1)); - - txc->s.len = cpu_to_le16(len + sizeof(*txc)); - txc->f.length = cpu_to_le16(len + icv + 4); - SET_VAL(CARL9170_TX_SUPER_MISC_VIF_ID, txc->s.misc, - cvif ? cvif->id : 0); + ampdu = !!(info->flags & IEEE80211_TX_CTL_AMPDU); + if (ampdu) { + unsigned int density, factor; - txc->f.mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | - AR9170_TX_MAC_BACKOFF); + if (unlikely(!sta || !cvif)) + goto err_out; - SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, txc->s.misc, hw_queue); + factor = min_t(unsigned int, 1u, + info->control.sta->ht_cap.ampdu_factor); - txc->f.mac_control |= cpu_to_le16(hw_queue << AR9170_TX_MAC_QOS_S); - txc->f.mac_control |= cpu_to_le16(keytype); - txc->f.phy_control = cpu_to_le32(0); + density = info->control.sta->ht_cap.ampdu_density; - if (no_ack) - txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); + if (density) { + /* + * Watch out! + * + * Otus uses slightly different density values than + * those from the 802.11n spec. + */ - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) - txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB; + density = max_t(unsigned int, density + 1, 7u); + } - txrate = &info->control.rates[0]; - if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) - txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - else if (carl9170_tx_cts_check(ar, txrate)) - txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); + SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY, + txc->s.ampdu_settings, density); - SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); - txc->f.phy_control |= carl9170_tx_physet(ar, info, txrate); + SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, + txc->s.ampdu_settings, factor); - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - for (i = 1; i < CARL9170_TX_MAX_RATES; i++) { + for (i = 0; i < CARL9170_TX_MAX_RATES; i++) { txrate = &info->control.rates[i]; - if (txrate->idx >= 0) + if (txrate->idx >= 0) { + txc->s.ri[i] = + CARL9170_TX_SUPER_RI_AMPDU; + + if (WARN_ON(!(txrate->flags & + IEEE80211_TX_RC_MCS))) { + /* + * Not sure if it's even possible + * to aggregate non-ht rates with + * this HW. + */ + goto err_out; + } continue; + } txrate->idx = 0; txrate->count = ar->hw->max_rate_tries; } + + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_AGGR); } /* @@ -878,57 +909,21 @@ static int carl9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) txc->s.ri[i] |= (AR9170_TX_MAC_PROT_CTS << CARL9170_TX_SUPER_RI_ERP_PROT_S); - /* - * unaggregated fallback, in case aggregation - * proves to be unsuccessful and unreliable. - */ - if (ampdu && i < 3) - txc->s.ri[i] |= CARL9170_TX_SUPER_RI_AMPDU; - txc->s.rr[i - 1] = carl9170_tx_physet(ar, info, txrate); } - if (ieee80211_is_probe_resp(hdr->frame_control)) - txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF; - - if (ampdu) { - unsigned int density, factor; - - if (unlikely(!sta || !cvif)) - goto err_out; - - density = info->control.sta->ht_cap.ampdu_density; - factor = info->control.sta->ht_cap.ampdu_factor; - - if (density) { - /* - * Watch out! - * - * Otus uses slightly different density values than - * those from the 802.11n spec. - */ - - density = max_t(unsigned int, density + 1, 7u); - } - - factor = min_t(unsigned int, 1u, factor); - - SET_VAL(CARL9170_TX_SUPER_AMPDU_DENSITY, - txc->s.ampdu_settings, density); + txrate = &info->control.rates[0]; + SET_VAL(CARL9170_TX_SUPER_RI_TRIES, txc->s.ri[0], txrate->count); - SET_VAL(CARL9170_TX_SUPER_AMPDU_FACTOR, - txc->s.ampdu_settings, factor); + if (carl9170_tx_rts_check(ar, txrate, ampdu, no_ack)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); + else if (carl9170_tx_cts_check(ar, txrate)) + mac_tmp |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS) { - txc->f.mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - } else { - /* - * Not sure if it's even possible to aggregate - * non-ht rates with this HW. - */ - WARN_ON_ONCE(1); - } - } + txc->s.len = cpu_to_le16(skb->len); + txc->f.length = cpu_to_le16(len + FCS_LEN); + txc->f.mac_control = mac_tmp; + txc->f.phy_control = carl9170_tx_physet(ar, info, txrate); arinfo = (void *)info->rate_driver_data; arinfo->timeout = jiffies; @@ -1042,41 +1037,8 @@ retry: queue = TID_TO_WME_AC(tid_info->tid); spin_lock_bh(&tid_info->lock); - if (tid_info->state != CARL9170_TID_STATE_XMIT) { - first = skb_peek(&tid_info->queue); - if (first) { - struct ieee80211_tx_info *txinfo; - struct carl9170_tx_info *arinfo; - - txinfo = IEEE80211_SKB_CB(first); - arinfo = (void *) txinfo->rate_driver_data; - - if (time_is_after_jiffies(arinfo->timeout + - msecs_to_jiffies(CARL9170_QUEUE_TIMEOUT)) - == true) - goto processed; - - /* - * We've been waiting for the frame which - * matches "snx" (start sequence of the - * next aggregate) for some time now. - * - * But it never arrived. Therefore - * jump to the next available frame - * and kick-start the transmission. - * - * Note: This might induce odd latency - * spikes because the receiver will be - * waiting for the lost frame too. - */ - ar->tx_ampdu_timeout++; - - tid_info->snx = carl9170_get_seq(first); - tid_info->state = CARL9170_TID_STATE_XMIT; - } else { - goto processed; - } - } + if (tid_info->state != CARL9170_TID_STATE_XMIT) + goto processed; tid_info->counter++; first = skb_peek(&tid_info->queue); diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index eb789a9e4f15..c7f6193934ea 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -606,8 +606,6 @@ int __carl9170_exec_cmd(struct ar9170 *ar, struct carl9170_cmd *cmd, AR9170_USB_EP_CMD), cmd, cmd->hdr.len + 4, carl9170_usb_cmd_complete, ar, 1); - urb->transfer_flags |= URB_ZERO_PACKET; - if (free_buf) urb->transfer_flags |= URB_FREE_BUFFER; |