Skip to content

Commit d6caeaf

Browse files
superm1bp3tk0v
authored andcommitted
x86/amd_nb: Move SMN access code to a new amd_node driver
SMN access was bolted into amd_nb mostly as convenience. This has limitations though that require incurring tech debt to keep it working. Move SMN access to the newly introduced AMD Node driver. Signed-off-by: Mario Limonciello <[email protected]> Signed-off-by: Yazen Ghannam <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Acked-by: Ilpo Järvinen <[email protected]> # pdx86 Acked-by: Shyam Sundar S K <[email protected]> # PMF, PMC Link: https://lore.kernel.org/r/[email protected]
1 parent 7dd57db commit d6caeaf

File tree

16 files changed

+107
-100
lines changed

16 files changed

+107
-100
lines changed

Diff for: MAINTAINERS

+1
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,7 @@ S: Supported
11221122
F: drivers/i2c/busses/i2c-amd-asf-plat.c
11231123

11241124
AMD NODE DRIVER
1125+
M: Mario Limonciello <[email protected]>
11251126
M: Yazen Ghannam <[email protected]>
11261127
11271128
S: Supported

Diff for: arch/x86/include/asm/amd_nb.h

-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ extern int amd_numa_init(void);
2121
extern int amd_get_subcaches(int);
2222
extern int amd_set_subcaches(int, unsigned long);
2323

24-
int __must_check amd_smn_read(u16 node, u32 address, u32 *value);
25-
int __must_check amd_smn_write(u16 node, u32 address, u32 value);
26-
2724
struct amd_l3_cache {
2825
unsigned indices;
2926
u8 subcaches[4];

Diff for: arch/x86/include/asm/amd_node.h

+3
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,7 @@ static inline u16 amd_num_nodes(void)
3030
return topology_amd_nodes_per_pkg() * topology_max_packages();
3131
}
3232

33+
int __must_check amd_smn_read(u16 node, u32 address, u32 *value);
34+
int __must_check amd_smn_write(u16 node, u32 address, u32 value);
35+
3336
#endif /*_ASM_X86_AMD_NODE_H_*/

Diff for: arch/x86/kernel/amd_nb.c

-89
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,6 @@
1515
#include <linux/pci_ids.h>
1616
#include <asm/amd_nb.h>
1717

18-
/* Protect the PCI config register pairs used for SMN. */
19-
static DEFINE_MUTEX(smn_mutex);
20-
2118
static u32 *flush_words;
2219

2320
static const struct pci_device_id amd_nb_misc_ids[] = {
@@ -59,92 +56,6 @@ struct amd_northbridge *node_to_amd_nb(int node)
5956
}
6057
EXPORT_SYMBOL_GPL(node_to_amd_nb);
6158

