Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=88e2f98e1b3eb27ae708daa3b37dd50f3f06c952
Commit:     88e2f98e1b3eb27ae708daa3b37dd50f3f06c952
Parent:     9ad5204d68a3b48b92907d88d1c28d33fde6ba2a
Author:     Salyzyn, Mark <[EMAIL PROTECTED]>
AuthorDate: Tue Jul 17 14:01:28 2007 -0400
Committer:  James Bottomley <[EMAIL PROTECTED]>
CommitDate: Wed Jul 18 11:17:48 2007 -0500

    [SCSI] aacraid: add vpd to inquiry
    
    Report VPD inquiry page 0x80 with an unique array creation serial
    number (CUID). When an array is created, the metadata stored on the
    physical drives gets an unique serial number. This serial number
    remains constant through array morphing or migration to other
    controllers.  This patch is a forward port and modification to survive
    morphing and migration operations, of a similar piece of
    (un-attributed author) code added to the SLES10 SP1 aacraid driver.
    
    To test the results of the patch, observe that /dev/disk/by-id/
    entries will show up for the arrays resulting from the udev rules.
    Also, as per the udev rules, 'scsi_id -g -x -a -s /block/sd? -d
    /dev/sd?'  will report the ID_SERIAL as constructed from the inquiry
    data.
    
    It was reported to me that the 'ADPT' leading the serial number was bad
    form, that the inquiry vendor field was enough to differentiate the
    storage uniquely. Subsequent search found that another Adaptec AAC based
    driver reported the 8 hex serial number only without such adornments, so
    dropped ADPT to match. Resubmitting the patch with this alteration.
    
    Signed-off-by: Mark Salyzyn <[EMAIL PROTECTED]>
    Signed-off-by: James Bottomley <[EMAIL PROTECTED]>
---
 drivers/scsi/aacraid/aachba.c  |  138 ++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/aacraid/aacraid.h |   14 ++++
 2 files changed, 152 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 80d4207..a26baab 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -751,6 +751,101 @@ static void setinqstr(struct aac_dev *dev, void *data, 
int tindex)
        inqstrcpy ("V1.0", str->prl);
 }
 
+static void get_container_serial_callback(void *context, struct fib * fibptr)
+{
+       struct aac_get_serial_resp * get_serial_reply;
+       struct scsi_cmnd * scsicmd;
+
+       BUG_ON(fibptr == NULL);
+
+       scsicmd = (struct scsi_cmnd *) context;
+       if (!aac_valid_context(scsicmd, fibptr))
+               return;
+
+       get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr);
+       /* Failure is irrelevant, using default value instead */
+       if (le32_to_cpu(get_serial_reply->status) == CT_OK) {
+               char sp[13];
+               /* EVPD bit set */
+               sp[0] = INQD_PDT_DA;
+               sp[1] = scsicmd->cmnd[2];
+               sp[2] = 0;
+               sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X",
+                 le32_to_cpu(get_serial_reply->uid));
+               aac_internal_transfer(scsicmd, sp, 0, sizeof(sp));
+       }
+
+       scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+
+       aac_fib_complete(fibptr);
+       aac_fib_free(fibptr);
+       scsicmd->scsi_done(scsicmd);
+}
+
+/**
+ *     aac_get_container_serial - get container serial, none blocking.
+ */
+static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
+{
+       int status;
+       struct aac_get_serial *dinfo;
+       struct fib * cmd_fibcontext;
+       struct aac_dev * dev;
+
+       dev = (struct aac_dev *)scsicmd->device->host->hostdata;
+
+       if (!(cmd_fibcontext = aac_fib_alloc(dev)))
+               return -ENOMEM;
+
+       aac_fib_init(cmd_fibcontext);
+       dinfo = (struct aac_get_serial *) fib_data(cmd_fibcontext);
+
+       dinfo->command = cpu_to_le32(VM_ContainerConfig);
+       dinfo->type = cpu_to_le32(CT_CID_TO_32BITS_UID);
+       dinfo->cid = cpu_to_le32(scmd_id(scsicmd));
+
+       status = aac_fib_send(ContainerCommand,
+                 cmd_fibcontext,
+                 sizeof (struct aac_get_serial),
+                 FsaNormal,
+                 0, 1,
+                 (fib_callback) get_container_serial_callback,
+                 (void *) scsicmd);
+
+       /*
+        *      Check that the command queued to the controller
+        */
+       if (status == -EINPROGRESS) {
+               scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+               return 0;
+       }
+
+       printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with 
status: %d.\n", status);
+       aac_fib_complete(cmd_fibcontext);
+       aac_fib_free(cmd_fibcontext);
+       return -1;
+}
+
+/* Function: setinqserial
+ *
+ * Arguments: [1] pointer to void [1] int
+ *
+ * Purpose: Sets SCSI Unit Serial number.
+ *          This is a fake. We should read a proper
+ *          serial number from the container. <SuSE>But
+ *          without docs it's quite hard to do it :-)
+ *          So this will have to do in the meantime.</SuSE>
+ */
+
+static int setinqserial(struct aac_dev *dev, void *data, int cid)
+{
+       /*
+        *      This breaks array migration.
+        */
+       return snprintf((char *)(data), sizeof(struct scsi_inq) - 4, "%08X%02X",
+                       le32_to_cpu(dev->adapter_info.serial[0]), cid);
+}
+
 static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
                      u8 a_sense_code, u8 incorrect_length,
                      u8 bit_pointer, u16 field_pointer,
