aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/i82860_edac.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac/i82860_edac.c')
-rw-r--r--drivers/edac/i82860_edac.c127
1 files changed, 76 insertions, 51 deletions
diff --git a/drivers/edac/i82860_edac.c b/drivers/edac/i82860_edac.c
index 52596e75f9c2..fd342163cf97 100644
--- a/drivers/edac/i82860_edac.c
+++ b/drivers/edac/i82860_edac.c
@@ -9,7 +9,6 @@
9 * by Thayne Harbaugh of Linux Networx. (http://lnxi.com) 9 * by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
10 */ 10 */
11 11
12
13#include <linux/config.h> 12#include <linux/config.h>
14#include <linux/module.h> 13#include <linux/module.h>
15#include <linux/init.h> 14#include <linux/init.h>
@@ -18,6 +17,11 @@
18#include <linux/slab.h> 17#include <linux/slab.h>
19#include "edac_mc.h" 18#include "edac_mc.h"
20 19
20#define i82860_printk(level, fmt, arg...) \
21 edac_printk(level, "i82860", fmt, ##arg)
22
23#define i82860_mc_printk(mci, level, fmt, arg...) \
24 edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
21 25
22#ifndef PCI_DEVICE_ID_INTEL_82860_0 26#ifndef PCI_DEVICE_ID_INTEL_82860_0
23#define PCI_DEVICE_ID_INTEL_82860_0 0x2531 27#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
@@ -48,15 +52,15 @@ struct i82860_error_info {
48 52
49static const struct i82860_dev_info i82860_devs[] = { 53static const struct i82860_dev_info i82860_devs[] = {
50 [I82860] = { 54 [I82860] = {
51 .ctl_name = "i82860"}, 55 .ctl_name = "i82860"
56 },
52}; 57};
53 58
54static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code 59static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
55 has already registered driver */ 60 * has already registered driver
61 */
56 62
57static int i82860_registered = 1; 63static void i82860_get_error_info(struct mem_ctl_info *mci,
58
59static void i82860_get_error_info (struct mem_ctl_info *mci,
60 struct i82860_error_info *info) 64 struct i82860_error_info *info)
61{ 65{
62 /* 66 /*
@@ -78,14 +82,15 @@ static void i82860_get_error_info (struct mem_ctl_info *mci,
78 */ 82 */
79 if (!(info->errsts2 & 0x0003)) 83 if (!(info->errsts2 & 0x0003))
80 return; 84 return;
85
81 if ((info->errsts ^ info->errsts2) & 0x0003) { 86 if ((info->errsts ^ info->errsts2) & 0x0003) {
82 pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap); 87 pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
83 pci_read_config_word(mci->pdev, I82860_DERRCTL_STS, 88 pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
84 &info->derrsyn); 89 &info->derrsyn);
85 } 90 }
86} 91}
87 92
88static int i82860_process_error_info (struct mem_ctl_info *mci, 93static int i82860_process_error_info(struct mem_ctl_info *mci,
89 struct i82860_error_info *info, int handle_errors) 94 struct i82860_error_info *info, int handle_errors)
90{ 95{
91 int row; 96 int row;
@@ -107,8 +112,8 @@ static int i82860_process_error_info (struct mem_ctl_info *mci,
107 if (info->errsts & 0x0002) 112 if (info->errsts & 0x0002)
108 edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE"); 113 edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
109 else 114 else
110 edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 115 edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0,
111 0, "i82860 UE"); 116 "i82860 UE");
112 117
113 return 1; 118 return 1;
114} 119}
@@ -117,7 +122,7 @@ static void i82860_check(struct mem_ctl_info *mci)
117{ 122{
118 struct i82860_error_info info; 123 struct i82860_error_info info;
119 124
120 debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); 125 debugf1("MC%d: %s()\n", mci->mc_idx, __func__);
121 i82860_get_error_info(mci, &info); 126 i82860_get_error_info(mci, &info);
122 i82860_process_error_info(mci, &info, 1); 127 i82860_process_error_info(mci, &info, 1);
123} 128}
@@ -128,6 +133,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
128 int index; 133 int index;
129 struct mem_ctl_info *mci = NULL; 134 struct mem_ctl_info *mci = NULL;
130 unsigned long last_cumul_size; 135 unsigned long last_cumul_size;
136 struct i82860_error_info discard;
131 137
132 u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */ 138 u16 mchcfg_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
133 139
@@ -140,21 +146,20 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
140 going to make 1 channel for group. 146 going to make 1 channel for group.
141 */ 147 */
142 mci = edac_mc_alloc(0, 16, 1); 148 mci = edac_mc_alloc(0, 16, 1);
149
143 if (!mci) 150 if (!mci)
144 return -ENOMEM; 151 return -ENOMEM;
145 152
146 debugf3("MC: " __FILE__ ": %s(): init mci\n", __func__); 153 debugf3("%s(): init mci\n", __func__);
147
148 mci->pdev = pdev; 154 mci->pdev = pdev;
149 mci->mtype_cap = MEM_FLAG_DDR; 155 mci->mtype_cap = MEM_FLAG_DDR;
150 156
151
152 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED; 157 mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
153 /* I"m not sure about this but I think that all RDRAM is SECDED */ 158 /* I"m not sure about this but I think that all RDRAM is SECDED */
154 mci->edac_cap = EDAC_FLAG_SECDED; 159 mci->edac_cap = EDAC_FLAG_SECDED;
155 /* adjust FLAGS */ 160 /* adjust FLAGS */
156 161
157 mci->mod_name = BS_MOD_STR; 162 mci->mod_name = EDAC_MOD_STR;
158 mci->mod_ver = "$Revision: 1.1.2.6 $"; 163 mci->mod_ver = "$Revision: 1.1.2.6 $";
159 mci->ctl_name = i82860_devs[dev_idx].ctl_name; 164 mci->ctl_name = i82860_devs[dev_idx].ctl_name;
160 mci->edac_check = i82860_check; 165 mci->edac_check = i82860_check;
@@ -175,12 +180,13 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
175 struct csrow_info *csrow = &mci->csrows[index]; 180 struct csrow_info *csrow = &mci->csrows[index];
176 181
177 pci_read_config_word(mci->pdev, I82860_GBA + index * 2, 182 pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
178 &value); 183 &value);
179 184
180 cumul_size = (value & I82860_GBA_MASK) << 185 cumul_size = (value & I82860_GBA_MASK) <<
181 (I82860_GBA_SHIFT - PAGE_SHIFT); 186 (I82860_GBA_SHIFT - PAGE_SHIFT);
182 debugf3("MC: " __FILE__ ": %s(): (%d) cumul_size 0x%x\n", 187 debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
183 __func__, index, cumul_size); 188 cumul_size);
189
184 if (cumul_size == last_cumul_size) 190 if (cumul_size == last_cumul_size)
185 continue; /* not populated */ 191 continue; /* not populated */
186 192
@@ -188,42 +194,43 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
188 csrow->last_page = cumul_size - 1; 194 csrow->last_page = cumul_size - 1;
189 csrow->nr_pages = cumul_size - last_cumul_size; 195 csrow->nr_pages = cumul_size - last_cumul_size;
190 last_cumul_size = cumul_size; 196 last_cumul_size = cumul_size;
191 csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */ 197 csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
192 csrow->mtype = MEM_RMBS; 198 csrow->mtype = MEM_RMBS;
193 csrow->dtype = DEV_UNKNOWN; 199 csrow->dtype = DEV_UNKNOWN;
194 csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE; 200 csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
195 } 201 }
196 202
197 /* clear counters */ 203 i82860_get_error_info(mci, &discard); /* clear counters */
198 pci_write_bits16(mci->pdev, I82860_ERRSTS, 0x0003, 0x0003);
199 204
200 if (edac_mc_add_mc(mci)) { 205 if (edac_mc_add_mc(mci)) {
201 debugf3("MC: " __FILE__ 206 debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
202 ": %s(): failed edac_mc_add_mc()\n",
203 __func__);
204 edac_mc_free(mci); 207 edac_mc_free(mci);
205 } else { 208 } else {
206 /* get this far and it's successful */ 209 /* get this far and it's successful */
207 debugf3("MC: " __FILE__ ": %s(): success\n", __func__); 210 debugf3("%s(): success\n", __func__);
208 rc = 0; 211 rc = 0;
209 } 212 }
213
210 return rc; 214 return rc;
211} 215}
212 216
213/* returns count (>= 0), or negative on error */ 217/* returns count (>= 0), or negative on error */
214static int __devinit i82860_init_one(struct pci_dev *pdev, 218static int __devinit i82860_init_one(struct pci_dev *pdev,
215 const struct pci_device_id *ent) 219 const struct pci_device_id *ent)
216{ 220{
217 int rc; 221 int rc;
218 222
219 debugf0("MC: " __FILE__ ": %s()\n", __func__); 223 debugf0("%s()\n", __func__);
224 i82860_printk(KERN_INFO, "i82860 init one\n");
220 225
221 printk(KERN_INFO "i82860 init one\n"); 226 if (pci_enable_device(pdev) < 0)
222 if(pci_enable_device(pdev) < 0)
223 return -EIO; 227 return -EIO;
228
224 rc = i82860_probe1(pdev, ent->driver_data); 229 rc = i82860_probe1(pdev, ent->driver_data);
225 if(rc == 0) 230
231 if (rc == 0)
226 mci_pdev = pci_dev_get(pdev); 232 mci_pdev = pci_dev_get(pdev);
233
227 return rc; 234 return rc;
228} 235}
229 236
@@ -231,23 +238,28 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev)
231{ 238{
232 struct mem_ctl_info *mci; 239 struct mem_ctl_info *mci;
233 240
234 debugf0(__FILE__ ": %s()\n", __func__); 241 debugf0("%s()\n", __func__);
235 242
236 mci = edac_mc_find_mci_by_pdev(pdev); 243 if ((mci = edac_mc_del_mc(pdev)) == NULL)
237 if ((mci != NULL) && (edac_mc_del_mc(mci) == 0)) 244 return;
238 edac_mc_free(mci); 245
246 edac_mc_free(mci);
239} 247}
240 248
241static const struct pci_device_id i82860_pci_tbl[] __devinitdata = { 249static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
242 {PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0, 250 {
243 I82860}, 251 PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
244 {0,} /* 0 terminated list. */ 252 I82860
253 },
254 {
255 0,
256 } /* 0 terminated list. */
245}; 257};
246 258
247MODULE_DEVICE_TABLE(pci, i82860_pci_tbl); 259MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
248 260
249static struct pci_driver i82860_driver = { 261static struct pci_driver i82860_driver = {
250 .name = BS_MOD_STR, 262 .name = EDAC_MOD_STR,
251 .probe = i82860_init_one, 263 .probe = i82860_init_one,
252 .remove = __devexit_p(i82860_remove_one), 264 .remove = __devexit_p(i82860_remove_one),
253 .id_table = i82860_pci_tbl, 265 .id_table = i82860_pci_tbl,
@@ -257,43 +269,56 @@ static int __init i82860_init(void)
257{ 269{
258 int pci_rc; 270 int pci_rc;
259 271
260 debugf3("MC: " __FILE__ ": %s()\n", __func__); 272 debugf3("%s()\n", __func__);
273
261 if ((pci_rc = pci_register_driver(&i82860_driver)) < 0) 274 if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
262 return pci_rc; 275 goto fail0;
263 276
264 if (!mci_pdev) { 277 if (!mci_pdev) {
265 i82860_registered = 0;
266 mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 278 mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
267 PCI_DEVICE_ID_INTEL_82860_0, NULL); 279 PCI_DEVICE_ID_INTEL_82860_0, NULL);
280
268 if (mci_pdev == NULL) { 281 if (mci_pdev == NULL) {
269 debugf0("860 pci_get_device fail\n"); 282 debugf0("860 pci_get_device fail\n");
270 return -ENODEV; 283 pci_rc = -ENODEV;
284 goto fail1;
271 } 285 }
286
272 pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl); 287 pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
288
273 if (pci_rc < 0) { 289 if (pci_rc < 0) {
274 debugf0("860 init fail\n"); 290 debugf0("860 init fail\n");
275 pci_dev_put(mci_pdev); 291 pci_rc = -ENODEV;
276 return -ENODEV; 292 goto fail1;
277 } 293 }
278 } 294 }
295
279 return 0; 296 return 0;
297
298fail1:
299 pci_unregister_driver(&i82860_driver);
300
301fail0:
302 if (mci_pdev != NULL)
303 pci_dev_put(mci_pdev);
304
305 return pci_rc;
280} 306}
281 307
282static void __exit i82860_exit(void) 308static void __exit i82860_exit(void)
283{ 309{
284 debugf3("MC: " __FILE__ ": %s()\n", __func__); 310 debugf3("%s()\n", __func__);
285 311
286 pci_unregister_driver(&i82860_driver); 312 pci_unregister_driver(&i82860_driver);
287 if (!i82860_registered) { 313
288 i82860_remove_one(mci_pdev); 314 if (mci_pdev != NULL)
289 pci_dev_put(mci_pdev); 315 pci_dev_put(mci_pdev);
290 }
291} 316}
292 317
293module_init(i82860_init); 318module_init(i82860_init);
294module_exit(i82860_exit); 319module_exit(i82860_exit);
295 320
296MODULE_LICENSE("GPL"); 321MODULE_LICENSE("GPL");
297MODULE_AUTHOR 322MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
298 ("Red Hat Inc. (http://www.redhat.com.com) Ben Woodard <woodard@redhat.com>"); 323 "Ben Woodard <woodard@redhat.com>");
299MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers"); 324MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");