62-
/*
63-
* SMN accesses may fail in ways that are difficult to detect here in the called
64-
* functions amd_smn_read() and amd_smn_write(). Therefore, callers must do
65-
* their own checking based on what behavior they expect.
66-
*
67-
* For SMN reads, the returned value may be zero if the register is Read-as-Zero.
68-
* Or it may be a "PCI Error Response", e.g. all 0xFFs. The "PCI Error Response"
69-
* can be checked here, and a proper error code can be returned.
70-
*
71-
* But the Read-as-Zero response cannot be verified here. A value of 0 may be
72-
* correct in some cases, so callers must check that this correct is for the
73-
* register/fields they need.
74-
*
75-
* For SMN writes, success can be determined through a "write and read back"
76-
* However, this is not robust when done here.
77-
*
78-
* Possible issues:
79-
*
80-
* 1) Bits that are "Write-1-to-Clear". In this case, the read value should
81-
* *not* match the write value.
82-
*
83-
* 2) Bits that are "Read-as-Zero"/"Writes-Ignored". This information cannot be
84-
* known here.
85-
*
86-
* 3) Bits that are "Reserved / Set to 1". Ditto above.
87-
*
88-
* Callers of amd_smn_write() should do the "write and read back" check
89-
* themselves, if needed.
90-
*
91-
* For #1, they can see if their target bits got cleared.
92-
*
93-
* For #2 and #3, they can check if their target bits got set as intended.
94-
*
95-
* This matches what is done for RDMSR/WRMSR. As long as there's no #GP, then
96-
* the operation is considered a success, and the caller does their own
97-
* checking.
98-
*/
99-
static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
100-
{
101-
struct pci_dev *root;
102-
int err = -ENODEV;
103-
104-
if (node >= amd_northbridges.num)
105-
goto out;
106-
107-
root = node_to_amd_nb(node)->root;
108-
if (!root)
109-
goto out;
110-
111-
mutex_lock(&smn_mutex);
112-
113-
err = pci_write_config_dword(root, 0x60, address);
114-
if (err) {
115-
pr_warn("Error programming SMN address 0x%x.\n", address);
116-
goto out_unlock;
117-
}
118-
119-
err = (write ? pci_write_config_dword(root, 0x64, *value)
120-
: pci_read_config_dword(root, 0x64, value));
121-
122-
out_unlock:
123-
mutex_unlock(&smn_mutex);
124-
125-
out:
126-
return err;
127-
}
128-
129-
int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
130-
{
131-
int err = __amd_smn_rw(node, address, value, false);
132-
133-
if (PCI_POSSIBLE_ERROR(*value)) {
134-
err = -ENODEV;
135-
*value = 0;
136-
}
137-
138-
return err;
139-
}
140-
EXPORT_SYMBOL_GPL(amd_smn_read);
141-
142-
int __must_check amd_smn_write(u16 node, u32 address, u32 value)
143-
{
144-
return __amd_smn_rw(node, address, &value, true);
145-
}
146-
EXPORT_SYMBOL_GPL(amd_smn_write);
147-
14859
static int amd_cache_northbridges(void)
14960
{
15061
struct amd_northbridge *nb;

Diff for: arch/x86/kernel/amd_node.c

+90
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
* Author: Yazen Ghannam <[email protected]>
99
*/
1010

11+
#include <asm/amd_nb.h>
1112
#include <asm/amd_node.h>
1213

1314
/*
@@ -88,3 +89,92 @@ struct pci_dev *amd_node_get_root(u16 node)
8889
pci_dbg(root, "is root for AMD node %u\n", node);
8990
return root;
9091
}
92+
93+
/* Protect the PCI config register pairs used for SMN. */
94+
static DEFINE_MUTEX(smn_mutex);
95+
96+
/*
97+
* SMN accesses may fail in ways that are difficult to detect here in the called
98+
* functions amd_smn_read() and amd_smn_write(). Therefore, callers must do
99+
* their own checking based on what behavior they expect.
100+
*
101+
* For SMN reads, the returned value may be zero if the register is Read-as-Zero.
102+
* Or it may be a "PCI Error Response", e.g. all 0xFFs. The "PCI Error Response"
103+
* can be checked here, and a proper error code can be returned.
104+
*
105+
* But the Read-as-Zero response cannot be verified here. A value of 0 may be
106+
* correct in some cases, so callers must check that this correct is for the
107+
* register/fields they need.
108+
*
109+
* For SMN writes, success can be determined through a "write and read back"
110+
* However, this is not robust when done here.
111+
*
112+
* Possible issues:
113+
*
114+
* 1) Bits that are "Write-1-to-Clear". In this case, the read value should
115+
* *not* match the write value.
116+
*
117+
* 2) Bits that are "Read-as-Zero"/"Writes-Ignored". This information cannot be
118+
* known here.
119+
*
120+
* 3) Bits that are "Reserved / Set to 1". Ditto above.
121+
*
122+
* Callers of amd_smn_write() should do the "write and read back" check
123+
* themselves, if needed.
124+
*
125+
* For #1, they can see if their target bits got cleared.
126+
*
127+
* For #2 and #3, they can check if their target bits got set as intended.
128+
*
129+
* This matches what is done for RDMSR/WRMSR. As long as there's no #GP, then
130+
* the operation is considered a success, and the caller does their own
131+
* checking.
132+
*/
133+
static int __amd_smn_rw(u16 node, u32 address, u32 *value, bool write)
134+
{
135+
struct pci_dev *root;
136+
int err = -ENODEV;
137+
138+
if (node >= amd_nb_num())
139+
goto out;
140+
141+
root = node_to_amd_nb(node)->root;
142+
if (!root)
143+
goto out;
144+
145+
mutex_lock(&smn_mutex);
146+
147+
err = pci_write_config_dword(root, 0x60, address);
148+
if (err) {
149+
pr_warn("Error programming SMN address 0x%x.\n", address);
150+
goto out_unlock;
151+
}
152+
153+
err = (write ? pci_write_config_dword(root, 0x64, *value)
154+
: pci_read_config_dword(root, 0x64, value));
155+
156+
out_unlock:
157+
mutex_unlock(&smn_mutex);
158+
159+
out:
160+
return err;
161+
}
162+
163+
int __must_check amd_smn_read(u16 node, u32 address, u32 *value)
164+
{
165+
int err = __amd_smn_rw(node, address, value, false);
166+
167+
if (PCI_POSSIBLE_ERROR(*value)) {
168+
err = -ENODEV;
169+
*value = 0;
170+
}
171+
172+
return err;
173+
}
174+
EXPORT_SYMBOL_GPL(amd_smn_read);
175+
176+
int __must_check amd_smn_write(u16 node, u32 address, u32 value)
177+
{
178+
return __amd_smn_rw(node, address, &value, true);
179+
}
180+
EXPORT_SYMBOL_GPL(amd_smn_write);

Diff for: arch/x86/pci/fixup.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
#include <linux/pci.h>
1010
#include <linux/suspend.h>
1111
#include <linux/vgaarb.h>
12-
#include <asm/amd_nb.h>
12+
#include <asm/amd_node.h>
1313
#include <asm/hpet.h>
1414
#include <asm/pci_x86.h>
1515

@@ -828,7 +828,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7910, rs690_fix_64bit_dma);
828828

