[PATCH] scsi_add_host/scsi_Remove_host for aic7xxx/aic79xx

Christoph Hellwig
2003-02-26T19:05:42Z

I remember having this submitted a while ago, but here's the code
again, this time with the untested aic79xx bits.

--- 1.22/drivers/scsi/aic7xxx/aic79xx_osm.c Tue Feb 18 19:12:35 2003
+++ edited/drivers/scsi/aic7xxx/aic79xx_osm.c Wed Feb 26 19:53:22 2003
@@ -801,7 +801,6 @@

/************************ Host template entry points *************************/
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 int ahd_linux_queue(Scsi_Cmnd *, void (*)(Scsi_Cmnd *));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
@@ -811,6 +810,7 @@
static int ahd_linux_biosparam(struct scsi_device*,
struct block_device*, sector_t, int[]);
#else
+static int ahd_linux_release(struct Scsi_Host *);
static void ahd_linux_select_queue_depth(struct Scsi_Host *host,
Scsi_Device *scsi_devs);
static int ahd_linux_biosparam(Disk *, kdev_t, int[]);
@@ -874,7 +874,7 @@
ahd_list_lockinit();

#ifdef CONFIG_PCI
- ahd_linux_pci_probe(template);
+ ahd_linux_pci_init();
#endif

/*
@@ -894,6 +894,7 @@
return (found);
}

+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* Free the passed in Scsi_Host memory structures prior to unloading the
* module.
@@ -925,6 +926,7 @@
ahd_list_unlock(&l);
return (0);
}
+#endif

/*
* Return a string describing the driver.
@@ -1664,9 +1666,9 @@
}

Scsi_Host_Template aic79xx_driver_template = {
+ .module = THIS_MODULE,
+ .name = "aic79xx",
.proc_info = ahd_linux_proc_info,
- .detect = ahd_linux_detect,
- .release = ahd_linux_release,
.info = ahd_linux_info,
.queuecommand = ahd_linux_queue,
.eh_abort_handler = ahd_linux_abort,
@@ -1698,18 +1700,17 @@
#endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- .name = "aic79xx",
.slave_alloc = ahd_linux_slave_alloc,
.slave_configure = ahd_linux_slave_configure,
.slave_destroy = ahd_linux_slave_destroy,
#else
+ .detect = ahd_linux_detect,
+ .release = ahd_linux_release,
.select_queue_depths = ahd_linux_select_queue_depth,
.use_new_eh_code = 1,
#endif
};

-#define driver_template aic79xx_driver_template
-#include "scsi_module.c"
/**************************** Tasklet Handler *********************************/

static void
@@ -2381,9 +2382,8 @@
ahd_set_name(ahd, new_name);
}
host->unique_id = ahd->unit;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- scsi_set_device(host, &ahd->dev_softc->dev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \
+ LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
scsi_set_pci_device(host, ahd->dev_softc);
#endif
ahd_linux_initialize_scsi_bus(ahd);
@@ -2410,6 +2410,10 @@
ahd_intr_enable(ahd, TRUE);
ahd_linux_start_dv(ahd);
ahd_unlock(ahd, &s);
+
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+ scsi_add_host(host, &ahd->dev_softc->dev);
+#endif
return (0);
}

@@ -2556,8 +2560,12 @@
__WCLONE) == -ERESTARTSYS);
}
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);
+ }

/* destroy all of the device and target objects */
for (i = 0; i < AHD_NUM_TARGETS; i++) {
@@ -2595,21 +2603,17 @@
0x1000);
#endif
}
-#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,4,0) && \
+ 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)
ahd->dev_softc->driver = NULL;
#endif
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
@@ -5315,3 +5319,30 @@
}
}
}
+
+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);
--- 1.16/drivers/scsi/aic7xxx/aic79xx_osm.h Fri Feb 7 09:20:36 2003
+++ edited/drivers/scsi/aic7xxx/aic79xx_osm.h Wed Feb 26 19:46:01 2003
@@ -952,7 +952,8 @@
#include <linux/bios32.h>
#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_int(struct ahd_softc *ahd);

