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