@@ -1798,6 +1893,49 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
                dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
                memset(&inq_data, 0, sizeof (struct inquiry_data));
 
+               if (scsicmd->cmnd[1] & 0x1 ) {
+                       char *arr = (char *)&inq_data;
+
+                       /* EVPD bit set */
+                       arr[0] = (scmd_id(scsicmd) == host->this_id) ?
+                         INQD_PDT_PROC : INQD_PDT_DA;
+                       if (scsicmd->cmnd[2] == 0) {
+                               /* supported vital product data pages */
+                               arr[3] = 2;
+                               arr[4] = 0x0;
+                               arr[5] = 0x80;
+                               arr[1] = scsicmd->cmnd[2];
+                               aac_internal_transfer(scsicmd, &inq_data, 0,
+                                 sizeof(inq_data));
+                               scsicmd->result = DID_OK << 16 |
+                                 COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
+                       } else if (scsicmd->cmnd[2] == 0x80) {
+                               /* unit serial number page */
+                               arr[3] = setinqserial(dev, &arr[4],
+                                 scmd_id(scsicmd));
+                               arr[1] = scsicmd->cmnd[2];
+                               aac_internal_transfer(scsicmd, &inq_data, 0,
+                                 sizeof(inq_data));
+                               return aac_get_container_serial(scsicmd);
+                       } else {
+                               /* vpd page not implemented */
+                               scsicmd->result = DID_OK << 16 |
+                                 COMMAND_COMPLETE << 8 |
+                                 SAM_STAT_CHECK_CONDITION;
+                               set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
+                                 ILLEGAL_REQUEST,
+                                 SENCODE_INVALID_CDB_FIELD,
+                                 ASENCODE_NO_SENSE, 0, 7, 2, 0);
+                               memcpy(scsicmd->sense_buffer,
+                                 &dev->fsa_dev[cid].sense_data,
+                                 (sizeof(dev->fsa_dev[cid].sense_data) >
+                                   sizeof(scsicmd->sense_buffer))
+                                      ? sizeof(scsicmd->sense_buffer)
+                                      : sizeof(dev->fsa_dev[cid].sense_data));
+                       }
+                       scsicmd->scsi_done(scsicmd);
+                       return 0;
+               }
                inq_data.inqd_ver = 2;  /* claim compliance to SCSI-2 */
                inq_data.inqd_rdf = 2;  /* A response data format value of two 
indicates that the data shall be in the format specified in SCSI-2 */
                inq_data.inqd_len = 31;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index f1d3b66..400d034 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1567,6 +1567,20 @@ struct aac_get_name_resp {
        u8              data[16];
 };
 
+#define CT_CID_TO_32BITS_UID 165
+struct aac_get_serial {
+       __le32          command;        /* VM_ContainerConfig */
+       __le32          type;           /* CT_CID_TO_32BITS_UID */
+       __le32          cid;
+};
+
+struct aac_get_serial_resp {
+       __le32          dummy0;
+       __le32          dummy1;
+       __le32          status; /* CT_OK */
+       __le32          uid;
+};
+
 /*
  * The following command is sent to shut down each container.
  */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to