From fe76df4235986cfacc2d3b71cef7c42bc1a6dd6c Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 12:55:07 -0700 Subject: [SCSI] aacraid: Fix blocking issue with container probing function (cast update) Received from Mark Salyzyn, The aac_probe_container call blocks. This is an issue because it is called on occasion in the context of the queuecommand handler. Once in a blue moon this has resulted in a kernel panic sleeping during interrupt; or problems with some embedded system versions of the kernel that depend on queuecommand to not block. This ugly patch rewrites the aac_probe_container call into a new routine _aac_probe_container that is an asynchronous state machine to complete the series of operations. The legacy blocking aac_probe_container call used in other areas of the driver (during initialization scanning for all targets and in the separate hot-add/remove [aacraid] thread) merely issues _aac_probe_container and then simple spins calling schedule() waiting for completion. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 311 +++++++++++++++++++++++------------------- 1 file changed, 169 insertions(+), 142 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index d789e61bdc4..1610f0670c7 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -258,13 +258,10 @@ int aac_get_containers(struct aac_dev *dev) u32 index; int status = 0; struct fib * fibptr; - unsigned instance; struct aac_get_container_count *dinfo; struct aac_get_container_count_resp *dresp; int maximum_num_containers = MAXIMUM_NUM_CONTAINERS; - instance = dev->scsi_host_ptr->unique_id; - if (!(fibptr = aac_fib_alloc(dev))) return -ENOMEM; @@ -284,88 +281,35 @@ int aac_get_containers(struct aac_dev *dev) maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); aac_fib_complete(fibptr); } + aac_fib_free(fibptr); if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) maximum_num_containers = MAXIMUM_NUM_CONTAINERS; - fsa_dev_ptr = kmalloc( - sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); - if (!fsa_dev_ptr) { - aac_fib_free(fibptr); + fsa_dev_ptr = kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, + GFP_KERNEL); + if (!fsa_dev_ptr) return -ENOMEM; - } memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); dev->fsa_dev = fsa_dev_ptr; dev->maximum_num_containers = maximum_num_containers; - for (index = 0; index < dev->maximum_num_containers; index++) { - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - + for (index = 0; index < dev->maximum_num_containers; ) { fsa_dev_ptr[index].devname[0] = '\0'; - aac_fib_init(fibptr); - dinfo = (struct aac_query_mount *) fib_data(fibptr); - - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(index); - dinfo->type = cpu_to_le32(FT_FILESYS); + status = aac_probe_container(dev, index); - status = aac_fib_send(ContainerCommand, - fibptr, - sizeof (struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); - if (status < 0 ) { + if (status < 0) { printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); break; } - dresp = (struct aac_mount *)fib_data(fibptr); - - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { - dinfo->command = cpu_to_le32(VM_NameServe64); - dinfo->count = cpu_to_le32(index); - dinfo->type = cpu_to_le32(FT_FILESYS); - if (aac_fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL) < 0) - continue; - } else - dresp->mnt[0].capacityhigh = 0; - - dprintk ((KERN_DEBUG - "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n", - (int)index, (int)le32_to_cpu(dresp->status), - (int)le32_to_cpu(dresp->mnt[0].vol), - (int)le32_to_cpu(dresp->mnt[0].state), - ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + - (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32))); - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr[index].valid = 1; - fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr[index].size - = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + - (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr[index].ro = 1; - } - aac_fib_complete(fibptr); /* * If there are no more containers, then stop asking. */ - if ((index + 1) >= le32_to_cpu(dresp->count)){ + if (++index >= status) break; - } } - aac_fib_free(fibptr); return status; } @@ -473,85 +417,185 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) return -1; } -/** - * aac_probe_container - query a logical volume - * @dev: device to query - * @cid: container identifier - * - * Queries the controller about the given volume. The volume information - * is updated in the struct fsa_dev_info structure rather than returned. - */ - -int aac_probe_container(struct aac_dev *dev, int cid) +static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) { - struct fsa_dev_info *fsa_dev_ptr; - int status; - struct aac_query_mount *dinfo; - struct aac_mount *dresp; - struct fib * fibptr; - unsigned instance; + struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; - fsa_dev_ptr = dev->fsa_dev; - if (!fsa_dev_ptr) - return -ENOMEM; - instance = dev->scsi_host_ptr->unique_id; + if (fsa_dev_ptr[scmd_id(scsicmd)].valid) + return aac_scsi_cmd(scsicmd); - if (!(fibptr = aac_fib_alloc(dev))) - return -ENOMEM; + scsicmd->result = DID_NO_CONNECT << 16; + scsicmd->scsi_done(scsicmd); + return 0; +} + +static int _aac_probe_container2(void * context, struct fib * fibptr) +{ + struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; + struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; + int (*callback)(struct scsi_cmnd *); + + scsicmd->SCp.Status = 0; + if (fsa_dev_ptr) { + struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr); + fsa_dev_ptr += scmd_id(scsicmd); + + if ((le32_to_cpu(dresp->status) == ST_OK) && + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { + fsa_dev_ptr->valid = 1; + fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); + fsa_dev_ptr->size + = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + + (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); + fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0); + } + if ((fsa_dev_ptr->valid & 1) == 0) + fsa_dev_ptr->valid = 0; + scsicmd->SCp.Status = le32_to_cpu(dresp->count); + } + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr); + scsicmd->SCp.ptr = NULL; + return (*callback)(scsicmd); +} + +static int _aac_probe_container1(void * context, struct fib * fibptr) +{ + struct scsi_cmnd * scsicmd; + struct aac_mount * dresp; + struct aac_query_mount *dinfo; + int status; + + dresp = (struct aac_mount *) fib_data(fibptr); + dresp->mnt[0].capacityhigh = 0; + if ((le32_to_cpu(dresp->status) != ST_OK) || + ((le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && + (le32_to_cpu(dresp->mnt[0].state) == FSCS_HIDDEN))) + return _aac_probe_container2(context, fibptr); + scsicmd = (struct scsi_cmnd *) context; + scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); - dinfo->command = cpu_to_le32(VM_NameServe); - dinfo->count = cpu_to_le32(cid); + dinfo->command = cpu_to_le32(VM_NameServe64); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); dinfo->type = cpu_to_le32(FT_FILESYS); status = aac_fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL); + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 0, 1, + (fib_callback) _aac_probe_container2, + (void *) scsicmd); + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) { + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; + return 0; + } if (status < 0) { - printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n"); - goto error; + /* Inherit results from VM_NameServe, if any */ + dresp->status = cpu_to_le32(ST_OK); + return _aac_probe_container2(context, fibptr); } + return 0; +} - dresp = (struct aac_mount *) fib_data(fibptr); +static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *)) +{ + struct fib * fibptr; + int status = -ENOMEM; - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { - dinfo->command = cpu_to_le32(VM_NameServe64); - dinfo->count = cpu_to_le32(cid); - dinfo->type = cpu_to_le32(FT_FILESYS); + if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) { + struct aac_query_mount *dinfo; - if (aac_fib_send(ContainerCommand, - fibptr, - sizeof(struct aac_query_mount), - FsaNormal, - 1, 1, - NULL, NULL) < 0) - goto error; - } else - dresp->mnt[0].capacityhigh = 0; + aac_fib_init(fibptr); + + dinfo = (struct aac_query_mount *)fib_data(fibptr); + + dinfo->command = cpu_to_le32(VM_NameServe); + dinfo->count = cpu_to_le32(scmd_id(scsicmd)); + dinfo->type = cpu_to_le32(FT_FILESYS); + scsicmd->SCp.ptr = (char *)callback; - if ((le32_to_cpu(dresp->status) == ST_OK) && - (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { - fsa_dev_ptr[cid].valid = 1; - fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol); - fsa_dev_ptr[cid].size - = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + - (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); - if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) - fsa_dev_ptr[cid].ro = 1; + status = aac_fib_send(ContainerCommand, + fibptr, + sizeof(struct aac_query_mount), + FsaNormal, + 0, 1, + (fib_callback) _aac_probe_container1, + (void *) scsicmd); + /* + * Check that the command queued to the controller + */ + if (status == -EINPROGRESS) { + scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; + return 0; + } + if (status < 0) { + scsicmd->SCp.ptr = NULL; + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + } + } + if (status < 0) { + struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; + if (fsa_dev_ptr) { + fsa_dev_ptr += scmd_id(scsicmd); + if ((fsa_dev_ptr->valid & 1) == 0) { + fsa_dev_ptr->valid = 0; + return (*callback)(scsicmd); + } + } } + return status; +} -error: - aac_fib_complete(fibptr); - aac_fib_free(fibptr); +/** + * aac_probe_container - query a logical volume + * @dev: device to query + * @cid: container identifier + * + * Queries the controller about the given volume. The volume information + * is updated in the struct fsa_dev_info structure rather than returned. + */ +static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd) +{ + scsicmd->device = NULL; + return 0; +} +int aac_probe_container(struct aac_dev *dev, int cid) +{ + struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL); + struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL); + int status; + + if (!scsicmd || !scsidev) { + kfree(scsicmd); + kfree(scsidev); + return -ENOMEM; + } + scsicmd->list.next = NULL; + scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1; + + scsicmd->device = scsidev; + scsidev->sdev_state = 0; + scsidev->id = cid; + scsidev->host = dev->scsi_host_ptr; + + if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) + while (scsicmd->device == scsidev) + schedule(); + status = scsicmd->SCp.Status; + kfree(scsicmd); + kfree(scsidev); return status; } @@ -1646,29 +1690,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case TEST_UNIT_READY: if (dev->in_reset) return -1; - spin_unlock_irq(host->host_lock); - aac_probe_container(dev, cid); - if ((fsa_dev_ptr[cid].valid & 1) == 0) - fsa_dev_ptr[cid].valid = 0; - spin_lock_irq(host->host_lock); - if (fsa_dev_ptr[cid].valid == 0) { - scsicmd->result = DID_NO_CONNECT << 16; - scsicmd->scsi_done(scsicmd); - return 0; - } + return _aac_probe_container(scsicmd, + aac_probe_container_callback2); default: break; } } - /* - * If the target container still doesn't exist, - * return failure - */ - if (fsa_dev_ptr[cid].valid == 0) { - scsicmd->result = DID_BAD_TARGET << 16; - scsicmd->scsi_done(scsicmd); - return 0; - } } else { /* check for physical non-dasd devices */ if ((dev->nondasd_support == 1) || expose_physicals) { if (dev->in_reset) -- cgit v1.2.3-70-g09d2 From 9e7c349c91db3a9f9ac6cd74a693c4093c7d4571 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:26:55 -0700 Subject: [SCSI] aacraid: remove un-needed references to container id (cid) Received from Mark Salyzyn, This little patch removes the ',cid)' container identification argument from some of the functions. The argument is used in some cases as merely a debug helper and thus not used, and in others, the value can be quickly acquired from the scsi command in their single solitary use in the procedure rather than wasting resources on passing the argument in from above. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 1610f0670c7..3d21d7dd2e5 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -375,7 +375,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) /** * aac_get_container_name - get container name, none blocking. */ -static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) +static int aac_get_container_name(struct scsi_cmnd * scsicmd) { int status; struct aac_get_name *dinfo; @@ -392,7 +392,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) dinfo->command = cpu_to_le32(VM_ContainerConfig); dinfo->type = cpu_to_le32(CT_READ_NAME); - dinfo->cid = cpu_to_le32(cid); + dinfo->cid = cpu_to_le32(scmd_id(scsicmd)); dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); status = aac_fib_send(ContainerCommand, @@ -1361,7 +1361,7 @@ static void io_callback(void *context, struct fib * fibptr) scsicmd->scsi_done(scsicmd); } -static int aac_read(struct scsi_cmnd * scsicmd, int cid) +static int aac_read(struct scsi_cmnd * scsicmd) { u64 lba; u32 count; @@ -1375,7 +1375,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) */ switch (scsicmd->cmnd[0]) { case READ_6: - dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd))); lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; @@ -1385,7 +1385,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) count = 256; break; case READ_16: - dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 56) | ((u64)scsicmd->cmnd[3] << 48) | @@ -1399,7 +1399,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; break; case READ_12: - dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | @@ -1409,7 +1409,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; break; default: - dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | @@ -1449,7 +1449,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) return 0; } -static int aac_write(struct scsi_cmnd * scsicmd, int cid) +static int aac_write(struct scsi_cmnd * scsicmd) { u64 lba; u32 count; @@ -1468,7 +1468,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) if (count == 0) count = 256; } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ - dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 56) | ((u64)scsicmd->cmnd[3] << 48) | @@ -1480,14 +1480,14 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ - dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; } else { - dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid)); + dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; } @@ -1567,7 +1567,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) cmd->scsi_done(cmd); } -static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) +static int aac_synchronize(struct scsi_cmnd *scsicmd) { int status; struct fib *cmd_fibcontext; @@ -1612,7 +1612,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) synchronizecmd = fib_data(cmd_fibcontext); synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); - synchronizecmd->cid = cpu_to_le32(cid); + synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); synchronizecmd->count = cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); @@ -1760,7 +1760,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); - return aac_get_container_name(scsicmd, cid); + return aac_get_container_name(scsicmd); } case SERVICE_ACTION_IN: if (!(dev->raw_io_interface) || @@ -1926,7 +1926,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) min(sizeof(fsa_dev_ptr[cid].devname), sizeof(scsicmd->request->rq_disk->disk_name) + 1)); - return aac_read(scsicmd, cid); + return aac_read(scsicmd); case WRITE_6: case WRITE_10: @@ -1934,11 +1934,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) case WRITE_16: if (dev->in_reset) return -1; - return aac_write(scsicmd, cid); + return aac_write(scsicmd); case SYNCHRONIZE_CACHE: /* Issue FIB to tell Firmware to flush it's cache */ - return aac_synchronize(scsicmd, cid); + return aac_synchronize(scsicmd); default: /* -- cgit v1.2.3-70-g09d2 From 03d4433721880bf1972c924b168e4e1dd3c59d53 Mon Sep 17 00:00:00 2001 From: Mark Haverkamp Date: Thu, 15 Mar 2007 10:27:45 -0700 Subject: [SCSI] aacraid: Improved error handling Received from Mark Salyzyn, This set of fixes improve error handling stability of the driver. A popular manifestation of the problems is an NULL pointer reference in the interrupt handler when referencing portions of the scsi command context, or in the scsi_done handling when an offlined device is referenced. The aacraid driver currently does not get notification of orphaned command completions due to devices going offline. The driver also fails to handle the commands that are finished by the error handler, and thus can complete again later at the hands of the adapter causing situations of completion of an invalid scsi command context. Test Unit Ready calls abort assuming that the abort was successful, but are not, and thus when the interrupt from the adapter occurs, they reference invalid command contexts. We add in a TIMED_OUT flag to inform the aacraid FIB context that the interrupt service should merely release the driver resources and not complete the command up. We take advantage of this with the abort handler as well for select abortable commands. And we detect and react if a command that can not be aborted is currently still outstanding to the controller when reissued by the retry mechanism. Signed-off-by: Mark Haverkamp Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 51 +++++++++++++++++++++++++++++++-- drivers/scsi/aacraid/aacraid.h | 1 - drivers/scsi/aacraid/commsup.c | 23 ++++++--------- drivers/scsi/aacraid/dpcsup.c | 24 ++++++++-------- drivers/scsi/aacraid/linit.c | 64 +++++++++++++++++++++++++++++++++++++++--- 5 files changed, 130 insertions(+), 33 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 3d21d7dd2e5..0c4e27eb652 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -172,6 +172,30 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. int expose_physicals = -1; module_param(expose_physicals, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); + + +static inline int aac_valid_context(struct scsi_cmnd *scsicmd, + struct fib *fibptr) { + struct scsi_device *device; + + if (unlikely(!scsicmd || !scsicmd->scsi_done )) { + dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")) +; + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + return 0; + } + scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + device = scsicmd->device; + if (unlikely(!device || !scsi_device_online(device))) { + dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n")); + aac_fib_complete(fibptr); + aac_fib_free(fibptr); + return 0; + } + return 1; +} + /** * aac_get_config_status - check the adapter configuration * @common: adapter to query @@ -342,6 +366,9 @@ static void get_container_name_callback(void *context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(scsicmd, fibptr)) + return; + dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); @@ -431,9 +458,14 @@ static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) static int _aac_probe_container2(void * context, struct fib * fibptr) { - struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; - struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; + struct fsa_dev_info *fsa_dev_ptr; int (*callback)(struct scsi_cmnd *); + struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; + + if (!aac_valid_context(scsicmd, fibptr)) + return 0; + + fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; scsicmd->SCp.Status = 0; if (fsa_dev_ptr) { @@ -477,6 +509,9 @@ static int _aac_probe_container1(void * context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(scsicmd, fibptr)) + return 0; + aac_fib_init(fibptr); dinfo = (struct aac_query_mount *)fib_data(fibptr); @@ -1287,6 +1322,9 @@ static void io_callback(void *context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(scsicmd, fibptr)) + return; + dev = (struct aac_dev *)scsicmd->device->host->hostdata; cid = scmd_id(scsicmd); @@ -1534,6 +1572,9 @@ static void synchronize_callback(void *context, struct fib *fibptr) cmd = context; cmd->SCp.phase = AAC_OWNER_MIDLEVEL; + if (!aac_valid_context(cmd, fibptr)) + return; + dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); BUG_ON(fibptr == NULL); @@ -2086,6 +2127,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr) scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; + + if (!aac_valid_context(scsicmd, fibptr)) + return; + dev = (struct aac_dev *)scsicmd->device->host->hostdata; BUG_ON(fibptr == NULL); diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 9ca594b33d1..2c0994b448d 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -971,7 +971,6 @@ struct aac_dev struct fib *fibs; struct fib *free_fib; - struct fib *timeout_fib; spinlock_t fib_lock; struct aac_queue_block *queues; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index c933df30f58..a23d7e5de5b 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -178,7 +178,6 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) * @fibptr: fib to free up * * Frees up a fib and places it on the appropriate queue - * (either free or timed out) */ void aac_fib_free(struct fib *fibptr) @@ -186,19 +185,15 @@ void aac_fib_free(struct fib *fibptr) unsigned long flags; spin_lock_irqsave(&fibptr->dev->fib_lock, flags); - if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) { + if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) aac_config.fib_timeouts++; - fibptr->next = fibptr->dev->timeout_fib; - fibptr->dev->timeout_fib = fibptr; - } else { - if (fibptr->hw_fib_va->header.XferState != 0) { - printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", - (void*)fibptr, - le32_to_cpu(fibptr->hw_fib_va->header.XferState)); - } - fibptr->next = fibptr->dev->free_fib; - fibptr->dev->free_fib = fibptr; - } + if (fibptr->hw_fib_va->header.XferState != 0) { + printk(KERN_WARNING "aac_fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", + (void*)fibptr, + le32_to_cpu(fibptr->hw_fib_va->header.XferState)); + } + fibptr->next = fibptr->dev->free_fib; + fibptr->dev->free_fib = fibptr; spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags); } diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index 26f4d563d95..4e53f9db1b2 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -84,11 +84,13 @@ unsigned int aac_response_normal(struct aac_queue * q) * continue. The caller has already been notified that * the fib timed out. */ - if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) - dev->queues->queue[AdapNormCmdQueue].numpending--; - else { - printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); - printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); + dev->queues->queue[AdapNormCmdQueue].numpending--; + + if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { + spin_unlock_irqrestore(q->lock, flags); + aac_fib_complete(fib); + aac_fib_free(fib); + spin_lock_irqsave(q->lock, flags); continue; } spin_unlock_irqrestore(q->lock, flags); @@ -281,14 +283,14 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index) * continue. The caller has already been notified that * the fib timed out. */ - if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { - printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); - printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib); + dev->queues->queue[AdapNormCmdQueue].numpending--; + + if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { + aac_fib_complete(fib); + aac_fib_free(fib); return 0; } - dev->queues->queue[AdapNormCmdQueue].numpending--; - if (fast) { /* * Doctor the fib diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 0f948c2fb60..3cf3f6472e9 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -5,7 +5,7 @@ * based on the old aacraid driver that is.. * Adaptec aacraid device driver for Linux. * - * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) + * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -247,6 +247,19 @@ static struct aac_driver_ident aac_drivers[] = { static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { + struct Scsi_Host *host = cmd->device->host; + struct aac_dev *dev = (struct aac_dev *)host->hostdata; + u32 count = 0; + cmd->scsi_done = done; + for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct fib * fib = &dev->fibs[count]; + struct scsi_cmnd * command; + if (fib->hw_fib_va->header.XferState && + ((command = fib->callback_data)) && + (command == cmd) && + (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) + return 0; /* Already owned by Adapter */ + } cmd->scsi_done = done; cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); @@ -446,6 +459,40 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) return aac_do_ioctl(dev, cmd, arg); } +static int aac_eh_abort(struct scsi_cmnd* cmd) +{ + struct Scsi_Host * host = cmd->device->host; + struct aac_dev * aac = (struct aac_dev *)host->hostdata; + int count; + int ret = FAILED; + + printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n", + AAC_DRIVERNAME, + cmd->device->host->host_no, sdev_channel(cmd->device), + sdev_id(cmd->device), cmd->device->lun); + switch (cmd->cmnd[0]) { + case SERVICE_ACTION_IN: + if (!(aac->raw_io_interface) || + !(aac->raw_io_64) || + ((cmd->cmnd[1] & 0x1f) != SAI_READ_CAPACITY_16)) + break; + case INQUIRY: + case READ_CAPACITY: + case TEST_UNIT_READY: + /* Mark associated FIB to not complete, eh handler does this */ + for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct fib * fib = &aac->fibs[count]; + if (fib->hw_fib_va->header.XferState && + (fib->callback_data == cmd)) { + fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; + cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; + ret = SUCCESS; + } + } + } + return ret; +} + /* * aac_eh_reset - Reset command handling * @scsi_cmd: SCSI command block causing the reset @@ -457,12 +504,20 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) struct Scsi_Host * host = dev->host; struct scsi_cmnd * command; int count; - struct aac_dev * aac; + struct aac_dev * aac = (struct aac_dev *)host->hostdata; unsigned long flags; + /* Mark the associated FIB to not complete, eh handler does this */ + for (count = 0; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { + struct fib * fib = &aac->fibs[count]; + if (fib->hw_fib_va->header.XferState && + (fib->callback_data == cmd)) { + fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT; + cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER; + } + } printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n", AAC_DRIVERNAME); - aac = (struct aac_dev *)host->hostdata; if ((count = aac_check_health(aac))) return count; @@ -496,7 +551,7 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) ssleep(1); } printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); - return -ETIMEDOUT; + return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */ } /** @@ -796,6 +851,7 @@ static struct scsi_host_template aac_driver_template = { .bios_param = aac_biosparm, .shost_attrs = aac_attrs, .slave_configure = aac_slave_configure, + .eh_abort_handler = aac_eh_abort, .eh_host_reset_handler = aac_eh_reset, .can_queue = AAC_NUM_IO_FIB, .this_id = MAXIMUM_NUM_CONTAINERS, -- cgit v1.2.3-70-g09d2 From 20235f35221472f1a127a5d5414f11091eb0a845 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 21 Mar 2007 13:22:56 -0400 Subject: [SCSI] aacraid: check buffer address in aac_internal_transfer Captured a panic on an older kernel where an application issuing commands via sg was sending requests that lacked a request_buffer, thus the buffer pointer used in aac_internal_transer was NULL. The application was fixed closing the issue, but felt it was advised to immunize the driver against the eventuality. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 0c4e27eb652..f9deab686dc 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -350,8 +350,9 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne buf = scsicmd->request_buffer; transfer_len = min(scsicmd->request_bufflen, len + offset); } - - memcpy(buf + offset, data, transfer_len - offset); + transfer_len -= offset; + if (buf && transfer_len) + memcpy(buf + offset, data, transfer_len); if (scsicmd->use_sg) kunmap_atomic(buf - sg->offset, KM_IRQ0); -- cgit v1.2.3-70-g09d2 From 802ae2f05b646c1e5f9e33cfe4c80cfa1452a0e3 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 21 Mar 2007 13:49:47 -0400 Subject: [SCSI] aacraid: cleanup and version stamp driver There is some residual cleanup of the last series of patches and the need to bump the revision number to draw the line in the sand. The cmd->SCp.phase is set in the aac_valid_context routine, then set again to the same value following it's return. The cmd->scsi_done is set twice in the aac_queuecommand routine. Free up the scsidev FILO in aac_probe_container as it is not needed further down the function in any case. Improve the efficiency of the abort handler kernel print parameters. Bump revision number of driver to approximate the equivalent in the Adaptec supplied version. Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 6 +----- drivers/scsi/aacraid/aacraid.h | 4 ++-- drivers/scsi/aacraid/linit.c | 7 +++---- 3 files changed, 6 insertions(+), 11 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index f9deab686dc..fc16fe0dfa8 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -365,7 +365,6 @@ static void get_container_name_callback(void *context, struct fib * fibptr) struct scsi_cmnd * scsicmd; scsicmd = (struct scsi_cmnd *) context; - scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(scsicmd, fibptr)) return; @@ -629,9 +628,9 @@ int aac_probe_container(struct aac_dev *dev, int cid) if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) while (scsicmd->device == scsidev) schedule(); + kfree(scsidev); status = scsicmd->SCp.Status; kfree(scsicmd); - kfree(scsidev); return status; } @@ -1321,7 +1320,6 @@ static void io_callback(void *context, struct fib * fibptr) u32 cid; scsicmd = (struct scsi_cmnd *) context; - scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(scsicmd, fibptr)) return; @@ -1571,7 +1569,6 @@ static void synchronize_callback(void *context, struct fib *fibptr) struct scsi_cmnd *cmd; cmd = context; - cmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(cmd, fibptr)) return; @@ -2127,7 +2124,6 @@ static void aac_srb_callback(void *context, struct fib * fibptr) struct scsi_cmnd *scsicmd; scsicmd = (struct scsi_cmnd *) context; - scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; if (!aac_valid_context(scsicmd, fibptr)) return; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 2c0994b448d..1771851db6e 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -12,8 +12,8 @@ *----------------------------------------------------------------------------*/ #ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 2423 -# define AAC_DRIVER_BRANCH "-mh3" +# define AAC_DRIVER_BUILD 2437 +# define AAC_DRIVER_BRANCH "-mh4" #endif #define MAXIMUM_NUM_CONTAINERS 32 diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 3cf3f6472e9..a5950c17d62 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -260,7 +260,6 @@ static int aac_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) return 0; /* Already owned by Adapter */ } - cmd->scsi_done = done; cmd->SCp.phase = AAC_OWNER_LOWLEVEL; return (aac_scsi_cmd(cmd) ? FAILED : 0); } @@ -461,15 +460,15 @@ static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) static int aac_eh_abort(struct scsi_cmnd* cmd) { - struct Scsi_Host * host = cmd->device->host; + struct scsi_device * dev = cmd->device; + struct Scsi_Host * host = dev->host; struct aac_dev * aac = (struct aac_dev *)host->hostdata; int count; int ret = FAILED; printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n", AAC_DRIVERNAME, - cmd->device->host->host_no, sdev_channel(cmd->device), - sdev_id(cmd->device), cmd->device->lun); + host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun); switch (cmd->cmnd[0]) { case SERVICE_ACTION_IN: if (!(aac->raw_io_interface) || -- cgit v1.2.3-70-g09d2 From a45c863f02c808107172b4b2975e1130c7da66d6 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Wed, 28 Mar 2007 13:44:54 -0400 Subject: [SCSI] aacraid: fix print of Firmware Build Date and add TSID The Adapter build date that is to be printed on instantiation was not displayed as a result of the supplemental adapter information structure not being in sync with the Firmware; the driver took an early test cycle version that had a miss-sized padded region at the head and the structure was not re-checked at the end of qualification. The Build Date was not a priority and is merely a cosmetic enhancement, and the wrong location for the start of the structure member would not induce any side-effect problems. We updated the structure to match the actual format, and added the TSID (Tech Support Identification) value print, should it be present, to the adapter instantiation announcements during driver load. This later enhancement should improve the relationship between Service folk & Tech Support if the printed value of the TSID found it's way into the circular file labeled G... Neither of these values show in sysfs (yet). Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 6 ++++++ drivers/scsi/aacraid/aacraid.h | 19 +++++++++++++++++-- 2 files changed, 23 insertions(+), 2 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index fc16fe0dfa8..31ac9f56cd1 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -1194,6 +1194,12 @@ int aac_get_adapter_info(struct aac_dev* dev) printk(KERN_INFO "%s%d: serial %x\n", dev->name, dev->id, le32_to_cpu(dev->adapter_info.serial[0])); + if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) { + printk(KERN_INFO "%s%d: TSID %.*s\n", + dev->name, dev->id, + (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid), + dev->supplement_adapter_info.VpdInfo.Tsid); + } } dev->nondasd_support = 0; diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 12cad1f3020..45ca3e80161 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -843,10 +843,25 @@ struct aac_supplement_adapter_info __le32 Version; __le32 FeatureBits; u8 SlotNumber; - u8 ReservedPad0[0]; + u8 ReservedPad0[3]; u8 BuildDate[12]; __le32 CurrentNumberPorts; - __le32 ReservedGrowth[24]; + struct { + u8 AssemblyPn[8]; + u8 FruPn[8]; + u8 BatteryFruPn[8]; + u8 EcVersionString[8]; + u8 Tsid[12]; + } VpdInfo; + __le32 FlashFirmwareRevision; + __le32 FlashFirmwareBuild; + __le32 RaidTypeMorphOptions; + __le32 FlashFirmwareBootRevision; + __le32 FlashFirmwareBootBuild; + u8 MfgPcbaSerialNo[12]; + u8 MfgWWNName[8]; + __le32 MoreFeatureBits; + __le32 ReservedGrowth[1]; }; #define AAC_FEATURE_FALCON 0x00000010 #define AAC_SIS_VERSION_V3 3 -- cgit v1.2.3-70-g09d2 From 4def7fa11208f779f22e6ba7344370b0220d3350 Mon Sep 17 00:00:00 2001 From: "Salyzyn, Mark" Date: Fri, 13 Apr 2007 08:35:25 -0400 Subject: [SCSI] aacraid: fix aacraid not finding device Thanks for the help from Steve Fox and Duane Cox investigating this issue, I'd like to report that we found the problem. The issue is with the patch Steve Fox isolated below, by not accommodating older adapters properly and issuing a command they do not support when retrieving storage parameters about the arrays. This simple patch resolves the problem (and more accurately mimics the logic of the original code before the patch). Signed-off-by: Mark Salyzyn Signed-off-by: James Bottomley --- drivers/scsi/aacraid/aachba.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/scsi/aacraid/aachba.c') diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 31ac9f56cd1..1e82c69b36b 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -503,8 +503,7 @@ static int _aac_probe_container1(void * context, struct fib * fibptr) dresp = (struct aac_mount *) fib_data(fibptr); dresp->mnt[0].capacityhigh = 0; if ((le32_to_cpu(dresp->status) != ST_OK) || - ((le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && - (le32_to_cpu(dresp->mnt[0].state) == FSCS_HIDDEN))) + (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) return _aac_probe_container2(context, fibptr); scsicmd = (struct scsi_cmnd *) context; scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; -- cgit v1.2.3-70-g09d2