linux/drivers/edac/amd8111_edac.c
<<
>>
Prefs
   1/*
   2 * amd8111_edac.c, AMD8111 Hyper Transport chip EDAC kernel module
   3 *
   4 * Copyright (c) 2008 Wind River Systems, Inc.
   5 *
   6 * Authors:     Cao Qingtao <qingtao.cao@windriver.com>
   7 *              Benjamin Walsh <benjamin.walsh@windriver.com>
   8 *              Hu Yongqi <yongqi.hu@windriver.com>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License version 2 as
  12 * published by the Free Software Foundation.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17 * See the GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23
  24#include <linux/module.h>
  25#include <linux/init.h>
  26#include <linux/interrupt.h>
  27#include <linux/bitops.h>
  28#include <linux/edac.h>
  29#include <linux/pci_ids.h>
  30#include <asm/io.h>
  31
  32#include "edac_core.h"
  33#include "edac_module.h"
  34#include "amd8111_edac.h"
  35
  36#define AMD8111_EDAC_REVISION   " Ver: 1.0.0"
  37#define AMD8111_EDAC_MOD_STR    "amd8111_edac"
  38
  39#define PCI_DEVICE_ID_AMD_8111_PCI      0x7460
  40
  41enum amd8111_edac_devs {
  42        LPC_BRIDGE = 0,
  43};
  44
  45enum amd8111_edac_pcis {
  46        PCI_BRIDGE = 0,
  47};
  48
  49/* Wrapper functions for accessing PCI configuration space */
  50static int edac_pci_read_dword(struct pci_dev *dev, int reg, u32 *val32)
  51{
  52        int ret;
  53
  54        ret = pci_read_config_dword(dev, reg, val32);
  55        if (ret != 0)
  56                printk(KERN_ERR AMD8111_EDAC_MOD_STR
  57                        " PCI Access Read Error at 0x%x\n", reg);
  58
  59        return ret;
  60}
  61
  62static void edac_pci_read_byte(struct pci_dev *dev, int reg, u8 *val8)
  63{
  64        int ret;
  65
  66        ret = pci_read_config_byte(dev, reg, val8);
  67        if (ret != 0)
  68                printk(KERN_ERR AMD8111_EDAC_MOD_STR
  69                        " PCI Access Read Error at 0x%x\n", reg);
  70}
  71
  72static void edac_pci_write_dword(struct pci_dev *dev, int reg, u32 val32)
  73{
  74        int ret;
  75
  76        ret = pci_write_config_dword(dev, reg, val32);
  77        if (ret != 0)
  78                printk(KERN_ERR AMD8111_EDAC_MOD_STR
  79                        " PCI Access Write Error at 0x%x\n", reg);
  80}
  81
  82static void edac_pci_write_byte(struct pci_dev *dev, int reg, u8 val8)
  83{
  84        int ret;
  85
  86        ret = pci_write_config_byte(dev, reg, val8);
  87        if (ret != 0)
  88                printk(KERN_ERR AMD8111_EDAC_MOD_STR
  89                        " PCI Access Write Error at 0x%x\n", reg);
  90}
  91
  92/*
  93 * device-specific methods for amd8111 PCI Bridge Controller
  94 *
  95 * Error Reporting and Handling for amd8111 chipset could be found
  96 * in its datasheet 3.1.2 section, P37
  97 */
  98static void amd8111_pci_bridge_init(struct amd8111_pci_info *pci_info)
  99{
 100        u32 val32;
 101        struct pci_dev *dev = pci_info->dev;
 102
 103        /* First clear error detection flags on the host interface */
 104
 105        /* Clear SSE/SMA/STA flags in the global status register*/
 106        edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
 107        if (val32 & PCI_STSCMD_CLEAR_MASK)
 108                edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
 109
 110        /* Clear CRC and Link Fail flags in HT Link Control reg */
 111        edac_pci_read_dword(dev, REG_HT_LINK, &val32);
 112        if (val32 & HT_LINK_CLEAR_MASK)
 113                edac_pci_write_dword(dev, REG_HT_LINK, val32);
 114
 115        /* Second clear all fault on the secondary interface */
 116
 117        /* Clear error flags in the memory-base limit reg. */
 118        edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
 119        if (val32 & MEM_LIMIT_CLEAR_MASK)
 120                edac_pci_write_dword(dev, REG_MEM_LIM, val32);
 121
 122        /* Clear Discard Timer Expired flag in Interrupt/Bridge Control reg */
 123        edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
 124        if (val32 & PCI_INTBRG_CTRL_CLEAR_MASK)
 125                edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
 126
 127        /* Last enable error detections */
 128        if (edac_op_state == EDAC_OPSTATE_POLL) {
 129                /* Enable System Error reporting in global status register */
 130                edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
 131                val32 |= PCI_STSCMD_SERREN;
 132                edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
 133
 134                /* Enable CRC Sync flood packets to HyperTransport Link */
 135                edac_pci_read_dword(dev, REG_HT_LINK, &val32);
 136                val32 |= HT_LINK_CRCFEN;
 137                edac_pci_write_dword(dev, REG_HT_LINK, val32);
 138
 139                /* Enable SSE reporting etc in Interrupt control reg */
 140                edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
 141                val32 |= PCI_INTBRG_CTRL_POLL_MASK;
 142                edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
 143        }
 144}
 145
 146static void amd8111_pci_bridge_exit(struct amd8111_pci_info *pci_info)
 147{
 148        u32 val32;
 149        struct pci_dev *dev = pci_info->dev;
 150
 151        if (edac_op_state == EDAC_OPSTATE_POLL) {
 152                /* Disable System Error reporting */
 153                edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
 154                val32 &= ~PCI_STSCMD_SERREN;
 155                edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
 156
 157                /* Disable CRC flood packets */
 158                edac_pci_read_dword(dev, REG_HT_LINK, &val32);
 159                val32 &= ~HT_LINK_CRCFEN;
 160                edac_pci_write_dword(dev, REG_HT_LINK, val32);
 161
 162                /* Disable DTSERREN/MARSP/SERREN in Interrupt Control reg */
 163                edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
 164                val32 &= ~PCI_INTBRG_CTRL_POLL_MASK;
 165                edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
 166        }
 167}
 168
 169static void amd8111_pci_bridge_check(struct edac_pci_ctl_info *edac_dev)
 170{
 171        struct amd8111_pci_info *pci_info = edac_dev->pvt_info;
 172        struct pci_dev *dev = pci_info->dev;
 173        u32 val32;
 174
 175        /* Check out PCI Bridge Status and Command Register */
 176        edac_pci_read_dword(dev, REG_PCI_STSCMD, &val32);
 177        if (val32 & PCI_STSCMD_CLEAR_MASK) {
 178                printk(KERN_INFO "Error(s) in PCI bridge status and command"
 179                        "register on device %s\n", pci_info->ctl_name);
 180                printk(KERN_INFO "SSE: %d, RMA: %d, RTA: %d\n",
 181                        (val32 & PCI_STSCMD_SSE) != 0,
 182                        (val32 & PCI_STSCMD_RMA) != 0,
 183                        (val32 & PCI_STSCMD_RTA) != 0);
 184
 185                val32 |= PCI_STSCMD_CLEAR_MASK;
 186                edac_pci_write_dword(dev, REG_PCI_STSCMD, val32);
 187
 188                edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
 189        }
 190
 191        /* Check out HyperTransport Link Control Register */
 192        edac_pci_read_dword(dev, REG_HT_LINK, &val32);
 193        if (val32 & HT_LINK_LKFAIL) {
 194                printk(KERN_INFO "Error(s) in hypertransport link control"
 195                        "register on device %s\n", pci_info->ctl_name);
 196                printk(KERN_INFO "LKFAIL: %d\n",
 197                        (val32 & HT_LINK_LKFAIL) != 0);
 198
 199                val32 |= HT_LINK_LKFAIL;
 200                edac_pci_write_dword(dev, REG_HT_LINK, val32);
 201
 202                edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
 203        }
 204
 205        /* Check out PCI Interrupt and Bridge Control Register */
 206        edac_pci_read_dword(dev, REG_PCI_INTBRG_CTRL, &val32);
 207        if (val32 & PCI_INTBRG_CTRL_DTSTAT) {
 208                printk(KERN_INFO "Error(s) in PCI interrupt and bridge control"
 209                        "register on device %s\n", pci_info->ctl_name);
 210                printk(KERN_INFO "DTSTAT: %d\n",
 211                        (val32 & PCI_INTBRG_CTRL_DTSTAT) != 0);
 212
 213                val32 |= PCI_INTBRG_CTRL_DTSTAT;
 214                edac_pci_write_dword(dev, REG_PCI_INTBRG_CTRL, val32);
 215
 216                edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
 217        }
 218
 219        /* Check out PCI Bridge Memory Base-Limit Register */
 220        edac_pci_read_dword(dev, REG_MEM_LIM, &val32);
 221        if (val32 & MEM_LIMIT_CLEAR_MASK) {
 222                printk(KERN_INFO
 223                        "Error(s) in mem limit register on %s device\n",
 224                        pci_info->ctl_name);
 225                printk(KERN_INFO "DPE: %d, RSE: %d, RMA: %d\n"
 226                        "RTA: %d, STA: %d, MDPE: %d\n",
 227                        (val32 & MEM_LIMIT_DPE)  != 0,
 228                        (val32 & MEM_LIMIT_RSE)  != 0,
 229                        (val32 & MEM_LIMIT_RMA)  != 0,
 230                        (val32 & MEM_LIMIT_RTA)  != 0,
 231                        (val32 & MEM_LIMIT_STA)  != 0,
 232                        (val32 & MEM_LIMIT_MDPE) != 0);
 233
 234                val32 |= MEM_LIMIT_CLEAR_MASK;
 235                edac_pci_write_dword(dev, REG_MEM_LIM, val32);
 236
 237                edac_pci_handle_npe(edac_dev, edac_dev->ctl_name);
 238        }
 239}
 240
 241static struct resource *legacy_io_res;
 242static int at_compat_reg_broken;
 243#define LEGACY_NR_PORTS 1
 244
 245/* device-specific methods for amd8111 LPC Bridge device */
 246static void amd8111_lpc_bridge_init(struct amd8111_dev_info *dev_info)
 247{
 248        u8 val8;
 249        struct pci_dev *dev = dev_info->dev;
 250
 251        /* First clear REG_AT_COMPAT[SERR, IOCHK] if necessary */
 252        legacy_io_res = request_region(REG_AT_COMPAT, LEGACY_NR_PORTS,
 253                                        AMD8111_EDAC_MOD_STR);
 254        if (!legacy_io_res)
 255                printk(KERN_INFO "%s: failed to request legacy I/O region "
 256                        "start %d, len %d\n", __func__,
 257                        REG_AT_COMPAT, LEGACY_NR_PORTS);
 258        else {
 259                val8 = __do_inb(REG_AT_COMPAT);
 260                if (val8 == 0xff) { /* buggy port */
 261                        printk(KERN_INFO "%s: port %d is buggy, not supported"
 262                                " by hardware?\n", __func__, REG_AT_COMPAT);
 263                        at_compat_reg_broken = 1;
 264                        release_region(REG_AT_COMPAT, LEGACY_NR_PORTS);
 265                        legacy_io_res = NULL;
 266                } else {
 267                        u8 out8 = 0;
 268                        if (val8 & AT_COMPAT_SERR)
 269                                out8 = AT_COMPAT_CLRSERR;
 270                        if (val8 & AT_COMPAT_IOCHK)
 271                                out8 |= AT_COMPAT_CLRIOCHK;
 272                        if (out8 > 0)
 273                                __do_outb(out8, REG_AT_COMPAT);
 274                }
 275        }
 276
 277        /* Second clear error flags on LPC bridge */
 278        edac_pci_read_byte(dev, REG_IO_CTRL_1, &val8);
 279        if (val8 & IO_CTRL_1_CLEAR_MASK)
 280                edac_pci_write_byte(dev, REG_IO_CTRL_1, val8);
 281}
 282
 283static void amd8111_lpc_bridge_exit(struct amd8111_dev_info *dev_info)
 284{
 285        if (legacy_io_res)
 286                release_region(REG_AT_COMPAT, LEGACY_NR_PORTS);
 287}
 288
 289static void amd8111_lpc_bridge_check(struct edac_device_ctl_info *edac_dev)
 290{
 291        struct amd8111_dev_info *dev_info = edac_dev->pvt_info;
 292        struct pci_dev *dev = dev_info->dev;
 293        u8 val8;
 294
 295        edac_pci_read_byte(dev, REG_IO_CTRL_1, &val8);
 296        if (val8 & IO_CTRL_1_CLEAR_MASK) {
 297                printk(KERN_INFO
 298                        "Error(s) in IO control register on %s device\n",
 299                        dev_info->ctl_name);
 300                printk(KERN_INFO "LPC ERR: %d, PW2LPC: %d\n",
 301                        (val8 & IO_CTRL_1_LPC_ERR) != 0,
 302                        (val8 & IO_CTRL_1_PW2LPC) != 0);
 303
 304                val8 |= IO_CTRL_1_CLEAR_MASK;
 305                edac_pci_write_byte(dev, REG_IO_CTRL_1, val8);
 306
 307                edac_device_handle_ue(edac_dev, 0, 0, edac_dev->ctl_name);
 308        }
 309
 310        if (at_compat_reg_broken == 0) {
 311                u8 out8 = 0;
 312                val8 = __do_inb(REG_AT_COMPAT);
 313                if (val8 & AT_COMPAT_SERR)
 314                        out8 = AT_COMPAT_CLRSERR;
 315                if (val8 & AT_COMPAT_IOCHK)
 316                        out8 |= AT_COMPAT_CLRIOCHK;
 317                if (out8 > 0) {
 318                        __do_outb(out8, REG_AT_COMPAT);
 319                        edac_device_handle_ue(edac_dev, 0, 0,
 320                                                edac_dev->ctl_name);
 321                }
 322        }
 323}
 324
 325/* General devices represented by edac_device_ctl_info */
 326static struct amd8111_dev_info amd8111_devices[] = {
 327        [LPC_BRIDGE] = {
 328                .err_dev = PCI_DEVICE_ID_AMD_8111_LPC,
 329                .ctl_name = "lpc",
 330                .init = amd8111_lpc_bridge_init,
 331                .exit = amd8111_lpc_bridge_exit,
 332                .check = amd8111_lpc_bridge_check,
 333        },
 334        {0},
 335};
 336
 337/* PCI controllers represented by edac_pci_ctl_info */
 338static struct amd8111_pci_info amd8111_pcis[] = {
 339        [PCI_BRIDGE] = {
 340                .err_dev = PCI_DEVICE_ID_AMD_8111_PCI,
 341                .ctl_name = "AMD8111_PCI_Controller",
 342                .init = amd8111_pci_bridge_init,
 343                .exit = amd8111_pci_bridge_exit,
 344                .check = amd8111_pci_bridge_check,
 345        },
 346        {0},
 347};
 348
 349static int amd8111_dev_probe(struct pci_dev *dev,
 350                                const struct pci_device_id *id)
 351{
 352        struct amd8111_dev_info *dev_info = &amd8111_devices[id->driver_data];
 353
 354        dev_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
 355                                        dev_info->err_dev, NULL);
 356
 357        if (!dev_info->dev) {
 358                printk(KERN_ERR "EDAC device not found:"
 359                        "vendor %x, device %x, name %s\n",
 360                        PCI_VENDOR_ID_AMD, dev_info->err_dev,
 361                        dev_info->ctl_name);
 362                return -ENODEV;
 363        }
 364
 365        if (pci_enable_device(dev_info->dev)) {
 366                pci_dev_put(dev_info->dev);
 367                printk(KERN_ERR "failed to enable:"
 368                        "vendor %x, device %x, name %s\n",
 369                        PCI_VENDOR_ID_AMD, dev_info->err_dev,
 370                        dev_info->ctl_name);
 371                return -ENODEV;
 372        }
 373
 374        /*
 375         * we do not allocate extra private structure for
 376         * edac_device_ctl_info, but make use of existing
 377         * one instead.
 378        */
 379        dev_info->edac_idx = edac_device_alloc_index();
 380        dev_info->edac_dev =
 381                edac_device_alloc_ctl_info(0, dev_info->ctl_name, 1,
 382                                           NULL, 0, 0,
 383                                           NULL, 0, dev_info->edac_idx);
 384        if (!dev_info->edac_dev)
 385                return -ENOMEM;
 386
 387        dev_info->edac_dev->pvt_info = dev_info;
 388        dev_info->edac_dev->dev = &dev_info->dev->dev;
 389        dev_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR;
 390        dev_info->edac_dev->ctl_name = dev_info->ctl_name;
 391        dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev);
 392
 393        if (edac_op_state == EDAC_OPSTATE_POLL)
 394                dev_info->edac_dev->edac_check = dev_info->check;
 395
 396        if (dev_info->init)
 397                dev_info->init(dev_info);
 398
 399        if (edac_device_add_device(dev_info->edac_dev) > 0) {
 400                printk(KERN_ERR "failed to add edac_dev for %s\n",
 401                        dev_info->ctl_name);
 402                edac_device_free_ctl_info(dev_info->edac_dev);
 403                return -ENODEV;
 404        }
 405
 406        printk(KERN_INFO "added one edac_dev on AMD8111 "
 407                "vendor %x, device %x, name %s\n",
 408                PCI_VENDOR_ID_AMD, dev_info->err_dev,
 409                dev_info->ctl_name);
 410
 411        return 0;
 412}
 413
 414static void amd8111_dev_remove(struct pci_dev *dev)
 415{
 416        struct amd8111_dev_info *dev_info;
 417
 418        for (dev_info = amd8111_devices; dev_info->err_dev; dev_info++)
 419                if (dev_info->dev->device == dev->device)
 420                        break;
 421
 422        if (!dev_info->err_dev) /* should never happen */
 423                return;
 424
 425        if (dev_info->edac_dev) {
 426                edac_device_del_device(dev_info->edac_dev->dev);
 427                edac_device_free_ctl_info(dev_info->edac_dev);
 428        }
 429
 430        if (dev_info->exit)
 431                dev_info->exit(dev_info);
 432
 433        pci_dev_put(dev_info->dev);
 434}
 435
 436static int amd8111_pci_probe(struct pci_dev *dev,
 437                                const struct pci_device_id *id)
 438{
 439        struct amd8111_pci_info *pci_info = &amd8111_pcis[id->driver_data];
 440
 441        pci_info->dev = pci_get_device(PCI_VENDOR_ID_AMD,
 442                                        pci_info->err_dev, NULL);
 443
 444        if (!pci_info->dev) {
 445                printk(KERN_ERR "EDAC device not found:"
 446                        "vendor %x, device %x, name %s\n",
 447                        PCI_VENDOR_ID_AMD, pci_info->err_dev,
 448                        pci_info->ctl_name);
 449                return -ENODEV;
 450        }
 451
 452        if (pci_enable_device(pci_info->dev)) {
 453                pci_dev_put(pci_info->dev);
 454                printk(KERN_ERR "failed to enable:"
 455                        "vendor %x, device %x, name %s\n",
 456                        PCI_VENDOR_ID_AMD, pci_info->err_dev,
 457                        pci_info->ctl_name);
 458                return -ENODEV;
 459        }
 460
 461        /*
 462         * we do not allocate extra private structure for
 463         * edac_pci_ctl_info, but make use of existing
 464         * one instead.
 465        */
 466        pci_info->edac_idx = edac_pci_alloc_index();
 467        pci_info->edac_dev = edac_pci_alloc_ctl_info(0, pci_info->ctl_name);
 468        if (!pci_info->edac_dev)
 469                return -ENOMEM;
 470
 471        pci_info->edac_dev->pvt_info = pci_info;
 472        pci_info->edac_dev->dev = &pci_info->dev->dev;
 473        pci_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR;
 474        pci_info->edac_dev->ctl_name = pci_info->ctl_name;
 475        pci_info->edac_dev->dev_name = dev_name(&pci_info->dev->dev);
 476
 477        if (edac_op_state == EDAC_OPSTATE_POLL)
 478                pci_info->edac_dev->edac_check = pci_info->check;
 479
 480        if (pci_info->init)
 481                pci_info->init(pci_info);
 482
 483        if (edac_pci_add_device(pci_info->edac_dev, pci_info->edac_idx) > 0) {
 484                printk(KERN_ERR "failed to add edac_pci for %s\n",
 485                        pci_info->ctl_name);
 486                edac_pci_free_ctl_info(pci_info->edac_dev);
 487                return -ENODEV;
 488        }
 489
 490        printk(KERN_INFO "added one edac_pci on AMD8111 "
 491                "vendor %x, device %x, name %s\n",
 492                PCI_VENDOR_ID_AMD, pci_info->err_dev,
 493                pci_info->ctl_name);
 494
 495        return 0;
 496}
 497
 498static void amd8111_pci_remove(struct pci_dev *dev)
 499{
 500        struct amd8111_pci_info *pci_info;
 501
 502        for (pci_info = amd8111_pcis; pci_info->err_dev; pci_info++)
 503                if (pci_info->dev->device == dev->device)
 504                        break;
 505
 506        if (!pci_info->err_dev) /* should never happen */
 507                return;
 508
 509        if (pci_info->edac_dev) {
 510                edac_pci_del_device(pci_info->edac_dev->dev);
 511                edac_pci_free_ctl_info(pci_info->edac_dev);
 512        }
 513
 514        if (pci_info->exit)
 515                pci_info->exit(pci_info);
 516
 517        pci_dev_put(pci_info->dev);
 518}
 519
 520/* PCI Device ID talbe for general EDAC device */
 521static const struct pci_device_id amd8111_edac_dev_tbl[] = {
 522        {
 523        PCI_VEND_DEV(AMD, 8111_LPC),
 524        .subvendor = PCI_ANY_ID,
 525        .subdevice = PCI_ANY_ID,
 526        .class = 0,
 527        .class_mask = 0,
 528        .driver_data = LPC_BRIDGE,
 529        },
 530        {
 531        0,
 532        }                       /* table is NULL-terminated */
 533};
 534MODULE_DEVICE_TABLE(pci, amd8111_edac_dev_tbl);
 535
 536static struct pci_driver amd8111_edac_dev_driver = {
 537        .name = "AMD8111_EDAC_DEV",
 538        .probe = amd8111_dev_probe,
 539        .remove = amd8111_dev_remove,
 540        .id_table = amd8111_edac_dev_tbl,
 541};
 542
 543/* PCI Device ID table for EDAC PCI controller */
 544static const struct pci_device_id amd8111_edac_pci_tbl[] = {
 545        {
 546        PCI_VEND_DEV(AMD, 8111_PCI),
 547        .subvendor = PCI_ANY_ID,
 548        .subdevice = PCI_ANY_ID,
 549        .class = 0,
 550        .class_mask = 0,
 551        .driver_data = PCI_BRIDGE,
 552        },
 553        {
 554        0,
 555        }                       /* table is NULL-terminated */
 556};
 557MODULE_DEVICE_TABLE(pci, amd8111_edac_pci_tbl);
 558
 559static struct pci_driver amd8111_edac_pci_driver = {
 560        .name = "AMD8111_EDAC_PCI",
 561        .probe = amd8111_pci_probe,
 562        .remove = amd8111_pci_remove,
 563        .id_table = amd8111_edac_pci_tbl,
 564};
 565
 566static int __init amd8111_edac_init(void)
 567{
 568        int val;
 569
 570        printk(KERN_INFO "AMD8111 EDAC driver " AMD8111_EDAC_REVISION "\n");
 571        printk(KERN_INFO "\t(c) 2008 Wind River Systems, Inc.\n");
 572
 573        /* Only POLL mode supported so far */
 574        edac_op_state = EDAC_OPSTATE_POLL;
 575
 576        val = pci_register_driver(&amd8111_edac_dev_driver);
 577        val |= pci_register_driver(&amd8111_edac_pci_driver);
 578
 579        return val;
 580}
 581
 582static void __exit amd8111_edac_exit(void)
 583{
 584        pci_unregister_driver(&amd8111_edac_pci_driver);
 585        pci_unregister_driver(&amd8111_edac_dev_driver);
 586}
 587
 588
 589module_init(amd8111_edac_init);
 590module_exit(amd8111_edac_exit);
 591
 592MODULE_LICENSE("GPL");
 593MODULE_AUTHOR("Cao Qingtao <qingtao.cao@windriver.com>\n");
 594MODULE_DESCRIPTION("AMD8111 HyperTransport I/O Hub EDAC kernel module");
 595
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.