aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi/aacraid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r--drivers/scsi/aacraid/aachba.c140
-rw-r--r--drivers/scsi/aacraid/aacraid.h14
-rw-r--r--drivers/scsi/aacraid/commsup.c16
3 files changed, 162 insertions, 8 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 0b6fd0b654d..a26baab09db 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;
@@ -2070,7 +2208,7 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
}
else return -EINVAL;
- qd.valid = fsa_dev_ptr[qd.cnum].valid;
+ qd.valid = fsa_dev_ptr[qd.cnum].valid != 0;
qd.locked = fsa_dev_ptr[qd.cnum].locked;
qd.deleted = fsa_dev_ptr[qd.cnum].deleted;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index f1d3b66af87..400d03403cd 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.
*/
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index d510839c0bb..bb870906b4c 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -80,7 +80,11 @@ static int fib_map_alloc(struct aac_dev *dev)
void aac_fib_map_free(struct aac_dev *dev)
{
- pci_free_consistent(dev->pdev, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB), dev->hw_fib_va, dev->hw_fib_pa);
+ pci_free_consistent(dev->pdev,
+ dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
+ dev->hw_fib_va, dev->hw_fib_pa);
+ dev->hw_fib_va = NULL;
+ dev->hw_fib_pa = 0;
}
/**
@@ -1087,8 +1091,6 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
* case.
*/
aac_fib_map_free(aac);
- aac->hw_fib_va = NULL;
- aac->hw_fib_pa = 0;
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
aac->comm_addr = NULL;
aac->comm_phys = 0;
@@ -1098,12 +1100,12 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced)
kfree(aac->fsa_dev);
aac->fsa_dev = NULL;
if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) {
- if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) ||
- ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK))))
+ if (((retval = pci_set_dma_mask(aac->pdev, DMA_31BIT_MASK))) ||
+ ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_31BIT_MASK))))
goto out;
} else {
- if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) ||
- ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL))))
+ if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) ||
+ ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK))))
goto out;
}
if ((retval = (*(aac_get_driver_ident(index)->init))(aac)))