diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-01-02 12:12:25 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-01-16 14:23:57 +0100 |
commit | 1c3fea82d6ebf33edadefed2d9ce3efa1a654338 (patch) | |
tree | 58c8269e2275f8ea47f8a48a22c063d8ed1ed267 /drivers/net/wireless/iwlwifi/pcie/trans.c | |
parent | ddaf5a5b300b8f9d3591b509fd8bedab1c9887be (diff) | |
download | op-kernel-dev-1c3fea82d6ebf33edadefed2d9ce3efa1a654338.zip op-kernel-dev-1c3fea82d6ebf33edadefed2d9ce3efa1a654338.tar.gz |
iwlwifi: improve the reports in TX path
Also when things go wrong (queues don't get emtpy), try to
get some data from the HW.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/trans.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/trans.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 59340ff..c57641e 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -890,6 +890,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) struct iwl_queue *q; int cnt; unsigned long now = jiffies; + u32 scd_sram_addr; + u8 buf[16]; int ret = 0; /* waiting for all the tx frames complete might take a while */ @@ -903,11 +905,50 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans) msleep(1); if (q->read_ptr != q->write_ptr) { - IWL_ERR(trans, "fail to flush all tx fifo queues\n"); + IWL_ERR(trans, + "fail to flush all tx fifo queues Q %d\n", cnt); ret = -ETIMEDOUT; break; } } + + if (!ret) + return 0; + + IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", + txq->q.read_ptr, txq->q.write_ptr); + + scd_sram_addr = trans_pcie->scd_base_addr + + SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); + iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); + + iwl_print_hex_error(trans, buf, sizeof(buf)); + + for (cnt = 0; cnt < FH_TCSR_CHNL_NUM; cnt++) + IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", cnt, + iwl_read_direct32(trans, FH_TX_TRB_REG(cnt))); + + for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { + u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(cnt)); + u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; + bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); + u32 tbl_dw = + iwl_trans_read_mem32(trans, trans_pcie->scd_base_addr + + SCD_TRANS_TBL_OFFSET_QUEUE(cnt)); + + if (cnt & 0x1) + tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; + else + tbl_dw = tbl_dw & 0x0000FFFF; + + IWL_ERR(trans, + "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", + cnt, active ? "" : "in", fifo, tbl_dw, + iwl_read_prph(trans, + SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1), + iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); + } + return ret; } |