iwlwifi: mvm: support dumping UMAC internal txfifos
[deliverable/linux.git] / drivers / net / wireless / intel / iwlwifi / mvm / fw-dbg.c
index 4856eac120f60d5eff2e9707e828e541761a76ae..6ef706c13cda56af5937b3d3d8546b20ab4581ed 100644 (file)
@@ -7,7 +7,7 @@
  *
  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2015        Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of version 2 of the GNU General Public License as
@@ -32,7 +32,7 @@
  *
  * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
- * Copyright(c) 2015        Intel Deutschland GmbH
+ * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -265,6 +265,65 @@ static void iwl_mvm_dump_fifos(struct iwl_mvm *mvm,
                *dump_data = iwl_fw_error_next_data(*dump_data);
        }
 
+       if (fw_has_capa(&mvm->fw->ucode_capa,
+                       IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
+               /* Pull UMAC internal TXF data from all TXFs */
+               for (i = 0;
+                    i < ARRAY_SIZE(mvm->shared_mem_cfg.internal_txfifo_size);
+                    i++) {
+                       /* Mark the number of TXF we're pulling now */
+                       iwl_trans_write_prph(mvm->trans, TXF_CPU2_NUM, i);
+
+                       fifo_hdr = (void *)(*dump_data)->data;
+                       fifo_data = (void *)fifo_hdr->data;
+                       fifo_len = mvm->shared_mem_cfg.internal_txfifo_size[i];
+
+                       /* No need to try to read the data if the length is 0 */
+                       if (fifo_len == 0)
+                               continue;
+
+                       /* Add a TLV for the internal FIFOs */
+                       (*dump_data)->type =
+                               cpu_to_le32(IWL_FW_ERROR_DUMP_INTERNAL_TXF);
+                       (*dump_data)->len =
+                               cpu_to_le32(fifo_len + sizeof(*fifo_hdr));
+
+                       fifo_hdr->fifo_num = cpu_to_le32(i);
+                       fifo_hdr->available_bytes =
+                               cpu_to_le32(iwl_trans_read_prph(mvm->trans,
+                                                               TXF_CPU2_FIFO_ITEM_CNT));
+                       fifo_hdr->wr_ptr =
+                               cpu_to_le32(iwl_trans_read_prph(mvm->trans,
+                                                               TXF_CPU2_WR_PTR));
+                       fifo_hdr->rd_ptr =
+                               cpu_to_le32(iwl_trans_read_prph(mvm->trans,
+                                                               TXF_CPU2_RD_PTR));
+                       fifo_hdr->fence_ptr =
+                               cpu_to_le32(iwl_trans_read_prph(mvm->trans,
+                                                               TXF_CPU2_FENCE_PTR));
+                       fifo_hdr->fence_mode =
+                               cpu_to_le32(iwl_trans_read_prph(mvm->trans,
+                                                               TXF_CPU2_LOCK_FENCE));
+
+                       /* Set TXF_CPU2_READ_MODIFY_ADDR to TXF_CPU2_WR_PTR */
+                       iwl_trans_write_prph(mvm->trans,
+                                            TXF_CPU2_READ_MODIFY_ADDR,
+                                            TXF_CPU2_WR_PTR);
+
+                       /* Dummy-read to advance the read pointer to head */
+                       iwl_trans_read_prph(mvm->trans,
+                                           TXF_CPU2_READ_MODIFY_DATA);
+
+                       /* Read FIFO */
+                       fifo_len /= sizeof(u32); /* Size in DWORDS */
+                       for (j = 0; j < fifo_len; j++)
+                               fifo_data[j] =
+                                       iwl_trans_read_prph(mvm->trans,
+                                                           TXF_CPU2_READ_MODIFY_DATA);
+                       *dump_data = iwl_fw_error_next_data(*dump_data);
+               }
+       }
+
        iwl_trans_release_nic_access(mvm->trans, &flags);
 }
 
@@ -494,6 +553,22 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
                                         sizeof(struct iwl_fw_error_dump_fifo);
                }
 
+               if (fw_has_capa(&mvm->fw->ucode_capa,
+                               IWL_UCODE_TLV_CAPA_EXTEND_SHARED_MEM_CFG)) {
+                       for (i = 0;
+                            i < ARRAY_SIZE(mem_cfg->internal_txfifo_size);
+                            i++) {
+                               if (!mem_cfg->internal_txfifo_size[i])
+                                       continue;
+
+                               /* Add header info */
+                               fifo_data_len +=
+                                       mem_cfg->internal_txfifo_size[i] +
+                                       sizeof(*dump_data) +
+                                       sizeof(struct iwl_fw_error_dump_fifo);
+                       }
+               }
+
                /* Make room for PRPH registers */
                for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
                        /* The range includes both boundaries */
This page took 0.027221 seconds and 5 git commands to generate.