diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-15 19:51:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-15 19:51:54 -0400 |
commit | bc06cffdec85d487c77109dffcd2f285bdc502d3 (patch) | |
tree | adc6e6398243da87e66c56102840597a329183a0 /drivers/scsi/aacraid | |
parent | d3502d7f25b22cfc9762bf1781faa9db1bb3be2e (diff) | |
parent | 9413d7b8aa777dd1fc7db9563ce5e80d769fe7b5 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (166 commits)
[SCSI] ibmvscsi: convert to use the data buffer accessors
[SCSI] dc395x: convert to use the data buffer accessors
[SCSI] ncr53c8xx: convert to use the data buffer accessors
[SCSI] sym53c8xx: convert to use the data buffer accessors
[SCSI] ppa: coding police and printk levels
[SCSI] aic7xxx_old: remove redundant GFP_ATOMIC from kmalloc
[SCSI] i2o: remove redundant GFP_ATOMIC from kmalloc from device.c
[SCSI] remove the dead CYBERSTORMIII_SCSI option
[SCSI] don't build scsi_dma_{map,unmap} for !HAS_DMA
[SCSI] Clean up scsi_add_lun a bit
[SCSI] 53c700: Remove printk, which triggers because of low scsi clock on SNI RMs
[SCSI] sni_53c710: Cleanup
[SCSI] qla4xxx: Fix underrun/overrun conditions
[SCSI] megaraid_mbox: use mutex instead of semaphore
[SCSI] aacraid: add 51245, 51645 and 52245 adapters to documentation.
[SCSI] qla2xxx: update version to 8.02.00-k1.
[SCSI] qla2xxx: add support for NPIV
[SCSI] stex: use resid for xfer len information
[SCSI] Add Brownie 1200U3P to blacklist
[SCSI] scsi.c: convert to use the data buffer accessors
...
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 322 | ||||
-rw-r--r-- | drivers/scsi/aacraid/aacraid.h | 40 | ||||
-rw-r--r-- | drivers/scsi/aacraid/commsup.c | 210 | ||||
-rw-r--r-- | drivers/scsi/aacraid/linit.c | 104 | ||||
-rw-r--r-- | drivers/scsi/aacraid/rx.c | 33 |
5 files changed, 490 insertions, 219 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 8dcfe4ec35c2..0b6fd0b654d2 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -169,6 +169,18 @@ int acbsize = -1; | |||
169 | module_param(acbsize, int, S_IRUGO|S_IWUSR); | 169 | module_param(acbsize, int, S_IRUGO|S_IWUSR); |
170 | MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware."); | 170 | MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware."); |
171 | 171 | ||
172 | int update_interval = 30 * 60; | ||
173 | module_param(update_interval, int, S_IRUGO|S_IWUSR); | ||
174 | MODULE_PARM_DESC(update_interval, "Interval in seconds between time sync updates issued to adapter."); | ||
175 | |||
176 | int check_interval = 24 * 60 * 60; | ||
177 | module_param(check_interval, int, S_IRUGO|S_IWUSR); | ||
178 | MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks."); | ||
179 | |||
180 | int check_reset = 1; | ||
181 | module_param(check_reset, int, S_IRUGO|S_IWUSR); | ||
182 | MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the adapter."); | ||
183 | |||
172 | int expose_physicals = -1; | 184 | int expose_physicals = -1; |
173 | module_param(expose_physicals, int, S_IRUGO|S_IWUSR); | 185 | module_param(expose_physicals, int, S_IRUGO|S_IWUSR); |
174 | MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); | 186 | MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); |
@@ -312,11 +324,10 @@ int aac_get_containers(struct aac_dev *dev) | |||
312 | 324 | ||
313 | if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) | 325 | if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) |
314 | maximum_num_containers = MAXIMUM_NUM_CONTAINERS; | 326 | maximum_num_containers = MAXIMUM_NUM_CONTAINERS; |
315 | fsa_dev_ptr = kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, | 327 | fsa_dev_ptr = kzalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, |
316 | GFP_KERNEL); | 328 | GFP_KERNEL); |
317 | if (!fsa_dev_ptr) | 329 | if (!fsa_dev_ptr) |
318 | return -ENOMEM; | 330 | return -ENOMEM; |
319 | memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); | ||
320 | 331 | ||
321 | dev->fsa_dev = fsa_dev_ptr; | 332 | dev->fsa_dev = fsa_dev_ptr; |
322 | dev->maximum_num_containers = maximum_num_containers; | 333 | dev->maximum_num_containers = maximum_num_containers; |
@@ -344,21 +355,16 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne | |||
344 | { | 355 | { |
345 | void *buf; | 356 | void *buf; |
346 | int transfer_len; | 357 | int transfer_len; |
347 | struct scatterlist *sg = scsicmd->request_buffer; | 358 | struct scatterlist *sg = scsi_sglist(scsicmd); |
359 | |||
360 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
361 | transfer_len = min(sg->length, len + offset); | ||
348 | 362 | ||
349 | if (scsicmd->use_sg) { | ||
350 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
351 | transfer_len = min(sg->length, len + offset); | ||
352 | } else { | ||
353 | buf = scsicmd->request_buffer; | ||
354 | transfer_len = min(scsicmd->request_bufflen, len + offset); | ||
355 | } | ||
356 | transfer_len -= offset; | 363 | transfer_len -= offset; |
357 | if (buf && transfer_len > 0) | 364 | if (buf && transfer_len > 0) |
358 | memcpy(buf + offset, data, transfer_len); | 365 | memcpy(buf + offset, data, transfer_len); |
359 | 366 | ||
360 | if (scsicmd->use_sg) | 367 | kunmap_atomic(buf - sg->offset, KM_IRQ0); |
361 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
362 | 368 | ||
363 | } | 369 | } |
364 | 370 | ||
@@ -451,7 +457,7 @@ static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) | |||
451 | { | 457 | { |
452 | struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; | 458 | struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; |
453 | 459 | ||
454 | if (fsa_dev_ptr[scmd_id(scsicmd)].valid) | 460 | if ((fsa_dev_ptr[scmd_id(scsicmd)].valid & 1)) |
455 | return aac_scsi_cmd(scsicmd); | 461 | return aac_scsi_cmd(scsicmd); |
456 | 462 | ||
457 | scsicmd->result = DID_NO_CONNECT << 16; | 463 | scsicmd->result = DID_NO_CONNECT << 16; |
@@ -459,18 +465,18 @@ static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) | |||
459 | return 0; | 465 | return 0; |
460 | } | 466 | } |
461 | 467 | ||
462 | static int _aac_probe_container2(void * context, struct fib * fibptr) | 468 | static void _aac_probe_container2(void * context, struct fib * fibptr) |
463 | { | 469 | { |
464 | struct fsa_dev_info *fsa_dev_ptr; | 470 | struct fsa_dev_info *fsa_dev_ptr; |
465 | int (*callback)(struct scsi_cmnd *); | 471 | int (*callback)(struct scsi_cmnd *); |
466 | struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; | 472 | struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; |
467 | 473 | ||
468 | if (!aac_valid_context(scsicmd, fibptr)) | ||
469 | return 0; | ||
470 | 474 | ||
471 | fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; | 475 | if (!aac_valid_context(scsicmd, fibptr)) |
476 | return; | ||
472 | 477 | ||
473 | scsicmd->SCp.Status = 0; | 478 | scsicmd->SCp.Status = 0; |
479 | fsa_dev_ptr = fibptr->dev->fsa_dev; | ||
474 | if (fsa_dev_ptr) { | 480 | if (fsa_dev_ptr) { |
475 | struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr); | 481 | struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr); |
476 | fsa_dev_ptr += scmd_id(scsicmd); | 482 | fsa_dev_ptr += scmd_id(scsicmd); |
@@ -493,10 +499,11 @@ static int _aac_probe_container2(void * context, struct fib * fibptr) | |||
493 | aac_fib_free(fibptr); | 499 | aac_fib_free(fibptr); |
494 | callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr); | 500 | callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr); |
495 | scsicmd->SCp.ptr = NULL; | 501 | scsicmd->SCp.ptr = NULL; |
496 | return (*callback)(scsicmd); | 502 | (*callback)(scsicmd); |
503 | return; | ||
497 | } | 504 | } |
498 | 505 | ||
499 | static int _aac_probe_container1(void * context, struct fib * fibptr) | 506 | static void _aac_probe_container1(void * context, struct fib * fibptr) |
500 | { | 507 | { |
501 | struct scsi_cmnd * scsicmd; | 508 | struct scsi_cmnd * scsicmd; |
502 | struct aac_mount * dresp; | 509 | struct aac_mount * dresp; |
@@ -506,13 +513,14 @@ static int _aac_probe_container1(void * context, struct fib * fibptr) | |||
506 | dresp = (struct aac_mount *) fib_data(fibptr); | 513 | dresp = (struct aac_mount *) fib_data(fibptr); |
507 | dresp->mnt[0].capacityhigh = 0; | 514 | dresp->mnt[0].capacityhigh = 0; |
508 | if ((le32_to_cpu(dresp->status) != ST_OK) || | 515 | if ((le32_to_cpu(dresp->status) != ST_OK) || |
509 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) | 516 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { |
510 | return _aac_probe_container2(context, fibptr); | 517 | _aac_probe_container2(context, fibptr); |
518 | return; | ||
519 | } | ||
511 | scsicmd = (struct scsi_cmnd *) context; | 520 | scsicmd = (struct scsi_cmnd *) context; |
512 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; | ||
513 | 521 | ||
514 | if (!aac_valid_context(scsicmd, fibptr)) | 522 | if (!aac_valid_context(scsicmd, fibptr)) |
515 | return 0; | 523 | return; |
516 | 524 | ||
517 | aac_fib_init(fibptr); | 525 | aac_fib_init(fibptr); |
518 | 526 | ||
@@ -527,21 +535,18 @@ static int _aac_probe_container1(void * context, struct fib * fibptr) | |||
527 | sizeof(struct aac_query_mount), | 535 | sizeof(struct aac_query_mount), |
528 | FsaNormal, | 536 | FsaNormal, |
529 | 0, 1, | 537 | 0, 1, |
530 | (fib_callback) _aac_probe_container2, | 538 | _aac_probe_container2, |
531 | (void *) scsicmd); | 539 | (void *) scsicmd); |
532 | /* | 540 | /* |
533 | * Check that the command queued to the controller | 541 | * Check that the command queued to the controller |
534 | */ | 542 | */ |
535 | if (status == -EINPROGRESS) { | 543 | if (status == -EINPROGRESS) |
536 | scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; | 544 | scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; |
537 | return 0; | 545 | else if (status < 0) { |
538 | } | ||
539 | if (status < 0) { | ||
540 | /* Inherit results from VM_NameServe, if any */ | 546 | /* Inherit results from VM_NameServe, if any */ |
541 | dresp->status = cpu_to_le32(ST_OK); | 547 | dresp->status = cpu_to_le32(ST_OK); |
542 | return _aac_probe_container2(context, fibptr); | 548 | _aac_probe_container2(context, fibptr); |
543 | } | 549 | } |
544 | return 0; | ||
545 | } | 550 | } |
546 | 551 | ||
547 | static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *)) | 552 | static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *)) |
@@ -566,7 +571,7 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru | |||
566 | sizeof(struct aac_query_mount), | 571 | sizeof(struct aac_query_mount), |
567 | FsaNormal, | 572 | FsaNormal, |
568 | 0, 1, | 573 | 0, 1, |
569 | (fib_callback) _aac_probe_container1, | 574 | _aac_probe_container1, |
570 | (void *) scsicmd); | 575 | (void *) scsicmd); |
571 | /* | 576 | /* |
572 | * Check that the command queued to the controller | 577 | * Check that the command queued to the controller |
@@ -620,7 +625,7 @@ int aac_probe_container(struct aac_dev *dev, int cid) | |||
620 | return -ENOMEM; | 625 | return -ENOMEM; |
621 | } | 626 | } |
622 | scsicmd->list.next = NULL; | 627 | scsicmd->list.next = NULL; |
623 | scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1; | 628 | scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))aac_probe_container_callback1; |
624 | 629 | ||
625 | scsicmd->device = scsidev; | 630 | scsicmd->device = scsidev; |
626 | scsidev->sdev_state = 0; | 631 | scsidev->sdev_state = 0; |
@@ -825,7 +830,7 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 | |||
825 | readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 830 | readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
826 | readcmd->count = cpu_to_le32(count<<9); | 831 | readcmd->count = cpu_to_le32(count<<9); |
827 | readcmd->cid = cpu_to_le16(scmd_id(cmd)); | 832 | readcmd->cid = cpu_to_le16(scmd_id(cmd)); |
828 | readcmd->flags = cpu_to_le16(1); | 833 | readcmd->flags = cpu_to_le16(IO_TYPE_READ); |
829 | readcmd->bpTotal = 0; | 834 | readcmd->bpTotal = 0; |
830 | readcmd->bpComplete = 0; | 835 | readcmd->bpComplete = 0; |
831 | 836 | ||
@@ -904,7 +909,7 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 | |||
904 | (void *) cmd); | 909 | (void *) cmd); |
905 | } | 910 | } |
906 | 911 | ||
907 | static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) | 912 | static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) |
908 | { | 913 | { |
909 | u16 fibsize; | 914 | u16 fibsize; |
910 | struct aac_raw_io *writecmd; | 915 | struct aac_raw_io *writecmd; |
@@ -914,7 +919,9 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u | |||
914 | writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 919 | writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
915 | writecmd->count = cpu_to_le32(count<<9); | 920 | writecmd->count = cpu_to_le32(count<<9); |
916 | writecmd->cid = cpu_to_le16(scmd_id(cmd)); | 921 | writecmd->cid = cpu_to_le16(scmd_id(cmd)); |
917 | writecmd->flags = 0; | 922 | writecmd->flags = fua ? |
923 | cpu_to_le16(IO_TYPE_WRITE|IO_SUREWRITE) : | ||
924 | cpu_to_le16(IO_TYPE_WRITE); | ||
918 | writecmd->bpTotal = 0; | 925 | writecmd->bpTotal = 0; |
919 | writecmd->bpComplete = 0; | 926 | writecmd->bpComplete = 0; |
920 | 927 | ||
@@ -933,7 +940,7 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u | |||
933 | (void *) cmd); | 940 | (void *) cmd); |
934 | } | 941 | } |
935 | 942 | ||
936 | static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) | 943 | static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) |
937 | { | 944 | { |
938 | u16 fibsize; | 945 | u16 fibsize; |
939 | struct aac_write64 *writecmd; | 946 | struct aac_write64 *writecmd; |
@@ -964,7 +971,7 @@ static int aac_write_block64(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, | |||
964 | (void *) cmd); | 971 | (void *) cmd); |
965 | } | 972 | } |
966 | 973 | ||
967 | static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count) | 974 | static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua) |
968 | { | 975 | { |
969 | u16 fibsize; | 976 | u16 fibsize; |
970 | struct aac_write *writecmd; | 977 | struct aac_write *writecmd; |
@@ -1041,7 +1048,7 @@ static int aac_scsi_64(struct fib * fib, struct scsi_cmnd * cmd) | |||
1041 | struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); | 1048 | struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); |
1042 | 1049 | ||
1043 | aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg); | 1050 | aac_build_sg64(cmd, (struct sgmap64*) &srbcmd->sg); |
1044 | srbcmd->count = cpu_to_le32(cmd->request_bufflen); | 1051 | srbcmd->count = cpu_to_le32(scsi_bufflen(cmd)); |
1045 | 1052 | ||
1046 | memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); | 1053 | memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); |
1047 | memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); | 1054 | memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); |
@@ -1069,7 +1076,7 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd) | |||
1069 | struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); | 1076 | struct aac_srb * srbcmd = aac_scsi_common(fib, cmd); |
1070 | 1077 | ||
1071 | aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg); | 1078 | aac_build_sg(cmd, (struct sgmap*)&srbcmd->sg); |
1072 | srbcmd->count = cpu_to_le32(cmd->request_bufflen); | 1079 | srbcmd->count = cpu_to_le32(scsi_bufflen(cmd)); |
1073 | 1080 | ||
1074 | memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); | 1081 | memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb)); |
1075 | memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); | 1082 | memcpy(srbcmd->cdb, cmd->cmnd, cmd->cmd_len); |
@@ -1172,6 +1179,7 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
1172 | } | 1179 | } |
1173 | 1180 | ||
1174 | if (!dev->in_reset) { | 1181 | if (!dev->in_reset) { |
1182 | char buffer[16]; | ||
1175 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); | 1183 | tmp = le32_to_cpu(dev->adapter_info.kernelrev); |
1176 | printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", | 1184 | printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", |
1177 | dev->name, | 1185 | dev->name, |
@@ -1192,16 +1200,23 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
1192 | dev->name, dev->id, | 1200 | dev->name, dev->id, |
1193 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, | 1201 | tmp>>24,(tmp>>16)&0xff,tmp&0xff, |
1194 | le32_to_cpu(dev->adapter_info.biosbuild)); | 1202 | le32_to_cpu(dev->adapter_info.biosbuild)); |
1195 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) | 1203 | buffer[0] = '\0'; |
1196 | printk(KERN_INFO "%s%d: serial %x\n", | 1204 | if (aac_show_serial_number( |
1197 | dev->name, dev->id, | 1205 | shost_to_class(dev->scsi_host_ptr), buffer)) |
1198 | le32_to_cpu(dev->adapter_info.serial[0])); | 1206 | printk(KERN_INFO "%s%d: serial %s", |
1207 | dev->name, dev->id, buffer); | ||
1199 | if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) { | 1208 | if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) { |
1200 | printk(KERN_INFO "%s%d: TSID %.*s\n", | 1209 | printk(KERN_INFO "%s%d: TSID %.*s\n", |
1201 | dev->name, dev->id, | 1210 | dev->name, dev->id, |
1202 | (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid), | 1211 | (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid), |
1203 | dev->supplement_adapter_info.VpdInfo.Tsid); | 1212 | dev->supplement_adapter_info.VpdInfo.Tsid); |
1204 | } | 1213 | } |
1214 | if (!check_reset || | ||
1215 | (dev->supplement_adapter_info.SupportedOptions2 & | ||
1216 | le32_to_cpu(AAC_OPTION_IGNORE_RESET))) { | ||
1217 | printk(KERN_INFO "%s%d: Reset Adapter Ignored\n", | ||
1218 | dev->name, dev->id); | ||
1219 | } | ||
1205 | } | 1220 | } |
1206 | 1221 | ||
1207 | dev->nondasd_support = 0; | 1222 | dev->nondasd_support = 0; |
@@ -1332,7 +1347,7 @@ static void io_callback(void *context, struct fib * fibptr) | |||
1332 | if (!aac_valid_context(scsicmd, fibptr)) | 1347 | if (!aac_valid_context(scsicmd, fibptr)) |
1333 | return; | 1348 | return; |
1334 | 1349 | ||
1335 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | 1350 | dev = fibptr->dev; |
1336 | cid = scmd_id(scsicmd); | 1351 | cid = scmd_id(scsicmd); |
1337 | 1352 | ||
1338 | if (nblank(dprintk(x))) { | 1353 | if (nblank(dprintk(x))) { |
@@ -1371,16 +1386,9 @@ static void io_callback(void *context, struct fib * fibptr) | |||
1371 | } | 1386 | } |
1372 | 1387 | ||
1373 | BUG_ON(fibptr == NULL); | 1388 | BUG_ON(fibptr == NULL); |
1374 | 1389 | ||
1375 | if(scsicmd->use_sg) | 1390 | scsi_dma_unmap(scsicmd); |
1376 | pci_unmap_sg(dev->pdev, | 1391 | |
1377 | (struct scatterlist *)scsicmd->request_buffer, | ||
1378 | scsicmd->use_sg, | ||
1379 | scsicmd->sc_data_direction); | ||
1380 | else if(scsicmd->request_bufflen) | ||
1381 | pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, | ||
1382 | scsicmd->request_bufflen, | ||
1383 | scsicmd->sc_data_direction); | ||
1384 | readreply = (struct aac_read_reply *)fib_data(fibptr); | 1392 | readreply = (struct aac_read_reply *)fib_data(fibptr); |
1385 | if (le32_to_cpu(readreply->status) == ST_OK) | 1393 | if (le32_to_cpu(readreply->status) == ST_OK) |
1386 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1394 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
@@ -1498,6 +1506,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) | |||
1498 | { | 1506 | { |
1499 | u64 lba; | 1507 | u64 lba; |
1500 | u32 count; | 1508 | u32 count; |
1509 | int fua; | ||
1501 | int status; | 1510 | int status; |
1502 | struct aac_dev *dev; | 1511 | struct aac_dev *dev; |
1503 | struct fib * cmd_fibcontext; | 1512 | struct fib * cmd_fibcontext; |
@@ -1512,6 +1521,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) | |||
1512 | count = scsicmd->cmnd[4]; | 1521 | count = scsicmd->cmnd[4]; |
1513 | if (count == 0) | 1522 | if (count == 0) |
1514 | count = 256; | 1523 | count = 256; |
1524 | fua = 0; | ||
1515 | } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ | 1525 | } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ |
1516 | dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); | 1526 | dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); |
1517 | 1527 | ||
@@ -1524,6 +1534,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) | |||
1524 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; | 1534 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; |
1525 | count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | | 1535 | count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | |
1526 | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; | 1536 | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; |
1537 | fua = scsicmd->cmnd[1] & 0x8; | ||
1527 | } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ | 1538 | } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ |
1528 | dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); | 1539 | dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); |
1529 | 1540 | ||
@@ -1531,10 +1542,12 @@ static int aac_write(struct scsi_cmnd * scsicmd) | |||
1531 | | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; | 1542 | | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; |
1532 | count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) | 1543 | count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) |
1533 | | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; | 1544 | | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; |
1545 | fua = scsicmd->cmnd[1] & 0x8; | ||
1534 | } else { | 1546 | } else { |
1535 | dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); | 1547 | dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); |
1536 | lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; | 1548 | lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; |
1537 | count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; | 1549 | count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; |
1550 | fua = scsicmd->cmnd[1] & 0x8; | ||
1538 | } | 1551 | } |
1539 | dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", | 1552 | dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %llu, t = %ld.\n", |
1540 | smp_processor_id(), (unsigned long long)lba, jiffies)); | 1553 | smp_processor_id(), (unsigned long long)lba, jiffies)); |
@@ -1549,7 +1562,7 @@ static int aac_write(struct scsi_cmnd * scsicmd) | |||
1549 | return 0; | 1562 | return 0; |
1550 | } | 1563 | } |
1551 | 1564 | ||
1552 | status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count); | 1565 | status = aac_adapter_write(cmd_fibcontext, scsicmd, lba, count, fua); |
1553 | 1566 | ||
1554 | /* | 1567 | /* |
1555 | * Check that the command queued to the controller | 1568 | * Check that the command queued to the controller |
@@ -1592,7 +1605,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) | |||
1592 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1605 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1593 | else { | 1606 | else { |
1594 | struct scsi_device *sdev = cmd->device; | 1607 | struct scsi_device *sdev = cmd->device; |
1595 | struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; | 1608 | struct aac_dev *dev = fibptr->dev; |
1596 | u32 cid = sdev_id(sdev); | 1609 | u32 cid = sdev_id(sdev); |
1597 | printk(KERN_WARNING | 1610 | printk(KERN_WARNING |
1598 | "synchronize_callback: synchronize failed, status = %d\n", | 1611 | "synchronize_callback: synchronize failed, status = %d\n", |
@@ -1699,7 +1712,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd) | |||
1699 | 1712 | ||
1700 | int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | 1713 | int aac_scsi_cmd(struct scsi_cmnd * scsicmd) |
1701 | { | 1714 | { |
1702 | u32 cid = 0; | 1715 | u32 cid; |
1703 | struct Scsi_Host *host = scsicmd->device->host; | 1716 | struct Scsi_Host *host = scsicmd->device->host; |
1704 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | 1717 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; |
1705 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; | 1718 | struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev; |
@@ -1711,15 +1724,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1711 | * Test does not apply to ID 16, the pseudo id for the controller | 1724 | * Test does not apply to ID 16, the pseudo id for the controller |
1712 | * itself. | 1725 | * itself. |
1713 | */ | 1726 | */ |
1714 | if (scmd_id(scsicmd) != host->this_id) { | 1727 | cid = scmd_id(scsicmd); |
1715 | if ((scmd_channel(scsicmd) == CONTAINER_CHANNEL)) { | 1728 | if (cid != host->this_id) { |
1716 | if((scmd_id(scsicmd) >= dev->maximum_num_containers) || | 1729 | if (scmd_channel(scsicmd) == CONTAINER_CHANNEL) { |
1730 | if((cid >= dev->maximum_num_containers) || | ||
1717 | (scsicmd->device->lun != 0)) { | 1731 | (scsicmd->device->lun != 0)) { |
1718 | scsicmd->result = DID_NO_CONNECT << 16; | 1732 | scsicmd->result = DID_NO_CONNECT << 16; |
1719 | scsicmd->scsi_done(scsicmd); | 1733 | scsicmd->scsi_done(scsicmd); |
1720 | return 0; | 1734 | return 0; |
1721 | } | 1735 | } |
1722 | cid = scmd_id(scsicmd); | ||
1723 | 1736 | ||
1724 | /* | 1737 | /* |
1725 | * If the target container doesn't exist, it may have | 1738 | * If the target container doesn't exist, it may have |
@@ -1782,7 +1795,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1782 | { | 1795 | { |
1783 | struct inquiry_data inq_data; | 1796 | struct inquiry_data inq_data; |
1784 | 1797 | ||
1785 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scmd_id(scsicmd))); | 1798 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid)); |
1786 | memset(&inq_data, 0, sizeof (struct inquiry_data)); | 1799 | memset(&inq_data, 0, sizeof (struct inquiry_data)); |
1787 | 1800 | ||
1788 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ | 1801 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ |
@@ -1794,7 +1807,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1794 | * Set the Vendor, Product, and Revision Level | 1807 | * Set the Vendor, Product, and Revision Level |
1795 | * see: <vendor>.c i.e. aac.c | 1808 | * see: <vendor>.c i.e. aac.c |
1796 | */ | 1809 | */ |
1797 | if (scmd_id(scsicmd) == host->this_id) { | 1810 | if (cid == host->this_id) { |
1798 | setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types)); | 1811 | setinqstr(dev, (void *) (inq_data.inqd_vid), ARRAY_SIZE(container_types)); |
1799 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ | 1812 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ |
1800 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | 1813 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); |
@@ -1886,15 +1899,29 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1886 | 1899 | ||
1887 | case MODE_SENSE: | 1900 | case MODE_SENSE: |
1888 | { | 1901 | { |
1889 | char mode_buf[4]; | 1902 | char mode_buf[7]; |
1903 | int mode_buf_length = 4; | ||
1890 | 1904 | ||
1891 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); | 1905 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); |
1892 | mode_buf[0] = 3; /* Mode data length */ | 1906 | mode_buf[0] = 3; /* Mode data length */ |
1893 | mode_buf[1] = 0; /* Medium type - default */ | 1907 | mode_buf[1] = 0; /* Medium type - default */ |
1894 | mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ | 1908 | mode_buf[2] = 0; /* Device-specific param, |
1909 | bit 8: 0/1 = write enabled/protected | ||
1910 | bit 4: 0/1 = FUA enabled */ | ||
1911 | if (dev->raw_io_interface) | ||
1912 | mode_buf[2] = 0x10; | ||
1895 | mode_buf[3] = 0; /* Block descriptor length */ | 1913 | mode_buf[3] = 0; /* Block descriptor length */ |
1896 | 1914 | if (((scsicmd->cmnd[2] & 0x3f) == 8) || | |
1897 | aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); | 1915 | ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { |
1916 | mode_buf[0] = 6; | ||
1917 | mode_buf[4] = 8; | ||
1918 | mode_buf[5] = 1; | ||
1919 | mode_buf[6] = 0x04; /* WCE */ | ||
1920 | mode_buf_length = 7; | ||
1921 | if (mode_buf_length > scsicmd->cmnd[4]) | ||
1922 | mode_buf_length = scsicmd->cmnd[4]; | ||
1923 | } | ||
1924 | aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length); | ||
1898 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1925 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1899 | scsicmd->scsi_done(scsicmd); | 1926 | scsicmd->scsi_done(scsicmd); |
1900 | 1927 | ||
@@ -1902,18 +1929,33 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1902 | } | 1929 | } |
1903 | case MODE_SENSE_10: | 1930 | case MODE_SENSE_10: |
1904 | { | 1931 | { |
1905 | char mode_buf[8]; | 1932 | char mode_buf[11]; |
1933 | int mode_buf_length = 8; | ||
1906 | 1934 | ||
1907 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); | 1935 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); |
1908 | mode_buf[0] = 0; /* Mode data length (MSB) */ | 1936 | mode_buf[0] = 0; /* Mode data length (MSB) */ |
1909 | mode_buf[1] = 6; /* Mode data length (LSB) */ | 1937 | mode_buf[1] = 6; /* Mode data length (LSB) */ |
1910 | mode_buf[2] = 0; /* Medium type - default */ | 1938 | mode_buf[2] = 0; /* Medium type - default */ |
1911 | mode_buf[3] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ | 1939 | mode_buf[3] = 0; /* Device-specific param, |
1940 | bit 8: 0/1 = write enabled/protected | ||
1941 | bit 4: 0/1 = FUA enabled */ | ||
1942 | if (dev->raw_io_interface) | ||
1943 | mode_buf[3] = 0x10; | ||
1912 | mode_buf[4] = 0; /* reserved */ | 1944 | mode_buf[4] = 0; /* reserved */ |
1913 | mode_buf[5] = 0; /* reserved */ | 1945 | mode_buf[5] = 0; /* reserved */ |
1914 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ | 1946 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ |
1915 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ | 1947 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ |
1916 | aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); | 1948 | if (((scsicmd->cmnd[2] & 0x3f) == 8) || |
1949 | ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { | ||
1950 | mode_buf[1] = 9; | ||
1951 | mode_buf[8] = 8; | ||
1952 | mode_buf[9] = 1; | ||
1953 | mode_buf[10] = 0x04; /* WCE */ | ||
1954 | mode_buf_length = 11; | ||
1955 | if (mode_buf_length > scsicmd->cmnd[8]) | ||
1956 | mode_buf_length = scsicmd->cmnd[8]; | ||
1957 | } | ||
1958 | aac_internal_transfer(scsicmd, mode_buf, 0, mode_buf_length); | ||
1917 | 1959 | ||
1918 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1960 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1919 | scsicmd->scsi_done(scsicmd); | 1961 | scsicmd->scsi_done(scsicmd); |
@@ -2136,28 +2178,21 @@ static void aac_srb_callback(void *context, struct fib * fibptr) | |||
2136 | if (!aac_valid_context(scsicmd, fibptr)) | 2178 | if (!aac_valid_context(scsicmd, fibptr)) |
2137 | return; | 2179 | return; |
2138 | 2180 | ||
2139 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | ||
2140 | |||
2141 | BUG_ON(fibptr == NULL); | 2181 | BUG_ON(fibptr == NULL); |
2142 | 2182 | ||
2183 | dev = fibptr->dev; | ||
2184 | |||
2143 | srbreply = (struct aac_srb_reply *) fib_data(fibptr); | 2185 | srbreply = (struct aac_srb_reply *) fib_data(fibptr); |
2144 | 2186 | ||
2145 | scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ | 2187 | scsicmd->sense_buffer[0] = '\0'; /* Initialize sense valid flag to false */ |
2146 | /* | 2188 | /* |
2147 | * Calculate resid for sg | 2189 | * Calculate resid for sg |
2148 | */ | 2190 | */ |
2149 | 2191 | ||
2150 | scsicmd->resid = scsicmd->request_bufflen - | 2192 | scsi_set_resid(scsicmd, scsi_bufflen(scsicmd) |
2151 | le32_to_cpu(srbreply->data_xfer_length); | 2193 | - le32_to_cpu(srbreply->data_xfer_length)); |
2152 | 2194 | ||
2153 | if(scsicmd->use_sg) | 2195 | scsi_dma_unmap(scsicmd); |
2154 | pci_unmap_sg(dev->pdev, | ||
2155 | (struct scatterlist *)scsicmd->request_buffer, | ||
2156 | scsicmd->use_sg, | ||
2157 | scsicmd->sc_data_direction); | ||
2158 | else if(scsicmd->request_bufflen) | ||
2159 | pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen, | ||
2160 | scsicmd->sc_data_direction); | ||
2161 | 2196 | ||
2162 | /* | 2197 | /* |
2163 | * First check the fib status | 2198 | * First check the fib status |
@@ -2233,7 +2268,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) | |||
2233 | break; | 2268 | break; |
2234 | 2269 | ||
2235 | case SRB_STATUS_BUSY: | 2270 | case SRB_STATUS_BUSY: |
2236 | scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8; | 2271 | scsicmd->result = DID_BUS_BUSY << 16 | COMMAND_COMPLETE << 8; |
2237 | break; | 2272 | break; |
2238 | 2273 | ||
2239 | case SRB_STATUS_BUS_RESET: | 2274 | case SRB_STATUS_BUS_RESET: |
@@ -2343,34 +2378,33 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) | |||
2343 | { | 2378 | { |
2344 | struct aac_dev *dev; | 2379 | struct aac_dev *dev; |
2345 | unsigned long byte_count = 0; | 2380 | unsigned long byte_count = 0; |
2381 | int nseg; | ||
2346 | 2382 | ||
2347 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | 2383 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; |
2348 | // Get rid of old data | 2384 | // Get rid of old data |
2349 | psg->count = 0; | 2385 | psg->count = 0; |
2350 | psg->sg[0].addr = 0; | 2386 | psg->sg[0].addr = 0; |
2351 | psg->sg[0].count = 0; | 2387 | psg->sg[0].count = 0; |
2352 | if (scsicmd->use_sg) { | 2388 | |
2389 | nseg = scsi_dma_map(scsicmd); | ||
2390 | BUG_ON(nseg < 0); | ||
2391 | if (nseg) { | ||
2353 | struct scatterlist *sg; | 2392 | struct scatterlist *sg; |
2354 | int i; | 2393 | int i; |
2355 | int sg_count; | ||
2356 | sg = (struct scatterlist *) scsicmd->request_buffer; | ||
2357 | 2394 | ||
2358 | sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, | 2395 | psg->count = cpu_to_le32(nseg); |
2359 | scsicmd->sc_data_direction); | ||
2360 | psg->count = cpu_to_le32(sg_count); | ||
2361 | 2396 | ||
2362 | for (i = 0; i < sg_count; i++) { | 2397 | scsi_for_each_sg(scsicmd, sg, nseg, i) { |
2363 | psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); | 2398 | psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg)); |
2364 | psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); | 2399 | psg->sg[i].count = cpu_to_le32(sg_dma_len(sg)); |
2365 | byte_count += sg_dma_len(sg); | 2400 | byte_count += sg_dma_len(sg); |
2366 | sg++; | ||
2367 | } | 2401 | } |
2368 | /* hba wants the size to be exact */ | 2402 | /* hba wants the size to be exact */ |
2369 | if(byte_count > scsicmd->request_bufflen){ | 2403 | if (byte_count > scsi_bufflen(scsicmd)) { |
2370 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - | 2404 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - |
2371 | (byte_count - scsicmd->request_bufflen); | 2405 | (byte_count - scsi_bufflen(scsicmd)); |
2372 | psg->sg[i-1].count = cpu_to_le32(temp); | 2406 | psg->sg[i-1].count = cpu_to_le32(temp); |
2373 | byte_count = scsicmd->request_bufflen; | 2407 | byte_count = scsi_bufflen(scsicmd); |
2374 | } | 2408 | } |
2375 | /* Check for command underflow */ | 2409 | /* Check for command underflow */ |
2376 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ | 2410 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ |
@@ -2378,18 +2412,6 @@ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg) | |||
2378 | byte_count, scsicmd->underflow); | 2412 | byte_count, scsicmd->underflow); |
2379 | } | 2413 | } |
2380 | } | 2414 | } |
2381 | else if(scsicmd->request_bufflen) { | ||
2382 | u32 addr; | ||
2383 | scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, | ||
2384 | scsicmd->request_buffer, | ||
2385 | scsicmd->request_bufflen, | ||
2386 | scsicmd->sc_data_direction); | ||
2387 | addr = scsicmd->SCp.dma_handle; | ||
2388 | psg->count = cpu_to_le32(1); | ||
2389 | psg->sg[0].addr = cpu_to_le32(addr); | ||
2390 | psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); | ||
2391 | byte_count = scsicmd->request_bufflen; | ||
2392 | } | ||
2393 | return byte_count; | 2415 | return byte_count; |
2394 | } | 2416 | } |
2395 | 2417 | ||
@@ -2399,6 +2421,7 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p | |||
2399 | struct aac_dev *dev; | 2421 | struct aac_dev *dev; |
2400 | unsigned long byte_count = 0; | 2422 | unsigned long byte_count = 0; |
2401 | u64 addr; | 2423 | u64 addr; |
2424 | int nseg; | ||
2402 | 2425 | ||
2403 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | 2426 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; |
2404 | // Get rid of old data | 2427 | // Get rid of old data |
@@ -2406,31 +2429,28 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p | |||
2406 | psg->sg[0].addr[0] = 0; | 2429 | psg->sg[0].addr[0] = 0; |
2407 | psg->sg[0].addr[1] = 0; | 2430 | psg->sg[0].addr[1] = 0; |
2408 | psg->sg[0].count = 0; | 2431 | psg->sg[0].count = 0; |
2409 | if (scsicmd->use_sg) { | 2432 | |
2433 | nseg = scsi_dma_map(scsicmd); | ||
2434 | BUG_ON(nseg < 0); | ||
2435 | if (nseg) { | ||
2410 | struct scatterlist *sg; | 2436 | struct scatterlist *sg; |
2411 | int i; | 2437 | int i; |
2412 | int sg_count; | ||
2413 | sg = (struct scatterlist *) scsicmd->request_buffer; | ||
2414 | |||
2415 | sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, | ||
2416 | scsicmd->sc_data_direction); | ||
2417 | 2438 | ||
2418 | for (i = 0; i < sg_count; i++) { | 2439 | scsi_for_each_sg(scsicmd, sg, nseg, i) { |
2419 | int count = sg_dma_len(sg); | 2440 | int count = sg_dma_len(sg); |
2420 | addr = sg_dma_address(sg); | 2441 | addr = sg_dma_address(sg); |
2421 | psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); | 2442 | psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); |
2422 | psg->sg[i].addr[1] = cpu_to_le32(addr>>32); | 2443 | psg->sg[i].addr[1] = cpu_to_le32(addr>>32); |
2423 | psg->sg[i].count = cpu_to_le32(count); | 2444 | psg->sg[i].count = cpu_to_le32(count); |
2424 | byte_count += count; | 2445 | byte_count += count; |
2425 | sg++; | ||
2426 | } | 2446 | } |
2427 | psg->count = cpu_to_le32(sg_count); | 2447 | psg->count = cpu_to_le32(nseg); |
2428 | /* hba wants the size to be exact */ | 2448 | /* hba wants the size to be exact */ |
2429 | if(byte_count > scsicmd->request_bufflen){ | 2449 | if (byte_count > scsi_bufflen(scsicmd)) { |
2430 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - | 2450 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - |
2431 | (byte_count - scsicmd->request_bufflen); | 2451 | (byte_count - scsi_bufflen(scsicmd)); |
2432 | psg->sg[i-1].count = cpu_to_le32(temp); | 2452 | psg->sg[i-1].count = cpu_to_le32(temp); |
2433 | byte_count = scsicmd->request_bufflen; | 2453 | byte_count = scsi_bufflen(scsicmd); |
2434 | } | 2454 | } |
2435 | /* Check for command underflow */ | 2455 | /* Check for command underflow */ |
2436 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ | 2456 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ |
@@ -2438,26 +2458,13 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p | |||
2438 | byte_count, scsicmd->underflow); | 2458 | byte_count, scsicmd->underflow); |
2439 | } | 2459 | } |
2440 | } | 2460 | } |
2441 | else if(scsicmd->request_bufflen) { | ||
2442 | scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, | ||
2443 | scsicmd->request_buffer, | ||
2444 | scsicmd->request_bufflen, | ||
2445 | scsicmd->sc_data_direction); | ||
2446 | addr = scsicmd->SCp.dma_handle; | ||
2447 | psg->count = cpu_to_le32(1); | ||
2448 | psg->sg[0].addr[0] = cpu_to_le32(addr & 0xffffffff); | ||
2449 | psg->sg[0].addr[1] = cpu_to_le32(addr >> 32); | ||
2450 | psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen); | ||
2451 | byte_count = scsicmd->request_bufflen; | ||
2452 | } | ||
2453 | return byte_count; | 2461 | return byte_count; |
2454 | } | 2462 | } |
2455 | 2463 | ||
2456 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg) | 2464 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg) |
2457 | { | 2465 | { |
2458 | struct Scsi_Host *host = scsicmd->device->host; | ||
2459 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | ||
2460 | unsigned long byte_count = 0; | 2466 | unsigned long byte_count = 0; |
2467 | int nseg; | ||
2461 | 2468 | ||
2462 | // Get rid of old data | 2469 | // Get rid of old data |
2463 | psg->count = 0; | 2470 | psg->count = 0; |
@@ -2467,16 +2474,14 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* | |||
2467 | psg->sg[0].addr[1] = 0; | 2474 | psg->sg[0].addr[1] = 0; |
2468 | psg->sg[0].count = 0; | 2475 | psg->sg[0].count = 0; |
2469 | psg->sg[0].flags = 0; | 2476 | psg->sg[0].flags = 0; |
2470 | if (scsicmd->use_sg) { | 2477 | |
2478 | nseg = scsi_dma_map(scsicmd); | ||
2479 | BUG_ON(nseg < 0); | ||
2480 | if (nseg) { | ||
2471 | struct scatterlist *sg; | 2481 | struct scatterlist *sg; |
2472 | int i; | 2482 | int i; |
2473 | int sg_count; | ||
2474 | sg = (struct scatterlist *) scsicmd->request_buffer; | ||
2475 | 2483 | ||
2476 | sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, | 2484 | scsi_for_each_sg(scsicmd, sg, nseg, i) { |
2477 | scsicmd->sc_data_direction); | ||
2478 | |||
2479 | for (i = 0; i < sg_count; i++) { | ||
2480 | int count = sg_dma_len(sg); | 2485 | int count = sg_dma_len(sg); |
2481 | u64 addr = sg_dma_address(sg); | 2486 | u64 addr = sg_dma_address(sg); |
2482 | psg->sg[i].next = 0; | 2487 | psg->sg[i].next = 0; |
@@ -2486,15 +2491,14 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* | |||
2486 | psg->sg[i].count = cpu_to_le32(count); | 2491 | psg->sg[i].count = cpu_to_le32(count); |
2487 | psg->sg[i].flags = 0; | 2492 | psg->sg[i].flags = 0; |
2488 | byte_count += count; | 2493 | byte_count += count; |
2489 | sg++; | ||
2490 | } | 2494 | } |
2491 | psg->count = cpu_to_le32(sg_count); | 2495 | psg->count = cpu_to_le32(nseg); |
2492 | /* hba wants the size to be exact */ | 2496 | /* hba wants the size to be exact */ |
2493 | if(byte_count > scsicmd->request_bufflen){ | 2497 | if (byte_count > scsi_bufflen(scsicmd)) { |
2494 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - | 2498 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - |
2495 | (byte_count - scsicmd->request_bufflen); | 2499 | (byte_count - scsi_bufflen(scsicmd)); |
2496 | psg->sg[i-1].count = cpu_to_le32(temp); | 2500 | psg->sg[i-1].count = cpu_to_le32(temp); |
2497 | byte_count = scsicmd->request_bufflen; | 2501 | byte_count = scsi_bufflen(scsicmd); |
2498 | } | 2502 | } |
2499 | /* Check for command underflow */ | 2503 | /* Check for command underflow */ |
2500 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ | 2504 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ |
@@ -2502,24 +2506,6 @@ static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* | |||
2502 | byte_count, scsicmd->underflow); | 2506 | byte_count, scsicmd->underflow); |
2503 | } | 2507 | } |
2504 | } | 2508 | } |
2505 | else if(scsicmd->request_bufflen) { | ||
2506 | int count; | ||
2507 | u64 addr; | ||
2508 | scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, | ||
2509 | scsicmd->request_buffer, | ||
2510 | scsicmd->request_bufflen, | ||
2511 | scsicmd->sc_data_direction); | ||
2512 | addr = scsicmd->SCp.dma_handle; | ||
2513 | count = scsicmd->request_bufflen; | ||
2514 | psg->count = cpu_to_le32(1); | ||
2515 | psg->sg[0].next = 0; | ||
2516 | psg->sg[0].prev = 0; | ||
2517 | psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32)); | ||
2518 | psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | ||
2519 | psg->sg[0].count = cpu_to_le32(count); | ||
2520 | psg->sg[0].flags = 0; | ||
2521 | byte_count = scsicmd->request_bufflen; | ||
2522 | } | ||
2523 | return byte_count; | 2509 | return byte_count; |
2524 | } | 2510 | } |
2525 | 2511 | ||
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index c81edf36913f..f1d3b66af879 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -12,8 +12,8 @@ | |||
12 | *----------------------------------------------------------------------------*/ | 12 | *----------------------------------------------------------------------------*/ |
13 | 13 | ||
14 | #ifndef AAC_DRIVER_BUILD | 14 | #ifndef AAC_DRIVER_BUILD |
15 | # define AAC_DRIVER_BUILD 2437 | 15 | # define AAC_DRIVER_BUILD 2447 |
16 | # define AAC_DRIVER_BRANCH "-mh4" | 16 | # define AAC_DRIVER_BRANCH "-ms" |
17 | #endif | 17 | #endif |
18 | #define MAXIMUM_NUM_CONTAINERS 32 | 18 | #define MAXIMUM_NUM_CONTAINERS 32 |
19 | 19 | ||
@@ -464,12 +464,12 @@ struct adapter_ops | |||
464 | int (*adapter_restart)(struct aac_dev *dev, int bled); | 464 | int (*adapter_restart)(struct aac_dev *dev, int bled); |
465 | /* Transport operations */ | 465 | /* Transport operations */ |
466 | int (*adapter_ioremap)(struct aac_dev * dev, u32 size); | 466 | int (*adapter_ioremap)(struct aac_dev * dev, u32 size); |
467 | irqreturn_t (*adapter_intr)(int irq, void *dev_id); | 467 | irq_handler_t adapter_intr; |
468 | /* Packet operations */ | 468 | /* Packet operations */ |
469 | int (*adapter_deliver)(struct fib * fib); | 469 | int (*adapter_deliver)(struct fib * fib); |
470 | int (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba); | 470 | int (*adapter_bounds)(struct aac_dev * dev, struct scsi_cmnd * cmd, u64 lba); |
471 | int (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); | 471 | int (*adapter_read)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); |
472 | int (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count); | 472 | int (*adapter_write)(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 count, int fua); |
473 | int (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd); | 473 | int (*adapter_scsi)(struct fib * fib, struct scsi_cmnd * cmd); |
474 | /* Administrative operations */ | 474 | /* Administrative operations */ |
475 | int (*adapter_comm)(struct aac_dev * dev, int comm); | 475 | int (*adapter_comm)(struct aac_dev * dev, int comm); |
@@ -860,10 +860,12 @@ struct aac_supplement_adapter_info | |||
860 | __le32 FlashFirmwareBootBuild; | 860 | __le32 FlashFirmwareBootBuild; |
861 | u8 MfgPcbaSerialNo[12]; | 861 | u8 MfgPcbaSerialNo[12]; |
862 | u8 MfgWWNName[8]; | 862 | u8 MfgWWNName[8]; |
863 | __le32 MoreFeatureBits; | 863 | __le32 SupportedOptions2; |
864 | __le32 ReservedGrowth[1]; | 864 | __le32 ReservedGrowth[1]; |
865 | }; | 865 | }; |
866 | #define AAC_FEATURE_FALCON 0x00000010 | 866 | #define AAC_FEATURE_FALCON 0x00000010 |
867 | #define AAC_OPTION_MU_RESET 0x00000001 | ||
868 | #define AAC_OPTION_IGNORE_RESET 0x00000002 | ||
867 | #define AAC_SIS_VERSION_V3 3 | 869 | #define AAC_SIS_VERSION_V3 3 |
868 | #define AAC_SIS_SLOT_UNKNOWN 0xFF | 870 | #define AAC_SIS_SLOT_UNKNOWN 0xFF |
869 | 871 | ||
@@ -1054,8 +1056,8 @@ struct aac_dev | |||
1054 | #define aac_adapter_read(fib,cmd,lba,count) \ | 1056 | #define aac_adapter_read(fib,cmd,lba,count) \ |
1055 | ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count) | 1057 | ((fib)->dev)->a_ops.adapter_read(fib,cmd,lba,count) |
1056 | 1058 | ||
1057 | #define aac_adapter_write(fib,cmd,lba,count) \ | 1059 | #define aac_adapter_write(fib,cmd,lba,count,fua) \ |
1058 | ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count) | 1060 | ((fib)->dev)->a_ops.adapter_write(fib,cmd,lba,count,fua) |
1059 | 1061 | ||
1060 | #define aac_adapter_scsi(fib,cmd) \ | 1062 | #define aac_adapter_scsi(fib,cmd) \ |
1061 | ((fib)->dev)->a_ops.adapter_scsi(fib,cmd) | 1063 | ((fib)->dev)->a_ops.adapter_scsi(fib,cmd) |
@@ -1213,6 +1215,9 @@ struct aac_write64 | |||
1213 | __le32 block; | 1215 | __le32 block; |
1214 | __le16 pad; | 1216 | __le16 pad; |
1215 | __le16 flags; | 1217 | __le16 flags; |
1218 | #define IO_TYPE_WRITE 0x00000000 | ||
1219 | #define IO_TYPE_READ 0x00000001 | ||
1220 | #define IO_SUREWRITE 0x00000008 | ||
1216 | struct sgmap64 sg; // Must be last in struct because it is variable | 1221 | struct sgmap64 sg; // Must be last in struct because it is variable |
1217 | }; | 1222 | }; |
1218 | struct aac_write_reply | 1223 | struct aac_write_reply |
@@ -1257,6 +1262,19 @@ struct aac_synchronize_reply { | |||
1257 | u8 data[16]; | 1262 | u8 data[16]; |
1258 | }; | 1263 | }; |
1259 | 1264 | ||
1265 | #define CT_PAUSE_IO 65 | ||
1266 | #define CT_RELEASE_IO 66 | ||
1267 | struct aac_pause { | ||
1268 | __le32 command; /* VM_ContainerConfig */ | ||
1269 | __le32 type; /* CT_PAUSE_IO */ | ||
1270 | __le32 timeout; /* 10ms ticks */ | ||
1271 | __le32 min; | ||
1272 | __le32 noRescan; | ||
1273 | __le32 parm3; | ||
1274 | __le32 parm4; | ||
1275 | __le32 count; /* sizeof(((struct aac_pause_reply *)NULL)->data) */ | ||
1276 | }; | ||
1277 | |||
1260 | struct aac_srb | 1278 | struct aac_srb |
1261 | { | 1279 | { |
1262 | __le32 function; | 1280 | __le32 function; |
@@ -1804,6 +1822,10 @@ int aac_get_config_status(struct aac_dev *dev, int commit_flag); | |||
1804 | int aac_get_containers(struct aac_dev *dev); | 1822 | int aac_get_containers(struct aac_dev *dev); |
1805 | int aac_scsi_cmd(struct scsi_cmnd *cmd); | 1823 | int aac_scsi_cmd(struct scsi_cmnd *cmd); |
1806 | int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); | 1824 | int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg); |
1825 | #ifndef shost_to_class | ||
1826 | #define shost_to_class(shost) &shost->shost_classdev | ||
1827 | #endif | ||
1828 | ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf); | ||
1807 | int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg); | 1829 | int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg); |
1808 | int aac_rx_init(struct aac_dev *dev); | 1830 | int aac_rx_init(struct aac_dev *dev); |
1809 | int aac_rkt_init(struct aac_dev *dev); | 1831 | int aac_rkt_init(struct aac_dev *dev); |
@@ -1813,6 +1835,7 @@ int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw | |||
1813 | unsigned int aac_response_normal(struct aac_queue * q); | 1835 | unsigned int aac_response_normal(struct aac_queue * q); |
1814 | unsigned int aac_command_normal(struct aac_queue * q); | 1836 | unsigned int aac_command_normal(struct aac_queue * q); |
1815 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); | 1837 | unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index); |
1838 | int aac_reset_adapter(struct aac_dev * dev, int forced); | ||
1816 | int aac_check_health(struct aac_dev * dev); | 1839 | int aac_check_health(struct aac_dev * dev); |
1817 | int aac_command_thread(void *data); | 1840 | int aac_command_thread(void *data); |
1818 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); | 1841 | int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); |
@@ -1832,3 +1855,6 @@ extern int aif_timeout; | |||
1832 | extern int expose_physicals; | 1855 | extern int expose_physicals; |
1833 | extern int aac_reset_devices; | 1856 | extern int aac_reset_devices; |
1834 | extern int aac_commit; | 1857 | extern int aac_commit; |
1858 | extern int update_interval; | ||
1859 | extern int check_interval; | ||
1860 | extern int check_reset; | ||
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 9aca57eda943..d510839c0bb2 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -1021,7 +1021,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1021 | 1021 | ||
1022 | } | 1022 | } |
1023 | 1023 | ||
1024 | static int _aac_reset_adapter(struct aac_dev *aac) | 1024 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) |
1025 | { | 1025 | { |
1026 | int index, quirks; | 1026 | int index, quirks; |
1027 | int retval; | 1027 | int retval; |
@@ -1029,25 +1029,32 @@ static int _aac_reset_adapter(struct aac_dev *aac) | |||
1029 | struct scsi_device *dev; | 1029 | struct scsi_device *dev; |
1030 | struct scsi_cmnd *command; | 1030 | struct scsi_cmnd *command; |
1031 | struct scsi_cmnd *command_list; | 1031 | struct scsi_cmnd *command_list; |
1032 | int jafo = 0; | ||
1032 | 1033 | ||
1033 | /* | 1034 | /* |
1034 | * Assumptions: | 1035 | * Assumptions: |
1035 | * - host is locked. | 1036 | * - host is locked, unless called by the aacraid thread. |
1037 | * (a matter of convenience, due to legacy issues surrounding | ||
1038 | * eh_host_adapter_reset). | ||
1036 | * - in_reset is asserted, so no new i/o is getting to the | 1039 | * - in_reset is asserted, so no new i/o is getting to the |
1037 | * card. | 1040 | * card. |
1038 | * - The card is dead. | 1041 | * - The card is dead, or will be very shortly ;-/ so no new |
1042 | * commands are completing in the interrupt service. | ||
1039 | */ | 1043 | */ |
1040 | host = aac->scsi_host_ptr; | 1044 | host = aac->scsi_host_ptr; |
1041 | scsi_block_requests(host); | 1045 | scsi_block_requests(host); |
1042 | aac_adapter_disable_int(aac); | 1046 | aac_adapter_disable_int(aac); |
1043 | spin_unlock_irq(host->host_lock); | 1047 | if (aac->thread->pid != current->pid) { |
1044 | kthread_stop(aac->thread); | 1048 | spin_unlock_irq(host->host_lock); |
1049 | kthread_stop(aac->thread); | ||
1050 | jafo = 1; | ||
1051 | } | ||
1045 | 1052 | ||
1046 | /* | 1053 | /* |
1047 | * If a positive health, means in a known DEAD PANIC | 1054 | * If a positive health, means in a known DEAD PANIC |
1048 | * state and the adapter could be reset to `try again'. | 1055 | * state and the adapter could be reset to `try again'. |
1049 | */ | 1056 | */ |
1050 | retval = aac_adapter_restart(aac, aac_adapter_check_health(aac)); | 1057 | retval = aac_adapter_restart(aac, forced ? 0 : aac_adapter_check_health(aac)); |
1051 | 1058 | ||
1052 | if (retval) | 1059 | if (retval) |
1053 | goto out; | 1060 | goto out; |
@@ -1104,10 +1111,12 @@ static int _aac_reset_adapter(struct aac_dev *aac) | |||
1104 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) | 1111 | if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) |
1105 | if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) | 1112 | if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) |
1106 | goto out; | 1113 | goto out; |
1107 | aac->thread = kthread_run(aac_command_thread, aac, aac->name); | 1114 | if (jafo) { |
1108 | if (IS_ERR(aac->thread)) { | 1115 | aac->thread = kthread_run(aac_command_thread, aac, aac->name); |
1109 | retval = PTR_ERR(aac->thread); | 1116 | if (IS_ERR(aac->thread)) { |
1110 | goto out; | 1117 | retval = PTR_ERR(aac->thread); |
1118 | goto out; | ||
1119 | } | ||
1111 | } | 1120 | } |
1112 | (void)aac_get_adapter_info(aac); | 1121 | (void)aac_get_adapter_info(aac); |
1113 | quirks = aac_get_driver_ident(index)->quirks; | 1122 | quirks = aac_get_driver_ident(index)->quirks; |
@@ -1150,7 +1159,98 @@ static int _aac_reset_adapter(struct aac_dev *aac) | |||
1150 | out: | 1159 | out: |
1151 | aac->in_reset = 0; | 1160 | aac->in_reset = 0; |
1152 | scsi_unblock_requests(host); | 1161 | scsi_unblock_requests(host); |
1153 | spin_lock_irq(host->host_lock); | 1162 | if (jafo) { |
1163 | spin_lock_irq(host->host_lock); | ||
1164 | } | ||
1165 | return retval; | ||
1166 | } | ||
1167 | |||
1168 | int aac_reset_adapter(struct aac_dev * aac, int forced) | ||
1169 | { | ||
1170 | unsigned long flagv = 0; | ||
1171 | int retval; | ||
1172 | struct Scsi_Host * host; | ||
1173 | |||
1174 | if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0) | ||
1175 | return -EBUSY; | ||
1176 | |||
1177 | if (aac->in_reset) { | ||
1178 | spin_unlock_irqrestore(&aac->fib_lock, flagv); | ||
1179 | return -EBUSY; | ||
1180 | } | ||
1181 | aac->in_reset = 1; | ||
1182 | spin_unlock_irqrestore(&aac->fib_lock, flagv); | ||
1183 | |||
1184 | /* | ||
1185 | * Wait for all commands to complete to this specific | ||
1186 | * target (block maximum 60 seconds). Although not necessary, | ||
1187 | * it does make us a good storage citizen. | ||
1188 | */ | ||
1189 | host = aac->scsi_host_ptr; | ||
1190 | scsi_block_requests(host); | ||
1191 | if (forced < 2) for (retval = 60; retval; --retval) { | ||
1192 | struct scsi_device * dev; | ||
1193 | struct scsi_cmnd * command; | ||
1194 | int active = 0; | ||
1195 | |||
1196 | __shost_for_each_device(dev, host) { | ||
1197 | spin_lock_irqsave(&dev->list_lock, flagv); | ||
1198 | list_for_each_entry(command, &dev->cmd_list, list) { | ||
1199 | if (command->SCp.phase == AAC_OWNER_FIRMWARE) { | ||
1200 | active++; | ||
1201 | break; | ||
1202 | } | ||
1203 | } | ||
1204 | spin_unlock_irqrestore(&dev->list_lock, flagv); | ||
1205 | if (active) | ||
1206 | break; | ||
1207 | |||
1208 | } | ||
1209 | /* | ||
1210 | * We can exit If all the commands are complete | ||
1211 | */ | ||
1212 | if (active == 0) | ||
1213 | break; | ||
1214 | ssleep(1); | ||
1215 | } | ||
1216 | |||
1217 | /* Quiesce build, flush cache, write through mode */ | ||
1218 | aac_send_shutdown(aac); | ||
1219 | spin_lock_irqsave(host->host_lock, flagv); | ||
1220 | retval = _aac_reset_adapter(aac, forced); | ||
1221 | spin_unlock_irqrestore(host->host_lock, flagv); | ||
1222 | |||
1223 | if (retval == -ENODEV) { | ||
1224 | /* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */ | ||
1225 | struct fib * fibctx = aac_fib_alloc(aac); | ||
1226 | if (fibctx) { | ||
1227 | struct aac_pause *cmd; | ||
1228 | int status; | ||
1229 | |||
1230 | aac_fib_init(fibctx); | ||
1231 | |||
1232 | cmd = (struct aac_pause *) fib_data(fibctx); | ||
1233 | |||
1234 | cmd->command = cpu_to_le32(VM_ContainerConfig); | ||
1235 | cmd->type = cpu_to_le32(CT_PAUSE_IO); | ||
1236 | cmd->timeout = cpu_to_le32(1); | ||
1237 | cmd->min = cpu_to_le32(1); | ||
1238 | cmd->noRescan = cpu_to_le32(1); | ||
1239 | cmd->count = cpu_to_le32(0); | ||
1240 | |||
1241 | status = aac_fib_send(ContainerCommand, | ||
1242 | fibctx, | ||
1243 | sizeof(struct aac_pause), | ||
1244 | FsaNormal, | ||
1245 | -2 /* Timeout silently */, 1, | ||
1246 | NULL, NULL); | ||
1247 | |||
1248 | if (status >= 0) | ||
1249 | aac_fib_complete(fibctx); | ||
1250 | aac_fib_free(fibctx); | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1154 | return retval; | 1254 | return retval; |
1155 | } | 1255 | } |
1156 | 1256 | ||
@@ -1270,10 +1370,15 @@ int aac_check_health(struct aac_dev * aac) | |||
1270 | 1370 | ||
1271 | printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); | 1371 | printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); |
1272 | 1372 | ||
1373 | if (!check_reset || (aac->supplement_adapter_info.SupportedOptions2 & | ||
1374 | le32_to_cpu(AAC_OPTION_IGNORE_RESET))) | ||
1375 | goto out; | ||
1273 | host = aac->scsi_host_ptr; | 1376 | host = aac->scsi_host_ptr; |
1274 | spin_lock_irqsave(host->host_lock, flagv); | 1377 | if (aac->thread->pid != current->pid) |
1275 | BlinkLED = _aac_reset_adapter(aac); | 1378 | spin_lock_irqsave(host->host_lock, flagv); |
1276 | spin_unlock_irqrestore(host->host_lock, flagv); | 1379 | BlinkLED = _aac_reset_adapter(aac, 0); |
1380 | if (aac->thread->pid != current->pid) | ||
1381 | spin_unlock_irqrestore(host->host_lock, flagv); | ||
1277 | return BlinkLED; | 1382 | return BlinkLED; |
1278 | 1383 | ||
1279 | out: | 1384 | out: |
@@ -1300,6 +1405,9 @@ int aac_command_thread(void *data) | |||
1300 | struct aac_fib_context *fibctx; | 1405 | struct aac_fib_context *fibctx; |
1301 | unsigned long flags; | 1406 | unsigned long flags; |
1302 | DECLARE_WAITQUEUE(wait, current); | 1407 | DECLARE_WAITQUEUE(wait, current); |
1408 | unsigned long next_jiffies = jiffies + HZ; | ||
1409 | unsigned long next_check_jiffies = next_jiffies; | ||
1410 | long difference = HZ; | ||
1303 | 1411 | ||
1304 | /* | 1412 | /* |
1305 | * We can only have one thread per adapter for AIF's. | 1413 | * We can only have one thread per adapter for AIF's. |
@@ -1368,7 +1476,7 @@ int aac_command_thread(void *data) | |||
1368 | cpu_to_le32(AifCmdJobProgress))) { | 1476 | cpu_to_le32(AifCmdJobProgress))) { |
1369 | aac_handle_aif(dev, fib); | 1477 | aac_handle_aif(dev, fib); |
1370 | } | 1478 | } |
1371 | 1479 | ||
1372 | time_now = jiffies/HZ; | 1480 | time_now = jiffies/HZ; |
1373 | 1481 | ||
1374 | /* | 1482 | /* |
@@ -1507,11 +1615,79 @@ int aac_command_thread(void *data) | |||
1507 | * There are no more AIF's | 1615 | * There are no more AIF's |
1508 | */ | 1616 | */ |
1509 | spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); | 1617 | spin_unlock_irqrestore(dev->queues->queue[HostNormCmdQueue].lock, flags); |
1510 | schedule(); | 1618 | |
1619 | /* | ||
1620 | * Background activity | ||
1621 | */ | ||
1622 | if ((time_before(next_check_jiffies,next_jiffies)) | ||
1623 | && ((difference = next_check_jiffies - jiffies) <= 0)) { | ||
1624 | next_check_jiffies = next_jiffies; | ||
1625 | if (aac_check_health(dev) == 0) { | ||
1626 | difference = ((long)(unsigned)check_interval) | ||
1627 | * HZ; | ||
1628 | next_check_jiffies = jiffies + difference; | ||
1629 | } else if (!dev->queues) | ||
1630 | break; | ||
1631 | } | ||
1632 | if (!time_before(next_check_jiffies,next_jiffies) | ||
1633 | && ((difference = next_jiffies - jiffies) <= 0)) { | ||
1634 | struct timeval now; | ||
1635 | int ret; | ||
1636 | |||
1637 | /* Don't even try to talk to adapter if its sick */ | ||
1638 | ret = aac_check_health(dev); | ||
1639 | if (!ret && !dev->queues) | ||
1640 | break; | ||
1641 | next_check_jiffies = jiffies | ||
1642 | + ((long)(unsigned)check_interval) | ||
1643 | * HZ; | ||
1644 | do_gettimeofday(&now); | ||
1645 | |||
1646 | /* Synchronize our watches */ | ||
1647 | if (((1000000 - (1000000 / HZ)) > now.tv_usec) | ||
1648 | && (now.tv_usec > (1000000 / HZ))) | ||
1649 | difference = (((1000000 - now.tv_usec) * HZ) | ||
1650 | + 500000) / 1000000; | ||
1651 | else if (ret == 0) { | ||
1652 | struct fib *fibptr; | ||
1653 | |||
1654 | if ((fibptr = aac_fib_alloc(dev))) { | ||
1655 | u32 * info; | ||
1656 | |||
1657 | aac_fib_init(fibptr); | ||
1658 | |||
1659 | info = (u32 *) fib_data(fibptr); | ||
1660 | if (now.tv_usec > 500000) | ||
1661 | ++now.tv_sec; | ||
1662 | |||
1663 | *info = cpu_to_le32(now.tv_sec); | ||
1664 | |||
1665 | (void)aac_fib_send(SendHostTime, | ||
1666 | fibptr, | ||
1667 | sizeof(*info), | ||
1668 | FsaNormal, | ||
1669 | 1, 1, | ||
1670 | NULL, | ||
1671 | NULL); | ||
1672 | aac_fib_complete(fibptr); | ||
1673 | aac_fib_free(fibptr); | ||
1674 | } | ||
1675 | difference = (long)(unsigned)update_interval*HZ; | ||
1676 | } else { | ||
1677 | /* retry shortly */ | ||
1678 | difference = 10 * HZ; | ||
1679 | } | ||
1680 | next_jiffies = jiffies + difference; | ||
1681 | if (time_before(next_check_jiffies,next_jiffies)) | ||
1682 | difference = next_check_jiffies - jiffies; | ||
1683 | } | ||
1684 | if (difference <= 0) | ||
1685 | difference = 1; | ||
1686 | set_current_state(TASK_INTERRUPTIBLE); | ||
1687 | schedule_timeout(difference); | ||
1511 | 1688 | ||
1512 | if (kthread_should_stop()) | 1689 | if (kthread_should_stop()) |
1513 | break; | 1690 | break; |
1514 | set_current_state(TASK_INTERRUPTIBLE); | ||
1515 | } | 1691 | } |
1516 | if (dev->queues) | 1692 | if (dev->queues) |
1517 | remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); | 1693 | remove_wait_queue(&dev->queues->queue[HostNormCmdQueue].cmdready, &wait); |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 5c487ff096c7..d76e1a8cb93a 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -39,10 +39,8 @@ | |||
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
42 | #include <linux/dma-mapping.h> | ||
43 | #include <linux/syscalls.h> | 42 | #include <linux/syscalls.h> |
44 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
45 | #include <linux/smp_lock.h> | ||
46 | #include <linux/kthread.h> | 44 | #include <linux/kthread.h> |
47 | #include <asm/semaphore.h> | 45 | #include <asm/semaphore.h> |
48 | 46 | ||
@@ -223,12 +221,12 @@ static struct aac_driver_ident aac_drivers[] = { | |||
223 | { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ | 221 | { aac_rx_init, "percraid", "DELL ", "PERC 320/DC ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Perc 320/DC*/ |
224 | { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ | 222 | { aac_sa_init, "aacraid", "ADAPTEC ", "Adaptec 5400S ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ |
225 | { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ | 223 | { aac_sa_init, "aacraid", "ADAPTEC ", "AAC-364 ", 4, AAC_QUIRK_34SG }, /* Adaptec 5400S (Mustang)*/ |
226 | { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell PERC2/QC */ | 224 | { aac_sa_init, "percraid", "DELL ", "PERCRAID ", 4, AAC_QUIRK_34SG }, /* Dell PERC2/QC */ |
227 | { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */ | 225 | { aac_sa_init, "hpnraid", "HP ", "NetRAID ", 4, AAC_QUIRK_34SG }, /* HP NetRAID-4M */ |
228 | 226 | ||
229 | { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */ | 227 | { aac_rx_init, "aacraid", "DELL ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Dell Catchall */ |
230 | { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */ | 228 | { aac_rx_init, "aacraid", "Legend ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Legend Catchall */ |
231 | { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec Catch All */ | 229 | { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ |
232 | { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ | 230 | { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ |
233 | { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec NEMER/ARK Catch All */ | 231 | { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec NEMER/ARK Catch All */ |
234 | }; | 232 | }; |
@@ -403,10 +401,6 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, | |||
403 | 401 | ||
404 | static int aac_slave_configure(struct scsi_device *sdev) | 402 | static int aac_slave_configure(struct scsi_device *sdev) |
405 | { | 403 | { |
406 | if (sdev_channel(sdev) == CONTAINER_CHANNEL) { | ||
407 | sdev->skip_ms_page_8 = 1; | ||
408 | sdev->skip_ms_page_3f = 1; | ||
409 | } | ||
410 | if ((sdev->type == TYPE_DISK) && | 404 | if ((sdev->type == TYPE_DISK) && |
411 | (sdev_channel(sdev) != CONTAINER_CHANNEL)) { | 405 | (sdev_channel(sdev) != CONTAINER_CHANNEL)) { |
412 | if (expose_physicals == 0) | 406 | if (expose_physicals == 0) |
@@ -450,6 +444,43 @@ static int aac_slave_configure(struct scsi_device *sdev) | |||
450 | return 0; | 444 | return 0; |
451 | } | 445 | } |
452 | 446 | ||
447 | /** | ||
448 | * aac_change_queue_depth - alter queue depths | ||
449 | * @sdev: SCSI device we are considering | ||
450 | * @depth: desired queue depth | ||
451 | * | ||
452 | * Alters queue depths for target device based on the host adapter's | ||
453 | * total capacity and the queue depth supported by the target device. | ||
454 | */ | ||
455 | |||
456 | static int aac_change_queue_depth(struct scsi_device *sdev, int depth) | ||
457 | { | ||
458 | if (sdev->tagged_supported && (sdev->type == TYPE_DISK) && | ||
459 | (sdev_channel(sdev) == CONTAINER_CHANNEL)) { | ||
460 | struct scsi_device * dev; | ||
461 | struct Scsi_Host *host = sdev->host; | ||
462 | unsigned num = 0; | ||
463 | |||
464 | __shost_for_each_device(dev, host) { | ||
465 | if (dev->tagged_supported && (dev->type == TYPE_DISK) && | ||
466 | (sdev_channel(dev) == CONTAINER_CHANNEL)) | ||
467 | ++num; | ||
468 | ++num; | ||
469 | } | ||
470 | if (num >= host->can_queue) | ||
471 | num = host->can_queue - 1; | ||
472 | if (depth > (host->can_queue - num)) | ||
473 | depth = host->can_queue - num; | ||
474 | if (depth > 256) | ||
475 | depth = 256; | ||
476 | else if (depth < 2) | ||
477 | depth = 2; | ||
478 | scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, depth); | ||
479 | } else | ||
480 | scsi_adjust_queue_depth(sdev, 0, 1); | ||
481 | return sdev->queue_depth; | ||
482 | } | ||
483 | |||
453 | static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) | 484 | static int aac_ioctl(struct scsi_device *sdev, int cmd, void __user * arg) |
454 | { | 485 | { |
455 | struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; | 486 | struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; |
@@ -548,6 +579,14 @@ static int aac_eh_reset(struct scsi_cmnd* cmd) | |||
548 | ssleep(1); | 579 | ssleep(1); |
549 | } | 580 | } |
550 | printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); | 581 | printk(KERN_ERR "%s: SCSI bus appears hung\n", AAC_DRIVERNAME); |
582 | /* | ||
583 | * This adapter needs a blind reset, only do so for Adapters that | ||
584 | * support a register, instead of a commanded, reset. | ||
585 | */ | ||
586 | if ((aac->supplement_adapter_info.SupportedOptions2 & | ||
587 | le32_to_cpu(AAC_OPTION_MU_RESET|AAC_OPTION_IGNORE_RESET)) == | ||
588 | le32_to_cpu(AAC_OPTION_MU_RESET)) | ||
589 | aac_reset_adapter(aac, 2); /* Bypass wait for command quiesce */ | ||
551 | return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */ | 590 | return SUCCESS; /* Cause an immediate retry of the command with a ten second delay after successful tur */ |
552 | } | 591 | } |
553 | 592 | ||
@@ -731,15 +770,21 @@ static ssize_t aac_show_bios_version(struct class_device *class_dev, | |||
731 | return len; | 770 | return len; |
732 | } | 771 | } |
733 | 772 | ||
734 | static ssize_t aac_show_serial_number(struct class_device *class_dev, | 773 | ssize_t aac_show_serial_number(struct class_device *class_dev, char *buf) |
735 | char *buf) | ||
736 | { | 774 | { |
737 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; | 775 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; |
738 | int len = 0; | 776 | int len = 0; |
739 | 777 | ||
740 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) | 778 | if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0) |
741 | len = snprintf(buf, PAGE_SIZE, "%x\n", | 779 | len = snprintf(buf, PAGE_SIZE, "%06X\n", |
742 | le32_to_cpu(dev->adapter_info.serial[0])); | 780 | le32_to_cpu(dev->adapter_info.serial[0])); |
781 | if (len && | ||
782 | !memcmp(&dev->supplement_adapter_info.MfgPcbaSerialNo[ | ||
783 | sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo)+2-len], | ||
784 | buf, len)) | ||
785 | len = snprintf(buf, PAGE_SIZE, "%.*s\n", | ||
786 | (int)sizeof(dev->supplement_adapter_info.MfgPcbaSerialNo), | ||
787 | dev->supplement_adapter_info.MfgPcbaSerialNo); | ||
743 | return len; | 788 | return len; |
744 | } | 789 | } |
745 | 790 | ||
@@ -755,6 +800,31 @@ static ssize_t aac_show_max_id(struct class_device *class_dev, char *buf) | |||
755 | class_to_shost(class_dev)->max_id); | 800 | class_to_shost(class_dev)->max_id); |
756 | } | 801 | } |
757 | 802 | ||
803 | static ssize_t aac_store_reset_adapter(struct class_device *class_dev, | ||
804 | const char *buf, size_t count) | ||
805 | { | ||
806 | int retval = -EACCES; | ||
807 | |||
808 | if (!capable(CAP_SYS_ADMIN)) | ||
809 | return retval; | ||
810 | retval = aac_reset_adapter((struct aac_dev*)class_to_shost(class_dev)->hostdata, buf[0] == '!'); | ||
811 | if (retval >= 0) | ||
812 | retval = count; | ||
813 | return retval; | ||
814 | } | ||
815 | |||
816 | static ssize_t aac_show_reset_adapter(struct class_device *class_dev, | ||
817 | char *buf) | ||
818 | { | ||
819 | struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata; | ||
820 | int len, tmp; | ||
821 | |||
822 | tmp = aac_adapter_check_health(dev); | ||
823 | if ((tmp == 0) && dev->in_reset) | ||
824 | tmp = -EBUSY; | ||
825 | len = snprintf(buf, PAGE_SIZE, "0x%x", tmp); | ||
826 | return len; | ||
827 | } | ||
758 | 828 | ||
759 | static struct class_device_attribute aac_model = { | 829 | static struct class_device_attribute aac_model = { |
760 | .attr = { | 830 | .attr = { |
@@ -812,6 +882,14 @@ static struct class_device_attribute aac_max_id = { | |||
812 | }, | 882 | }, |
813 | .show = aac_show_max_id, | 883 | .show = aac_show_max_id, |
814 | }; | 884 | }; |
885 | static struct class_device_attribute aac_reset = { | ||
886 | .attr = { | ||
887 | .name = "reset_host", | ||
888 | .mode = S_IWUSR|S_IRUGO, | ||
889 | }, | ||
890 | .store = aac_store_reset_adapter, | ||
891 | .show = aac_show_reset_adapter, | ||
892 | }; | ||
815 | 893 | ||
816 | static struct class_device_attribute *aac_attrs[] = { | 894 | static struct class_device_attribute *aac_attrs[] = { |
817 | &aac_model, | 895 | &aac_model, |
@@ -822,6 +900,7 @@ static struct class_device_attribute *aac_attrs[] = { | |||
822 | &aac_serial_number, | 900 | &aac_serial_number, |
823 | &aac_max_channel, | 901 | &aac_max_channel, |
824 | &aac_max_id, | 902 | &aac_max_id, |
903 | &aac_reset, | ||
825 | NULL | 904 | NULL |
826 | }; | 905 | }; |
827 | 906 | ||
@@ -848,6 +927,7 @@ static struct scsi_host_template aac_driver_template = { | |||
848 | .bios_param = aac_biosparm, | 927 | .bios_param = aac_biosparm, |
849 | .shost_attrs = aac_attrs, | 928 | .shost_attrs = aac_attrs, |
850 | .slave_configure = aac_slave_configure, | 929 | .slave_configure = aac_slave_configure, |
930 | .change_queue_depth = aac_change_queue_depth, | ||
851 | .eh_abort_handler = aac_eh_abort, | 931 | .eh_abort_handler = aac_eh_abort, |
852 | .eh_host_reset_handler = aac_eh_reset, | 932 | .eh_host_reset_handler = aac_eh_reset, |
853 | .can_queue = AAC_NUM_IO_FIB, | 933 | .can_queue = AAC_NUM_IO_FIB, |
@@ -1086,7 +1166,7 @@ static int __init aac_init(void) | |||
1086 | { | 1166 | { |
1087 | int error; | 1167 | int error; |
1088 | 1168 | ||
1089 | printk(KERN_INFO "Adaptec %s driver (%s)\n", | 1169 | printk(KERN_INFO "Adaptec %s driver %s\n", |
1090 | AAC_DRIVERNAME, aac_driver_version); | 1170 | AAC_DRIVERNAME, aac_driver_version); |
1091 | 1171 | ||
1092 | error = pci_register_driver(&aac_pci_driver); | 1172 | error = pci_register_driver(&aac_pci_driver); |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index ae978a373c56..ebc65b9fea92 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -464,21 +464,24 @@ static int aac_rx_restart_adapter(struct aac_dev *dev, int bled) | |||
464 | { | 464 | { |
465 | u32 var; | 465 | u32 var; |
466 | 466 | ||
467 | if (bled) | 467 | if (!(dev->supplement_adapter_info.SupportedOptions2 & |
468 | printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", | 468 | le32_to_cpu(AAC_OPTION_MU_RESET)) || (bled >= 0) || (bled == -2)) { |
469 | dev->name, dev->id, bled); | 469 | if (bled) |
470 | else { | 470 | printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", |
471 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, | 471 | dev->name, dev->id, bled); |
472 | 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); | 472 | else { |
473 | if (!bled && (var != 0x00000001)) | 473 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, |
474 | bled = -EINVAL; | 474 | 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); |
475 | } | 475 | if (!bled && (var != 0x00000001)) |
476 | if (bled && (bled != -ETIMEDOUT)) | 476 | bled = -EINVAL; |
477 | bled = aac_adapter_sync_cmd(dev, IOP_RESET, | 477 | } |
478 | 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); | 478 | if (bled && (bled != -ETIMEDOUT)) |
479 | bled = aac_adapter_sync_cmd(dev, IOP_RESET, | ||
480 | 0, 0, 0, 0, 0, 0, &var, NULL, NULL, NULL, NULL); | ||
479 | 481 | ||
480 | if (bled && (bled != -ETIMEDOUT)) | 482 | if (bled && (bled != -ETIMEDOUT)) |
481 | return -EINVAL; | 483 | return -EINVAL; |
484 | } | ||
482 | if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */ | 485 | if (bled || (var == 0x3803000F)) { /* USE_OTHER_METHOD */ |
483 | rx_writel(dev, MUnit.reserved2, 3); | 486 | rx_writel(dev, MUnit.reserved2, 3); |
484 | msleep(5000); /* Delay 5 seconds */ | 487 | msleep(5000); /* Delay 5 seconds */ |
@@ -596,7 +599,7 @@ int _aac_rx_init(struct aac_dev *dev) | |||
596 | } | 599 | } |
597 | msleep(1); | 600 | msleep(1); |
598 | } | 601 | } |
599 | if (restart) | 602 | if (restart && aac_commit) |
600 | aac_commit = 1; | 603 | aac_commit = 1; |
601 | /* | 604 | /* |
602 | * Fill in the common function dispatch table. | 605 | * Fill in the common function dispatch table. |