diff options
Diffstat (limited to 'drivers/edac/amd76x_edac.c')
-rw-r--r-- | drivers/edac/amd76x_edac.c | 98 |
1 files changed, 54 insertions, 44 deletions
diff --git a/drivers/edac/amd76x_edac.c b/drivers/edac/amd76x_edac.c index 35599ed4bad5..d75864e35fef 100644 --- a/drivers/edac/amd76x_edac.c +++ b/drivers/edac/amd76x_edac.c | |||
@@ -19,6 +19,9 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include "edac_mc.h" | 20 | #include "edac_mc.h" |
21 | 21 | ||
22 | #define AMD76X_REVISION " Ver: 2.0.0 " __DATE__ | ||
23 | |||
24 | |||
22 | #define amd76x_printk(level, fmt, arg...) \ | 25 | #define amd76x_printk(level, fmt, arg...) \ |
23 | edac_printk(level, "amd76x", fmt, ##arg) | 26 | edac_printk(level, "amd76x", fmt, ##arg) |
24 | 27 | ||
@@ -101,15 +104,18 @@ static const struct amd76x_dev_info amd76x_devs[] = { | |||
101 | static void amd76x_get_error_info(struct mem_ctl_info *mci, | 104 | static void amd76x_get_error_info(struct mem_ctl_info *mci, |
102 | struct amd76x_error_info *info) | 105 | struct amd76x_error_info *info) |
103 | { | 106 | { |
104 | pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS, | 107 | struct pci_dev *pdev; |
108 | |||
109 | pdev = to_pci_dev(mci->dev); | ||
110 | pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, | ||
105 | &info->ecc_mode_status); | 111 | &info->ecc_mode_status); |
106 | 112 | ||
107 | if (info->ecc_mode_status & BIT(8)) | 113 | if (info->ecc_mode_status & BIT(8)) |
108 | pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, | 114 | pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS, |
109 | (u32) BIT(8), (u32) BIT(8)); | 115 | (u32) BIT(8), (u32) BIT(8)); |
110 | 116 | ||
111 | if (info->ecc_mode_status & BIT(9)) | 117 | if (info->ecc_mode_status & BIT(9)) |
112 | pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS, | 118 | pci_write_bits32(pdev, AMD76X_ECC_MODE_STATUS, |
113 | (u32) BIT(9), (u32) BIT(9)); | 119 | (u32) BIT(9), (u32) BIT(9)); |
114 | } | 120 | } |
115 | 121 | ||
@@ -175,6 +181,38 @@ static void amd76x_check(struct mem_ctl_info *mci) | |||
175 | amd76x_process_error_info(mci, &info, 1); | 181 | amd76x_process_error_info(mci, &info, 1); |
176 | } | 182 | } |
177 | 183 | ||
184 | static void amd76x_init_csrows(struct mem_ctl_info *mci, struct pci_dev *pdev, | ||
185 | enum edac_type edac_mode) | ||
186 | { | ||
187 | struct csrow_info *csrow; | ||
188 | u32 mba, mba_base, mba_mask, dms; | ||
189 | int index; | ||
190 | |||
191 | for (index = 0; index < mci->nr_csrows; index++) { | ||
192 | csrow = &mci->csrows[index]; | ||
193 | |||
194 | /* find the DRAM Chip Select Base address and mask */ | ||
195 | pci_read_config_dword(pdev, | ||
196 | AMD76X_MEM_BASE_ADDR + (index * 4), | ||
197 | &mba); | ||
198 | |||
199 | if (!(mba & BIT(0))) | ||
200 | continue; | ||
201 | |||
202 | mba_base = mba & 0xff800000UL; | ||
203 | mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; | ||
204 | pci_read_config_dword(pdev, AMD76X_DRAM_MODE_STATUS, &dms); | ||
205 | csrow->first_page = mba_base >> PAGE_SHIFT; | ||
206 | csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; | ||
207 | csrow->last_page = csrow->first_page + csrow->nr_pages - 1; | ||
208 | csrow->page_mask = mba_mask >> PAGE_SHIFT; | ||
209 | csrow->grain = csrow->nr_pages << PAGE_SHIFT; | ||
210 | csrow->mtype = MEM_RDDR; | ||
211 | csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; | ||
212 | csrow->edac_mode = edac_mode; | ||
213 | } | ||
214 | } | ||
215 | |||
178 | /** | 216 | /** |
179 | * amd76x_probe1 - Perform set up for detected device | 217 | * amd76x_probe1 - Perform set up for detected device |
180 | * @pdev; PCI device detected | 218 | * @pdev; PCI device detected |
@@ -186,15 +224,13 @@ static void amd76x_check(struct mem_ctl_info *mci) | |||
186 | */ | 224 | */ |
187 | static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) | 225 | static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) |
188 | { | 226 | { |
189 | int rc = -ENODEV; | 227 | static const enum edac_type ems_modes[] = { |
190 | int index; | ||
191 | struct mem_ctl_info *mci = NULL; | ||
192 | enum edac_type ems_modes[] = { | ||
193 | EDAC_NONE, | 228 | EDAC_NONE, |
194 | EDAC_EC, | 229 | EDAC_EC, |
195 | EDAC_SECDED, | 230 | EDAC_SECDED, |
196 | EDAC_SECDED | 231 | EDAC_SECDED |
197 | }; | 232 | }; |
233 | struct mem_ctl_info *mci = NULL; | ||
198 | u32 ems; | 234 | u32 ems; |
199 | u32 ems_mode; | 235 | u32 ems_mode; |
200 | struct amd76x_error_info discard; | 236 | struct amd76x_error_info discard; |
@@ -205,53 +241,28 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) | |||
205 | mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); | 241 | mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS); |
206 | 242 | ||
207 | if (mci == NULL) { | 243 | if (mci == NULL) { |
208 | rc = -ENOMEM; | 244 | return -ENOMEM; |
209 | goto fail; | ||
210 | } | 245 | } |
211 | 246 | ||
212 | debugf0("%s(): mci = %p\n", __func__, mci); | 247 | debugf0("%s(): mci = %p\n", __func__, mci); |
213 | mci->pdev = pdev; | 248 | mci->dev = &pdev->dev; |
214 | mci->mtype_cap = MEM_FLAG_RDDR; | 249 | mci->mtype_cap = MEM_FLAG_RDDR; |
215 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 250 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
216 | mci->edac_cap = ems_mode ? | 251 | mci->edac_cap = ems_mode ? |
217 | (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; | 252 | (EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE; |
218 | mci->mod_name = EDAC_MOD_STR; | 253 | mci->mod_name = EDAC_MOD_STR; |
219 | mci->mod_ver = "$Revision: 1.4.2.5 $"; | 254 | mci->mod_ver = AMD76X_REVISION; |
220 | mci->ctl_name = amd76x_devs[dev_idx].ctl_name; | 255 | mci->ctl_name = amd76x_devs[dev_idx].ctl_name; |
221 | mci->edac_check = amd76x_check; | 256 | mci->edac_check = amd76x_check; |
222 | mci->ctl_page_to_phys = NULL; | 257 | mci->ctl_page_to_phys = NULL; |
223 | 258 | ||
224 | for (index = 0; index < mci->nr_csrows; index++) { | 259 | amd76x_init_csrows(mci, pdev, ems_modes[ems_mode]); |
225 | struct csrow_info *csrow = &mci->csrows[index]; | ||
226 | u32 mba; | ||
227 | u32 mba_base; | ||
228 | u32 mba_mask; | ||
229 | u32 dms; | ||
230 | |||
231 | /* find the DRAM Chip Select Base address and mask */ | ||
232 | pci_read_config_dword(mci->pdev, | ||
233 | AMD76X_MEM_BASE_ADDR + (index * 4), &mba); | ||
234 | |||
235 | if (!(mba & BIT(0))) | ||
236 | continue; | ||
237 | |||
238 | mba_base = mba & 0xff800000UL; | ||
239 | mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL; | ||
240 | pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS, | ||
241 | &dms); | ||
242 | csrow->first_page = mba_base >> PAGE_SHIFT; | ||
243 | csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT; | ||
244 | csrow->last_page = csrow->first_page + csrow->nr_pages - 1; | ||
245 | csrow->page_mask = mba_mask >> PAGE_SHIFT; | ||
246 | csrow->grain = csrow->nr_pages << PAGE_SHIFT; | ||
247 | csrow->mtype = MEM_RDDR; | ||
248 | csrow->dtype = ((dms >> index) & 0x1) ? DEV_X4 : DEV_UNKNOWN; | ||
249 | csrow->edac_mode = ems_modes[ems_mode]; | ||
250 | } | ||
251 | |||
252 | amd76x_get_error_info(mci, &discard); /* clear counters */ | 260 | amd76x_get_error_info(mci, &discard); /* clear counters */ |
253 | 261 | ||
254 | if (edac_mc_add_mc(mci)) { | 262 | /* Here we assume that we will never see multiple instances of this |
263 | * type of memory controller. The ID is therefore hardcoded to 0. | ||
264 | */ | ||
265 | if (edac_mc_add_mc(mci,0)) { | ||
255 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); | 266 | debugf3("%s(): failed edac_mc_add_mc()\n", __func__); |
256 | goto fail; | 267 | goto fail; |
257 | } | 268 | } |
@@ -261,9 +272,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx) | |||
261 | return 0; | 272 | return 0; |
262 | 273 | ||
263 | fail: | 274 | fail: |
264 | if (mci != NULL) | 275 | edac_mc_free(mci); |
265 | edac_mc_free(mci); | 276 | return -ENODEV; |
266 | return rc; | ||
267 | } | 277 | } |
268 | 278 | ||
269 | /* returns count (>= 0), or negative on error */ | 279 | /* returns count (>= 0), or negative on error */ |
@@ -290,7 +300,7 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev) | |||
290 | 300 | ||
291 | debugf0("%s()\n", __func__); | 301 | debugf0("%s()\n", __func__); |
292 | 302 | ||
293 | if ((mci = edac_mc_del_mc(pdev)) == NULL) | 303 | if ((mci = edac_mc_del_mc(&pdev->dev)) == NULL) |
294 | return; | 304 | return; |
295 | 305 | ||
296 | edac_mc_free(mci); | 306 | edac_mc_free(mci); |