aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-06-22 21:48:29 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 10:44:45 -0400
commit8f331907578623f90a134261a559fa3249142caa (patch)
treedc73b3736a8214f2bafcbfea0edd9ed96e140505
parent0b2b7b7ec06ce615acd11374bf9a512e166dabb0 (diff)
i7core_edac: Registers all supported MC functions
Now, it will try to register on all supported Memory Controller functions. It should be noticed that dev3, function 2 is present only on chips with Registered DIMM's, according to the datasheet. So, the driver doesn't return -ENODEV is all functions but this one were successfully registered and enabled: EDAC i7core: Registered device 8086:2c18 fn=3 0 EDAC i7core: Registered device 8086:2c19 fn=3 1 EDAC i7core: Device not found: PCI ID 8086:2c1a (dev 3, func 2) EDAC i7core: Registered device 8086:2c1c fn=3 4 EDAC i7core: Registered device 8086:2c20 fn=4 0 EDAC i7core: Registered device 8086:2c21 fn=4 1 EDAC i7core: Registered device 8086:2c22 fn=4 2 EDAC i7core: Registered device 8086:2c23 fn=4 3 EDAC i7core: Registered device 8086:2c28 fn=5 0 EDAC i7core: Registered device 8086:2c29 fn=5 1 EDAC i7core: Registered device 8086:2c2a fn=5 2 EDAC i7core: Registered device 8086:2c2b fn=5 3 EDAC i7core: Registered device 8086:2c30 fn=6 0 EDAC i7core: Registered device 8086:2c31 fn=6 1 EDAC i7core: Registered device 8086:2c32 fn=6 2 EDAC i7core: Registered device 8086:2c33 fn=6 3 EDAC i7core: Driver loaded. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/edac/i7core_edac.c217
1 files changed, 131 insertions, 86 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index da40730bf9c..79aa84eaa12 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -128,7 +128,8 @@
128 */ 128 */
129 129
130#define NUM_CHANS 3 130#define NUM_CHANS 3
131#define NUM_FUNCS 1 131#define NUM_MCR_FUNCS 4
132#define NUM_CHAN_FUNCS 3
132 133
133struct i7core_info { 134struct i7core_info {
134 u32 mc_control; 135 u32 mc_control;
@@ -153,9 +154,16 @@ struct i7core_channel {
153 u32 dimms; 154 u32 dimms;
154}; 155};
155 156
157struct pci_id_descr {
158 int dev;
159 int func;
160 int dev_id;
161 struct pci_dev *pdev;
162};
163
156struct i7core_pvt { 164struct i7core_pvt {
157 struct pci_dev *pci_mcr; /* Dev 3:0 */ 165 struct pci_dev *pci_mcr[NUM_MCR_FUNCS];
158 struct pci_dev *pci_ch[NUM_CHANS][NUM_FUNCS]; 166 struct pci_dev *pci_ch[NUM_CHANS][NUM_CHAN_FUNCS];
159 struct i7core_info info; 167 struct i7core_info info;
160 struct i7core_inject inject; 168 struct i7core_inject inject;
161 struct i7core_channel channel[NUM_CHANS]; 169 struct i7core_channel channel[NUM_CHANS];
@@ -167,11 +175,47 @@ struct i7core_dev_info {
167 u16 fsb_mapping_errors; /* DID for the branchmap,control */ 175 u16 fsb_mapping_errors; /* DID for the branchmap,control */
168}; 176};
169 177
170static int chan_pci_ids[NUM_CHANS] = { 178#define PCI_DESCR(device, function, device_id) \
171 PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL, /* Dev 4 */ 179 .dev = (device), \
172 PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL, /* Dev 5 */ 180 .func = (function), \
173 PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL, /* Dev 6 */ 181 .dev_id = (device_id)
182
183struct pci_id_descr pci_devs[] = {
184 /* Memory controller */
185 { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) },
186 { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) },
187 { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM is supported */
188 { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) },
189
190 /* Channel 0 */
191 { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) },
192 { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) },
193 { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK) },
194 { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC) },
195
196 /* Channel 1 */
197 { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL) },
198 { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR) },
199 { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK) },
200 { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC) },
201
202 /* Channel 2 */
203 { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL) },
204 { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) },
205 { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) },
206 { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) },
174}; 207};
208#define N_DEVS ARRAY_SIZE(pci_devs)
209
210/*
211 * pci_device_id table for which devices we are looking for
212 * This should match the first device at pci_devs table
213 */
214static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
215 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR)},
216 {0,} /* 0 terminated list. */
217};
218
175 219
176/* Table of devices attributes supported by this driver */ 220/* Table of devices attributes supported by this driver */
177static const struct i7core_dev_info i7core_devs[] = { 221static const struct i7core_dev_info i7core_devs[] = {
@@ -242,9 +286,12 @@ static int get_dimm_config(struct mem_ctl_info *mci)
242 struct i7core_pvt *pvt = mci->pvt_info; 286 struct i7core_pvt *pvt = mci->pvt_info;
243 int i; 287 int i;
244 288
245 pci_read_config_dword(pvt->pci_mcr, MC_CONTROL, &pvt->info.mc_control); 289 if (!pvt->pci_mcr[0])
246 pci_read_config_dword(pvt->pci_mcr, MC_STATUS, &pvt->info.mc_status); 290 return -ENODEV;
247 pci_read_config_dword(pvt->pci_mcr, MC_MAX_DOD, &pvt->info.max_dod); 291
292 pci_read_config_dword(pvt->pci_mcr[0], MC_CONTROL, &pvt->info.mc_control);
293 pci_read_config_dword(pvt->pci_mcr[0], MC_STATUS, &pvt->info.mc_status);
294 pci_read_config_dword(pvt->pci_mcr[0], MC_MAX_DOD, &pvt->info.max_dod);
248 295
249 if (ECC_ENABLED(pvt)) 296 if (ECC_ENABLED(pvt))
250 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4); 297 debugf0("ECC enabled with x%d SDCC\n", ECCx8(pvt)?8:4);
@@ -303,14 +350,19 @@ static int get_dimm_config(struct mem_ctl_info *mci)
303 we're disabling error injection on all write calls to the sysfs nodes that 350 we're disabling error injection on all write calls to the sysfs nodes that
304 controls the error code injection. 351 controls the error code injection.
305 */ 352 */
306static void disable_inject(struct mem_ctl_info *mci) 353static int disable_inject(struct mem_ctl_info *mci)
307{ 354{
308 struct i7core_pvt *pvt = mci->pvt_info; 355 struct i7core_pvt *pvt = mci->pvt_info;
309 356
310 pvt->inject.enable = 0; 357 pvt->inject.enable = 0;
311 358
359 if (!pvt->pci_ch[pvt->inject.channel][0])
360 return -ENODEV;
361
312 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], 362 pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0],
313 MC_CHANNEL_ERROR_MASK, 0); 363 MC_CHANNEL_ERROR_MASK, 0);
364
365 return 0;
314} 366}
315 367
316/* 368/*
@@ -550,6 +602,9 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci,
550 int rc; 602 int rc;
551 long enable; 603 long enable;
552 604
605 if (!pvt->pci_ch[pvt->inject.channel][0])
606 return 0;
607
553 rc = strict_strtoul(data, 10, &enable); 608 rc = strict_strtoul(data, 10, &enable);
554 if ((rc < 0)) 609 if ((rc < 0))
555 return 0; 610 return 0;
@@ -684,17 +739,12 @@ static struct mcidev_sysfs_attribute i7core_inj_attrs[] = {
684 * i7core_put_devices 'put' all the devices that we have 739 * i7core_put_devices 'put' all the devices that we have
685 * reserved via 'get' 740 * reserved via 'get'
686 */ 741 */
687static void i7core_put_devices(struct mem_ctl_info *mci) 742static void i7core_put_devices(void)
688{ 743{
689 struct i7core_pvt *pvt = mci->pvt_info; 744 int i;
690 int i, n;
691
692 pci_dev_put(pvt->pci_mcr);
693 745
694 /* Release all PCI device functions at MTR channel controllers */ 746 for (i = 0; i < N_DEVS; i++)
695 for (i = 0; i < NUM_CHANS; i++) 747 pci_dev_put(pci_devs[i].pdev);
696 for (n = 0; n < NUM_FUNCS; n++)
697 pci_dev_put(pvt->pci_ch[i][n]);
698} 748}
699 749
700/* 750/*
@@ -703,50 +753,67 @@ static void i7core_put_devices(struct mem_ctl_info *mci)
703 * 753 *
704 * Need to 'get' device 16 func 1 and func 2 754 * Need to 'get' device 16 func 1 and func 2
705 */ 755 */
706static int i7core_get_devices(struct mem_ctl_info *mci, int dev_idx) 756static int i7core_get_devices(struct mem_ctl_info *mci, struct pci_dev *mcidev)
707{ 757{
708 struct i7core_pvt *pvt; 758 struct i7core_pvt *pvt = mci->pvt_info;
709 struct pci_dev *pdev; 759 int rc, i,func;
710 int i, n, func; 760 struct pci_dev *pdev = NULL;
711 761
712 pvt = mci->pvt_info; 762 pvt = mci->pvt_info;
713 memset(pvt, 0, sizeof(*pvt)); 763 memset(pvt, 0, sizeof(*pvt));
714 764
715 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR, 765 for (i = 0; i < N_DEVS; i++) {
716 NULL); 766 pdev = pci_get_device(PCI_VENDOR_ID_INTEL,
717 if (!pdev) { 767 pci_devs[i].dev_id, NULL);
718 i7core_printk(KERN_ERR, 768 if (!pdev) {
719 "Couldn't get PCI ID %04x:%04x function 0\n", 769 /* End of list, leave */
720 PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR); 770 i7core_printk(KERN_ERR,
721 return -ENODEV; 771 "Device not found: PCI ID %04x:%04x "
722 } 772 "(dev %d, func %d)\n",
723 pvt->pci_mcr=pdev; 773 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
774 pci_devs[i].dev,pci_devs[i].func);
775 if ((pci_devs[i].dev == 3) && (pci_devs[i].func == 2))
776 continue; /* Only on chips with RDIMMs */
777 else
778 i7core_put_devices();
779 }
780 pci_devs[i].pdev = pdev;
781
782 rc = pci_enable_device(pdev);
783 if (rc < 0) {
784 i7core_printk(KERN_ERR,
785 "Couldn't enable PCI ID %04x:%04x "
786 "(dev %d, func %d)\n",
787 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
788 pci_devs[i].dev, pci_devs[i].func);
789 i7core_put_devices();
790 return rc;
791 }
792 /* Sanity check */
793 if (PCI_FUNC(pdev->devfn) != pci_devs[i].func) {
794 i7core_printk(KERN_ERR,
795 "Device PCI ID %04x:%04x "
796 "has function %d instead of %d\n",
797 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
798 PCI_FUNC(pdev->devfn), pci_devs[i].func);
799 i7core_put_devices();
800 return -EINVAL;
801 }
724 802
725 /* Retrieve all needed functions at MTR channel controllers */ 803 i7core_printk(KERN_INFO,
726 for (i = 0; i < NUM_CHANS; i++) { 804 "Registered device %0x:%0x fn=%0x %0x\n",
727 pdev = NULL; 805 PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id,
728 for (n = 0; n < NUM_FUNCS; n++) { 806 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
729 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 807
730 chan_pci_ids[i], pdev); 808 func = PCI_FUNC(pdev->devfn);
731 if (!pdev) { 809 if (pci_devs[i].dev < 4) {
732 /* End of list, leave */ 810 pvt->pci_mcr[func] = pdev;
733 i7core_printk(KERN_ERR, 811 } else {
734 "Device not found: PCI ID %04x:%04x " 812 pvt->pci_ch[pci_devs[i].dev - 4][func] = pdev;
735 "found only %d functions "
736 "(broken BIOS?)\n",
737 PCI_VENDOR_ID_INTEL,
738 chan_pci_ids[i], n);
739 i7core_put_devices(mci);
740 return -ENODEV;
741 }
742 func = PCI_FUNC(pdev->devfn);
743 pvt->pci_ch[i][func] = pdev;
744 } 813 }
745 } 814 }
746 i7core_printk(KERN_INFO, "Driver loaded.\n");
747 815
748 /* Get dimm basic config */ 816 i7core_printk(KERN_INFO, "Driver loaded.\n");
749 get_dimm_config(mci);
750 817
751 return 0; 818 return 0;
752} 819}
@@ -763,7 +830,6 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
763{ 830{
764 struct mem_ctl_info *mci; 831 struct mem_ctl_info *mci;
765 struct i7core_pvt *pvt; 832 struct i7core_pvt *pvt;
766 int rc;
767 int num_channels; 833 int num_channels;
768 int num_csrows; 834 int num_csrows;
769 int num_dimms_per_channel; 835 int num_dimms_per_channel;
@@ -772,20 +838,6 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
772 if (dev_idx >= ARRAY_SIZE(i7core_devs)) 838 if (dev_idx >= ARRAY_SIZE(i7core_devs))
773 return -EINVAL; 839 return -EINVAL;
774 840
775 /* wake up device */
776 rc = pci_enable_device(pdev);
777 if (rc == -EIO)
778 return rc;
779
780 debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n",
781 __func__,
782 pdev->bus->number,
783 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
784
785 /* We only are looking for func 0 of the set */
786 if (PCI_FUNC(pdev->devfn) != 0)
787 return -ENODEV;
788
789 num_channels = NUM_CHANS; 841 num_channels = NUM_CHANS;
790 842
791 /* FIXME: FAKE data, since we currently don't now how to get this */ 843 /* FIXME: FAKE data, since we currently don't now how to get this */
@@ -808,10 +860,6 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
808// pvt->maxch = num_channels; 860// pvt->maxch = num_channels;
809// pvt->maxdimmperch = num_dimms_per_channel; 861// pvt->maxdimmperch = num_dimms_per_channel;
810 862
811 /* 'get' the pci devices we want to reserve for our use */
812 if (i7core_get_devices(mci, dev_idx))
813 goto fail0;
814
815 mci->mc_idx = 0; 863 mci->mc_idx = 0;
816 mci->mtype_cap = MEM_FLAG_FB_DDR2; /* FIXME: it uses DDR3 */ 864 mci->mtype_cap = MEM_FLAG_FB_DDR2; /* FIXME: it uses DDR3 */
817 mci->edac_ctl_cap = EDAC_FLAG_NONE; 865 mci->edac_ctl_cap = EDAC_FLAG_NONE;
@@ -823,6 +871,10 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
823 mci->ctl_page_to_phys = NULL; 871 mci->ctl_page_to_phys = NULL;
824 mci->mc_driver_sysfs_attributes = i7core_inj_attrs; 872 mci->mc_driver_sysfs_attributes = i7core_inj_attrs;
825 873
874 /* 'get' the pci devices we want to reserve for our use */
875 if (i7core_get_devices(mci, pdev))
876 goto fail0;
877
826 /* add this new MC control structure to EDAC's list of MCs */ 878 /* add this new MC control structure to EDAC's list of MCs */
827 if (edac_mc_add_mc(mci)) { 879 if (edac_mc_add_mc(mci)) {
828 debugf0("MC: " __FILE__ 880 debugf0("MC: " __FILE__
@@ -852,10 +904,13 @@ static int __devinit i7core_probe(struct pci_dev *pdev,
852 pvt->inject.page = -1; 904 pvt->inject.page = -1;
853 pvt->inject.col = -1; 905 pvt->inject.col = -1;
854 906
907 /* Get dimm basic config */
908 get_dimm_config(mci);
909
855 return 0; 910 return 0;
856 911
857fail1: 912fail1:
858 i7core_put_devices(mci); 913 i7core_put_devices();
859 914
860fail0: 915fail0:
861 edac_mc_free(mci); 916 edac_mc_free(mci);
@@ -880,21 +935,11 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
880 return; 935 return;
881 936
882 /* retrieve references to resources, and free those resources */ 937 /* retrieve references to resources, and free those resources */
883 i7core_put_devices(mci); 938 i7core_put_devices();
884 939
885 edac_mc_free(mci); 940 edac_mc_free(mci);
886} 941}
887 942
888/*
889 * pci_device_id table for which devices we are looking for
890 *
891 * The "E500P" device is the first device supported.
892 */
893static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
894 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR)},
895 {0,} /* 0 terminated list. */
896};
897
898MODULE_DEVICE_TABLE(pci, i7core_pci_tbl); 943MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);
899 944
900/* 945/*