]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/edac/i7300_edac.c
ixgbe: move device pointer into the ring structure
[net-next-2.6.git] / drivers / edac / i7300_edac.c
index 6278209fec07c0cf29591c32248aa2212f2e00c9..05523b504271f09e08fd8a4c63441aaa5094748b 100644 (file)
@@ -104,7 +104,7 @@ struct i7300_pvt {
 
        u16 mir[MAX_MIR];                       /* Memory Interleave Reg*/
 
-       u16 mtr[MAX_SLOTS][MAX_BRANCHES];               /* Memory Technlogy Reg */
+       u16 mtr[MAX_SLOTS][MAX_BRANCHES];       /* Memory Technlogy Reg */
        u16 ambpresent[MAX_CHANNELS];           /* AMB present regs */
 
        /* DIMM information matrix, allocating architecture maximums */
@@ -121,14 +121,6 @@ static struct edac_pci_ctl_info *i7300_pci;
  * i7300 Register definitions for memory enumeration
  ***************************************************/
 
-/*
- * I7300 devices:
- * All 3 functions of Device 16 (0,1,2) share the SAME DID and
- * uses PCI_DEVICE_ID_INTEL_I7300_MCH_ERR for device 16 (0,1,2).
- * PCI_DEVICE_ID_INTEL_I7300_MCH_FB0 is used for device 21 (0,1)
- * and PCI_DEVICE_ID_INTEL_I7300_MCH_FB1 is used for device 21 (0,1).
- */
-
 /*
  * Device 16,
  * Function 0: System Address (not documented)
@@ -170,7 +162,7 @@ static struct edac_pci_ctl_info *i7300_pci;
 #define AMBPRESENT_0   0x64
 #define AMBPRESENT_1   0x66
 
-const static u16 mtr_regs [MAX_SLOTS] = {
+const static u16 mtr_regs[MAX_SLOTS] = {
        0x80, 0x84, 0x88, 0x8c,
        0x82, 0x86, 0x8a, 0x8e
 };
@@ -345,9 +337,24 @@ static const char *ferr_global_lo_name[] = {
  * i7300 Functions related to error detection
  ********************************************/
 
-const char *get_err_from_table(const char *table[], int size, int pos)
+/**
+ * get_err_from_table() - Gets the error message from a table
+ * @table:     table name (array of char *)
+ * @size:      number of elements at the table
+ * @pos:       position of the element to be returned
+ *
+ * This is a small routine that gets the pos-th element of a table. If the
+ * element doesn't exist (or it is empty), it returns "reserved".
+ * Instead of calling it directly, the better is to call via the macro
+ * GET_ERR_FROM_TABLE(), that automatically checks the table size via
+ * ARRAY_SIZE() macro
+ */
+static const char *get_err_from_table(const char *table[], int size, int pos)
 {
-       if (pos >= size)
+       if (unlikely(pos >= size))
+               return "Reserved";
+
+       if (unlikely(!table[pos]))
                return "Reserved";
 
        return table[pos];
@@ -356,10 +363,11 @@ const char *get_err_from_table(const char *table[], int size, int pos)
 #define GET_ERR_FROM_TABLE(table, pos)                         \
        get_err_from_table(table, ARRAY_SIZE(table), pos)
 
-/*
- *     i7300_process_error_global Retrieve the hardware error information from
- *                             the hardware and cache it in the 'info'
- *                             structure
+/**
+ * i7300_process_error_global() - Retrieve the hardware error information from
+ *                               the hardware global error registers and
+ *                               sends it to dmesg
+ * @mci: struct mem_ctl_info pointer
  */
 static void i7300_process_error_global(struct mem_ctl_info *mci)
 {
@@ -410,10 +418,11 @@ error_global:
                        is_fatal ? "Fatal" : "NOT fatal", specific);
 }
 
-/*
- *     i7300_process_fbd_error Retrieve the hardware error information from
- *                             the hardware and cache it in the 'info'
- *                             structure
+/**
+ * i7300_process_fbd_error() - Retrieve the hardware error information from
+ *                            the FBD error registers and sends it via
+ *                            EDAC error API calls
+ * @mci: struct mem_ctl_info pointer
  */
 static void i7300_process_fbd_error(struct mem_ctl_info *mci)
 {
@@ -524,10 +533,9 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
        return;
 }
 
-/*
- *     i7300_check_error Retrieve the hardware error information from
- *                             the hardware and cache it in the 'info'
- *                             structure
+/**
+ * i7300_check_error() - Calls the error checking subroutines
+ * @mci: struct mem_ctl_info pointer
  */
 static void i7300_check_error(struct mem_ctl_info *mci)
 {
@@ -535,11 +543,9 @@ static void i7300_check_error(struct mem_ctl_info *mci)
        i7300_process_fbd_error(mci);
 };
 
-/*
- *     i7300_clear_error       Retrieve any error from the hardware
- *                             but do NOT process that error.
- *                             Used for 'clearing' out of previous errors
- *                             Called by the Core module.
+/**
+ * i7300_clear_error() - Clears the error registers
+ * @mci: struct mem_ctl_info pointer
  */
 static void i7300_clear_error(struct mem_ctl_info *mci)
 {
@@ -573,9 +579,10 @@ static void i7300_clear_error(struct mem_ctl_info *mci)
                              FERR_NF_FBD, value);
 }
 
