|
15 | 15 | #include <linux/pci_ids.h> |
16 | 16 | #include <asm/amd_nb.h> |
17 | 17 |
|
18 | | -/* Protect the PCI config register pairs used for SMN. */ |
19 | | -static DEFINE_MUTEX(smn_mutex); |
20 | | - |
21 | 18 | static u32 *flush_words; |
22 | 19 |
|
23 | 20 | static const struct pci_device_id amd_nb_misc_ids[] = { |
@@ -59,92 +56,6 @@ struct amd_northbridge *node_to_amd_nb(int node) |
59 | 56 | } |
60 | 57 | EXPORT_SYMBOL_GPL(node_to_amd_nb); |
61 | 58 |
|
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 | | - |
148 | 59 | static int amd_cache_northbridges(void) |
149 | 60 | { |
150 | 61 | struct amd_northbridge *nb; |
|
0 commit comments