aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/device_handler/scsi_dh_alua.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/device_handler/scsi_dh_alua.c')
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c89
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 e99507ed0e3c..854b568b9931 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;