diff options
Diffstat (limited to 'drivers/scsi/device_handler/scsi_dh_alua.c')
-rw-r--r-- | drivers/scsi/device_handler/scsi_dh_alua.c | 89 |
1 files changed, 32 insertions, 57 deletions
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index e99507e..854b568 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -62,6 +62,7 @@ #define ALUA_OPTIMIZE_STPG 1 struct alua_dh_data { + struct scsi_dh_data dh_data; int group_id; int rel_port; int tpgs; @@ -87,9 +88,7 @@ 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) { - struct scsi_dh_data *scsi_dh_data = sdev->scsi_dh_data; - BUG_ON(scsi_dh_data == NULL); - return ((struct alua_dh_data *) scsi_dh_data->buf); + return container_of(sdev->scsi_dh_data, struct alua_dh_data, dh_data); } static int realloc_buffer(struct alua_dh_data *h, unsigned len) @@ -474,6 +473,13 @@ static int alua_check_sense(struct scsi_device *sdev, * LUN Not Ready -- Offline */ return SUCCESS; + if (sdev->allow_restart && + sense_hdr->asc == 0x04 && sense_hdr->ascq == 0x02) + /* + * if the device is not started, we need to wake + * the error handler to start the motor + */ + return FAILED; break; case UNIT_ATTENTION: if (sense_hdr->asc == 0x29 && sense_hdr->ascq == 0x00) @@ -818,42 +824,18 @@ static bool alua_match(struct scsi_device *sdev) return (scsi_device_tpgs(sdev) != 0); } -static int alua_bus_attach(struct scsi_device *sdev); -static void alua_bus_detach(struct scsi_device *sdev); - -static struct scsi_device_handler alua_dh = { - .name = ALUA_DH_NAME, - .module = THIS_MODULE, - .attach = alua_bus_attach, - .detach = alua_bus_detach, - .prep_fn = alua_prep_fn, - .check_sense = alua_check_sense, - .activate = alua_activate, - .set_params = alua_set_params, - .match = alua_match, -}; - /* * alua_bus_attach - Attach device handler * @sdev: device to be attached to */ -static int alua_bus_attach(struct scsi_device *sdev) +static struct scsi_dh_data *alua_bus_attach(struct scsi_device *sdev) { - struct scsi_dh_data *scsi_dh_data; struct alua_dh_data *h; - unsigned long flags; - int err = SCSI_DH_OK; - - scsi_dh_data = kzalloc(sizeof(*scsi_dh_data) - + sizeof(*h) , GFP_KERNEL); - if (!scsi_dh_data) { - sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n", - ALUA_DH_NAME); - return -ENOMEM; - } + int err; - scsi_dh_data->scsi_dh = &alua_dh; - h = (struct alua_dh_data *) scsi_dh_data->buf; + h = kzalloc(sizeof(*h) , GFP_KERNEL); + if (!h) + return ERR_PTR(-ENOMEM); h->tpgs = TPGS_MODE_UNINITIALIZED; h->state = TPGS_STATE_OPTIMIZED; h->group_id = -1; @@ -863,23 +845,14 @@ static int alua_bus_attach(struct scsi_device *sdev) h->sdev = sdev; err = alua_initialize(sdev, h); - if ((err != SCSI_DH_OK) && (err != SCSI_DH_DEV_OFFLINED)) + if (err != SCSI_DH_OK && err != SCSI_DH_DEV_OFFLINED) goto failed; - if (!try_module_get(THIS_MODULE)) - goto failed; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - sdev->scsi_dh_data = scsi_dh_data; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); sdev_printk(KERN_NOTICE, sdev, "%s: Attached\n", ALUA_DH_NAME); - - return 0; - + return &h->dh_data; failed: - kfree(scsi_dh_data); - sdev_printk(KERN_ERR, sdev, "%s: not attached\n", ALUA_DH_NAME); - return -EINVAL; + kfree(h); + return ERR_PTR(-EINVAL); } /* @@ -888,23 +861,25 @@ failed: */ static void alua_bus_detach(struct scsi_device *sdev) { - struct scsi_dh_data *scsi_dh_data; - struct alua_dh_data *h; - unsigned long flags; - - spin_lock_irqsave(sdev->request_queue->queue_lock, flags); - scsi_dh_data = sdev->scsi_dh_data; - sdev->scsi_dh_data = NULL; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); + struct alua_dh_data *h = get_alua_data(sdev); - h = (struct alua_dh_data *) scsi_dh_data->buf; if (h->buff && h->inq != h->buff) kfree(h->buff); - kfree(scsi_dh_data); - module_put(THIS_MODULE); - sdev_printk(KERN_NOTICE, sdev, "%s: Detached\n", ALUA_DH_NAME); + kfree(h); } +static struct scsi_device_handler alua_dh = { + .name = ALUA_DH_NAME, + .module = THIS_MODULE, + .attach = alua_bus_attach, + .detach = alua_bus_detach, + .prep_fn = alua_prep_fn, + .check_sense = alua_check_sense, + .activate = alua_activate, + .set_params = alua_set_params, + .match = alua_match, +}; + static int __init alua_init(void) { int r; |