|
@@ -88,6 +88,93 @@
|
|
|
#define IWL_FW_MEM_EXTENDED_START 0x40000
|
|
|
#define IWL_FW_MEM_EXTENDED_END 0x57FFF
|
|
|
|
|
|
+static void iwl_trans_pcie_err_dump(struct iwl_trans *trans)
|
|
|
+{
|
|
|
+#define PCI_DUMP_SIZE 64
|
|
|
+#define PREFIX_LEN 32
|
|
|
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
|
+ struct pci_dev *pdev = trans_pcie->pci_dev;
|
|
|
+ u32 i, pos, alloc_size, *ptr, *buf;
|
|
|
+ char *prefix;
|
|
|
+
|
|
|
+ if (trans_pcie->pcie_dbg_dumped_once)
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* Should be a multiple of 4 */
|
|
|
+ BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);
|
|
|
+ /* Alloc a max size buffer */
|
|
|
+ if (PCI_ERR_ROOT_ERR_SRC + 4 > PCI_DUMP_SIZE)
|
|
|
+ alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;
|
|
|
+ else
|
|
|
+ alloc_size = PCI_DUMP_SIZE + PREFIX_LEN;
|
|
|
+ buf = kmalloc(alloc_size, GFP_ATOMIC);
|
|
|
+ if (!buf)
|
|
|
+ return;
|
|
|
+ prefix = (char *)buf + alloc_size - PREFIX_LEN;
|
|
|
+
|
|
|
+ IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n");
|
|
|
+
|
|
|
+ /* Print wifi device registers */
|
|
|
+ sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
|
|
|
+ IWL_ERR(trans, "iwlwifi device config registers:\n");
|
|
|
+ for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
|
|
|
+ if (pci_read_config_dword(pdev, i, ptr))
|
|
|
+ goto err_read;
|
|
|
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
|
|
+
|
|
|
+ IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
|
|
|
+ for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
|
|
|
+ *ptr = iwl_read32(trans, i);
|
|
|
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
|
|
+
|
|
|
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
|
|
|
+ if (pos) {
|
|
|
+ IWL_ERR(trans, "iwlwifi device AER capability structure:\n");
|
|
|
+ for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)
|
|
|
+ if (pci_read_config_dword(pdev, pos + i, ptr))
|
|
|
+ goto err_read;
|
|
|
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
|
|
|
+ 32, 4, buf, i, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Print parent device registers next */
|
|
|
+ if (!pdev->bus->self)
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ pdev = pdev->bus->self;
|
|
|
+ sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
|
|
|
+
|
|
|
+ IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
|
|
|
+ pci_name(pdev));
|
|
|
+ for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
|
|
|
+ if (pci_read_config_dword(pdev, i, ptr))
|
|
|
+ goto err_read;
|
|
|
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
|
|
+
|
|
|
+ /* Print root port AER registers */
|
|
|
+ pos = 0;
|
|
|
+ pdev = pcie_find_root_port(pdev);
|
|
|
+ if (pdev)
|
|
|
+ pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
|
|
|
+ if (pos) {
|
|
|
+ IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",
|
|
|
+ pci_name(pdev));
|
|
|
+ sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
|
|
|
+ for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)
|
|
|
+ if (pci_read_config_dword(pdev, pos + i, ptr))
|
|
|
+ goto err_read;
|
|
|
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,
|
|
|
+ 4, buf, i, 0);
|
|
|
+ }
|
|
|
+
|
|
|
+err_read:
|
|
|
+ print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
|
|
|
+ IWL_ERR(trans, "Read failed at 0x%X\n", i);
|
|
|
+out:
|
|
|
+ trans_pcie->pcie_dbg_dumped_once = 1;
|
|
|
+ kfree(buf);
|
|
|
+}
|
|
|
+
|
|
|
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
|
|
|
{
|
|
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
@@ -649,6 +736,7 @@ static int iwl_pcie_load_firmware_chunk(struct iwl_trans *trans,
|
|
|
trans_pcie->ucode_write_complete, 5 * HZ);
|
|
|
if (!ret) {
|
|
|
IWL_ERR(trans, "Failed to load firmware chunk!\n");
|
|
|
+ iwl_trans_pcie_err_dump(trans);
|
|
|
return -ETIMEDOUT;
|
|
|
}
|
|
|
|
|
@@ -1868,6 +1956,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans,
|
|
|
(CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
|
|
|
CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
|
|
|
if (unlikely(ret < 0)) {
|
|
|
+ iwl_trans_pcie_err_dump(trans);
|
|
|
iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
|
|
|
WARN_ONCE(1,
|
|
|
"Timeout waiting for hardware access (CSR_GP_CNTRL 0x%08x)\n",
|