--- 1.5/drivers/scsi/aic7xxx/aic79xx_osm_pci.c Wed Jan 8 03:58:34 2003
+++ edited/drivers/scsi/aic7xxx/aic79xx_osm_pci.c Wed Feb 26 19:48:22 2003
@@ -183,14 +183,21 @@
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
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);
+#else
+ printf("aic79xx: ignoring PCI device found after "
+ "initialization\n");
+ return (-ENODEV);
+#endif
+ }
#endif
return (0);
}

int
-ahd_linux_pci_probe(Scsi_Host_Template *template)
+ahd_linux_pci_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
return (pci_module_init(&aic79xx_pci_driver));
@@ -217,6 +224,12 @@
}
return (found);
#endif
+}
+
+void
+ahd_linux_pci_exit(void)
+{
+ pci_unregister_driver(&aic79xx_pci_driver);
}

static int
--- 1.20/drivers/scsi/aic7xxx/aic7xxx_osm.c Tue Feb 25 18:45:05 2003
+++ edited/drivers/scsi/aic7xxx/aic7xxx_osm.c Wed Feb 26 19:50:29 2003
@@ -875,7 +875,7 @@
ahc_list_lockinit();

#ifdef CONFIG_PCI
- ahc_linux_pci_probe(template);
+ ahc_linux_pci_init();
#endif

if (aic7xxx_no_probe == 0)
@@ -1266,9 +1266,9 @@
}

Scsi_Host_Template aic7xxx_driver_template = {
+ .module = THIS_MODULE,
+ .name = "aic7xxx",
.proc_info = ahc_linux_proc_info,
- .detect = ahc_linux_detect,
- .release = ahc_linux_release,
.info = ahc_linux_info,
.queuecommand = ahc_linux_queue,
.eh_abort_handler = ahc_linux_abort,
@@ -1300,19 +1300,17 @@
#endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- .name = "aic7xxx",
.slave_alloc = ahc_linux_slave_alloc,
.slave_configure = ahc_linux_slave_configure,
.slave_destroy = ahc_linux_slave_destroy,
#else
+ .detect = ahc_linux_detect,
+ .release = ahc_linux_release,
.select_queue_depths = ahc_linux_select_queue_depth,
.use_new_eh_code = 1,
#endif
};

-#define driver_template aic7xxx_driver_template
-#include "scsi_module.c"
-
/**************************** Tasklet Handler *********************************/

static void
@@ -1861,9 +1859,8 @@
ahc_set_name(ahc, new_name);
}
host->unique_id = ahc->unit;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- scsi_set_device(host, &ahc->dev_softc->dev);
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,4) && \
+ LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
scsi_set_pci_device(host, ahc->dev_softc);
#endif
ahc_linux_initialize_scsi_bus(ahc);
@@ -1897,6 +1894,10 @@
ahc_intr_enable(ahc, TRUE);
ahc_linux_start_dv(ahc);
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);
}

@@ -2075,8 +2076,12 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
tasklet_kill(&ahc->platform_data->runq_tasklet);
#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);
+ }

/* destroy all of the device and target objects */
for (i = 0; i < AHC_NUM_TARGETS; i++) {
@@ -2112,19 +2117,16 @@
#endif
}
#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)
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
+ free(ahc->platform_data, M_DEVBUF);
}
}

@@ -5182,3 +5184,51 @@
}
}
}
+
+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);
--- 1.28/drivers/scsi/aic7xxx/aic7xxx_osm.h Fri Feb 7 09:20:36 2003
+++ edited/drivers/scsi/aic7xxx/aic7xxx_osm.h Wed Feb 26 17:14:16 2003
@@ -912,7 +912,8 @@
#include <linux/bios32.h>
#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_int(struct ahc_softc *ahc);

--- 1.6/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c Wed Jan 8 03:58:35 2003
+++ edited/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c Wed Feb 26 17:14:16 2003
@@ -179,14 +179,21 @@
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
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);
+#else
+ printf("aic7xxx: ignoring PCI device found after "
+ "initialization\n");
+ return (-ENODEV);
+#endif
+ }
#endif
return (0);
}

int
-ahc_linux_pci_probe(Scsi_Host_Template *template)
+ahc_linux_pci_init(void)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
return (pci_module_init(&aic7xxx_pci_driver));
@@ -213,6 +220,12 @@
}
return (found);
#endif
+}
+
+void
+ahc_linux_pci_exit(void)
+{
+ pci_unregister_driver(&aic7xxx_pci_driver);
}

static int