Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/iwlwifi/pcie/utils.c
48373 views
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
12
void 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
#if defined(__linux__)
51
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
52
#elif defined(__FreeBSD__)
53
iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);
54
#endif
55
56
IWL_ERR(trans, "iwlwifi device memory mapped registers:\n");
57
for (i = 0, ptr = buf; i < PCI_MEM_DUMP_SIZE; i += 4, ptr++)
58
*ptr = iwl_read32(trans, i);
59
#if defined(__linux__)
60
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
61
#elif defined(__FreeBSD__)
62
iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);
63
#endif
64
65
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
66
if (pos) {
67
IWL_ERR(trans, "iwlwifi device AER capability structure:\n");
68
for (i = 0, ptr = buf; i < PCI_ERR_ROOT_COMMAND; i += 4, ptr++)
69
if (pci_read_config_dword(pdev, pos + i, ptr))
70
goto err_read;
71
#if defined(__linux__)
72
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET,
73
32, 4, buf, i, 0);
74
#elif defined(__FreeBSD__)
75
iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);
76
#endif
77
}
78
79
/* Print parent device registers next */
80
if (!pdev->bus->self)
81
goto out;
82
83
pdev = pdev->bus->self;
84
sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
85
86
IWL_ERR(trans, "iwlwifi parent port (%s) config registers:\n",
87
pci_name(pdev));
88
for (i = 0, ptr = buf; i < PCI_PARENT_DUMP_SIZE; i += 4, ptr++)
89
if (pci_read_config_dword(pdev, i, ptr))
90
goto err_read;
91
#if defined(__linux__)
92
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
93
#elif defined(__FreeBSD__)
94
iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);
95
#endif
96
97
/* Print root port AER registers */
98
pos = 0;
99
pdev = pcie_find_root_port(pdev);
100
if (pdev)
101
pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR);
102
if (pos) {
103
IWL_ERR(trans, "iwlwifi root port (%s) AER cap structure:\n",
104
pci_name(pdev));
105
sprintf(prefix, "iwlwifi %s: ", pci_name(pdev));
106
for (i = 0, ptr = buf; i <= PCI_ERR_ROOT_ERR_SRC; i += 4, ptr++)
107
if (pci_read_config_dword(pdev, pos + i, ptr))
108
goto err_read;
109
#if defined(__linux__)
110
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32,
111
4, buf, i, 0);
112
#elif defined(__FreeBSD__)
113
iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);
114
#endif
115
}
116
goto out;
117
118
err_read:
119
#if defined(__linux__)
120
print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 32, 4, buf, i, 0);
121
#elif defined(__FreeBSD__)
122
iwl_print_hex_dump(NULL, IWL_DL_ANY, prefix, (u8 *)buf, i);
123
#endif
124
IWL_ERR(trans, "Read failed at 0x%X\n", i);
125
out:
126
pcie_dbg_dumped_once = 1;
127
kfree(buf);
128
}
129
130