]> Pileus Git - ~andy/linux/blobdiff - drivers/scsi/device_handler/scsi_dh_alua.c
Merge branch 'modsplit-Oct31_2011' of git://git.kernel.org/pub/scm/linux/kernel/git...
[~andy/linux] / drivers / scsi / device_handler / scsi_dh_alua.c
index 6fec9fe5dc39f7908df4bdc79f02cdafe92b415d..4ef021291a4d06d2ecd4340f5ba1c35658a5c9d1 100644 (file)
@@ -21,6 +21,7 @@
  */
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_eh.h>
 #include <scsi/scsi_dh.h>
@@ -127,43 +128,6 @@ static struct request *get_alua_req(struct scsi_device *sdev,
        return rq;
 }
 
-/*
- * submit_std_inquiry - Issue a standard INQUIRY command
- * @sdev: sdev the command should be send to
- */
-static int submit_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
-{
-       struct request *rq;
-       int err = SCSI_DH_RES_TEMP_UNAVAIL;
-
-       rq = get_alua_req(sdev, h->inq, ALUA_INQUIRY_SIZE, READ);
-       if (!rq)
-               goto done;
-
-       /* Prepare the command. */
-       rq->cmd[0] = INQUIRY;
-       rq->cmd[1] = 0;
-       rq->cmd[2] = 0;
-       rq->cmd[4] = ALUA_INQUIRY_SIZE;
-       rq->cmd_len = COMMAND_SIZE(INQUIRY);
-
-       rq->sense = h->sense;
-       memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
-       rq->sense_len = h->senselen = 0;
-
-       err = blk_execute_rq(rq->q, NULL, rq, 1);
-       if (err == -EIO) {
-               sdev_printk(KERN_INFO, sdev,
-                           "%s: std inquiry failed with %x\n",
-                           ALUA_DH_NAME, rq->errors);
-               h->senselen = rq->sense_len;
-               err = SCSI_DH_IO;
-       }
-       blk_put_request(rq);
-done:
-       return err;
-}
-
 /*
  * submit_vpd_inquiry - Issue an INQUIRY VPD page 0x83 command
  * @sdev: sdev the command should be sent to
@@ -338,23 +302,17 @@ static unsigned submit_stpg(struct alua_dh_data *h)
 }
 
 /*
- * alua_std_inquiry - Evaluate standard INQUIRY command
+ * alua_check_tpgs - Evaluate TPGS setting
  * @sdev: device to be checked
  *
- * Just extract the TPGS setting to find out if ALUA
+ * Examine the TPGS setting of the sdev to find out if ALUA
  * is supported.
  */
-static int alua_std_inquiry(struct scsi_device *sdev, struct alua_dh_data *h)
+static int alua_check_tpgs(struct scsi_device *sdev, struct alua_dh_data *h)
 {
-       int err;
-
-       err = submit_std_inquiry(sdev, h);
-
-       if (err != SCSI_DH_OK)
-               return err;
+       int err = SCSI_DH_OK;
 
-       /* Check TPGS setting */
-       h->tpgs = (h->inq[5] >> 4) & 0x3;
+       h->tpgs = scsi_device_tpgs(sdev);
        switch (h->tpgs) {
        case TPGS_MODE_EXPLICIT|TPGS_MODE_IMPLICIT:
                sdev_printk(KERN_INFO, sdev,
@@ -508,27 +466,28 @@ static int alua_check_sense(struct scsi_device *sdev,
                         * Power On, Reset, or Bus Device Reset, just retry.
                         */
                        return ADD_TO_MLQUEUE;
-               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06) {
+               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x06)
                        /*
                         * ALUA state changed
                         */
                        return ADD_TO_MLQUEUE;
-               }
-               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07) {
+               if (sense_hdr->asc == 0x2a && sense_hdr->ascq == 0x07)
                        /*
                         * Implicit ALUA state transition failed
                         */
                        return ADD_TO_MLQUEUE;
-               }
-               if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e) {
+               if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x03)
+                       /*
+                        * Inquiry data has changed
+                        */
+                       return ADD_TO_MLQUEUE;
+               if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e)
                        /*
                         * REPORTED_LUNS_DATA_HAS_CHANGED is reported
                         * when switching controllers on targets like
                         * Intel Multi-Flex. We can just retry.
                         */
                        return ADD_TO_MLQUEUE;
-               }
-
                break;
        }
 
@@ -547,9 +506,9 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
 {
        struct scsi_sense_hdr sense_hdr;
        int len, k, off, valid_states = 0;
-       char *ucp;
+       unsigned char *ucp;
        unsigned err;
-       unsigned long expiry, interval = 10;
+       unsigned long expiry, interval = 1000;
 
        expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
  retry:
@@ -610,7 +569,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
        case TPGS_STATE_TRANSITIONING:
                if (time_before(jiffies, expiry)) {
                        /* State transition, retry */
-                       interval *= 10;
+                       interval *= 2;
                        msleep(interval);
                        goto retry;
                }
@@ -642,7 +601,7 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
 {
        int err;
 
-       err = alua_std_inquiry(sdev, h);
+       err = alua_check_tpgs(sdev, h);
        if (err != SCSI_DH_OK)
                goto out;
 
@@ -674,11 +633,9 @@ static int alua_activate(struct scsi_device *sdev,
        struct alua_dh_data *h = get_alua_data(sdev);
        int err = SCSI_DH_OK;
 
-       if (h->group_id != -1) {
-               err = alua_rtpg(sdev, h);
-               if (err != SCSI_DH_OK)
-                       goto out;
-       }
+       err = alua_rtpg(sdev, h);
+       if (err != SCSI_DH_OK)
+               goto out;
 
        if (h->tpgs & TPGS_MODE_EXPLICIT &&
            h->state != TPGS_STATE_OPTIMIZED &&
@@ -720,23 +677,10 @@ static int alua_prep_fn(struct scsi_device *sdev, struct request *req)
 
 }
 
-static const struct scsi_dh_devlist alua_dev_list[] = {
-       {"HP", "MSA VOLUME" },
-       {"HP", "HSV101" },
-       {"HP", "HSV111" },
-       {"HP", "HSV200" },
-       {"HP", "HSV210" },
-       {"HP", "HSV300" },
-       {"IBM", "2107900" },
-       {"IBM", "2145" },
-       {"Pillar", "Axiom" },
-       {"Intel", "Multi-Flex"},
-       {"NETAPP", "LUN"},
-       {"NETAPP", "LUN C-Mode"},
-       {"AIX", "NVDISK"},
-       {"Promise", "VTrak"},
-       {NULL, NULL}
-};
+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);
@@ -744,12 +688,12 @@ static void alua_bus_detach(struct scsi_device *sdev);
 static struct scsi_device_handler alua_dh = {
        .name = ALUA_DH_NAME,
        .module = THIS_MODULE,
-       .devlist = alua_dev_list,
        .attach = alua_bus_attach,
        .detach = alua_bus_detach,
        .prep_fn = alua_prep_fn,
        .check_sense = alua_check_sense,
        .activate = alua_activate,
+       .match = alua_match,
 };
 
 /*
@@ -791,6 +735,7 @@ static int alua_bus_attach(struct scsi_device *sdev)
        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;