Commit 83c9f08e authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Martin K. Petersen

scsi: remove the old scsi_module.c initialization model

After more than 15 years all users of this legacy interface are finally
gone.  Rest in peace!
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 616434e2
......@@ -154,12 +154,6 @@ lists).
.. kernel-doc:: drivers/scsi/scsi_lib_dma.c
:export:
drivers/scsi/scsi_module.c
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The file drivers/scsi/scsi_module.c contains legacy support for
old-style host templates. It should never be used by any new driver.
drivers/scsi/scsi_proc.c
~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -114,9 +114,7 @@ called "xxx" could be defined as
"static int xxx_slave_alloc(struct scsi_device * sdev) { /* code */ }"
** the scsi_host_alloc() function is a replacement for the rather vaguely
named scsi_register() function in most situations. The scsi_register()
and scsi_unregister() functions remain to support legacy LLDs that use
the passive initialization model.
named scsi_register() function in most situations.
Hotplug initialization model
......@@ -228,79 +226,6 @@ slave_configure() callbacks). Such instances are "owned" by the mid-level.
struct scsi_device instances are freed after slave_destroy().
Passive initialization model
============================
These older LLDs include a file called "scsi_module.c" [yes the ".c" is a
little surprising] in their source code. For that file to work an
instance of struct scsi_host_template with the name "driver_template"
needs to be defined. Here is a typical code sequence used in this model:
static struct scsi_host_template driver_template = {
...
};
#include "scsi_module.c"
The scsi_module.c file contains two functions:
- init_this_scsi_driver() which is executed when the LLD is
initialized (i.e. boot time or module load time)
- exit_this_scsi_driver() which is executed when the LLD is shut
down (i.e. module unload time)
Note: since these functions are tagged with __init and __exit qualifiers
an LLD should not call them explicitly (since the kernel does that).
Here is an example of an initialization sequence when two hosts are
detected (so detect() returns 2) and the SCSI bus scan on each host
finds 1 SCSI device (and a second device does not respond).
LLD mid level LLD
===----------------------=========-----------------===------
init_this_scsi_driver() ----+
|
detect() -----------------+
| |
| scsi_register()
| scsi_register()
|
slave_alloc()
slave_configure() --> scsi_change_queue_depth()
slave_alloc() ***
slave_destroy() ***
|
slave_alloc()
slave_configure()
slave_alloc() ***
slave_destroy() ***
------------------------------------------------------------
The mid level invokes scsi_change_queue_depth() with "cmd_per_lun" for that
host as the queue length. These settings can be overridden by a
slave_configure() supplied by the LLD.
*** For scsi devices that the mid level tries to scan but do not
respond, a slave_alloc(), slave_destroy() pair is called.
Here is an LLD shutdown sequence:
LLD mid level LLD
===----------------------=========-----------------===------
exit_this_scsi_driver() ----+
|
slave_destroy()
release() --> scsi_unregister()
|
slave_destroy()
release() --> scsi_unregister()
------------------------------------------------------------
An LLD need not define slave_destroy() (i.e. it is optional).
The shortcoming of the "passive initialization model" is that host
registration and de-registration are (typically) tied to LLD initialization
and shutdown. Once the LLD is initialized then a new host that appears
(e.g. via hotplugging) cannot easily be added without a redundant
driver shutdown and re-initialization. It may be possible to write an LLD
that uses both initialization models.
Reference Counting
==================
The Scsi_Host structure has had reference counting infrastructure added.
......@@ -738,7 +663,6 @@ The interface functions are listed below in alphabetical order.
Summary:
bios_param - fetch head, sector, cylinder info for a disk
detect - detects HBAs this driver wants to control
eh_timed_out - notify the host that a command timer expired
eh_abort_handler - abort given command
eh_bus_reset_handler - issue SCSI bus reset
......@@ -748,7 +672,6 @@ Summary:
ioctl - driver can respond to ioctls
proc_info - supports /proc/scsi/{driver_name}/{host_no}
queuecommand - queue scsi command, invoke 'done' on completion
release - release all resources associated with given host
slave_alloc - prior to any commands being sent to a new device
slave_configure - driver fine tuning for given device after attach
slave_destroy - given device is about to be shut down
......@@ -784,28 +707,6 @@ Details:
sector_t capacity, int params[3])
/**
* detect - detects HBAs this driver wants to control
* @shtp: host template for this driver.
*
* Returns number of hosts this driver wants to control. 0 means no
* suitable hosts found.
*
* Locks: none held
*
* Calling context: process [invoked from init_this_scsi_driver()]
*
* Notes: First function called from the SCSI mid level on this
* driver. Upper level drivers (e.g. sd) may not (yet) be present.
* For each host found, this method should call scsi_register()
* [see hosts.c].
*
* Defined in: LLD (required if "passive initialization mode" is used,
* not invoked in "hotplug initialization mode")
**/
int detect(struct scsi_host_template * shtp)
/**
* eh_timed_out - The timer for the command has just fired
* @scp: identifies command timing out
......@@ -1073,27 +974,6 @@ Details:
int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
/**
* release - release all resources associated with given host
* @shp: host to be released.
*
* Return value ignored (could soon be a function returning void).
*
* Locks: none held
*
* Calling context: process
*
* Notes: Invoked from scsi_module.c's exit_this_scsi_driver().
* LLD's implementation of this function should call
* scsi_unregister(shp) prior to returning.
* Only needed for old-style host templates.
*
* Defined in: LLD (required in "passive initialization model",
* should not be defined in hotplug model)
**/
int release(struct Scsi_Host * shp)
/**
* slave_alloc - prior to any commands being sent to a new device
* (i.e. just prior to scan) this call is made
......
......@@ -518,29 +518,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
}
EXPORT_SYMBOL(scsi_host_alloc);
struct Scsi_Host *scsi_register(struct scsi_host_template *sht, int privsize)
{
struct Scsi_Host *shost = scsi_host_alloc(sht, privsize);
if (!sht->detect) {
printk(KERN_WARNING "scsi_register() called on new-style "
"template for driver %s\n", sht->name);
dump_stack();
}
if (shost)
list_add_tail(&shost->sht_legacy_list, &sht->legacy_hosts);
return shost;
}
EXPORT_SYMBOL(scsi_register);
void scsi_unregister(struct Scsi_Host *shost)
{
list_del(&shost->sht_legacy_list);
scsi_host_put(shost);
}
EXPORT_SYMBOL(scsi_unregister);
static int __scsi_host_match(struct device *dev, const void *data)
{
struct Scsi_Host *p;
......
/*
* Copyright (C) 2003 Christoph Hellwig.
* Released under GPL v2.
*
* Support for old-style host templates.
*
* NOTE: Do not use this for new drivers ever.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <scsi/scsi_host.h>
static int __init init_this_scsi_driver(void)
{
struct scsi_host_template *sht = &driver_template;
struct Scsi_Host *shost;
struct list_head *l;
int error;
if (!sht->release) {
printk(KERN_ERR
"scsi HBA driver %s didn't set a release method.\n",
sht->name);
return -EINVAL;
}
sht->module = THIS_MODULE;
INIT_LIST_HEAD(&sht->legacy_hosts);
sht->detect(sht);
if (list_empty(&sht->legacy_hosts))
return -ENODEV;
list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list) {
error = scsi_add_host(shost, NULL);
if (error)
goto fail;
scsi_scan_host(shost);
}
return 0;
fail:
l = &shost->sht_legacy_list;
while ((l = l->prev) != &sht->legacy_hosts)
scsi_remove_host(list_entry(l, struct Scsi_Host, sht_legacy_list));
return error;
}
static void __exit exit_this_scsi_driver(void)
{
struct scsi_host_template *sht = &driver_template;
struct Scsi_Host *shost, *s;
list_for_each_entry(shost, &sht->legacy_hosts, sht_legacy_list)
scsi_remove_host(shost);
list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list)
sht->release(shost);
if (list_empty(&sht->legacy_hosts))
return;
printk(KERN_WARNING "%s did not call scsi_unregister\n", sht->name);
dump_stack();
list_for_each_entry_safe(shost, s, &sht->legacy_hosts, sht_legacy_list)
scsi_unregister(shost);
}
module_init(init_this_scsi_driver);
module_exit(exit_this_scsi_driver);
......@@ -51,21 +51,6 @@ struct scsi_host_template {
struct module *module;
const char *name;
/*
* Used to initialize old-style drivers. For new-style drivers
* just perform all work in your module initialization function.
*
* Status: OBSOLETE
*/
int (* detect)(struct scsi_host_template *);
/*
* Used as unload callback for hosts with old-style drivers.
*
* Status: OBSOLETE
*/
int (* release)(struct Scsi_Host *);
/*
* The info function will return whatever useful information the
* developer sees fit. If not provided, then the name field will
......@@ -482,15 +467,6 @@ struct scsi_host_template {
*/
const struct attribute_group **sdev_groups;
/*
* List of hosts per template.
*
* This is only for use by scsi_module.c for legacy templates.
* For these access to it is synchronized implicitly by
* module_init/module_exit.
*/
struct list_head legacy_hosts;
/*
* Vendor Identifier associated with the host
*
......@@ -713,15 +689,6 @@ struct Scsi_Host {
/* ldm bits */
struct device shost_gendev, shost_dev;
/*
* List of hosts per template.
*
* This is only for use by scsi_module.c for legacy templates.
* For these access to it is synchronized implicitly by
* module_init/module_exit.
*/
struct list_head sht_legacy_list;
/*
* Points to the transport data (if any) which is allocated
* separately
......@@ -922,9 +889,6 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
return shost->prot_guard_type;
}
/* legacy interfaces */
extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
extern void scsi_unregister(struct Scsi_Host *);
extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
#endif /* _SCSI_SCSI_HOST_H */
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