-/*
- *     i7300_enable_error_reporting
- *                     Turn on the memory reporting features of the hardware
+/**
+ * i7300_enable_error_reporting() - Enable the memory reporting logic at the
+ *                                 hardware
+ * @mci: struct mem_ctl_info pointer
  */
 static void i7300_enable_error_reporting(struct mem_ctl_info *mci)
 {
@@ -597,15 +604,20 @@ static void i7300_enable_error_reporting(struct mem_ctl_info *mci)
  * i7300 Functions related to memory enumberation
  ************************************************/
 
-/*
- * determine_mtr(pvt, csrow, channel)
- *
- * return the proper MTR register as determine by the csrow and desired channel
+/**
+ * decode_mtr() - Decodes the MTR descriptor, filling the edac structs
+ * @pvt: pointer to the private data struct used by i7300 driver
+ * @slot: DIMM slot (0 to 7)
+ * @ch: Channel number within the branch (0 or 1)
+ * @branch: Branch number (0 or 1)
+ * @dinfo: Pointer to DIMM info where dimm size is stored
+ * @p_csrow: Pointer to the struct csrow_info that corresponds to that element
  */
 static int decode_mtr(struct i7300_pvt *pvt,
                      int slot, int ch, int branch,
                      struct i7300_dimm_info *dinfo,
-                     struct csrow_info *p_csrow)
+                     struct csrow_info *p_csrow,
+                     u32 *nr_pages)
 {
        int mtr, ans, addrBits, channel;
 
@@ -619,14 +631,8 @@ static int decode_mtr(struct i7300_pvt *pvt,
                ans ? "Present" : "NOT Present");
 
        /* Determine if there is a DIMM present in this DIMM slot */
-
-#if 0
-       if (!amb_present || !ans)
-               return 0;
-#else
        if (!ans)
                return 0;
-#endif
 
        /* Start with the number of bits for a Bank
        * on the DRAM */
@@ -643,6 +649,7 @@ static int decode_mtr(struct i7300_pvt *pvt,
        addrBits -= 3;  /* 8 bits per bytes */
 
        dinfo->megabytes = 1 << addrBits;
+       *nr_pages = dinfo->megabytes << 8;
 
        debugf2("\t\tWIDTH: x%d\n", MTR_DRAM_WIDTH(mtr));
 
@@ -656,8 +663,9 @@ static int decode_mtr(struct i7300_pvt *pvt,
        debugf2("\t\tSIZE: %d MB\n", dinfo->megabytes);
 
        p_csrow->grain = 8;
-       p_csrow->nr_pages = dinfo->megabytes << 8;
        p_csrow->mtype = MEM_FB_DDR2;
+       p_csrow->csrow_idx = slot;
+       p_csrow->page_mask = 0;
 
        /*
         * The type of error detection actually depends of the
@@ -692,14 +700,15 @@ static int decode_mtr(struct i7300_pvt *pvt,
        return mtr;
 }
 
-/*
- *     print_dimm_size
+/**
+ * print_dimm_size() - Prints dump of the memory organization
+ * @pvt: pointer to the private data struct used by i7300 driver
  *
- *     also will output a DIMM matrix map, if debug is enabled, for viewing
- *     how the DIMMs are populated
+ * Useful for debug. If debug is disabled, this routine do nothing
  */
 static void print_dimm_size(struct i7300_pvt *pvt)
 {
+#ifdef CONFIG_EDAC_DEBUG
        struct i7300_dimm_info *dinfo;
        char *p;
        int space, n;
@@ -720,7 +729,7 @@ static void print_dimm_size(struct i7300_pvt *pvt)
        p = pvt->tmp_prt_buffer;
        space = PAGE_SIZE;
        n = snprintf(p, space, "-------------------------------"
-                              "------------------------------");
+                              "------------------------------");
        p += n;
        space -= n;
        debugf2("%s\n", pvt->tmp_prt_buffer);
@@ -745,49 +754,48 @@ static void print_dimm_size(struct i7300_pvt *pvt)
        }
 
        n = snprintf(p, space, "-------------------------------"
-                              "------------------------------");
+                              "------------------------------");
        p += n;
        space -= n;
        debugf2("%s\n", pvt->tmp_prt_buffer);
        p = pvt->tmp_prt_buffer;
        space = PAGE_SIZE;
+#endif
 }
 
-/*
- *     i7300_init_csrows       Initialize the 'csrows' table within
- *                             the mci control structure with the
- *                             addressing of memory.
- *
- *     return:
- *             0       success
- *             1       no actual memory found on this MC
+/**
+ * i7300_init_csrows() - Initialize the 'csrows' table within
+ *                      the mci control structure with the
+ *                      addressing of memory.
+ * @mci: struct mem_ctl_info pointer
  */
 static int i7300_init_csrows(struct mem_ctl_info *mci)
 {
        struct i7300_pvt *pvt;
        struct i7300_dimm_info *dinfo;
        struct csrow_info *p_csrow;
-       int empty;
+       int rc = -ENODEV;
        int mtr;
        int ch, branch, slot, channel;
+       u32 last_page = 0, nr_pages;
 
        pvt = mci->pvt_info;
 
-       empty = 1;              /* Assume NO memory */
-
        debugf2("Memory Technology Registers:\n");
 
        /* Get the AMB present registers for the four channels */
        for (branch = 0; branch < MAX_BRANCHES; branch++) {
                /* Read and dump branch 0's MTRs */
                channel = to_channel(0, branch);
-               pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_0,
+               pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
+                                    AMBPRESENT_0,
                                &pvt->ambpresent[channel]);
                debugf2("\t\tAMB-present CH%d = 0x%x:\n",
                        channel, pvt->ambpresent[channel]);
 
                channel = to_channel(1, branch);
-               pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch], AMBPRESENT_1,
+               pci_read_config_word(pvt->pci_dev_2x_0_fbd_branch[branch],
+                                    AMBPRESENT_1,
                                &pvt->ambpresent[channel]);
                debugf2("\t\tAMB-present CH%d = 0x%x:\n",
                        channel, pvt->ambpresent[channel]);
@@ -807,41 +815,46 @@ static int i7300_init_csrows(struct mem_ctl_info *mci)
                                p_csrow = &mci->csrows[slot];
 
                                mtr = decode_mtr(pvt, slot, ch, branch,
-                                                       dinfo, p_csrow);
+                                                dinfo, p_csrow, &nr_pages);
                                /* if no DIMMS on this row, continue */
                                if (!MTR_DIMMS_PRESENT(mtr))
                                        continue;
 
-                               p_csrow->csrow_idx = slot;
+                               /* Update per_csrow memory count */
+                               p_csrow->nr_pages += nr_pages;
+                               p_csrow->first_page = last_page;
+                               last_page += nr_pages;
+                               p_csrow->last_page = last_page;
 
-                               /* FAKE OUT VALUES, FIXME */
-                               p_csrow->first_page = 0 + slot * 20;
-                               p_csrow->last_page = 9 + slot * 20;
-                               p_csrow->page_mask = 0xfff;
-
-                               empty = 0;
+                               rc = 0;
                        }
                }
        }
 
-       return empty;
+       return rc;
 }
 
+/**
+ * decode_mir() - Decodes Memory Interleave Register (MIR) info
+ * @int mir_no: number of the MIR register to decode
+ * @mir: array with the MIR data cached on the driver
+ */
 static void decode_mir(int mir_no, u16 mir[MAX_MIR])
 {
        if (mir[mir_no] & 3)
-               debugf2("MIR%d: limit= 0x%x Branch(es) that participate: %s %s\n",
+               debugf2("MIR%d: limit= 0x%x Branch(es) that participate:"
+                       " %s %s\n",
                        mir_no,
                        (mir[mir_no] >> 4) & 0xfff,
                        (mir[mir_no] & 1) ? "B0" : "",
-                       (mir[mir_no] & 2) ? "B1": "");
+                       (mir[mir_no] & 2) ? "B1" : "");
 }
 
-/*
- *     i7300_get_mc_regs       read in the necessary registers and
- *                             cache locally
+/**
+ * i7300_get_mc_regs() - Get the contents of the MC enumeration registers
+ * @mci: struct mem_ctl_info pointer
  *
- *                     Fills in the private data members
+ * Data read is cached internally for its usage when needed
  */
 static int i7300_get_mc_regs(struct mem_ctl_info *mci)
 {
@@ -884,9 +897,12 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci)
                IS_RETRY_ENABLED(pvt->mc_settings) ? "enabled" : "disabled");
 
        /* Get Memory Interleave Range registers */
-       pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0, &pvt->mir[0]);
-       pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1, &pvt->mir[1]);
-       pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2, &pvt->mir[2]);
+       pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR0,
+                            &pvt->mir[0]);
+       pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR1,
+                            &pvt->mir[1]);
+       pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, MIR2,
+                            &pvt->mir[2]);
 
        /* Decode the MIR regs */
        for (i = 0; i < MAX_MIR; i++)
@@ -907,9 +923,9 @@ static int i7300_get_mc_regs(struct mem_ctl_info *mci)
  * i7300 Functions related to device probe/release
  *************************************************/
 
-/*
- *     i7300_put_devices       'put' all the devices that we have
- *                             reserved via 'get'
+/**
+ * i7300_put_devices() - Release the PCI devices
+ * @mci: struct mem_ctl_info pointer
  */
 static void i7300_put_devices(struct mem_ctl_info *mci)
 {
@@ -925,13 +941,18 @@ static void i7300_put_devices(struct mem_ctl_info *mci)
        pci_dev_put(pvt->pci_dev_16_1_fsb_addr_map);
 }
 
-/*
- *     i7300_get_devices       Find and perform 'get' operation on the MCH's
- *                     device/functions we want to reference for this driver
+/**
+ * i7300_get_devices() - Find and perform 'get' operation on the MCH's
+ *                      device/functions we want to reference for this driver
+ * @mci: struct mem_ctl_info pointer
  *
- *                     Need to 'get' device 16 func 1 and func 2
+ * Access and prepare the several devices for usage:
+ * I7300 devices used by this driver:
+ *    Device 16, functions 0,1 and 2:  PCI_DEVICE_ID_INTEL_I7300_MCH_ERR
+ *    Device 21 function 0:            PCI_DEVICE_ID_INTEL_I7300_MCH_FB0
+ *    Device 22 function 0:            PCI_DEVICE_ID_INTEL_I7300_MCH_FB1
  */
-static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx)
+static int __devinit i7300_get_devices(struct mem_ctl_info *mci)
 {
        struct i7300_pvt *pvt;
        struct pci_dev *pdev;
@@ -940,7 +961,8 @@ static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx)
 
        /* Attempt to 'get' the MCH register we want */
        pdev = NULL;
-       while (!pvt->pci_dev_16_1_fsb_addr_map || !pvt->pci_dev_16_2_fsb_err_regs) {
+       while (!pvt->pci_dev_16_1_fsb_addr_map ||
+              !pvt->pci_dev_16_2_fsb_err_regs) {
                pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
                                      PCI_DEVICE_ID_INTEL_I7300_MCH_ERR, pdev);
                if (!pdev) {
@@ -968,16 +990,19 @@ static int i7300_get_devices(struct mem_ctl_info *mci, int dev_idx)
 
        debugf1("System Address, processor bus- PCI Bus ID: %s  %x:%x\n",
                pci_name(pvt->pci_dev_16_0_fsb_ctlr),
-               pvt->pci_dev_16_0_fsb_ctlr->vendor, pvt->pci_dev_16_0_fsb_ctlr->device);
+               pvt->pci_dev_16_0_fsb_ctlr->vendor,
+               pvt->pci_dev_16_0_fsb_ctlr->device);
        debugf1("Branchmap, control and errors - PCI Bus ID: %s  %x:%x\n",
                pci_name(pvt->pci_dev_16_1_fsb_addr_map),
-               pvt->pci_dev_16_1_fsb_addr_map->vendor, pvt->pci_dev_16_1_fsb_addr_map->device);
+               pvt->pci_dev_16_1_fsb_addr_map->vendor,
+               pvt->pci_dev_16_1_fsb_addr_map->device);
        debugf1("FSB Error Regs - PCI Bus ID: %s  %x:%x\n",
                pci_name(pvt->pci_dev_16_2_fsb_err_regs),
-               pvt->pci_dev_16_2_fsb_err_regs->vendor, pvt->pci_dev_16_2_fsb_err_regs->device);
+               pvt->pci_dev_16_2_fsb_err_regs->vendor,
+               pvt->pci_dev_16_2_fsb_err_regs->device);
 
        pvt->pci_dev_2x_0_fbd_branch[0] = pci_get_device(PCI_VENDOR_ID_INTEL,
-                                           PCI_DEVICE_ID_INTEL_I7300_MCH_FB0,
+                                           PCI_DEVICE_ID_INTEL_I7300_MCH_FB0,
                                            NULL);
        if (!pvt->pci_dev_2x_0_fbd_branch[0]) {
                i7300_printk(KERN_ERR,
@@ -1007,23 +1032,25 @@ error:
        return -ENODEV;
 }
 
-/*
- *     i7300_probe1    Probe for ONE instance of device to see if it is
- *                     present.
- *     return:
- *             0 for FOUND a device
- *             < 0 for error code
+/**
+ * i7300_init_one() - Probe for one instance of the device
+ * @pdev: struct pci_dev pointer
+ * @id: struct pci_device_id pointer - currently unused
  */
-static int i7300_probe1(struct pci_dev *pdev, int dev_idx)
+static int __devinit i7300_init_one(struct pci_dev *pdev,
+                                   const struct pci_device_id *id)
 {
        struct mem_ctl_info *mci;
        struct i7300_pvt *pvt;
        int num_channels;
        int num_dimms_per_channel;
        int num_csrows;
+       int rc;
 
-       if (dev_idx >= ARRAY_SIZE(i7300_devs))
-               return -EINVAL;
+       /* wake up device */
+       rc = pci_enable_device(pdev);
+       if (rc == -EIO)
+               return rc;
 
        debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
                __func__,
@@ -1068,7 +1095,7 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx)
        }
 
        /* 'get' the pci devices we want to reserve for our use */
-       if (i7300_get_devices(mci, dev_idx))
+       if (i7300_get_devices(mci))
                goto fail0;
 
        mci->mc_idx = 0;
@@ -1077,7 +1104,7 @@ static int i7300_probe1(struct pci_dev *pdev, int dev_idx)
        mci->edac_cap = EDAC_FLAG_NONE;
        mci->mod_name = "i7300_edac.c";
        mci->mod_ver = I7300_REVISION;
-       mci->ctl_name = i7300_devs[dev_idx].ctl_name;
+       mci->ctl_name = i7300_devs[0].ctl_name;
        mci->dev_name = pci_name(pdev);
        mci->ctl_page_to_phys = NULL;
 
@@ -1132,32 +1159,9 @@ fail0:
        return -ENODEV;
 }
 
-/*
- *     i7300_init_one  constructor for one instance of device
- *
- *     returns:
- *             negative on error
- *             count (>= 0)
- */
-static int __devinit i7300_init_one(struct pci_dev *pdev,
-                               const struct pci_device_id *id)
-{
-       int rc;
-
-       debugf0("MC: " __FILE__ ": %s()\n", __func__);
-
-       /* wake up device */
-       rc = pci_enable_device(pdev);
-       if (rc == -EIO)
-               return rc;
-
-       /* now probe and enable the device */
-       return i7300_probe1(pdev, id->driver_data);
-}
-
-/*
- *     i7300_remove_one        destructor for one instance of device
- *
+/**
+ * i7300_remove_one() - Remove the driver
+ * @pdev: struct pci_dev pointer
  */
 static void __devexit i7300_remove_one(struct pci_dev *pdev)
 {
@@ -1183,9 +1187,9 @@ static void __devexit i7300_remove_one(struct pci_dev *pdev)
 }
 
 /*
- *     pci_device_id   table for which devices we are looking for
+ * pci_device_id: table for which devices we are looking for
  *
- *     The "E500P" device is the first device supported.
+ * Has only 8086:360c PCI ID
  */
 static const struct pci_device_id i7300_pci_tbl[] __devinitdata = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7300_MCH_ERR)},
@@ -1195,8 +1199,7 @@ static const struct pci_device_id i7300_pci_tbl[] __devinitdata = {
 MODULE_DEVICE_TABLE(pci, i7300_pci_tbl);
 
 /*
- *     i7300_driver    pci_driver structure for this module
- *
+ * i7300_driver: pci_driver structure for this module
  */
 static struct pci_driver i7300_driver = {
        .name = "i7300_edac",
@@ -1205,9 +1208,8 @@ static struct pci_driver i7300_driver = {
        .id_table = i7300_pci_tbl,
 };
 
-/*
- *     i7300_init              Module entry function
- *                     Try to initialize this module for its devices
+/**
+ * i7300_init() - Registers the driver
  */
 static int __init i7300_init(void)
 {
@@ -1223,9 +1225,8 @@ static int __init i7300_init(void)
        return (pci_rc < 0) ? pci_rc : 0;
 }
 
-/*
- *     i7300_exit()    Module exit function
- *                     Unregister the driver
+/**
+ * i7300_init() - Unregisters the driver
  */
 static void __exit i7300_exit(void)
 {