iwlwifi: receive umac and lmac error table addresses from TLVs
authorShahar S Matityahu <shahar.s.matityahu@intel.com>
Tue, 24 Apr 2018 10:35:59 +0000 (13:35 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Thu, 14 Feb 2019 09:29:45 +0000 (11:29 +0200)
TLV 54 holds umac debug related addresses.
TLV 55 holds lmac debug related addresses.
These TLVs aim to replace the alive notification data in the future.

Parse and keep error table addresses received from the TLVs
for both lmac and umac and use these addresses instead of the pointer
received from alive notification.

The feature supports only unified image.

Signed-off-by: Shahar S Matityahu <shahar.s.matityahu@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/fw/api/alive.h
drivers/net/wireless/intel/iwlwifi/fw/dbg.h
drivers/net/wireless/intel/iwlwifi/fw/file.h
drivers/net/wireless/intel/iwlwifi/iwl-drv.c
drivers/net/wireless/intel/iwlwifi/iwl-trans.h
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/utils.c

index 08d3d8a190f6b9f0ce75cbc39754247b2fc4d1cf..0026e259fd8759107433e1bf55fe0b2850fbc149 100644 (file)
@@ -96,14 +96,7 @@ enum {
 
 #define IWL_ALIVE_FLG_RFKILL   BIT(0)
 
-struct iwl_lmac_alive {
-       __le32 ucode_major;
-       __le32 ucode_minor;
-       u8 ver_subtype;
-       u8 ver_type;
-       u8 mac;
-       u8 opt;
-       __le32 timestamp;
+struct iwl_lmac_debug_addrs {
        __le32 error_event_table_ptr;   /* SRAM address for error log */
        __le32 log_event_table_ptr;     /* SRAM address for LMAC event log */
        __le32 cpu_register_ptr;
@@ -112,13 +105,28 @@ struct iwl_lmac_alive {
        __le32 scd_base_ptr;            /* SRAM address for SCD */
        __le32 st_fwrd_addr;            /* pointer to Store and forward */
        __le32 st_fwrd_size;
+} __packed; /* UCODE_DEBUG_ADDRS_API_S_VER_2 */
+
+struct iwl_lmac_alive {
+       __le32 ucode_major;
+       __le32 ucode_minor;
+       u8 ver_subtype;
+       u8 ver_type;
+       u8 mac;
+       u8 opt;
+       __le32 timestamp;
+       struct iwl_lmac_debug_addrs dbg_ptrs;
 } __packed; /* UCODE_ALIVE_NTFY_API_S_VER_3 */
 
+struct iwl_umac_debug_addrs {
+       __le32 error_info_addr;         /* SRAM address for UMAC error log */
+       __le32 dbg_print_buff_addr;
+} __packed; /* UMAC_DEBUG_ADDRS_API_S_VER_1 */
+
 struct iwl_umac_alive {
        __le32 umac_major;              /* UMAC version: major */
        __le32 umac_minor;              /* UMAC version: minor */
-       __le32 error_info_addr;         /* SRAM address for UMAC error log */
-       __le32 dbg_print_buff_addr;
+       struct iwl_umac_debug_addrs dbg_ptrs;
 } __packed; /* UMAC_ALIVE_DATA_API_S_VER_2 */
 
 struct mvm_alive_resp_v3 {
index a6133b5f9e83c36dc50280b0c14a4a33e93aefd1..d11923edd695f51690599eafc822cfc5360c26ed 100644 (file)
@@ -442,6 +442,26 @@ void iwl_fw_dbg_apply_point(struct iwl_fw_runtime *fwrt,
 
 void iwl_fwrt_stop_device(struct iwl_fw_runtime *fwrt);
 
+static inline void iwl_fw_lmac1_set_alive_err_table(struct iwl_trans *trans,
+                                                   u32 lmac_error_event_table)
+{
+       if (!(trans->error_event_table_tlv_status &
+             IWL_ERROR_EVENT_TABLE_LMAC1) ||
+           WARN_ON(trans->lmac_error_event_table[0] !=
+                   lmac_error_event_table))
+               trans->lmac_error_event_table[0] = lmac_error_event_table;
+}
+
+static inline void iwl_fw_umac_set_alive_err_table(struct iwl_trans *trans,
+                                                  u32 umac_error_event_table)
+{
+       if (!(trans->error_event_table_tlv_status &
+             IWL_ERROR_EVENT_TABLE_UMAC) ||
+           WARN_ON(trans->umac_error_event_table !=
+                   umac_error_event_table))
+               trans->umac_error_event_table = umac_error_event_table;
+}
+
 /* This bit is used to differentiate the legacy dump from the ini dump */
 #define INI_DUMP_BIT BIT(31)
 
index 3bffb0f7a5e5af7c9bd20cd7b46f198913623c2c..886a620e03cf793fbacc58e83dda3c483d50b902 100644 (file)
@@ -143,6 +143,8 @@ enum iwl_ucode_tlv_type {
        IWL_UCODE_TLV_FW_GSCAN_CAPA     = 50,
        IWL_UCODE_TLV_FW_MEM_SEG        = 51,
        IWL_UCODE_TLV_IML               = 52,
+       IWL_UCODE_TLV_UMAC_DEBUG_ADDRS  = 54,
+       IWL_UCODE_TLV_LMAC_DEBUG_ADDRS  = 55,
        IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION    = IWL_UCODE_INI_TLV_GROUP | 0x1,
        IWL_UCODE_TLV_TYPE_HCMD                 = IWL_UCODE_INI_TLV_GROUP | 0x2,
        IWL_UCODE_TLV_TYPE_REGIONS              = IWL_UCODE_INI_TLV_GROUP | 0x3,
index 2efa1dfe9b4ca86ac7471aec8e8e9672e4142d87..784e07b648e6f200d6afb3ebece0d1855d0a53da 100644 (file)
@@ -75,6 +75,7 @@
 #include "iwl-dbg-tlv.h"
 #include "iwl-config.h"
 #include "iwl-modparams.h"
+#include "fw/api/alive.h"
 
 /******************************************************************************
  *
@@ -588,6 +589,8 @@ static int iwl_parse_v1_v2_firmware(struct iwl_drv *drv,
        return 0;
 }
 
+#define FW_ADDR_CACHE_CONTROL 0xC0000000
+
 static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                                const struct firmware *ucode_raw,
                                struct iwl_firmware_pieces *pieces,
@@ -1085,6 +1088,38 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
                                return -ENOMEM;
                        break;
                        }
+               case IWL_UCODE_TLV_UMAC_DEBUG_ADDRS: {
+                       struct iwl_umac_debug_addrs *dbg_ptrs =
+                               (void *)tlv_data;
+
+                       if (tlv_len != sizeof(*dbg_ptrs))
+                               goto invalid_tlv_len;
+                       if (drv->trans->cfg->device_family <
+                           IWL_DEVICE_FAMILY_22000)
+                               break;
+                       drv->trans->umac_error_event_table =
+                               le32_to_cpu(dbg_ptrs->error_info_addr) &
+                               ~FW_ADDR_CACHE_CONTROL;
+                       drv->trans->error_event_table_tlv_status |=
+                               IWL_ERROR_EVENT_TABLE_UMAC;
+                       break;
+                       }
+               case IWL_UCODE_TLV_LMAC_DEBUG_ADDRS: {
+                       struct iwl_lmac_debug_addrs *dbg_ptrs =
+                               (void *)tlv_data;
+
+                       if (tlv_len != sizeof(*dbg_ptrs))
+                               goto invalid_tlv_len;
+                       if (drv->trans->cfg->device_family <
+                           IWL_DEVICE_FAMILY_22000)
+                               break;
+                       drv->trans->lmac_error_event_table[0] =
+                               le32_to_cpu(dbg_ptrs->error_event_table_ptr) &
+                               ~FW_ADDR_CACHE_CONTROL;
+                       drv->trans->error_event_table_tlv_status |=
+                               IWL_ERROR_EVENT_TABLE_LMAC1;
+                       break;
+                       }
                case IWL_UCODE_TLV_TYPE_BUFFER_ALLOCATION:
                case IWL_UCODE_TLV_TYPE_HCMD:
                case IWL_UCODE_TLV_TYPE_REGIONS:
index ef23c6aafb5ca263e5941cb096ff3556642f8efb..bbebbf3efd57db1a2101a5e6cc02cf2095666dd7 100644 (file)
@@ -232,6 +232,12 @@ enum iwl_hcmd_dataflag {
        IWL_HCMD_DFL_DUP        = BIT(1),
 };
 
+enum iwl_error_event_table_status {
+       IWL_ERROR_EVENT_TABLE_LMAC1 = BIT(0),
+       IWL_ERROR_EVENT_TABLE_LMAC2 = BIT(1),
+       IWL_ERROR_EVENT_TABLE_UMAC = BIT(2),
+};
+
 /**
  * struct iwl_host_cmd - Host command to the uCode
  *
@@ -759,6 +765,10 @@ struct iwl_self_init_dram {
  *     mode is set during the initialization phase and is not
  *     supposed to change during runtime.
  * @dbg_rec_on: true iff there is a fw debug recording currently active
+ * @lmac_error_event_table: addrs of lmacs error tables
+ * @umac_error_event_table: addr of umac error table
+ * @error_event_table_tlv_status: bitmap that indicates what error table
+ *     pointers was recevied via TLV. use enum &iwl_error_event_table_status
  */
 struct iwl_trans {
        const struct iwl_trans_ops *ops;
index 36ed7d6fc9714376d7c80ad2f183780f245d6b76..808bc6f363d0e4642d38daf28a4ea7165037dc32 100644 (file)
@@ -1899,7 +1899,7 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac,
 static int iwl_mvm_check_rt_status(struct iwl_mvm *mvm,
                                   struct ieee80211_vif *vif)
 {
-       u32 base = mvm->error_event_table[0];
+       u32 base = mvm->trans->lmac_error_event_table[0];
        struct error_table_start {
                /* cf. struct iwl_error_event_table */
                u32 valid;
index 8140b193cc059855ce0f9cfa231496cb1661d47b..cf7f8c340ffeea53d04b477ceaf38f6e6f9a965a 100644 (file)
@@ -218,7 +218,7 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
        struct iwl_lmac_alive *lmac1;
        struct iwl_lmac_alive *lmac2 = NULL;
        u16 status;
-       u32 umac_error_event_table;
+       u32 lmac_error_event_table, umac_error_event_table;
 
        if (iwl_rx_packet_payload_len(pkt) == sizeof(*palive)) {
                palive = (void *)pkt->data;
@@ -233,30 +233,35 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
                status = le16_to_cpu(palive3->status);
        }
 
-       mvm->error_event_table[0] = le32_to_cpu(lmac1->error_event_table_ptr);
+       lmac_error_event_table =
+               le32_to_cpu(lmac1->dbg_ptrs.error_event_table_ptr);
+       iwl_fw_lmac1_set_alive_err_table(mvm->trans, lmac_error_event_table);
+
        if (lmac2)
-               mvm->error_event_table[1] =
-                       le32_to_cpu(lmac2->error_event_table_ptr);
-       mvm->log_event_table = le32_to_cpu(lmac1->log_event_table_ptr);
+               mvm->trans->lmac_error_event_table[1] =
+                       le32_to_cpu(lmac2->dbg_ptrs.error_event_table_ptr);
 
-       umac_error_event_table = le32_to_cpu(umac->error_info_addr);
+       umac_error_event_table = le32_to_cpu(umac->dbg_ptrs.error_info_addr);
 
        if (!umac_error_event_table) {
                mvm->support_umac_log = false;
        } else if (umac_error_event_table >=
                   mvm->trans->cfg->min_umac_error_event_table) {
                mvm->support_umac_log = true;
-               mvm->umac_error_event_table = umac_error_event_table;
        } else {
                IWL_ERR(mvm,
                        "Not valid error log pointer 0x%08X for %s uCode\n",
-                       mvm->umac_error_event_table,
+                       umac_error_event_table,
                        (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) ?
                        "Init" : "RT");
                mvm->support_umac_log = false;
        }
 
-       alive_data->scd_base_addr = le32_to_cpu(lmac1->scd_base_ptr);
+       if (mvm->support_umac_log)
+               iwl_fw_umac_set_alive_err_table(mvm->trans,
+                                               umac_error_event_table);
+
+       alive_data->scd_base_addr = le32_to_cpu(lmac1->dbg_ptrs.scd_base_ptr);
        alive_data->valid = status == IWL_ALIVE_STATUS_OK;
 
        IWL_DEBUG_FW(mvm,
index e9873fc7bd2bd4a6a3b27cb822d197546e6e6beb..0255157378db20e9130eae74d35883d068b659cf 100644 (file)
@@ -879,9 +879,6 @@ struct iwl_mvm {
 
        bool hw_registered;
        bool calibrating;
-       u32 error_event_table[2];
-       u32 log_event_table;
-       u32 umac_error_event_table;
        bool support_umac_log;
 
        u32 ampdu_ref;
index 4a18997fb48af7f2477eaa923cd3a51b49558733..4649327abb456bff84b3e455a56b13eefe17090d 100644 (file)
@@ -457,12 +457,14 @@ static void iwl_mvm_dump_umac_error_log(struct iwl_mvm *mvm)
 {
        struct iwl_trans *trans = mvm->trans;
        struct iwl_umac_error_event_table table;
+       u32 base = mvm->trans->umac_error_event_table;
 
-       if (!mvm->support_umac_log)
+       if (!mvm->support_umac_log &&
+           !(mvm->trans->error_event_table_tlv_status &
+             IWL_ERROR_EVENT_TABLE_UMAC))
                return;
 
-       iwl_trans_read_mem_bytes(trans, mvm->umac_error_event_table, &table,
-                                sizeof(table));
+       iwl_trans_read_mem_bytes(trans, base, &table, sizeof(table));
 
        if (table.valid)
                mvm->fwrt.dump.umac_err_id = table.error_id;
@@ -494,7 +496,7 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num)
 {
        struct iwl_trans *trans = mvm->trans;
        struct iwl_error_event_table table;
-       u32 val, base = mvm->error_event_table[lmac_num];
+       u32 val, base = mvm->trans->lmac_error_event_table[lmac_num];
 
        if (mvm->fwrt.cur_fw_img == IWL_UCODE_INIT) {
                if (!base)
@@ -590,7 +592,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
 
        iwl_mvm_dump_lmac_error_log(mvm, 0);
 
-       if (mvm->error_event_table[1])
+       if (mvm->trans->lmac_error_event_table[1])
                iwl_mvm_dump_lmac_error_log(mvm, 1);
 
        iwl_mvm_dump_umac_error_log(mvm);