]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
iwlwifi: dump smem configuration when firmware crashes
authorGolan Ben-Ami <golan.ben.ami@intel.com>
Sun, 25 Jun 2017 14:23:23 +0000 (17:23 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Wed, 9 Aug 2017 06:35:15 +0000 (09:35 +0300)
Add the smem configuration to the fw data dump, once
the firmware crashes. This is useful mainly for later
parsing of the smem.

Signed-off-by: Golan Ben-Ami <golan.ben.ami@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/dbg.c
drivers/net/wireless/intel/iwlwifi/fw/error-dump.h
drivers/net/wireless/intel/iwlwifi/fw/smem.c

index 77245fcba9966473843e5da03b85f4fc1173525c..6afc7a799892f424c64934f67b949d4c9beaa48d 100644 (file)
@@ -545,11 +545,13 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
        struct iwl_fw_error_dump_data *dump_data;
        struct iwl_fw_error_dump_info *dump_info;
        struct iwl_fw_error_dump_mem *dump_mem;
+       struct iwl_fw_error_dump_smem_cfg *dump_smem_cfg;
        struct iwl_fw_error_dump_trigger_desc *dump_trig;
        struct iwl_fw_dump_ptrs *fw_error_dump;
        struct scatterlist *sg_dump_data;
        u32 sram_len, sram_ofs;
        const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = fwrt->fw->dbg_mem_tlv;
+       struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
        u32 file_len, fifo_data_len = 0, prph_len = 0, radio_len = 0;
        u32 smem_len = fwrt->fw->n_dbg_mem_tlv ? 0 : fwrt->trans->cfg->smem_len;
        u32 sram2_len = fwrt->fw->n_dbg_mem_tlv ?
@@ -585,8 +587,6 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
 
        /* reading RXF/TXF sizes */
        if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
-               struct iwl_fwrt_shared_mem_cfg *mem_cfg = &fwrt->smem_cfg;
-
                fifo_data_len = 0;
 
                /* Count RXF2 size */
@@ -675,7 +675,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
        }
 
        file_len = sizeof(*dump_file) +
-                  sizeof(*dump_data) * 2 +
+                  sizeof(*dump_data) * 3 +
+                  sizeof(*dump_smem_cfg) +
                   fifo_data_len +
                   prph_len +
                   radio_len +
@@ -706,8 +707,8 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
 
        /* If we only want a monitor dump, reset the file length */
        if (monitor_dump_only) {
-               file_len = sizeof(*dump_file) + sizeof(*dump_data) +
-                          sizeof(*dump_info);
+               file_len = sizeof(*dump_file) + sizeof(*dump_data) * 2 +
+                          sizeof(*dump_info) + sizeof(*dump_smem_cfg);
        }
 
        if (fwrt->dump.desc)
@@ -744,6 +745,33 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
                sizeof(dump_info->bus_human_readable));
 
        dump_data = iwl_fw_error_next_data(dump_data);
