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;
static int aic7770_linux_config(struct aic7770_identity *entry,
aic7770_dev_t dev, u_int eisaBase);
void
int
ahc_linux_eisa_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
......@@ -82,7 +82,7 @@ ahc_linux_eisa_init(void)
int i;
if (aic7xxx_probe_eisa_vl == 0)
return;
return -ENODEV;
/*
* Linux requires the EISA IDs to be specified in
......@@ -93,7 +93,7 @@ ahc_linux_eisa_init(void)
(ahc_num_aic7770_devs + 1),
M_DEVBUF, M_NOWAIT);
if (aic7770_driver.id_table == NULL)
return;
return -ENOMEM;
for (eid = (struct eisa_device_id *)aic7770_driver.id_table,
id = aic7770_ident_table, i = 0;
......@@ -109,15 +109,16 @@ ahc_linux_eisa_init(void)
}
eid->sig[0] = 0;
eisa_driver_register(&aic7770_driver);
return eisa_driver_register(&aic7770_driver);
#else /* LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) */
struct aic7770_identity *entry;
u_int slot;
u_int eisaBase;
u_int i;
int ret = -ENODEV;
if (aic7xxx_probe_eisa_vl == 0)
return;
return ret;
eisaBase = 0x1000 + AHC_EISA_SLOT_OFFSET;
for (slot = 1; slot < NUMSLOTS; eisaBase+=0x1000, slot++) {
......@@ -146,9 +147,12 @@ ahc_linux_eisa_init(void)
continue; /* no EISA card in slot */
entry = aic7770_find_device(eisa_id);
if (entry != NULL)
if (entry != NULL) {
aic7770_linux_config(entry, NULL, eisaBase);
ret = 0;
}
}
return ret;
#endif
}
......@@ -156,13 +160,8 @@ void
ahc_linux_eisa_exit(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
if (aic7xxx_probe_eisa_vl == 0)
return;
if (aic7770_driver.id_table != NULL) {
eisa_driver_unregister(&aic7770_driver);
free(aic7770_driver.id_table, M_DEVBUF);
}
eisa_driver_unregister(&aic7770_driver);
free(aic7770_driver.id_table, M_DEVBUF);
#endif
}
......
......@@ -892,18 +892,25 @@ ahc_linux_detect(Scsi_Host_Template *template)
ahc_list_lockinit();
#ifdef CONFIG_PCI
ahc_linux_pci_init();
found = ahc_linux_pci_init();
if (found)
goto out;
#endif
#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
/*
* Register with the SCSI layer all
* controllers we've found.
*/
found = 0;
TAILQ_FOREACH(ahc, &ahc_tailq, links) {
if (ahc_linux_register_host(ahc, template) == 0)
......@@ -913,6 +920,8 @@ ahc_linux_detect(Scsi_Host_Template *template)
spin_lock_irq(&io_request_lock);
#endif
aic7xxx_detect_complete++;
out:
return (found);
}
......@@ -5067,11 +5076,17 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
}
}
static void __exit ahc_linux_exit(void);
static int __init
ahc_linux_init(void)
{
#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
scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
if (aic7xxx_driver_template.present == 0) {
......
......@@ -840,7 +840,7 @@ typedef enum
#ifdef CONFIG_EISA
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);
int aic7770_map_registers(struct ahc_softc *ahc,
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