Path: blob/main/sys/contrib/dev/iwlwifi/pcie/utils.c
48373 views
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause1/*2* Copyright (C) 2025 Intel Corporation3*/45#include <linux/pci.h>6#include <linux/gfp.h>78#include "iwl-io.h"9#include "pcie/utils.h"1011void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev)12{13#define PCI_DUMP_SIZE 35214#define PCI_MEM_DUMP_SIZE 6415#define PCI_PARENT_DUMP_SIZE 52416#define PREFIX_LEN 321718static bool pcie_dbg_dumped_once = 0;19u32 i, pos, alloc_size, *ptr, *buf;20char *prefix;2122if (pcie_dbg_dumped_once)23return;2425/* Should be a multiple of 4 */26BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);27BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3);28BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3);2930/* Alloc a max size buffer */31alloc_size = PCI_ERR_ROOT_ERR_SRC + 4 + PREFIX_LEN;32alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN);33alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN);34alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN);3536buf = kmalloc(alloc_size, GFP_ATOMIC);37if (!buf)38return;39prefix = (char *)buf + alloc_size - PREFIX_LEN;4041IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n");4243/* Print wifi device registers */44sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));45IWL_ERR(trans, "iwlwifi device config registers:\n");46for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)47if (pci_read_config_dword(pdev, i, ptr))48goto err_read;49#if defined(__linux__)50print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);51#elif defined(__FreeBSD__)52iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);53#endif5455IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");56for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++)57*ptr = iwl_read32(trans, i);58#if defined(__linux__)59print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);60#elif defined(__FreeBSD__)61iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);62#endif6364pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);65if (pos) {66IWL_ERR(trans, "iwlwifi device AER capability structure:\n");67for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)68if (pci_read_config_dword(pdev, pos + i, ptr))69goto err_read;70#if defined(__linux__)71print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,7232, 4, buf, i, 0);73#elif defined(__FreeBSD__)74iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);75#endif76}7778/* Print parent device registers next */79if (!pdev->bus->self)80goto out;8182pdev = pdev->bus->self;83sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));8485IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",86pci_name(pdev));87for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++)88if (pci_read_config_dword(pdev, i, ptr))89goto err_read;90#if defined(__linux__)91print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);92#elif defined(__FreeBSD__)93iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);94#endif9596/* Print root port AER registers */97pos = 0;98pdev = pcie_find_root_port(pdev);99if (pdev)100pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);101if (pos) {102IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",103pci_name(pdev));104sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));105for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)106if (pci_read_config_dword(pdev, pos + i, ptr))107goto err_read;108#if defined(__linux__)109print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,1104, buf, i, 0);111#elif defined(__FreeBSD__)112iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);113#endif114}115goto out;116117err_read:118#if defined(__linux__)119print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);120#elif defined(__FreeBSD__)121iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);122#endif123IWL_ERR(trans, "Read failed at 0x%X\n", i);124out:125pcie_dbg_dumped_once = 1;126kfree(buf);127}128129130