aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2009-09-05 22:06:50 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-10 10:45:00 -0400
commit22e6bcbdcf9279321dbe646c5a234b816db12881 (patch)
tree1488af672bbf9b4ffd5afd35c450c95b4fd8a32b /drivers/edac
parent0f062792b48dc8389fb18cbfb9318625886644c7 (diff)
i7core_edac: change remove module strategy
The old remove module stragegy didn't work on devices with multiple cores, since only one PCI device is used to open all mc's, due to Nehalem nature. Also, it were based at pdev value. However, this doesn't point to the pci device used at mci->dev. So, instead, it unregisters all devices at once, deleting them from the device list. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/i7core_edac.c55
1 files changed, 35 insertions, 20 deletions
diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c
index 391348bf93d2..c3fec5de3e51 100644
--- a/drivers/edac/i7core_edac.c
+++ b/drivers/edac/i7core_edac.c
@@ -1138,11 +1138,18 @@ static void i7core_put_devices(struct i7core_dev *i7core_dev)
1138{ 1138{
1139 int i; 1139 int i;
1140 1140
1141 for (i = 0; i < N_DEVS; i++) 1141 debugf0(__FILE__ ": %s()\n", __func__);
1142 pci_dev_put(i7core_dev->pdev[i]); 1142 for (i = 0; i < N_DEVS; i++) {
1143 1143 struct pci_dev *pdev = i7core_dev->pdev[i];
1144 list_del(&i7core_dev->list); 1144 if (!pdev)
1145 continue;
1146 debugf0("Removing dev %02x:%02x.%d\n",
1147 pdev->bus->number,
1148 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn));
1149 pci_dev_put(pdev);
1150 }
1145 kfree(i7core_dev->pdev); 1151 kfree(i7core_dev->pdev);
1152 list_del(&i7core_dev->list);
1146 kfree(i7core_dev); 1153 kfree(i7core_dev);
1147} 1154}
1148 1155
@@ -1863,31 +1870,39 @@ fail0:
1863static void __devexit i7core_remove(struct pci_dev *pdev) 1870static void __devexit i7core_remove(struct pci_dev *pdev)
1864{ 1871{
1865 struct mem_ctl_info *mci; 1872 struct mem_ctl_info *mci;
1866 struct i7core_pvt *pvt; 1873 struct i7core_dev *i7core_dev, *tmp;
1867 struct i7core_dev *i7core_dev;
1868 1874
1869 debugf0(__FILE__ ": %s()\n", __func__); 1875 debugf0(__FILE__ ": %s()\n", __func__);
1870 1876
1871 if (i7core_pci) 1877 if (i7core_pci)
1872 edac_pci_release_generic_ctl(i7core_pci); 1878 edac_pci_release_generic_ctl(i7core_pci);
1873 1879
1880 /*
1881 * we have a trouble here: pdev value for removal will be wrong, since
1882 * it will point to the X58 register used to detect that the machine
1883 * is a Nehalem or upper design. However, due to the way several PCI
1884 * devices are grouped together to provide MC functionality, we need
1885 * to use a different method for releasing the devices
1886 */
1874 1887
1875 mci = edac_mc_del_mc(&pdev->dev);
1876 if (!mci)
1877 return;
1878
1879 /* Unregisters on edac_mce in order to receive memory errors */
1880 pvt = mci->pvt_info;
1881 i7core_dev = pvt->i7core_dev;
1882 edac_mce_unregister(&pvt->edac_mce);
1883
1884 /* retrieve references to resources, and free those resources */
1885 mutex_lock(&i7core_edac_lock); 1888 mutex_lock(&i7core_edac_lock);
1886 i7core_put_devices(i7core_dev); 1889 list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
1890 mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
1891 if (mci) {
1892 struct i7core_pvt *pvt = mci->pvt_info;
1893
1894 i7core_dev = pvt->i7core_dev;
1895 edac_mce_unregister(&pvt->edac_mce);
1896 kfree(mci->ctl_name);
1897 edac_mc_free(mci);
1898 i7core_put_devices(i7core_dev);
1899 } else {
1900 i7core_printk(KERN_ERR,
1901 "Couldn't find mci for socket %d\n",
1902 i7core_dev->socket);
1903 }
1904 }
1887 mutex_unlock(&i7core_edac_lock); 1905 mutex_unlock(&i7core_edac_lock);
1888
1889 kfree(mci->ctl_name);
1890 edac_mc_free(mci);
1891} 1906}
1892 1907
1893MODULE_DEVICE_TABLE(pci, i7core_pci_tbl); 1908MODULE_DEVICE_TABLE(pci, i7core_pci_tbl);