File Index
Files and directories
Sign in
FILE

utils.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/wireless/intel/iwlwifi/pcie/utils.c C
  1// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
  2/*
  3 * Copyright (C) 2025 Intel Corporation
  4 */
  5
  6#include <linux/pci.h>
  7#include <linux/gfp.h>
  8
  9#include "iwl-io.h"
 10#include "pcie/utils.h"
 11
 12void iwl_trans_pcie_dump_regs(struct iwl_trans *trans, struct pci_dev *pdev)
 13{
 14#define PCI_DUMP_SIZE		352
 15#define PCI_MEM_DUMP_SIZE	64
 16#define PCI_PARENT_DUMP_SIZE	524
 17#define PREFIX_LEN		32
 18
 19	static bool pcie_dbg_dumped_once = 0;
 20	u32 i, pos, alloc_size, *ptr, *buf;
 21	char *prefix;
 22
 23	if (pcie_dbg_dumped_once)
 24		return;
 25
 26	/* Should be a multiple of 4 */
 27	BUILD_BUG_ON(PCI_DUMP_SIZE > 4096 || PCI_DUMP_SIZE & 0x3);
 28	BUILD_BUG_ON(PCI_MEM_DUMP_SIZE > 4096 || PCI_MEM_DUMP_SIZE & 0x3);
 29	BUILD_BUG_ON(PCI_PARENT_DUMP_SIZE > 4096 || PCI_PARENT_DUMP_SIZE & 0x3);
 30
 31	/* Alloc a max size buffer */
 32	alloc_size = PCI_ERR_ROOT_ERR_SRC +  4 + PREFIX_LEN;
 33	alloc_size = max_t(u32, alloc_size, PCI_DUMP_SIZE + PREFIX_LEN);
 34	alloc_size = max_t(u32, alloc_size, PCI_MEM_DUMP_SIZE + PREFIX_LEN);
 35	alloc_size = max_t(u32, alloc_size, PCI_PARENT_DUMP_SIZE + PREFIX_LEN);
 36
 37	buf = kmalloc(alloc_size, GFP_ATOMIC);
 38	if (!buf)
 39		return;
 40	prefix = (char *)buf + alloc_size - PREFIX_LEN;
 41
 42	IWL_ERR(trans, "iwlwifi transaction failed, dumping registers\n");
 43
 44	/* Print wifi device registers */
 45	sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
 46	IWL_ERR(trans, "iwlwifi device config registers:\n");
 47	for (i = 0, ptr = buf; i < PCI_DUMP_SIZE; i += 4, ptr++)
 48		if (pci_read_config_dword(pdev, i, ptr))
 49			goto err_read;
 50	print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
 51
 52	IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
 53	for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++)
 54		*ptr = iwl_read32(trans, i);
 55	print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
 56
 57	pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
 58	if (pos) {
 59		IWL_ERR(trans, "iwlwifi device AER capability structure:\n");
 60		for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)
 61			if (pci_read_config_dword(pdev, pos + i, ptr))
 62				goto err_read;
 63		print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
 64			       32, 4, buf, i, 0);
 65	}
 66
 67	/* Print parent device registers next */
 68	if (!pdev->bus->self)
 69		goto out;
 70
 71	pdev = pdev->bus->self;
 72	sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
 73
 74	IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
 75		pci_name(pdev));
 76	for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++)
 77		if (pci_read_config_dword(pdev, i, ptr))
 78			goto err_read;
 79	print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
 80
 81	/* Print root port AER registers */
 82	pos = 0;
 83	pdev = pcie_find_root_port(pdev);
 84	if (pdev)
 85		pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
 86	if (pos) {
 87		IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",
 88			pci_name(pdev));
 89		sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
 90		for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)
 91			if (pci_read_config_dword(pdev, pos + i, ptr))
 92				goto err_read;
 93		print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,
 94			       4, buf, i, 0);
 95	}
 96	goto out;
 97
 98err_read:
 99	print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
100	IWL_ERR(trans, "Read failed at 0x%X\n", i);
101out:
102	pcie_dbg_dumped_once = 1;
103	kfree(buf);
104}
~/ Read-only file preview.