Commit 52839747 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by James Bottomley

[PATCH] scsi_add_host/scsi_Remove_host for aic7xxx/aic79xx

I remember having this submitted a while ago, but here's the code
again, this time with the untested aic79xx bits.
parent 44b2383d
...@@ -801,7 +801,6 @@ ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb, ...@@ -801,7 +801,6 @@ ahd_linux_map_seg(struct ahd_softc *ahd, struct scb *scb,
/************************ Host template entry points *************************/ /************************ Host template entry points *************************/
static int ahd_linux_detect(Scsi_Host_Template *); static int ahd_linux_detect(Scsi_Host_Template *);
static int ahd_linux_release(struct Scsi_Host *);
static const char *ahd_linux_info(struct Scsi_Host *); static const char *ahd_linux_info(struct Scsi_Host *);
static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *)); static int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
...@@ -811,6 +810,7 @@ static void ahd_linux_slave_destroy(Scsi_Device *); ...@@ -811,6 +810,7 @@ static void ahd_linux_slave_destroy(Scsi_Device *);
static int ahd_linux_biosparam(struct scsi_device*, static int ahd_linux_biosparam(struct scsi_device*,
struct block_device*, sector_t, int[]); struct block_device*, sector_t, int[]);
#else #else
static int ahd_linux_release(struct Scsi_Host *);
static void ahd_linux_select_queue_depth(struct Scsi_Host *host, static void ahd_linux_select_queue_depth(struct Scsi_Host *host,
Scsi_Device *scsi_devs); Scsi_Device *scsi_devs);
static int ahd_linux_biosparam(Disk *, kdev_t, int[]); static int ahd_linux_biosparam(Disk *, kdev_t, int[]);
...@@ -874,7 +874,7 @@ ahd_linux_detect(Scsi_Host_Template *template) ...@@ -874,7 +874,7 @@ ahd_linux_detect(Scsi_Host_Template *template)
ahd_list_lockinit(); ahd_list_lockinit();
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
ahd_linux_pci_probe(template); ahd_linux_pci_init();
#endif #endif
/* /*
...@@ -894,6 +894,7 @@ ahd_linux_detect(Scsi_Host_Template *template) ...@@ -894,6 +894,7 @@ ahd_linux_detect(Scsi_Host_Template *template)
return (found); return (found);
} }
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/* /*
* Free the passed in Scsi_Host memory structures prior to unloading the * Free the passed in Scsi_Host memory structures prior to unloading the
* module. * module.
...@@ -925,6 +926,7 @@ ahd_linux_release(struct Scsi_Host * host) ...@@ -925,6 +926,7 @@ ahd_linux_release(struct Scsi_Host * host)
ahd_list_unlock(&l); ahd_list_unlock(&l);
return (0); return (0);
} }
#endif
/* /*
* Return a string describing the driver. * Return a string describing the driver.
...@@ -1664,9 +1666,9 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd) ...@@ -1664,9 +1666,9 @@ ahd_linux_bus_reset(Scsi_Cmnd *cmd)
} }
Scsi_Host_Template aic79xx_driver_template = { Scsi_Host_Template aic79xx_driver_template = {
.module = THIS_MODULE,
.name = "aic79xx",
.proc_info = ahd_linux_proc_info, .proc_info = ahd_linux_proc_info,
.detect = ahd_linux_detect,
.release = ahd_linux_release,
.info = ahd_linux_info, .info = ahd_linux_info,
.queuecommand = ahd_linux_queue, .queuecommand = ahd_linux_queue,
.eh_abort_handler = ahd_linux_abort, .eh_abort_handler = ahd_linux_abort,
...@@ -1698,18 +1700,17 @@ Scsi_Host_Template aic79xx_driver_template = { ...@@ -1698,18 +1700,17 @@ Scsi_Host_Template aic79xx_driver_template = {
#endif #endif
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
.name = "aic79xx",
.slave_alloc = ahd_linux_slave_alloc, .slave_alloc = ahd_linux_slave_alloc,
.slave_configure = ahd_linux_slave_configure, .slave_configure = ahd_linux_slave_configure,
.slave_destroy = ahd_linux_slave_destroy, .slave_destroy = ahd_linux_slave_destroy,
#else #else
.detect = ahd_linux_detect,
.release = ahd_linux_release,
.select_queue_depths = ahd_linux_select_queue_depth, .select_queue_depths = ahd_linux_select_queue_depth,
.use_new_eh_code = 1, .use_new_eh_code = 1,
#endif #endif
}; };
#define driver_template aic79xx_driver_template
#include "scsi_module.c"
/**************************** Tasklet Handler *********************************/ /**************************** Tasklet Handler *********************************/
static void static void
...@@ -2381,9 +2382,8 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) ...@@ -2381,9 +2382,8 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
ahd_set_name(ahd, new_name); ahd_set_name(ahd, new_name);
} }
host->unique_id = ahd->unit; host->unique_id = ahd->unit;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \
scsi_set_device(host, &ahd->dev_softc->dev); LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
scsi_set_pci_device(host, ahd->dev_softc); scsi_set_pci_device(host, ahd->dev_softc);
#endif #endif
ahd_linux_initialize_scsi_bus(ahd); ahd_linux_initialize_scsi_bus(ahd);
...@@ -2410,6 +2410,10 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template) ...@@ -2410,6 +2410,10 @@ ahd_linux_register_host(struct ahd_softc *ahd, Scsi_Host_Template *template)
ahd_intr_enable(ahd, TRUE); ahd_intr_enable(ahd, TRUE);
ahd_linux_start_dv(ahd); ahd_linux_start_dv(ahd);
ahd_unlock(ahd, &s); ahd_unlock(ahd, &s);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
scsi_add_host(host, &ahd->dev_softc->dev);
#endif
return (0); return (0);
} }
...@@ -2556,8 +2560,12 @@ ahd_platform_free(struct ahd_softc *ahd) ...@@ -2556,8 +2560,12 @@ ahd_platform_free(struct ahd_softc *ahd)
__WCLONE) == -ERESTARTSYS); __WCLONE) == -ERESTARTSYS);
} }
ahd_teardown_runq_tasklet(ahd); ahd_teardown_runq_tasklet(ahd);
if (ahd->platform_data->host != NULL) if (ahd->platform_data->host != NULL) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
scsi_remove_host(ahd->platform_data->host);
#endif
scsi_unregister(ahd->platform_data->host); scsi_unregister(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++) {
...@@ -2595,21 +2603,17 @@ ahd_platform_free(struct ahd_softc *ahd) ...@@ -2595,21 +2603,17 @@ ahd_platform_free(struct ahd_softc *ahd)
0x1000); 0x1000);
#endif #endif
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) && \
/* XXX Need an instance detach in the PCI code */ LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
/*
* In 2.4 we detach from the scsi midlayer before the PCI
* layer invokes our remove callback.
*/
if (ahd->dev_softc != NULL) if (ahd->dev_softc != NULL)
ahd->dev_softc->driver = NULL; ahd->dev_softc->driver = NULL;
#endif #endif
free(ahd->platform_data, M_DEVBUF); free(ahd->platform_data, M_DEVBUF);
} }
if (TAILQ_EMPTY(&ahd_tailq)) {
unregister_reboot_notifier(&ahd_linux_notifier);
#ifdef CONFIG_PCI
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_unregister_driver(&aic79xx_pci_driver);
#endif
#endif
}
} }
void void
...@@ -5315,3 +5319,30 @@ ahd_platform_dump_card_state(struct ahd_softc *ahd) ...@@ -5315,3 +5319,30 @@ ahd_platform_dump_card_state(struct ahd_softc *ahd)
} }
} }
} }
static int __init ahd_linux_init(void)
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
return (ahd_linux_detect(&aic79xx_driver_template) ? 0 : -ENODEV);
#else
scsi_register_module(MODULE_SCSI_HA, &aic79xx_driver_template);
if (!driver_template.present) {
scsi_unregister_module(MODULE_SCSI_HA,
&aic79xx_driver_template);
return (-ENODEV);
}
return (0);
#endif
}
static void __exit ahd_linux_exit(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
scsi_unregister_module(MODULE_SCSI_HA, &aic79xx_driver_template);
#endif
ahd_linux_pci_exit();
}
module_init(ahd_linux_init);
module_exit(ahd_linux_exit);
...@@ -952,7 +952,8 @@ void ahd_power_state_change(struct ahd_softc *ahd, ...@@ -952,7 +952,8 @@ void ahd_power_state_change(struct ahd_softc *ahd,
#include <linux/bios32.h> #include <linux/bios32.h>
#endif #endif
int ahd_linux_pci_probe(Scsi_Host_Template *); int ahd_linux_pci_init(void);
void ahd_linux_pci_exit(void);
int ahd_pci_map_registers(struct ahd_softc *ahd); int ahd_pci_map_registers(struct ahd_softc *ahd);
int ahd_pci_map_int(struct ahd_softc *ahd); int ahd_pci_map_int(struct ahd_softc *ahd);
......
...@@ -183,14 +183,21 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -183,14 +183,21 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_set_drvdata(pdev, ahd); pci_set_drvdata(pdev, ahd);
if (aic79xx_detect_complete) if (aic79xx_detect_complete) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahd_linux_register_host(ahd, &aic79xx_driver_template); ahd_linux_register_host(ahd, &aic79xx_driver_template);
#else
printf("aic79xx: ignoring PCI device found after "
"initialization\n");
return (-ENODEV);
#endif
}
#endif #endif
return (0); return (0);
} }
int int
ahd_linux_pci_probe(Scsi_Host_Template *template) ahd_linux_pci_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
return (pci_module_init(&aic79xx_pci_driver)); return (pci_module_init(&aic79xx_pci_driver));
...@@ -219,6 +226,12 @@ ahd_linux_pci_probe(Scsi_Host_Template *template) ...@@ -219,6 +226,12 @@ ahd_linux_pci_probe(Scsi_Host_Template *template)
#endif #endif
} }
void
ahd_linux_pci_exit(void)
{
pci_unregister_driver(&aic79xx_pci_driver);
}
static int static int
ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base, ahd_linux_pci_reserve_io_regions(struct ahd_softc *ahd, u_long *base,
u_long *base2) u_long *base2)
......
...@@ -875,7 +875,7 @@ ahc_linux_detect(Scsi_Host_Template *template) ...@@ -875,7 +875,7 @@ ahc_linux_detect(Scsi_Host_Template *template)
ahc_list_lockinit(); ahc_list_lockinit();
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
ahc_linux_pci_probe(template); ahc_linux_pci_init();
#endif #endif
if (aic7xxx_no_probe == 0) if (aic7xxx_no_probe == 0)
...@@ -1266,9 +1266,9 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd) ...@@ -1266,9 +1266,9 @@ ahc_linux_bus_reset(Scsi_Cmnd *cmd)
} }
Scsi_Host_Template aic7xxx_driver_template = { Scsi_Host_Template aic7xxx_driver_template = {
.module = THIS_MODULE,
.name = "aic7xxx",
.proc_info = ahc_linux_proc_info, .proc_info = ahc_linux_proc_info,
.detect = ahc_linux_detect,
.release = ahc_linux_release,
.info = ahc_linux_info, .info = ahc_linux_info,
.queuecommand = ahc_linux_queue, .queuecommand = ahc_linux_queue,
.eh_abort_handler = ahc_linux_abort, .eh_abort_handler = ahc_linux_abort,
...@@ -1300,19 +1300,17 @@ Scsi_Host_Template aic7xxx_driver_template = { ...@@ -1300,19 +1300,17 @@ Scsi_Host_Template aic7xxx_driver_template = {
#endif #endif
#endif #endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
.name = "aic7xxx",
.slave_alloc = ahc_linux_slave_alloc, .slave_alloc = ahc_linux_slave_alloc,
.slave_configure = ahc_linux_slave_configure, .slave_configure = ahc_linux_slave_configure,
.slave_destroy = ahc_linux_slave_destroy, .slave_destroy = ahc_linux_slave_destroy,
#else #else
.detect = ahc_linux_detect,
.release = ahc_linux_release,
.select_queue_depths = ahc_linux_select_queue_depth, .select_queue_depths = ahc_linux_select_queue_depth,
.use_new_eh_code = 1, .use_new_eh_code = 1,
#endif #endif
}; };
#define driver_template aic7xxx_driver_template
#include "scsi_module.c"
/**************************** Tasklet Handler *********************************/ /**************************** Tasklet Handler *********************************/
static void static void
...@@ -1861,9 +1859,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) ...@@ -1861,9 +1859,8 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
ahc_set_name(ahc, new_name); ahc_set_name(ahc, new_name);
} }
host->unique_id = ahc->unit; host->unique_id = ahc->unit;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \
scsi_set_device(host, &ahc->dev_softc->dev); LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
scsi_set_pci_device(host, ahc->dev_softc); scsi_set_pci_device(host, ahc->dev_softc);
#endif #endif
ahc_linux_initialize_scsi_bus(ahc); ahc_linux_initialize_scsi_bus(ahc);
...@@ -1897,6 +1894,10 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template) ...@@ -1897,6 +1894,10 @@ ahc_linux_register_host(struct ahc_softc *ahc, Scsi_Host_Template *template)
ahc_intr_enable(ahc, TRUE); ahc_intr_enable(ahc, TRUE);
ahc_linux_start_dv(ahc); ahc_linux_start_dv(ahc);
ahc_unlock(ahc, &s); ahc_unlock(ahc, &s);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
scsi_add_host(host, (ahc->dev_softc ? &ahc->dev_softc->dev : NULL));
#endif
return (0); return (0);
} }
...@@ -2075,8 +2076,12 @@ ahc_platform_free(struct ahc_softc *ahc) ...@@ -2075,8 +2076,12 @@ ahc_platform_free(struct ahc_softc *ahc)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_kill(&ahc->platform_data->runq_tasklet); tasklet_kill(&ahc->platform_data->runq_tasklet);
#endif #endif
if (ahc->platform_data->host != NULL) if (ahc->platform_data->host != NULL) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
scsi_remove_host(ahc->platform_data->host);
#endif
scsi_unregister(ahc->platform_data->host); scsi_unregister(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++) {
...@@ -2112,19 +2117,16 @@ ahc_platform_free(struct ahc_softc *ahc) ...@@ -2112,19 +2117,16 @@ ahc_platform_free(struct ahc_softc *ahc)
#endif #endif
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
/* XXX Need an instance detach in the PCI code */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* In 2.4 we detach from the scsi midlayer before the PCI
* layer invokes our remove callback.
*/
if (ahc->dev_softc != NULL) if (ahc->dev_softc != NULL)
ahc->dev_softc->driver = NULL; ahc->dev_softc->driver = NULL;
#endif
free(ahc->platform_data, M_DEVBUF);
}
if (TAILQ_EMPTY(&ahc_tailq)) {
unregister_reboot_notifier(&ahc_linux_notifier);
#ifdef CONFIG_PCI
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_unregister_driver(&aic7xxx_pci_driver);
#endif #endif
#endif #endif
free(ahc->platform_data, M_DEVBUF);
} }
} }
...@@ -5182,3 +5184,51 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc) ...@@ -5182,3 +5184,51 @@ ahc_platform_dump_card_state(struct ahc_softc *ahc)
} }
} }
} }
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);
#else
scsi_register_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
if (!driver_template.present) {
scsi_unregister_module(MODULE_SCSI_HA,
&aic7xxx_driver_template);
return (-ENODEV);
}
return (0);
#endif
}
static void __exit ahc_linux_exit(void)
{
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
struct ahc_softc *ahc;
ahc_linux_pci_exit();
/*
* Get rid of the non-pci devices.
*
* XXX(hch): switch over eisa support to new LDM-based API
*/
TAILQ_FOREACH(ahc, &ahc_tailq, links)
ahc_linux_release(ahc->platform_data->host);
#else
scsi_unregister_module(MODULE_SCSI_HA, &aic7xxx_driver_template);
/*
* In 2.4 we have to unregister from the PCI core _after_
* unregistering from the scsi midlayer to avoid danling references.
*
* The 2.4 scsi midlayer is so f***ed..
*/
ahc_linux_pci_exit();
#endif
unregister_reboot_notifier(&ahc_linux_notifier);
}
module_init(ahc_linux_init);
module_exit(ahc_linux_exit);
...@@ -912,7 +912,8 @@ int aic7770_map_int(struct ahc_softc *ahc, u_int irq); ...@@ -912,7 +912,8 @@ int aic7770_map_int(struct ahc_softc *ahc, u_int irq);
#include <linux/bios32.h> #include <linux/bios32.h>
#endif #endif
int ahc_linux_pci_probe(Scsi_Host_Template *); int ahc_linux_pci_init(void);
void ahc_linux_pci_exit(void);
int ahc_pci_map_registers(struct ahc_softc *ahc); int ahc_pci_map_registers(struct ahc_softc *ahc);
int ahc_pci_map_int(struct ahc_softc *ahc); int ahc_pci_map_int(struct ahc_softc *ahc);
......
...@@ -179,14 +179,21 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -179,14 +179,21 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
pci_set_drvdata(pdev, ahc); pci_set_drvdata(pdev, ahc);
if (aic7xxx_detect_complete) if (aic7xxx_detect_complete) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
ahc_linux_register_host(ahc, &aic7xxx_driver_template); ahc_linux_register_host(ahc, &aic7xxx_driver_template);
#else
printf("aic7xxx: ignoring PCI device found after "
"initialization\n");
return (-ENODEV);
#endif
}
#endif #endif
return (0); return (0);
} }
int int
ahc_linux_pci_probe(Scsi_Host_Template *template) ahc_linux_pci_init(void)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
return (pci_module_init(&aic7xxx_pci_driver)); return (pci_module_init(&aic7xxx_pci_driver));
...@@ -215,6 +222,12 @@ ahc_linux_pci_probe(Scsi_Host_Template *template) ...@@ -215,6 +222,12 @@ ahc_linux_pci_probe(Scsi_Host_Template *template)
#endif #endif
} }
void
ahc_linux_pci_exit(void)
{
pci_unregister_driver(&aic7xxx_pci_driver);
}
static int static int
ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base) ahc_linux_pci_reserve_io_region(struct ahc_softc *ahc, u_long *base)
{ {
......
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