aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aacraid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r--drivers/scsi/aacraid/aachba.c337
-rw-r--r--drivers/scsi/aacraid/aacraid.h6
-rw-r--r--drivers/scsi/aacraid/comminit.c6
-rw-r--r--drivers/scsi/aacraid/commsup.c3
-rw-r--r--drivers/scsi/aacraid/linit.c324
-rw-r--r--drivers/scsi/aacraid/src.c2
6 files changed, 412 insertions, 266 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index a1a2c71e1626..af3e4d3f9735 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -594,6 +594,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
aac_fib_init(cmd_fibcontext);
dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
dinfo->command = cpu_to_le32(VM_ContainerConfig);
dinfo->type = cpu_to_le32(CT_READ_NAME);
@@ -611,10 +612,8 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
printk(KERN_WARNING "aac_get_container_name: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
@@ -700,13 +699,13 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
int status;
dresp = (struct aac_mount *) fib_data(fibptr);
- if (!(fibptr->dev->supplement_adapter_info.supported_options2 &
- AAC_OPTION_VARIABLE_BLOCK_SIZE))
+ if (!aac_supports_2T(fibptr->dev)) {
dresp->mnt[0].capacityhigh = 0;
- if ((le32_to_cpu(dresp->status) != ST_OK) ||
- (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
- _aac_probe_container2(context, fibptr);
- return;
+ if ((le32_to_cpu(dresp->status) == ST_OK) &&
+ (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
+ _aac_probe_container2(context, fibptr);
+ return;
+ }
}
scsicmd = (struct scsi_cmnd *) context;
@@ -725,6 +724,7 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
dinfo->count = cpu_to_le32(scmd_id(scsicmd));
dinfo->type = cpu_to_le32(FT_FILESYS);
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_fib_send(ContainerCommand,
fibptr,
@@ -736,9 +736,7 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS)
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
- else if (status < 0) {
+ if (status < 0 && status != -EINPROGRESS) {
/* Inherit results from VM_NameServe, if any */
dresp->status = cpu_to_le32(ST_OK);
_aac_probe_container2(context, fibptr);
@@ -766,6 +764,7 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru
dinfo->count = cpu_to_le32(scmd_id(scsicmd));
dinfo->type = cpu_to_le32(FT_FILESYS);
scsicmd->SCp.ptr = (char *)callback;
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_fib_send(ContainerCommand,
fibptr,
@@ -777,10 +776,9 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
+
if (status < 0) {
scsicmd->SCp.ptr = NULL;
aac_fib_complete(fibptr);
@@ -1126,6 +1124,7 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
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));
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_fib_send(ContainerCommand,
cmd_fibcontext,
@@ -1138,10 +1137,8 @@ static int aac_get_container_serial(struct scsi_cmnd * scsicmd)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
printk(KERN_WARNING "aac_get_container_serial: aac_fib_send failed with status: %d.\n", status);
aac_fib_complete(cmd_fibcontext);
@@ -2335,16 +2332,14 @@ static int aac_read(struct scsi_cmnd * scsicmd)
* Alocate and initialize a Fib
*/
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
-
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_read(cmd_fibcontext, scsicmd, lba, count);
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
printk(KERN_WARNING "aac_read: aac_fib_send failed with status: %d.\n", status);
/*
@@ -2429,16 +2424,14 @@ static int aac_write(struct scsi_cmnd * scsicmd)
* Allocate and initialize a Fib then setup a BlockWrite command
*/
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
-
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua);
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
printk(KERN_WARNING "aac_write: aac_fib_send failed with status: %d\n", status);
/*
@@ -2588,6 +2581,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd));
synchronizecmd->count =
cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data));
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
/*
* Now send the Fib to the adapter
@@ -2603,10 +2597,8 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
printk(KERN_WARNING
"aac_synchronize: aac_fib_send failed with status: %d.\n", status);
@@ -2666,6 +2658,7 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd)
pmcmd->cid = cpu_to_le32(sdev_id(sdev));
pmcmd->parm = (scsicmd->cmnd[1] & 1) ?
cpu_to_le32(CT_PM_UNIT_IMMEDIATE) : 0;
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
/*
* Now send the Fib to the adapter
@@ -2681,10 +2674,8 @@ static int aac_start_stop(struct scsi_cmnd *scsicmd)
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
aac_fib_complete(cmd_fibcontext);
aac_fib_free(cmd_fibcontext);
@@ -3692,16 +3683,14 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
* Allocate and initialize a Fib then setup a BlockWrite command
*/
cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
-
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_scsi(cmd_fibcontext, scsicmd);
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);
aac_fib_complete(cmd_fibcontext);
@@ -3739,15 +3728,14 @@ static int aac_send_hba_fib(struct scsi_cmnd *scsicmd)
if (!cmd_fibcontext)
return -1;
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
status = aac_adapter_hba(cmd_fibcontext, scsicmd);
/*
* Check that the command queued to the controller
*/
- if (status == -EINPROGRESS) {
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ if (status == -EINPROGRESS)
return 0;
- }
pr_warn("aac_hba_cmd_req: aac_fib_send failed with status: %d\n",
status);
@@ -3763,6 +3751,8 @@ static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg)
struct aac_dev *dev;
unsigned long byte_count = 0;
int nseg;
+ struct scatterlist *sg;
+ int i;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
@@ -3771,32 +3761,29 @@ static long aac_build_sg(struct scsi_cmnd *scsicmd, struct sgmap *psg)
psg->sg[0].count = 0;
nseg = scsi_dma_map(scsicmd);
- if (nseg < 0)
+ if (nseg <= 0)
return nseg;
- if (nseg) {
- struct scatterlist *sg;
- int i;
- psg->count = cpu_to_le32(nseg);
+ psg->count = cpu_to_le32(nseg);
- scsi_for_each_sg(scsicmd, sg, nseg, i) {
- psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
- psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
- byte_count += sg_dma_len(sg);
- }
- /* hba wants the size to be exact */
- if (byte_count > scsi_bufflen(scsicmd)) {
- u32 temp = le32_to_cpu(psg->sg[i-1].count) -
- (byte_count - scsi_bufflen(scsicmd));
- psg->sg[i-1].count = cpu_to_le32(temp);
- byte_count = scsi_bufflen(scsicmd);
- }
- /* Check for command underflow */
- if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
- printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
- byte_count, scsicmd->underflow);
- }
+ scsi_for_each_sg(scsicmd, sg, nseg, i) {
+ psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
+ psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
+ byte_count += sg_dma_len(sg);
}
+ /* hba wants the size to be exact */
+ if (byte_count > scsi_bufflen(scsicmd)) {
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsi_bufflen(scsicmd));
+ psg->sg[i-1].count = cpu_to_le32(temp);
+ byte_count = scsi_bufflen(scsicmd);
+ }
+ /* Check for command underflow */
+ if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
+ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+ byte_count, scsicmd->underflow);
+ }
+
return byte_count;
}
@@ -3807,6 +3794,8 @@ static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg)
unsigned long byte_count = 0;
u64 addr;
int nseg;
+ struct scatterlist *sg;
+ int i;
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
// Get rid of old data
@@ -3816,34 +3805,31 @@ static long aac_build_sg64(struct scsi_cmnd *scsicmd, struct sgmap64 *psg)
psg->sg[0].count = 0;
nseg = scsi_dma_map(scsicmd);
- if (nseg < 0)
+ if (nseg <= 0)
return nseg;
- if (nseg) {
- struct scatterlist *sg;
- int i;
-
- scsi_for_each_sg(scsicmd, sg, nseg, i) {
- int count = sg_dma_len(sg);
- addr = sg_dma_address(sg);
- psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
- psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
- psg->sg[i].count = cpu_to_le32(count);
- byte_count += count;
- }
- psg->count = cpu_to_le32(nseg);
- /* hba wants the size to be exact */
- if (byte_count > scsi_bufflen(scsicmd)) {
- u32 temp = le32_to_cpu(psg->sg[i-1].count) -
- (byte_count - scsi_bufflen(scsicmd));
- psg->sg[i-1].count = cpu_to_le32(temp);
- byte_count = scsi_bufflen(scsicmd);
- }
- /* Check for command underflow */
- if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
- printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
- byte_count, scsicmd->underflow);
- }
+
+ scsi_for_each_sg(scsicmd, sg, nseg, i) {
+ int count = sg_dma_len(sg);
+ addr = sg_dma_address(sg);
+ psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
+ psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
+ psg->sg[i].count = cpu_to_le32(count);
+ byte_count += count;
+ }
+ psg->count = cpu_to_le32(nseg);
+ /* hba wants the size to be exact */
+ if (byte_count > scsi_bufflen(scsicmd)) {
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsi_bufflen(scsicmd));
+ psg->sg[i-1].count = cpu_to_le32(temp);
+ byte_count = scsi_bufflen(scsicmd);
}
+ /* Check for command underflow */
+ if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
+ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+ byte_count, scsicmd->underflow);
+ }
+
return byte_count;
}
@@ -3851,6 +3837,8 @@ static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg)
{
unsigned long byte_count = 0;
int nseg;
+ struct scatterlist *sg;
+ int i;
// Get rid of old data
psg->count = 0;
@@ -3862,37 +3850,34 @@ static long aac_build_sgraw(struct scsi_cmnd *scsicmd, struct sgmapraw *psg)
psg->sg[0].flags = 0;
nseg = scsi_dma_map(scsicmd);
- if (nseg < 0)
+ if (nseg <= 0)
return nseg;
- if (nseg) {
- struct scatterlist *sg;
- int i;
-
- scsi_for_each_sg(scsicmd, sg, nseg, i) {
- int count = sg_dma_len(sg);
- u64 addr = sg_dma_address(sg);
- psg->sg[i].next = 0;
- psg->sg[i].prev = 0;
- psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
- psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
- psg->sg[i].count = cpu_to_le32(count);
- psg->sg[i].flags = 0;
- byte_count += count;
- }
- psg->count = cpu_to_le32(nseg);
- /* hba wants the size to be exact */
- if (byte_count > scsi_bufflen(scsicmd)) {
- u32 temp = le32_to_cpu(psg->sg[i-1].count) -
- (byte_count - scsi_bufflen(scsicmd));
- psg->sg[i-1].count = cpu_to_le32(temp);
- byte_count = scsi_bufflen(scsicmd);
- }
- /* Check for command underflow */
- if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
- printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
- byte_count, scsicmd->underflow);
- }
+
+ scsi_for_each_sg(scsicmd, sg, nseg, i) {
+ int count = sg_dma_len(sg);
+ u64 addr = sg_dma_address(sg);
+ psg->sg[i].next = 0;
+ psg->sg[i].prev = 0;
+ psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32));
+ psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+ psg->sg[i].count = cpu_to_le32(count);
+ psg->sg[i].flags = 0;
+ byte_count += count;
+ }
+ psg->count = cpu_to_le32(nseg);
+ /* hba wants the size to be exact */
+ if (byte_count > scsi_bufflen(scsicmd)) {
+ u32 temp = le32_to_cpu(psg->sg[i-1].count) -
+ (byte_count - scsi_bufflen(scsicmd));
+ psg->sg[i-1].count = cpu_to_le32(temp);
+ byte_count = scsi_bufflen(scsicmd);
+ }
+ /* Check for command underflow */
+ if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
+ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+ byte_count, scsicmd->underflow);
}
+
return byte_count;
}
@@ -3901,75 +3886,77 @@ static long aac_build_sgraw2(struct scsi_cmnd *scsicmd,
{
unsigned long byte_count = 0;
int nseg;
+ struct scatterlist *sg;
+ int i, conformable = 0;
+ u32 min_size = PAGE_SIZE, cur_size;
nseg = scsi_dma_map(scsicmd);
- if (nseg < 0)
+ if (nseg <= 0)
return nseg;
- if (nseg) {
- struct scatterlist *sg;
- int i, conformable = 0;
- u32 min_size = PAGE_SIZE, cur_size;
-
- scsi_for_each_sg(scsicmd, sg, nseg, i) {
- int count = sg_dma_len(sg);
- u64 addr = sg_dma_address(sg);
-
- BUG_ON(i >= sg_max);
- rio2->sge[i].addrHigh = cpu_to_le32((u32)(addr>>32));
- rio2->sge[i].addrLow = cpu_to_le32((u32)(addr & 0xffffffff));
- cur_size = cpu_to_le32(count);
- rio2->sge[i].length = cur_size;
- rio2->sge[i].flags = 0;
- if (i == 0) {
- conformable = 1;
- rio2->sgeFirstSize = cur_size;
- } else if (i == 1) {
- rio2->sgeNominalSize = cur_size;
+
+ scsi_for_each_sg(scsicmd, sg, nseg, i) {
+ int count = sg_dma_len(sg);
+ u64 addr = sg_dma_address(sg);
+
+ BUG_ON(i >= sg_max);
+ rio2->sge[i].addrHigh = cpu_to_le32((u32)(addr>>32));
+ rio2->sge[i].addrLow = cpu_to_le32((u32)(addr & 0xffffffff));
+ cur_size = cpu_to_le32(count);
+ rio2->sge[i].length = cur_size;
+ rio2->sge[i].flags = 0;
+ if (i == 0) {
+ conformable = 1;
+ rio2->sgeFirstSize = cur_size;
+ } else if (i == 1) {
+ rio2->sgeNominalSize = cur_size;
+ min_size = cur_size;
+ } else if ((i+1) < nseg && cur_size != rio2->sgeNominalSize) {
+ conformable = 0;
+ if (cur_size < min_size)
min_size = cur_size;
- } else if ((i+1) < nseg && cur_size != rio2->sgeNominalSize) {
- conformable = 0;
- if (cur_size < min_size)
- min_size = cur_size;
- }
- byte_count += count;
}
+ byte_count += count;
+ }
- /* hba wants the size to be exact */
- if (byte_count > scsi_bufflen(scsicmd)) {
- u32 temp = le32_to_cpu(rio2->sge[i-1].length) -
- (byte_count - scsi_bufflen(scsicmd));
- rio2->sge[i-1].length = cpu_to_le32(temp);
- byte_count = scsi_bufflen(scsicmd);
- }
+ /* hba wants the size to be exact */
+ if (byte_count > scsi_bufflen(scsicmd)) {
+ u32 temp = le32_to_cpu(rio2->sge[i-1].length) -
+ (byte_count - scsi_bufflen(scsicmd));
+ rio2->sge[i-1].length = cpu_to_le32(temp);
+ byte_count = scsi_bufflen(scsicmd);
+ }
- rio2->sgeCnt = cpu_to_le32(nseg);
- rio2->flags |= cpu_to_le16(RIO2_SG_FORMAT_IEEE1212);
- /* not conformable: evaluate required sg elements */
- if (!conformable) {
- int j, nseg_new = nseg, err_found;
- for (i = min_size / PAGE_SIZE; i >= 1; --i) {
- err_found = 0;
- nseg_new = 2;
- for (j = 1; j < nseg - 1; ++j) {
- if (rio2->sge[j].length % (i*PAGE_SIZE)) {
- err_found = 1;
- break;
- }
- nseg_new += (rio2->sge[j].length / (i*PAGE_SIZE));
- }
- if (!err_found)
+ rio2->sgeCnt = cpu_to_le32(nseg);
+ rio2->flags |= cpu_to_le16(RIO2_SG_FORMAT_IEEE1212);
+ /* not conformable: evaluate required sg elements */
+ if (!conformable) {
+ int j, nseg_new = nseg, err_found;
+ for (i = min_size / PAGE_SIZE; i >= 1; --i) {
+ err_found = 0;
+ nseg_new = 2;
+ for (j = 1; j < nseg - 1; ++j) {
+ if (rio2->sge[j].length % (i*PAGE_SIZE)) {
+ err_found = 1;
break;
+ }
+ nseg_new += (rio2->sge[j].length / (i*PAGE_SIZE));
}
- if (i > 0 && nseg_new <= sg_max)
- aac_convert_sgraw2(rio2, i, nseg, nseg_new);
- } else
- rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT);
+ if (!err_found)
+ break;
+ }
+ if (i > 0 && nseg_new <= sg_max) {
+ int ret = aac_convert_sgraw2(rio2, i, nseg, nseg_new);
- /* Check for command underflow */
- if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
- printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
- byte_count, scsicmd->underflow);
+ if (ret < 0)
+ return ret;
}
+ } else
+ rio2->flags |= cpu_to_le16(RIO2_SGL_CONFORMANT);
+
+ /* Check for command underflow */
+ if (scsicmd->underflow && (byte_count < scsicmd->underflow)) {
+ printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
+ byte_count, scsicmd->underflow);
}
return byte_count;
@@ -3986,7 +3973,7 @@ static int aac_convert_sgraw2(struct aac_raw_io2 *rio2, int pages, int nseg, int
sge = kmalloc(nseg_new * sizeof(struct sge_ieee1212), GFP_ATOMIC);
if (sge == NULL)
- return -1;
+ return -ENOMEM;
for (i = 1, pos = 1; i < nseg-1; ++i) {
for (j = 0; j < rio2->sge[i].length / (pages * PAGE_SIZE); ++j) {
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index ee2667e20e42..403a639574e5 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1723,6 +1723,7 @@ struct aac_dev
#define FIB_CONTEXT_FLAG_FASTRESP (0x00000008)
#define FIB_CONTEXT_FLAG_NATIVE_HBA (0x00000010)
#define FIB_CONTEXT_FLAG_NATIVE_HBA_TMF (0x00000020)
+#define FIB_CONTEXT_FLAG_SCSI_CMD (0x00000040)
/*
* Define the command values
@@ -2700,6 +2701,11 @@ static inline int aac_is_src(struct aac_dev *dev)
return 0;
}
+static inline int aac_supports_2T(struct aac_dev *dev)
+{
+ return (dev->adapter_info.options & AAC_OPT_NEW_COMM_64);
+}
+
char * get_container_type(unsigned type);
extern int numacb;
extern char aac_driver_version[];
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 9ee025b1d0e0..97d269f16888 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -520,9 +520,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
dev->raw_io_64 = 1;
dev->sync_mode = aac_sync_mode;
if (dev->a_ops.adapter_comm &&
- (status[1] & AAC_OPT_NEW_COMM)) {
- dev->comm_interface = AAC_COMM_MESSAGE;
- dev->raw_io_interface = 1;
+ (status[1] & AAC_OPT_NEW_COMM)) {
+ dev->comm_interface = AAC_COMM_MESSAGE;
+ dev->raw_io_interface = 1;
if ((status[1] & AAC_OPT_NEW_COMM_TYPE1)) {
/* driver supports TYPE1 (Tupelo) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 1c617ccfaf12..dfe8e70f8d99 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -770,7 +770,8 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
/* bit1 of request_id must be 0 */
hbacmd->request_id =
cpu_to_le32((((u32)(fibptr - dev->fibs)) << 2) + 1);
- } else
+ fibptr->flags |= FIB_CONTEXT_FLAG_SCSI_CMD;
+ } else if (command != HBA_IU_TYPE_SCSI_TM_REQ)
return -EINVAL;
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 0f277df73af0..62beb2596466 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -814,111 +814,229 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
return ret;
}
+static u8 aac_eh_tmf_lun_reset_fib(struct aac_hba_map_info *info,
+ struct fib *fib, u64 tmf_lun)
+{
+ struct aac_hba_tm_req *tmf;
+ u64 address;
+
+ /* start a HBA_TMF_LUN_RESET TMF request */
+ tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
+ memset(tmf, 0, sizeof(*tmf));
+ tmf->tmf = HBA_TMF_LUN_RESET;
+ tmf->it_nexus = info->rmw_nexus;
+ int_to_scsilun(tmf_lun, (struct scsi_lun *)tmf->lun);
+
+ address = (u64)fib->hw_error_pa;
+ tmf->error_ptr_hi = cpu_to_le32
+ ((u32)(address >> 32));
+ tmf->error_ptr_lo = cpu_to_le32
+ ((u32)(address & 0xffffffff));
+ tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
+ fib->hbacmd_size = sizeof(*tmf);
+
+ return HBA_IU_TYPE_SCSI_TM_REQ;
+}
+
+static u8 aac_eh_tmf_hard_reset_fib(struct aac_hba_map_info *info,
+ struct fib *fib)
+{
+ struct aac_hba_reset_req *rst;
+ u64 address;
+
+ /* already tried, start a hard reset now */
+ rst = (struct aac_hba_reset_req *)fib->hw_fib_va;
+ memset(rst, 0, sizeof(*rst));
+ rst->it_nexus = info->rmw_nexus;
+
+ address = (u64)fib->hw_error_pa;
+ rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
+ rst->error_ptr_lo = cpu_to_le32
+ ((u32)(address & 0xffffffff));
+ rst->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
+ fib->hbacmd_size = sizeof(*rst);
+
+ return HBA_IU_TYPE_SATA_REQ;
+}
+
+void aac_tmf_callback(void *context, struct fib *fibptr)
+{
+ struct aac_hba_resp *err =
+ &((struct aac_native_hba *)fibptr->hw_fib_va)->resp.err;
+ struct aac_hba_map_info *info = context;
+ int res;
+
+ switch (err->service_response) {
+ case HBA_RESP_SVCRES_TMF_REJECTED:
+ res = -1;
+ break;
+ case HBA_RESP_SVCRES_TMF_LUN_INVALID:
+ res = 0;
+ break;
+ case HBA_RESP_SVCRES_TMF_COMPLETE:
+ case HBA_RESP_SVCRES_TMF_SUCCEEDED:
+ res = 0;
+ break;
+ default:
+ res = -2;
+ break;
+ }
+ aac_fib_complete(fibptr);
+
+ info->reset_state = res;
+}
+
/*
- * aac_eh_reset - Reset command handling
+ * aac_eh_dev_reset - Device reset command handling
* @scsi_cmd: SCSI command block causing the reset
*
*/
-static int aac_eh_reset(struct scsi_cmnd* cmd)
+static int aac_eh_dev_reset(struct scsi_cmnd *cmd)
{
struct scsi_device * dev = cmd->device;
struct Scsi_Host * host = dev->host;
struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+ struct aac_hba_map_info *info;
int count;
u32 bus, cid;
+ struct fib *fib;
int ret = FAILED;
- int status = 0;
- __le32 supported_options2 = 0;
- bool is_mu_reset;
- bool is_ignore_reset;
- bool is_doorbell_reset;
-
+ int status;
+ u8 command;
bus = aac_logical_to_phys(scmd_channel(cmd));
cid = scmd_id(cmd);
- if (bus < AAC_MAX_BUSES && cid < AAC_MAX_TARGETS &&
- aac->hba_map[bus][cid].devtype == AAC_DEVTYPE_NATIVE_RAW) {
- struct fib *fib;
- int status;
- u64 address;
- u8 command;
- pr_err("%s: Host adapter reset request. SCSI hang ?\n",
- AAC_DRIVERNAME);
+ if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS)
+ return FAILED;
- fib = aac_fib_alloc(aac);
- if (!fib)
- return ret;
+ info = &aac->hba_map[bus][cid];
+
+ if (info->devtype != AAC_DEVTYPE_NATIVE_RAW &&
+ info->reset_state > 0)
+ return FAILED;
+
+ pr_err("%s: Host adapter reset request. SCSI hang ?\n",
+ AAC_DRIVERNAME);
+
+ fib = aac_fib_alloc(aac);
+ if (!fib)
+ return ret;
+ /* start a HBA_TMF_LUN_RESET TMF request */
+ command = aac_eh_tmf_lun_reset_fib(info, fib, dev->lun);
- if (aac->hba_map[bus][cid].reset_state == 0) {
- struct aac_hba_tm_req *tmf;
-
- /* start a HBA_TMF_LUN_RESET TMF request */
- tmf = (struct aac_hba_tm_req *)fib->hw_fib_va;
- memset(tmf, 0, sizeof(*tmf));
- tmf->tmf = HBA_TMF_LUN_RESET;
- tmf->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
- tmf->lun[1] = cmd->device->lun;
-
- address = (u64)fib->hw_error_pa;
- tmf->error_ptr_hi = cpu_to_le32
- ((u32)(address >> 32));
- tmf->error_ptr_lo = cpu_to_le32
- ((u32)(address & 0xffffffff));
- tmf->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
- fib->hbacmd_size = sizeof(*tmf);
-
- command = HBA_IU_TYPE_SCSI_TM_REQ;
- aac->hba_map[bus][cid].reset_state++;
- } else if (aac->hba_map[bus][cid].reset_state >= 1) {
- struct aac_hba_reset_req *rst;
-
- /* already tried, start a hard reset now */
- rst = (struct aac_hba_reset_req *)fib->hw_fib_va;
- memset(rst, 0, sizeof(*rst));
- /* reset_type is already zero... */
- rst->it_nexus = aac->hba_map[bus][cid].rmw_nexus;
-
- address = (u64)fib->hw_error_pa;
- rst->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
- rst->error_ptr_lo = cpu_to_le32
- ((u32)(address & 0xffffffff));
- rst->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
- fib->hbacmd_size = sizeof(*rst);
-
- command = HBA_IU_TYPE_SATA_REQ;
- aac->hba_map[bus][cid].reset_state = 0;
+ info->reset_state = 1;
+
+ status = aac_hba_send(command, fib,
+ (fib_callback) aac_tmf_callback,
+ (void *) info);
+
+ /* Wait up to 15 seconds for completion */
+ for (count = 0; count < 15; ++count) {
+ if (info->reset_state == 0) {
+ ret = info->reset_state == 0 ? SUCCESS : FAILED;
+ break;
}
- cmd->SCp.sent_command = 0;
+ msleep(1000);
+ }
- status = aac_hba_send(command, fib,
- (fib_callback) aac_hba_callback,
- (void *) cmd);
+ return ret;
+}
- /* Wait up to 15 seconds for completion */
- for (count = 0; count < 15; ++count) {
- if (cmd->SCp.sent_command) {
- ret = SUCCESS;
- break;
- }
- msleep(1000);
+/*
+ * aac_eh_target_reset - Target reset command handling
+ * @scsi_cmd: SCSI command block causing the reset
+ *
+ */
+static int aac_eh_target_reset(struct scsi_cmnd *cmd)
+{
+ struct scsi_device * dev = cmd->device;
+ struct Scsi_Host * host = dev->host;
+ struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+ struct aac_hba_map_info *info;
+ int count;
+ u32 bus, cid;
+ int ret = FAILED;
+ struct fib *fib;
+ int status;
+ u8 command;
+
+ bus = aac_logical_to_phys(scmd_channel(cmd));
+ cid = scmd_id(cmd);
+
+ if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS)
+ return FAILED;
+
+ info = &aac->hba_map[bus][cid];
+
+ if (info->devtype != AAC_DEVTYPE_NATIVE_RAW &&
+ info->reset_state > 0)
+ return FAILED;
+
+ pr_err("%s: Host adapter reset request. SCSI hang ?\n",
+ AAC_DRIVERNAME);
+
+ fib = aac_fib_alloc(aac);
+ if (!fib)
+ return ret;
+
+
+ /* already tried, start a hard reset now */
+ command = aac_eh_tmf_hard_reset_fib(info, fib);
+
+ info->reset_state = 2;
+
+ status = aac_hba_send(command, fib,
+ (fib_callback) aac_tmf_callback,
+ (void *) info);
+
+ /* Wait up to 15 seconds for completion */
+ for (count = 0; count < 15; ++count) {
+ if (info->reset_state <= 0) {
+ ret = info->reset_state == 0 ? SUCCESS : FAILED;
+ break;
}
+ msleep(1000);
+ }
- if (ret == SUCCESS)
- goto out;
+ return ret;
+}
- } else {
+/*
+ * aac_eh_bus_reset - Bus reset command handling
+ * @scsi_cmd: SCSI command block causing the reset
+ *
+ */
+static int aac_eh_bus_reset(struct scsi_cmnd* cmd)
+{
+ struct scsi_device * dev = cmd->device;
+ struct Scsi_Host * host = dev->host;
+ struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+ int count;
+ u32 cmd_bus;
+ int status = 0;
- /* Mark the assoc. 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->flags & FIB_CONTEXT_FLAG) &&
- (fib->callback_data == cmd)) {
+ cmd_bus = aac_logical_to_phys(scmd_channel(cmd));
+ /* Mark the assoc. 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->flags & FIB_CONTEXT_FLAG) &&
+ (fib->flags & FIB_CONTEXT_FLAG_SCSI_CMD)) {
+ struct aac_hba_map_info *info;
+ u32 bus, cid;
+
+ cmd = (struct scsi_cmnd *)fib->callback_data;
+ bus = aac_logical_to_phys(scmd_channel(cmd));
+ if (bus != cmd_bus)
+ continue;
+ cid = scmd_id(cmd);
+ info = &aac->hba_map[bus][cid];
+ if (bus >= AAC_MAX_BUSES || cid >= AAC_MAX_TARGETS ||
+ info->devtype != AAC_DEVTYPE_NATIVE_RAW) {
fib->flags |= FIB_CONTEXT_FLAG_TIMED_OUT;
cmd->SCp.phase = AAC_OWNER_ERROR_HANDLER;
}
@@ -935,8 +1053,24 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
dev_err(&aac->pdev->dev, "Adapter health - %d\n", status);
count = get_num_of_incomplete_fibs(aac);
- if (count == 0)
- return SUCCESS;
+ return (count == 0) ? SUCCESS : FAILED;
+}
+
+/*
+ * aac_eh_host_reset - Host reset command handling
+ * @scsi_cmd: SCSI command block causing the reset
+ *
+ */
+int aac_eh_host_reset(struct scsi_cmnd *cmd)
+{
+ struct scsi_device * dev = cmd->device;
+ struct Scsi_Host * host = dev->host;
+ struct aac_dev * aac = (struct aac_dev *)host->hostdata;
+ int ret = FAILED;
+ __le32 supported_options2 = 0;
+ bool is_mu_reset;
+ bool is_ignore_reset;
+ bool is_doorbell_reset;
/*
* Check if reset is supported by the firmware
@@ -954,11 +1088,24 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
&& aac_check_reset
&& (aac_check_reset != -1 || !is_ignore_reset)) {
/* Bypass wait for command quiesce */
- aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET);
+ if (aac_reset_adapter(aac, 2, IOP_HWSOFT_RESET) == 0)
+ ret = SUCCESS;
+ }
+ /*
+ * Reset EH state
+ */
+ if (ret == SUCCESS) {
+ int bus, cid;
+ struct aac_hba_map_info *info;
+
+ for (bus = 0; bus < AAC_MAX_BUSES; bus++) {
+ for (cid = 0; cid < AAC_MAX_TARGETS; cid++) {
+ info = &aac->hba_map[bus][cid];
+ if (info->devtype == AAC_DEVTYPE_NATIVE_RAW)
+ info->reset_state = 0;
+ }
+ }
}
- ret = SUCCESS;
-
-out:
return ret;
}
@@ -1382,7 +1529,10 @@ static struct scsi_host_template aac_driver_template = {
.change_queue_depth = aac_change_queue_depth,
.sdev_attrs = aac_dev_attrs,
.eh_abort_handler = aac_eh_abort,
- .eh_host_reset_handler = aac_eh_reset,
+ .eh_device_reset_handler = aac_eh_dev_reset,
+ .eh_target_reset_handler = aac_eh_target_reset,
+ .eh_bus_reset_handler = aac_eh_bus_reset,
+ .eh_host_reset_handler = aac_eh_host_reset,
.can_queue = AAC_NUM_IO_FIB,
.this_id = MAXIMUM_NUM_CONTAINERS,
.sg_tablesize = 16,
@@ -1457,7 +1607,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
/*
* Only series 7 needs freset.
*/
- if (pdev->device == PMC_DEVICE_S7)
+ if (pdev->device == PMC_DEVICE_S7)
pdev->needs_freset = 1;
list_for_each_entry(aac, &aac_devices, entry) {
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c
index 48c2b2b34b72..0c9361c87ec8 100644
--- a/drivers/scsi/aacraid/src.c
+++ b/drivers/scsi/aacraid/src.c
@@ -740,6 +740,8 @@ static void aac_send_iop_reset(struct aac_dev *dev)
aac_set_intx_mode(dev);
src_writel(dev, MUnit.IDR, IOP_SRC_RESET_MASK);
+
+ msleep(5000);
}
static void aac_send_hardware_soft_reset(struct aac_dev *dev)