Commit e7ecd891 authored by Dave Peterson's avatar Dave Peterson Committed by Linus Torvalds

[PATCH] EDAC: formatting cleanup

Cosmetic indentation/formatting cleanup for EDAC code.  Make sure we
are using tabs rather than spaces to indent, etc.
Signed-off-by: default avatarDavid S. Peterson <dsp@llnl.gov>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 54933ddd
......@@ -12,33 +12,26 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include "edac_mc.h"
#define amd76x_printk(level, fmt, arg...) \
edac_printk(level, "amd76x", fmt, ##arg)
edac_printk(level, "amd76x", fmt, ##arg)
#define amd76x_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg)
edac_mc_chipset_printk(mci, level, "amd76x", fmt, ##arg)
#define AMD76X_NR_CSROWS 8
#define AMD76X_NR_CHANS 1
#define AMD76X_NR_DIMMS 4
/* AMD 76x register addresses - device 0 function 0 - PCI bridge */
#define AMD76X_ECC_MODE_STATUS 0x48 /* Mode and status of ECC (32b)
*
* 31:16 reserved
......@@ -50,6 +43,7 @@
* 7:4 UE cs row
* 3:0 CE cs row
*/
#define AMD76X_DRAM_MODE_STATUS 0x58 /* DRAM Mode and status (32b)
*
* 31:26 clock disable 5 - 0
......@@ -64,6 +58,7 @@
* 15:8 reserved
* 7:0 x4 mode enable 7 - 0
*/
#define AMD76X_MEM_BASE_ADDR 0xC0 /* Memory base address (8 x 32b)
*
* 31:23 chip-select base
......@@ -74,29 +69,28 @@
* 0 chip-select enable
*/
struct amd76x_error_info {
u32 ecc_mode_status;
};
enum amd76x_chips {
AMD761 = 0,
AMD762
};
struct amd76x_dev_info {
const char *ctl_name;
};
static const struct amd76x_dev_info amd76x_devs[] = {
[AMD761] = {.ctl_name = "AMD761"},
[AMD762] = {.ctl_name = "AMD762"},
[AMD761] = {
.ctl_name = "AMD761"
},
[AMD762] = {
.ctl_name = "AMD762"
},
};
/**
* amd76x_get_error_info - fetch error information
* @mci: Memory controller
......@@ -105,23 +99,21 @@ static const struct amd76x_dev_info amd76x_devs[] = {
* Fetch and store the AMD76x ECC status. Clear pending status
* on the chip so that further errors will be reported
*/
static void amd76x_get_error_info (struct mem_ctl_info *mci,
struct amd76x_error_info *info)
static void amd76x_get_error_info(struct mem_ctl_info *mci,
struct amd76x_error_info *info)
{
pci_read_config_dword(mci->pdev, AMD76X_ECC_MODE_STATUS,
&info->ecc_mode_status);
if (info->ecc_mode_status & BIT(8))
pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
(u32) BIT(8), (u32) BIT(8));
(u32) BIT(8), (u32) BIT(8));
if (info->ecc_mode_status & BIT(9))
pci_write_bits32(mci->pdev, AMD76X_ECC_MODE_STATUS,
(u32) BIT(9), (u32) BIT(9));
(u32) BIT(9), (u32) BIT(9));
}
/**
* amd76x_process_error_info - Error check
* @mci: Memory controller
......@@ -132,8 +124,7 @@ static void amd76x_get_error_info (struct mem_ctl_info *mci,
* A return of 1 indicates an error. Also if handle_errors is true
* then attempt to handle and clean up after the error
*/
static int amd76x_process_error_info (struct mem_ctl_info *mci,
static int amd76x_process_error_info(struct mem_ctl_info *mci,
struct amd76x_error_info *info, int handle_errors)
{
int error_found;
......@@ -149,9 +140,8 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci,
if (handle_errors) {
row = (info->ecc_mode_status >> 4) & 0xf;
edac_mc_handle_ue(mci,
mci->csrows[row].first_page, 0, row,
mci->ctl_name);
edac_mc_handle_ue(mci, mci->csrows[row].first_page, 0,
row, mci->ctl_name);
}
}
......@@ -163,11 +153,11 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci,
if (handle_errors) {
row = info->ecc_mode_status & 0xf;
edac_mc_handle_ce(mci,
mci->csrows[row].first_page, 0, 0, row, 0,
mci->ctl_name);
edac_mc_handle_ce(mci, mci->csrows[row].first_page, 0,
0, row, 0, mci->ctl_name);
}
}
return error_found;
}
......@@ -178,7 +168,6 @@ static int amd76x_process_error_info (struct mem_ctl_info *mci,
* Called by the poll handlers this function reads the status
* from the controller and checks for errors.
*/
static void amd76x_check(struct mem_ctl_info *mci)
{
struct amd76x_error_info info;
......@@ -187,7 +176,6 @@ static void amd76x_check(struct mem_ctl_info *mci)
amd76x_process_error_info(mci, &info, 1);
}
/**
* amd76x_probe1 - Perform set up for detected device
* @pdev; PCI device detected
......@@ -197,7 +185,6 @@ static void amd76x_check(struct mem_ctl_info *mci)
* controller status reporting. We configure and set up the
* memory controller reporting and claim the device.
*/
static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc = -ENODEV;
......@@ -214,10 +201,8 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
struct amd76x_error_info discard;
debugf0("%s()\n", __func__);
pci_read_config_dword(pdev, AMD76X_ECC_MODE_STATUS, &ems);
ems_mode = (ems >> 10) & 0x3;
mci = edac_mc_alloc(0, AMD76X_NR_CSROWS, AMD76X_NR_CHANS);
if (mci == NULL) {
......@@ -226,14 +211,11 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
}
debugf0("%s(): mci = %p\n", __func__, mci);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
mci->edac_cap = ems_mode ?
(EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
(EDAC_FLAG_EC | EDAC_FLAG_SECDED) : EDAC_FLAG_NONE;
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.4.2.5 $";
mci->ctl_name = amd76x_devs[dev_idx].ctl_name;
......@@ -249,18 +231,15 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
/* find the DRAM Chip Select Base address and mask */
pci_read_config_dword(mci->pdev,
AMD76X_MEM_BASE_ADDR + (index * 4),
&mba);
AMD76X_MEM_BASE_ADDR + (index * 4), &mba);
if (!(mba & BIT(0)))
continue;
mba_base = mba & 0xff800000UL;
mba_mask = ((mba & 0xff80) << 16) | 0x7fffffUL;
pci_read_config_dword(mci->pdev, AMD76X_DRAM_MODE_STATUS,
&dms);
&dms);
csrow->first_page = mba_base >> PAGE_SHIFT;
csrow->nr_pages = (mba_mask + 1) >> PAGE_SHIFT;
csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
......@@ -290,7 +269,7 @@ static int amd76x_probe1(struct pci_dev *pdev, int dev_idx)
/* returns count (>= 0), or negative on error */
static int __devinit amd76x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
......@@ -298,7 +277,6 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev,
return amd76x_probe1(pdev, ent->driver_data);
}
/**
* amd76x_remove_one - driver shutdown
* @pdev: PCI device being handed back
......@@ -307,7 +285,6 @@ static int __devinit amd76x_init_one(struct pci_dev *pdev,
* structure for the device then delete the mci and free the
* resources.
*/
static void __devexit amd76x_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
......@@ -320,18 +297,22 @@ static void __devexit amd76x_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
static const struct pci_device_id amd76x_pci_tbl[] __devinitdata = {
{PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
AMD762},
{PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
AMD761},
{0,} /* 0 terminated list. */
{
PCI_VEND_DEV(AMD, FE_GATE_700C), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
AMD762
},
{
PCI_VEND_DEV(AMD, FE_GATE_700E), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
AMD761
},
{
0,
} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, amd76x_pci_tbl);
static struct pci_driver amd76x_driver = {
.name = EDAC_MOD_STR,
.probe = amd76x_init_one,
......
......@@ -17,26 +17,19 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include "edac_mc.h"
#define e752x_printk(level, fmt, arg...) \
edac_printk(level, "e752x", fmt, ##arg)
edac_printk(level, "e752x", fmt, ##arg)
#define e752x_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg)
edac_mc_chipset_printk(mci, level, "e752x", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_7520_0
#define PCI_DEVICE_ID_INTEL_7520_0 0x3590
......@@ -64,7 +57,6 @@
#define E752X_NR_CSROWS 8 /* number of csrows */
/* E752X register addresses - device 0 function 0 */
#define E752X_DRB 0x60 /* DRAM row boundary register (8b) */
#define E752X_DRA 0x70 /* DRAM row attribute register (8b) */
......@@ -164,7 +156,6 @@ enum e752x_chips {
E7320 = 2
};
struct e752x_pvt {
struct pci_dev *bridge_ck;
struct pci_dev *dev_d0f0;
......@@ -178,7 +169,6 @@ struct e752x_pvt {
const struct e752x_dev_info *dev_info;
};
struct e752x_dev_info {
u16 err_dev;
u16 ctl_dev;
......@@ -207,22 +197,24 @@ struct e752x_error_info {
static const struct e752x_dev_info e752x_devs[] = {
[E7520] = {
.err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
.ctl_dev = PCI_DEVICE_ID_INTEL_7520_0,
.ctl_name = "E7520"},
.err_dev = PCI_DEVICE_ID_INTEL_7520_1_ERR,
.ctl_dev = PCI_DEVICE_ID_INTEL_7520_0,
.ctl_name = "E7520"
},
[E7525] = {
.err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
.ctl_dev = PCI_DEVICE_ID_INTEL_7525_0,
.ctl_name = "E7525"},
.err_dev = PCI_DEVICE_ID_INTEL_7525_1_ERR,
.ctl_dev = PCI_DEVICE_ID_INTEL_7525_0,
.ctl_name = "E7525"
},
[E7320] = {
.err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
.ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
.ctl_name = "E7320"},
.err_dev = PCI_DEVICE_ID_INTEL_7320_1_ERR,
.ctl_dev = PCI_DEVICE_ID_INTEL_7320_0,
.ctl_name = "E7320"
},
};
static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
unsigned long page)
unsigned long page)
{
u32 remap;
struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
......@@ -231,17 +223,21 @@ static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
if (page < pvt->tolm)
return page;
if ((page >= 0x100000) && (page < pvt->remapbase))
return page;
remap = (page - pvt->tolm) + pvt->remapbase;
if (remap < pvt->remaplimit)
return remap;
e752x_printk(KERN_ERR, "Invalid page %lx - out of range\n", page);
return pvt->tolm - 1;
}
static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
u32 sec1_add, u16 sec1_syndrome)
u32 sec1_add, u16 sec1_syndrome)
{
u32 page;
int row;
......@@ -259,34 +255,36 @@ static void do_process_ce(struct mem_ctl_info *mci, u16 error_one,
/* chip select are bits 14 & 13 */
row = ((page >> 1) & 3);
e752x_printk(KERN_WARNING,
"Test row %d Table %d %d %d %d %d %d %d %d\n",
row, pvt->map[0], pvt->map[1], pvt->map[2],
pvt->map[3], pvt->map[4], pvt->map[5],
pvt->map[6], pvt->map[7]);
"Test row %d Table %d %d %d %d %d %d %d %d\n", row,
pvt->map[0], pvt->map[1], pvt->map[2], pvt->map[3],
pvt->map[4], pvt->map[5], pvt->map[6], pvt->map[7]);
/* test for channel remapping */
for (i = 0; i < 8; i++) {
if (pvt->map[i] == row)
break;
}
e752x_printk(KERN_WARNING, "Test computed row %d\n", i);
if (i < 8)
row = i;
else
e752x_mc_printk(mci, KERN_WARNING,
"row %d not found in remap table\n", row);
"row %d not found in remap table\n", row);
} else
row = edac_mc_find_csrow_by_page(mci, page);
/* 0 = channel A, 1 = channel B */
channel = !(error_one & 1);
if (!pvt->map_type)
row = 7 - row;
edac_mc_handle_ce(mci, page, 0, sec1_syndrome, row, channel,
"e752x CE");
"e752x CE");
}
static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
u32 sec1_add, u16 sec1_syndrome, int *error_found,
int handle_error)
......@@ -297,8 +295,8 @@ static inline void process_ce(struct mem_ctl_info *mci, u16 error_one,
do_process_ce(mci, error_one, sec1_add, sec1_syndrome);
}
static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
u32 scrb_add)
static void do_process_ue(struct mem_ctl_info *mci, u16 error_one,
u32 ded_add, u32 scrb_add)
{
u32 error_2b, block_page;
int row;
......@@ -308,25 +306,31 @@ static void do_process_ue(struct mem_ctl_info *mci, u16 error_one, u32 ded_add,
if (error_one & 0x0202) {
error_2b = ded_add;
/* convert to 4k address */
block_page = error_2b >> (PAGE_SHIFT - 4);
row = pvt->mc_symmetric ?
/* chip select are bits 14 & 13 */
((block_page >> 1) & 3) :
edac_mc_find_csrow_by_page(mci, block_page);
/* chip select are bits 14 & 13 */
((block_page >> 1) & 3) :
edac_mc_find_csrow_by_page(mci, block_page);
edac_mc_handle_ue(mci, block_page, 0, row,
"e752x UE from Read");
"e752x UE from Read");
}
if (error_one & 0x0404) {
error_2b = scrb_add;
/* convert to 4k address */
block_page = error_2b >> (PAGE_SHIFT - 4);
row = pvt->mc_symmetric ?
/* chip select are bits 14 & 13 */
((block_page >> 1) & 3) :
edac_mc_find_csrow_by_page(mci, block_page);
/* chip select are bits 14 & 13 */
((block_page >> 1) & 3) :
edac_mc_find_csrow_by_page(mci, block_page);
edac_mc_handle_ue(mci, block_page, 0, row,
"e752x UE from Scruber");
"e752x UE from Scruber");
}
}
......@@ -359,13 +363,13 @@ static void do_process_ded_retry(struct mem_ctl_info *mci, u16 error,
struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info;
error_1b = retry_add;
page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
page = error_1b >> (PAGE_SHIFT - 4); /* convert the addr to 4k page */
row = pvt->mc_symmetric ?
((page >> 1) & 3) : /* chip select are bits 14 & 13 */
edac_mc_find_csrow_by_page(mci, page);
((page >> 1) & 3) : /* chip select are bits 14 & 13 */
edac_mc_find_csrow_by_page(mci, page);
e752x_mc_printk(mci, KERN_WARNING,
"CE page 0x%lx, row %d : Memory read retry\n",
(long unsigned int) page, row);
"CE page 0x%lx, row %d : Memory read retry\n",
(long unsigned int) page, row);
}
static inline void process_ded_retry(struct mem_ctl_info *mci, u16 error,
......@@ -402,7 +406,7 @@ static void do_global_error(int fatal, u32 errors)
for (i = 0; i < 11; i++) {
if (errors & (1 << i))
e752x_printk(KERN_WARNING, "%sError %s\n",
fatal_message[fatal], global_message[i]);
fatal_message[fatal], global_message[i]);
}
}
......@@ -429,7 +433,7 @@ static void do_hub_error(int fatal, u8 errors)
for (i = 0; i < 7; i++) {
if (errors & (1 << i))
e752x_printk(KERN_WARNING, "%sError %s\n",
fatal_message[fatal], hub_message[i]);
fatal_message[fatal], hub_message[i]);
}
}
......@@ -456,7 +460,7 @@ static void do_membuf_error(u8 errors)
for (i = 0; i < 4; i++) {
if (errors & (1 << i))
e752x_printk(KERN_WARNING, "Non-Fatal Error %s\n",
membuf_message[i]);
membuf_message[i]);
}
}
......@@ -489,7 +493,7 @@ static void do_sysbus_error(int fatal, u32 errors)
for (i = 0; i < 10; i++) {
if (errors & (1 << i))
e752x_printk(KERN_WARNING, "%sError System Bus %s\n",
fatal_message[fatal], global_message[i]);
fatal_message[fatal], global_message[i]);
}
}
......@@ -502,33 +506,42 @@ static inline void sysbus_error(int fatal, u32 errors, int *error_found,
do_sysbus_error(fatal, errors);
}
static void e752x_check_hub_interface (struct e752x_error_info *info,
static void e752x_check_hub_interface(struct e752x_error_info *info,
int *error_found, int handle_error)
{
u8 stat8;
//pci_read_config_byte(dev,E752X_HI_FERR,&stat8);
stat8 = info->hi_ferr;
if(stat8 & 0x7f) { /* Error, so process */
stat8 &= 0x7f;
if(stat8 & 0x2b)
hub_error(1, stat8 & 0x2b, error_found, handle_error);
if(stat8 & 0x54)
hub_error(0, stat8 & 0x54, error_found, handle_error);
}
//pci_read_config_byte(dev,E752X_HI_NERR,&stat8);
stat8 = info->hi_nerr;
if(stat8 & 0x7f) { /* Error, so process */
stat8 &= 0x7f;
if (stat8 & 0x2b)
hub_error(1, stat8 & 0x2b, error_found, handle_error);
if(stat8 & 0x54)
hub_error(0, stat8 & 0x54, error_found, handle_error);
}
}
static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
int handle_error)
static void e752x_check_sysbus(struct e752x_error_info *info,
int *error_found, int handle_error)
{
u32 stat32, error32;
......@@ -540,27 +553,34 @@ static void e752x_check_sysbus (struct e752x_error_info *info, int *error_found,
error32 = (stat32 >> 16) & 0x3ff;
stat32 = stat32 & 0x3ff;
if(stat32 & 0x083)
sysbus_error(1, stat32 & 0x083, error_found, handle_error);
if(stat32 & 0x37c)
sysbus_error(0, stat32 & 0x37c, error_found, handle_error);
if(error32 & 0x083)
sysbus_error(1, error32 & 0x083, error_found, handle_error);
if(error32 & 0x37c)
sysbus_error(0, error32 & 0x37c, error_found, handle_error);
}
static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
int handle_error)
static void e752x_check_membuf (struct e752x_error_info *info,
int *error_found, int handle_error)
{
u8 stat8;
stat8 = info->buf_ferr;
if (stat8 & 0x0f) { /* Error, so process */
stat8 &= 0x0f;
membuf_error(stat8, error_found, handle_error);
}
stat8 = info->buf_nerr;
if (stat8 & 0x0f) { /* Error, so process */
stat8 &= 0x0f;
membuf_error(stat8, error_found, handle_error);
......@@ -568,7 +588,8 @@ static void e752x_check_membuf (struct e752x_error_info *info, int *error_found,
}
static void e752x_check_dram (struct mem_ctl_info *mci,
struct e752x_error_info *info, int *error_found, int handle_error)
struct e752x_error_info *info, int *error_found,
int handle_error)
{
u16 error_one, error_next;
......@@ -618,7 +639,7 @@ static void e752x_check_dram (struct mem_ctl_info *mci,
}
static void e752x_get_error_info (struct mem_ctl_info *mci,
struct e752x_error_info *info)
struct e752x_error_info *info)
{
struct pci_dev *dev;
struct e752x_pvt *pvt;
......@@ -626,7 +647,6 @@ static void e752x_get_error_info (struct mem_ctl_info *mci,
memset(info, 0, sizeof(*info));
pvt = (struct e752x_pvt *) mci->pvt_info;
dev = pvt->dev_d0f1;
pci_read_config_dword(dev, E752X_FERR_GLOBAL, &info->ferr_global);
if (info->ferr_global) {
......@@ -737,6 +757,7 @@ static int e752x_process_error_info (struct mem_ctl_info *mci,
static void e752x_check(struct mem_ctl_info *mci)
{
struct e752x_error_info info;
debugf3("%s()\n", __func__);
e752x_get_error_info(mci, &info);
e752x_process_error_info(mci, &info, 1);
......@@ -752,9 +773,9 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
struct e752x_pvt *pvt = NULL;
u16 ddrcsr;
u32 drc;
int drc_chan; /* Number of channels 0=1chan,1=2chan */
int drc_drbg; /* DRB granularity 0=64mb,1=128mb */
int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
int drc_chan; /* Number of channels 0=1chan,1=2chan */
int drc_drbg; /* DRB granularity 0=64mb, 1=128mb */
int drc_ddim; /* DRAM Data Integrity Mode 0=none,2=edac */
u32 dra;
unsigned long last_cumul_size;
struct pci_dev *dev = NULL;
......@@ -785,7 +806,6 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
}
debugf3("%s(): init mci\n", __func__);
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
EDAC_FLAG_S4ECD4ED;
......@@ -798,19 +818,21 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pvt = (struct e752x_pvt *) mci->pvt_info;
pvt->dev_info = &e752x_devs[dev_idx];
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
pvt->dev_info->err_dev,
pvt->bridge_ck);
pvt->dev_info->err_dev,
pvt->bridge_ck);
if (pvt->bridge_ck == NULL)
pvt->bridge_ck = pci_scan_single_device(pdev->bus,
PCI_DEVFN(0, 1));
PCI_DEVFN(0, 1));
if (pvt->bridge_ck == NULL) {
e752x_printk(KERN_ERR, "error reporting device not found:"
"vendor %x device 0x%x (broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
"vendor %x device 0x%x (broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].err_dev);
goto fail;
}
pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
pvt->mc_symmetric = ((ddrcsr & 0x10) != 0);
debugf3("%s(): more mci init\n", __func__);
mci->ctl_name = pvt->dev_info->ctl_name;
mci->edac_check = e752x_check;
......@@ -828,6 +850,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
for (last_cumul_size = index = 0; index < mci->nr_csrows; index++) {
u8 value;
u32 cumul_size;
/* mem_dev 0=x8, 1=x4 */
int mem_dev = (dra >> (index * 4 + 2)) & 0x3;
struct csrow_info *csrow = &mci->csrows[index];
......@@ -838,15 +861,16 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
cumul_size);
if (cumul_size == last_cumul_size)
continue; /* not populated */
continue; /* not populated */
csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
csrow->mtype = MEM_RDDR; /* only one type supported */
csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
csrow->mtype = MEM_RDDR; /* only one type supported */
csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
/*
......@@ -870,29 +894,32 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
u8 value;
u8 last = 0;
u8 row = 0;
for (index = 0; index < 8; index += 2) {
for (index = 0; index < 8; index += 2) {
pci_read_config_byte(mci->pdev, E752X_DRB + index,
&value);
&value);
/* test if there is a dimm in this slot */
if (value == last) {
/* no dimm in the slot, so flag it as empty */
pvt->map[index] = 0xff;
pvt->map[index + 1] = 0xff;
} else { /* there is a dimm in the slot */
} else { /* there is a dimm in the slot */
pvt->map[index] = row;
row++;
last = value;
/* test the next value to see if the dimm is
double sided */
pci_read_config_byte(mci->pdev,
E752X_DRB + index + 1,
&value);
E752X_DRB + index + 1,
&value);
pvt->map[index + 1] = (value == last) ?
0xff : /* the dimm is single sided,
so flag as empty */
row; /* this is a double sided dimm
to save the next row # */
0xff : /* the dimm is single sided,
* so flag as empty
*/
row; /* this is a double sided dimm
* to save the next row #
*/
row++;
last = value;
}
......@@ -904,8 +931,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pvt->map_type = ((stat8 & 0x0f) > ((stat8 >> 4) & 0x0f));
mci->edac_cap |= EDAC_FLAG_NONE;
debugf3("%s(): tolm, remapbase, remaplimit\n", __func__);
/* load the top of low memory, remap base, and remap limit vars */
pci_read_config_word(mci->pdev, E752X_TOLM, &pci_data);
pvt->tolm = ((u32) pci_data) << 4;
......@@ -914,8 +941,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pci_read_config_word(mci->pdev, E752X_REMAPLIMIT, &pci_data);
pvt->remaplimit = ((u32) pci_data) << 14;
e752x_printk(KERN_INFO,
"tolm = %x, remapbase = %x, remaplimit = %x\n",
pvt->tolm, pvt->remapbase, pvt->remaplimit);
"tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
pvt->remapbase, pvt->remaplimit);
if (edac_mc_add_mc(mci)) {
debugf3("%s(): failed edac_mc_add_mc()\n", __func__);
......@@ -923,7 +950,7 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
}
dev = pci_get_device(PCI_VENDOR_ID_INTEL, e752x_devs[dev_idx].ctl_dev,
NULL);
NULL);
pvt->dev_d0f0 = dev;
/* find the error reporting device and clear errors */
dev = pvt->dev_d0f1 = pci_dev_get(pvt->bridge_ck);
......@@ -936,8 +963,8 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
pci_write_config_byte(dev, E752X_BUF_SMICMD, 0x00);
pci_write_config_byte(dev, E752X_DRAM_ERRMASK, 0x00);
pci_write_config_byte(dev, E752X_DRAM_SMICMD, 0x00);
/* clear other MCH errors */
e752x_get_error_info(mci, &discard);
e752x_get_error_info(mci, &discard); /* clear other MCH errors */
/* get this far and it's successful */
debugf3("%s(): success\n", __func__);
......@@ -947,28 +974,32 @@ static int e752x_probe1(struct pci_dev *pdev, int dev_idx)
if (mci) {
if (pvt->dev_d0f0)
pci_dev_put(pvt->dev_d0f0);
if (pvt->dev_d0f1)
pci_dev_put(pvt->dev_d0f1);
if (pvt->bridge_ck)
pci_dev_put(pvt->bridge_ck);
edac_mc_free(mci);
}
return rc;
}
/* returns count (>= 0), or negative on error */
static int __devinit e752x_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
/* wake up and enable device */
if(pci_enable_device(pdev) < 0)
return -EIO;
return e752x_probe1(pdev, ent->driver_data);
}
static void __devexit e752x_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
......@@ -986,20 +1017,26 @@ static void __devexit e752x_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
static const struct pci_device_id e752x_pci_tbl[] __devinitdata = {
{PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7520},
{PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7525},
{PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7320},
{0,} /* 0 terminated list. */
{
PCI_VEND_DEV(INTEL, 7520_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7520
},
{
PCI_VEND_DEV(INTEL, 7525_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7525
},
{
PCI_VEND_DEV(INTEL, 7320_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7320
},
{
0,
} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, e752x_pci_tbl);
static struct pci_driver e752x_driver = {
.name = EDAC_MOD_STR,
.probe = e752x_init_one,
......@@ -1007,7 +1044,6 @@ static struct pci_driver e752x_driver = {
.id_table = e752x_pci_tbl,
};
static int __init e752x_init(void)
{
int pci_rc;
......@@ -1017,14 +1053,12 @@ static int __init e752x_init(void)
return (pci_rc < 0) ? pci_rc : 0;
}
static void __exit e752x_exit(void)
{
debugf3("%s()\n", __func__);
pci_unregister_driver(&e752x_driver);
}
module_init(e752x_init);
module_exit(e752x_exit);
......
......@@ -11,9 +11,9 @@
* http://www.anime.net/~goemon/linux-ecc/
*
* Contributors:
* Eric Biederman (Linux Networx)
* Tom Zimmerman (Linux Networx)
* Jim Garlick (Lawrence Livermore National Labs)
* Eric Biederman (Linux Networx)
* Tom Zimmerman (Linux Networx)
* Jim Garlick (Lawrence Livermore National Labs)
* Dave Peterson (Lawrence Livermore National Labs)
* That One Guy (Some other place)
* Wang Zhenyu (intel.com)
......@@ -22,7 +22,6 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
......@@ -31,14 +30,11 @@
#include <linux/slab.h>
#include "edac_mc.h"
#define e7xxx_printk(level, fmt, arg...) \
edac_printk(level, "e7xxx", fmt, ##arg)
edac_printk(level, "e7xxx", fmt, ##arg)
#define e7xxx_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg)
edac_mc_chipset_printk(mci, level, "e7xxx", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_7205_0
#define PCI_DEVICE_ID_INTEL_7205_0 0x255d
......@@ -72,11 +68,9 @@
#define PCI_DEVICE_ID_INTEL_7505_1_ERR 0x2551
#endif /* PCI_DEVICE_ID_INTEL_7505_1_ERR */
#define E7XXX_NR_CSROWS 8 /* number of csrows */
#define E7XXX_NR_DIMMS 8 /* FIXME - is this correct? */
/* E7XXX register addresses - device 0 function 0 */
#define E7XXX_DRB 0x60 /* DRAM row boundary register (8b) */
#define E7XXX_DRA 0x70 /* DRAM row attribute register (8b) */
......@@ -126,7 +120,6 @@ enum e7xxx_chips {
E7205,
};
struct e7xxx_pvt {
struct pci_dev *bridge_ck;
u32 tolm;
......@@ -135,13 +128,11 @@ struct e7xxx_pvt {
const struct e7xxx_dev_info *dev_info;
};
struct e7xxx_dev_info {
u16 err_dev;
const char *ctl_name;
};
struct e7xxx_error_info {
u8 dram_ferr;
u8 dram_nerr;
......@@ -152,20 +143,23 @@ struct e7xxx_error_info {
static const struct e7xxx_dev_info e7xxx_devs[] = {
[E7500] = {
.err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
.ctl_name = "E7500"},
.err_dev = PCI_DEVICE_ID_INTEL_7500_1_ERR,
.ctl_name = "E7500"
},
[E7501] = {
.err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
.ctl_name = "E7501"},
.err_dev = PCI_DEVICE_ID_INTEL_7501_1_ERR,
.ctl_name = "E7501"
},
[E7505] = {
.err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
.ctl_name = "E7505"},
.err_dev = PCI_DEVICE_ID_INTEL_7505_1_ERR,
.ctl_name = "E7505"
},
[E7205] = {
.err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
.ctl_name = "E7205"},
.err_dev = PCI_DEVICE_ID_INTEL_7205_1_ERR,
.ctl_name = "E7205"
},
};
/* FIXME - is this valid for both SECDED and S4ECD4ED? */
static inline int e7xxx_find_channel(u16 syndrome)
{
......@@ -173,16 +167,18 @@ static inline int e7xxx_find_channel(u16 syndrome)
if ((syndrome & 0xff00) == 0)
return 0;
if ((syndrome & 0x00ff) == 0)
return 1;
if ((syndrome & 0xf000) == 0 || (syndrome & 0x0f00) == 0)
return 0;
return 1;
}
static unsigned long
ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
static unsigned long ctl_page_to_phys(struct mem_ctl_info *mci,
unsigned long page)
{
u32 remap;
struct e7xxx_pvt *pvt = (struct e7xxx_pvt *) mci->pvt_info;
......@@ -190,17 +186,20 @@ ctl_page_to_phys(struct mem_ctl_info *mci, unsigned long page)
debugf3("%s()\n", __func__);
if ((page < pvt->tolm) ||
((page >= 0x100000) && (page < pvt->remapbase)))
((page >= 0x100000) && (page < pvt->remapbase)))
return page;
remap = (page - pvt->tolm) + pvt->remapbase;
if (remap < pvt->remaplimit)
return remap;
e7xxx_printk(KERN_ERR, "Invalid page %lx - out of range\n", page);
return pvt->tolm - 1;
}
static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
static void process_ce(struct mem_ctl_info *mci,
struct e7xxx_error_info *info)
{
u32 error_1b, page;
u16 syndrome;
......@@ -208,52 +207,46 @@ static void process_ce(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
int channel;
debugf3("%s()\n", __func__);
/* read the error address */
error_1b = info->dram_celog_add;
/* FIXME - should use PAGE_SHIFT */
page = error_1b >> 6; /* convert the address to 4k page */
page = error_1b >> 6; /* convert the address to 4k page */
/* read the syndrome */
syndrome = info->dram_celog_syndrome;
/* FIXME - check for -1 */
row = edac_mc_find_csrow_by_page(mci, page);
/* convert syndrome to channel */
channel = e7xxx_find_channel(syndrome);
edac_mc_handle_ce(mci, page, 0, syndrome, row, channel,
"e7xxx CE");
edac_mc_handle_ce(mci, page, 0, syndrome, row, channel, "e7xxx CE");
}
static void process_ce_no_info(struct mem_ctl_info *mci)
{
debugf3("%s()\n", __func__);
edac_mc_handle_ce_no_info(mci, "e7xxx CE log register overflow");
}
static void process_ue(struct mem_ctl_info *mci, struct e7xxx_error_info *info)
static void process_ue(struct mem_ctl_info *mci,
struct e7xxx_error_info *info)
{
u32 error_2b, block_page;
int row;
debugf3("%s()\n", __func__);
/* read the error address */
error_2b = info->dram_uelog_add;
/* FIXME - should use PAGE_SHIFT */
block_page = error_2b >> 6; /* convert to 4k address */
block_page = error_2b >> 6; /* convert to 4k address */
row = edac_mc_find_csrow_by_page(mci, block_page);
edac_mc_handle_ue(mci, block_page, 0, row, "e7xxx UE");
}
static void process_ue_no_info(struct mem_ctl_info *mci)
{
debugf3("%s()\n", __func__);
edac_mc_handle_ue_no_info(mci, "e7xxx UE log register overflow");
}
static void e7xxx_get_error_info (struct mem_ctl_info *mci,
struct e7xxx_error_info *info)
{
......@@ -261,31 +254,29 @@ static void e7xxx_get_error_info (struct mem_ctl_info *mci,
pvt = (struct e7xxx_pvt *) mci->pvt_info;
pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_FERR,
&info->dram_ferr);
&info->dram_ferr);
pci_read_config_byte(pvt->bridge_ck, E7XXX_DRAM_NERR,
&info->dram_nerr);
&info->dram_nerr);
if ((info->dram_ferr & 1) || (info->dram_nerr & 1)) {
pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_CELOG_ADD,
&info->dram_celog_add);
&info->dram_celog_add);
pci_read_config_word(pvt->bridge_ck,
E7XXX_DRAM_CELOG_SYNDROME, &info->dram_celog_syndrome);
E7XXX_DRAM_CELOG_SYNDROME,
&info->dram_celog_syndrome);
}
if ((info->dram_ferr & 2) || (info->dram_nerr & 2))
pci_read_config_dword(pvt->bridge_ck, E7XXX_DRAM_UELOG_ADD,
&info->dram_uelog_add);
&info->dram_uelog_add);
if (info->dram_ferr & 3)
pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03,
0x03);
pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_FERR, 0x03, 0x03);
if (info->dram_nerr & 3)
pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03,
0x03);
pci_write_bits8(pvt->bridge_ck, E7XXX_DRAM_NERR, 0x03, 0x03);
}
static int e7xxx_process_error_info (struct mem_ctl_info *mci,
struct e7xxx_error_info *info, int handle_errors)
{
......@@ -333,7 +324,6 @@ static int e7xxx_process_error_info (struct mem_ctl_info *mci,
return error_found;
}
static void e7xxx_check(struct mem_ctl_info *mci)
{
struct e7xxx_error_info info;
......@@ -343,7 +333,6 @@ static void e7xxx_check(struct mem_ctl_info *mci)
e7xxx_process_error_info(mci, &info, 1);
}
static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
{
int rc = -ENODEV;
......@@ -363,13 +352,14 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
/* need to find out the number of channels */
pci_read_config_dword(pdev, E7XXX_DRC, &drc);
/* only e7501 can be single channel */
if (dev_idx == E7501) {
drc_chan = ((drc >> 22) & 0x1);
drc_drbg = (drc >> 18) & 0x3;
}
drc_ddim = (drc >> 20) & 0x3;
drc_ddim = (drc >> 20) & 0x3;
mci = edac_mc_alloc(sizeof(*pvt), E7XXX_NR_CSROWS, drc_chan + 1);
if (mci == NULL) {
......@@ -378,10 +368,9 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
}
debugf3("%s(): init mci\n", __func__);
mci->mtype_cap = MEM_FLAG_RDDR;
mci->edac_ctl_cap =
EDAC_FLAG_NONE | EDAC_FLAG_SECDED | EDAC_FLAG_S4ECD4ED;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED |
EDAC_FLAG_S4ECD4ED;
/* FIXME - what if different memory types are in different csrows? */
mci->mod_name = EDAC_MOD_STR;
mci->mod_ver = "$Revision: 1.5.2.9 $";
......@@ -391,19 +380,18 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
pvt = (struct e7xxx_pvt *) mci->pvt_info;
pvt->dev_info = &e7xxx_devs[dev_idx];
pvt->bridge_ck = pci_get_device(PCI_VENDOR_ID_INTEL,
pvt->dev_info->err_dev,
pvt->bridge_ck);
pvt->dev_info->err_dev,
pvt->bridge_ck);
if (!pvt->bridge_ck) {
e7xxx_printk(KERN_ERR, "error reporting device not found:"
"vendor %x device 0x%x (broken BIOS?)\n",
PCI_VENDOR_ID_INTEL,
e7xxx_devs[dev_idx].err_dev);
"vendor %x device 0x%x (broken BIOS?)\n",
PCI_VENDOR_ID_INTEL, e7xxx_devs[dev_idx].err_dev);
goto fail;
}
debugf3("%s(): more mci init\n", __func__);
mci->ctl_name = pvt->dev_info->ctl_name;
mci->edac_check = e7xxx_check;
mci->ctl_page_to_phys = ctl_page_to_phys;
......@@ -428,15 +416,16 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
cumul_size = value << (25 + drc_drbg - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
cumul_size);
if (cumul_size == last_cumul_size)
continue; /* not populated */
continue; /* not populated */
csrow->first_page = last_cumul_size;
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
csrow->mtype = MEM_RDDR; /* only one type supported */
csrow->grain = 1 << 12; /* 4KiB - resolution of CELOG */
csrow->mtype = MEM_RDDR; /* only one type supported */
csrow->dtype = mem_dev ? DEV_X4 : DEV_X8;
/*
......@@ -466,8 +455,8 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
pci_read_config_word(mci->pdev, E7XXX_REMAPLIMIT, &pci_data);
pvt->remaplimit = ((u32) pci_data) << 14;
e7xxx_printk(KERN_INFO,
"tolm = %x, remapbase = %x, remaplimit = %x\n",
pvt->tolm, pvt->remapbase, pvt->remaplimit);
"tolm = %x, remapbase = %x, remaplimit = %x\n", pvt->tolm,
pvt->remapbase, pvt->remaplimit);
/* clear any pending errors, or initial state bits */
e7xxx_get_error_info(mci, &discard);
......@@ -492,17 +481,16 @@ static int e7xxx_probe1(struct pci_dev *pdev, int dev_idx)
}
/* returns count (>= 0), or negative on error */
static int __devinit
e7xxx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
static int __devinit e7xxx_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
/* wake up and enable device */
return pci_enable_device(pdev) ?
-EIO : e7xxx_probe1(pdev, ent->driver_data);
-EIO : e7xxx_probe1(pdev, ent->driver_data);
}
static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
......@@ -518,22 +506,30 @@ static void __devexit e7xxx_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
static const struct pci_device_id e7xxx_pci_tbl[] __devinitdata = {
{PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7205},
{PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7500},
{PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7501},
{PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7505},
{0,} /* 0 terminated list. */
{
PCI_VEND_DEV(INTEL, 7205_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7205
},
{
PCI_VEND_DEV(INTEL, 7500_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7500
},
{
PCI_VEND_DEV(INTEL, 7501_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7501
},
{
PCI_VEND_DEV(INTEL, 7505_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
E7505
},
{
0,
} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, e7xxx_pci_tbl);
static struct pci_driver e7xxx_driver = {
.name = EDAC_MOD_STR,
.probe = e7xxx_init_one,
......@@ -541,13 +537,11 @@ static struct pci_driver e7xxx_driver = {
.id_table = e7xxx_pci_tbl,
};
static int __init e7xxx_init(void)
{
return pci_register_driver(&e7xxx_driver);
}
static void __exit e7xxx_exit(void)
{
pci_unregister_driver(&e7xxx_driver);
......@@ -556,8 +550,7 @@ static void __exit e7xxx_exit(void)
module_init(e7xxx_init);
module_exit(e7xxx_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
"Based on.work by Dan Hollis et al");
"Based on.work by Dan Hollis et al");
MODULE_DESCRIPTION("MC support for Intel e7xxx memory controllers");
......@@ -12,7 +12,6 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
......@@ -30,14 +29,12 @@
#include <linux/sysdev.h>
#include <linux/ctype.h>
#include <linux/kthread.h>
#include <asm/uaccess.h>
#include <asm/page.h>
#include <asm/edac.h>
#include "edac_mc.h"
#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__
#define EDAC_MC_VERSION "Ver: 2.0.0 " __DATE__
/* For now, disable the EDAC sysfs code. The sysfs interface that EDAC
* presents to user space needs more thought, and is likely to change
......@@ -73,7 +70,6 @@ struct edac_pci_device_list {
unsigned int device; /* Deviice ID */
};
#define MAX_LISTED_PCI_DEVICES 32
/* List of PCI devices (vendor-id:device-id) that should be skipped */
......@@ -126,7 +122,6 @@ static const char *edac_caps[] = {
[EDAC_S16ECD16ED] = "S16ECD16ED"
};
/* sysfs object: /sys/devices/system/edac */
static struct sysdev_class edac_class = {
set_kset_name("edac"),
......@@ -147,7 +142,7 @@ static struct completion edac_pci_kobj_complete;
/*
* /sys/devices/system/edac/mc;
* data structures and methods
* data structures and methods
*/
#if 0
static ssize_t memctrl_string_show(void *ptr, char *buffer)
......@@ -174,33 +169,34 @@ static ssize_t memctrl_int_store(void *ptr, const char *buffer, size_t count)
}
struct memctrl_dev_attribute {
struct attribute attr;
void *value;
struct attribute attr;
void *value;
ssize_t (*show)(void *,char *);
ssize_t (*store)(void *, const char *, size_t);
};
/* Set of show/store abstract level functions for memory control object */
static ssize_t
memctrl_dev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
static ssize_t memctrl_dev_show(struct kobject *kobj,
struct attribute *attr, char *buffer)
{
struct memctrl_dev_attribute *memctrl_dev;
memctrl_dev = (struct memctrl_dev_attribute*)attr;
if (memctrl_dev->show)
return memctrl_dev->show(memctrl_dev->value, buffer);
return -EIO;
}
static ssize_t
memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
static ssize_t memctrl_dev_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
{
struct memctrl_dev_attribute *memctrl_dev;
memctrl_dev = (struct memctrl_dev_attribute*)attr;
if (memctrl_dev->store)
return memctrl_dev->store(memctrl_dev->value, buffer, count);
return -EIO;
}
......@@ -236,7 +232,6 @@ MEMCTRL_ATTR(log_ue,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
MEMCTRL_ATTR(log_ce,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
MEMCTRL_ATTR(poll_msec,S_IRUGO|S_IWUSR,memctrl_int_show,memctrl_int_store);
/* Base Attributes of the memory ECC object */
static struct memctrl_dev_attribute *memctrl_attr[] = {
&attr_panic_on_ue,
......@@ -254,9 +249,9 @@ static void edac_memctrl_master_release(struct kobject *kobj)
}
static struct kobj_type ktype_memctrl = {
.release = edac_memctrl_master_release,
.sysfs_ops = &memctrlfs_ops,
.default_attrs = (struct attribute **) memctrl_attr,
.release = edac_memctrl_master_release,
.sysfs_ops = &memctrlfs_ops,
.default_attrs = (struct attribute **) memctrl_attr,
};
#endif /* DISABLE_EDAC_SYSFS */
......@@ -282,6 +277,7 @@ static int edac_sysfs_memctrl_setup(void)
/* create the /sys/devices/system/edac directory */
err = sysdev_class_register(&edac_class);
if (!err) {
/* Init the MC's kobject */
memset(&edac_memctrl_kobj, 0, sizeof (edac_memctrl_kobj));
......@@ -290,18 +286,18 @@ static int edac_sysfs_memctrl_setup(void)
/* generate sysfs "..../edac/mc" */
err = kobject_set_name(&edac_memctrl_kobj,"mc");
if (!err) {
/* FIXME: maybe new sysdev_create_subdir() */
err = kobject_register(&edac_memctrl_kobj);
if (err) {
if (err)
debugf1("Failed to register '.../edac/mc'\n");
} else {
else
debugf1("Registered '.../edac/mc' kobject\n");
}
}
} else {
} else
debugf1("%s() error=%d\n", __func__, err);
}
return err;
}
......@@ -340,7 +336,6 @@ struct list_control {
int *count;
};
#if 0
/* Output the list as: vendor_id:device:id<,vendor_id:device_id> */
static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
......@@ -365,7 +360,6 @@ static ssize_t edac_pci_list_string_show(void *ptr, char *buffer)
}
len += snprintf(p + len,(PAGE_SIZE-len), "\n");
return (ssize_t) len;
}
......@@ -387,7 +381,7 @@ static int parse_one_device(const char **s,const char **e,
/* if null byte, we are done */
if (!**s) {
(*s)++; /* keep *s moving */
(*s)++; /* keep *s moving */
return 0;
}
......@@ -404,6 +398,7 @@ static int parse_one_device(const char **s,const char **e,
/* parse vendor_id */
runner = *s;
while (runner < *e) {
/* scan for vendor:device delimiter */
if (*runner == ':') {
......@@ -411,6 +406,7 @@ static int parse_one_device(const char **s,const char **e,
runner = p + 1;
break;
}
runner++;
}
......@@ -426,12 +422,11 @@ static int parse_one_device(const char **s,const char **e,
}
*s = runner;
return 1;
}
static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
size_t count)
size_t count)
{
struct list_control *listctl;
struct edac_pci_device_list *list;
......@@ -441,14 +436,12 @@ static ssize_t edac_pci_list_string_store(void *ptr, const char *buffer,
s = (char*)buffer;
e = s + count;
listctl = ptr;
list = listctl->list;
index = listctl->count;
*index = 0;
while (*index < MAX_LISTED_PCI_DEVICES) {
while (*index < MAX_LISTED_PCI_DEVICES) {
if (parse_one_device(&s,&e,&vendor_id,&device_id)) {
list[ *index ].vendor = vendor_id;
list[ *index ].device = device_id;
......@@ -481,15 +474,15 @@ static ssize_t edac_pci_int_store(void *ptr, const char *buffer, size_t count)
}
struct edac_pci_dev_attribute {
struct attribute attr;
void *value;
struct attribute attr;
void *value;
ssize_t (*show)(void *,char *);
ssize_t (*store)(void *, const char *,size_t);
};
/* Set of show/store abstract level functions for PCI Parity object */
static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
char *buffer)
char *buffer)
{
struct edac_pci_dev_attribute *edac_pci_dev;
edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
......@@ -499,8 +492,8 @@ static ssize_t edac_pci_dev_show(struct kobject *kobj, struct attribute *attr,
return -EIO;
}
static ssize_t edac_pci_dev_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
static ssize_t edac_pci_dev_store(struct kobject *kobj,
struct attribute *attr, const char *buffer, size_t count)
{
struct edac_pci_dev_attribute *edac_pci_dev;
edac_pci_dev= (struct edac_pci_dev_attribute*)attr;
......@@ -515,7 +508,6 @@ static struct sysfs_ops edac_pci_sysfs_ops = {
.store = edac_pci_dev_store
};
#define EDAC_PCI_ATTR(_name,_mode,_show,_store) \
struct edac_pci_dev_attribute edac_pci_attr_##_name = { \
.attr = {.name = __stringify(_name), .mode = _mode }, \
......@@ -558,9 +550,11 @@ EDAC_PCI_STRING_ATTR(pci_parity_blacklist,
#endif
/* PCI Parity control files */
EDAC_PCI_ATTR(check_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
EDAC_PCI_ATTR(panic_on_pci_parity,S_IRUGO|S_IWUSR,edac_pci_int_show,edac_pci_int_store);
EDAC_PCI_ATTR(pci_parity_count,S_IRUGO,edac_pci_int_show,NULL);
EDAC_PCI_ATTR(check_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show,
edac_pci_int_store);
EDAC_PCI_ATTR(panic_on_pci_parity, S_IRUGO|S_IWUSR, edac_pci_int_show,
edac_pci_int_store);
EDAC_PCI_ATTR(pci_parity_count, S_IRUGO, edac_pci_int_show, NULL);
/* Base Attributes of the memory ECC object */
static struct edac_pci_dev_attribute *edac_pci_attr[] = {
......@@ -578,9 +572,9 @@ static void edac_pci_release(struct kobject *kobj)
}
static struct kobj_type ktype_edac_pci = {
.release = edac_pci_release,
.sysfs_ops = &edac_pci_sysfs_ops,
.default_attrs = (struct attribute **) edac_pci_attr,
.release = edac_pci_release,
.sysfs_ops = &edac_pci_sysfs_ops,
.default_attrs = (struct attribute **) edac_pci_attr,
};
#endif /* DISABLE_EDAC_SYSFS */
......@@ -603,17 +597,19 @@ static int edac_sysfs_pci_setup(void)
memset(&edac_pci_kobj, 0, sizeof(edac_pci_kobj));
edac_pci_kobj.parent = &edac_class.kset.kobj;
edac_pci_kobj.ktype = &ktype_edac_pci;
err = kobject_set_name(&edac_pci_kobj, "pci");
if (!err) {
/* Instanstiate the csrow object */
/* FIXME: maybe new sysdev_create_subdir() */
err = kobject_register(&edac_pci_kobj);
if (err)
debugf1("Failed to register '.../edac/pci'\n");
else
debugf1("Registered '.../edac/pci' kobject\n");
}
return err;
}
#endif /* DISABLE_EDAC_SYSFS */
......@@ -641,6 +637,7 @@ static ssize_t csrow_ch0_dimm_label_show(struct csrow_info *csrow, char *data)
size = snprintf(data, EDAC_MC_LABEL_LEN,"%s\n",
csrow->channels[0].label);
}
return size;
}
......@@ -652,11 +649,12 @@ static ssize_t csrow_ch1_dimm_label_show(struct csrow_info *csrow, char *data)
size = snprintf(data, EDAC_MC_LABEL_LEN, "%s\n",
csrow->channels[1].label);
}
return size;
}
static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
const char *data, size_t size)
const char *data, size_t size)
{
ssize_t max_size = 0;
......@@ -665,11 +663,12 @@ static ssize_t csrow_ch0_dimm_label_store(struct csrow_info *csrow,
strncpy(csrow->channels[0].label, data, max_size);
csrow->channels[0].label[max_size] = '\0';
}
return size;
}
static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
const char *data, size_t size)
const char *data, size_t size)
{
ssize_t max_size = 0;
......@@ -678,6 +677,7 @@ static ssize_t csrow_ch1_dimm_label_store(struct csrow_info *csrow,
strncpy(csrow->channels[1].label, data, max_size);
csrow->channels[1].label[max_size] = '\0';
}
return max_size;
}
......@@ -698,6 +698,7 @@ static ssize_t csrow_ch0_ce_count_show(struct csrow_info *csrow, char *data)
if (csrow->nr_channels > 0) {
size = sprintf(data,"%u\n", csrow->channels[0].ce_count);
}
return size;
}
......@@ -708,6 +709,7 @@ static ssize_t csrow_ch1_ce_count_show(struct csrow_info *csrow, char *data)
if (csrow->nr_channels > 1) {
size = sprintf(data,"%u\n", csrow->channels[1].ce_count);
}
return size;
}
......@@ -732,7 +734,7 @@ static ssize_t csrow_edac_mode_show(struct csrow_info *csrow, char *data)
}
struct csrowdev_attribute {
struct attribute attr;
struct attribute attr;
ssize_t (*show)(struct csrow_info *,char *);
ssize_t (*store)(struct csrow_info *, const char *,size_t);
};
......@@ -742,24 +744,26 @@ struct csrowdev_attribute {
/* Set of show/store higher level functions for csrow objects */
static ssize_t csrowdev_show(struct kobject *kobj, struct attribute *attr,
char *buffer)
char *buffer)
{
struct csrow_info *csrow = to_csrow(kobj);
struct csrowdev_attribute *csrowdev_attr = to_csrowdev_attr(attr);
if (csrowdev_attr->show)
return csrowdev_attr->show(csrow, buffer);
return -EIO;
}
static ssize_t csrowdev_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
const char *buffer, size_t count)
{
struct csrow_info *csrow = to_csrow(kobj);
struct csrowdev_attribute * csrowdev_attr = to_csrowdev_attr(attr);
if (csrowdev_attr->store)
return csrowdev_attr->store(csrow, buffer, count);
return -EIO;
}
......@@ -793,7 +797,6 @@ CSROWDEV_ATTR(ch1_dimm_label,S_IRUGO|S_IWUSR,
csrow_ch1_dimm_label_show,
csrow_ch1_dimm_label_store);
/* Attributes of the CSROW<id> object */
static struct csrowdev_attribute *csrow_attr[] = {
&attr_dev_type,
......@@ -809,7 +812,6 @@ static struct csrowdev_attribute *csrow_attr[] = {
NULL,
};
/* No memory to release */
static void edac_csrow_instance_release(struct kobject *kobj)
{
......@@ -821,19 +823,18 @@ static void edac_csrow_instance_release(struct kobject *kobj)
}
static struct kobj_type ktype_csrow = {
.release = edac_csrow_instance_release,
.sysfs_ops = &csrowfs_ops,
.default_attrs = (struct attribute **) csrow_attr,
.release = edac_csrow_instance_release,
.sysfs_ops = &csrowfs_ops,
.default_attrs = (struct attribute **) csrow_attr,
};
/* Create a CSROW object under specifed edac_mc_device */
static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
struct csrow_info *csrow, int index )
struct csrow_info *csrow, int index)
{
int err = 0;
debugf0("%s()\n", __func__);
memset(&csrow->kobj, 0, sizeof(csrow->kobj));
/* generate ..../edac/mc/mc<id>/csrow<index> */
......@@ -843,9 +844,11 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
/* name this instance of csrow<id> */
err = kobject_set_name(&csrow->kobj,"csrow%d",index);
if (!err) {
/* Instanstiate the csrow object */
err = kobject_register(&csrow->kobj);
if (err)
debugf0("Failed to register CSROW%d\n",index);
else
......@@ -857,8 +860,8 @@ static int edac_create_csrow_object(struct kobject *edac_mci_kobj,
/* sysfs data structures and methods for the MCI kobjects */
static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
const char *data, size_t count )
static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
const char *data, size_t count)
{
int row, chan;
......@@ -866,16 +869,18 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci,
mci->ce_noinfo_count = 0;
mci->ue_count = 0;
mci->ce_count = 0;
for (row = 0; row < mci->nr_csrows; row++) {
struct csrow_info *ri = &mci->csrows[row];
ri->ue_count = 0;
ri->ce_count = 0;
for (chan = 0; chan < ri->nr_channels; chan++)
ri->channels[chan].ce_count = 0;
}
mci->start_time = jiffies;
mci->start_time = jiffies;
return count;
}
......@@ -933,18 +938,16 @@ static ssize_t mci_edac_capability_show(struct mem_ctl_info *mci, char *data)
p += mci_output_edac_cap(p,mci->edac_ctl_cap);
p += sprintf(p, "\n");
return p - data;
}
static ssize_t mci_edac_current_capability_show(struct mem_ctl_info *mci,
char *data)
char *data)
{
char *p = data;
p += mci_output_edac_cap(p,mci->edac_cap);
p += sprintf(p, "\n");
return p - data;
}
......@@ -961,13 +964,13 @@ static int mci_output_mtype_cap(char *buf, unsigned long mtype_cap)
return p - buf;
}
static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci, char *data)
static ssize_t mci_supported_mem_type_show(struct mem_ctl_info *mci,
char *data)
{
char *p = data;
p += mci_output_mtype_cap(p,mci->mtype_cap);
p += sprintf(p, "\n");
return p - data;
}
......@@ -981,6 +984,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
if (!csrow->nr_pages)
continue;
total_pages += csrow->nr_pages;
}
......@@ -988,7 +992,7 @@ static ssize_t mci_size_mb_show(struct mem_ctl_info *mci, char *data)
}
struct mcidev_attribute {
struct attribute attr;
struct attribute attr;
ssize_t (*show)(struct mem_ctl_info *,char *);
ssize_t (*store)(struct mem_ctl_info *, const char *,size_t);
};
......@@ -997,30 +1001,32 @@ struct mcidev_attribute {
#define to_mcidev_attr(a) container_of(a, struct mcidev_attribute, attr)
static ssize_t mcidev_show(struct kobject *kobj, struct attribute *attr,
char *buffer)
char *buffer)
{
struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
if (mcidev_attr->show)
return mcidev_attr->show(mem_ctl_info, buffer);
return -EIO;
}
static ssize_t mcidev_store(struct kobject *kobj, struct attribute *attr,
const char *buffer, size_t count)
const char *buffer, size_t count)
{
struct mem_ctl_info *mem_ctl_info = to_mci(kobj);
struct mcidev_attribute * mcidev_attr = to_mcidev_attr(attr);
if (mcidev_attr->store)
return mcidev_attr->store(mem_ctl_info, buffer, count);
return -EIO;
}
static struct sysfs_ops mci_ops = {
.show = mcidev_show,
.store = mcidev_store
.show = mcidev_show,
.store = mcidev_store
};
#define MCIDEV_ATTR(_name,_mode,_show,_store) \
......@@ -1048,7 +1054,6 @@ MCIDEV_ATTR(edac_current_capability,S_IRUGO,
MCIDEV_ATTR(supported_mem_type,S_IRUGO,
mci_supported_mem_type_show,NULL);
static struct mcidev_attribute *mci_attr[] = {
&mci_attr_reset_counters,
&mci_attr_module_name,
......@@ -1065,7 +1070,6 @@ static struct mcidev_attribute *mci_attr[] = {
NULL
};
/*
* Release of a MC controlling instance
*/
......@@ -1079,9 +1083,9 @@ static void edac_mci_instance_release(struct kobject *kobj)
}
static struct kobj_type ktype_mci = {
.release = edac_mci_instance_release,
.sysfs_ops = &mci_ops,
.default_attrs = (struct attribute **) mci_attr,
.release = edac_mci_instance_release,
.sysfs_ops = &mci_ops,
.default_attrs = (struct attribute **) mci_attr,
};
#endif /* DISABLE_EDAC_SYSFS */
......@@ -1109,11 +1113,11 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
struct kobject *edac_mci_kobj=&mci->edac_mci_kobj;
debugf0("%s() idx=%d\n", __func__, mci->mc_idx);
memset(edac_mci_kobj, 0, sizeof(*edac_mci_kobj));
/* set the name of the mc<id> object */
err = kobject_set_name(edac_mci_kobj,"mc%d",mci->mc_idx);
if (err)
return err;
......@@ -1123,12 +1127,14 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
/* register the mc<id> kobject */
err = kobject_register(edac_mci_kobj);
if (err)
return err;
/* create a symlink for the device */
err = sysfs_create_link(edac_mci_kobj, &mci->pdev->dev.kobj,
EDAC_DEVICE_SYMLINK);
if (err)
goto fail0;
......@@ -1136,12 +1142,12 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
* under the mc<id> kobject
*/
for (i = 0; i < mci->nr_csrows; i++) {
csrow = &mci->csrows[i];
/* Only expose populated CSROWs */
if (csrow->nr_pages > 0) {
err = edac_create_csrow_object(edac_mci_kobj,csrow,i);
if (err)
goto fail1;
}
......@@ -1149,7 +1155,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
return 0;
/* CSROW error: backout what has already been registered, */
fail1:
for ( i--; i >= 0; i--) {
......@@ -1164,7 +1169,6 @@ static int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
init_completion(&mci->kobj_complete);
kobject_unregister(edac_mci_kobj);
wait_for_completion(&mci->kobj_complete);
return err;
}
#endif /* DISABLE_EDAC_SYSFS */
......@@ -1199,7 +1203,6 @@ static void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
#ifdef CONFIG_EDAC_DEBUG
void edac_mc_dump_channel(struct channel_info *chan)
{
debugf4("\tchannel = %p\n", chan);
......@@ -1210,7 +1213,6 @@ void edac_mc_dump_channel(struct channel_info *chan)
}
EXPORT_SYMBOL(edac_mc_dump_channel);
void edac_mc_dump_csrow(struct csrow_info *csrow)
{
debugf4("\tcsrow = %p\n", csrow);
......@@ -1227,7 +1229,6 @@ void edac_mc_dump_csrow(struct csrow_info *csrow)
}
EXPORT_SYMBOL(edac_mc_dump_csrow);
void edac_mc_dump_mci(struct mem_ctl_info *mci)
{
debugf3("\tmci = %p\n", mci);
......@@ -1244,8 +1245,7 @@ void edac_mc_dump_mci(struct mem_ctl_info *mci)
}
EXPORT_SYMBOL(edac_mc_dump_mci);
#endif /* CONFIG_EDAC_DEBUG */
#endif /* CONFIG_EDAC_DEBUG */
/* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'.
* Adjust 'ptr' so that its alignment is at least as stringent as what the
......@@ -1254,7 +1254,7 @@ EXPORT_SYMBOL(edac_mc_dump_mci);
* If 'size' is a constant, the compiler will optimize this whole function
* down to either a no-op or the addition of a constant to the value of 'ptr'.
*/
static inline char * align_ptr (void *ptr, unsigned size)
static inline char * align_ptr(void *ptr, unsigned size)
{
unsigned align, r;
......@@ -1281,7 +1281,6 @@ static inline char * align_ptr (void *ptr, unsigned size)
return (char *) (((unsigned long) ptr) + align - r);
}
/**
* edac_mc_alloc: Allocate a struct mem_ctl_info structure
* @size_pvt: size of private storage needed
......@@ -1299,7 +1298,7 @@ static inline char * align_ptr (void *ptr, unsigned size)
* struct mem_ctl_info pointer
*/
struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
unsigned nr_chans)
unsigned nr_chans)
{
struct mem_ctl_info *mci;
struct csrow_info *csi, *csrow;
......@@ -1330,8 +1329,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
chi = (struct channel_info *) (((char *) mci) + ((unsigned long) chi));
pvt = sz_pvt ? (((char *) mci) + ((unsigned long) pvt)) : NULL;
memset(mci, 0, size); /* clear all fields */
memset(mci, 0, size); /* clear all fields */
mci->csrows = csi;
mci->pvt_info = pvt;
mci->nr_csrows = nr_csrows;
......@@ -1355,7 +1353,6 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
}
EXPORT_SYMBOL(edac_mc_alloc);
/**
* edac_mc_free: Free a previously allocated 'mci' structure
* @mci: pointer to a struct mem_ctl_info structure
......@@ -1383,7 +1380,7 @@ static struct mem_ctl_info *find_mci_by_pdev(struct pci_dev *pdev)
return NULL;
}
static int add_mc_to_global_list (struct mem_ctl_info *mci)
static int add_mc_to_global_list(struct mem_ctl_info *mci)
{
struct list_head *item, *insert_before;
struct mem_ctl_info *p;
......@@ -1426,8 +1423,7 @@ static int add_mc_to_global_list (struct mem_ctl_info *mci)
return 0;
}
static void complete_mc_list_del (struct rcu_head *head)
static void complete_mc_list_del(struct rcu_head *head)
{
struct mem_ctl_info *mci;
......@@ -1436,8 +1432,7 @@ static void complete_mc_list_del (struct rcu_head *head)
complete(&mci->complete);
}
static void del_mc_from_global_list (struct mem_ctl_info *mci)
static void del_mc_from_global_list(struct mem_ctl_info *mci)
{
list_del_rcu(&mci->link);
init_completion(&mci->complete);
......@@ -1445,7 +1440,6 @@ static void del_mc_from_global_list (struct mem_ctl_info *mci)
wait_for_completion(&mci->complete);
}
/**
* edac_mc_add_mc: Insert the 'mci' structure into the mci global list and
* create sysfs entries associated with mci structure
......@@ -1463,15 +1457,17 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
#ifdef CONFIG_EDAC_DEBUG
if (edac_debug_level >= 3)
edac_mc_dump_mci(mci);
if (edac_debug_level >= 4) {
int i;
for (i = 0; i < mci->nr_csrows; i++) {
int j;
edac_mc_dump_csrow(&mci->csrows[i]);
for (j = 0; j < mci->csrows[i].nr_channels; j++)
edac_mc_dump_channel(&mci->csrows[i].
channels[j]);
edac_mc_dump_channel(
&mci->csrows[i].channels[j]);
}
}
#endif
......@@ -1505,7 +1501,6 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
}
EXPORT_SYMBOL(edac_mc_add_mc);
/**
* edac_mc_del_mc: Remove sysfs entries for specified mci structure and
* remove mci structure from global list
......@@ -1535,9 +1530,7 @@ struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev)
}
EXPORT_SYMBOL(edac_mc_del_mc);
void edac_mc_scrub_block(unsigned long page, unsigned long offset,
u32 size)
void edac_mc_scrub_block(unsigned long page, unsigned long offset, u32 size)
{
struct page *pg;
void *virt_addr;
......@@ -1568,10 +1561,8 @@ void edac_mc_scrub_block(unsigned long page, unsigned long offset,
}
EXPORT_SYMBOL(edac_mc_scrub_block);
/* FIXME - should return -1 */
int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
unsigned long page)
int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci, unsigned long page)
{
struct csrow_info *csrows = mci->csrows;
int row, i;
......@@ -1608,14 +1599,11 @@ int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
}
EXPORT_SYMBOL(edac_mc_find_csrow_by_page);
/* FIXME - setable log (warning/emerg) levels */
/* FIXME - integrate with evlog: http://evlog.sourceforge.net/ */
void edac_mc_handle_ce(struct mem_ctl_info *mci,
unsigned long page_frame_number,
unsigned long offset_in_page,
unsigned long syndrome, int row, int channel,
const char *msg)
unsigned long page_frame_number, unsigned long offset_in_page,
unsigned long syndrome, int row, int channel, const char *msg)
{
unsigned long remapped_page;
......@@ -1630,6 +1618,7 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
edac_mc_handle_ce_no_info(mci, "INTERNAL ERROR");
return;
}
if (channel >= mci->csrows[row].nr_channels || channel < 0) {
/* something is wrong */
edac_mc_printk(mci, KERN_ERR,
......@@ -1668,28 +1657,25 @@ void edac_mc_handle_ce(struct mem_ctl_info *mci,
page_frame_number;
edac_mc_scrub_block(remapped_page, offset_in_page,
mci->csrows[row].grain);
mci->csrows[row].grain);
}
}
EXPORT_SYMBOL(edac_mc_handle_ce);
void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
const char *msg)
void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci, const char *msg)
{
if (log_ce)
edac_mc_printk(mci, KERN_WARNING,
"CE - no information available: %s\n", msg);
mci->ce_noinfo_count++;
mci->ce_count++;
}
EXPORT_SYMBOL(edac_mc_handle_ce_no_info);
void edac_mc_handle_ue(struct mem_ctl_info *mci,
unsigned long page_frame_number,
unsigned long offset_in_page, int row,
const char *msg)
unsigned long page_frame_number, unsigned long offset_in_page,
int row, const char *msg)
{
int len = EDAC_MC_LABEL_LEN * 4;
char labels[len + 1];
......@@ -1710,13 +1696,14 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
}
chars = snprintf(pos, len + 1, "%s",
mci->csrows[row].channels[0].label);
mci->csrows[row].channels[0].label);
len -= chars;
pos += chars;
for (chan = 1; (chan < mci->csrows[row].nr_channels) && (len > 0);
chan++) {
chars = snprintf(pos, len + 1, ":%s",
mci->csrows[row].channels[chan].label);
mci->csrows[row].channels[chan].label);
len -= chars;
pos += chars;
}
......@@ -1729,20 +1716,17 @@ void edac_mc_handle_ue(struct mem_ctl_info *mci,
msg);
if (panic_on_ue)
panic
("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, row %d,"
" labels \"%s\": %s\n", mci->mc_idx,
page_frame_number, offset_in_page,
mci->csrows[row].grain, row, labels, msg);
panic("EDAC MC%d: UE page 0x%lx, offset 0x%lx, grain %d, "
"row %d, labels \"%s\": %s\n", mci->mc_idx,
page_frame_number, offset_in_page,
mci->csrows[row].grain, row, labels, msg);
mci->ue_count++;
mci->csrows[row].ue_count++;
}
EXPORT_SYMBOL(edac_mc_handle_ue);
void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
const char *msg)
void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci, const char *msg)
{
if (panic_on_ue)
panic("EDAC MC%d: Uncorrected Error", mci->mc_idx);
......@@ -1755,7 +1739,6 @@ void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
}
EXPORT_SYMBOL(edac_mc_handle_ue_no_info);
#ifdef CONFIG_PCI
static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
......@@ -1766,18 +1749,22 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
where = secondary ? PCI_SEC_STATUS : PCI_STATUS;
pci_read_config_word(dev, where, &status);
/* If we get back 0xFFFF then we must suspect that the card has been pulled but
the Linux PCI layer has not yet finished cleaning up. We don't want to report
on such devices */
/* If we get back 0xFFFF then we must suspect that the card has been
* pulled but the Linux PCI layer has not yet finished cleaning up.
* We don't want to report on such devices
*/
if (status == 0xFFFF) {
u32 sanity;
pci_read_config_dword(dev, 0, &sanity);
if (sanity == 0xFFFFFFFF)
return 0;
}
status &= PCI_STATUS_DETECTED_PARITY | PCI_STATUS_SIG_SYSTEM_ERROR |
PCI_STATUS_PARITY;
PCI_STATUS_PARITY;
if (status)
/* reset only the bits we are interested in */
......@@ -1789,7 +1776,7 @@ static u16 get_pci_parity_status(struct pci_dev *dev, int secondary)
typedef void (*pci_parity_check_fn_t) (struct pci_dev *dev);
/* Clear any PCI parity errors logged by this device. */
static void edac_pci_dev_parity_clear( struct pci_dev *dev )
static void edac_pci_dev_parity_clear(struct pci_dev *dev)
{
u8 header_type;
......@@ -1890,58 +1877,55 @@ static void edac_pci_dev_parity_test(struct pci_dev *dev)
* Returns: 0 not found
* 1 found on list
*/
static int check_dev_on_list(struct edac_pci_device_list *list, int free_index,
struct pci_dev *dev)
{
int i;
int rc = 0; /* Assume not found */
unsigned short vendor=dev->vendor;
unsigned short device=dev->device;
/* Scan the list, looking for a vendor/device match
*/
for (i = 0; i < free_index; i++, list++ ) {
if ( (list->vendor == vendor ) &&
(list->device == device )) {
rc = 1;
break;
}
}
static int check_dev_on_list(struct edac_pci_device_list *list,
int free_index, struct pci_dev *dev)
{
int i;
int rc = 0; /* Assume not found */
unsigned short vendor=dev->vendor;
unsigned short device=dev->device;
/* Scan the list, looking for a vendor/device match */
for (i = 0; i < free_index; i++, list++ ) {
if ((list->vendor == vendor ) && (list->device == device )) {
rc = 1;
break;
}
}
return rc;
return rc;
}
/*
* pci_dev parity list iterator
* Scan the PCI device list for one iteration, looking for SERRORs
* Scan the PCI device list for one iteration, looking for SERRORs
* Master Parity ERRORS or Parity ERRORs on primary or secondary devices
*/
static inline void edac_pci_dev_parity_iterator(pci_parity_check_fn_t fn)
{
struct pci_dev *dev=NULL;
struct pci_dev *dev = NULL;
/* request for kernel access to the next PCI device, if any,
* and while we are looking at it have its reference count
* bumped until we are done with it
*/
while((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
/* if whitelist exists then it has priority, so only scan those
* devices on the whitelist
*/
if (pci_whitelist_count > 0 ) {
if (check_dev_on_list(pci_whitelist,
/* if whitelist exists then it has priority, so only scan
* those devices on the whitelist
*/
if (pci_whitelist_count > 0 ) {
if (check_dev_on_list(pci_whitelist,
pci_whitelist_count, dev))
fn(dev);
} else {
} else {
/*
* if no whitelist, then check if this devices is
* blacklisted
*/
if (!check_dev_on_list(pci_blacklist,
if (!check_dev_on_list(pci_blacklist,
pci_blacklist_count, dev))
fn(dev);
}
}
}
}
......@@ -1972,7 +1956,6 @@ static void do_pci_parity_check(void)
}
}
static inline void clear_pci_parity_errors(void)
{
/* Clear any PCI bus parity errors that devices initially have logged
......@@ -1981,34 +1964,29 @@ static inline void clear_pci_parity_errors(void)
edac_pci_dev_parity_iterator(edac_pci_dev_parity_clear);
}
#else /* CONFIG_PCI */
static inline void do_pci_parity_check(void)
{
/* no-op */
}
static inline void clear_pci_parity_errors(void)
{
/* no-op */
}
#endif /* CONFIG_PCI */
/*
* Iterate over all MC instances and check for ECC, et al, errors
*/
static inline void check_mc_devices (void)
static inline void check_mc_devices(void)
{
struct list_head *item;
struct mem_ctl_info *mci;
debugf3("%s()\n", __func__);
down(&mem_ctls_mutex);
list_for_each(item, &mc_devices) {
......@@ -2021,7 +1999,6 @@ static inline void check_mc_devices (void)
up(&mem_ctls_mutex);
}
/*
* Check MC status every poll_msec.
* Check PCI status every poll_msec as well.
......@@ -2084,6 +2061,7 @@ static int __init edac_mc_init(void)
/* create our kernel thread */
edac_thread = kthread_run(edac_kernel_thread, NULL, "kedac");
if (IS_ERR(edac_thread)) {
/* remove the sysfs entries */
edac_sysfs_memctrl_teardown();
......@@ -2094,7 +2072,6 @@ static int __init edac_mc_init(void)
return 0;
}
/*
* edac_mc_exit()
* module exit/termination functioni
......@@ -2102,7 +2079,6 @@ static int __init edac_mc_init(void)
static void __exit edac_mc_exit(void)
{
debugf0("%s()\n", __func__);
kthread_stop(edac_thread);
/* tear down the sysfs device */
......@@ -2110,15 +2086,12 @@ static void __exit edac_mc_exit(void)
edac_sysfs_pci_teardown();
}
module_init(edac_mc_init);
module_exit(edac_mc_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh et al\n"
"Based on.work by Dan Hollis et al");
"Based on work by Dan Hollis et al");
MODULE_DESCRIPTION("Core library routines for MC reporting");
module_param(panic_on_ue, int, 0644);
......
......@@ -15,11 +15,9 @@
*
*/
#ifndef _EDAC_MC_H_
#define _EDAC_MC_H_
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/types.h>
......@@ -33,7 +31,6 @@
#include <linux/completion.h>
#include <linux/kobject.h>
#define EDAC_MC_LABEL_LEN 31
#define MC_PROC_NAME_MAX_LEN 7
......@@ -44,13 +41,13 @@
#endif
#define edac_printk(level, prefix, fmt, arg...) \
printk(level "EDAC " prefix ": " fmt, ##arg)
printk(level "EDAC " prefix ": " fmt, ##arg)
#define edac_mc_printk(mci, level, fmt, arg...) \
printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg)
printk(level "EDAC MC%d: " fmt, mci->mc_idx, ##arg)
#define edac_mc_chipset_printk(mci, level, prefix, fmt, arg...) \
printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg)
printk(level "EDAC " prefix " MC%d: " fmt, mci->mc_idx, ##arg)
/* prefixes for edac_printk() and edac_mc_printk() */
#define EDAC_MC "MC"
......@@ -71,14 +68,16 @@ extern int edac_debug_level;
#define debugf2( ... ) edac_debug_printk(2, __VA_ARGS__ )
#define debugf3( ... ) edac_debug_printk(3, __VA_ARGS__ )
#define debugf4( ... ) edac_debug_printk(4, __VA_ARGS__ )
#else /* !CONFIG_EDAC_DEBUG */
#else /* !CONFIG_EDAC_DEBUG */
#define debugf0( ... )
#define debugf1( ... )
#define debugf2( ... )
#define debugf3( ... )
#define debugf4( ... )
#endif /* !CONFIG_EDAC_DEBUG */
#endif /* !CONFIG_EDAC_DEBUG */
#define edac_xstr(s) edac_str(s)
#define edac_str(s) #s
......@@ -86,7 +85,8 @@ extern int edac_debug_level;
#define BIT(x) (1 << (x))
#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, PCI_DEVICE_ID_ ## vend ## _ ## dev
#define PCI_VEND_DEV(vend, dev) PCI_VENDOR_ID_ ## vend, \
PCI_DEVICE_ID_ ## vend ## _ ## dev
/* memory devices */
enum dev_type {
......@@ -136,7 +136,6 @@ enum mem_type {
#define MEM_FLAG_RDDR BIT(MEM_RDDR)
#define MEM_FLAG_RMBS BIT(MEM_RMBS)
/* chipset Error Detection and Correction capabilities and mode */
enum edac_type {
EDAC_UNKNOWN = 0, /* Unknown if ECC is available */
......@@ -161,7 +160,6 @@ enum edac_type {
#define EDAC_FLAG_S8ECD8ED BIT(EDAC_S8ECD8ED)
#define EDAC_FLAG_S16ECD16ED BIT(EDAC_S16ECD16ED)
/* scrubbing capabilities */
enum scrub_type {
SCRUB_UNKNOWN = 0, /* Unknown if scrubber is available */
......@@ -269,20 +267,19 @@ enum scrub_type {
* PS - I enjoyed writing all that about as much as you enjoyed reading it.
*/
struct channel_info {
int chan_idx; /* channel index */
u32 ce_count; /* Correctable Errors for this CHANNEL */
char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
char label[EDAC_MC_LABEL_LEN + 1]; /* DIMM label on motherboard */
struct csrow_info *csrow; /* the parent */
};
struct csrow_info {
unsigned long first_page; /* first page number in dimm */
unsigned long last_page; /* last page number in dimm */
unsigned long page_mask; /* used for interleaving -
0UL for non intlv */
* 0UL for non intlv
*/
u32 nr_pages; /* number of pages in csrow */
u32 grain; /* granularity of reported error in bytes */
int csrow_idx; /* the chip-select row */
......@@ -301,18 +298,18 @@ struct csrow_info {
struct channel_info *channels;
};
struct mem_ctl_info {
struct list_head link; /* for global list of mem_ctl_info structs */
unsigned long mtype_cap; /* memory types supported by mc */
unsigned long edac_ctl_cap; /* Mem controller EDAC capabilities */
unsigned long edac_cap; /* configuration capabilities - this is
closely related to edac_ctl_cap. The
difference is that the controller
may be capable of s4ecd4ed which would
be listed in edac_ctl_cap, but if
channels aren't capable of s4ecd4ed then the
edac_cap would not have that capability. */
* closely related to edac_ctl_cap. The
* difference is that the controller may be
* capable of s4ecd4ed which would be listed
* in edac_ctl_cap, but if channels aren't
* capable of s4ecd4ed then the edac_cap would
* not have that capability.
*/
unsigned long scrub_cap; /* chipset scrub capabilities */
enum scrub_type scrub_mode; /* current scrub mode */
......@@ -324,7 +321,7 @@ struct mem_ctl_info {
*/
/* FIXME - why not send the phys page to begin with? */
unsigned long (*ctl_page_to_phys) (struct mem_ctl_info * mci,
unsigned long page);
unsigned long page);
int mc_idx;
int nr_csrows;
struct csrow_info *csrows;
......@@ -356,67 +353,66 @@ struct mem_ctl_info {
struct completion kobj_complete;
};
/* write all or some bits in a byte-register*/
static inline void pci_write_bits8(struct pci_dev *pdev, int offset,
u8 value, u8 mask)
static inline void pci_write_bits8(struct pci_dev *pdev, int offset, u8 value,
u8 mask)
{
if (mask != 0xff) {
u8 buf;
pci_read_config_byte(pdev, offset, &buf);
value &= mask;
buf &= ~mask;
value |= buf;
}
pci_write_config_byte(pdev, offset, value);
}
/* write all or some bits in a word-register*/
static inline void pci_write_bits16(struct pci_dev *pdev, int offset,
u16 value, u16 mask)
u16 value, u16 mask)
{
if (mask != 0xffff) {
u16 buf;
pci_read_config_word(pdev, offset, &buf);
value &= mask;
buf &= ~mask;
value |= buf;
}
pci_write_config_word(pdev, offset, value);
}
/* write all or some bits in a dword-register*/
static inline void pci_write_bits32(struct pci_dev *pdev, int offset,
u32 value, u32 mask)
u32 value, u32 mask)
{
if (mask != 0xffff) {
u32 buf;
pci_read_config_dword(pdev, offset, &buf);
value &= mask;
buf &= ~mask;
value |= buf;
}
pci_write_config_dword(pdev, offset, value);
}
#ifdef CONFIG_EDAC_DEBUG
void edac_mc_dump_channel(struct channel_info *chan);
void edac_mc_dump_mci(struct mem_ctl_info *mci);
void edac_mc_dump_csrow(struct csrow_info *csrow);
#endif /* CONFIG_EDAC_DEBUG */
#endif /* CONFIG_EDAC_DEBUG */
extern int edac_mc_add_mc(struct mem_ctl_info *mci);
extern struct mem_ctl_info * edac_mc_del_mc(struct pci_dev *pdev);
extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
unsigned long page);
extern void edac_mc_scrub_block(unsigned long page,
unsigned long offset, u32 size);
unsigned long page);
extern void edac_mc_scrub_block(unsigned long page, unsigned long offset,
u32 size);
/*
* The no info errors are used when error overflows are reported.
......@@ -429,31 +425,25 @@ extern void edac_mc_scrub_block(unsigned long page,
* statement clutter and extra function arguments.
*/
extern void edac_mc_handle_ce(struct mem_ctl_info *mci,
unsigned long page_frame_number,
unsigned long offset_in_page,
unsigned long syndrome,
int row, int channel, const char *msg);
unsigned long page_frame_number, unsigned long offset_in_page,
unsigned long syndrome, int row, int channel,
const char *msg);
extern void edac_mc_handle_ce_no_info(struct mem_ctl_info *mci,
const char *msg);
const char *msg);
extern void edac_mc_handle_ue(struct mem_ctl_info *mci,
unsigned long page_frame_number,
unsigned long offset_in_page,
int row, const char *msg);
unsigned long page_frame_number, unsigned long offset_in_page,
int row, const char *msg);
extern void edac_mc_handle_ue_no_info(struct mem_ctl_info *mci,
const char *msg);
const char *msg);
/*
* This kmalloc's and initializes all the structures.
* Can't be used if all structures don't have the same lifetime.
*/
extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt,
unsigned nr_csrows, unsigned nr_chans);
extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
unsigned nr_chans);
/* Free an mc previously allocated by edac_mc_alloc() */
extern void edac_mc_free(struct mem_ctl_info *mci);
#endif /* _EDAC_MC_H_ */
......@@ -9,7 +9,6 @@
* by Thayne Harbaugh of Linux Networx. (http://lnxi.com)
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
......@@ -18,14 +17,11 @@
#include <linux/slab.h>
#include "edac_mc.h"
#define i82860_printk(level, fmt, arg...) \
edac_printk(level, "i82860", fmt, ##arg)
edac_printk(level, "i82860", fmt, ##arg)
#define i82860_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
edac_mc_chipset_printk(mci, level, "i82860", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_82860_0
#define PCI_DEVICE_ID_INTEL_82860_0 0x2531
......@@ -56,13 +52,15 @@ struct i82860_error_info {
static const struct i82860_dev_info i82860_devs[] = {
[I82860] = {
.ctl_name = "i82860"},
.ctl_name = "i82860"
},
};
static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
has already registered driver */
* has already registered driver
*/
static void i82860_get_error_info (struct mem_ctl_info *mci,
static void i82860_get_error_info(struct mem_ctl_info *mci,
struct i82860_error_info *info)
{
/*
......@@ -84,14 +82,15 @@ static void i82860_get_error_info (struct mem_ctl_info *mci,
*/
if (!(info->errsts2 & 0x0003))
return;
if ((info->errsts ^ info->errsts2) & 0x0003) {
pci_read_config_dword(mci->pdev, I82860_EAP, &info->eap);
pci_read_config_word(mci->pdev, I82860_DERRCTL_STS,
&info->derrsyn);
&info->derrsyn);
}
}
static int i82860_process_error_info (struct mem_ctl_info *mci,
static int i82860_process_error_info(struct mem_ctl_info *mci,
struct i82860_error_info *info, int handle_errors)
{
int row;
......@@ -113,8 +112,8 @@ static int i82860_process_error_info (struct mem_ctl_info *mci,
if (info->errsts & 0x0002)
edac_mc_handle_ue(mci, info->eap, 0, row, "i82860 UE");
else
edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
0, "i82860 UE");
edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row, 0,
"i82860 UE");
return 1;
}
......@@ -147,15 +146,14 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
going to make 1 channel for group.
*/
mci = edac_mc_alloc(0, 16, 1);
if (!mci)
return -ENOMEM;
debugf3("%s(): init mci\n", __func__);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_DDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
/* I"m not sure about this but I think that all RDRAM is SECDED */
mci->edac_cap = EDAC_FLAG_SECDED;
......@@ -182,12 +180,13 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
struct csrow_info *csrow = &mci->csrows[index];
pci_read_config_word(mci->pdev, I82860_GBA + index * 2,
&value);
&value);
cumul_size = (value & I82860_GBA_MASK) <<
(I82860_GBA_SHIFT - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
cumul_size);
if (cumul_size == last_cumul_size)
continue; /* not populated */
......@@ -195,7 +194,7 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
csrow->grain = 1 << 12; /* I82860_EAP has 4KiB reolution */
csrow->mtype = MEM_RMBS;
csrow->dtype = DEV_UNKNOWN;
csrow->edac_mode = mchcfg_ddim ? EDAC_SECDED : EDAC_NONE;
......@@ -211,23 +210,27 @@ static int i82860_probe1(struct pci_dev *pdev, int dev_idx)
debugf3("%s(): success\n", __func__);
rc = 0;
}
return rc;
}
/* returns count (>= 0), or negative on error */
static int __devinit i82860_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
const struct pci_device_id *ent)
{
int rc;
debugf0("%s()\n", __func__);
i82860_printk(KERN_INFO, "i82860 init one\n");
if(pci_enable_device(pdev) < 0)
if (pci_enable_device(pdev) < 0)
return -EIO;
rc = i82860_probe1(pdev, ent->driver_data);
if(rc == 0)
if (rc == 0)
mci_pdev = pci_dev_get(pdev);
return rc;
}
......@@ -244,9 +247,13 @@ static void __devexit i82860_remove_one(struct pci_dev *pdev)
}
static const struct pci_device_id i82860_pci_tbl[] __devinitdata = {
{PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
I82860},
{0,} /* 0 terminated list. */
{
PCI_VEND_DEV(INTEL, 82860_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
I82860
},
{
0,
} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, i82860_pci_tbl);
......@@ -263,24 +270,29 @@ static int __init i82860_init(void)
int pci_rc;
debugf3("%s()\n", __func__);
if ((pci_rc = pci_register_driver(&i82860_driver)) < 0)
goto fail0;
if (!mci_pdev) {
mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82860_0, NULL);
PCI_DEVICE_ID_INTEL_82860_0, NULL);
if (mci_pdev == NULL) {
debugf0("860 pci_get_device fail\n");
pci_rc = -ENODEV;
goto fail1;
}
pci_rc = i82860_init_one(mci_pdev, i82860_pci_tbl);
if (pci_rc < 0) {
debugf0("860 init fail\n");
pci_rc = -ENODEV;
goto fail1;
}
}
return 0;
fail1:
......@@ -307,6 +319,6 @@ module_init(i82860_init);
module_exit(i82860_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR
("Red Hat Inc. (http://www.redhat.com) Ben Woodard <woodard@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com) "
"Ben Woodard <woodard@redhat.com>");
MODULE_DESCRIPTION("ECC support for Intel 82860 memory hub controllers");
......@@ -13,26 +13,19 @@
* Note: E7210 appears same as D82875P - zhenyu.z.wang at intel.com
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include "edac_mc.h"
#define i82875p_printk(level, fmt, arg...) \
edac_printk(level, "i82875p", fmt, ##arg)
edac_printk(level, "i82875p", fmt, ##arg)
#define i82875p_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg)
edac_mc_chipset_printk(mci, level, "i82875p", fmt, ##arg)
#ifndef PCI_DEVICE_ID_INTEL_82875_0
#define PCI_DEVICE_ID_INTEL_82875_0 0x2578
......@@ -42,11 +35,9 @@
#define PCI_DEVICE_ID_INTEL_82875_6 0x257e
#endif /* PCI_DEVICE_ID_INTEL_82875_6 */
/* four csrows in dual channel, eight in single channel */
#define I82875P_NR_CSROWS(nr_chans) (8/(nr_chans))
/* Intel 82875p register addresses - device 0 function 0 - DRAM Controller */
#define I82875P_EAP 0x58 /* Error Address Pointer (32b)
*
......@@ -95,7 +86,6 @@
* 0 reserved
*/
/* Intel 82875p register addresses - device 6 function 0 - DRAM Controller */
#define I82875P_PCICMD6 0x04 /* PCI Command Register (16b)
*
......@@ -159,23 +149,19 @@
* 1:0 DRAM type 01=DDR
*/
enum i82875p_chips {
I82875P = 0,
};
struct i82875p_pvt {
struct pci_dev *ovrfl_pdev;
void __iomem *ovrfl_window;
};
struct i82875p_dev_info {
const char *ctl_name;
};
struct i82875p_error_info {
u16 errsts;
u32 eap;
......@@ -184,17 +170,19 @@ struct i82875p_error_info {
u16 errsts2;
};
static const struct i82875p_dev_info i82875p_devs[] = {
[I82875P] = {
.ctl_name = "i82875p"},
.ctl_name = "i82875p"
},
};
static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code
has already registered driver */
static struct pci_dev *mci_pdev = NULL; /* init dev: in case that AGP code has
* already registered driver
*/
static int i82875p_registered = 1;
static void i82875p_get_error_info (struct mem_ctl_info *mci,
static void i82875p_get_error_info(struct mem_ctl_info *mci,
struct i82875p_error_info *info)
{
/*
......@@ -218,15 +206,16 @@ static void i82875p_get_error_info (struct mem_ctl_info *mci,
*/
if (!(info->errsts2 & 0x0081))
return;
if ((info->errsts ^ info->errsts2) & 0x0081) {
pci_read_config_dword(mci->pdev, I82875P_EAP, &info->eap);
pci_read_config_byte(mci->pdev, I82875P_DES, &info->des);
pci_read_config_byte(mci->pdev, I82875P_DERRSYN,
&info->derrsyn);
&info->derrsyn);
}
}
static int i82875p_process_error_info (struct mem_ctl_info *mci,
static int i82875p_process_error_info(struct mem_ctl_info *mci,
struct i82875p_error_info *info, int handle_errors)
{
int row, multi_chan;
......@@ -251,13 +240,12 @@ static int i82875p_process_error_info (struct mem_ctl_info *mci,
edac_mc_handle_ue(mci, info->eap, 0, row, "i82875p UE");
else
edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
multi_chan ? (info->des & 0x1) : 0,
"i82875p CE");
multi_chan ? (info->des & 0x1) : 0,
"i82875p CE");
return 1;
}
static void i82875p_check(struct mem_ctl_info *mci)
{
struct i82875p_error_info info;
......@@ -267,7 +255,6 @@ static void i82875p_check(struct mem_ctl_info *mci)
i82875p_process_error_info(mci, &info, 1);
}
#ifdef CONFIG_PROC_FS
extern int pci_proc_attach_device(struct pci_dev *);
#endif
......@@ -281,7 +268,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
unsigned long last_cumul_size;
struct pci_dev *ovrfl_pdev;
void __iomem *ovrfl_window = NULL;
u32 drc;
u32 drc_chan; /* Number of channels 0=1chan,1=2chan */
u32 nr_chans;
......@@ -289,7 +275,6 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
struct i82875p_error_info discard;
debugf0("%s()\n", __func__);
ovrfl_pdev = pci_get_device(PCI_VEND_DEV(INTEL, 82875_6), NULL);
if (!ovrfl_pdev) {
......@@ -301,22 +286,23 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
*/
pci_write_bits8(pdev, 0xf4, 0x2, 0x2);
ovrfl_pdev =
pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
pci_scan_single_device(pdev->bus, PCI_DEVFN(6, 0));
if (!ovrfl_pdev)
return -ENODEV;
}
#ifdef CONFIG_PROC_FS
if (!ovrfl_pdev->procent && pci_proc_attach_device(ovrfl_pdev)) {
i82875p_printk(KERN_ERR,
"%s(): Failed to attach overflow device\n",
__func__);
"%s(): Failed to attach overflow device\n", __func__);
return -ENODEV;
}
#endif /* CONFIG_PROC_FS */
#endif
/* CONFIG_PROC_FS */
if (pci_enable_device(ovrfl_pdev)) {
i82875p_printk(KERN_ERR,
"%s(): Failed to enable overflow device\n",
__func__);
"%s(): Failed to enable overflow device\n", __func__);
return -ENODEV;
}
......@@ -325,13 +311,14 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
goto fail0;
#endif
}
/* cache is irrelevant for PCI bus reads/writes */
ovrfl_window = ioremap_nocache(pci_resource_start(ovrfl_pdev, 0),
pci_resource_len(ovrfl_pdev, 0));
pci_resource_len(ovrfl_pdev, 0));
if (!ovrfl_window) {
i82875p_printk(KERN_ERR, "%s(): Failed to ioremap bar6\n",
__func__);
__func__);
goto fail1;
}
......@@ -339,10 +326,10 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
drc = readl(ovrfl_window + I82875P_DRC);
drc_chan = ((drc >> 21) & 0x1);
nr_chans = drc_chan + 1;
drc_ddim = (drc >> 18) & 0x1;
drc_ddim = (drc >> 18) & 0x1;
mci = edac_mc_alloc(sizeof(*pvt), I82875P_NR_CSROWS(nr_chans),
nr_chans);
nr_chans);
if (!mci) {
rc = -ENOMEM;
......@@ -350,10 +337,8 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
}
debugf3("%s(): init mci\n", __func__);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_DDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
mci->edac_cap = EDAC_FLAG_UNKNOWN;
/* adjust FLAGS */
......@@ -363,9 +348,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
mci->ctl_name = i82875p_devs[dev_idx].ctl_name;
mci->edac_check = i82875p_check;
mci->ctl_page_to_phys = NULL;
debugf3("%s(): init pvt\n", __func__);
pvt = (struct i82875p_pvt *) mci->pvt_info;
pvt->ovrfl_pdev = ovrfl_pdev;
pvt->ovrfl_window = ovrfl_window;
......@@ -385,6 +368,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
cumul_size = value << (I82875P_DRB_SHIFT - PAGE_SHIFT);
debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
cumul_size);
if (cumul_size == last_cumul_size)
continue; /* not populated */
......@@ -392,7 +376,7 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
csrow->last_page = cumul_size - 1;
csrow->nr_pages = cumul_size - last_cumul_size;
last_cumul_size = cumul_size;
csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
csrow->grain = 1 << 12; /* I82875P_EAP has 4KiB reolution */
csrow->mtype = MEM_DDR;
csrow->dtype = DEV_UNKNOWN;
csrow->edac_mode = drc_ddim ? EDAC_SECDED : EDAC_NONE;
......@@ -426,25 +410,26 @@ static int i82875p_probe1(struct pci_dev *pdev, int dev_idx)
return rc;
}
/* returns count (>= 0), or negative on error */
static int __devinit i82875p_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
const struct pci_device_id *ent)
{
int rc;
debugf0("%s()\n", __func__);
i82875p_printk(KERN_INFO, "i82875p init one\n");
if(pci_enable_device(pdev) < 0)
if (pci_enable_device(pdev) < 0)
return -EIO;
rc = i82875p_probe1(pdev, ent->driver_data);
if (mci_pdev == NULL)
mci_pdev = pci_dev_get(pdev);
return rc;
}
static void __devexit i82875p_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
......@@ -456,6 +441,7 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
return;
pvt = (struct i82875p_pvt *) mci->pvt_info;
if (pvt->ovrfl_window)
iounmap(pvt->ovrfl_window);
......@@ -470,16 +456,18 @@ static void __devexit i82875p_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
static const struct pci_device_id i82875p_pci_tbl[] __devinitdata = {
{PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
I82875P},
{0,} /* 0 terminated list. */
{
PCI_VEND_DEV(INTEL, 82875_0), PCI_ANY_ID, PCI_ANY_ID, 0, 0,
I82875P
},
{
0,
} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, i82875p_pci_tbl);
static struct pci_driver i82875p_driver = {
.name = EDAC_MOD_STR,
.probe = i82875p_init_one,
......@@ -487,31 +475,35 @@ static struct pci_driver i82875p_driver = {
.id_table = i82875p_pci_tbl,
};
static int __init i82875p_init(void)
{
int pci_rc;
debugf3("%s()\n", __func__);
pci_rc = pci_register_driver(&i82875p_driver);
if (pci_rc < 0)
goto fail0;
if (mci_pdev == NULL) {
mci_pdev =
pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82875_0, NULL);
mci_pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82875_0, NULL);
if (!mci_pdev) {
debugf0("875p pci_get_device fail\n");
pci_rc = -ENODEV;
goto fail1;
}
pci_rc = i82875p_init_one(mci_pdev, i82875p_pci_tbl);
if (pci_rc < 0) {
debugf0("875p init fail\n");
pci_rc = -ENODEV;
goto fail1;
}
}
return 0;
fail1:
......@@ -524,23 +516,21 @@ static int __init i82875p_init(void)
return pci_rc;
}
static void __exit i82875p_exit(void)
{
debugf3("%s()\n", __func__);
pci_unregister_driver(&i82875p_driver);
if (!i82875p_registered) {
i82875p_remove_one(mci_pdev);
pci_dev_put(mci_pdev);
}
}
module_init(i82875p_init);
module_exit(i82875p_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Linux Networx (http://lnxi.com) Thayne Harbaugh");
MODULE_DESCRIPTION("MC support for Intel 82875 memory hub controllers");
......@@ -18,19 +18,16 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include "edac_mc.h"
#define r82600_printk(level, fmt, arg...) \
edac_printk(level, "r82600", fmt, ##arg)
edac_printk(level, "r82600", fmt, ##arg)
#define r82600_mc_printk(mci, level, fmt, arg...) \
edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg)
edac_mc_chipset_printk(mci, level, "r82600", fmt, ##arg)
/* Radisys say "The 82600 integrates a main memory SDRAM controller that
* supports up to four banks of memory. The four banks can support a mix of
......@@ -132,10 +129,8 @@ struct r82600_error_info {
u32 eapr;
};
static unsigned int disable_hardware_scrub = 0;
static void r82600_get_error_info (struct mem_ctl_info *mci,
struct r82600_error_info *info)
{
......@@ -144,17 +139,16 @@ static void r82600_get_error_info (struct mem_ctl_info *mci,
if (info->eapr & BIT(0))
/* Clear error to allow next error to be reported [p.62] */
pci_write_bits32(mci->pdev, R82600_EAP,
((u32) BIT(0) & (u32) BIT(1)),
((u32) BIT(0) & (u32) BIT(1)));
((u32) BIT(0) & (u32) BIT(1)),
((u32) BIT(0) & (u32) BIT(1)));
if (info->eapr & BIT(1))
/* Clear error to allow next error to be reported [p.62] */
pci_write_bits32(mci->pdev, R82600_EAP,
((u32) BIT(0) & (u32) BIT(1)),
((u32) BIT(0) & (u32) BIT(1)));
((u32) BIT(0) & (u32) BIT(1)),
((u32) BIT(0) & (u32) BIT(1)));
}
static int r82600_process_error_info (struct mem_ctl_info *mci,
struct r82600_error_info *info, int handle_errors)
{
......@@ -173,26 +167,25 @@ static int r82600_process_error_info (struct mem_ctl_info *mci,
* granularity (upper 19 bits only) */
page = eapaddr >> PAGE_SHIFT;
if (info->eapr & BIT(0)) { /* CE? */
if (info->eapr & BIT(0)) { /* CE? */
error_found = 1;
if (handle_errors)
edac_mc_handle_ce(
mci, page, 0, /* not avail */
syndrome,
edac_mc_find_csrow_by_page(mci, page),
0, /* channel */
mci->ctl_name);
edac_mc_handle_ce(mci, page, 0, /* not avail */
syndrome,
edac_mc_find_csrow_by_page(mci, page),
0, /* channel */
mci->ctl_name);
}
if (info->eapr & BIT(1)) { /* UE? */
if (info->eapr & BIT(1)) { /* UE? */
error_found = 1;
if (handle_errors)
/* 82600 doesn't give enough info */
edac_mc_handle_ue(mci, page, 0,
edac_mc_find_csrow_by_page(mci, page),
mci->ctl_name);
edac_mc_find_csrow_by_page(mci, page),
mci->ctl_name);
}
return error_found;
......@@ -222,21 +215,15 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
struct r82600_error_info discard;
debugf0("%s()\n", __func__);
pci_read_config_byte(pdev, R82600_DRAMC, &dramcr);
pci_read_config_dword(pdev, R82600_EAP, &eapr);
ecc_on = dramcr & BIT(5);
reg_sdram = dramcr & BIT(4);
scrub_disabled = eapr & BIT(31);
sdram_refresh_rate = dramcr & (BIT(0) | BIT(1));
debugf2("%s(): sdram refresh rate = %#0x\n", __func__,
sdram_refresh_rate);
debugf2("%s(): DRAMC register = %#0x\n", __func__, dramcr);
mci = edac_mc_alloc(0, R82600_NR_CSROWS, R82600_NR_CHANS);
if (mci == NULL) {
......@@ -245,19 +232,19 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
}
debugf0("%s(): mci = %p\n", __func__, mci);
mci->pdev = pdev;
mci->mtype_cap = MEM_FLAG_RDDR | MEM_FLAG_DDR;
mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
/* FIXME try to work out if the chip leads have been *
* used for COM2 instead on this board? [MA6?] MAYBE: */
/* FIXME try to work out if the chip leads have been used for COM2
* instead on this board? [MA6?] MAYBE:
*/
/* On the R82600, the pins for memory bits 72:65 - i.e. the *
* EC bits are shared with the pins for COM2 (!), so if COM2 *
* is enabled, we assume COM2 is wired up, and thus no EDAC *
* is possible. */
mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED;
if (ecc_on) {
if (scrub_disabled)
debugf3("%s(): mci = %p - Scrubbing disabled! EAP: "
......@@ -295,7 +282,6 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
continue;
row_base = row_high_limit_last;
csrow->first_page = row_base >> PAGE_SHIFT;
csrow->last_page = (row_high_limit >> PAGE_SHIFT) - 1;
csrow->nr_pages = csrow->last_page - csrow->first_page + 1;
......@@ -338,7 +324,7 @@ static int r82600_probe1(struct pci_dev *pdev, int dev_idx)
/* returns count (>= 0), or negative on error */
static int __devinit r82600_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
const struct pci_device_id *ent)
{
debugf0("%s()\n", __func__);
......@@ -346,7 +332,6 @@ static int __devinit r82600_init_one(struct pci_dev *pdev,
return r82600_probe1(pdev, ent->driver_data);
}
static void __devexit r82600_remove_one(struct pci_dev *pdev)
{
struct mem_ctl_info *mci;
......@@ -359,15 +344,17 @@ static void __devexit r82600_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
static const struct pci_device_id r82600_pci_tbl[] __devinitdata = {
{PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)},
{0,} /* 0 terminated list. */
{
PCI_DEVICE(PCI_VENDOR_ID_RADISYS, R82600_BRIDGE_ID)
},
{
0,
} /* 0 terminated list. */
};
MODULE_DEVICE_TABLE(pci, r82600_pci_tbl);
static struct pci_driver r82600_driver = {
.name = EDAC_MOD_STR,
.probe = r82600_init_one,
......@@ -375,26 +362,22 @@ static struct pci_driver r82600_driver = {
.id_table = r82600_pci_tbl,
};
static int __init r82600_init(void)
{
return pci_register_driver(&r82600_driver);
}
static void __exit r82600_exit(void)
{
pci_unregister_driver(&r82600_driver);
}
module_init(r82600_init);
module_exit(r82600_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Tim Small <tim@buttersideup.com> - WPAD Ltd. "
"on behalf of EADS Astrium");
"on behalf of EADS Astrium");
MODULE_DESCRIPTION("MC support for Radisys 82600 memory controllers");
module_param(disable_hardware_scrub, bool, 0644);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment