CHROMIUMOS: Move ath recv hang messages behind a flag
authorPaul Stewart <pstew@chromium.org>
Sat, 18 Feb 2012 20:53:05 +0000 (12:53 -0800)
committerOlof Johansson <olof@lixom.net>
Fri, 1 Jun 2012 07:02:15 +0000 (00:02 -0700)
Signed-off-by: Paul Stewart <pstew@chromium.org>
BUG=None
TEST=Load kernel

Change-Id: Icf8b75f710c30cbd2554693fcd52c8cbdce915bd
Reviewed-on: https://gerrit.chromium.org/gerrit/16219
Reviewed-by: Benson Leung <bleung@chromium.org>
Reviewed-by: Sam Leffler <sleffler@chromium.org>
Tested-by: Paul Stewart <pstew@chromium.org>
Commit-Ready: Paul Stewart <pstew@chromium.org>

[ Rebase-3.3: s/ATH_DBG_RX_STUCK/RX_STUCK when used by ath_dbg() macro
-ggg ]

drivers/net/wireless/ath/ath.h
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/ar9003_phy.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/main.c

index c54b7d3..fa90d05 100644 (file)
@@ -242,6 +242,7 @@ enum ATH_DEBUG {
        ATH_DBG_BSTUCK          = 0x00008000,
        ATH_DBG_MCI             = 0x00010000,
        ATH_DBG_DFS             = 0x00020000,
+       ATH_DBG_RX_STUCK        = 0x00040000,
        ATH_DBG_ANY             = 0xffffffff
 };
 
index a66a13b..c865049 100644 (file)
@@ -565,3 +565,22 @@ void ath9k_hw_setup_statusring(struct ath_hw *ah, void *ts_start,
        ath9k_hw_reset_txstatus_ring(ah);
 }
 EXPORT_SYMBOL(ath9k_hw_setup_statusring);
+
+void ar9003_hw_dump_txdesc(struct ath_hw *ah)
+{
+       struct ar9003_txs *ads;
+       struct ath_common *common = ath9k_hw_common(ah);
+       u32 status, i, len = 0;
+       u8 buf[1200];
+
+       memset(buf, 0, sizeof(buf));
+       ath_dbg(common, RX_STUCK, "ts_tail %d\n", ah->ts_tail);
+
+       for (i = 0; i < ah->ts_size; i++) {
+               ads = &ah->ts_ring[i];
+               status = ACCESS_ONCE(ads->status8);
+               len += sprintf(buf + len, "%d ", status & AR_TxDone);
+       }
+       ath_dbg(common, RX_STUCK, "ring status: %s\n", buf);
+}
+EXPORT_SYMBOL(ar9003_hw_dump_txdesc);
index 600aca9..60032b2 100644 (file)
@@ -1504,3 +1504,51 @@ void ar9003_hw_disable_phy_restart(struct ath_hw *ah)
        REG_WRITE(ah, AR_PHY_RESTART, val);
 }
 EXPORT_SYMBOL(ar9003_hw_disable_phy_restart);
