iwlwifi: pcie: support marbh fw dbg mode
authorLiad Kaufman <liad.kaufman@intel.com>
Mon, 5 Jan 2015 12:06:14 +0000 (14:06 +0200)
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Wed, 29 Apr 2015 10:12:49 +0000 (13:12 +0300)
This adds support for configuring and retrieving the FW
monitor in MARBH mode.

Signed-off-by: Liad Kaufman <liad.kaufman@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/pcie/trans.c

index 88a57e6e232ff318dea917d0856da781662bc5eb..5af1c776d2d4381fdd01e0044c4eeb5108236a18 100644 (file)
@@ -348,6 +348,9 @@ enum secure_load_status_reg {
 #define MON_BUFF_WRPTR                 (0xa03c44)
 #define MON_BUFF_CYCLE_CNT             (0xa03c48)
 
+#define MON_DMARB_RD_CTL_ADDR          (0xa03c60)
+#define MON_DMARB_RD_DATA_ADDR         (0xa03c5c)
+
 #define DBGC_IN_SAMPLE                 (0xa03c00)
 
 /* enable the ID buf for read */
index 47bbf573fdc836c9e410bd58c8decbe7e91830c4..d108e5bef9b737362ace36768d1f8eabeab52552 100644 (file)
@@ -2198,6 +2198,29 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
        return sizeof(**data) + fh_regs_len;
 }
 
+static u32
+iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans,
+                                struct iwl_fw_error_dump_fw_mon *fw_mon_data,
+                                u32 monitor_len)
+{
+       u32 buf_size_in_dwords = (monitor_len >> 2);
+       u32 *buffer = (u32 *)fw_mon_data->data;
+       unsigned long flags;
+       u32 i;
+
+       if (!iwl_trans_grab_nic_access(trans, false, &flags))
+               return 0;
+
+       __iwl_write_prph(trans, MON_DMARB_RD_CTL_ADDR, 0x1);
+       for (i = 0; i < buf_size_in_dwords; i++)
+               buffer[i] = __iwl_read_prph(trans, MON_DMARB_RD_DATA_ADDR);
+       __iwl_write_prph(trans, MON_DMARB_RD_CTL_ADDR, 0x0);
+
+       iwl_trans_release_nic_access(trans, &flags);
+
+       return monitor_len;
+}
+
 static
 struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
 {
@@ -2250,7 +2273,8 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
                      trans->dbg_dest_tlv->end_shift;
 
                /* Make "end" point to the actual end */
-               if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+               if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 ||
+                   trans->dbg_dest_tlv->monitor_mode == MARBH_MODE)
                        end += (1 << trans->dbg_dest_tlv->end_shift);
                monitor_len = end - base;
                len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
@@ -2326,9 +2350,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
 
                len += sizeof(*data) + sizeof(*fw_mon_data);
                if (trans_pcie->fw_mon_page) {
-                       data->len = cpu_to_le32(trans_pcie->fw_mon_size +
-                                               sizeof(*fw_mon_data));
-
                        /*
                         * The firmware is now asserted, it won't write anything
                         * to the buffer. CPU can take ownership to fetch the
@@ -2343,10 +2364,8 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
                               page_address(trans_pcie->fw_mon_page),
                               trans_pcie->fw_mon_size);
 
-                       len += trans_pcie->fw_mon_size;
-               } else {
-                       /* If we are here then the buffer is internal */
-
+                       monitor_len = trans_pcie->fw_mon_size;
+               } else if (trans->dbg_dest_tlv->monitor_mode == SMEM_MODE) {
                        /*
                         * Update pointers to reflect actual values after
                         * shifting
@@ -2355,10 +2374,18 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
                               trans->dbg_dest_tlv->base_shift;
                        iwl_trans_read_mem(trans, base, fw_mon_data->data,
                                           monitor_len / sizeof(u32));
-                       data->len = cpu_to_le32(sizeof(*fw_mon_data) +
-                                               monitor_len);
-                       len += monitor_len;
+               } else if (trans->dbg_dest_tlv->monitor_mode == MARBH_MODE) {
+                       monitor_len =
+                               iwl_trans_pci_dump_marbh_monitor(trans,
+                                                                fw_mon_data,
+                                                                monitor_len);
+               } else {
+                       /* Didn't match anything - output no monitor data */
+                       monitor_len = 0;
                }
+
+               len += monitor_len;
+               data->len = cpu_to_le32(monitor_len + sizeof(*fw_mon_data));
        }
 
        dump_data->len = len;