diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2013-01-02 05:12:25 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-01-16 08:23:57 -0500 |
commit | 1c3fea82d6ebf33edadefed2d9ce3efa1a654338 (patch) | |
tree | 58c8269e2275f8ea47f8a48a22c063d8ed1ed267 /drivers/net/wireless/iwlwifi/pcie/trans.c | |
parent | ddaf5a5b300b8f9d3591b509fd8bedab1c9887be (diff) |
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 59340ff13a64..c57641eb83d5 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) | |||
890 | struct iwl_queue *q; | 890 | struct iwl_queue *q; |
891 | int cnt; | 891 | int cnt; |
892 | unsigned long now = jiffies; | 892 | unsigned long now = jiffies; |
893 | u32 scd_sram_addr; | ||
894 | u8 buf[16]; | ||
893 | int ret = 0; | 895 | int ret = 0; |
894 | 896 | ||
895 | /* waiting for all the tx frames complete might take a while */ | 897 | /* 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) | |||
903 | msleep(1); | 905 | msleep(1); |
904 | 906 | ||
905 | if (q->read_ptr != q->write_ptr) { | 907 | if (q->read_ptr != q->write_ptr) { |
906 | IWL_ERR(trans, "fail to flush all tx fifo queues\n"); | 908 | IWL_ERR(trans, |
909 | "fail to flush all tx fifo queues Q %d\n", cnt); | ||
907 | ret = -ETIMEDOUT; | 910 | ret = -ETIMEDOUT; |
908 | break; | 911 | break; |
909 | } | 912 | } |
910 | } | 913 | } |
914 | |||
915 | if (!ret) | ||
916 | return 0; | ||
917 | |||
918 | IWL_ERR(trans, "Current SW read_ptr %d write_ptr %d\n", | ||
919 | txq->q.read_ptr, txq->q.write_ptr); | ||
920 | |||
921 | scd_sram_addr = trans_pcie->scd_base_addr + | ||
922 | SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); | ||
923 | iwl_trans_read_mem_bytes(trans, scd_sram_addr, buf, sizeof(buf)); | ||
924 | |||
925 | iwl_print_hex_error(trans, buf, sizeof(buf)); | ||
926 | |||
927 | for (cnt = 0; cnt < FH_TCSR_CHNL_NUM; cnt++) | ||
928 | IWL_ERR(trans, "FH TRBs(%d) = 0x%08x\n", cnt, | ||
929 | iwl_read_direct32(trans, FH_TX_TRB_REG(cnt))); | ||
930 | |||
931 | for (cnt = 0; cnt < trans->cfg->base_params->num_of_queues; cnt++) { | ||
932 | u32 status = iwl_read_prph(trans, SCD_QUEUE_STATUS_BITS(cnt)); | ||
933 | u8 fifo = (status >> SCD_QUEUE_STTS_REG_POS_TXF) & 0x7; | ||
934 | bool active = !!(status & BIT(SCD_QUEUE_STTS_REG_POS_ACTIVE)); | ||
935 | u32 tbl_dw = | ||
936 | iwl_trans_read_mem32(trans, trans_pcie->scd_base_addr + | ||
937 | SCD_TRANS_TBL_OFFSET_QUEUE(cnt)); | ||
938 | |||
939 | if (cnt & 0x1) | ||
940 | tbl_dw = (tbl_dw & 0xFFFF0000) >> 16; | ||
941 | else | ||
942 | tbl_dw = tbl_dw & 0x0000FFFF; | ||
943 | |||
944 | IWL_ERR(trans, | ||
945 | "Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n", | ||
946 | cnt, active ? "" : "in", fifo, tbl_dw, | ||
947 | iwl_read_prph(trans, | ||
948 | SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1), | ||
949 | iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt))); | ||
950 | } | ||
951 | |||
911 | return ret; | 952 | return ret; |
912 | } | 953 | } |
913 | 954 | ||