+
+void ar9003_hw_dump_ani_reg(struct ath_hw *ah)
+{
+       u32 reg;
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       reg = REG_READ(ah, AR_PHY_FIND_SIG_LOW);
+       ath_dbg(common, RX_STUCK, "FIRStep Low = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW),
+                       MS(reg, AR_PHY_FIND_SIG_LOW_FIRSTEP_LOW));
+       reg = REG_READ(ah, AR_PHY_DESIRED_SZ);
+       ath_dbg(common, RX_STUCK, "Total Desired = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_DESIRED_SZ_TOT_DES),
+                       MS(reg, AR_PHY_DESIRED_SZ_TOT_DES));
+       ath_dbg(common, RX_STUCK, "ADC Desired = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_DESIRED_SZ_ADC),
+                       MS(reg, AR_PHY_DESIRED_SZ_ADC));
+       reg = REG_READ(ah, AR_PHY_FIND_SIG);
+       ath_dbg(common, RX_STUCK, "FIRStep = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_FIND_SIG_FIRSTEP),
+                       MS(reg, AR_PHY_FIND_SIG_FIRSTEP));
+       reg = REG_READ(ah, AR_PHY_AGC);
+       ath_dbg(common, RX_STUCK, "Coarse High = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_AGC_COARSE_HIGH),
+                       MS(reg, AR_PHY_AGC_COARSE_HIGH));
+       ath_dbg(common, RX_STUCK, "Coarse Low = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_AGC_COARSE_LOW),
+                       MS(reg, AR_PHY_AGC_COARSE_LOW));
+       ath_dbg(common, RX_STUCK, "Coarse Power Constant = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_AGC_COARSE_PWR_CONST),
+                       MS(reg, AR_PHY_AGC_COARSE_PWR_CONST));
+       reg = REG_READ(ah, AR_PHY_TIMING5);
+       ath_dbg(common, RX_STUCK, "Enable Cyclic Power Thresh = %d\n",
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1_ENABLE));
+       ath_dbg(common, RX_STUCK, "Cyclic Power Thresh = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1),
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1));
+       ath_dbg(common, RX_STUCK, "Cyclic Power Thresh 1A= 0x%x (%d)\n",
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1A),
+                       MS(reg, AR_PHY_TIMING5_CYCPWR_THR1A));
+       reg = REG_READ(ah, AR_PHY_DAG_CTRLCCK);
+       ath_dbg(common, RX_STUCK, "Barker RSSI Thresh Enable = %d\n",
+                       MS(reg, AR_PHY_DAG_CTRLCCK_EN_RSSI_THR));
+       ath_dbg(common, RX_STUCK, "Barker RSSI Thresh = 0x%x (%d)\n",
+                       MS(reg, AR_PHY_DAG_CTRLCCK_RSSI_THR),
+                       MS(reg, AR_PHY_DAG_CTRLCCK_RSSI_THR));
+}
+EXPORT_SYMBOL(ar9003_hw_dump_ani_reg);
index fa84e37..c3a3cdb 100644 (file)
@@ -3074,3 +3074,65 @@ void ath9k_hw_name(struct ath_hw *ah, char *hw_name, size_t len)
        hw_name[used] = '\0';
 }
 EXPORT_SYMBOL(ath9k_hw_name);
+
+#define DCU_COMPLETE_STATE  1
+#define NUM_STATUS_READS    50
+bool ath9k_hw_detect_mac_hang(struct ath_hw *ah)
+{
+       u32 dma_dbg_4 = 0, dma_dbg_5 = 0, dma_dbg_6;
+       u32 cur_chain_state = 0;
+       int i, hang_pos, hang_state = 0;
+
+       dma_dbg_6 = REG_READ(ah, AR_DMADBG_6);
+
+       if ((dma_dbg_6 & 0x3) != DCU_COMPLETE_STATE) {
+               ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+                       "MAC Hang signature not found at DCU complete\n");
+               return false;
+       }
+
+       dma_dbg_5 = REG_READ(ah, AR_DMADBG_5);
+       for (hang_pos = 3; hang_pos >= 0; hang_pos--) {
+               hang_state = (dma_dbg_5 >> (5 * hang_pos)) & 0x1f;
+               if (hang_state)
+                       goto hang_check_iter;
+       }
+
+       dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
+       for (hang_pos = 5; hang_pos >= 0; hang_pos--) {
+               hang_state = (dma_dbg_4 >> (5 * hang_pos)) & 0x1f;
+               if (hang_state)
+                       goto hang_check_iter;
+       }
+
+       ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+               "MAC Hang signature 1 not found\n");
+       return false;
+
+hang_check_iter:
+       ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+               "DMA Registers: %x %x %x Hang pos: %d\n",
+               dma_dbg_4, dma_dbg_5, dma_dbg_6, hang_pos);
+
+
+       for (i = 0; i < NUM_STATUS_READS; i++) {
+               if (dma_dbg_4) {
+                       dma_dbg_4 = REG_READ(ah, AR_DMADBG_4);
+                       cur_chain_state = (dma_dbg_4 >> (5 * hang_pos)) & 0x1f;
+               } else {
+                       dma_dbg_5 = REG_READ(ah, AR_DMADBG_5);
+                       cur_chain_state = (dma_dbg_5 >> (5 * hang_pos)) & 0x1f;
+               }
+               dma_dbg_6 = REG_READ(ah, AR_DMADBG_6);
+
+               if (((dma_dbg_6 & 0x3) != DCU_COMPLETE_STATE) ||
+                   (cur_chain_state != hang_state))
+                       return false;
+       }
+
+       ath_dbg(ath9k_hw_common(ah), RX_STUCK,
+               "MAC Hang signature 1 found\n");
+
+       return true;
+}
+EXPORT_SYMBOL(ath9k_hw_detect_mac_hang);
index 798ea57..32c2247 100644 (file)
@@ -661,6 +661,270 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
                ath_tx_node_cleanup(sc, an);
 }
 
