[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>
This commit is contained in:
parent
9e70592fcd
commit
97af50f60f
|
@ -112,6 +112,9 @@ aic7770_remove(struct device *dev)
|
||||||
struct ahc_softc *ahc = dev_get_drvdata(dev);
|
struct ahc_softc *ahc = dev_get_drvdata(dev);
|
||||||
u_long s;
|
u_long s;
|
||||||
|
|
||||||
|
if (ahc->platform_data && ahc->platform_data->host)
|
||||||
|
scsi_remove_host(ahc->platform_data->host);
|
||||||
|
|
||||||
ahc_lock(ahc, &s);
|
ahc_lock(ahc, &s);
|
||||||
ahc_intr_enable(ahc, FALSE);
|
ahc_intr_enable(ahc, FALSE);
|
||||||
ahc_unlock(ahc, &s);
|
ahc_unlock(ahc, &s);
|
||||||
|
|
|
@ -1192,11 +1192,6 @@ ahd_platform_free(struct ahd_softc *ahd)
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (ahd->platform_data != NULL) {
|
if (ahd->platform_data != NULL) {
|
||||||
if (ahd->platform_data->host != NULL) {
|
|
||||||
scsi_remove_host(ahd->platform_data->host);
|
|
||||||
scsi_host_put(ahd->platform_data->host);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* destroy all of the device and target objects */
|
/* destroy all of the device and target objects */
|
||||||
for (i = 0; i < AHD_NUM_TARGETS; i++) {
|
for (i = 0; i < AHD_NUM_TARGETS; i++) {
|
||||||
starget = ahd->platform_data->starget[i];
|
starget = ahd->platform_data->starget[i];
|
||||||
|
@ -1226,6 +1221,9 @@ ahd_platform_free(struct ahd_softc *ahd)
|
||||||
release_mem_region(ahd->platform_data->mem_busaddr,
|
release_mem_region(ahd->platform_data->mem_busaddr,
|
||||||
0x1000);
|
0x1000);
|
||||||
}
|
}
|
||||||
|
if (ahd->platform_data->host)
|
||||||
|
scsi_host_put(ahd->platform_data->host);
|
||||||
|
|
||||||
free(ahd->platform_data, M_DEVBUF);
|
free(ahd->platform_data, M_DEVBUF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,9 @@ ahd_linux_pci_dev_remove(struct pci_dev *pdev)
|
||||||
struct ahd_softc *ahd = pci_get_drvdata(pdev);
|
struct ahd_softc *ahd = pci_get_drvdata(pdev);
|
||||||
u_long s;
|
u_long s;
|
||||||
|
|
||||||
|
if (ahd->platform_data && ahd->platform_data->host)
|
||||||
|
scsi_remove_host(ahd->platform_data->host);
|
||||||
|
|
||||||
ahd_lock(ahd, &s);
|
ahd_lock(ahd, &s);
|
||||||
ahd_intr_enable(ahd, FALSE);
|
ahd_intr_enable(ahd, FALSE);
|
||||||
ahd_unlock(ahd, &s);
|
ahd_unlock(ahd, &s);
|
||||||
|
|
|
@ -1209,11 +1209,6 @@ ahc_platform_free(struct ahc_softc *ahc)
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if (ahc->platform_data != NULL) {
|
if (ahc->platform_data != NULL) {
|
||||||
if (ahc->platform_data->host != NULL) {
|
|
||||||
scsi_remove_host(ahc->platform_data->host);
|
|
||||||
scsi_host_put(ahc->platform_data->host);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* destroy all of the device and target objects */
|
/* destroy all of the device and target objects */
|
||||||
for (i = 0; i < AHC_NUM_TARGETS; i++) {
|
for (i = 0; i < AHC_NUM_TARGETS; i++) {
|
||||||
starget = ahc->platform_data->starget[i];
|
starget = ahc->platform_data->starget[i];
|
||||||
|
@ -1242,6 +1237,9 @@ ahc_platform_free(struct ahc_softc *ahc)
|
||||||
0x1000);
|
0x1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ahc->platform_data->host)
|
||||||
|
scsi_host_put(ahc->platform_data->host);
|
||||||
|
|
||||||
free(ahc->platform_data, M_DEVBUF);
|
free(ahc->platform_data, M_DEVBUF);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,9 @@ ahc_linux_pci_dev_remove(struct pci_dev *pdev)
|
||||||
struct ahc_softc *ahc = pci_get_drvdata(pdev);
|
struct ahc_softc *ahc = pci_get_drvdata(pdev);
|
||||||
u_long s;
|
u_long s;
|
||||||
|
|
||||||
|
if (ahc->platform_data && ahc->platform_data->host)
|
||||||
|
scsi_remove_host(ahc->platform_data->host);
|
||||||
|
|
||||||
ahc_lock(ahc, &s);
|
ahc_lock(ahc, &s);
|
||||||
ahc_intr_enable(ahc, FALSE);
|
ahc_intr_enable(ahc, FALSE);
|
||||||
ahc_unlock(ahc, &s);
|
ahc_unlock(ahc, &s);
|
||||||
|
|
Loading…
Reference in New Issue