+
+       /* Dump shared memory configuration */
+       dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM_CFG);
+       dump_data->len = cpu_to_le32(sizeof(*dump_smem_cfg));
+       dump_smem_cfg = (void *)dump_data->data;
+       dump_smem_cfg->num_lmacs = cpu_to_le32(mem_cfg->num_lmacs);
+       dump_smem_cfg->num_txfifo_entries =
+               cpu_to_le32(mem_cfg->num_txfifo_entries);
+       for (i = 0; i < MAX_NUM_LMAC; i++) {
+               int j;
+
+               for (j = 0; j < TX_FIFO_MAX_NUM; j++)
+                       dump_smem_cfg->lmac[i].txfifo_size[j] =
+                               cpu_to_le32(mem_cfg->lmac[i].txfifo_size[j]);
+               dump_smem_cfg->lmac[i].rxfifo1_size =
+                       cpu_to_le32(mem_cfg->lmac[i].rxfifo1_size);
+       }
+       dump_smem_cfg->rxfifo2_size = cpu_to_le32(mem_cfg->rxfifo2_size);
+       dump_smem_cfg->internal_txfifo_addr =
+               cpu_to_le32(mem_cfg->internal_txfifo_addr);
+       for (i = 0; i < TX_FIFO_INTERNAL_MAX_NUM; i++) {
+               dump_smem_cfg->internal_txfifo_size[i] =
+                       cpu_to_le32(mem_cfg->internal_txfifo_size[i]);
+       }
+
+       dump_data = iwl_fw_error_next_data(dump_data);
+
        /* We only dump the FIFOs if the FW is in error state */
        if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) {
                iwl_fw_dump_fifos(fwrt, &dump_data);
index cfebde68a39173a64cea7c6b88c61ba59ddae966..ed7beca8817e2e435dfbdc09ab3f977343614e9e 100644 (file)
@@ -7,6 +7,7 @@
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 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
@@ -33,6 +34,7 @@
  *
  * Copyright(c) 2014 Intel Corporation. All rights reserved.
  * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -92,6 +94,9 @@
  * @IWL_FW_ERROR_DUMP_EXTERNAL: used only by external code utilities, and
  *     for that reason is not in use in any other place in the Linux Wi-Fi
  *     stack.
+ * @IWL_FW_ERROR_DUMP_MEM_CFG: the addresses and sizes of fifos in the smem,
+ *     which we get from the fw after ALIVE. The content is structured as
+ *     &struct iwl_fw_error_dump_smem_cfg.
  */
 enum iwl_fw_error_dump_type {
        /* 0 is deprecated */
@@ -110,6 +115,7 @@ enum iwl_fw_error_dump_type {
        IWL_FW_ERROR_DUMP_RADIO_REG = 13,
        IWL_FW_ERROR_DUMP_INTERNAL_TXF = 14,
        IWL_FW_ERROR_DUMP_EXTERNAL = 15, /* Do not move */
+       IWL_FW_ERROR_DUMP_MEM_CFG = 16,
 
        IWL_FW_ERROR_DUMP_MAX,
 };
@@ -208,6 +214,30 @@ struct iwl_fw_error_dump_fw_mon {
        u8 data[];
 } __packed;
 
+#define MAX_NUM_LMAC 2
+#define TX_FIFO_INTERNAL_MAX_NUM       6
+#define TX_FIFO_MAX_NUM                        15
+/**
+ * struct iwl_fw_error_dump_smem_cfg - Dump SMEM configuration
+ *     This must follow &struct iwl_fwrt_shared_mem_cfg.
+ * @num_lmacs: number of lmacs
+ * @num_txfifo_entries: number of tx fifos
+ * @lmac: sizes of lmacs txfifos and rxfifo1
+ * @rxfifo2_size: size of rxfifo2
+ * @internal_txfifo_addr: address of internal tx fifo
+ * @internal_txfifo_size: size of internal tx fifo
+ */
+struct iwl_fw_error_dump_smem_cfg {
+       __le32 num_lmacs;
+       __le32 num_txfifo_entries;
+       struct {
+               __le32 txfifo_size[TX_FIFO_MAX_NUM];
+               __le32 rxfifo1_size;
+       } lmac[MAX_NUM_LMAC];
+       __le32 rxfifo2_size;
+       __le32 internal_txfifo_addr;
+       __le32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM];
+} __packed;
 /**
  * struct iwl_fw_error_dump_prph - periphery registers data
  * @prph_start: address of the first register in this chunk
index 065a951cefbaa51a84fdb16878ecce70452b4f56..76675736ba4f77c33f9069c1156863a4f71e8c14 100644 (file)
@@ -113,6 +113,9 @@ static void iwl_parse_shared_mem(struct iwl_fw_runtime *fwrt,
                BUILD_BUG_ON(sizeof(fwrt->smem_cfg.internal_txfifo_size) !=
                             sizeof(mem_cfg->internal_txfifo_size));
 
+               fwrt->smem_cfg.internal_txfifo_addr =
+                       le32_to_cpu(mem_cfg->internal_txfifo_addr);
+
                for (i = 0;
                     i < ARRAY_SIZE(fwrt->smem_cfg.internal_txfifo_size);
                     i++)