+void ath_rx_poll_work(unsigned long data)
+{
+       struct ath_softc *sc = (struct ath_softc *)data;
+       struct ath_hw *ah = sc->sc_ah;
+       struct ath_common *common = ath9k_hw_common(ah);
+       struct ieee80211_conf *conf = &common->hw->conf;
+       struct ath9k_nfcal_hist *h = sc->caldata.nfCalHist;
+       static u32 iter, match_count;
+       static u64 last_run;
+       unsigned long flags;
+       u32 rx_clear, rx, tx, delay = 10, reg;
+       int i, j;
+       u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+       u8 nread;
+
+       if (jiffies_to_msecs(jiffies - last_run) > 30)
+               iter = match_count = 0;
+       else {
+               if (atomic_read(&sc->stop_rx_poll) && iter) {
+                       iter = match_count = 0;
+                       return;
+               }
+               iter += 1;
+       }
+       sc->ps_flags |= PS_WAIT_FOR_BEACON;
+       ath9k_ps_wakeup(sc);
+
+       spin_lock_irqsave(&common->cc_lock, flags);
+       ath_hw_cycle_counters_update(common);
+
+       rx_clear = common->cc_rxpoll.rx_busy * 100 / common->cc_rxpoll.cycles;
+       rx = common->cc_rxpoll.rx_frame * 100 / common->cc_rxpoll.cycles;
+       tx = common->cc_rxpoll.tx_frame * 100 / common->cc_rxpoll.cycles;
+       memset(&common->cc_rxpoll, 0, sizeof(common->cc_rxpoll));
+
+       spin_unlock_irqrestore(&common->cc_lock, flags);
+
+       ath_dbg(common, RX_STUCK,
+               "--------------------------------------------------\n");
+       ath_dbg(common, RX_STUCK, "Iteration: %d\n", iter);
+       ath_dbg(common, RX_STUCK, "Cycle Counters:\n");
+       ath_dbg(common, RX_STUCK,
+               "rx_clear = %d%% rx_frame %d%% tx_frame %d%%\n",
+               rx_clear, rx, tx);
+
+       ath_dbg(common, RX_STUCK, "IMR %08x IER %08x intr_cnt %d\n",
+               REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER),
+               atomic_read(&ah->intr_ref_cnt));
+       ar9003_hw_dump_txdesc(ah);
+
+       REG_SET_BIT(ah, AR_DIAG_SW, 0x8080000);
+       for (i = 0; i < 5; i++) {
+               ath_dbg(common, RX_STUCK,
+                       "OBS_BUS_1(0x806c) = %08x "
+                       "OBS_BUS_CTRL(0x8068) = %08x\n",
+                       REG_READ(ah, AR_OBS_BUS_1),
+                       REG_READ(ah, AR_OBS_BUS_CTRL));
+       }
+       ath_dbg(common, RX_STUCK,
+               "DIAG_SW(0x8048) = %08x MAC_PCU_LOGIC_ANALYZER(0x8264) = %08x"
+               " PCU_MISC_MODE2(0x8344) = %08x\n",
+               REG_READ(ah, AR_DIAG_SW),
+               REG_READ(ah, AR_MAC_PCU_LOGIC_ANALYZER),
+               REG_READ(ah, AR_PCU_MISC_MODE2));
+
+       ath_dbg(common, RX_STUCK, "0x100 = %08x 0x104 = %08x\n",
+               REG_READ(ah, 0x100), REG_READ(ah, 0x104));
+       for (i = 0; i < 10; i++)
+               ath_dbg(common, RX_STUCK, "QSTS(%d) = %08x\n",
+                       i, REG_READ(ah, AR_QSTS(i)));
+
+       ath_dbg(common, RX_STUCK, "Rxdp: hp %08x lp %08x\n",
+               REG_READ(ah, AR_HP_RXDP), REG_READ(ah, AR_LP_RXDP));
+       ath_dbg(common, RX_STUCK,
+               "rx filter: %08x\n", REG_READ(ah, AR_RX_FILTER));
+
+       ath_dbg(common, RX_STUCK, "DMADBG dump:\n");
+       for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++)
+               ath_dbg(common, RX_STUCK, "%d: %08x ",
+                       i, REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))));
+       ath_dbg(common, RX_STUCK, "\n");
+
+       ath_dbg(common, RX_STUCK, "BB Debug dump:\n");
+       /* Step 1a: Set bit 23 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x00800000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2a: Set register 0xa364 to 0x1000 */
+       reg = 0x1000;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3a: Read bits 17:0 of register 0x9c20 */
+       reg = REG_READ(ah, 0x9c20);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x1000] 0x9c20[17:0] = 0x%x\n", reg);
+
+       /* Step 1b: Set bit 23 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x00800000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2b: Set register 0xa364 to 0x1400 */
+       reg = 0x1400;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3b: Read bits 17:0 of register 0x9c20 */
+       reg = REG_READ(ah, 0x9c20);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x1400] 0x9c20[17:0] = 0x%x\n", reg);
+
+       /* Step 1c: Set bit 23 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x00800000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2c: Set register 0xa364 to 0x3C00 */
+       reg = 0x3c00;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3c: Read bits 17:0 of register 0x9c20 */
+       reg = REG_READ(ah, 0x9c20);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x3C00] 0x9c20[17:0] = 0x%x\n", reg);
+
+       /* Step 1d: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001040000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2d: Set register 0xa364 to 0x5005D */
+       reg = 0x5005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3d: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x5005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       /* Step 1e: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001040000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2e: Set register 0xa364 to 0x7005D */
+       reg = 0x7005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3e: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x7005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       /* Step 1f: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001000000;
+       reg |= 0x40000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2f: Set register 0xa364 to 0x3005D */
+       reg = 0x3005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3f: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x3005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       /* Step 1g: Set bit 24 of register 0xa360 to 0 */
+       reg = REG_READ(ah, 0xa360);
+       reg &= ~0x001000000;
+       reg |= 0x40000;
+       REG_WRITE(ah, 0xa360, reg);
+
+       /* Step 2g: Set register 0xa364 to 0x6005D */
+       reg = 0x6005D;
+       REG_WRITE(ah, 0xa364, reg);
+
+       /* Step 3g: Read bits 17:0 of register 0xa368 */
+       reg = REG_READ(ah, 0xa368);
+       reg &= 0x0003ffff;
+       ath_dbg(common, RX_STUCK,
+               "Test Control Status [0x6005D] 0xa368[17:0] = 0x%x\n", reg);
+
+       ar9003_hw_dump_ani_reg(ah);
+
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXLP", sc->debug.stats.istats.rxlp);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXHP", sc->debug.stats.istats.rxhp);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "WATCHDOG",
+               sc->debug.stats.istats.bb_watchdog);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "TX", sc->debug.stats.istats.txok);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib);
+       ath_dbg(common, RX_STUCK, "%8s: %10u\n", "RXPHY",
+               sc->debug.stats.istats.rxphyerr);
+       ath_dbg(common, RX_STUCK, "%8s: %10u\n", "RXKCM",
+               sc->debug.stats.istats.rx_keycache_miss);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "CST", sc->debug.stats.istats.cst);
+       ath_dbg(common, RX_STUCK,
+               "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt);
+
+       ath_dbg(common, RX_STUCK, "Noise floor dump:\n");
+       ath_dbg(common, RX_STUCK,
+               "Channel Noise Floor : %d\n", ah->noise);
+       ath_dbg(common, RX_STUCK,
+               "Chain | privNF | # Readings | NF Readings\n");
+       for (i = 0; i < 6; i++) {
+               if (!(chainmask & (1 << i)) ||
+                               ((i >= 3) && !conf_is_ht40(conf)))
+                       continue;
+
+               nread = 5 - h[i].invalidNFcount;
+               ath_dbg(common, RX_STUCK,
+               " %d\t %d\t %d\t\t", i, h[i].privNF, nread);
+               for (j = 0; j < nread; j++)
+                       ath_dbg(common, RX_STUCK,
+                               " %d", h[i].nfCalBuffer[j]);
+               ath_dbg(common, RX_STUCK, "\n");
+       }
+
+       last_run = jiffies;
+       if (rx_clear > 98) {
+               ath_dbg(common, RX_STUCK,
+                       "rx clear %d tx %d matched count %d\n",
+                       rx_clear, tx, match_count);
+               if (match_count++ > 9) {
+                       ath9k_ps_restore(sc);
+                       ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+                       iter = match_count = 0;
+                       return;
+               }
+       } else if (ath9k_hw_detect_mac_hang(ah)) {
+               ath_dbg(common, RX_STUCK, "MAC hang signature found\n");
+               ath9k_ps_restore(sc);
+               ieee80211_queue_work(sc->hw, &sc->hw_reset_work);
+               iter = match_count = 0;
+               return;
+       } else if (iter >= 15) {
+               iter = match_count = 0;
+               delay = 200;
+       }
+       ath9k_ps_restore(sc);
+       atomic_set(&sc->stop_rx_poll, 0);
+       mod_timer(&sc->rx_poll_timer, jiffies + msecs_to_jiffies(delay));
+}
 
 void ath9k_tasklet(unsigned long data)
 {