Skip to content

Commit 40a5f6f

Browse files
yghannambp3tk0v
authored andcommitted
x86/amd_nb: Simplify root device search
The "root" device search was introduced to support SMN access for Zen systems. This device represents a PCIe root complex. It is not the same as the "CPU/node" devices found at slots 0x18-0x1F. There may be multiple PCIe root complexes within an AMD node. Such is the case with server or High-end Desktop (HEDT) systems, etc. Therefore it is not enough to assume "root <-> AMD node" is a 1-to-1 association. Currently, this is handled by skipping "extra" root complexes during the search. However, the hardware provides the PCI bus number of an AMD node's root device. Use the hardware info to get the root device's bus and drop the extra search code and PCI IDs. Signed-off-by: Yazen Ghannam <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 962f197 commit 40a5f6f

File tree

3 files changed

+61
-76
lines changed

3 files changed

+61
-76
lines changed

arch/x86/include/asm/amd_node.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,6 @@
2323
#define AMD_NODE0_PCI_SLOT 0x18
2424

2525
struct pci_dev *amd_node_get_func(u16 node, u8 func);
26+
struct pci_dev *amd_node_get_root(u16 node);
2627

2728
#endif /*_ASM_X86_AMD_NODE_H_*/

arch/x86/kernel/amd_nb.c

Lines changed: 4 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -15,44 +15,11 @@
1515
#include <linux/pci_ids.h>
1616
#include <asm/amd_nb.h>
1717

18-
#define PCI_DEVICE_ID_AMD_17H_ROOT 0x1450
19-
#define PCI_DEVICE_ID_AMD_17H_M10H_ROOT 0x15d0
20-
#define PCI_DEVICE_ID_AMD_17H_M30H_ROOT 0x1480
21-
#define PCI_DEVICE_ID_AMD_17H_M60H_ROOT 0x1630
22-
#define PCI_DEVICE_ID_AMD_17H_MA0H_ROOT 0x14b5
23-
#define PCI_DEVICE_ID_AMD_19H_M10H_ROOT 0x14a4
24-
#define PCI_DEVICE_ID_AMD_19H_M40H_ROOT 0x14b5
25-
#define PCI_DEVICE_ID_AMD_19H_M60H_ROOT 0x14d8
26-
#define PCI_DEVICE_ID_AMD_19H_M70H_ROOT 0x14e8
27-
#define PCI_DEVICE_ID_AMD_1AH_M00H_ROOT 0x153a
28-
#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
29-
#define PCI_DEVICE_ID_AMD_1AH_M60H_ROOT 0x1122
30-
#define PCI_DEVICE_ID_AMD_MI200_ROOT 0x14bb
31-
#define PCI_DEVICE_ID_AMD_MI300_ROOT 0x14f8
32-
3318
/* Protect the PCI config register pairs used for SMN. */
3419
static DEFINE_MUTEX(smn_mutex);
3520

3621
static u32 *flush_words;
3722

38-
static const struct pci_device_id amd_root_ids[] = {
39-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_ROOT) },
40-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M10H_ROOT) },
41-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M30H_ROOT) },
42-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_M60H_ROOT) },
43-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_MA0H_ROOT) },
44-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M10H_ROOT) },
45-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M40H_ROOT) },
46-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M60H_ROOT) },
47-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_19H_M70H_ROOT) },
48-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M00H_ROOT) },
49-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
50-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M60H_ROOT) },
51-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI200_ROOT) },
52-
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_MI300_ROOT) },
53-
{}
54-
};
55-
5623
static const struct pci_device_id amd_nb_misc_ids[] = {
5724
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
5825
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
@@ -85,11 +52,6 @@ static const struct pci_device_id amd_nb_misc_ids[] = {
8552
{}
8653
};
8754

88-
static const struct pci_device_id hygon_root_ids[] = {
89-
{ PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_ROOT) },
90-
{}
91-
};
92-
9355
static const struct pci_device_id hygon_nb_misc_ids[] = {
9456
{ PCI_DEVICE(PCI_VENDOR_ID_HYGON, PCI_DEVICE_ID_AMD_17H_DF_F3) },
9557
{}
@@ -222,19 +184,15 @@ EXPORT_SYMBOL_GPL(amd_smn_write);
222184
static int amd_cache_northbridges(void)
223185
{
224186
const struct pci_device_id *misc_ids = amd_nb_misc_ids;
225-
const struct pci_device_id *root_ids = amd_root_ids;
226-
struct pci_dev *root, *misc;
187+
struct pci_dev *misc;
227188
struct amd_northbridge *nb;
228-
u16 roots_per_misc = 0;
229189
u16 misc_count = 0;
230-
u16 root_count = 0;
231-
u16 i, j;
190+
u16 i;
232191

233192
if (amd_northbridges.num)
234193
return 0;
235194

236195
if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
237-
root_ids = hygon_root_ids;
238196
misc_ids = hygon_nb_misc_ids;
239197
}
240198

@@ -245,49 +203,19 @@ static int amd_cache_northbridges(void)
245203
if (!misc_count)
246204
return -ENODEV;
247205

248-
root = NULL;
249-
while ((root = next_northbridge(root, root_ids)))
250-
root_count++;
251-
252-
if (root_count) {
253-
roots_per_misc = root_count / misc_count;
254-
255-
/*
256-
* There should be _exactly_ N roots for each DF/SMN
257-
* interface.
258-
*/
259-
if (!roots_per_misc || (root_count % roots_per_misc)) {
260-
pr_info("Unsupported AMD DF/PCI configuration found\n");
261-
return -ENODEV;
262-
}
263-
}
264-
265206
nb = kcalloc(misc_count, sizeof(struct amd_northbridge), GFP_KERNEL);
266207
if (!nb)
267208
return -ENOMEM;
268209

269210
amd_northbridges.nb = nb;
270211
amd_northbridges.num = misc_count;
271212

272-
misc = root = NULL;
213+
misc = NULL;
273214
for (i = 0; i < amd_northbridges.num; i++) {
274-
node_to_amd_nb(i)->root = root =
275-
next_northbridge(root, root_ids);
215+
node_to_amd_nb(i)->root = amd_node_get_root(i);
276216
node_to_amd_nb(i)->misc = misc =
277217
next_northbridge(misc, misc_ids);
278218
node_to_amd_nb(i)->link = amd_node_get_func(i, 4);
279-
280-
/*
281-
* If there are more PCI root devices than data fabric/
282-
* system management network interfaces, then the (N)
283-
* PCI roots per DF/SMN interface are functionally the
284-
* same (for DF/SMN access) and N-1 are redundant. N-1
285-
* PCI roots should be skipped per DF/SMN interface so
286-
* the following DF/SMN interfaces get mapped to
287-
* correct PCI roots.
288-
*/
289-
for (j = 1; j < roots_per_misc; j++)
290-
root = next_northbridge(root, root_ids);
291219
}
292220

293221
if (amd_gart_present())

arch/x86/kernel/amd_node.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,59 @@ struct pci_dev *amd_node_get_func(u16 node, u8 func)
3232

3333
return pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(AMD_NODE0_PCI_SLOT + node, func));
3434
}
35+
36+
#define DF_BLK_INST_CNT 0x040
37+
#define DF_CFG_ADDR_CNTL_LEGACY 0x084
38+
#define DF_CFG_ADDR_CNTL_DF4 0xC04
39+
40+
#define DF_MAJOR_REVISION GENMASK(27, 24)
41+
42+
static u16 get_cfg_addr_cntl_offset(struct pci_dev *df_f0)
43+
{
44+
u32 reg;
45+
46+
/*
47+
* Revision fields added for DF4 and later.
48+
*
49+
* Major revision of '0' is found pre-DF4. Field is Read-as-Zero.
50+
*/
51+
if (pci_read_config_dword(df_f0, DF_BLK_INST_CNT, &reg))
52+
return 0;
53+
54+
if (reg & DF_MAJOR_REVISION)
55+
return DF_CFG_ADDR_CNTL_DF4;
56+
57+
return DF_CFG_ADDR_CNTL_LEGACY;
58+
}
59+
60+
struct pci_dev *amd_node_get_root(u16 node)
61+
{
62+
struct pci_dev *root;
63+
u16 cntl_off;
64+
u8 bus;
65+
66+
if (!cpu_feature_enabled(X86_FEATURE_ZEN))
67+
return NULL;
68+
69+
/*
70+
* D18F0xXXX [Config Address Control] (DF::CfgAddressCntl)
71+
* Bits [7:0] (SecBusNum) holds the bus number of the root device for
72+
* this Data Fabric instance. The segment, device, and function will be 0.
73+
*/
74+
struct pci_dev *df_f0 __free(pci_dev_put) = amd_node_get_func(node, 0);
75+
if (!df_f0)
76+
return NULL;
77+
78+
cntl_off = get_cfg_addr_cntl_offset(df_f0);
79+
if (!cntl_off)
80+
return NULL;
81+
82+
if (pci_read_config_byte(df_f0, cntl_off, &bus))
83+
return NULL;
84+
85+
/* Grab the pointer for the actual root device instance. */
86+
root = pci_get_domain_bus_and_slot(0, bus, 0);
87+
88+
pci_dbg(root, "is root for AMD node %u\n", node);
89+
return root;
90+
}

0 commit comments

Comments
 (0)