829829
#endif
830830

831-
#ifdef CONFIG_AMD_NB
831+
#ifdef CONFIG_AMD_NODE
832832

833833
#define AMD_15B8_RCC_DEV2_EPF0_STRAP2 0x10136008
834834
#define AMD_15B8_RCC_DEV2_EPF0_STRAP2_NO_SOFT_RESET_DEV2_F0_MASK 0x00000080L

Diff for: drivers/edac/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ config EDAC_GHES
7878
config EDAC_AMD64
7979
tristate "AMD64 (Opteron, Athlon64)"
8080
depends on AMD_NB && EDAC_DECODE_MCE
81+
depends on AMD_NODE
8182
imply AMD_ATL
8283
help
8384
Support for error detection and correction of DRAM ECC errors on

Diff for: drivers/edac/amd64_edac.c

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <linux/ras.h>
33
#include "amd64_edac.h"
44
#include <asm/amd_nb.h>
5+
#include <asm/amd_node.h>
56

67
static struct edac_pci_ctl_info *pci_ctl;
78

Diff for: drivers/hwmon/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ config SENSORS_K8TEMP
324324

325325
config SENSORS_K10TEMP
326326
tristate "AMD Family 10h+ temperature sensor"
327-
depends on X86 && PCI && AMD_NB
327+
depends on X86 && PCI && AMD_NODE
328328
help
329329
If you say yes here you get support for the temperature
330330
sensor(s) inside your CPU. Supported are later revisions of

Diff for: drivers/hwmon/k10temp.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#include <linux/module.h>
2121
#include <linux/pci.h>
2222
#include <linux/pci_ids.h>
23-
#include <asm/amd_nb.h>
23+
#include <asm/amd_node.h>
2424
#include <asm/processor.h>
2525

2626
MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor");

Diff for: drivers/platform/x86/amd/pmc/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
config AMD_PMC
77
tristate "AMD SoC PMC driver"
8-
depends on ACPI && PCI && RTC_CLASS && AMD_NB
8+
depends on ACPI && PCI && RTC_CLASS && AMD_NODE
99
depends on SUSPEND
1010
select SERIO
1111
help

Diff for: drivers/platform/x86/amd/pmc/pmc.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010

1111
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1212

13-
#include <asm/amd_nb.h>
1413
#include <linux/acpi.h>
1514
#include <linux/bitfield.h>
1615
#include <linux/bits.h>
@@ -28,6 +27,8 @@
2827
#include <linux/seq_file.h>
2928
#include <linux/uaccess.h>
3029

30+
#include <asm/amd_node.h>
31+
3132
#include "pmc.h"
3233

3334
/* SMU communication registers */

Diff for: drivers/platform/x86/amd/pmf/Kconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ config AMD_PMF
77
tristate "AMD Platform Management Framework"
88
depends on ACPI && PCI
99
depends on POWER_SUPPLY
10-
depends on AMD_NB
10+
depends on AMD_NODE
1111
select ACPI_PLATFORM_PROFILE
1212
depends on TEE && AMDTEE
1313
depends on AMD_SFH_HID

Diff for: drivers/platform/x86/amd/pmf/core.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
* Author: Shyam Sundar S K <[email protected]>
99
*/
1010

11-
#include <asm/amd_nb.h>
1211
#include <linux/debugfs.h>
1312
#include <linux/iopoll.h>
1413
#include <linux/module.h>
1514
#include <linux/pci.h>
1615
#include <linux/platform_device.h>
1716
#include <linux/power_supply.h>
17+
#include <asm/amd_node.h>
1818
#include "pmf.h"
1919

2020
/* PMF-SMU communication registers */

Diff for: drivers/ras/amd/atl/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
config AMD_ATL
1111
tristate "AMD Address Translation Library"
1212
depends on AMD_NB && X86_64 && RAS
13+
depends on AMD_NODE
1314
depends on MEMORY_FAILURE
1415
default N
1516
help

Diff for: drivers/ras/amd/atl/internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/ras.h>
1919

2020
#include <asm/amd_nb.h>
21+
#include <asm/amd_node.h>
2122

2223
#include "reg_fields.h"
2324

0 commit comments

Comments
 (0)