Commit fc649790 authored by Andrew Morton's avatar Andrew Morton Committed by James Bottomley

[PATCH] aic7xxx: fix oops whe hardware is not present

From: Herbert Xu <herbert@gondor.apana.org.au>

This is because aic7xxx does not unregister itself properly if no devices
are found.  This patch fixes the problem.
parent 66b47029
...@@ -73,7 +73,7 @@ typedef void *aic7770_dev_t; ...@@ -73,7 +73,7 @@ typedef void *aic7770_dev_t;
static int aic7770_linux_config(struct aic7770_identity *entry, static int aic7770_linux_config(struct aic7770_identity *entry,
aic7770_dev_t dev, u_int eisaBase); aic7770_dev_t dev, u_int eisaBase);
void int
ahc_linux_eisa_init(void) ahc_linux_eisa_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
...@@ -82,7 +82,7 @@ ahc_linux_eisa_init(void) ...@@ -82,7 +82,7 @@ ahc_linux_eisa_init(void)
int i; int i;
if (aic7xxx_probe_eisa_vl == 0) if (aic7xxx_probe_eisa_vl == 0)
return; return -ENODEV;
/* /*
* Linux requires the EISA IDs to be specified in * Linux requires the EISA IDs to be specified in
...@@ -93,7 +93,7 @@ ahc_linux_eisa_init(void) ...@@ -93,7 +93,7 @@ ahc_linux_eisa_init(void)
(ahc_num_aic7770_devs + 1), (ahc_num_aic7770_devs + 1),
M_DEVBUF, M_NOWAIT); M_DEVBUF, M_NOWAIT);
if (aic7770_driver.id_table == NULL) if (aic7770_driver.id_table == NULL)
return; return -ENOMEM;
for (eid = (struct eisa_device_id *)aic7770_driver.id_table, for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
id = aic7770_ident_table, i = 0; id = aic7770_ident_table, i = 0;
...@@ -109,15 +109,16 @@ ahc_linux_eisa_init(void) ...@@ -109,15 +109,16 @@ ahc_linux_eisa_init(void)
} }
eid->sig[0] = 0; eid->sig[0] = 0;
eisa_driver_register(&aic7770_driver); return eisa_driver_register(&aic7770_driver);
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */ #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
struct aic7770_identity *entry; struct aic7770_identity *entry;
u_int slot; u_int slot;
u_int eisaBase; u_int eisaBase;
u_int i; u_int i;
int ret = -ENODEV;
if (aic7xxx_probe_eisa_vl == 0) if (aic7xxx_probe_eisa_vl == 0)
return; return ret;
eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET; eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) { for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
...@@ -146,9 +147,12 @@ ahc_linux_eisa_init(void) ...@@ -146,9 +147,12 @@ ahc_linux_eisa_init(void)
continue; /* no EISA card in slot */ continue; /* no EISA card in slot */
entry = aic7770_find_device(eisa_id); entry = aic7770_find_device(eisa_id);
if (entry != NULL) if (entry != NULL) {
aic7770_linux_config(entry, NULL, eisaBase); aic7770_linux_config(entry, NULL, eisaBase);
ret = 0;
}
} }
return ret;
#endif #endif
} }
...@@ -156,13 +160,8 @@ void ...@@ -156,13 +160,8 @@ void
ahc_linux_eisa_exit(void) ahc_linux_eisa_exit(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if (aic7xxx_probe_eisa_vl == 0) eisa_driver_unregister(&aic7770_driver);
return; free(aic7770_driver.id_table, M_DEVBUF);
if (aic7770_driver.id_table != NULL) {
eisa_driver_unregister(&aic7770_driver);
free(aic7770_driver.id_table, M_DEVBUF);
}
#endif #endif
} }
......
...@@ -892,18 +892,25 @@ ahc_linux_detect(Scsi_Host_Template *template) ...@@ -892,18 +892,25 @@ ahc_linux_detect(Scsi_Host_Template *template)
ahc_list_lockinit(); ahc_list_lockinit();
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
ahc_linux_pci_init(); found = ahc_linux_pci_init();
if (found)
goto out;
#endif #endif
#ifdef CONFIG_EISA #ifdef CONFIG_EISA
ahc_linux_eisa_init(); found = ahc_linux_eisa_init();
if (found) {
#ifdef CONFIG_PCI
ahc_linux_pci_exit();
#endif
goto out;
}
#endif #endif
/* /*
* Register with the SCSI layer all * Register with the SCSI layer all
* controllers we've found. * controllers we've found.
*/ */
found = 0;
TAILQ_FOREACH(ahc, &ahc_tailq, links) { TAILQ_FOREACH(ahc, &ahc_tailq, links) {
if (ahc_linux_register_host(ahc, template) == 0) if (ahc_linux_register_host(ahc, template) == 0)
...@@ -913,6 +920,8 @@ ahc_linux_detect(Scsi_Host_Template *template) ...@@ -913,6 +920,8 @@ ahc_linux_detect(Scsi_Host_Template *template)
spin_lock_irq(&io_request_lock); spin_lock_irq(&io_request_lock);
#endif #endif
aic7xxx_detect_complete++; aic7xxx_detect_complete++;
out:
return (found); return (found);
} }
...@@ -5067,11 +5076,17 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) ...@@ -5067,11 +5076,17 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
} }
} }
static void __exit ahc_linux_exit(void);
static int __init static int __init
ahc_linux_init(void) ahc_linux_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
return (ahc_linux_detect(&aic7xxx_driver_template) ? 0 : -ENODEV); int rc = ahc_linux_detect(&aic7xxx_driver_template);
if (rc)
return rc;
ahc_linux_exit();
return -ENODEV;
#else #else
scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template); scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
if (aic7xxx_driver_template.present == 0) { if (aic7xxx_driver_template.present == 0) {
......
...@@ -840,7 +840,7 @@ typedef enum ...@@ -840,7 +840,7 @@ typedef enum
#ifdef CONFIG_EISA #ifdef CONFIG_EISA
extern uint32_t aic7xxx_probe_eisa_vl; extern uint32_t aic7xxx_probe_eisa_vl;
void ahc_linux_eisa_init(void); int ahc_linux_eisa_init(void);
void ahc_linux_eisa_exit(void); void ahc_linux_eisa_exit(void);
int aic7770_map_registers(struct ahc_softc *ahc, int aic7770_map_registers(struct ahc_softc *ahc,
u_int port); u_int port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment