ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
                ah->config.serialize_regmode);
 
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
+       else
+               ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
+
        if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
                ath_print(common, ATH_DBG_FATAL,
                          "Mac Chip Rev 0x%02x.%x is not supported by "
                pCap->keycache_size = AR_KEYTABLE_SIZE;
 
        pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
-       pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
+
+       if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
+               pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
+       else
+               pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
 
        if (AR_SREV_9285_10_OR_LATER(ah))
                pCap->num_gpio_pins = AR9285_NUM_GPIO;
 
 #define AR_SPUR_FEEQ_BOUND_HT20 10
        int spurmode;
        u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
+       u8 max_txtrig_level;
 };
 
 enum ath9k_int {
 
 }
 EXPORT_SYMBOL(ath9k_hw_numtxpending);
 
+/**
+ * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
+ *
+ * @ah: atheros hardware struct
+ * @bIncTrigLevel: whether or not the frame trigger level should be updated
+ *
+ * The frame trigger level specifies the minimum number of bytes,
+ * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
+ * before the PCU will initiate sending the frame on the air. This can
+ * mean we initiate transmit before a full frame is on the PCU TX FIFO.
+ * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
+ * first)
+ *
+ * Caution must be taken to ensure to set the frame trigger level based
+ * on the DMA request size. For example if the DMA request size is set to
+ * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
+ * there need to be enough space in the tx FIFO for the requested transfer
+ * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
+ * the threshold to a value beyond 6, then the transmit will hang.
+ *
+ * Current dual   stream devices have a PCU TX FIFO size of 8 KB.
+ * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
+ * there is a hardware issue which forces us to use 2 KB instead so the
+ * frame trigger level must not exceed 2 KB for these chipsets.
+ */
 bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
 {
        u32 txcfg, curLevel, newLevel;
        enum ath9k_int omask;
 
-       if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD)
+       if (ah->tx_trig_level >= ah->config.max_txtrig_level)
                return false;
 
        omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
        curLevel = MS(txcfg, AR_FTRIG);
        newLevel = curLevel;
        if (bIncTrigLevel) {
-               if (curLevel < MAX_TX_FIFO_THRESHOLD)
+               if (curLevel < ah->config.max_txtrig_level)
                        newLevel++;
        } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
                newLevel--;
 
 #define ATH9K_TX_SW_ABORTED        0x40
 #define ATH9K_TX_SW_FILTERED       0x80
 
+/* 64 bytes */
 #define MIN_TX_FIFO_THRESHOLD   0x1
+
+/*
+ * Single stream device AR9285 and AR9271 require 2 KB
+ * to work around a hardware issue, all other devices
+ * have can use the max 4 KB limit.
+ */
 #define MAX_TX_FIFO_THRESHOLD   ((4096 / 64) - 1)
-#define INIT_TX_FIFO_THRESHOLD  MIN_TX_FIFO_THRESHOLD
 
 struct ath_tx_status {
        u32 ts_tstamp;
 
                return;
 
        /*
-        * If underrun error is seen assume it as an excessive retry only
-        * if prefetch trigger level have reached the max (0x3f for 5416)
-        * Adjust the long retry as if the frame was tried hw->max_rate_tries
-        * times. This affects how ratectrl updates PER for the failed rate.
+        * If an underrun error is seen assume it as an excessive retry only
+        * if max frame trigger level has been reached (2 KB for singel stream,
+        * and 4 KB for dual stream). Adjust the long retry as if the frame was
+        * tried hw->max_rate_tries times to affect how ratectrl updates PER for
+        * the failed rate. In case of congestion on the bus penalizing these
+        * type of underruns should help hardware actually transmit new frames
+        * successfully by eventually preferring slower rates. This itself
+        * should also alleviate congestion on the bus.
         */
        if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) &&
            (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {