aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2012-04-16 14:10:12 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-05-28 18:13:42 -0400
commit0975c16f4fa901403708a0d3f19b33a726b10326 (patch)
tree622a5a9b66afc2205ef74c3064f8e2792ed26911 /drivers
parent70e2a8379b6e704b2e8cdfcf151954171c36e779 (diff)
i7core_edac: convert driver to use the new edac ABI
The legacy edac ABI is going to be removed. Port the driver to use and benefit from the new API functionality. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/edac/i7core_edac.c202
1 files changed, 50 insertions, 152 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 0e3cc34bcc22..bc2c04550b8b 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -257,7 +257,6 @@ struct i7core_pvt {
257 struct i7core_channel channel[NUM_CHANS]; 257 struct i7core_channel channel[NUM_CHANS];
258 258
259 int ce_count_available; 259 int ce_count_available;
260 int csrow_map[NUM_CHANS][MAX_DIMMS];
261 260
262 /* ECC corrected errors counts per udimm */ 261 /* ECC corrected errors counts per udimm */
263 unsigned long udimm_ce_count[MAX_DIMMS]; 262 unsigned long udimm_ce_count[MAX_DIMMS];
@@ -492,113 +491,12 @@ static void free_i7core_dev(struct i7core_dev *i7core_dev)
492/**************************************************************************** 491/****************************************************************************
493 Memory check routines 492 Memory check routines
494 ****************************************************************************/ 493 ****************************************************************************/
495static struct pci_dev *get_pdev_slot_func(u8 socket, unsigned slot,
496 unsigned func)
497{
498 struct i7core_dev *i7core_dev = get_i7core_dev(socket);
499 int i;
500
501 if (!i7core_dev)
502 return NULL;
503
504 for (i = 0; i < i7core_dev->n_devs; i++) {
505 if (!i7core_dev->pdev[i])
506 continue;
507
508 if (PCI_SLOT(i7core_dev->pdev[i]->devfn) == slot &&
509 PCI_FUNC(i7core_dev->pdev[i]->devfn) == func) {
510 return i7core_dev->pdev[i];
511 }
512 }
513
514 return NULL;
515}
516
517/**
518 * i7core_get_active_channels() - gets the number of channels and csrows
519 * @socket: Quick Path Interconnect socket
520 * @channels: Number of channels that will be returned
521 * @csrows: Number of csrows found
522 *
523 * Since EDAC core needs to know in advance the number of available channels
524 * and csrows, in order to allocate memory for csrows/channels, it is needed
525 * to run two similar steps. At the first step, implemented on this function,
526 * it checks the number of csrows/channels present at one socket.
527 * this is used in order to properly allocate the size of mci components.
528 *
529 * It should be noticed that none of the current available datasheets explain
530 * or even mention how csrows are seen by the memory controller. So, we need
531 * to add a fake description for csrows.
532 * So, this driver is attributing one DIMM memory for one csrow.
533 */
534static int i7core_get_active_channels(const u8 socket, unsigned *channels,
535 unsigned *csrows)
536{
537 struct pci_dev *pdev = NULL;
538 int i, j;
539 u32 status, control;
540
541 *channels = 0;
542 *csrows = 0;
543
544 pdev = get_pdev_slot_func(socket, 3, 0);
545 if (!pdev) {
546 i7core_printk(KERN_ERR, "Couldn't find socket %d fn 3.0!!!\n",
547 socket);
548 return -ENODEV;
549 }
550
551 /* Device 3 function 0 reads */
552 pci_read_config_dword(pdev, MC_STATUS, &status);
553 pci_read_config_dword(pdev, MC_CONTROL, &control);
554
555 for (i = 0; i < NUM_CHANS; i++) {
556 u32 dimm_dod[3];
557 /* Check if the channel is active */
558 if (!(control & (1 << (8 + i))))
559 continue;
560
561 /* Check if the channel is disabled */
562 if (status & (1 << i))
563 continue;
564
565 pdev = get_pdev_slot_func(socket, i + 4, 1);
566 if (!pdev) {
567 i7core_printk(KERN_ERR, "Couldn't find socket %d "
568 "fn %d.%d!!!\n",
569 socket, i + 4, 1);
570 return -ENODEV;
571 }
572 /* Devices 4-6 function 1 */
573 pci_read_config_dword(pdev,
574 MC_DOD_CH_DIMM0, &dimm_dod[0]);
575 pci_read_config_dword(pdev,
576 MC_DOD_CH_DIMM1, &dimm_dod[1]);
577 pci_read_config_dword(pdev,
578 MC_DOD_CH_DIMM2, &dimm_dod[2]);
579
580 (*channels)++;
581
582 for (j = 0; j < 3; j++) {
583 if (!DIMM_PRESENT(dimm_dod[j]))
584 continue;
585 (*csrows)++;
586 }
587 }
588
589 debugf0("Number of active channels on socket %d: %d\n",
590 socket, *channels);
591
592 return 0;
593}
594 494
595static int get_dimm_config(struct mem_ctl_info *mci) 495static int get_dimm_config(struct mem_ctl_info *mci)
596{ 496{
597 struct i7core_pvt *pvt = mci->pvt_info; 497 struct i7core_pvt *pvt = mci->pvt_info;
598 struct csrow_info *csr;
599 struct pci_dev *pdev; 498 struct pci_dev *pdev;
600 int i, j; 499 int i, j;
601 int csrow = 0;
602 enum edac_type mode; 500 enum edac_type mode;
603 enum mem_type mtype; 501 enum mem_type mtype;
604 struct dimm_info *dimm; 502 struct dimm_info *dimm;
@@ -696,6 +594,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
696 if (!DIMM_PRESENT(dimm_dod[j])) 594 if (!DIMM_PRESENT(dimm_dod[j]))
697 continue; 595 continue;
698 596
597 dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers,
598 i, j, 0);
699 banks = numbank(MC_DOD_NUMBANK(dimm_dod[j])); 599 banks = numbank(MC_DOD_NUMBANK(dimm_dod[j]));
700 ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j])); 600 ranks = numrank(MC_DOD_NUMRANK(dimm_dod[j]));
701 rows = numrow(MC_DOD_NUMROW(dimm_dod[j])); 601 rows = numrow(MC_DOD_NUMROW(dimm_dod[j]));
@@ -704,8 +604,6 @@ static int get_dimm_config(struct mem_ctl_info *mci)
704 /* DDR3 has 8 I/O banks */ 604 /* DDR3 has 8 I/O banks */
705 size = (rows * cols * banks * ranks) >> (20 - 3); 605 size = (rows * cols * banks * ranks) >> (20 - 3);
706 606
707 pvt->channel[i].dimms++;
708
709 debugf0("\tdimm %d %d Mb offset: %x, " 607 debugf0("\tdimm %d %d Mb offset: %x, "
710 "bank: %d, rank: %d, row: %#x, col: %#x\n", 608 "bank: %d, rank: %d, row: %#x, col: %#x\n",
711 j, size, 609 j, size,
@@ -714,11 +612,6 @@ static int get_dimm_config(struct mem_ctl_info *mci)
714 612
715 npages = MiB_TO_PAGES(size); 613 npages = MiB_TO_PAGES(size);
716 614
717 csr = &mci->csrows[csrow];
718
719 pvt->csrow_map[i][j] = csrow;
720
721 dimm = csr->channels[0].dimm;
722 dimm->nr_pages = npages; 615 dimm->nr_pages = npages;
723 616
724 switch (banks) { 617 switch (banks) {
@@ -741,7 +634,6 @@ static int get_dimm_config(struct mem_ctl_info *mci)
741 dimm->grain = 8; 634 dimm->grain = 8;
742 dimm->edac_mode = mode; 635 dimm->edac_mode = mode;
743 dimm->mtype = mtype; 636 dimm->mtype = mtype;
744 csrow++;
745 } 637 }
746 638
747 pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]); 639 pci_read_config_dword(pdev, MC_SAG_CH_0, &value[0]);
@@ -1557,22 +1449,16 @@ error:
1557/**************************************************************************** 1449/****************************************************************************
1558 Error check routines 1450 Error check routines
1559 ****************************************************************************/ 1451 ****************************************************************************/
1560static void i7core_rdimm_update_csrow(struct mem_ctl_info *mci, 1452static void i7core_rdimm_update_errcount(struct mem_ctl_info *mci,
1561 const int chan, 1453 const int chan,
1562 const int dimm, 1454 const int dimm,
1563 const int add) 1455 const int add)
1564{ 1456{
1565 char *msg; 1457 int i;
1566 struct i7core_pvt *pvt = mci->pvt_info;
1567 int row = pvt->csrow_map[chan][dimm], i;
1568 1458
1569 for (i = 0; i < add; i++) { 1459 for (i = 0; i < add; i++) {
1570 msg = kasprintf(GFP_KERNEL, "Corrected error " 1460 edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 0, 0, 0,
1571 "(Socket=%d channel=%d dimm=%d)", 1461 chan, dimm, -1, "error", "", NULL);
1572 pvt->i7core_dev->socket, chan, dimm);
1573
1574 edac_mc_handle_fbd_ce(mci, row, 0, msg);
1575 kfree (msg);
1576 } 1462 }
1577} 1463}
1578 1464
@@ -1613,11 +1499,11 @@ static void i7core_rdimm_update_ce_count(struct mem_ctl_info *mci,
1613 1499
1614 /*updated the edac core */ 1500 /*updated the edac core */
1615 if (add0 != 0) 1501 if (add0 != 0)
1616 i7core_rdimm_update_csrow(mci, chan, 0, add0); 1502 i7core_rdimm_update_errcount(mci, chan, 0, add0);
1617 if (add1 != 0) 1503 if (add1 != 0)
1618 i7core_rdimm_update_csrow(mci, chan, 1, add1); 1504 i7core_rdimm_update_errcount(mci, chan, 1, add1);
1619 if (add2 != 0) 1505 if (add2 != 0)
1620 i7core_rdimm_update_csrow(mci, chan, 2, add2); 1506 i7core_rdimm_update_errcount(mci, chan, 2, add2);
1621 1507
1622} 1508}
1623 1509
@@ -1738,19 +1624,29 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
1738{ 1624{
1739 struct i7core_pvt *pvt = mci->pvt_info; 1625 struct i7core_pvt *pvt = mci->pvt_info;
1740 char *type, *optype, *err, *msg; 1626 char *type, *optype, *err, *msg;
1627 enum hw_event_mc_err_type tp_event;
1741 unsigned long error = m->status & 0x1ff0000l; 1628 unsigned long error = m->status & 0x1ff0000l;
1629 bool uncorrected_error = m->mcgstatus & 1ll << 61;
1630 bool ripv = m->mcgstatus & 1;
1742 u32 optypenum = (m->status >> 4) & 0x07; 1631 u32 optypenum = (m->status >> 4) & 0x07;
1743 u32 core_err_cnt = (m->status >> 38) & 0x7fff; 1632 u32 core_err_cnt = (m->status >> 38) & 0x7fff;
1744 u32 dimm = (m->misc >> 16) & 0x3; 1633 u32 dimm = (m->misc >> 16) & 0x3;
1745 u32 channel = (m->misc >> 18) & 0x3; 1634 u32 channel = (m->misc >> 18) & 0x3;
1746 u32 syndrome = m->misc >> 32; 1635 u32 syndrome = m->misc >> 32;
1747 u32 errnum = find_first_bit(&error, 32); 1636 u32 errnum = find_first_bit(&error, 32);
1748 int csrow;
1749 1637
1750 if (m->mcgstatus & 1) 1638 if (uncorrected_error) {
1751 type = "FATAL"; 1639 if (ripv) {
1752 else 1640 type = "FATAL";
1753 type = "NON_FATAL"; 1641 tp_event = HW_EVENT_ERR_FATAL;
1642 } else {
1643 type = "NON_FATAL";
1644 tp_event = HW_EVENT_ERR_UNCORRECTED;
1645 }
1646 } else {
1647 type = "CORRECTED";
1648 tp_event = HW_EVENT_ERR_CORRECTED;
1649 }
1754 1650
1755 switch (optypenum) { 1651 switch (optypenum) {
1756 case 0: 1652 case 0:
@@ -1805,25 +1701,23 @@ static void i7core_mce_output_error(struct mem_ctl_info *mci,
1805 err = "unknown"; 1701 err = "unknown";
1806 } 1702 }
1807 1703
1808 /* FIXME: should convert addr into bank and rank information */
1809 msg = kasprintf(GFP_ATOMIC, 1704 msg = kasprintf(GFP_ATOMIC,
1810 "%s (addr = 0x%08llx, cpu=%d, Dimm=%d, Channel=%d, " 1705 "addr=0x%08llx cpu=%d count=%d Err=%08llx:%08llx (%s: %s))\n",
1811 "syndrome=0x%08x, count=%d, Err=%08llx:%08llx (%s: %s))\n", 1706 (long long) m->addr, m->cpu, core_err_cnt,
1812 type, (long long) m->addr, m->cpu, dimm, channel, 1707 (long long)m->status, (long long)m->misc, optype, err);
1813 syndrome, core_err_cnt, (long long)m->status,
1814 (long long)m->misc, optype, err);
1815 1708
1816 debugf0("%s", msg); 1709 /*
1817 1710 * Call the helper to output message
1818 csrow = pvt->csrow_map[channel][dimm]; 1711 * FIXME: what to do if core_err_cnt > 1? Currently, it generates
1819 1712 * only one event
1820 /* Call the helper to output message */ 1713 */
1821 if (m->mcgstatus & 1) 1714 if (uncorrected_error || !pvt->is_registered)
1822 edac_mc_handle_fbd_ue(mci, csrow, 0, 1715 edac_mc_handle_error(tp_event, mci,
1823 0 /* FIXME: should be channel here */, msg); 1716 m->addr >> PAGE_SHIFT,
1824 else if (!pvt->is_registered) 1717 m->addr & ~PAGE_MASK,
1825 edac_mc_handle_fbd_ce(mci, csrow, 1718 syndrome,
1826 0 /* FIXME: should be channel here */, msg); 1719 channel, dimm, -1,
1720 err, msg, m);
1827 1721
1828 kfree(msg); 1722 kfree(msg);
1829} 1723}
@@ -2242,15 +2136,19 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
2242{ 2136{
2243 struct mem_ctl_info *mci; 2137 struct mem_ctl_info *mci;
2244 struct i7core_pvt *pvt; 2138 struct i7core_pvt *pvt;
2245 int rc, channels, csrows; 2139 int rc;
2246 2140 struct edac_mc_layer layers[2];
2247 /* Check the number of active and not disabled channels */
2248 rc = i7core_get_active_channels(i7core_dev->socket, &channels, &csrows);
2249 if (unlikely(rc < 0))
2250 return rc;
2251 2141
2252 /* allocate a new MC control structure */ 2142 /* allocate a new MC control structure */
2253 mci = edac_mc_alloc(sizeof(*pvt), csrows, channels, i7core_dev->socket); 2143
2144 layers[0].type = EDAC_MC_LAYER_CHANNEL;
2145 layers[0].size = NUM_CHANS;
2146 layers[0].is_virt_csrow = false;
2147 layers[1].type = EDAC_MC_LAYER_SLOT;
2148 layers[1].size = MAX_DIMMS;
2149 layers[1].is_virt_csrow = true;
2150 mci = new_edac_mc_alloc(i7core_dev->socket, ARRAY_SIZE(layers), layers,
2151 sizeof(*pvt));
2254 if (unlikely(!mci)) 2152 if (unlikely(!mci))
2255 return -ENOMEM; 2153 return -ENOMEM;
2256 2154