scsi_dh: kill struct scsi_dh_data

Add a ->handler and a ->handler_data field to struct scsi_device and kill
this indirection.  Also move struct scsi_device_handler to scsi_dh.h so that
changes to it don't require rebuilding every SCSI LLDD.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: James Bottomley <JBottomley@Odin.com>
This commit is contained in:
Christoph Hellwig 2015-08-27 14:16:59 +02:00 committed by James Bottomley
parent d95dbff2a4
commit ee14c674e8
9 changed files with 98 additions and 140 deletions

View File

@ -62,7 +62,6 @@
#define ALUA_OPTIMIZE_STPG 1
struct alua_dh_data {
struct scsi_dh_data dh_data;
int group_id;
int rel_port;
int tpgs;
@ -86,11 +85,6 @@ struct alua_dh_data {
static char print_alua_state(int);
static int alua_check_sense(struct scsi_device *, struct scsi_sense_hdr *);
static inline struct alua_dh_data *get_alua_data(struct scsi_device *sdev)
{
return container_of(sdev->scsi_dh_data, struct alua_dh_data, dh_data);
}
static int realloc_buffer(struct alua_dh_data *h, unsigned len)
{
if (h->buff && h->buff != h->inq)
@ -708,7 +702,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
*/
static int alua_set_params(struct scsi_device *sdev, const char *params)
{
struct alua_dh_data *h = get_alua_data(sdev);
struct alua_dh_data *h = sdev->handler_data;
unsigned int optimize = 0, argc;
const char *p = params;
int result = SCSI_DH_OK;
@ -746,7 +740,7 @@ MODULE_PARM_DESC(optimize_stpg, "Allow use of a non-optimized path, rather than
static int alua_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{
struct alua_dh_data *h = get_alua_data(sdev);
struct alua_dh_data *h = sdev->handler_data;
int err = SCSI_DH_OK;
int stpg = 0;
@ -804,7 +798,7 @@ static int alua_activate(struct scsi_device *sdev,
*/
static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct alua_dh_data *h = get_alua_data(sdev);
struct alua_dh_data *h = sdev->handler_data;
int ret = BLKPREP_OK;
if (h->state == TPGS_STATE_TRANSITIONING)
@ -823,14 +817,14 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
* alua_bus_attach - Attach device handler
* @sdev: device to be attached to
*/
static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev)
static int alua_bus_attach(struct scsi_device *sdev)
{
struct alua_dh_data *h;
int err;
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
h->tpgs = TPGS_MODE_UNINITIALIZED;
h->state = TPGS_STATE_OPTIMIZED;
h->group_id = -1;
@ -843,11 +837,11 @@ static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev)
if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED)
goto failed;
sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME);
return &h->dh_data;
sdev->handler_data = h;
return 0;
failed:
kfree(h);
return ERR_PTR(-EINVAL);
return -EINVAL;
}
/*
@ -856,10 +850,11 @@ static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev)
*/
static void alua_bus_detach(struct scsi_device *sdev)
{
struct alua_dh_data *h = get_alua_data(sdev);
struct alua_dh_data *h = sdev->handler_data;
if (h->buff && h->inq != h->buff)
kfree(h->buff);
sdev->handler_data = NULL;
kfree(h);
}

View File

@ -72,7 +72,6 @@ static const char * lun_state[] =
};
struct clariion_dh_data {
struct scsi_dh_data dh_data;
/*
* Flags:
* CLARIION_SHORT_TRESPASS
@ -114,13 +113,6 @@ struct clariion_dh_data {
int current_sp;
};
static inline struct clariion_dh_data
*get_clariion_data(struct scsi_device *sdev)
{
return container_of(sdev->scsi_dh_data, struct clariion_dh_data,
dh_data);
}
/*
* Parse MODE_SELECT cmd reply.
*/
@ -450,7 +442,7 @@ static int clariion_check_sense(struct scsi_device *sdev,
static int clariion_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct clariion_dh_data *h = get_clariion_data(sdev);
struct clariion_dh_data *h = sdev->handler_data;
int ret = BLKPREP_OK;
if (h->lun_state != CLARIION_LUN_OWNED) {
@ -533,7 +525,7 @@ static int clariion_send_inquiry(struct scsi_device *sdev,
static int clariion_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{
struct clariion_dh_data *csdev = get_clariion_data(sdev);
struct clariion_dh_data *csdev = sdev->handler_data;
int result;
result = clariion_send_inquiry(sdev, csdev);
@ -574,7 +566,7 @@ static int clariion_activate(struct scsi_device *sdev,
*/
static int clariion_set_params(struct scsi_device *sdev, const char *params)
{
struct clariion_dh_data *csdev = get_clariion_data(sdev);
struct clariion_dh_data *csdev = sdev->handler_data;
unsigned int hr = 0, st = 0, argc;
const char *p = params;
int result = SCSI_DH_OK;
@ -622,14 +614,14 @@ static int clariion_set_params(struct scsi_device *sdev, const char *params)
return result;
}
static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev)
static int clariion_bus_attach(struct scsi_device *sdev)
{
struct clariion_dh_data *h;
int err;
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
h->lun_state = CLARIION_LUN_UNINITIALIZED;
h->default_sp = CLARIION_UNBOUND_LU;
h->current_sp = CLARIION_UNBOUND_LU;
@ -647,18 +639,19 @@ static struct scsi_dh_data *clariion_bus_attach(struct scsi_device *sdev)
CLARIION_NAME, h->current_sp + 'A',
h->port, lun_state[h->lun_state],
h->default_sp + 'A');
return &h->dh_data;
sdev->handler_data = h;
return 0;
failed:
kfree(h);
return ERR_PTR(-EINVAL);
return -EINVAL;
}
static void clariion_bus_detach(struct scsi_device *sdev)
{
struct clariion_dh_data *h = get_clariion_data(sdev);
kfree(h);
kfree(sdev->handler_data);
sdev->handler_data = NULL;
}
static struct scsi_device_handler clariion_dh = {

View File

@ -38,7 +38,6 @@
#define HP_SW_PATH_PASSIVE 1
struct hp_sw_dh_data {
struct scsi_dh_data dh_data;
unsigned char sense[SCSI_SENSE_BUFFERSIZE];
int path_state;
int retries;
@ -50,11 +49,6 @@ struct hp_sw_dh_data {
static int hp_sw_start_stop(struct hp_sw_dh_data *);
static inline struct hp_sw_dh_data *get_hp_sw_data(struct scsi_device *sdev)
{
return container_of(sdev->scsi_dh_data, struct hp_sw_dh_data, dh_data);
}
/*
* tur_done - Handle TEST UNIT READY return status
* @sdev: sdev the command has been sent to
@ -267,7 +261,7 @@ static int hp_sw_start_stop(struct hp_sw_dh_data *h)
static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
struct hp_sw_dh_data *h = sdev->handler_data;
int ret = BLKPREP_OK;
if (h->path_state != HP_SW_PATH_ACTIVE) {
@ -292,7 +286,7 @@ static int hp_sw_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{
int ret = SCSI_DH_OK;
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
struct hp_sw_dh_data *h = sdev->handler_data;
ret = hp_sw_tur(sdev, h);
@ -311,14 +305,14 @@ static int hp_sw_activate(struct scsi_device *sdev,
return 0;
}
static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev)
static int hp_sw_bus_attach(struct scsi_device *sdev)
{
struct hp_sw_dh_data *h;
int ret;
h = kzalloc(sizeof(*h), GFP_KERNEL);
if (!h)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
h->path_state = HP_SW_PATH_UNINITIALIZED;
h->retries = HP_SW_RETRIES;
h->sdev = sdev;
@ -330,17 +324,18 @@ static struct scsi_dh_data *hp_sw_bus_attach(struct scsi_device *sdev)
sdev_printk(KERN_INFO, sdev, "%s: attached to %s path\n",
HP_SW_NAME, h->path_state == HP_SW_PATH_ACTIVE?
"active":"passive");
return &h->dh_data;
sdev->handler_data = h;
return 0;
failed:
kfree(h);
return ERR_PTR(-EINVAL);
return -EINVAL;
}
static void hp_sw_bus_detach( struct scsi_device *sdev )
{
struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
kfree(h);
kfree(sdev->handler_data);
sdev->handler_data = NULL;
}
static struct scsi_device_handler hp_sw_dh = {

View File

@ -181,7 +181,6 @@ struct c2_inquiry {
};
struct rdac_dh_data {
struct scsi_dh_data dh_data;
struct rdac_controller *ctlr;
#define UNINITIALIZED_LUN (1 << 8)
unsigned lun;
@ -260,11 +259,6 @@ do { \
sdev_printk(KERN_INFO, sdev, RDAC_NAME ": " f "\n", ## arg); \
} while (0);
static inline struct rdac_dh_data *get_rdac_data(struct scsi_device *sdev)
{
return container_of(sdev->scsi_dh_data, struct rdac_dh_data, dh_data);
}
static struct request *get_rdac_req(struct scsi_device *sdev,
void *buffer, unsigned buflen, int rw)
{
@ -544,7 +538,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
{
struct scsi_sense_hdr sense_hdr;
int err = SCSI_DH_IO, ret;
struct rdac_dh_data *h = get_rdac_data(sdev);
struct rdac_dh_data *h = sdev->handler_data;
ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
if (!ret)
@ -589,7 +583,7 @@ static void send_mode_select(struct work_struct *work)
container_of(work, struct rdac_controller, ms_work);
struct request *rq;
struct scsi_device *sdev = ctlr->ms_sdev;
struct rdac_dh_data *h = get_rdac_data(sdev);
struct rdac_dh_data *h = sdev->handler_data;
struct request_queue *q = sdev->request_queue;
int err, retry_cnt = RDAC_RETRY_COUNT;
struct rdac_queue_data *tmp, *qdata;
@ -648,7 +642,7 @@ static int queue_mode_select(struct scsi_device *sdev,
if (!qdata)
return SCSI_DH_RETRY;
qdata->h = get_rdac_data(sdev);
qdata->h = sdev->handler_data;
qdata->callback_fn = fn;
qdata->callback_data = data;
@ -667,7 +661,7 @@ static int queue_mode_select(struct scsi_device *sdev,
static int rdac_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{
struct rdac_dh_data *h = get_rdac_data(sdev);
struct rdac_dh_data *h = sdev->handler_data;
int err = SCSI_DH_OK;
int act = 0;
@ -702,7 +696,7 @@ static int rdac_activate(struct scsi_device *sdev,
static int rdac_prep_fn(struct scsi_device *sdev, struct request *req)
{
struct rdac_dh_data *h = get_rdac_data(sdev);
struct rdac_dh_data *h = sdev->handler_data;
int ret = BLKPREP_OK;
if (h->state != RDAC_STATE_ACTIVE) {
@ -716,7 +710,7 @@ static int rdac_prep_fn(struct scsi_device *sdev, struct request *req)
static int rdac_check_sense(struct scsi_device *sdev,
struct scsi_sense_hdr *sense_hdr)
{
struct rdac_dh_data *h = get_rdac_data(sdev);
struct rdac_dh_data *h = sdev->handler_data;
RDAC_LOG(RDAC_LOG_SENSE, sdev, "array %s, ctlr %d, "
"I/O returned with sense %02x/%02x/%02x",
@ -778,7 +772,7 @@ static int rdac_check_sense(struct scsi_device *sdev,
return SCSI_RETURN_NOT_HANDLED;
}
static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev)
static int rdac_bus_attach(struct scsi_device *sdev)
{
struct rdac_dh_data *h;
int err;
@ -787,7 +781,7 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev)
h = kzalloc(sizeof(*h) , GFP_KERNEL);
if (!h)
return ERR_PTR(-ENOMEM);
return -ENOMEM;
h->lun = UNINITIALIZED_LUN;
h->state = RDAC_STATE_ACTIVE;
@ -812,7 +806,8 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev)
RDAC_NAME, h->lun, mode[(int)h->mode],
lun_state[(int)h->lun_state]);
return &h->dh_data;
sdev->handler_data = h;
return 0;
clean_ctlr:
spin_lock(&list_lock);
@ -821,12 +816,12 @@ static struct scsi_dh_data *rdac_bus_attach(struct scsi_device *sdev)
failed:
kfree(h);
return ERR_PTR(-EINVAL);
return -EINVAL;
}
static void rdac_bus_detach( struct scsi_device *sdev )
{
struct rdac_dh_data *h = get_rdac_data(sdev);
struct rdac_dh_data *h = sdev->handler_data;
if (h->ctlr && h->ctlr->ms_queued)
flush_workqueue(kmpath_rdacd);
@ -835,6 +830,7 @@ static void rdac_bus_detach( struct scsi_device *sdev )
if (h->ctlr)
kref_put(&h->ctlr->kref, release_controller);
spin_unlock(&list_lock);
sdev->handler_data = NULL;
kfree(h);
}

View File

@ -126,26 +126,20 @@ static struct scsi_device_handler *scsi_dh_lookup(const char *name)
static int scsi_dh_handler_attach(struct scsi_device *sdev,
struct scsi_device_handler *scsi_dh)
{
struct scsi_dh_data *d;
int error;
if (!try_module_get(scsi_dh->module))
return -EINVAL;
d = scsi_dh->attach(sdev);
if (IS_ERR(d)) {
sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%ld)\n",
scsi_dh->name, PTR_ERR(d));
error = scsi_dh->attach(sdev);
if (error) {
sdev_printk(KERN_ERR, sdev, "%s: Attach failed (%d)\n",
scsi_dh->name, error);
module_put(scsi_dh->module);
return PTR_ERR(d);
}
} else
sdev->handler = scsi_dh;
d->scsi_dh = scsi_dh;
d->sdev = sdev;
spin_lock_irq(sdev->request_queue->queue_lock);
sdev->scsi_dh_data = d;
spin_unlock_irq(sdev->request_queue->queue_lock);
return 0;
return error;
}
/*
@ -154,17 +148,9 @@ static int scsi_dh_handler_attach(struct scsi_device *sdev,
*/
static void scsi_dh_handler_detach(struct scsi_device *sdev)
{
struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data;
struct scsi_device_handler *scsi_dh = scsi_dh_data->scsi_dh;
scsi_dh->detach(sdev);
spin_lock_irq(sdev->request_queue->queue_lock);
sdev->scsi_dh_data = NULL;
spin_unlock_irq(sdev->request_queue->queue_lock);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", scsi_dh->name);
module_put(scsi_dh->module);
sdev->handler->detach(sdev);
sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", sdev->handler->name);
module_put(sdev->handler->module);
}
/*
@ -182,7 +168,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
sdev->sdev_state == SDEV_DEL)
return -ENODEV;
if (!sdev->scsi_dh_data) {
if (!sdev->handler) {
/*
* Attach to a device handler
*/
@ -191,7 +177,6 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
return err;
err = scsi_dh_handler_attach(sdev, scsi_dh);
} else {
scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (!strncmp(buf, "detach", 6)) {
/*
* Detach from a device handler
@ -202,8 +187,8 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
/*
* Activate a device handler
*/
if (scsi_dh->activate)
err = scsi_dh->activate(sdev, NULL, NULL);
if (sdev->handler->activate)
err = sdev->handler->activate(sdev, NULL, NULL);
else
err = 0;
}
@ -217,10 +202,10 @@ show_dh_state(struct device *dev, struct device_attribute *attr, char *buf)
{
struct scsi_device *sdev = to_scsi_device(dev);
if (!sdev->scsi_dh_data)
if (!sdev->handler)
return snprintf(buf, 20, "detached\n");
return snprintf(buf, 20, "%s\n", sdev->scsi_dh_data->scsi_dh->name);
return snprintf(buf, 20, "%s\n", sdev->handler->name);
}
static struct device_attribute scsi_dh_state_attr =
@ -247,7 +232,7 @@ int scsi_dh_add_device(struct scsi_device *sdev)
void scsi_dh_remove_device(struct scsi_device *sdev)
{
if (sdev->scsi_dh_data)
if (sdev->handler)
scsi_dh_handler_detach(sdev);
device_remove_file(&sdev->sdev_gendev, &scsi_dh_state_attr);
}
@ -316,7 +301,6 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
int err = 0;
unsigned long flags;
struct scsi_device *sdev;
struct scsi_device_handler *scsi_dh = NULL;
struct device *dev = NULL;
spin_lock_irqsave(q->queue_lock, flags);
@ -329,10 +313,8 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
return err;
}
if (sdev->scsi_dh_data)
scsi_dh = sdev->scsi_dh_data->scsi_dh;
dev = get_device(&sdev->sdev_gendev);
if (!scsi_dh || !dev ||
if (!sdev->handler || !dev ||
sdev->sdev_state == SDEV_CANCEL ||
sdev->sdev_state == SDEV_DEL)
err = SCSI_DH_NOSYS;
@ -346,8 +328,8 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
goto out;
}
if (scsi_dh->activate)
err = scsi_dh->activate(sdev, fn, data);
if (sdev->handler->activate)
err = sdev->handler->activate(sdev, fn, data);
out:
put_device(dev);
return err;
@ -369,19 +351,18 @@ int scsi_dh_set_params(struct request_queue *q, const char *params)
int err = -SCSI_DH_NOSYS;
unsigned long flags;
struct scsi_device *sdev;
struct scsi_device_handler *scsi_dh = NULL;
spin_lock_irqsave(q->queue_lock, flags);
sdev = q->queuedata;
if (sdev && sdev->scsi_dh_data)
scsi_dh = sdev->scsi_dh_data->scsi_dh;
if (scsi_dh && scsi_dh->set_params && get_device(&sdev->sdev_gendev))
if (sdev->handler &&
sdev->handler->set_params &&
get_device(&sdev->sdev_gendev))
err = 0;
spin_unlock_irqrestore(q->queue_lock, flags);
if (err)
return err;
err = scsi_dh->set_params(sdev, params);
err = sdev->handler->set_params(sdev, params);
put_device(&sdev->sdev_gendev);
return err;
}
@ -413,8 +394,8 @@ int scsi_dh_attach(struct request_queue *q, const char *name)
if (err)
return err;
if (sdev->scsi_dh_data) {
if (sdev->scsi_dh_data->scsi_dh != scsi_dh)
if (sdev->handler) {
if (sdev->handler != scsi_dh)
err = -EBUSY;
goto out_put_device;
}
@ -451,8 +432,8 @@ const char *scsi_dh_attached_handler_name(struct request_queue *q, gfp_t gfp)
if (!sdev)
return NULL;
if (sdev->scsi_dh_data)
handler_name = kstrdup(sdev->scsi_dh_data->scsi_dh->name, gfp);
if (sdev->handler)
handler_name = kstrdup(sdev->handler->name, gfp);
put_device(&sdev->sdev_gendev);
return handler_name;

View File

@ -37,6 +37,7 @@
#include <scsi/scsi_transport.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi_dh.h>
#include <scsi/sg.h>
#include "scsi_priv.h"
@ -464,11 +465,10 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
if (scsi_sense_is_deferred(&sshdr))
return NEEDS_RETRY;
if (sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh &&
sdev->scsi_dh_data->scsi_dh->check_sense) {
if (sdev->handler && sdev->handler->check_sense) {
int rc;
rc = sdev->scsi_dh_data->scsi_dh->check_sense(sdev, &sshdr);
rc = sdev->handler->check_sense(sdev, &sshdr);
if (rc != SCSI_RETURN_NOT_HANDLED)
return rc;
/* handler does not care. Drop down to default handling */

View File

@ -31,6 +31,7 @@
#include <scsi/scsi_driver.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_dh.h>
#include <trace/events/scsi.h>
@ -1248,9 +1249,8 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req)
{
struct scsi_cmnd *cmd = req->special;
if (unlikely(sdev->scsi_dh_data && sdev->scsi_dh_data->scsi_dh
&& sdev->scsi_dh_data->scsi_dh->prep_fn)) {
int ret = sdev->scsi_dh_data->scsi_dh->prep_fn(sdev, req);
if (unlikely(sdev->handler && sdev->handler->prep_fn)) {
int ret = sdev->handler->prep_fn(sdev, req);
if (ret != BLKPREP_OK)
return ret;
}

View File

@ -196,32 +196,13 @@ struct scsi_device {
struct execute_work ew; /* used to get process context on put */
struct work_struct requeue_work;
struct scsi_dh_data *scsi_dh_data;
struct scsi_device_handler *handler;
void *handler_data;
enum scsi_device_state sdev_state;
unsigned long sdev_data[0];
} __attribute__((aligned(sizeof(unsigned long))));
typedef void (*activate_complete)(void *, int);
struct scsi_device_handler {
/* Used by the infrastructure */
struct list_head list; /* list of scsi_device_handlers */
/* Filled by the hardware handler */
struct module *module;
const char *name;
int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
struct scsi_dh_data *(*attach)(struct scsi_device *);
void (*detach)(struct scsi_device *);
int (*activate)(struct scsi_device *, activate_complete, void *);
int (*prep_fn)(struct scsi_device *, struct request *);
int (*set_params)(struct scsi_device *, const char *);
};
struct scsi_dh_data {
struct scsi_device_handler *scsi_dh;
struct scsi_device *sdev;
};
#define to_scsi_device(d) \
container_of(d, struct scsi_device, sdev_gendev)
#define class_to_sdev(d) \

View File

@ -55,6 +55,23 @@ enum {
SCSI_DH_NOSYS,
SCSI_DH_DRIVER_MAX,
};
typedef void (*activate_complete)(void *, int);
struct scsi_device_handler {
/* Used by the infrastructure */
struct list_head list; /* list of scsi_device_handlers */
/* Filled by the hardware handler */
struct module *module;
const char *name;
int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
int (*attach)(struct scsi_device *);
void (*detach)(struct scsi_device *);
int (*activate)(struct scsi_device *, activate_complete, void *);
int (*prep_fn)(struct scsi_device *, struct request *);
int (*set_params)(struct scsi_device *, const char *);
};
#ifdef CONFIG_SCSI_DH
extern int scsi_dh_activate(struct request_queue *, activate_complete, void *);
extern int scsi_dh_attach(struct request_queue *, const char *);