diff options
| author | James Bottomley <James.Bottomley@steeleye.com> | 2005-10-02 16:22:35 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.(none)> | 2005-10-02 16:32:25 -0400 |
| commit | 97af50f60ff1202b0dd9ce481d4cf98c6a578bec (patch) | |
| tree | 5637b5d7d505869ee5aace5ad6ed33085fc78697 | |
| parent | 9e70592fcd87c90e9e98090d66cb79f39d740d4a (diff) | |
[SCSI] aic7xxx/aic79xx: fix module removal path not to panic
In these drivers, scsi_remove_host() is called too late, at the point
it is called, the driver has already shut down too far to accept any
I/O that the shutdown might generate. Any generated I/O actually
triggers a panic.
Fix this by calling scsi_remove_host() as early as possible and not
calling scsi_host_put() until just before we kfree the ahc_softc.
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
| -rw-r--r-- | drivers/scsi/aic7xxx/aic7770_osm.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic79xx_osm_pci.c | 3 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 8 | ||||
| -rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 3 |
5 files changed, 15 insertions, 10 deletions
diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index 70c5fb59c9ea..d754b3267863 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c | |||
| @@ -112,6 +112,9 @@ aic7770_remove(struct device *dev) | |||
| 112 | struct ahc_softc *ahc = dev_get_drvdata(dev); | 112 | struct ahc_softc *ahc = dev_get_drvdata(dev); |
| 113 | u_long s; | 113 | u_long s; |
| 114 | 114 | ||
| 115 | if (ahc->platform_data && ahc->platform_data->host) | ||
| 116 | scsi_remove_host(ahc->platform_data->host); | ||
| 117 | |||
| 115 | ahc_lock(ahc, &s); | 118 | ahc_lock(ahc, &s); |
| 116 | ahc_intr_enable(ahc, FALSE); | 119 | ahc_intr_enable(ahc, FALSE); |
| 117 | ahc_unlock(ahc, &s); | 120 | ahc_unlock(ahc, &s); |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 6b6d4e287793..95c285cc83e4 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
| @@ -1192,11 +1192,6 @@ ahd_platform_free(struct ahd_softc *ahd) | |||
| 1192 | int i, j; | 1192 | int i, j; |
| 1193 | 1193 | ||
| 1194 | if (ahd->platform_data != NULL) { | 1194 | if (ahd->platform_data != NULL) { |
| 1195 | if (ahd->platform_data->host != NULL) { | ||
| 1196 | scsi_remove_host(ahd->platform_data->host); | ||
| 1197 | scsi_host_put(ahd->platform_data->host); | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | /* destroy all of the device and target objects */ | 1195 | /* destroy all of the device and target objects */ |
| 1201 | for (i = 0; i < AHD_NUM_TARGETS; i++) { | 1196 | for (i = 0; i < AHD_NUM_TARGETS; i++) { |
| 1202 | starget = ahd->platform_data->starget[i]; | 1197 | starget = ahd->platform_data->starget[i]; |
| @@ -1226,6 +1221,9 @@ ahd_platform_free(struct ahd_softc *ahd) | |||
| 1226 | release_mem_region(ahd->platform_data->mem_busaddr, | 1221 | release_mem_region(ahd->platform_data->mem_busaddr, |
| 1227 | 0x1000); | 1222 | 0x1000); |
| 1228 | } | 1223 | } |
| 1224 | if (ahd->platform_data->host) | ||
| 1225 | scsi_host_put(ahd->platform_data->host); | ||
| 1226 | |||
| 1229 | free(ahd->platform_data, M_DEVBUF); | 1227 | free(ahd->platform_data, M_DEVBUF); |
| 1230 | } | 1228 | } |
| 1231 | } | 1229 | } |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 390b53852d4b..bf360ae021ab 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c | |||
| @@ -95,6 +95,9 @@ ahd_linux_pci_dev_remove(struct pci_dev *pdev) | |||
| 95 | struct ahd_softc *ahd = pci_get_drvdata(pdev); | 95 | struct ahd_softc *ahd = pci_get_drvdata(pdev); |
| 96 | u_long s; | 96 | u_long s; |
| 97 | 97 | ||
| 98 | if (ahd->platform_data && ahd->platform_data->host) | ||
| 99 | scsi_remove_host(ahd->platform_data->host); | ||
| 100 | |||
| 98 | ahd_lock(ahd, &s); | 101 | ahd_lock(ahd, &s); |
| 99 | ahd_intr_enable(ahd, FALSE); | 102 | ahd_intr_enable(ahd, FALSE); |
| 100 | ahd_unlock(ahd, &s); | 103 | ahd_unlock(ahd, &s); |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 876d1de8480d..6ee1435d37fa 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
| @@ -1209,11 +1209,6 @@ ahc_platform_free(struct ahc_softc *ahc) | |||
| 1209 | int i, j; | 1209 | int i, j; |
| 1210 | 1210 | ||
| 1211 | if (ahc->platform_data != NULL) { | 1211 | if (ahc->platform_data != NULL) { |
| 1212 | if (ahc->platform_data->host != NULL) { | ||
| 1213 | scsi_remove_host(ahc->platform_data->host); | ||
| 1214 | scsi_host_put(ahc->platform_data->host); | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | /* destroy all of the device and target objects */ | 1212 | /* destroy all of the device and target objects */ |
| 1218 | for (i = 0; i < AHC_NUM_TARGETS; i++) { | 1213 | for (i = 0; i < AHC_NUM_TARGETS; i++) { |
| 1219 | starget = ahc->platform_data->starget[i]; | 1214 | starget = ahc->platform_data->starget[i]; |
| @@ -1242,6 +1237,9 @@ ahc_platform_free(struct ahc_softc *ahc) | |||
| 1242 | 0x1000); | 1237 | 0x1000); |
| 1243 | } | 1238 | } |
| 1244 | 1239 | ||
| 1240 | if (ahc->platform_data->host) | ||
| 1241 | scsi_host_put(ahc->platform_data->host); | ||
| 1242 | |||
| 1245 | free(ahc->platform_data, M_DEVBUF); | 1243 | free(ahc->platform_data, M_DEVBUF); |
| 1246 | } | 1244 | } |
| 1247 | } | 1245 | } |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 3ce77ddc889e..cb30d9c1153d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | |||
| @@ -143,6 +143,9 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev) | |||
| 143 | struct ahc_softc *ahc = pci_get_drvdata(pdev); | 143 | struct ahc_softc *ahc = pci_get_drvdata(pdev); |
| 144 | u_long s; | 144 | u_long s; |
| 145 | 145 | ||
| 146 | if (ahc->platform_data && ahc->platform_data->host) | ||
| 147 | scsi_remove_host(ahc->platform_data->host); | ||
| 148 | |||
| 146 | ahc_lock(ahc, &s); | 149 | ahc_lock(ahc, &s); |
| 147 | ahc_intr_enable(ahc, FALSE); | 150 | ahc_intr_enable(ahc, FALSE); |
| 148 | ahc_unlock(ahc, &s); | 151 | ahc_unlock(ahc, &s); |
