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: Christoph Hellwig <hch@lst.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>hifive-unleashed-5.1
parent
616434e2aa
commit
83c9f08e6c
|
@ -154,12 +154,6 @@ lists).
|
||||||
.. kernel-doc:: drivers/scsi/scsi_lib_dma.c
|
.. kernel-doc:: drivers/scsi/scsi_lib_dma.c
|
||||||
:export:
|
: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
|
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 */ }"
|
"static int xxx_slave_alloc(struct scsi_device * sdev) { /* code */ }"
|
||||||
|
|
||||||
** the scsi_host_alloc() function is a replacement for the rather vaguely
|
** the scsi_host_alloc() function is a replacement for the rather vaguely
|
||||||
named scsi_register() function in most situations. The scsi_register()
|
named scsi_register() function in most situations.
|
||||||
and scsi_unregister() functions remain to support legacy LLDs that use
|
|
||||||
the passive initialization model.
|
|
||||||
|
|
||||||
|
|
||||||
Hotplug initialization model
|
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().
|
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
|
Reference Counting
|
||||||
==================
|
==================
|
||||||
The Scsi_Host structure has had reference counting infrastructure added.
|
The Scsi_Host structure has had reference counting infrastructure added.
|
||||||
|
@ -738,7 +663,6 @@ The interface functions are listed below in alphabetical order.
|
||||||
|
|
||||||
Summary:
|
Summary:
|
||||||
bios_param - fetch head, sector, cylinder info for a disk
|
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_timed_out - notify the host that a command timer expired
|
||||||
eh_abort_handler - abort given command
|
eh_abort_handler - abort given command
|
||||||
eh_bus_reset_handler - issue SCSI bus reset
|
eh_bus_reset_handler - issue SCSI bus reset
|
||||||
|
@ -748,7 +672,6 @@ Summary:
|
||||||
ioctl - driver can respond to ioctls
|
ioctl - driver can respond to ioctls
|
||||||
proc_info - supports /proc/scsi/{driver_name}/{host_no}
|
proc_info - supports /proc/scsi/{driver_name}/{host_no}
|
||||||
queuecommand - queue scsi command, invoke 'done' on completion
|
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_alloc - prior to any commands being sent to a new device
|
||||||
slave_configure - driver fine tuning for given device after attach
|
slave_configure - driver fine tuning for given device after attach
|
||||||
slave_destroy - given device is about to be shut down
|
slave_destroy - given device is about to be shut down
|
||||||
|
@ -784,28 +707,6 @@ Details:
|
||||||
sector_t capacity, int params[3])
|
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
|
* eh_timed_out - The timer for the command has just fired
|
||||||
* @scp: identifies command timing out
|
* @scp: identifies command timing out
|
||||||
|
@ -1073,27 +974,6 @@ Details:
|
||||||
int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
|
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
|
* slave_alloc - prior to any commands being sent to a new device
|
||||||
* (i.e. just prior to scan) this call is made
|
* (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);
|
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)
|
static int __scsi_host_match(struct device *dev, const void *data)
|
||||||
{
|
{
|
||||||
struct Scsi_Host *p;
|
struct Scsi_Host *p;
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
/*
|
|
||||||
* 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;
|
struct module *module;
|
||||||
const char *name;
|
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
|
* The info function will return whatever useful information the
|
||||||
* developer sees fit. If not provided, then the name field will
|
* 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;
|
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
|
* Vendor Identifier associated with the host
|
||||||
*
|
*
|
||||||
|
@ -713,15 +689,6 @@ struct Scsi_Host {
|
||||||
/* ldm bits */
|
/* ldm bits */
|
||||||
struct device shost_gendev, shost_dev;
|
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
|
* Points to the transport data (if any) which is allocated
|
||||||
* separately
|
* separately
|
||||||
|
@ -922,9 +889,6 @@ static inline unsigned char scsi_host_get_guard(struct Scsi_Host *shost)
|
||||||
return shost->prot_guard_type;
|
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);
|
extern int scsi_host_set_state(struct Scsi_Host *, enum scsi_host_state);
|
||||||
|
|
||||||
#endif /* _SCSI_SCSI_HOST_H */
|
#endif /* _SCSI_SCSI_HOST_H */
|
||||||
|
|
Loading…
Reference in New Issue