diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/i7core_edac.c | 55 |
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: | |||
1863 | static void __devexit i7core_remove(struct pci_dev *pdev) | 1870 | static 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 | ||
1893 | MODULE_DEVICE_TABLE(pci, i7core_pci_tbl); | 1908 | MODULE_DEVICE_TABLE(pci, i7core_pci_tbl); |