diff options
69 files changed, 3509 insertions, 2219 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 56a432d51119..f40881b5ad20 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -8653,11 +8653,9 @@ F: drivers/scsi/sg.c | |||
8653 | F: include/scsi/sg.h | 8653 | F: include/scsi/sg.h |
8654 | 8654 | ||
8655 | SCSI SUBSYSTEM | 8655 | SCSI SUBSYSTEM |
8656 | M: "James E.J. Bottomley" <JBottomley@parallels.com> | 8656 | M: "James E.J. Bottomley" <JBottomley@odin.com> |
8657 | L: linux-scsi@vger.kernel.org | 8657 | L: linux-scsi@vger.kernel.org |
8658 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git | 8658 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git |
8659 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6.git | ||
8660 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-pending-2.6.git | ||
8661 | S: Maintained | 8659 | S: Maintained |
8662 | F: drivers/scsi/ | 8660 | F: drivers/scsi/ |
8663 | F: include/scsi/ | 8661 | F: include/scsi/ |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 655e570b9b31..5ea2f0bbbc7c 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -342,7 +342,7 @@ static void virtblk_config_changed_work(struct work_struct *work) | |||
342 | struct request_queue *q = vblk->disk->queue; | 342 | struct request_queue *q = vblk->disk->queue; |
343 | char cap_str_2[10], cap_str_10[10]; | 343 | char cap_str_2[10], cap_str_10[10]; |
344 | char *envp[] = { "RESIZE=1", NULL }; | 344 | char *envp[] = { "RESIZE=1", NULL }; |
345 | u64 capacity, size; | 345 | u64 capacity; |
346 | 346 | ||
347 | /* Host must always specify the capacity. */ | 347 | /* Host must always specify the capacity. */ |
348 | virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity); | 348 | virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity); |
@@ -354,9 +354,10 @@ static void virtblk_config_changed_work(struct work_struct *work) | |||
354 | capacity = (sector_t)-1; | 354 | capacity = (sector_t)-1; |
355 | } | 355 | } |
356 | 356 | ||
357 | size = capacity * queue_logical_block_size(q); | 357 | string_get_size(capacity, queue_logical_block_size(q), |
358 | string_get_size(size, STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); | 358 | STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); |
359 | string_get_size(size, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); | 359 | string_get_size(capacity, queue_logical_block_size(q), |
360 | STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); | ||
360 | 361 | ||
361 | dev_notice(&vdev->dev, | 362 | dev_notice(&vdev->dev, |
362 | "new size: %llu %d-byte logical blocks (%s/%s)\n", | 363 | "new size: %llu %d-byte logical blocks (%s/%s)\n", |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index c69afb5e264e..2fc426926574 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -2230,7 +2230,7 @@ static int mmc_blk_alloc_part(struct mmc_card *card, | |||
2230 | part_md->part_type = part_type; | 2230 | part_md->part_type = part_type; |
2231 | list_add(&part_md->part, &md->part); | 2231 | list_add(&part_md->part, &md->part); |
2232 | 2232 | ||
2233 | string_get_size((u64)get_capacity(part_md->disk) << 9, STRING_UNITS_2, | 2233 | string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2, |
2234 | cap_str, sizeof(cap_str)); | 2234 | cap_str, sizeof(cap_str)); |
2235 | pr_info("%s: %s %s partition %u %s\n", | 2235 | pr_info("%s: %s %s partition %u %s\n", |
2236 | part_md->disk->disk_name, mmc_card_id(card), | 2236 | part_md->disk->disk_name, mmc_card_id(card), |
@@ -2436,7 +2436,7 @@ static int mmc_blk_probe(struct device *dev) | |||
2436 | if (IS_ERR(md)) | 2436 | if (IS_ERR(md)) |
2437 | return PTR_ERR(md); | 2437 | return PTR_ERR(md); |
2438 | 2438 | ||
2439 | string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2, | 2439 | string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, |
2440 | cap_str, sizeof(cap_str)); | 2440 | cap_str, sizeof(cap_str)); |
2441 | pr_info("%s: %s %s %s %s\n", | 2441 | pr_info("%s: %s %s %s %s\n", |
2442 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), | 2442 | md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), |
diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 8981701802ca..a777e5c412df 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c | |||
@@ -474,11 +474,11 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) | |||
474 | */ | 474 | */ |
475 | #ifndef USLEEP_SLEEP | 475 | #ifndef USLEEP_SLEEP |
476 | /* 20 ms (reasonable hard disk speed) */ | 476 | /* 20 ms (reasonable hard disk speed) */ |
477 | #define USLEEP_SLEEP (20*HZ/1000) | 477 | #define USLEEP_SLEEP msecs_to_jiffies(20) |
478 | #endif | 478 | #endif |
479 | /* 300 RPM (floppy speed) */ | 479 | /* 300 RPM (floppy speed) */ |
480 | #ifndef USLEEP_POLL | 480 | #ifndef USLEEP_POLL |
481 | #define USLEEP_POLL (200*HZ/1000) | 481 | #define USLEEP_POLL msecs_to_jiffies(200) |
482 | #endif | 482 | #endif |
483 | #ifndef USLEEP_WAITLONG | 483 | #ifndef USLEEP_WAITLONG |
484 | /* RvC: (reasonable time to wait on select error) */ | 484 | /* RvC: (reasonable time to wait on select error) */ |
@@ -576,7 +576,7 @@ static int __init __maybe_unused NCR5380_probe_irq(struct Scsi_Host *instance, | |||
576 | if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0)) | 576 | if ((mask & possible) && (request_irq(i, &probe_intr, 0, "NCR-probe", NULL) == 0)) |
577 | trying_irqs |= mask; | 577 | trying_irqs |= mask; |
578 | 578 | ||
579 | timeout = jiffies + (250 * HZ / 1000); | 579 | timeout = jiffies + msecs_to_jiffies(250); |
580 | probe_irq = NO_IRQ; | 580 | probe_irq = NO_IRQ; |
581 | 581 | ||
582 | /* | 582 | /* |
@@ -634,7 +634,7 @@ static void prepare_info(struct Scsi_Host *instance) | |||
634 | "sg_tablesize %d, this_id %d, " | 634 | "sg_tablesize %d, this_id %d, " |
635 | "flags { %s%s%s}, " | 635 | "flags { %s%s%s}, " |
636 | #if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG) | 636 | #if defined(USLEEP_POLL) && defined(USLEEP_WAITLONG) |
637 | "USLEEP_POLL %d, USLEEP_WAITLONG %d, " | 637 | "USLEEP_POLL %lu, USLEEP_WAITLONG %lu, " |
638 | #endif | 638 | #endif |
639 | "options { %s} ", | 639 | "options { %s} ", |
640 | instance->hostt->name, instance->io_port, instance->n_io_port, | 640 | instance->hostt->name, instance->io_port, instance->n_io_port, |
@@ -1346,7 +1346,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) | |||
1346 | * selection. | 1346 | * selection. |
1347 | */ | 1347 | */ |
1348 | 1348 | ||
1349 | timeout = jiffies + (250 * HZ / 1000); | 1349 | timeout = jiffies + msecs_to_jiffies(250); |
1350 | 1350 | ||
1351 | /* | 1351 | /* |
1352 | * XXX very interesting - we're seeing a bounce where the BSY we | 1352 | * XXX very interesting - we're seeing a bounce where the BSY we |
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index b32e77db0c48..9b3dd6ef6a0b 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -111,6 +111,41 @@ | |||
111 | #define BYTE2(x) (unsigned char)((x) >> 16) | 111 | #define BYTE2(x) (unsigned char)((x) >> 16) |
112 | #define BYTE3(x) (unsigned char)((x) >> 24) | 112 | #define BYTE3(x) (unsigned char)((x) >> 24) |
113 | 113 | ||
114 | /* MODE_SENSE data format */ | ||
115 | typedef struct { | ||
116 | struct { | ||
117 | u8 data_length; | ||
118 | u8 med_type; | ||
119 | u8 dev_par; | ||
120 | u8 bd_length; | ||
121 | } __attribute__((packed)) hd; | ||
122 | struct { | ||
123 | u8 dens_code; | ||
124 | u8 block_count[3]; | ||
125 | u8 reserved; | ||
126 | u8 block_length[3]; | ||
127 | } __attribute__((packed)) bd; | ||
128 | u8 mpc_buf[3]; | ||
129 | } __attribute__((packed)) aac_modep_data; | ||
130 | |||
131 | /* MODE_SENSE_10 data format */ | ||
132 | typedef struct { | ||
133 | struct { | ||
134 | u8 data_length[2]; | ||
135 | u8 med_type; | ||
136 | u8 dev_par; | ||
137 | u8 rsrvd[2]; | ||
138 | u8 bd_length[2]; | ||
139 | } __attribute__((packed)) hd; | ||
140 | struct { | ||
141 | u8 dens_code; | ||
142 | u8 block_count[3]; | ||
143 | u8 reserved; | ||
144 | u8 block_length[3]; | ||
145 | } __attribute__((packed)) bd; | ||
146 | u8 mpc_buf[3]; | ||
147 | } __attribute__((packed)) aac_modep10_data; | ||
148 | |||
114 | /*------------------------------------------------------------------------------ | 149 | /*------------------------------------------------------------------------------ |
115 | * S T R U C T S / T Y P E D E F S | 150 | * S T R U C T S / T Y P E D E F S |
116 | *----------------------------------------------------------------------------*/ | 151 | *----------------------------------------------------------------------------*/ |
@@ -128,6 +163,48 @@ struct inquiry_data { | |||
128 | u8 inqd_prl[4]; /* Product Revision Level */ | 163 | u8 inqd_prl[4]; /* Product Revision Level */ |
129 | }; | 164 | }; |
130 | 165 | ||
166 | /* Added for VPD 0x83 */ | ||
167 | typedef struct { | ||
168 | u8 CodeSet:4; /* VPD_CODE_SET */ | ||
169 | u8 Reserved:4; | ||
170 | u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */ | ||
171 | u8 Reserved2:4; | ||
172 | u8 Reserved3; | ||
173 | u8 IdentifierLength; | ||
174 | u8 VendId[8]; | ||
175 | u8 ProductId[16]; | ||
176 | u8 SerialNumber[8]; /* SN in ASCII */ | ||
177 | |||
178 | } TVPD_ID_Descriptor_Type_1; | ||
179 | |||
180 | typedef struct { | ||
181 | u8 CodeSet:4; /* VPD_CODE_SET */ | ||
182 | u8 Reserved:4; | ||
183 | u8 IdentifierType:4; /* VPD_IDENTIFIER_TYPE */ | ||
184 | u8 Reserved2:4; | ||
185 | u8 Reserved3; | ||
186 | u8 IdentifierLength; | ||
187 | struct TEU64Id { | ||
188 | u32 Serial; | ||
189 | /* The serial number supposed to be 40 bits, | ||
190 | * bit we only support 32, so make the last byte zero. */ | ||
191 | u8 Reserved; | ||
192 | u8 VendId[3]; | ||
193 | } EU64Id; | ||
194 | |||
195 | } TVPD_ID_Descriptor_Type_2; | ||
196 | |||
197 | typedef struct { | ||
198 | u8 DeviceType:5; | ||
199 | u8 DeviceTypeQualifier:3; | ||
200 | u8 PageCode; | ||
201 | u8 Reserved; | ||
202 | u8 PageLength; | ||
203 | TVPD_ID_Descriptor_Type_1 IdDescriptorType1; | ||
204 | TVPD_ID_Descriptor_Type_2 IdDescriptorType2; | ||
205 | |||
206 | } TVPD_Page83; | ||
207 | |||
131 | /* | 208 | /* |
132 | * M O D U L E G L O B A L S | 209 | * M O D U L E G L O B A L S |
133 | */ | 210 | */ |
@@ -385,6 +462,11 @@ int aac_get_containers(struct aac_dev *dev) | |||
385 | if (status >= 0) { | 462 | if (status >= 0) { |
386 | dresp = (struct aac_get_container_count_resp *)fib_data(fibptr); | 463 | dresp = (struct aac_get_container_count_resp *)fib_data(fibptr); |
387 | maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); | 464 | maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); |
465 | if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & | ||
466 | AAC_OPTION_SUPPORTED_240_VOLUMES) { | ||
467 | maximum_num_containers = | ||
468 | le32_to_cpu(dresp->MaxSimpleVolumes); | ||
469 | } | ||
388 | aac_fib_complete(fibptr); | 470 | aac_fib_complete(fibptr); |
389 | } | 471 | } |
390 | /* FIB should be freed only after getting the response from the F/W */ | 472 | /* FIB should be freed only after getting the response from the F/W */ |
@@ -438,7 +520,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) | |||
438 | if ((le32_to_cpu(get_name_reply->status) == CT_OK) | 520 | if ((le32_to_cpu(get_name_reply->status) == CT_OK) |
439 | && (get_name_reply->data[0] != '\0')) { | 521 | && (get_name_reply->data[0] != '\0')) { |
440 | char *sp = get_name_reply->data; | 522 | char *sp = get_name_reply->data; |
441 | sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; | 523 | sp[sizeof(((struct aac_get_name_resp *)NULL)->data)] = '\0'; |
442 | while (*sp == ' ') | 524 | while (*sp == ' ') |
443 | ++sp; | 525 | ++sp; |
444 | if (*sp) { | 526 | if (*sp) { |
@@ -539,6 +621,14 @@ static void _aac_probe_container2(void * context, struct fib * fibptr) | |||
539 | if ((le32_to_cpu(dresp->status) == ST_OK) && | 621 | if ((le32_to_cpu(dresp->status) == ST_OK) && |
540 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && | 622 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && |
541 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { | 623 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { |
624 | if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 & | ||
625 | AAC_OPTION_VARIABLE_BLOCK_SIZE)) { | ||
626 | dresp->mnt[0].fileinfo.bdevinfo.block_size = 0x200; | ||
627 | fsa_dev_ptr->block_size = 0x200; | ||
628 | } else { | ||
629 | fsa_dev_ptr->block_size = | ||
630 | le32_to_cpu(dresp->mnt[0].fileinfo.bdevinfo.block_size); | ||
631 | } | ||
542 | fsa_dev_ptr->valid = 1; | 632 | fsa_dev_ptr->valid = 1; |
543 | /* sense_key holds the current state of the spin-up */ | 633 | /* sense_key holds the current state of the spin-up */ |
544 | if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) | 634 | if (dresp->mnt[0].state & cpu_to_le32(FSCS_NOT_READY)) |
@@ -571,7 +661,9 @@ static void _aac_probe_container1(void * context, struct fib * fibptr) | |||
571 | int status; | 661 | int status; |
572 | 662 | ||
573 | dresp = (struct aac_mount *) fib_data(fibptr); | 663 | dresp = (struct aac_mount *) fib_data(fibptr); |
574 | dresp->mnt[0].capacityhigh = 0; | 664 | if (!(fibptr->dev->supplement_adapter_info.SupportedOptions2 & |
665 | AAC_OPTION_VARIABLE_BLOCK_SIZE)) | ||
666 | dresp->mnt[0].capacityhigh = 0; | ||
575 | if ((le32_to_cpu(dresp->status) != ST_OK) || | 667 | if ((le32_to_cpu(dresp->status) != ST_OK) || |
576 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { | 668 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) { |
577 | _aac_probe_container2(context, fibptr); | 669 | _aac_probe_container2(context, fibptr); |
@@ -586,7 +678,12 @@ static void _aac_probe_container1(void * context, struct fib * fibptr) | |||
586 | 678 | ||
587 | dinfo = (struct aac_query_mount *)fib_data(fibptr); | 679 | dinfo = (struct aac_query_mount *)fib_data(fibptr); |
588 | 680 | ||
589 | dinfo->command = cpu_to_le32(VM_NameServe64); | 681 | if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & |
682 | AAC_OPTION_VARIABLE_BLOCK_SIZE) | ||
683 | dinfo->command = cpu_to_le32(VM_NameServeAllBlk); | ||
684 | else | ||
685 | dinfo->command = cpu_to_le32(VM_NameServe64); | ||
686 | |||
590 | dinfo->count = cpu_to_le32(scmd_id(scsicmd)); | 687 | dinfo->count = cpu_to_le32(scmd_id(scsicmd)); |
591 | dinfo->type = cpu_to_le32(FT_FILESYS); | 688 | dinfo->type = cpu_to_le32(FT_FILESYS); |
592 | 689 | ||
@@ -621,7 +718,12 @@ static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(stru | |||
621 | 718 | ||
622 | dinfo = (struct aac_query_mount *)fib_data(fibptr); | 719 | dinfo = (struct aac_query_mount *)fib_data(fibptr); |
623 | 720 | ||
624 | dinfo->command = cpu_to_le32(VM_NameServe); | 721 | if (fibptr->dev->supplement_adapter_info.SupportedOptions2 & |
722 | AAC_OPTION_VARIABLE_BLOCK_SIZE) | ||
723 | dinfo->command = cpu_to_le32(VM_NameServeAllBlk); | ||
724 | else | ||
725 | dinfo->command = cpu_to_le32(VM_NameServe); | ||
726 | |||
625 | dinfo->count = cpu_to_le32(scmd_id(scsicmd)); | 727 | dinfo->count = cpu_to_le32(scmd_id(scsicmd)); |
626 | dinfo->type = cpu_to_le32(FT_FILESYS); | 728 | dinfo->type = cpu_to_le32(FT_FILESYS); |
627 | scsicmd->SCp.ptr = (char *)callback; | 729 | scsicmd->SCp.ptr = (char *)callback; |
@@ -835,14 +937,88 @@ static void get_container_serial_callback(void *context, struct fib * fibptr) | |||
835 | get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); | 937 | get_serial_reply = (struct aac_get_serial_resp *) fib_data(fibptr); |
836 | /* Failure is irrelevant, using default value instead */ | 938 | /* Failure is irrelevant, using default value instead */ |
837 | if (le32_to_cpu(get_serial_reply->status) == CT_OK) { | 939 | if (le32_to_cpu(get_serial_reply->status) == CT_OK) { |
838 | char sp[13]; | 940 | /*Check to see if it's for VPD 0x83 or 0x80 */ |
839 | /* EVPD bit set */ | 941 | if (scsicmd->cmnd[2] == 0x83) { |
840 | sp[0] = INQD_PDT_DA; | 942 | /* vpd page 0x83 - Device Identification Page */ |
841 | sp[1] = scsicmd->cmnd[2]; | 943 | int i; |
842 | sp[2] = 0; | 944 | TVPD_Page83 VPDPage83Data; |
843 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", | 945 | |
844 | le32_to_cpu(get_serial_reply->uid)); | 946 | memset(((u8 *)&VPDPage83Data), 0, |
845 | scsi_sg_copy_from_buffer(scsicmd, sp, sizeof(sp)); | 947 | sizeof(VPDPage83Data)); |
948 | |||
949 | /* DIRECT_ACCESS_DEVIC */ | ||
950 | VPDPage83Data.DeviceType = 0; | ||
951 | /* DEVICE_CONNECTED */ | ||
952 | VPDPage83Data.DeviceTypeQualifier = 0; | ||
953 | /* VPD_DEVICE_IDENTIFIERS */ | ||
954 | VPDPage83Data.PageCode = 0x83; | ||
955 | VPDPage83Data.Reserved = 0; | ||
956 | VPDPage83Data.PageLength = | ||
957 | sizeof(VPDPage83Data.IdDescriptorType1) + | ||
958 | sizeof(VPDPage83Data.IdDescriptorType2); | ||
959 | |||
960 | /* T10 Vendor Identifier Field Format */ | ||
961 | /* VpdCodeSetAscii */ | ||
962 | VPDPage83Data.IdDescriptorType1.CodeSet = 2; | ||
963 | /* VpdIdentifierTypeVendorId */ | ||
964 | VPDPage83Data.IdDescriptorType1.IdentifierType = 1; | ||
965 | VPDPage83Data.IdDescriptorType1.IdentifierLength = | ||
966 | sizeof(VPDPage83Data.IdDescriptorType1) - 4; | ||
967 | |||
968 | /* "ADAPTEC " for adaptec */ | ||
969 | memcpy(VPDPage83Data.IdDescriptorType1.VendId, | ||
970 | "ADAPTEC ", | ||
971 | sizeof(VPDPage83Data.IdDescriptorType1.VendId)); | ||
972 | memcpy(VPDPage83Data.IdDescriptorType1.ProductId, | ||
973 | "ARRAY ", | ||
974 | sizeof( | ||
975 | VPDPage83Data.IdDescriptorType1.ProductId)); | ||
976 | |||
977 | /* Convert to ascii based serial number. | ||
978 | * The LSB is the the end. | ||
979 | */ | ||
980 | for (i = 0; i < 8; i++) { | ||
981 | u8 temp = | ||
982 | (u8)((get_serial_reply->uid >> ((7 - i) * 4)) & 0xF); | ||
983 | if (temp > 0x9) { | ||
984 | VPDPage83Data.IdDescriptorType1.SerialNumber[i] = | ||
985 | 'A' + (temp - 0xA); | ||
986 | } else { | ||
987 | VPDPage83Data.IdDescriptorType1.SerialNumber[i] = | ||
988 | '0' + temp; | ||
989 | } | ||
990 | } | ||
991 | |||
992 | /* VpdCodeSetBinary */ | ||
993 | VPDPage83Data.IdDescriptorType2.CodeSet = 1; | ||
994 | /* VpdIdentifierTypeEUI64 */ | ||
995 | VPDPage83Data.IdDescriptorType2.IdentifierType = 2; | ||
996 | VPDPage83Data.IdDescriptorType2.IdentifierLength = | ||
997 | sizeof(VPDPage83Data.IdDescriptorType2) - 4; | ||
998 | |||
999 | VPDPage83Data.IdDescriptorType2.EU64Id.VendId[0] = 0xD0; | ||
1000 | VPDPage83Data.IdDescriptorType2.EU64Id.VendId[1] = 0; | ||
1001 | VPDPage83Data.IdDescriptorType2.EU64Id.VendId[2] = 0; | ||
1002 | |||
1003 | VPDPage83Data.IdDescriptorType2.EU64Id.Serial = | ||
1004 | get_serial_reply->uid; | ||
1005 | VPDPage83Data.IdDescriptorType2.EU64Id.Reserved = 0; | ||
1006 | |||
1007 | /* Move the inquiry data to the response buffer. */ | ||
1008 | scsi_sg_copy_from_buffer(scsicmd, &VPDPage83Data, | ||
1009 | sizeof(VPDPage83Data)); | ||
1010 | } else { | ||
1011 | /* It must be for VPD 0x80 */ | ||
1012 | char sp[13]; | ||
1013 | /* EVPD bit set */ | ||
1014 | sp[0] = INQD_PDT_DA; | ||
1015 | sp[1] = scsicmd->cmnd[2]; | ||
1016 | sp[2] = 0; | ||
1017 | sp[3] = snprintf(sp+4, sizeof(sp)-4, "%08X", | ||
1018 | le32_to_cpu(get_serial_reply->uid)); | ||
1019 | scsi_sg_copy_from_buffer(scsicmd, sp, | ||
1020 | sizeof(sp)); | ||
1021 | } | ||
846 | } | 1022 | } |
847 | 1023 | ||
848 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1024 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
@@ -982,7 +1158,8 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 | |||
982 | memset(readcmd2, 0, sizeof(struct aac_raw_io2)); | 1158 | memset(readcmd2, 0, sizeof(struct aac_raw_io2)); |
983 | readcmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff)); | 1159 | readcmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff)); |
984 | readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 1160 | readcmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
985 | readcmd2->byteCount = cpu_to_le32(count<<9); | 1161 | readcmd2->byteCount = cpu_to_le32(count * |
1162 | dev->fsa_dev[scmd_id(cmd)].block_size); | ||
986 | readcmd2->cid = cpu_to_le16(scmd_id(cmd)); | 1163 | readcmd2->cid = cpu_to_le16(scmd_id(cmd)); |
987 | readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ); | 1164 | readcmd2->flags = cpu_to_le16(RIO2_IO_TYPE_READ); |
988 | ret = aac_build_sgraw2(cmd, readcmd2, | 1165 | ret = aac_build_sgraw2(cmd, readcmd2, |
@@ -997,7 +1174,8 @@ static int aac_read_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 | |||
997 | readcmd = (struct aac_raw_io *) fib_data(fib); | 1174 | readcmd = (struct aac_raw_io *) fib_data(fib); |
998 | readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); | 1175 | readcmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); |
999 | readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 1176 | readcmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
1000 | readcmd->count = cpu_to_le32(count<<9); | 1177 | readcmd->count = cpu_to_le32(count * |
1178 | dev->fsa_dev[scmd_id(cmd)].block_size); | ||
1001 | readcmd->cid = cpu_to_le16(scmd_id(cmd)); | 1179 | readcmd->cid = cpu_to_le16(scmd_id(cmd)); |
1002 | readcmd->flags = cpu_to_le16(RIO_TYPE_READ); | 1180 | readcmd->flags = cpu_to_le16(RIO_TYPE_READ); |
1003 | readcmd->bpTotal = 0; | 1181 | readcmd->bpTotal = 0; |
@@ -1062,6 +1240,7 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 | |||
1062 | { | 1240 | { |
1063 | u16 fibsize; | 1241 | u16 fibsize; |
1064 | struct aac_read *readcmd; | 1242 | struct aac_read *readcmd; |
1243 | struct aac_dev *dev = fib->dev; | ||
1065 | long ret; | 1244 | long ret; |
1066 | 1245 | ||
1067 | aac_fib_init(fib); | 1246 | aac_fib_init(fib); |
@@ -1069,7 +1248,8 @@ static int aac_read_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u32 | |||
1069 | readcmd->command = cpu_to_le32(VM_CtBlockRead); | 1248 | readcmd->command = cpu_to_le32(VM_CtBlockRead); |
1070 | readcmd->cid = cpu_to_le32(scmd_id(cmd)); | 1249 | readcmd->cid = cpu_to_le32(scmd_id(cmd)); |
1071 | readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); | 1250 | readcmd->block = cpu_to_le32((u32)(lba&0xffffffff)); |
1072 | readcmd->count = cpu_to_le32(count * 512); | 1251 | readcmd->count = cpu_to_le32(count * |
1252 | dev->fsa_dev[scmd_id(cmd)].block_size); | ||
1073 | 1253 | ||
1074 | ret = aac_build_sg(cmd, &readcmd->sg); | 1254 | ret = aac_build_sg(cmd, &readcmd->sg); |
1075 | if (ret < 0) | 1255 | if (ret < 0) |
@@ -1104,7 +1284,8 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u | |||
1104 | memset(writecmd2, 0, sizeof(struct aac_raw_io2)); | 1284 | memset(writecmd2, 0, sizeof(struct aac_raw_io2)); |
1105 | writecmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff)); | 1285 | writecmd2->blockLow = cpu_to_le32((u32)(lba&0xffffffff)); |
1106 | writecmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 1286 | writecmd2->blockHigh = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
1107 | writecmd2->byteCount = cpu_to_le32(count<<9); | 1287 | writecmd2->byteCount = cpu_to_le32(count * |
1288 | dev->fsa_dev[scmd_id(cmd)].block_size); | ||
1108 | writecmd2->cid = cpu_to_le16(scmd_id(cmd)); | 1289 | writecmd2->cid = cpu_to_le16(scmd_id(cmd)); |
1109 | writecmd2->flags = (fua && ((aac_cache & 5) != 1) && | 1290 | writecmd2->flags = (fua && ((aac_cache & 5) != 1) && |
1110 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? | 1291 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? |
@@ -1122,7 +1303,8 @@ static int aac_write_raw_io(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u | |||
1122 | writecmd = (struct aac_raw_io *) fib_data(fib); | 1303 | writecmd = (struct aac_raw_io *) fib_data(fib); |
1123 | writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); | 1304 | writecmd->block[0] = cpu_to_le32((u32)(lba&0xffffffff)); |
1124 | writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); | 1305 | writecmd->block[1] = cpu_to_le32((u32)((lba&0xffffffff00000000LL)>>32)); |
1125 | writecmd->count = cpu_to_le32(count<<9); | 1306 | writecmd->count = cpu_to_le32(count * |
1307 | dev->fsa_dev[scmd_id(cmd)].block_size); | ||
1126 | writecmd->cid = cpu_to_le16(scmd_id(cmd)); | 1308 | writecmd->cid = cpu_to_le16(scmd_id(cmd)); |
1127 | writecmd->flags = (fua && ((aac_cache & 5) != 1) && | 1309 | writecmd->flags = (fua && ((aac_cache & 5) != 1) && |
1128 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? | 1310 | (((aac_cache & 5) != 5) || !fib->dev->cache_protected)) ? |
@@ -1190,6 +1372,7 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 | |||
1190 | { | 1372 | { |
1191 | u16 fibsize; | 1373 | u16 fibsize; |
1192 | struct aac_write *writecmd; | 1374 | struct aac_write *writecmd; |
1375 | struct aac_dev *dev = fib->dev; | ||
1193 | long ret; | 1376 | long ret; |
1194 | 1377 | ||
1195 | aac_fib_init(fib); | 1378 | aac_fib_init(fib); |
@@ -1197,7 +1380,8 @@ static int aac_write_block(struct fib * fib, struct scsi_cmnd * cmd, u64 lba, u3 | |||
1197 | writecmd->command = cpu_to_le32(VM_CtBlockWrite); | 1380 | writecmd->command = cpu_to_le32(VM_CtBlockWrite); |
1198 | writecmd->cid = cpu_to_le32(scmd_id(cmd)); | 1381 | writecmd->cid = cpu_to_le32(scmd_id(cmd)); |
1199 | writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); | 1382 | writecmd->block = cpu_to_le32((u32)(lba&0xffffffff)); |
1200 | writecmd->count = cpu_to_le32(count * 512); | 1383 | writecmd->count = cpu_to_le32(count * |
1384 | dev->fsa_dev[scmd_id(cmd)].block_size); | ||
1201 | writecmd->sg.count = cpu_to_le32(1); | 1385 | writecmd->sg.count = cpu_to_le32(1); |
1202 | /* ->stable is not used - it did mean which type of write */ | 1386 | /* ->stable is not used - it did mean which type of write */ |
1203 | 1387 | ||
@@ -2246,9 +2430,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2246 | INQD_PDT_PROC : INQD_PDT_DA; | 2430 | INQD_PDT_PROC : INQD_PDT_DA; |
2247 | if (scsicmd->cmnd[2] == 0) { | 2431 | if (scsicmd->cmnd[2] == 0) { |
2248 | /* supported vital product data pages */ | 2432 | /* supported vital product data pages */ |
2249 | arr[3] = 2; | 2433 | arr[3] = 3; |
2250 | arr[4] = 0x0; | 2434 | arr[4] = 0x0; |
2251 | arr[5] = 0x80; | 2435 | arr[5] = 0x80; |
2436 | arr[6] = 0x83; | ||
2252 | arr[1] = scsicmd->cmnd[2]; | 2437 | arr[1] = scsicmd->cmnd[2]; |
2253 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, | 2438 | scsi_sg_copy_from_buffer(scsicmd, &inq_data, |
2254 | sizeof(inq_data)); | 2439 | sizeof(inq_data)); |
@@ -2264,7 +2449,16 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2264 | if (aac_wwn != 2) | 2449 | if (aac_wwn != 2) |
2265 | return aac_get_container_serial( | 2450 | return aac_get_container_serial( |
2266 | scsicmd); | 2451 | scsicmd); |
2267 | /* SLES 10 SP1 special */ | 2452 | scsicmd->result = DID_OK << 16 | |
2453 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | ||
2454 | } else if (scsicmd->cmnd[2] == 0x83) { | ||
2455 | /* vpd page 0x83 - Device Identification Page */ | ||
2456 | char *sno = (char *)&inq_data; | ||
2457 | sno[3] = setinqserial(dev, &sno[4], | ||
2458 | scmd_id(scsicmd)); | ||
2459 | if (aac_wwn != 2) | ||
2460 | return aac_get_container_serial( | ||
2461 | scsicmd); | ||
2268 | scsicmd->result = DID_OK << 16 | | 2462 | scsicmd->result = DID_OK << 16 | |
2269 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2463 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
2270 | } else { | 2464 | } else { |
@@ -2329,10 +2523,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2329 | cp[5] = (capacity >> 16) & 0xff; | 2523 | cp[5] = (capacity >> 16) & 0xff; |
2330 | cp[6] = (capacity >> 8) & 0xff; | 2524 | cp[6] = (capacity >> 8) & 0xff; |
2331 | cp[7] = (capacity >> 0) & 0xff; | 2525 | cp[7] = (capacity >> 0) & 0xff; |
2332 | cp[8] = 0; | 2526 | cp[8] = (fsa_dev_ptr[cid].block_size >> 24) & 0xff; |
2333 | cp[9] = 0; | 2527 | cp[9] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff; |
2334 | cp[10] = 2; | 2528 | cp[10] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff; |
2335 | cp[11] = 0; | 2529 | cp[11] = (fsa_dev_ptr[cid].block_size) & 0xff; |
2336 | cp[12] = 0; | 2530 | cp[12] = 0; |
2337 | 2531 | ||
2338 | alloc_len = ((scsicmd->cmnd[10] << 24) | 2532 | alloc_len = ((scsicmd->cmnd[10] << 24) |
@@ -2369,10 +2563,10 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2369 | cp[1] = (capacity >> 16) & 0xff; | 2563 | cp[1] = (capacity >> 16) & 0xff; |
2370 | cp[2] = (capacity >> 8) & 0xff; | 2564 | cp[2] = (capacity >> 8) & 0xff; |
2371 | cp[3] = (capacity >> 0) & 0xff; | 2565 | cp[3] = (capacity >> 0) & 0xff; |
2372 | cp[4] = 0; | 2566 | cp[4] = (fsa_dev_ptr[cid].block_size >> 24) & 0xff; |
2373 | cp[5] = 0; | 2567 | cp[5] = (fsa_dev_ptr[cid].block_size >> 16) & 0xff; |
2374 | cp[6] = 2; | 2568 | cp[6] = (fsa_dev_ptr[cid].block_size >> 8) & 0xff; |
2375 | cp[7] = 0; | 2569 | cp[7] = (fsa_dev_ptr[cid].block_size) & 0xff; |
2376 | scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); | 2570 | scsi_sg_copy_from_buffer(scsicmd, cp, sizeof(cp)); |
2377 | /* Do not cache partition table for arrays */ | 2571 | /* Do not cache partition table for arrays */ |
2378 | scsicmd->device->removable = 1; | 2572 | scsicmd->device->removable = 1; |
@@ -2385,30 +2579,79 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2385 | 2579 | ||
2386 | case MODE_SENSE: | 2580 | case MODE_SENSE: |
2387 | { | 2581 | { |
2388 | char mode_buf[7]; | ||
2389 | int mode_buf_length = 4; | 2582 | int mode_buf_length = 4; |
2583 | u32 capacity; | ||
2584 | aac_modep_data mpd; | ||
2585 | |||
2586 | if (fsa_dev_ptr[cid].size <= 0x100000000ULL) | ||
2587 | capacity = fsa_dev_ptr[cid].size - 1; | ||
2588 | else | ||
2589 | capacity = (u32)-1; | ||
2390 | 2590 | ||
2391 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); | 2591 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); |
2392 | mode_buf[0] = 3; /* Mode data length */ | 2592 | memset((char *)&mpd, 0, sizeof(aac_modep_data)); |
2393 | mode_buf[1] = 0; /* Medium type - default */ | 2593 | |
2394 | mode_buf[2] = 0; /* Device-specific param, | 2594 | /* Mode data length */ |
2395 | bit 8: 0/1 = write enabled/protected | 2595 | mpd.hd.data_length = sizeof(mpd.hd) - 1; |
2396 | bit 4: 0/1 = FUA enabled */ | 2596 | /* Medium type - default */ |
2597 | mpd.hd.med_type = 0; | ||
2598 | /* Device-specific param, | ||
2599 | bit 8: 0/1 = write enabled/protected | ||
2600 | bit 4: 0/1 = FUA enabled */ | ||
2601 | mpd.hd.dev_par = 0; | ||
2602 | |||
2397 | if (dev->raw_io_interface && ((aac_cache & 5) != 1)) | 2603 | if (dev->raw_io_interface && ((aac_cache & 5) != 1)) |
2398 | mode_buf[2] = 0x10; | 2604 | mpd.hd.dev_par = 0x10; |
2399 | mode_buf[3] = 0; /* Block descriptor length */ | 2605 | if (scsicmd->cmnd[1] & 0x8) |
2606 | mpd.hd.bd_length = 0; /* Block descriptor length */ | ||
2607 | else { | ||
2608 | mpd.hd.bd_length = sizeof(mpd.bd); | ||
2609 | mpd.hd.data_length += mpd.hd.bd_length; | ||
2610 | mpd.bd.block_length[0] = | ||
2611 | (fsa_dev_ptr[cid].block_size >> 16) & 0xff; | ||
2612 | mpd.bd.block_length[1] = | ||
2613 | (fsa_dev_ptr[cid].block_size >> 8) & 0xff; | ||
2614 | mpd.bd.block_length[2] = | ||
2615 | fsa_dev_ptr[cid].block_size & 0xff; | ||
2616 | |||
2617 | mpd.mpc_buf[0] = scsicmd->cmnd[2]; | ||
2618 | if (scsicmd->cmnd[2] == 0x1C) { | ||
2619 | /* page length */ | ||
2620 | mpd.mpc_buf[1] = 0xa; | ||
2621 | /* Mode data length */ | ||
2622 | mpd.hd.data_length = 23; | ||
2623 | } else { | ||
2624 | /* Mode data length */ | ||
2625 | mpd.hd.data_length = 15; | ||
2626 | } | ||
2627 | |||
2628 | if (capacity > 0xffffff) { | ||
2629 | mpd.bd.block_count[0] = 0xff; | ||
2630 | mpd.bd.block_count[1] = 0xff; | ||
2631 | mpd.bd.block_count[2] = 0xff; | ||
2632 | } else { | ||
2633 | mpd.bd.block_count[0] = (capacity >> 16) & 0xff; | ||
2634 | mpd.bd.block_count[1] = (capacity >> 8) & 0xff; | ||
2635 | mpd.bd.block_count[2] = capacity & 0xff; | ||
2636 | } | ||
2637 | } | ||
2400 | if (((scsicmd->cmnd[2] & 0x3f) == 8) || | 2638 | if (((scsicmd->cmnd[2] & 0x3f) == 8) || |
2401 | ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { | 2639 | ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { |
2402 | mode_buf[0] = 6; | 2640 | mpd.hd.data_length += 3; |
2403 | mode_buf[4] = 8; | 2641 | mpd.mpc_buf[0] = 8; |
2404 | mode_buf[5] = 1; | 2642 | mpd.mpc_buf[1] = 1; |
2405 | mode_buf[6] = ((aac_cache & 6) == 2) | 2643 | mpd.mpc_buf[2] = ((aac_cache & 6) == 2) |
2406 | ? 0 : 0x04; /* WCE */ | 2644 | ? 0 : 0x04; /* WCE */ |
2407 | mode_buf_length = 7; | 2645 | mode_buf_length = sizeof(mpd); |
2408 | if (mode_buf_length > scsicmd->cmnd[4]) | ||
2409 | mode_buf_length = scsicmd->cmnd[4]; | ||
2410 | } | 2646 | } |
2411 | scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length); | 2647 | |
2648 | if (mode_buf_length > scsicmd->cmnd[4]) | ||
2649 | mode_buf_length = scsicmd->cmnd[4]; | ||
2650 | else | ||
2651 | mode_buf_length = sizeof(mpd); | ||
2652 | scsi_sg_copy_from_buffer(scsicmd, | ||
2653 | (char *)&mpd, | ||
2654 | mode_buf_length); | ||
2412 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2655 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
2413 | scsicmd->scsi_done(scsicmd); | 2656 | scsicmd->scsi_done(scsicmd); |
2414 | 2657 | ||
@@ -2416,34 +2659,77 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
2416 | } | 2659 | } |
2417 | case MODE_SENSE_10: | 2660 | case MODE_SENSE_10: |
2418 | { | 2661 | { |
2419 | char mode_buf[11]; | 2662 | u32 capacity; |
2420 | int mode_buf_length = 8; | 2663 | int mode_buf_length = 8; |
2664 | aac_modep10_data mpd10; | ||
2665 | |||
2666 | if (fsa_dev_ptr[cid].size <= 0x100000000ULL) | ||
2667 | capacity = fsa_dev_ptr[cid].size - 1; | ||
2668 | else | ||
2669 | capacity = (u32)-1; | ||
2421 | 2670 | ||
2422 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); | 2671 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); |
2423 | mode_buf[0] = 0; /* Mode data length (MSB) */ | 2672 | memset((char *)&mpd10, 0, sizeof(aac_modep10_data)); |
2424 | mode_buf[1] = 6; /* Mode data length (LSB) */ | 2673 | /* Mode data length (MSB) */ |
2425 | mode_buf[2] = 0; /* Medium type - default */ | 2674 | mpd10.hd.data_length[0] = 0; |
2426 | mode_buf[3] = 0; /* Device-specific param, | 2675 | /* Mode data length (LSB) */ |
2427 | bit 8: 0/1 = write enabled/protected | 2676 | mpd10.hd.data_length[1] = sizeof(mpd10.hd) - 1; |
2428 | bit 4: 0/1 = FUA enabled */ | 2677 | /* Medium type - default */ |
2678 | mpd10.hd.med_type = 0; | ||
2679 | /* Device-specific param, | ||
2680 | bit 8: 0/1 = write enabled/protected | ||
2681 | bit 4: 0/1 = FUA enabled */ | ||
2682 | mpd10.hd.dev_par = 0; | ||
2683 | |||
2429 | if (dev->raw_io_interface && ((aac_cache & 5) != 1)) | 2684 | if (dev->raw_io_interface && ((aac_cache & 5) != 1)) |
2430 | mode_buf[3] = 0x10; | 2685 | mpd10.hd.dev_par = 0x10; |
2431 | mode_buf[4] = 0; /* reserved */ | 2686 | mpd10.hd.rsrvd[0] = 0; /* reserved */ |
2432 | mode_buf[5] = 0; /* reserved */ | 2687 | mpd10.hd.rsrvd[1] = 0; /* reserved */ |
2433 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ | 2688 | if (scsicmd->cmnd[1] & 0x8) { |
2434 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ | 2689 | /* Block descriptor length (MSB) */ |
2690 | mpd10.hd.bd_length[0] = 0; | ||
2691 | /* Block descriptor length (LSB) */ | ||
2692 | mpd10.hd.bd_length[1] = 0; | ||
2693 | } else { | ||
2694 | mpd10.hd.bd_length[0] = 0; | ||
2695 | mpd10.hd.bd_length[1] = sizeof(mpd10.bd); | ||
2696 | |||
2697 | mpd10.hd.data_length[1] += mpd10.hd.bd_length[1]; | ||
2698 | |||
2699 | mpd10.bd.block_length[0] = | ||
2700 | (fsa_dev_ptr[cid].block_size >> 16) & 0xff; | ||
2701 | mpd10.bd.block_length[1] = | ||
2702 | (fsa_dev_ptr[cid].block_size >> 8) & 0xff; | ||
2703 | mpd10.bd.block_length[2] = | ||
2704 | fsa_dev_ptr[cid].block_size & 0xff; | ||
2705 | |||
2706 | if (capacity > 0xffffff) { | ||
2707 | mpd10.bd.block_count[0] = 0xff; | ||
2708 | mpd10.bd.block_count[1] = 0xff; | ||
2709 | mpd10.bd.block_count[2] = 0xff; | ||
2710 | } else { | ||
2711 | mpd10.bd.block_count[0] = | ||
2712 | (capacity >> 16) & 0xff; | ||
2713 | mpd10.bd.block_count[1] = | ||
2714 | (capacity >> 8) & 0xff; | ||
2715 | mpd10.bd.block_count[2] = | ||
2716 | capacity & 0xff; | ||
2717 | } | ||
2718 | } | ||
2435 | if (((scsicmd->cmnd[2] & 0x3f) == 8) || | 2719 | if (((scsicmd->cmnd[2] & 0x3f) == 8) || |
2436 | ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { | 2720 | ((scsicmd->cmnd[2] & 0x3f) == 0x3f)) { |
2437 | mode_buf[1] = 9; | 2721 | mpd10.hd.data_length[1] += 3; |
2438 | mode_buf[8] = 8; | 2722 | mpd10.mpc_buf[0] = 8; |
2439 | mode_buf[9] = 1; | 2723 | mpd10.mpc_buf[1] = 1; |
2440 | mode_buf[10] = ((aac_cache & 6) == 2) | 2724 | mpd10.mpc_buf[2] = ((aac_cache & 6) == 2) |
2441 | ? 0 : 0x04; /* WCE */ | 2725 | ? 0 : 0x04; /* WCE */ |
2442 | mode_buf_length = 11; | 2726 | mode_buf_length = sizeof(mpd10); |
2443 | if (mode_buf_length > scsicmd->cmnd[8]) | 2727 | if (mode_buf_length > scsicmd->cmnd[8]) |
2444 | mode_buf_length = scsicmd->cmnd[8]; | 2728 | mode_buf_length = scsicmd->cmnd[8]; |
2445 | } | 2729 | } |
2446 | scsi_sg_copy_from_buffer(scsicmd, mode_buf, mode_buf_length); | 2730 | scsi_sg_copy_from_buffer(scsicmd, |
2731 | (char *)&mpd10, | ||
2732 | mode_buf_length); | ||
2447 | 2733 | ||
2448 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 2734 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
2449 | scsicmd->scsi_done(scsicmd); | 2735 | scsicmd->scsi_done(scsicmd); |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index eaaf8705a5f4..40fe65c91b41 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h | |||
@@ -6,13 +6,63 @@ | |||
6 | #define nblank(x) _nblank(x)[0] | 6 | #define nblank(x) _nblank(x)[0] |
7 | 7 | ||
8 | #include <linux/interrupt.h> | 8 | #include <linux/interrupt.h> |
9 | #include <linux/pci.h> | ||
9 | 10 | ||
10 | /*------------------------------------------------------------------------------ | 11 | /*------------------------------------------------------------------------------ |
11 | * D E F I N E S | 12 | * D E F I N E S |
12 | *----------------------------------------------------------------------------*/ | 13 | *----------------------------------------------------------------------------*/ |
13 | 14 | ||
15 | #define AAC_MAX_MSIX 8 /* vectors */ | ||
16 | #define AAC_PCI_MSI_ENABLE 0x8000 | ||
17 | |||
18 | enum { | ||
19 | AAC_ENABLE_INTERRUPT = 0x0, | ||
20 | AAC_DISABLE_INTERRUPT, | ||
21 | AAC_ENABLE_MSIX, | ||
22 | AAC_DISABLE_MSIX, | ||
23 | AAC_CLEAR_AIF_BIT, | ||
24 | AAC_CLEAR_SYNC_BIT, | ||
25 | AAC_ENABLE_INTX | ||
26 | }; | ||
27 | |||
28 | #define AAC_INT_MODE_INTX (1<<0) | ||
29 | #define AAC_INT_MODE_MSI (1<<1) | ||
30 | #define AAC_INT_MODE_AIF (1<<2) | ||
31 | #define AAC_INT_MODE_SYNC (1<<3) | ||
32 | |||
33 | #define AAC_INT_ENABLE_TYPE1_INTX 0xfffffffb | ||
34 | #define AAC_INT_ENABLE_TYPE1_MSIX 0xfffffffa | ||
35 | #define AAC_INT_DISABLE_ALL 0xffffffff | ||
36 | |||
37 | /* Bit definitions in IOA->Host Interrupt Register */ | ||
38 | #define PMC_TRANSITION_TO_OPERATIONAL (1<<31) | ||
39 | #define PMC_IOARCB_TRANSFER_FAILED (1<<28) | ||
40 | #define PMC_IOA_UNIT_CHECK (1<<27) | ||
41 | #define PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE (1<<26) | ||
42 | #define PMC_CRITICAL_IOA_OP_IN_PROGRESS (1<<25) | ||
43 | #define PMC_IOARRIN_LOST (1<<4) | ||
44 | #define PMC_SYSTEM_BUS_MMIO_ERROR (1<<3) | ||
45 | #define PMC_IOA_PROCESSOR_IN_ERROR_STATE (1<<2) | ||
46 | #define PMC_HOST_RRQ_VALID (1<<1) | ||
47 | #define PMC_OPERATIONAL_STATUS (1<<31) | ||
48 | #define PMC_ALLOW_MSIX_VECTOR0 (1<<0) | ||
49 | |||
50 | #define PMC_IOA_ERROR_INTERRUPTS (PMC_IOARCB_TRANSFER_FAILED | \ | ||
51 | PMC_IOA_UNIT_CHECK | \ | ||
52 | PMC_NO_HOST_RRQ_FOR_CMD_RESPONSE | \ | ||
53 | PMC_IOARRIN_LOST | \ | ||
54 | PMC_SYSTEM_BUS_MMIO_ERROR | \ | ||
55 | PMC_IOA_PROCESSOR_IN_ERROR_STATE) | ||
56 | |||
57 | #define PMC_ALL_INTERRUPT_BITS (PMC_IOA_ERROR_INTERRUPTS | \ | ||
58 | PMC_HOST_RRQ_VALID | \ | ||
59 | PMC_TRANSITION_TO_OPERATIONAL | \ | ||
60 | PMC_ALLOW_MSIX_VECTOR0) | ||
61 | #define PMC_GLOBAL_INT_BIT2 0x00000004 | ||
62 | #define PMC_GLOBAL_INT_BIT0 0x00000001 | ||
63 | |||
14 | #ifndef AAC_DRIVER_BUILD | 64 | #ifndef AAC_DRIVER_BUILD |
15 | # define AAC_DRIVER_BUILD 30300 | 65 | # define AAC_DRIVER_BUILD 40709 |
16 | # define AAC_DRIVER_BRANCH "-ms" | 66 | # define AAC_DRIVER_BRANCH "-ms" |
17 | #endif | 67 | #endif |
18 | #define MAXIMUM_NUM_CONTAINERS 32 | 68 | #define MAXIMUM_NUM_CONTAINERS 32 |
@@ -36,6 +86,7 @@ | |||
36 | #define CONTAINER_TO_ID(cont) (cont) | 86 | #define CONTAINER_TO_ID(cont) (cont) |
37 | #define CONTAINER_TO_LUN(cont) (0) | 87 | #define CONTAINER_TO_LUN(cont) (0) |
38 | 88 | ||
89 | #define PMC_DEVICE_S6 0x28b | ||
39 | #define PMC_DEVICE_S7 0x28c | 90 | #define PMC_DEVICE_S7 0x28c |
40 | #define PMC_DEVICE_S8 0x28d | 91 | #define PMC_DEVICE_S8 0x28d |
41 | #define PMC_DEVICE_S9 0x28f | 92 | #define PMC_DEVICE_S9 0x28f |
@@ -434,7 +485,7 @@ enum fib_xfer_state { | |||
434 | struct aac_init | 485 | struct aac_init |
435 | { | 486 | { |
436 | __le32 InitStructRevision; | 487 | __le32 InitStructRevision; |
437 | __le32 MiniPortRevision; | 488 | __le32 Sa_MSIXVectors; |
438 | __le32 fsrev; | 489 | __le32 fsrev; |
439 | __le32 CommHeaderAddress; | 490 | __le32 CommHeaderAddress; |
440 | __le32 FastIoCommAreaAddress; | 491 | __le32 FastIoCommAreaAddress; |
@@ -582,7 +633,8 @@ struct aac_queue { | |||
582 | spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ | 633 | spinlock_t lockdata; /* Actual lock (used only on one side of the lock) */ |
583 | struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ | 634 | struct list_head cmdq; /* A queue of FIBs which need to be prcessed by the FS thread. This is */ |
584 | /* only valid for command queues which receive entries from the adapter. */ | 635 | /* only valid for command queues which receive entries from the adapter. */ |
585 | u32 numpending; /* Number of entries on outstanding queue. */ | 636 | /* Number of entries on outstanding queue. */ |
637 | atomic_t numpending; | ||
586 | struct aac_dev * dev; /* Back pointer to adapter structure */ | 638 | struct aac_dev * dev; /* Back pointer to adapter structure */ |
587 | }; | 639 | }; |
588 | 640 | ||
@@ -755,7 +807,8 @@ struct rkt_registers { | |||
755 | 807 | ||
756 | struct src_mu_registers { | 808 | struct src_mu_registers { |
757 | /* PCI*| Name */ | 809 | /* PCI*| Name */ |
758 | __le32 reserved0[8]; /* 00h | Reserved */ | 810 | __le32 reserved0[6]; /* 00h | Reserved */ |
811 | __le32 IOAR[2]; /* 18h | IOA->host interrupt register */ | ||
759 | __le32 IDR; /* 20h | Inbound Doorbell Register */ | 812 | __le32 IDR; /* 20h | Inbound Doorbell Register */ |
760 | __le32 IISR; /* 24h | Inbound Int. Status Register */ | 813 | __le32 IISR; /* 24h | Inbound Int. Status Register */ |
761 | __le32 reserved1[3]; /* 28h | Reserved */ | 814 | __le32 reserved1[3]; /* 28h | Reserved */ |
@@ -767,17 +820,18 @@ struct src_mu_registers { | |||
767 | __le32 OMR; /* bch | Outbound Message Register */ | 820 | __le32 OMR; /* bch | Outbound Message Register */ |
768 | __le32 IQ_L; /* c0h | Inbound Queue (Low address) */ | 821 | __le32 IQ_L; /* c0h | Inbound Queue (Low address) */ |
769 | __le32 IQ_H; /* c4h | Inbound Queue (High address) */ | 822 | __le32 IQ_H; /* c4h | Inbound Queue (High address) */ |
823 | __le32 ODR_MSI; /* c8h | MSI register for sync./AIF */ | ||
770 | }; | 824 | }; |
771 | 825 | ||
772 | struct src_registers { | 826 | struct src_registers { |
773 | struct src_mu_registers MUnit; /* 00h - c7h */ | 827 | struct src_mu_registers MUnit; /* 00h - cbh */ |
774 | union { | 828 | union { |
775 | struct { | 829 | struct { |
776 | __le32 reserved1[130790]; /* c8h - 7fc5fh */ | 830 | __le32 reserved1[130789]; /* cch - 7fc5fh */ |
777 | struct src_inbound IndexRegs; /* 7fc60h */ | 831 | struct src_inbound IndexRegs; /* 7fc60h */ |
778 | } tupelo; | 832 | } tupelo; |
779 | struct { | 833 | struct { |
780 | __le32 reserved1[974]; /* c8h - fffh */ | 834 | __le32 reserved1[973]; /* cch - fffh */ |
781 | struct src_inbound IndexRegs; /* 1000h */ | 835 | struct src_inbound IndexRegs; /* 1000h */ |
782 | } denali; | 836 | } denali; |
783 | } u; | 837 | } u; |
@@ -857,6 +911,7 @@ struct fsa_dev_info { | |||
857 | u8 deleted; | 911 | u8 deleted; |
858 | char devname[8]; | 912 | char devname[8]; |
859 | struct sense_data sense_data; | 913 | struct sense_data sense_data; |
914 | u32 block_size; | ||
860 | }; | 915 | }; |
861 | 916 | ||
862 | struct fib { | 917 | struct fib { |
@@ -960,6 +1015,10 @@ struct aac_supplement_adapter_info | |||
960 | #define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002) | 1015 | #define AAC_OPTION_IGNORE_RESET cpu_to_le32(0x00000002) |
961 | #define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) | 1016 | #define AAC_OPTION_POWER_MANAGEMENT cpu_to_le32(0x00000004) |
962 | #define AAC_OPTION_DOORBELL_RESET cpu_to_le32(0x00004000) | 1017 | #define AAC_OPTION_DOORBELL_RESET cpu_to_le32(0x00004000) |
1018 | /* 4KB sector size */ | ||
1019 | #define AAC_OPTION_VARIABLE_BLOCK_SIZE cpu_to_le32(0x00040000) | ||
1020 | /* 240 simple volume support */ | ||
1021 | #define AAC_OPTION_SUPPORTED_240_VOLUMES cpu_to_le32(0x10000000) | ||
963 | #define AAC_SIS_VERSION_V3 3 | 1022 | #define AAC_SIS_VERSION_V3 3 |
964 | #define AAC_SIS_SLOT_UNKNOWN 0xFF | 1023 | #define AAC_SIS_SLOT_UNKNOWN 0xFF |
965 | 1024 | ||
@@ -1026,6 +1085,11 @@ struct aac_bus_info_response { | |||
1026 | #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) | 1085 | #define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30) |
1027 | #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) | 1086 | #define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31) |
1028 | 1087 | ||
1088 | /* MSIX context */ | ||
1089 | struct aac_msix_ctx { | ||
1090 | int vector_no; | ||
1091 | struct aac_dev *dev; | ||
1092 | }; | ||
1029 | 1093 | ||
1030 | struct aac_dev | 1094 | struct aac_dev |
1031 | { | 1095 | { |
@@ -1081,8 +1145,10 @@ struct aac_dev | |||
1081 | * if AAC_COMM_MESSAGE_TYPE1 */ | 1145 | * if AAC_COMM_MESSAGE_TYPE1 */ |
1082 | 1146 | ||
1083 | dma_addr_t host_rrq_pa; /* phys. address */ | 1147 | dma_addr_t host_rrq_pa; /* phys. address */ |
1084 | u32 host_rrq_idx; /* index into rrq buffer */ | 1148 | /* index into rrq buffer */ |
1085 | 1149 | u32 host_rrq_idx[AAC_MAX_MSIX]; | |
1150 | atomic_t rrq_outstanding[AAC_MAX_MSIX]; | ||
1151 | u32 fibs_pushed_no; | ||
1086 | struct pci_dev *pdev; /* Our PCI interface */ | 1152 | struct pci_dev *pdev; /* Our PCI interface */ |
1087 | void * printfbuf; /* pointer to buffer used for printf's from the adapter */ | 1153 | void * printfbuf; /* pointer to buffer used for printf's from the adapter */ |
1088 | void * comm_addr; /* Base address of Comm area */ | 1154 | void * comm_addr; /* Base address of Comm area */ |
@@ -1151,6 +1217,13 @@ struct aac_dev | |||
1151 | int sync_mode; | 1217 | int sync_mode; |
1152 | struct fib *sync_fib; | 1218 | struct fib *sync_fib; |
1153 | struct list_head sync_fib_list; | 1219 | struct list_head sync_fib_list; |
1220 | u32 doorbell_mask; | ||
1221 | u32 max_msix; /* max. MSI-X vectors */ | ||
1222 | u32 vector_cap; /* MSI-X vector capab.*/ | ||
1223 | int msi_enabled; /* MSI/MSI-X enabled */ | ||
1224 | struct msix_entry msixentry[AAC_MAX_MSIX]; | ||
1225 | struct aac_msix_ctx aac_msix[AAC_MAX_MSIX]; /* context */ | ||
1226 | u8 adapter_shutdown; | ||
1154 | }; | 1227 | }; |
1155 | 1228 | ||
1156 | #define aac_adapter_interrupt(dev) \ | 1229 | #define aac_adapter_interrupt(dev) \ |
@@ -1589,6 +1662,7 @@ struct aac_srb_reply | |||
1589 | #define VM_CtHostWrite64 20 | 1662 | #define VM_CtHostWrite64 20 |
1590 | #define VM_DrvErrTblLog 21 | 1663 | #define VM_DrvErrTblLog 21 |
1591 | #define VM_NameServe64 22 | 1664 | #define VM_NameServe64 22 |
1665 | #define VM_NameServeAllBlk 30 | ||
1592 | 1666 | ||
1593 | #define MAX_VMCOMMAND_NUM 23 /* used for sizing stats array - leave last */ | 1667 | #define MAX_VMCOMMAND_NUM 23 /* used for sizing stats array - leave last */ |
1594 | 1668 | ||
@@ -1611,8 +1685,13 @@ struct aac_fsinfo { | |||
1611 | __le32 fsInodeDensity; | 1685 | __le32 fsInodeDensity; |
1612 | }; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */ | 1686 | }; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */ |
1613 | 1687 | ||
1688 | struct aac_blockdevinfo { | ||
1689 | __le32 block_size; | ||
1690 | }; | ||
1691 | |||
1614 | union aac_contentinfo { | 1692 | union aac_contentinfo { |
1615 | struct aac_fsinfo filesys; /* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */ | 1693 | struct aac_fsinfo filesys; |
1694 | struct aac_blockdevinfo bdevinfo; | ||
1616 | }; | 1695 | }; |
1617 | 1696 | ||
1618 | /* | 1697 | /* |
@@ -1677,6 +1756,7 @@ struct aac_get_container_count_resp { | |||
1677 | __le32 MaxContainers; | 1756 | __le32 MaxContainers; |
1678 | __le32 ContainerSwitchEntries; | 1757 | __le32 ContainerSwitchEntries; |
1679 | __le32 MaxPartitions; | 1758 | __le32 MaxPartitions; |
1759 | __le32 MaxSimpleVolumes; | ||
1680 | }; | 1760 | }; |
1681 | 1761 | ||
1682 | 1762 | ||
@@ -1951,6 +2031,8 @@ extern struct aac_common aac_config; | |||
1951 | #define AifEnEnclosureManagement 13 /* EM_DRIVE_* */ | 2031 | #define AifEnEnclosureManagement 13 /* EM_DRIVE_* */ |
1952 | #define EM_DRIVE_INSERTION 31 | 2032 | #define EM_DRIVE_INSERTION 31 |
1953 | #define EM_DRIVE_REMOVAL 32 | 2033 | #define EM_DRIVE_REMOVAL 32 |
2034 | #define EM_SES_DRIVE_INSERTION 33 | ||
2035 | #define EM_SES_DRIVE_REMOVAL 26 | ||
1954 | #define AifEnBatteryEvent 14 /* Change in Battery State */ | 2036 | #define AifEnBatteryEvent 14 /* Change in Battery State */ |
1955 | #define AifEnAddContainer 15 /* A new array was created */ | 2037 | #define AifEnAddContainer 15 /* A new array was created */ |
1956 | #define AifEnDeleteContainer 16 /* A container was deleted */ | 2038 | #define AifEnDeleteContainer 16 /* A container was deleted */ |
@@ -1983,6 +2065,9 @@ extern struct aac_common aac_config; | |||
1983 | /* PMC NEW COMM: Request the event data */ | 2065 | /* PMC NEW COMM: Request the event data */ |
1984 | #define AifReqEvent 200 | 2066 | #define AifReqEvent 200 |
1985 | 2067 | ||
2068 | /* RAW device deleted */ | ||
2069 | #define AifRawDeviceRemove 203 | ||
2070 | |||
1986 | /* | 2071 | /* |
1987 | * Adapter Initiated FIB command structures. Start with the adapter | 2072 | * Adapter Initiated FIB command structures. Start with the adapter |
1988 | * initiated FIBs that really come from the adapter, and get responded | 2073 | * initiated FIBs that really come from the adapter, and get responded |
@@ -2025,6 +2110,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum); | |||
2025 | int aac_fib_complete(struct fib * context); | 2110 | int aac_fib_complete(struct fib * context); |
2026 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) | 2111 | #define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data) |
2027 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); | 2112 | struct aac_dev *aac_init_adapter(struct aac_dev *dev); |
2113 | void aac_src_access_devreg(struct aac_dev *dev, int mode); | ||
2028 | int aac_get_config_status(struct aac_dev *dev, int commit_flag); | 2114 | int aac_get_config_status(struct aac_dev *dev, int commit_flag); |
2029 | int aac_get_containers(struct aac_dev *dev); | 2115 | int aac_get_containers(struct aac_dev *dev); |
2030 | int aac_scsi_cmd(struct scsi_cmnd *cmd); | 2116 | int aac_scsi_cmd(struct scsi_cmnd *cmd); |
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index fbcd48d0bfc3..54195a117f72 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -689,7 +689,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
689 | kfree (usg); | 689 | kfree (usg); |
690 | } | 690 | } |
691 | srbcmd->count = cpu_to_le32(byte_count); | 691 | srbcmd->count = cpu_to_le32(byte_count); |
692 | psg->count = cpu_to_le32(sg_indx+1); | 692 | if (user_srbcmd->sg.count) |
693 | psg->count = cpu_to_le32(sg_indx+1); | ||
694 | else | ||
695 | psg->count = 0; | ||
693 | status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); | 696 | status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); |
694 | } else { | 697 | } else { |
695 | struct user_sgmap* upsg = &user_srbcmd->sg; | 698 | struct user_sgmap* upsg = &user_srbcmd->sg; |
@@ -775,7 +778,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
775 | } | 778 | } |
776 | } | 779 | } |
777 | srbcmd->count = cpu_to_le32(byte_count); | 780 | srbcmd->count = cpu_to_le32(byte_count); |
778 | psg->count = cpu_to_le32(sg_indx+1); | 781 | if (user_srbcmd->sg.count) |
782 | psg->count = cpu_to_le32(sg_indx+1); | ||
783 | else | ||
784 | psg->count = 0; | ||
779 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); | 785 | status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); |
780 | } | 786 | } |
781 | if (status == -ERESTARTSYS) { | 787 | if (status == -ERESTARTSYS) { |
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 177b094c7792..45db84ad322f 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -43,6 +43,8 @@ | |||
43 | 43 | ||
44 | #include "aacraid.h" | 44 | #include "aacraid.h" |
45 | 45 | ||
46 | static void aac_define_int_mode(struct aac_dev *dev); | ||
47 | |||
46 | struct aac_common aac_config = { | 48 | struct aac_common aac_config = { |
47 | .irq_mod = 1 | 49 | .irq_mod = 1 |
48 | }; | 50 | }; |
@@ -51,7 +53,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
51 | { | 53 | { |
52 | unsigned char *base; | 54 | unsigned char *base; |
53 | unsigned long size, align; | 55 | unsigned long size, align; |
54 | const unsigned long fibsize = 4096; | 56 | const unsigned long fibsize = dev->max_fib_size; |
55 | const unsigned long printfbufsiz = 256; | 57 | const unsigned long printfbufsiz = 256; |
56 | unsigned long host_rrq_size = 0; | 58 | unsigned long host_rrq_size = 0; |
57 | struct aac_init *init; | 59 | struct aac_init *init; |
@@ -91,7 +93,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
91 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); | 93 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); |
92 | if (dev->max_fib_size != sizeof(struct hw_fib)) | 94 | if (dev->max_fib_size != sizeof(struct hw_fib)) |
93 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); | 95 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); |
94 | init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION); | 96 | init->Sa_MSIXVectors = cpu_to_le32(Sa_MINIPORT_REVISION); |
95 | init->fsrev = cpu_to_le32(dev->fsrev); | 97 | init->fsrev = cpu_to_le32(dev->fsrev); |
96 | 98 | ||
97 | /* | 99 | /* |
@@ -140,7 +142,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
140 | INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); | 142 | INITFLAGS_NEW_COMM_TYPE2_SUPPORTED | INITFLAGS_FAST_JBOD_SUPPORTED); |
141 | init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); | 143 | init->HostRRQ_AddrHigh = cpu_to_le32((u32)((u64)dev->host_rrq_pa >> 32)); |
142 | init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); | 144 | init->HostRRQ_AddrLow = cpu_to_le32((u32)(dev->host_rrq_pa & 0xffffffff)); |
143 | init->MiniPortRevision = cpu_to_le32(0L); /* number of MSI-X */ | 145 | /* number of MSI-X */ |
146 | init->Sa_MSIXVectors = cpu_to_le32(dev->max_msix); | ||
144 | dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); | 147 | dprintk((KERN_WARNING"aacraid: New Comm Interface type2 enabled\n")); |
145 | } | 148 | } |
146 | 149 | ||
@@ -179,7 +182,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
179 | 182 | ||
180 | static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) | 183 | static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize) |
181 | { | 184 | { |
182 | q->numpending = 0; | 185 | atomic_set(&q->numpending, 0); |
183 | q->dev = dev; | 186 | q->dev = dev; |
184 | init_waitqueue_head(&q->cmdready); | 187 | init_waitqueue_head(&q->cmdready); |
185 | INIT_LIST_HEAD(&q->cmdq); | 188 | INIT_LIST_HEAD(&q->cmdq); |
@@ -228,6 +231,12 @@ int aac_send_shutdown(struct aac_dev * dev) | |||
228 | /* FIB should be freed only after getting the response from the F/W */ | 231 | /* FIB should be freed only after getting the response from the F/W */ |
229 | if (status != -ERESTARTSYS) | 232 | if (status != -ERESTARTSYS) |
230 | aac_fib_free(fibctx); | 233 | aac_fib_free(fibctx); |
234 | dev->adapter_shutdown = 1; | ||
235 | if ((dev->pdev->device == PMC_DEVICE_S7 || | ||
236 | dev->pdev->device == PMC_DEVICE_S8 || | ||
237 | dev->pdev->device == PMC_DEVICE_S9) && | ||
238 | dev->msi_enabled) | ||
239 | aac_src_access_devreg(dev, AAC_ENABLE_INTX); | ||
231 | return status; | 240 | return status; |
232 | } | 241 | } |
233 | 242 | ||
@@ -350,8 +359,10 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
350 | dev->raw_io_interface = dev->raw_io_64 = 0; | 359 | dev->raw_io_interface = dev->raw_io_64 = 0; |
351 | 360 | ||
352 | if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, | 361 | if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, |
353 | 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && | 362 | 0, 0, 0, 0, 0, 0, |
363 | status+0, status+1, status+2, status+3, NULL)) && | ||
354 | (status[0] == 0x00000001)) { | 364 | (status[0] == 0x00000001)) { |
365 | dev->doorbell_mask = status[3]; | ||
355 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) | 366 | if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) |
356 | dev->raw_io_64 = 1; | 367 | dev->raw_io_64 = 1; |
357 | dev->sync_mode = aac_sync_mode; | 368 | dev->sync_mode = aac_sync_mode; |
@@ -388,6 +399,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
388 | } | 399 | } |
389 | } | 400 | } |
390 | } | 401 | } |
402 | dev->max_msix = 0; | ||
403 | dev->msi_enabled = 0; | ||
404 | dev->adapter_shutdown = 0; | ||
391 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, | 405 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, |
392 | 0, 0, 0, 0, 0, 0, | 406 | 0, 0, 0, 0, 0, 0, |
393 | status+0, status+1, status+2, status+3, status+4)) | 407 | status+0, status+1, status+2, status+3, status+4)) |
@@ -461,6 +475,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
461 | if (host->can_queue > AAC_NUM_IO_FIB) | 475 | if (host->can_queue > AAC_NUM_IO_FIB) |
462 | host->can_queue = AAC_NUM_IO_FIB; | 476 | host->can_queue = AAC_NUM_IO_FIB; |
463 | 477 | ||
478 | if (dev->pdev->device == PMC_DEVICE_S6 || | ||
479 | dev->pdev->device == PMC_DEVICE_S7 || | ||
480 | dev->pdev->device == PMC_DEVICE_S8 || | ||
481 | dev->pdev->device == PMC_DEVICE_S9) | ||
482 | aac_define_int_mode(dev); | ||
464 | /* | 483 | /* |
465 | * Ok now init the communication subsystem | 484 | * Ok now init the communication subsystem |
466 | */ | 485 | */ |
@@ -489,4 +508,79 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) | |||
489 | return dev; | 508 | return dev; |
490 | } | 509 | } |
491 | 510 | ||
492 | 511 | static void aac_define_int_mode(struct aac_dev *dev) | |
512 | { | ||
513 | |||
514 | int i, msi_count; | ||
515 | |||
516 | msi_count = i = 0; | ||
517 | /* max. vectors from GET_COMM_PREFERRED_SETTINGS */ | ||
518 | if (dev->max_msix == 0 || | ||
519 | dev->pdev->device == PMC_DEVICE_S6 || | ||
520 | dev->sync_mode) { | ||
521 | dev->max_msix = 1; | ||
522 | dev->vector_cap = | ||
523 | dev->scsi_host_ptr->can_queue + | ||
524 | AAC_NUM_MGT_FIB; | ||
525 | return; | ||
526 | } | ||
527 | |||
528 | msi_count = min(dev->max_msix, | ||
529 | (unsigned int)num_online_cpus()); | ||
530 | |||
531 | dev->max_msix = msi_count; | ||
532 | |||
533 | if (msi_count > AAC_MAX_MSIX) | ||
534 | msi_count = AAC_MAX_MSIX; | ||
535 | |||
536 | for (i = 0; i < msi_count; i++) | ||
537 | dev->msixentry[i].entry = i; | ||
538 | |||
539 | if (msi_count > 1 && | ||
540 | pci_find_capability(dev->pdev, PCI_CAP_ID_MSIX)) { | ||
541 | i = pci_enable_msix(dev->pdev, | ||
542 | dev->msixentry, | ||
543 | msi_count); | ||
544 | /* Check how many MSIX vectors are allocated */ | ||
545 | if (i >= 0) { | ||
546 | dev->msi_enabled = 1; | ||
547 | if (i) { | ||
548 | msi_count = i; | ||
549 | if (pci_enable_msix(dev->pdev, | ||
550 | dev->msixentry, | ||
551 | msi_count)) { | ||
552 | dev->msi_enabled = 0; | ||
553 | printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", | ||
554 | dev->name, dev->id, i); | ||
555 | } | ||
556 | } | ||
557 | } else { | ||
558 | dev->msi_enabled = 0; | ||
559 | printk(KERN_ERR "%s%d: MSIX not supported!! Will try MSI 0x%x.\n", | ||
560 | dev->name, dev->id, i); | ||
561 | } | ||
562 | } | ||
563 | |||
564 | if (!dev->msi_enabled) { | ||
565 | msi_count = 1; | ||
566 | i = pci_enable_msi(dev->pdev); | ||
567 | |||
568 | if (!i) { | ||
569 | dev->msi_enabled = 1; | ||
570 | dev->msi = 1; | ||
571 | } else { | ||
572 | printk(KERN_ERR "%s%d: MSI not supported!! Will try INTx 0x%x.\n", | ||
573 | dev->name, dev->id, i); | ||
574 | } | ||
575 | } | ||
576 | |||
577 | if (!dev->msi_enabled) | ||
578 | dev->max_msix = msi_count = 1; | ||
579 | else { | ||
580 | if (dev->max_msix > msi_count) | ||
581 | dev->max_msix = msi_count; | ||
582 | } | ||
583 | dev->vector_cap = | ||
584 | (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) / | ||
585 | msi_count; | ||
586 | } | ||
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index cab190af6345..4da574925284 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c | |||
@@ -208,14 +208,10 @@ struct fib *aac_fib_alloc(struct aac_dev *dev) | |||
208 | 208 | ||
209 | void aac_fib_free(struct fib *fibptr) | 209 | void aac_fib_free(struct fib *fibptr) |
210 | { | 210 | { |
211 | unsigned long flags, flagsv; | 211 | unsigned long flags; |
212 | 212 | ||
213 | spin_lock_irqsave(&fibptr->event_lock, flagsv); | 213 | if (fibptr->done == 2) |
214 | if (fibptr->done == 2) { | ||
215 | spin_unlock_irqrestore(&fibptr->event_lock, flagsv); | ||
216 | return; | 214 | return; |
217 | } | ||
218 | spin_unlock_irqrestore(&fibptr->event_lock, flagsv); | ||
219 | 215 | ||
220 | spin_lock_irqsave(&fibptr->dev->fib_lock, flags); | 216 | spin_lock_irqsave(&fibptr->dev->fib_lock, flags); |
221 | if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) | 217 | if (unlikely(fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) |
@@ -321,7 +317,7 @@ static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entr | |||
321 | /* Queue is full */ | 317 | /* Queue is full */ |
322 | if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { | 318 | if ((*index + 1) == le32_to_cpu(*(q->headers.consumer))) { |
323 | printk(KERN_WARNING "Queue %d full, %u outstanding.\n", | 319 | printk(KERN_WARNING "Queue %d full, %u outstanding.\n", |
324 | qid, q->numpending); | 320 | qid, atomic_read(&q->numpending)); |
325 | return 0; | 321 | return 0; |
326 | } else { | 322 | } else { |
327 | *entry = q->base + *index; | 323 | *entry = q->base + *index; |
@@ -414,7 +410,6 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
414 | struct aac_dev * dev = fibptr->dev; | 410 | struct aac_dev * dev = fibptr->dev; |
415 | struct hw_fib * hw_fib = fibptr->hw_fib_va; | 411 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
416 | unsigned long flags = 0; | 412 | unsigned long flags = 0; |
417 | unsigned long qflags; | ||
418 | unsigned long mflags = 0; | 413 | unsigned long mflags = 0; |
419 | unsigned long sflags = 0; | 414 | unsigned long sflags = 0; |
420 | 415 | ||
@@ -568,9 +563,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, | |||
568 | int blink; | 563 | int blink; |
569 | if (time_is_before_eq_jiffies(timeout)) { | 564 | if (time_is_before_eq_jiffies(timeout)) { |
570 | struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; | 565 | struct aac_queue * q = &dev->queues->queue[AdapNormCmdQueue]; |
571 | spin_lock_irqsave(q->lock, qflags); | 566 | atomic_dec(&q->numpending); |
572 | q->numpending--; | ||
573 | spin_unlock_irqrestore(q->lock, qflags); | ||
574 | if (wait == -1) { | 567 | if (wait == -1) { |
575 | printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" | 568 | printk(KERN_ERR "aacraid: aac_fib_send: first asynchronous command timed out.\n" |
576 | "Usually a result of a PCI interrupt routing problem;\n" | 569 | "Usually a result of a PCI interrupt routing problem;\n" |
@@ -775,7 +768,6 @@ int aac_fib_adapter_complete(struct fib *fibptr, unsigned short size) | |||
775 | 768 | ||
776 | int aac_fib_complete(struct fib *fibptr) | 769 | int aac_fib_complete(struct fib *fibptr) |
777 | { | 770 | { |
778 | unsigned long flags; | ||
779 | struct hw_fib * hw_fib = fibptr->hw_fib_va; | 771 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
780 | 772 | ||
781 | /* | 773 | /* |
@@ -798,12 +790,6 @@ int aac_fib_complete(struct fib *fibptr) | |||
798 | * command is complete that we had sent to the adapter and this | 790 | * command is complete that we had sent to the adapter and this |
799 | * cdb could be reused. | 791 | * cdb could be reused. |
800 | */ | 792 | */ |
801 | spin_lock_irqsave(&fibptr->event_lock, flags); | ||
802 | if (fibptr->done == 2) { | ||
803 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
804 | return 0; | ||
805 | } | ||
806 | spin_unlock_irqrestore(&fibptr->event_lock, flags); | ||
807 | 793 | ||
808 | if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && | 794 | if((hw_fib->header.XferState & cpu_to_le32(SentFromHost)) && |
809 | (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) | 795 | (hw_fib->header.XferState & cpu_to_le32(AdapterProcessed))) |
@@ -868,7 +854,7 @@ void aac_printf(struct aac_dev *dev, u32 val) | |||
868 | * dispatches it to the appropriate routine for handling. | 854 | * dispatches it to the appropriate routine for handling. |
869 | */ | 855 | */ |
870 | 856 | ||
871 | #define AIF_SNIFF_TIMEOUT (30*HZ) | 857 | #define AIF_SNIFF_TIMEOUT (500*HZ) |
872 | static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | 858 | static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) |
873 | { | 859 | { |
874 | struct hw_fib * hw_fib = fibptr->hw_fib_va; | 860 | struct hw_fib * hw_fib = fibptr->hw_fib_va; |
@@ -897,6 +883,39 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
897 | switch (le32_to_cpu(aifcmd->command)) { | 883 | switch (le32_to_cpu(aifcmd->command)) { |
898 | case AifCmdDriverNotify: | 884 | case AifCmdDriverNotify: |
899 | switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { | 885 | switch (le32_to_cpu(((__le32 *)aifcmd->data)[0])) { |
886 | case AifRawDeviceRemove: | ||
887 | container = le32_to_cpu(((__le32 *)aifcmd->data)[1]); | ||
888 | if ((container >> 28)) { | ||
889 | container = (u32)-1; | ||
890 | break; | ||
891 | } | ||
892 | channel = (container >> 24) & 0xF; | ||
893 | if (channel >= dev->maximum_num_channels) { | ||
894 | container = (u32)-1; | ||
895 | break; | ||
896 | } | ||
897 | id = container & 0xFFFF; | ||
898 | if (id >= dev->maximum_num_physicals) { | ||
899 | container = (u32)-1; | ||
900 | break; | ||
901 | } | ||
902 | lun = (container >> 16) & 0xFF; | ||
903 | container = (u32)-1; | ||
904 | channel = aac_phys_to_logical(channel); | ||
905 | device_config_needed = | ||
906 | (((__le32 *)aifcmd->data)[0] == | ||
907 | cpu_to_le32(AifRawDeviceRemove)) ? DELETE : ADD; | ||
908 | |||
909 | if (device_config_needed == ADD) { | ||
910 | device = scsi_device_lookup( | ||
911 | dev->scsi_host_ptr, | ||
912 | channel, id, lun); | ||
913 | if (device) { | ||
914 | scsi_remove_device(device); | ||
915 | scsi_device_put(device); | ||
916 | } | ||
917 | } | ||
918 | break; | ||
900 | /* | 919 | /* |
901 | * Morph or Expand complete | 920 | * Morph or Expand complete |
902 | */ | 921 | */ |
@@ -1044,6 +1063,8 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1044 | switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { | 1063 | switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) { |
1045 | case EM_DRIVE_INSERTION: | 1064 | case EM_DRIVE_INSERTION: |
1046 | case EM_DRIVE_REMOVAL: | 1065 | case EM_DRIVE_REMOVAL: |
1066 | case EM_SES_DRIVE_INSERTION: | ||
1067 | case EM_SES_DRIVE_REMOVAL: | ||
1047 | container = le32_to_cpu( | 1068 | container = le32_to_cpu( |
1048 | ((__le32 *)aifcmd->data)[2]); | 1069 | ((__le32 *)aifcmd->data)[2]); |
1049 | if ((container >> 28)) { | 1070 | if ((container >> 28)) { |
@@ -1069,8 +1090,10 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr) | |||
1069 | } | 1090 | } |
1070 | channel = aac_phys_to_logical(channel); | 1091 | channel = aac_phys_to_logical(channel); |
1071 | device_config_needed = | 1092 | device_config_needed = |
1072 | (((__le32 *)aifcmd->data)[3] | 1093 | ((((__le32 *)aifcmd->data)[3] |
1073 | == cpu_to_le32(EM_DRIVE_INSERTION)) ? | 1094 | == cpu_to_le32(EM_DRIVE_INSERTION)) || |
1095 | (((__le32 *)aifcmd->data)[3] | ||
1096 | == cpu_to_le32(EM_SES_DRIVE_INSERTION))) ? | ||
1074 | ADD : DELETE; | 1097 | ADD : DELETE; |
1075 | break; | 1098 | break; |
1076 | } | 1099 | } |
@@ -1247,12 +1270,13 @@ retry_next: | |||
1247 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) | 1270 | static int _aac_reset_adapter(struct aac_dev *aac, int forced) |
1248 | { | 1271 | { |
1249 | int index, quirks; | 1272 | int index, quirks; |
1250 | int retval; | 1273 | int retval, i; |
1251 | struct Scsi_Host *host; | 1274 | struct Scsi_Host *host; |
1252 | struct scsi_device *dev; | 1275 | struct scsi_device *dev; |
1253 | struct scsi_cmnd *command; | 1276 | struct scsi_cmnd *command; |
1254 | struct scsi_cmnd *command_list; | 1277 | struct scsi_cmnd *command_list; |
1255 | int jafo = 0; | 1278 | int jafo = 0; |
1279 | int cpu; | ||
1256 | 1280 | ||
1257 | /* | 1281 | /* |
1258 | * Assumptions: | 1282 | * Assumptions: |
@@ -1315,7 +1339,33 @@ static int _aac_reset_adapter(struct aac_dev *aac, int forced) | |||
1315 | aac->comm_phys = 0; | 1339 | aac->comm_phys = 0; |
1316 | kfree(aac->queues); | 1340 | kfree(aac->queues); |
1317 | aac->queues = NULL; | 1341 | aac->queues = NULL; |
1318 | free_irq(aac->pdev->irq, aac); | 1342 | cpu = cpumask_first(cpu_online_mask); |
1343 | if (aac->pdev->device == PMC_DEVICE_S6 || | ||
1344 | aac->pdev->device == PMC_DEVICE_S7 || | ||
1345 | aac->pdev->device == PMC_DEVICE_S8 || | ||
1346 | aac->pdev->device == PMC_DEVICE_S9) { | ||
1347 | if (aac->max_msix > 1) { | ||
1348 | for (i = 0; i < aac->max_msix; i++) { | ||
1349 | if (irq_set_affinity_hint( | ||
1350 | aac->msixentry[i].vector, | ||
1351 | NULL)) { | ||
1352 | printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n", | ||
1353 | aac->name, | ||
1354 | aac->id, | ||
1355 | cpu); | ||
1356 | } | ||
1357 | cpu = cpumask_next(cpu, | ||
1358 | cpu_online_mask); | ||
1359 | free_irq(aac->msixentry[i].vector, | ||
1360 | &(aac->aac_msix[i])); | ||
1361 | } | ||
1362 | pci_disable_msix(aac->pdev); | ||
1363 | } else { | ||
1364 | free_irq(aac->pdev->irq, &(aac->aac_msix[0])); | ||
1365 | } | ||
1366 | } else { | ||
1367 | free_irq(aac->pdev->irq, aac); | ||
1368 | } | ||
1319 | if (aac->msi) | 1369 | if (aac->msi) |
1320 | pci_disable_msi(aac->pdev); | 1370 | pci_disable_msi(aac->pdev); |
1321 | kfree(aac->fsa_dev); | 1371 | kfree(aac->fsa_dev); |
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d81b2810f0f7..da9d9936e995 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c | |||
@@ -84,7 +84,7 @@ unsigned int aac_response_normal(struct aac_queue * q) | |||
84 | * continue. The caller has already been notified that | 84 | * continue. The caller has already been notified that |
85 | * the fib timed out. | 85 | * the fib timed out. |
86 | */ | 86 | */ |
87 | dev->queues->queue[AdapNormCmdQueue].numpending--; | 87 | atomic_dec(&dev->queues->queue[AdapNormCmdQueue].numpending); |
88 | 88 | ||
89 | if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { | 89 | if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { |
90 | spin_unlock_irqrestore(q->lock, flags); | 90 | spin_unlock_irqrestore(q->lock, flags); |
@@ -354,7 +354,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, | |||
354 | * continue. The caller has already been notified that | 354 | * continue. The caller has already been notified that |
355 | * the fib timed out. | 355 | * the fib timed out. |
356 | */ | 356 | */ |
357 | dev->queues->queue[AdapNormCmdQueue].numpending--; | 357 | atomic_dec(&dev->queues->queue[AdapNormCmdQueue].numpending); |
358 | 358 | ||
359 | if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { | 359 | if (unlikely(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) { |
360 | aac_fib_complete(fib); | 360 | aac_fib_complete(fib); |
@@ -389,8 +389,13 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, | |||
389 | * NOTE: we cannot touch the fib after this | 389 | * NOTE: we cannot touch the fib after this |
390 | * call, because it may have been deallocated. | 390 | * call, because it may have been deallocated. |
391 | */ | 391 | */ |
392 | fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; | 392 | if (likely(fib->callback && fib->callback_data)) { |
393 | fib->callback(fib->callback_data, fib); | 393 | fib->flags &= FIB_CONTEXT_FLAG_FASTRESP; |
394 | fib->callback(fib->callback_data, fib); | ||
395 | } else { | ||
396 | aac_fib_complete(fib); | ||
397 | aac_fib_free(fib); | ||
398 | } | ||
394 | } else { | 399 | } else { |
395 | unsigned long flagv; | 400 | unsigned long flagv; |
396 | dprintk((KERN_INFO "event_wait up\n")); | 401 | dprintk((KERN_INFO "event_wait up\n")); |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index fdcdf9f781bc..9eec02733c86 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -56,7 +56,7 @@ | |||
56 | 56 | ||
57 | #include "aacraid.h" | 57 | #include "aacraid.h" |
58 | 58 | ||
59 | #define AAC_DRIVER_VERSION "1.2-0" | 59 | #define AAC_DRIVER_VERSION "1.2-1" |
60 | #ifndef AAC_DRIVER_BRANCH | 60 | #ifndef AAC_DRIVER_BRANCH |
61 | #define AAC_DRIVER_BRANCH "" | 61 | #define AAC_DRIVER_BRANCH "" |
62 | #endif | 62 | #endif |
@@ -251,27 +251,15 @@ static struct aac_driver_ident aac_drivers[] = { | |||
251 | * TODO: unify with aac_scsi_cmd(). | 251 | * TODO: unify with aac_scsi_cmd(). |
252 | */ | 252 | */ |
253 | 253 | ||
254 | static int aac_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) | 254 | static int aac_queuecommand(struct Scsi_Host *shost, |
255 | struct scsi_cmnd *cmd) | ||
255 | { | 256 | { |
256 | struct Scsi_Host *host = cmd->device->host; | 257 | int r = 0; |
257 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | ||
258 | u32 count = 0; | ||
259 | cmd->scsi_done = done; | ||
260 | for (; count < (host->can_queue + AAC_NUM_MGT_FIB); ++count) { | ||
261 | struct fib * fib = &dev->fibs[count]; | ||
262 | struct scsi_cmnd * command; | ||
263 | if (fib->hw_fib_va->header.XferState && | ||
264 | ((command = fib->callback_data)) && | ||
265 | (command == cmd) && | ||
266 | (cmd->SCp.phase == AAC_OWNER_FIRMWARE)) | ||
267 | return 0; /* Already owned by Adapter */ | ||
268 | } | ||
269 | cmd->SCp.phase = AAC_OWNER_LOWLEVEL; | 258 | cmd->SCp.phase = AAC_OWNER_LOWLEVEL; |
270 | return (aac_scsi_cmd(cmd) ? FAILED : 0); | 259 | r = (aac_scsi_cmd(cmd) ? FAILED : 0); |
260 | return r; | ||
271 | } | 261 | } |
272 | 262 | ||
273 | static DEF_SCSI_QCMD(aac_queuecommand) | ||
274 | |||
275 | /** | 263 | /** |
276 | * aac_info - Returns the host adapter name | 264 | * aac_info - Returns the host adapter name |
277 | * @shost: Scsi host to report on | 265 | * @shost: Scsi host to report on |
@@ -713,7 +701,9 @@ static long aac_cfg_ioctl(struct file *file, | |||
713 | unsigned int cmd, unsigned long arg) | 701 | unsigned int cmd, unsigned long arg) |
714 | { | 702 | { |
715 | int ret; | 703 | int ret; |
716 | if (!capable(CAP_SYS_RAWIO)) | 704 | struct aac_dev *aac; |
705 | aac = (struct aac_dev *)file->private_data; | ||
706 | if (!capable(CAP_SYS_RAWIO) || aac->adapter_shutdown) | ||
717 | return -EPERM; | 707 | return -EPERM; |
718 | mutex_lock(&aac_mutex); | 708 | mutex_lock(&aac_mutex); |
719 | ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg); | 709 | ret = aac_do_ioctl(file->private_data, cmd, (void __user *)arg); |
@@ -1082,6 +1072,9 @@ static struct scsi_host_template aac_driver_template = { | |||
1082 | 1072 | ||
1083 | static void __aac_shutdown(struct aac_dev * aac) | 1073 | static void __aac_shutdown(struct aac_dev * aac) |
1084 | { | 1074 | { |
1075 | int i; | ||
1076 | int cpu; | ||
1077 | |||
1085 | if (aac->aif_thread) { | 1078 | if (aac->aif_thread) { |
1086 | int i; | 1079 | int i; |
1087 | /* Clear out events first */ | 1080 | /* Clear out events first */ |
@@ -1095,9 +1088,37 @@ static void __aac_shutdown(struct aac_dev * aac) | |||
1095 | } | 1088 | } |
1096 | aac_send_shutdown(aac); | 1089 | aac_send_shutdown(aac); |
1097 | aac_adapter_disable_int(aac); | 1090 | aac_adapter_disable_int(aac); |
1098 | free_irq(aac->pdev->irq, aac); | 1091 | cpu = cpumask_first(cpu_online_mask); |
1092 | if (aac->pdev->device == PMC_DEVICE_S6 || | ||
1093 | aac->pdev->device == PMC_DEVICE_S7 || | ||
1094 | aac->pdev->device == PMC_DEVICE_S8 || | ||
1095 | aac->pdev->device == PMC_DEVICE_S9) { | ||
1096 | if (aac->max_msix > 1) { | ||
1097 | for (i = 0; i < aac->max_msix; i++) { | ||
1098 | if (irq_set_affinity_hint( | ||
1099 | aac->msixentry[i].vector, | ||
1100 | NULL)) { | ||
1101 | printk(KERN_ERR "%s%d: Failed to reset IRQ affinity for cpu %d\n", | ||
1102 | aac->name, | ||
1103 | aac->id, | ||
1104 | cpu); | ||
1105 | } | ||
1106 | cpu = cpumask_next(cpu, | ||
1107 | cpu_online_mask); | ||
1108 | free_irq(aac->msixentry[i].vector, | ||
1109 | &(aac->aac_msix[i])); | ||
1110 | } | ||
1111 | } else { | ||
1112 | free_irq(aac->pdev->irq, | ||
1113 | &(aac->aac_msix[0])); | ||
1114 | } | ||
1115 | } else { | ||
1116 | free_irq(aac->pdev->irq, aac); | ||
1117 | } | ||
1099 | if (aac->msi) | 1118 | if (aac->msi) |
1100 | pci_disable_msi(aac->pdev); | 1119 | pci_disable_msi(aac->pdev); |
1120 | else if (aac->max_msix > 1) | ||
1121 | pci_disable_msix(aac->pdev); | ||
1101 | } | 1122 | } |
1102 | 1123 | ||
1103 | static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | 1124 | static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) |
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c index 5c6a8703f535..9570612b80ce 100644 --- a/drivers/scsi/aacraid/rx.c +++ b/drivers/scsi/aacraid/rx.c | |||
@@ -400,16 +400,13 @@ int aac_rx_deliver_producer(struct fib * fib) | |||
400 | { | 400 | { |
401 | struct aac_dev *dev = fib->dev; | 401 | struct aac_dev *dev = fib->dev; |
402 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; | 402 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; |
403 | unsigned long qflags; | ||
404 | u32 Index; | 403 | u32 Index; |
405 | unsigned long nointr = 0; | 404 | unsigned long nointr = 0; |
406 | 405 | ||
407 | spin_lock_irqsave(q->lock, qflags); | ||
408 | aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); | 406 | aac_queue_get( dev, &Index, AdapNormCmdQueue, fib->hw_fib_va, 1, fib, &nointr); |
409 | 407 | ||
410 | q->numpending++; | 408 | atomic_inc(&q->numpending); |
411 | *(q->headers.producer) = cpu_to_le32(Index + 1); | 409 | *(q->headers.producer) = cpu_to_le32(Index + 1); |
412 | spin_unlock_irqrestore(q->lock, qflags); | ||
413 | if (!(nointr & aac_config.irq_mod)) | 410 | if (!(nointr & aac_config.irq_mod)) |
414 | aac_adapter_notify(dev, AdapNormCmdQueue); | 411 | aac_adapter_notify(dev, AdapNormCmdQueue); |
415 | 412 | ||
@@ -426,15 +423,12 @@ static int aac_rx_deliver_message(struct fib * fib) | |||
426 | { | 423 | { |
427 | struct aac_dev *dev = fib->dev; | 424 | struct aac_dev *dev = fib->dev; |
428 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; | 425 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; |
429 | unsigned long qflags; | ||
430 | u32 Index; | 426 | u32 Index; |
431 | u64 addr; | 427 | u64 addr; |
432 | volatile void __iomem *device; | 428 | volatile void __iomem *device; |
433 | 429 | ||
434 | unsigned long count = 10000000L; /* 50 seconds */ | 430 | unsigned long count = 10000000L; /* 50 seconds */ |
435 | spin_lock_irqsave(q->lock, qflags); | 431 | atomic_inc(&q->numpending); |
436 | q->numpending++; | ||
437 | spin_unlock_irqrestore(q->lock, qflags); | ||
438 | for(;;) { | 432 | for(;;) { |
439 | Index = rx_readl(dev, MUnit.InboundQueue); | 433 | Index = rx_readl(dev, MUnit.InboundQueue); |
440 | if (unlikely(Index == 0xFFFFFFFFL)) | 434 | if (unlikely(Index == 0xFFFFFFFFL)) |
@@ -442,9 +436,7 @@ static int aac_rx_deliver_message(struct fib * fib) | |||
442 | if (likely(Index != 0xFFFFFFFFL)) | 436 | if (likely(Index != 0xFFFFFFFFL)) |
443 | break; | 437 | break; |
444 | if (--count == 0) { | 438 | if (--count == 0) { |
445 | spin_lock_irqsave(q->lock, qflags); | 439 | atomic_dec(&q->numpending); |
446 | q->numpending--; | ||
447 | spin_unlock_irqrestore(q->lock, qflags); | ||
448 | return -ETIMEDOUT; | 440 | return -ETIMEDOUT; |
449 | } | 441 | } |
450 | udelay(5); | 442 | udelay(5); |
diff --git a/drivers/scsi/aacraid/src.c b/drivers/scsi/aacraid/src.c index 9c65aed26212..4596e9dd757c 100644 --- a/drivers/scsi/aacraid/src.c +++ b/drivers/scsi/aacraid/src.c | |||
@@ -44,98 +44,128 @@ | |||
44 | 44 | ||
45 | #include "aacraid.h" | 45 | #include "aacraid.h" |
46 | 46 | ||
47 | static irqreturn_t aac_src_intr_message(int irq, void *dev_id) | 47 | static int aac_src_get_sync_status(struct aac_dev *dev); |
48 | |||
49 | irqreturn_t aac_src_intr_message(int irq, void *dev_id) | ||
48 | { | 50 | { |
49 | struct aac_dev *dev = dev_id; | 51 | struct aac_msix_ctx *ctx; |
52 | struct aac_dev *dev; | ||
50 | unsigned long bellbits, bellbits_shifted; | 53 | unsigned long bellbits, bellbits_shifted; |
51 | int our_interrupt = 0; | 54 | int vector_no; |
52 | int isFastResponse; | 55 | int isFastResponse, mode; |
53 | u32 index, handle; | 56 | u32 index, handle; |
54 | 57 | ||
55 | bellbits = src_readl(dev, MUnit.ODR_R); | 58 | ctx = (struct aac_msix_ctx *)dev_id; |
56 | if (bellbits & PmDoorBellResponseSent) { | 59 | dev = ctx->dev; |
57 | bellbits = PmDoorBellResponseSent; | 60 | vector_no = ctx->vector_no; |
58 | /* handle async. status */ | 61 | |
59 | src_writel(dev, MUnit.ODR_C, bellbits); | 62 | if (dev->msi_enabled) { |
60 | src_readl(dev, MUnit.ODR_C); | 63 | mode = AAC_INT_MODE_MSI; |
61 | our_interrupt = 1; | 64 | if (vector_no == 0) { |
62 | index = dev->host_rrq_idx; | 65 | bellbits = src_readl(dev, MUnit.ODR_MSI); |
63 | for (;;) { | 66 | if (bellbits & 0x40000) |
64 | isFastResponse = 0; | 67 | mode |= AAC_INT_MODE_AIF; |
65 | /* remove toggle bit (31) */ | 68 | if (bellbits & 0x1000) |
66 | handle = le32_to_cpu(dev->host_rrq[index]) & 0x7fffffff; | 69 | mode |= AAC_INT_MODE_SYNC; |
67 | /* check fast response bit (30) */ | ||
68 | if (handle & 0x40000000) | ||
69 | isFastResponse = 1; | ||
70 | handle &= 0x0000ffff; | ||
71 | if (handle == 0) | ||
72 | break; | ||
73 | |||
74 | aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); | ||
75 | |||
76 | dev->host_rrq[index++] = 0; | ||
77 | if (index == dev->scsi_host_ptr->can_queue + | ||
78 | AAC_NUM_MGT_FIB) | ||
79 | index = 0; | ||
80 | dev->host_rrq_idx = index; | ||
81 | } | 70 | } |
82 | } else { | 71 | } else { |
83 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); | 72 | mode = AAC_INT_MODE_INTX; |
84 | if (bellbits_shifted & DoorBellAifPending) { | 73 | bellbits = src_readl(dev, MUnit.ODR_R); |
74 | if (bellbits & PmDoorBellResponseSent) { | ||
75 | bellbits = PmDoorBellResponseSent; | ||
76 | src_writel(dev, MUnit.ODR_C, bellbits); | ||
77 | src_readl(dev, MUnit.ODR_C); | ||
78 | } else { | ||
79 | bellbits_shifted = (bellbits >> SRC_ODR_SHIFT); | ||
85 | src_writel(dev, MUnit.ODR_C, bellbits); | 80 | src_writel(dev, MUnit.ODR_C, bellbits); |
86 | src_readl(dev, MUnit.ODR_C); | 81 | src_readl(dev, MUnit.ODR_C); |
87 | our_interrupt = 1; | ||
88 | /* handle AIF */ | ||
89 | aac_intr_normal(dev, 0, 2, 0, NULL); | ||
90 | } else if (bellbits_shifted & OUTBOUNDDOORBELL_0) { | ||
91 | unsigned long sflags; | ||
92 | struct list_head *entry; | ||
93 | int send_it = 0; | ||
94 | extern int aac_sync_mode; | ||
95 | 82 | ||
83 | if (bellbits_shifted & DoorBellAifPending) | ||
84 | mode |= AAC_INT_MODE_AIF; | ||
85 | else if (bellbits_shifted & OUTBOUNDDOORBELL_0) | ||
86 | mode |= AAC_INT_MODE_SYNC; | ||
87 | } | ||
88 | } | ||
89 | |||
90 | if (mode & AAC_INT_MODE_SYNC) { | ||
91 | unsigned long sflags; | ||
92 | struct list_head *entry; | ||
93 | int send_it = 0; | ||
94 | extern int aac_sync_mode; | ||
95 | |||
96 | if (!aac_sync_mode && !dev->msi_enabled) { | ||
96 | src_writel(dev, MUnit.ODR_C, bellbits); | 97 | src_writel(dev, MUnit.ODR_C, bellbits); |
97 | src_readl(dev, MUnit.ODR_C); | 98 | src_readl(dev, MUnit.ODR_C); |
99 | } | ||
98 | 100 | ||
99 | if (!aac_sync_mode) { | 101 | if (dev->sync_fib) { |
100 | src_writel(dev, MUnit.ODR_C, bellbits); | 102 | if (dev->sync_fib->callback) |
101 | src_readl(dev, MUnit.ODR_C); | 103 | dev->sync_fib->callback(dev->sync_fib->callback_data, |
102 | our_interrupt = 1; | 104 | dev->sync_fib); |
105 | spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); | ||
106 | if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { | ||
107 | dev->management_fib_count--; | ||
108 | up(&dev->sync_fib->event_wait); | ||
103 | } | 109 | } |
104 | 110 | spin_unlock_irqrestore(&dev->sync_fib->event_lock, | |
105 | if (dev->sync_fib) { | 111 | sflags); |
106 | our_interrupt = 1; | 112 | spin_lock_irqsave(&dev->sync_lock, sflags); |
107 | if (dev->sync_fib->callback) | 113 | if (!list_empty(&dev->sync_fib_list)) { |
108 | dev->sync_fib->callback(dev->sync_fib->callback_data, | 114 | entry = dev->sync_fib_list.next; |
109 | dev->sync_fib); | 115 | dev->sync_fib = list_entry(entry, |
110 | spin_lock_irqsave(&dev->sync_fib->event_lock, sflags); | 116 | struct fib, |
111 | if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) { | 117 | fiblink); |
112 | dev->management_fib_count--; | 118 | list_del(entry); |
113 | up(&dev->sync_fib->event_wait); | 119 | send_it = 1; |
114 | } | 120 | } else { |
115 | spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags); | 121 | dev->sync_fib = NULL; |
116 | spin_lock_irqsave(&dev->sync_lock, sflags); | 122 | } |
117 | if (!list_empty(&dev->sync_fib_list)) { | 123 | spin_unlock_irqrestore(&dev->sync_lock, sflags); |
118 | entry = dev->sync_fib_list.next; | 124 | if (send_it) { |
119 | dev->sync_fib = list_entry(entry, struct fib, fiblink); | 125 | aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, |
120 | list_del(entry); | 126 | (u32)dev->sync_fib->hw_fib_pa, |
121 | send_it = 1; | 127 | 0, 0, 0, 0, 0, |
122 | } else { | 128 | NULL, NULL, NULL, NULL, NULL); |
123 | dev->sync_fib = NULL; | ||
124 | } | ||
125 | spin_unlock_irqrestore(&dev->sync_lock, sflags); | ||
126 | if (send_it) { | ||
127 | aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB, | ||
128 | (u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0, | ||
129 | NULL, NULL, NULL, NULL, NULL); | ||
130 | } | ||
131 | } | 129 | } |
132 | } | 130 | } |
131 | if (!dev->msi_enabled) | ||
132 | mode = 0; | ||
133 | |||
134 | } | ||
135 | |||
136 | if (mode & AAC_INT_MODE_AIF) { | ||
137 | /* handle AIF */ | ||
138 | aac_intr_normal(dev, 0, 2, 0, NULL); | ||
139 | if (dev->msi_enabled) | ||
140 | aac_src_access_devreg(dev, AAC_CLEAR_AIF_BIT); | ||
141 | mode = 0; | ||
133 | } | 142 | } |
134 | 143 | ||
135 | if (our_interrupt) { | 144 | if (mode) { |
136 | return IRQ_HANDLED; | 145 | index = dev->host_rrq_idx[vector_no]; |
146 | |||
147 | for (;;) { | ||
148 | isFastResponse = 0; | ||
149 | /* remove toggle bit (31) */ | ||
150 | handle = (dev->host_rrq[index] & 0x7fffffff); | ||
151 | /* check fast response bit (30) */ | ||
152 | if (handle & 0x40000000) | ||
153 | isFastResponse = 1; | ||
154 | handle &= 0x0000ffff; | ||
155 | if (handle == 0) | ||
156 | break; | ||
157 | if (dev->msi_enabled && dev->max_msix > 1) | ||
158 | atomic_dec(&dev->rrq_outstanding[vector_no]); | ||
159 | aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL); | ||
160 | dev->host_rrq[index++] = 0; | ||
161 | if (index == (vector_no + 1) * dev->vector_cap) | ||
162 | index = vector_no * dev->vector_cap; | ||
163 | dev->host_rrq_idx[vector_no] = index; | ||
164 | } | ||
165 | mode = 0; | ||
137 | } | 166 | } |
138 | return IRQ_NONE; | 167 | |
168 | return IRQ_HANDLED; | ||
139 | } | 169 | } |
140 | 170 | ||
141 | /** | 171 | /** |
@@ -155,7 +185,7 @@ static void aac_src_disable_interrupt(struct aac_dev *dev) | |||
155 | 185 | ||
156 | static void aac_src_enable_interrupt_message(struct aac_dev *dev) | 186 | static void aac_src_enable_interrupt_message(struct aac_dev *dev) |
157 | { | 187 | { |
158 | src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8); | 188 | aac_src_access_devreg(dev, AAC_ENABLE_INTERRUPT); |
159 | } | 189 | } |
160 | 190 | ||
161 | /** | 191 | /** |
@@ -174,6 +204,7 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
174 | u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) | 204 | u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4) |
175 | { | 205 | { |
176 | unsigned long start; | 206 | unsigned long start; |
207 | unsigned long delay; | ||
177 | int ok; | 208 | int ok; |
178 | 209 | ||
179 | /* | 210 | /* |
@@ -191,7 +222,10 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
191 | /* | 222 | /* |
192 | * Clear the synch command doorbell to start on a clean slate. | 223 | * Clear the synch command doorbell to start on a clean slate. |
193 | */ | 224 | */ |
194 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 225 | if (!dev->msi_enabled) |
226 | src_writel(dev, | ||
227 | MUnit.ODR_C, | ||
228 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
195 | 229 | ||
196 | /* | 230 | /* |
197 | * Disable doorbell interrupts | 231 | * Disable doorbell interrupts |
@@ -213,19 +247,29 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
213 | ok = 0; | 247 | ok = 0; |
214 | start = jiffies; | 248 | start = jiffies; |
215 | 249 | ||
216 | /* | 250 | if (command == IOP_RESET_ALWAYS) { |
217 | * Wait up to 5 minutes | 251 | /* Wait up to 10 sec */ |
218 | */ | 252 | delay = 10*HZ; |
219 | while (time_before(jiffies, start+300*HZ)) { | 253 | } else { |
254 | /* Wait up to 5 minutes */ | ||
255 | delay = 300*HZ; | ||
256 | } | ||
257 | while (time_before(jiffies, start+delay)) { | ||
220 | udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ | 258 | udelay(5); /* Delay 5 microseconds to let Mon960 get info. */ |
221 | /* | 259 | /* |
222 | * Mon960 will set doorbell0 bit when it has completed the command. | 260 | * Mon960 will set doorbell0 bit when it has completed the command. |
223 | */ | 261 | */ |
224 | if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { | 262 | if (aac_src_get_sync_status(dev) & OUTBOUNDDOORBELL_0) { |
225 | /* | 263 | /* |
226 | * Clear the doorbell. | 264 | * Clear the doorbell. |
227 | */ | 265 | */ |
228 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 266 | if (dev->msi_enabled) |
267 | aac_src_access_devreg(dev, | ||
268 | AAC_CLEAR_SYNC_BIT); | ||
269 | else | ||
270 | src_writel(dev, | ||
271 | MUnit.ODR_C, | ||
272 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
229 | ok = 1; | 273 | ok = 1; |
230 | break; | 274 | break; |
231 | } | 275 | } |
@@ -254,11 +298,16 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, | |||
254 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); | 298 | *r3 = readl(&dev->IndexRegs->Mailbox[3]); |
255 | if (r4) | 299 | if (r4) |
256 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); | 300 | *r4 = readl(&dev->IndexRegs->Mailbox[4]); |
257 | 301 | if (command == GET_COMM_PREFERRED_SETTINGS) | |
302 | dev->max_msix = | ||
303 | readl(&dev->IndexRegs->Mailbox[5]) & 0xFFFF; | ||
258 | /* | 304 | /* |
259 | * Clear the synch command doorbell. | 305 | * Clear the synch command doorbell. |
260 | */ | 306 | */ |
261 | src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | 307 | if (!dev->msi_enabled) |
308 | src_writel(dev, | ||
309 | MUnit.ODR_C, | ||
310 | OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); | ||
262 | } | 311 | } |
263 | 312 | ||
264 | /* | 313 | /* |
@@ -335,9 +384,14 @@ static void aac_src_notify_adapter(struct aac_dev *dev, u32 event) | |||
335 | static void aac_src_start_adapter(struct aac_dev *dev) | 384 | static void aac_src_start_adapter(struct aac_dev *dev) |
336 | { | 385 | { |
337 | struct aac_init *init; | 386 | struct aac_init *init; |
387 | int i; | ||
338 | 388 | ||
339 | /* reset host_rrq_idx first */ | 389 | /* reset host_rrq_idx first */ |
340 | dev->host_rrq_idx = 0; | 390 | for (i = 0; i < dev->max_msix; i++) { |
391 | dev->host_rrq_idx[i] = i * dev->vector_cap; | ||
392 | atomic_set(&dev->rrq_outstanding[i], 0); | ||
393 | } | ||
394 | dev->fibs_pushed_no = 0; | ||
341 | 395 | ||
342 | init = dev->init; | 396 | init = dev->init; |
343 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); | 397 | init->HostElapsedSeconds = cpu_to_le32(get_seconds()); |
@@ -390,15 +444,39 @@ static int aac_src_deliver_message(struct fib *fib) | |||
390 | { | 444 | { |
391 | struct aac_dev *dev = fib->dev; | 445 | struct aac_dev *dev = fib->dev; |
392 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; | 446 | struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue]; |
393 | unsigned long qflags; | ||
394 | u32 fibsize; | 447 | u32 fibsize; |
395 | dma_addr_t address; | 448 | dma_addr_t address; |
396 | struct aac_fib_xporthdr *pFibX; | 449 | struct aac_fib_xporthdr *pFibX; |
397 | u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size); | 450 | u16 hdr_size = le16_to_cpu(fib->hw_fib_va->header.Size); |
398 | 451 | ||
399 | spin_lock_irqsave(q->lock, qflags); | 452 | atomic_inc(&q->numpending); |
400 | q->numpending++; | 453 | |
401 | spin_unlock_irqrestore(q->lock, qflags); | 454 | if (dev->msi_enabled && fib->hw_fib_va->header.Command != AifRequest && |
455 | dev->max_msix > 1) { | ||
456 | u_int16_t vector_no, first_choice = 0xffff; | ||
457 | |||
458 | vector_no = dev->fibs_pushed_no % dev->max_msix; | ||
459 | do { | ||
460 | vector_no += 1; | ||
461 | if (vector_no == dev->max_msix) | ||
462 | vector_no = 1; | ||
463 | if (atomic_read(&dev->rrq_outstanding[vector_no]) < | ||
464 | dev->vector_cap) | ||
465 | break; | ||
466 | if (0xffff == first_choice) | ||
467 | first_choice = vector_no; | ||
468 | else if (vector_no == first_choice) | ||
469 | break; | ||
470 | } while (1); | ||
471 | if (vector_no == first_choice) | ||
472 | vector_no = 0; | ||
473 | atomic_inc(&dev->rrq_outstanding[vector_no]); | ||
474 | if (dev->fibs_pushed_no == 0xffffffff) | ||
475 | dev->fibs_pushed_no = 0; | ||
476 | else | ||
477 | dev->fibs_pushed_no++; | ||
478 | fib->hw_fib_va->header.Handle += (vector_no << 16); | ||
479 | } | ||
402 | 480 | ||
403 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { | 481 | if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE2) { |
404 | /* Calculate the amount to the fibsize bits */ | 482 | /* Calculate the amount to the fibsize bits */ |
@@ -498,15 +576,34 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) | |||
498 | if (bled) | 576 | if (bled) |
499 | printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", | 577 | printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n", |
500 | dev->name, dev->id, bled); | 578 | dev->name, dev->id, bled); |
579 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | ||
501 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, | 580 | bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, |
502 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); | 581 | 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); |
503 | if (bled || (var != 0x00000001)) | 582 | if ((bled || (var != 0x00000001)) && |
504 | return -EINVAL; | 583 | !dev->doorbell_mask) |
505 | if (dev->supplement_adapter_info.SupportedOptions2 & | 584 | return -EINVAL; |
506 | AAC_OPTION_DOORBELL_RESET) { | 585 | else if (dev->doorbell_mask) { |
507 | src_writel(dev, MUnit.IDR, reset_mask); | 586 | reset_mask = dev->doorbell_mask; |
587 | bled = 0; | ||
588 | var = 0x00000001; | ||
589 | } | ||
590 | |||
591 | if ((dev->pdev->device == PMC_DEVICE_S7 || | ||
592 | dev->pdev->device == PMC_DEVICE_S8 || | ||
593 | dev->pdev->device == PMC_DEVICE_S9) && dev->msi_enabled) { | ||
594 | aac_src_access_devreg(dev, AAC_ENABLE_INTX); | ||
595 | dev->msi_enabled = 0; | ||
508 | msleep(5000); /* Delay 5 seconds */ | 596 | msleep(5000); /* Delay 5 seconds */ |
509 | } | 597 | } |
598 | |||
599 | if (!bled && (dev->supplement_adapter_info.SupportedOptions2 & | ||
600 | AAC_OPTION_DOORBELL_RESET)) { | ||
601 | src_writel(dev, MUnit.IDR, reset_mask); | ||
602 | ssleep(45); | ||
603 | } else { | ||
604 | src_writel(dev, MUnit.IDR, 0x100); | ||
605 | ssleep(45); | ||
606 | } | ||
510 | } | 607 | } |
511 | 608 | ||
512 | if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) | 609 | if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC) |
@@ -527,7 +624,6 @@ int aac_src_select_comm(struct aac_dev *dev, int comm) | |||
527 | { | 624 | { |
528 | switch (comm) { | 625 | switch (comm) { |
529 | case AAC_COMM_MESSAGE: | 626 | case AAC_COMM_MESSAGE: |
530 | dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; | ||
531 | dev->a_ops.adapter_intr = aac_src_intr_message; | 627 | dev->a_ops.adapter_intr = aac_src_intr_message; |
532 | dev->a_ops.adapter_deliver = aac_src_deliver_message; | 628 | dev->a_ops.adapter_deliver = aac_src_deliver_message; |
533 | break; | 629 | break; |
@@ -625,6 +721,7 @@ int aac_src_init(struct aac_dev *dev) | |||
625 | */ | 721 | */ |
626 | dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; | 722 | dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; |
627 | dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; | 723 | dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; |
724 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | ||
628 | dev->a_ops.adapter_notify = aac_src_notify_adapter; | 725 | dev->a_ops.adapter_notify = aac_src_notify_adapter; |
629 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; | 726 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; |
630 | dev->a_ops.adapter_check_health = aac_src_check_health; | 727 | dev->a_ops.adapter_check_health = aac_src_check_health; |
@@ -646,8 +743,11 @@ int aac_src_init(struct aac_dev *dev) | |||
646 | 743 | ||
647 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | 744 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); |
648 | 745 | ||
746 | dev->aac_msix[0].vector_no = 0; | ||
747 | dev->aac_msix[0].dev = dev; | ||
748 | |||
649 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 749 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, |
650 | IRQF_SHARED, "aacraid", dev) < 0) { | 750 | IRQF_SHARED, "aacraid", &(dev->aac_msix[0])) < 0) { |
651 | 751 | ||
652 | if (dev->msi) | 752 | if (dev->msi) |
653 | pci_disable_msi(dev->pdev); | 753 | pci_disable_msi(dev->pdev); |
@@ -659,6 +759,7 @@ int aac_src_init(struct aac_dev *dev) | |||
659 | dev->dbg_base = pci_resource_start(dev->pdev, 2); | 759 | dev->dbg_base = pci_resource_start(dev->pdev, 2); |
660 | dev->dbg_base_mapped = dev->regs.src.bar1; | 760 | dev->dbg_base_mapped = dev->regs.src.bar1; |
661 | dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; | 761 | dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; |
762 | dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; | ||
662 | 763 | ||
663 | aac_adapter_enable_int(dev); | 764 | aac_adapter_enable_int(dev); |
664 | 765 | ||
@@ -688,7 +789,9 @@ int aac_srcv_init(struct aac_dev *dev) | |||
688 | unsigned long status; | 789 | unsigned long status; |
689 | int restart = 0; | 790 | int restart = 0; |
690 | int instance = dev->id; | 791 | int instance = dev->id; |
792 | int i, j; | ||
691 | const char *name = dev->name; | 793 | const char *name = dev->name; |
794 | int cpu; | ||
692 | 795 | ||
693 | dev->a_ops.adapter_ioremap = aac_srcv_ioremap; | 796 | dev->a_ops.adapter_ioremap = aac_srcv_ioremap; |
694 | dev->a_ops.adapter_comm = aac_src_select_comm; | 797 | dev->a_ops.adapter_comm = aac_src_select_comm; |
@@ -784,6 +887,7 @@ int aac_srcv_init(struct aac_dev *dev) | |||
784 | */ | 887 | */ |
785 | dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; | 888 | dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter; |
786 | dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; | 889 | dev->a_ops.adapter_disable_int = aac_src_disable_interrupt; |
890 | dev->a_ops.adapter_enable_int = aac_src_disable_interrupt; | ||
787 | dev->a_ops.adapter_notify = aac_src_notify_adapter; | 891 | dev->a_ops.adapter_notify = aac_src_notify_adapter; |
788 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; | 892 | dev->a_ops.adapter_sync_cmd = src_sync_cmd; |
789 | dev->a_ops.adapter_check_health = aac_src_check_health; | 893 | dev->a_ops.adapter_check_health = aac_src_check_health; |
@@ -802,18 +906,54 @@ int aac_srcv_init(struct aac_dev *dev) | |||
802 | goto error_iounmap; | 906 | goto error_iounmap; |
803 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) | 907 | if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE2) |
804 | goto error_iounmap; | 908 | goto error_iounmap; |
805 | dev->msi = aac_msi && !pci_enable_msi(dev->pdev); | 909 | if (dev->msi_enabled) |
806 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | 910 | aac_src_access_devreg(dev, AAC_ENABLE_MSIX); |
807 | IRQF_SHARED, "aacraid", dev) < 0) { | 911 | if (!dev->sync_mode && dev->msi_enabled && dev->max_msix > 1) { |
808 | if (dev->msi) | 912 | cpu = cpumask_first(cpu_online_mask); |
809 | pci_disable_msi(dev->pdev); | 913 | for (i = 0; i < dev->max_msix; i++) { |
810 | printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | 914 | dev->aac_msix[i].vector_no = i; |
811 | name, instance); | 915 | dev->aac_msix[i].dev = dev; |
812 | goto error_iounmap; | 916 | |
917 | if (request_irq(dev->msixentry[i].vector, | ||
918 | dev->a_ops.adapter_intr, | ||
919 | 0, | ||
920 | "aacraid", | ||
921 | &(dev->aac_msix[i]))) { | ||
922 | printk(KERN_ERR "%s%d: Failed to register IRQ for vector %d.\n", | ||
923 | name, instance, i); | ||
924 | for (j = 0 ; j < i ; j++) | ||
925 | free_irq(dev->msixentry[j].vector, | ||
926 | &(dev->aac_msix[j])); | ||
927 | pci_disable_msix(dev->pdev); | ||
928 | goto error_iounmap; | ||
929 | } | ||
930 | if (irq_set_affinity_hint( | ||
931 | dev->msixentry[i].vector, | ||
932 | get_cpu_mask(cpu))) { | ||
933 | printk(KERN_ERR "%s%d: Failed to set IRQ affinity for cpu %d\n", | ||
934 | name, instance, cpu); | ||
935 | } | ||
936 | cpu = cpumask_next(cpu, cpu_online_mask); | ||
937 | } | ||
938 | } else { | ||
939 | dev->aac_msix[0].vector_no = 0; | ||
940 | dev->aac_msix[0].dev = dev; | ||
941 | |||
942 | if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, | ||
943 | IRQF_SHARED, | ||
944 | "aacraid", | ||
945 | &(dev->aac_msix[0])) < 0) { | ||
946 | if (dev->msi) | ||
947 | pci_disable_msi(dev->pdev); | ||
948 | printk(KERN_ERR "%s%d: Interrupt unavailable.\n", | ||
949 | name, instance); | ||
950 | goto error_iounmap; | ||
951 | } | ||
813 | } | 952 | } |
814 | dev->dbg_base = dev->base_start; | 953 | dev->dbg_base = dev->base_start; |
815 | dev->dbg_base_mapped = dev->base; | 954 | dev->dbg_base_mapped = dev->base; |
816 | dev->dbg_size = dev->base_size; | 955 | dev->dbg_size = dev->base_size; |
956 | dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message; | ||
817 | 957 | ||
818 | aac_adapter_enable_int(dev); | 958 | aac_adapter_enable_int(dev); |
819 | 959 | ||
@@ -831,3 +971,93 @@ error_iounmap: | |||
831 | return -1; | 971 | return -1; |
832 | } | 972 | } |
833 | 973 | ||
974 | void aac_src_access_devreg(struct aac_dev *dev, int mode) | ||
975 | { | ||
976 | u_int32_t val; | ||
977 | |||
978 | switch (mode) { | ||
979 | case AAC_ENABLE_INTERRUPT: | ||
980 | src_writel(dev, | ||
981 | MUnit.OIMR, | ||
982 | dev->OIMR = (dev->msi_enabled ? | ||
983 | AAC_INT_ENABLE_TYPE1_MSIX : | ||
984 | AAC_INT_ENABLE_TYPE1_INTX)); | ||
985 | break; | ||
986 | |||
987 | case AAC_DISABLE_INTERRUPT: | ||
988 | src_writel(dev, | ||
989 | MUnit.OIMR, | ||
990 | dev->OIMR = AAC_INT_DISABLE_ALL); | ||
991 | break; | ||
992 | |||
993 | case AAC_ENABLE_MSIX: | ||
994 | /* set bit 6 */ | ||
995 | val = src_readl(dev, MUnit.IDR); | ||
996 | val |= 0x40; | ||
997 | src_writel(dev, MUnit.IDR, val); | ||
998 | src_readl(dev, MUnit.IDR); | ||
999 | /* unmask int. */ | ||
1000 | val = PMC_ALL_INTERRUPT_BITS; | ||
1001 | src_writel(dev, MUnit.IOAR, val); | ||
1002 | val = src_readl(dev, MUnit.OIMR); | ||
1003 | src_writel(dev, | ||
1004 | MUnit.OIMR, | ||
1005 | val & (~(PMC_GLOBAL_INT_BIT2 | PMC_GLOBAL_INT_BIT0))); | ||
1006 | break; | ||
1007 | |||
1008 | case AAC_DISABLE_MSIX: | ||
1009 | /* reset bit 6 */ | ||
1010 | val = src_readl(dev, MUnit.IDR); | ||
1011 | val &= ~0x40; | ||
1012 | src_writel(dev, MUnit.IDR, val); | ||
1013 | src_readl(dev, MUnit.IDR); | ||
1014 | break; | ||
1015 | |||
1016 | case AAC_CLEAR_AIF_BIT: | ||
1017 | /* set bit 5 */ | ||
1018 | val = src_readl(dev, MUnit.IDR); | ||
1019 | val |= 0x20; | ||
1020 | src_writel(dev, MUnit.IDR, val); | ||
1021 | src_readl(dev, MUnit.IDR); | ||
1022 | break; | ||
1023 | |||
1024 | case AAC_CLEAR_SYNC_BIT: | ||
1025 | /* set bit 4 */ | ||
1026 | val = src_readl(dev, MUnit.IDR); | ||
1027 | val |= 0x10; | ||
1028 | src_writel(dev, MUnit.IDR, val); | ||
1029 | src_readl(dev, MUnit.IDR); | ||
1030 | break; | ||
1031 | |||
1032 | case AAC_ENABLE_INTX: | ||
1033 | /* set bit 7 */ | ||
1034 | val = src_readl(dev, MUnit.IDR); | ||
1035 | val |= 0x80; | ||
1036 | src_writel(dev, MUnit.IDR, val); | ||
1037 | src_readl(dev, MUnit.IDR); | ||
1038 | /* unmask int. */ | ||
1039 | val = PMC_ALL_INTERRUPT_BITS; | ||
1040 | src_writel(dev, MUnit.IOAR, val); | ||
1041 | src_readl(dev, MUnit.IOAR); | ||
1042 | val = src_readl(dev, MUnit.OIMR); | ||
1043 | src_writel(dev, MUnit.OIMR, | ||
1044 | val & (~(PMC_GLOBAL_INT_BIT2))); | ||
1045 | break; | ||
1046 | |||
1047 | default: | ||
1048 | break; | ||
1049 | } | ||
1050 | } | ||
1051 | |||
1052 | static int aac_src_get_sync_status(struct aac_dev *dev) | ||
1053 | { | ||
1054 | |||
1055 | int val; | ||
1056 | |||
1057 | if (dev->msi_enabled) | ||
1058 | val = src_readl(dev, MUnit.ODR_MSI) & 0x1000 ? 1 : 0; | ||
1059 | else | ||
1060 | val = src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT; | ||
1061 | |||
1062 | return val; | ||
1063 | } | ||
diff --git a/drivers/scsi/aha1542.c b/drivers/scsi/aha1542.c index 770c48ddbe5e..ec432763a29a 100644 --- a/drivers/scsi/aha1542.c +++ b/drivers/scsi/aha1542.c | |||
@@ -1,28 +1,9 @@ | |||
1 | /* $Id: aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $ | 1 | /* |
2 | * linux/kernel/aha1542.c | 2 | * Driver for Adaptec AHA-1542 SCSI host adapters |
3 | * | 3 | * |
4 | * Copyright (C) 1992 Tommy Thorn | 4 | * Copyright (C) 1992 Tommy Thorn |
5 | * Copyright (C) 1993, 1994, 1995 Eric Youngdale | 5 | * Copyright (C) 1993, 1994, 1995 Eric Youngdale |
6 | * | 6 | * Copyright (C) 2015 Ondrej Zary |
7 | * Modified by Eric Youngdale | ||
8 | * Use request_irq and request_dma to help prevent unexpected conflicts | ||
9 | * Set up on-board DMA controller, such that we do not have to | ||
10 | * have the bios enabled to use the aha1542. | ||
11 | * Modified by David Gentzel | ||
12 | * Don't call request_dma if dma mask is 0 (for BusLogic BT-445S VL-Bus | ||
13 | * controller). | ||
14 | * Modified by Matti Aarnio | ||
15 | * Accept parameters from LILO cmd-line. -- 1-Oct-94 | ||
16 | * Modified by Mike McLagan <mike.mclagan@linux.org> | ||
17 | * Recognise extended mode on AHA1542CP, different bit than 1542CF | ||
18 | * 1-Jan-97 | ||
19 | * Modified by Bjorn L. Thordarson and Einar Thor Einarsson | ||
20 | * Recognize that DMA0 is valid DMA channel -- 13-Jul-98 | ||
21 | * Modified by Chris Faulhaber <jedgar@fxp.org> | ||
22 | * Added module command-line options | ||
23 | * 19-Jul-99 | ||
24 | * Modified by Adam Fritzler | ||
25 | * Added proper detection of the AHA-1640 (MCA, now deleted) | ||
26 | */ | 7 | */ |
27 | 8 | ||
28 | #include <linux/module.h> | 9 | #include <linux/module.h> |
@@ -30,96 +11,44 @@ | |||
30 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
31 | #include <linux/types.h> | 12 | #include <linux/types.h> |
32 | #include <linux/string.h> | 13 | #include <linux/string.h> |
33 | #include <linux/ioport.h> | ||
34 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
35 | #include <linux/proc_fs.h> | ||
36 | #include <linux/init.h> | 15 | #include <linux/init.h> |
37 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
38 | #include <linux/isapnp.h> | 17 | #include <linux/isa.h> |
39 | #include <linux/blkdev.h> | 18 | #include <linux/pnp.h> |
40 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
41 | 20 | #include <linux/io.h> | |
42 | #include <asm/dma.h> | 21 | #include <asm/dma.h> |
43 | #include <asm/io.h> | 22 | #include <scsi/scsi_cmnd.h> |
44 | 23 | #include <scsi/scsi_device.h> | |
45 | #include "scsi.h" | ||
46 | #include <scsi/scsi_host.h> | 24 | #include <scsi/scsi_host.h> |
47 | #include "aha1542.h" | 25 | #include "aha1542.h" |
48 | 26 | ||
49 | #define SCSI_BUF_PA(address) isa_virt_to_bus(address) | 27 | #define MAXBOARDS 4 |
50 | #define SCSI_SG_PA(sgent) (isa_page_to_bus(sg_page((sgent))) + (sgent)->offset) | ||
51 | |||
52 | #include <linux/stat.h> | ||
53 | |||
54 | #ifdef DEBUG | ||
55 | #define DEB(x) x | ||
56 | #else | ||
57 | #define DEB(x) | ||
58 | #endif | ||
59 | |||
60 | /* | ||
61 | static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/aha1542.c,v 1.1 1992/07/24 06:27:38 root Exp root $"; | ||
62 | */ | ||
63 | |||
64 | /* The adaptec can be configured for quite a number of addresses, but | ||
65 | I generally do not want the card poking around at random. We allow | ||
66 | two addresses - this allows people to use the Adaptec with a Midi | ||
67 | card, which also used 0x330 -- can be overridden with LILO! */ | ||
68 | |||
69 | #define MAXBOARDS 4 /* Increase this and the sizes of the | ||
70 | arrays below, if you need more.. */ | ||
71 | |||
72 | /* Boards 3,4 slots are reserved for ISAPnP scans */ | ||
73 | |||
74 | static unsigned int bases[MAXBOARDS] __initdata = {0x330, 0x334, 0, 0}; | ||
75 | |||
76 | /* set by aha1542_setup according to the command line; they also may | ||
77 | be marked __initdata, but require zero initializers then */ | ||
78 | |||
79 | static int setup_called[MAXBOARDS]; | ||
80 | static int setup_buson[MAXBOARDS]; | ||
81 | static int setup_busoff[MAXBOARDS]; | ||
82 | static int setup_dmaspeed[MAXBOARDS] __initdata = { -1, -1, -1, -1 }; | ||
83 | 28 | ||
84 | /* | 29 | static bool isapnp = 1; |
85 | * LILO/Module params: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]] | ||
86 | * | ||
87 | * Where: <PORTBASE> is any of the valid AHA addresses: | ||
88 | * 0x130, 0x134, 0x230, 0x234, 0x330, 0x334 | ||
89 | * <BUSON> is the time (in microsecs) that AHA spends on the AT-bus | ||
90 | * when transferring data. 1542A power-on default is 11us, | ||
91 | * valid values are in range: 2..15 (decimal) | ||
92 | * <BUSOFF> is the time that AHA spends OFF THE BUS after while | ||
93 | * it is transferring data (not to monopolize the bus). | ||
94 | * Power-on default is 4us, valid range: 1..64 microseconds. | ||
95 | * <DMASPEED> Default is jumper selected (1542A: on the J1), | ||
96 | * but experimenter can alter it with this. | ||
97 | * Valid values: 5, 6, 7, 8, 10 (MB/s) | ||
98 | * Factory default is 5 MB/s. | ||
99 | */ | ||
100 | |||
101 | #if defined(MODULE) | ||
102 | static bool isapnp = 0; | ||
103 | static int aha1542[] = {0x330, 11, 4, -1}; | ||
104 | module_param_array(aha1542, int, NULL, 0); | ||
105 | module_param(isapnp, bool, 0); | 30 | module_param(isapnp, bool, 0); |
31 | MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)"); | ||
106 | 32 | ||
107 | static struct isapnp_device_id id_table[] __initdata = { | 33 | static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 }; |
108 | { | 34 | module_param_array(io, int, NULL, 0); |
109 | ISAPNP_ANY_ID, ISAPNP_ANY_ID, | 35 | MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)"); |
110 | ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1542), | ||
111 | 0 | ||
112 | }, | ||
113 | {0} | ||
114 | }; | ||
115 | 36 | ||
116 | MODULE_DEVICE_TABLE(isapnp, id_table); | 37 | /* time AHA spends on the AT-bus during data transfer */ |
38 | static int bus_on[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 11us */ | ||
39 | module_param_array(bus_on, int, NULL, 0); | ||
40 | MODULE_PARM_DESC(bus_on, "bus on time [us] (2-15, default=-1 [HW default: 11])"); | ||
117 | 41 | ||
118 | #else | 42 | /* time AHA spends off the bus (not to monopolize it) during data transfer */ |
119 | static int isapnp = 1; | 43 | static int bus_off[MAXBOARDS] = { -1, -1, -1, -1 }; /* power-on default: 4us */ |
120 | #endif | 44 | module_param_array(bus_off, int, NULL, 0); |
45 | MODULE_PARM_DESC(bus_off, "bus off time [us] (1-64, default=-1 [HW default: 4])"); | ||
46 | |||
47 | /* default is jumper selected (J1 on 1542A), factory default = 5 MB/s */ | ||
48 | static int dma_speed[MAXBOARDS] = { -1, -1, -1, -1 }; | ||
49 | module_param_array(dma_speed, int, NULL, 0); | ||
50 | MODULE_PARM_DESC(dma_speed, "DMA speed [MB/s] (5,6,7,8,10, default=-1 [by jumper])"); | ||
121 | 51 | ||
122 | #define BIOS_TRANSLATION_1632 0 /* Used by some old 1542A boards */ | ||
123 | #define BIOS_TRANSLATION_6432 1 /* Default case these days */ | 52 | #define BIOS_TRANSLATION_6432 1 /* Default case these days */ |
124 | #define BIOS_TRANSLATION_25563 2 /* Big disk case */ | 53 | #define BIOS_TRANSLATION_25563 2 /* Big disk case */ |
125 | 54 | ||
@@ -128,134 +57,71 @@ struct aha1542_hostdata { | |||
128 | int bios_translation; /* Mapping bios uses - for compatibility */ | 57 | int bios_translation; /* Mapping bios uses - for compatibility */ |
129 | int aha1542_last_mbi_used; | 58 | int aha1542_last_mbi_used; |
130 | int aha1542_last_mbo_used; | 59 | int aha1542_last_mbo_used; |
131 | Scsi_Cmnd *SCint[AHA1542_MAILBOXES]; | 60 | struct scsi_cmnd *int_cmds[AHA1542_MAILBOXES]; |
132 | struct mailbox mb[2 * AHA1542_MAILBOXES]; | 61 | struct mailbox mb[2 * AHA1542_MAILBOXES]; |
133 | struct ccb ccb[AHA1542_MAILBOXES]; | 62 | struct ccb ccb[AHA1542_MAILBOXES]; |
134 | }; | 63 | }; |
135 | 64 | ||
136 | #define HOSTDATA(host) ((struct aha1542_hostdata *) &host->hostdata) | 65 | static inline void aha1542_intr_reset(u16 base) |
137 | 66 | { | |
138 | static DEFINE_SPINLOCK(aha1542_lock); | 67 | outb(IRST, CONTROL(base)); |
139 | 68 | } | |
140 | |||
141 | |||
142 | #define WAITnexttimeout 3000000 | ||
143 | |||
144 | static void setup_mailboxes(int base_io, struct Scsi_Host *shpnt); | ||
145 | static int aha1542_restart(struct Scsi_Host *shost); | ||
146 | static void aha1542_intr_handle(struct Scsi_Host *shost); | ||
147 | 69 | ||
148 | #define aha1542_intr_reset(base) outb(IRST, CONTROL(base)) | 70 | static inline bool wait_mask(u16 port, u8 mask, u8 allof, u8 noneof, int timeout) |
71 | { | ||
72 | bool delayed = true; | ||
149 | 73 | ||
150 | #define WAIT(port, mask, allof, noneof) \ | 74 | if (timeout == 0) { |
151 | { register int WAITbits; \ | 75 | timeout = 3000000; |
152 | register int WAITtimeout = WAITnexttimeout; \ | 76 | delayed = false; |
153 | while (1) { \ | 77 | } |
154 | WAITbits = inb(port) & (mask); \ | ||
155 | if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ | ||
156 | break; \ | ||
157 | if (--WAITtimeout == 0) goto fail; \ | ||
158 | } \ | ||
159 | } | ||
160 | 78 | ||
161 | /* Similar to WAIT, except we use the udelay call to regulate the | 79 | while (1) { |
162 | amount of time we wait. */ | 80 | u8 bits = inb(port) & mask; |
163 | #define WAITd(port, mask, allof, noneof, timeout) \ | 81 | if ((bits & allof) == allof && ((bits & noneof) == 0)) |
164 | { register int WAITbits; \ | 82 | break; |
165 | register int WAITtimeout = timeout; \ | 83 | if (delayed) |
166 | while (1) { \ | 84 | mdelay(1); |
167 | WAITbits = inb(port) & (mask); \ | 85 | if (--timeout == 0) |
168 | if ((WAITbits & (allof)) == (allof) && ((WAITbits & (noneof)) == 0)) \ | 86 | return false; |
169 | break; \ | 87 | } |
170 | mdelay(1); \ | ||
171 | if (--WAITtimeout == 0) goto fail; \ | ||
172 | } \ | ||
173 | } | ||
174 | 88 | ||
175 | static void aha1542_stat(void) | 89 | return true; |
176 | { | ||
177 | /* int s = inb(STATUS), i = inb(INTRFLAGS); | ||
178 | printk("status=%x intrflags=%x\n", s, i, WAITnexttimeout-WAITtimeout); */ | ||
179 | } | 90 | } |
180 | 91 | ||
181 | /* This is a bit complicated, but we need to make sure that an interrupt | 92 | static int aha1542_outb(unsigned int base, u8 val) |
182 | routine does not send something out while we are in the middle of this. | ||
183 | Fortunately, it is only at boot time that multi-byte messages | ||
184 | are ever sent. */ | ||
185 | static int aha1542_out(unsigned int base, unchar * cmdp, int len) | ||
186 | { | 93 | { |
187 | unsigned long flags = 0; | 94 | if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) |
188 | int got_lock; | 95 | return 1; |
189 | 96 | outb(val, DATA(base)); | |
190 | if (len == 1) { | 97 | |
191 | got_lock = 0; | ||
192 | while (1 == 1) { | ||
193 | WAIT(STATUS(base), CDF, 0, CDF); | ||
194 | spin_lock_irqsave(&aha1542_lock, flags); | ||
195 | if (inb(STATUS(base)) & CDF) { | ||
196 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
197 | continue; | ||
198 | } | ||
199 | outb(*cmdp, DATA(base)); | ||
200 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
201 | return 0; | ||
202 | } | ||
203 | } else { | ||
204 | spin_lock_irqsave(&aha1542_lock, flags); | ||
205 | got_lock = 1; | ||
206 | while (len--) { | ||
207 | WAIT(STATUS(base), CDF, 0, CDF); | ||
208 | outb(*cmdp++, DATA(base)); | ||
209 | } | ||
210 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
211 | } | ||
212 | return 0; | 98 | return 0; |
213 | fail: | ||
214 | if (got_lock) | ||
215 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
216 | printk(KERN_ERR "aha1542_out failed(%d): ", len + 1); | ||
217 | aha1542_stat(); | ||
218 | return 1; | ||
219 | } | 99 | } |
220 | 100 | ||
221 | /* Only used at boot time, so we do not need to worry about latency as much | 101 | static int aha1542_out(unsigned int base, u8 *buf, int len) |
222 | here */ | ||
223 | |||
224 | static int __init aha1542_in(unsigned int base, unchar * cmdp, int len) | ||
225 | { | 102 | { |
226 | unsigned long flags; | ||
227 | |||
228 | spin_lock_irqsave(&aha1542_lock, flags); | ||
229 | while (len--) { | 103 | while (len--) { |
230 | WAIT(STATUS(base), DF, DF, 0); | 104 | if (!wait_mask(STATUS(base), CDF, 0, CDF, 0)) |
231 | *cmdp++ = inb(DATA(base)); | 105 | return 1; |
106 | outb(*buf++, DATA(base)); | ||
232 | } | 107 | } |
233 | spin_unlock_irqrestore(&aha1542_lock, flags); | 108 | if (!wait_mask(INTRFLAGS(base), INTRMASK, HACC, 0, 0)) |
109 | return 1; | ||
110 | |||
234 | return 0; | 111 | return 0; |
235 | fail: | ||
236 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
237 | printk(KERN_ERR "aha1542_in failed(%d): ", len + 1); | ||
238 | aha1542_stat(); | ||
239 | return 1; | ||
240 | } | 112 | } |
241 | 113 | ||
242 | /* Similar to aha1542_in, except that we wait a very short period of time. | 114 | /* Only used at boot time, so we do not need to worry about latency as much |
243 | We use this if we know the board is alive and awake, but we are not sure | 115 | here */ |
244 | if the board will respond to the command we are about to send or not */ | ||
245 | static int __init aha1542_in1(unsigned int base, unchar * cmdp, int len) | ||
246 | { | ||
247 | unsigned long flags; | ||
248 | 116 | ||
249 | spin_lock_irqsave(&aha1542_lock, flags); | 117 | static int aha1542_in(unsigned int base, u8 *buf, int len, int timeout) |
118 | { | ||
250 | while (len--) { | 119 | while (len--) { |
251 | WAITd(STATUS(base), DF, DF, 0, 100); | 120 | if (!wait_mask(STATUS(base), DF, DF, 0, timeout)) |
252 | *cmdp++ = inb(DATA(base)); | 121 | return 1; |
122 | *buf++ = inb(DATA(base)); | ||
253 | } | 123 | } |
254 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
255 | return 0; | 124 | return 0; |
256 | fail: | ||
257 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
258 | return 1; | ||
259 | } | 125 | } |
260 | 126 | ||
261 | static int makecode(unsigned hosterr, unsigned scsierr) | 127 | static int makecode(unsigned hosterr, unsigned scsierr) |
@@ -297,7 +163,9 @@ static int makecode(unsigned hosterr, unsigned scsierr) | |||
297 | case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero | 163 | case 0x1a: /* Invalid CCB or Segment List Parameter-A segment list with a zero |
298 | length segment or invalid segment list boundaries was received. | 164 | length segment or invalid segment list boundaries was received. |
299 | A CCB parameter was invalid. */ | 165 | A CCB parameter was invalid. */ |
300 | DEB(printk("Aha1542: %x %x\n", hosterr, scsierr)); | 166 | #ifdef DEBUG |
167 | printk("Aha1542: %x %x\n", hosterr, scsierr); | ||
168 | #endif | ||
301 | hosterr = DID_ERROR; /* Couldn't find any better */ | 169 | hosterr = DID_ERROR; /* Couldn't find any better */ |
302 | break; | 170 | break; |
303 | 171 | ||
@@ -314,106 +182,74 @@ static int makecode(unsigned hosterr, unsigned scsierr) | |||
314 | return scsierr | (hosterr << 16); | 182 | return scsierr | (hosterr << 16); |
315 | } | 183 | } |
316 | 184 | ||
317 | static int __init aha1542_test_port(int bse, struct Scsi_Host *shpnt) | 185 | static int aha1542_test_port(struct Scsi_Host *sh) |
318 | { | 186 | { |
319 | unchar inquiry_cmd[] = {CMD_INQUIRY}; | 187 | u8 inquiry_result[4]; |
320 | unchar inquiry_result[4]; | 188 | int i; |
321 | unchar *cmdp; | ||
322 | int len; | ||
323 | volatile int debug = 0; | ||
324 | 189 | ||
325 | /* Quick and dirty test for presence of the card. */ | 190 | /* Quick and dirty test for presence of the card. */ |
326 | if (inb(STATUS(bse)) == 0xff) | 191 | if (inb(STATUS(sh->io_port)) == 0xff) |
327 | return 0; | 192 | return 0; |
328 | 193 | ||
329 | /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */ | 194 | /* Reset the adapter. I ought to make a hard reset, but it's not really necessary */ |
330 | 195 | ||
331 | /* DEB(printk("aha1542_test_port called \n")); */ | ||
332 | |||
333 | /* In case some other card was probing here, reset interrupts */ | 196 | /* In case some other card was probing here, reset interrupts */ |
334 | aha1542_intr_reset(bse); /* reset interrupts, so they don't block */ | 197 | aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */ |
335 | 198 | ||
336 | outb(SRST | IRST /*|SCRST */ , CONTROL(bse)); | 199 | outb(SRST | IRST /*|SCRST */ , CONTROL(sh->io_port)); |
337 | 200 | ||
338 | mdelay(20); /* Wait a little bit for things to settle down. */ | 201 | mdelay(20); /* Wait a little bit for things to settle down. */ |
339 | 202 | ||
340 | debug = 1; | ||
341 | /* Expect INIT and IDLE, any of the others are bad */ | 203 | /* Expect INIT and IDLE, any of the others are bad */ |
342 | WAIT(STATUS(bse), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF); | 204 | if (!wait_mask(STATUS(sh->io_port), STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) |
205 | return 0; | ||
343 | 206 | ||
344 | debug = 2; | ||
345 | /* Shouldn't have generated any interrupts during reset */ | 207 | /* Shouldn't have generated any interrupts during reset */ |
346 | if (inb(INTRFLAGS(bse)) & INTRMASK) | 208 | if (inb(INTRFLAGS(sh->io_port)) & INTRMASK) |
347 | goto fail; | 209 | return 0; |
348 | |||
349 | 210 | ||
350 | /* Perform a host adapter inquiry instead so we do not need to set | 211 | /* Perform a host adapter inquiry instead so we do not need to set |
351 | up the mailboxes ahead of time */ | 212 | up the mailboxes ahead of time */ |
352 | 213 | ||
353 | aha1542_out(bse, inquiry_cmd, 1); | 214 | aha1542_outb(sh->io_port, CMD_INQUIRY); |
354 | |||
355 | debug = 3; | ||
356 | len = 4; | ||
357 | cmdp = &inquiry_result[0]; | ||
358 | 215 | ||
359 | while (len--) { | 216 | for (i = 0; i < 4; i++) { |
360 | WAIT(STATUS(bse), DF, DF, 0); | 217 | if (!wait_mask(STATUS(sh->io_port), DF, DF, 0, 0)) |
361 | *cmdp++ = inb(DATA(bse)); | 218 | return 0; |
219 | inquiry_result[i] = inb(DATA(sh->io_port)); | ||
362 | } | 220 | } |
363 | 221 | ||
364 | debug = 8; | ||
365 | /* Reading port should reset DF */ | 222 | /* Reading port should reset DF */ |
366 | if (inb(STATUS(bse)) & DF) | 223 | if (inb(STATUS(sh->io_port)) & DF) |
367 | goto fail; | 224 | return 0; |
368 | 225 | ||
369 | debug = 9; | ||
370 | /* When HACC, command is completed, and we're though testing */ | 226 | /* When HACC, command is completed, and we're though testing */ |
371 | WAIT(INTRFLAGS(bse), HACC, HACC, 0); | 227 | if (!wait_mask(INTRFLAGS(sh->io_port), HACC, HACC, 0, 0)) |
372 | /* now initialize adapter */ | 228 | return 0; |
373 | 229 | ||
374 | debug = 10; | ||
375 | /* Clear interrupts */ | 230 | /* Clear interrupts */ |
376 | outb(IRST, CONTROL(bse)); | 231 | outb(IRST, CONTROL(sh->io_port)); |
377 | |||
378 | debug = 11; | ||
379 | |||
380 | return debug; /* 1 = ok */ | ||
381 | fail: | ||
382 | return 0; /* 0 = not ok */ | ||
383 | } | ||
384 | 232 | ||
385 | /* A quick wrapper for do_aha1542_intr_handle to grab the spin lock */ | 233 | return 1; |
386 | static irqreturn_t do_aha1542_intr_handle(int dummy, void *dev_id) | ||
387 | { | ||
388 | unsigned long flags; | ||
389 | struct Scsi_Host *shost = dev_id; | ||
390 | |||
391 | spin_lock_irqsave(shost->host_lock, flags); | ||
392 | aha1542_intr_handle(shost); | ||
393 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
394 | return IRQ_HANDLED; | ||
395 | } | 234 | } |
396 | 235 | ||
397 | /* A "high" level interrupt handler */ | 236 | static irqreturn_t aha1542_interrupt(int irq, void *dev_id) |
398 | static void aha1542_intr_handle(struct Scsi_Host *shost) | ||
399 | { | 237 | { |
400 | void (*my_done) (Scsi_Cmnd *) = NULL; | 238 | struct Scsi_Host *sh = dev_id; |
239 | struct aha1542_hostdata *aha1542 = shost_priv(sh); | ||
240 | void (*my_done)(struct scsi_cmnd *) = NULL; | ||
401 | int errstatus, mbi, mbo, mbistatus; | 241 | int errstatus, mbi, mbo, mbistatus; |
402 | int number_serviced; | 242 | int number_serviced; |
403 | unsigned long flags; | 243 | unsigned long flags; |
404 | Scsi_Cmnd *SCtmp; | 244 | struct scsi_cmnd *tmp_cmd; |
405 | int flag; | 245 | int flag; |
406 | int needs_restart; | 246 | struct mailbox *mb = aha1542->mb; |
407 | struct mailbox *mb; | 247 | struct ccb *ccb = aha1542->ccb; |
408 | struct ccb *ccb; | ||
409 | |||
410 | mb = HOSTDATA(shost)->mb; | ||
411 | ccb = HOSTDATA(shost)->ccb; | ||
412 | 248 | ||
413 | #ifdef DEBUG | 249 | #ifdef DEBUG |
414 | { | 250 | { |
415 | flag = inb(INTRFLAGS(shost->io_port)); | 251 | flag = inb(INTRFLAGS(sh->io_port)); |
416 | printk(KERN_DEBUG "aha1542_intr_handle: "); | 252 | shost_printk(KERN_DEBUG, sh, "aha1542_intr_handle: "); |
417 | if (!(flag & ANYINTR)) | 253 | if (!(flag & ANYINTR)) |
418 | printk("no interrupt?"); | 254 | printk("no interrupt?"); |
419 | if (flag & MBIF) | 255 | if (flag & MBIF) |
@@ -424,14 +260,14 @@ static void aha1542_intr_handle(struct Scsi_Host *shost) | |||
424 | printk("HACC "); | 260 | printk("HACC "); |
425 | if (flag & SCRD) | 261 | if (flag & SCRD) |
426 | printk("SCRD "); | 262 | printk("SCRD "); |
427 | printk("status %02x\n", inb(STATUS(shost->io_port))); | 263 | printk("status %02x\n", inb(STATUS(sh->io_port))); |
428 | }; | 264 | }; |
429 | #endif | 265 | #endif |
430 | number_serviced = 0; | 266 | number_serviced = 0; |
431 | needs_restart = 0; | ||
432 | 267 | ||
433 | while (1 == 1) { | 268 | spin_lock_irqsave(sh->host_lock, flags); |
434 | flag = inb(INTRFLAGS(shost->io_port)); | 269 | while (1) { |
270 | flag = inb(INTRFLAGS(sh->io_port)); | ||
435 | 271 | ||
436 | /* Check for unusual interrupts. If any of these happen, we should | 272 | /* Check for unusual interrupts. If any of these happen, we should |
437 | probably do something special, but for now just printing a message | 273 | probably do something special, but for now just printing a message |
@@ -442,15 +278,12 @@ static void aha1542_intr_handle(struct Scsi_Host *shost) | |||
442 | printk("MBOF "); | 278 | printk("MBOF "); |
443 | if (flag & HACC) | 279 | if (flag & HACC) |
444 | printk("HACC "); | 280 | printk("HACC "); |
445 | if (flag & SCRD) { | 281 | if (flag & SCRD) |
446 | needs_restart = 1; | ||
447 | printk("SCRD "); | 282 | printk("SCRD "); |
448 | } | ||
449 | } | 283 | } |
450 | aha1542_intr_reset(shost->io_port); | 284 | aha1542_intr_reset(sh->io_port); |
451 | 285 | ||
452 | spin_lock_irqsave(&aha1542_lock, flags); | 286 | mbi = aha1542->aha1542_last_mbi_used + 1; |
453 | mbi = HOSTDATA(shost)->aha1542_last_mbi_used + 1; | ||
454 | if (mbi >= 2 * AHA1542_MAILBOXES) | 287 | if (mbi >= 2 * AHA1542_MAILBOXES) |
455 | mbi = AHA1542_MAILBOXES; | 288 | mbi = AHA1542_MAILBOXES; |
456 | 289 | ||
@@ -460,57 +293,51 @@ static void aha1542_intr_handle(struct Scsi_Host *shost) | |||
460 | mbi++; | 293 | mbi++; |
461 | if (mbi >= 2 * AHA1542_MAILBOXES) | 294 | if (mbi >= 2 * AHA1542_MAILBOXES) |
462 | mbi = AHA1542_MAILBOXES; | 295 | mbi = AHA1542_MAILBOXES; |
463 | } while (mbi != HOSTDATA(shost)->aha1542_last_mbi_used); | 296 | } while (mbi != aha1542->aha1542_last_mbi_used); |
464 | 297 | ||
465 | if (mb[mbi].status == 0) { | 298 | if (mb[mbi].status == 0) { |
466 | spin_unlock_irqrestore(&aha1542_lock, flags); | 299 | spin_unlock_irqrestore(sh->host_lock, flags); |
467 | /* Hmm, no mail. Must have read it the last time around */ | 300 | /* Hmm, no mail. Must have read it the last time around */ |
468 | if (!number_serviced && !needs_restart) | 301 | if (!number_serviced) |
469 | printk(KERN_WARNING "aha1542.c: interrupt received, but no mail.\n"); | 302 | shost_printk(KERN_WARNING, sh, "interrupt received, but no mail.\n"); |
470 | /* We detected a reset. Restart all pending commands for | 303 | return IRQ_HANDLED; |
471 | devices that use the hard reset option */ | ||
472 | if (needs_restart) | ||
473 | aha1542_restart(shost); | ||
474 | return; | ||
475 | }; | 304 | }; |
476 | 305 | ||
477 | mbo = (scsi2int(mb[mbi].ccbptr) - (SCSI_BUF_PA(&ccb[0]))) / sizeof(struct ccb); | 306 | mbo = (scsi2int(mb[mbi].ccbptr) - (isa_virt_to_bus(&ccb[0]))) / sizeof(struct ccb); |
478 | mbistatus = mb[mbi].status; | 307 | mbistatus = mb[mbi].status; |
479 | mb[mbi].status = 0; | 308 | mb[mbi].status = 0; |
480 | HOSTDATA(shost)->aha1542_last_mbi_used = mbi; | 309 | aha1542->aha1542_last_mbi_used = mbi; |
481 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
482 | 310 | ||
483 | #ifdef DEBUG | 311 | #ifdef DEBUG |
484 | { | 312 | if (ccb[mbo].tarstat | ccb[mbo].hastat) |
485 | if (ccb[mbo].tarstat | ccb[mbo].hastat) | 313 | shost_printk(KERN_DEBUG, sh, "aha1542_command: returning %x (status %d)\n", |
486 | printk(KERN_DEBUG "aha1542_command: returning %x (status %d)\n", | 314 | ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status); |
487 | ccb[mbo].tarstat + ((int) ccb[mbo].hastat << 16), mb[mbi].status); | ||
488 | }; | ||
489 | #endif | 315 | #endif |
490 | 316 | ||
491 | if (mbistatus == 3) | 317 | if (mbistatus == 3) |
492 | continue; /* Aborted command not found */ | 318 | continue; /* Aborted command not found */ |
493 | 319 | ||
494 | #ifdef DEBUG | 320 | #ifdef DEBUG |
495 | printk(KERN_DEBUG "...done %d %d\n", mbo, mbi); | 321 | shost_printk(KERN_DEBUG, sh, "...done %d %d\n", mbo, mbi); |
496 | #endif | 322 | #endif |
497 | 323 | ||
498 | SCtmp = HOSTDATA(shost)->SCint[mbo]; | 324 | tmp_cmd = aha1542->int_cmds[mbo]; |
499 | 325 | ||
500 | if (!SCtmp || !SCtmp->scsi_done) { | 326 | if (!tmp_cmd || !tmp_cmd->scsi_done) { |
501 | printk(KERN_WARNING "aha1542_intr_handle: Unexpected interrupt\n"); | 327 | spin_unlock_irqrestore(sh->host_lock, flags); |
502 | printk(KERN_WARNING "tarstat=%x, hastat=%x idlun=%x ccb#=%d \n", ccb[mbo].tarstat, | 328 | shost_printk(KERN_WARNING, sh, "Unexpected interrupt\n"); |
329 | shost_printk(KERN_WARNING, sh, "tarstat=%x, hastat=%x idlun=%x ccb#=%d\n", ccb[mbo].tarstat, | ||
503 | ccb[mbo].hastat, ccb[mbo].idlun, mbo); | 330 | ccb[mbo].hastat, ccb[mbo].idlun, mbo); |
504 | return; | 331 | return IRQ_HANDLED; |
505 | } | 332 | } |
506 | my_done = SCtmp->scsi_done; | 333 | my_done = tmp_cmd->scsi_done; |
507 | kfree(SCtmp->host_scribble); | 334 | kfree(tmp_cmd->host_scribble); |
508 | SCtmp->host_scribble = NULL; | 335 | tmp_cmd->host_scribble = NULL; |
509 | /* Fetch the sense data, and tuck it away, in the required slot. The | 336 | /* Fetch the sense data, and tuck it away, in the required slot. The |
510 | Adaptec automatically fetches it, and there is no guarantee that | 337 | Adaptec automatically fetches it, and there is no guarantee that |
511 | we will still have it in the cdb when we come back */ | 338 | we will still have it in the cdb when we come back */ |
512 | if (ccb[mbo].tarstat == 2) | 339 | if (ccb[mbo].tarstat == 2) |
513 | memcpy(SCtmp->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], | 340 | memcpy(tmp_cmd->sense_buffer, &ccb[mbo].cdb[ccb[mbo].cdblen], |
514 | SCSI_SENSE_BUFFERSIZE); | 341 | SCSI_SENSE_BUFFERSIZE); |
515 | 342 | ||
516 | 343 | ||
@@ -525,166 +352,122 @@ static void aha1542_intr_handle(struct Scsi_Host *shost) | |||
525 | 352 | ||
526 | #ifdef DEBUG | 353 | #ifdef DEBUG |
527 | if (errstatus) | 354 | if (errstatus) |
528 | printk(KERN_DEBUG "(aha1542 error:%x %x %x) ", errstatus, | 355 | shost_printk(KERN_DEBUG, sh, "(aha1542 error:%x %x %x) ", errstatus, |
529 | ccb[mbo].hastat, ccb[mbo].tarstat); | 356 | ccb[mbo].hastat, ccb[mbo].tarstat); |
357 | if (ccb[mbo].tarstat == 2) | ||
358 | print_hex_dump_bytes("sense: ", DUMP_PREFIX_NONE, &ccb[mbo].cdb[ccb[mbo].cdblen], 12); | ||
359 | if (errstatus) | ||
360 | printk("aha1542_intr_handle: returning %6x\n", errstatus); | ||
530 | #endif | 361 | #endif |
531 | 362 | tmp_cmd->result = errstatus; | |
532 | if (ccb[mbo].tarstat == 2) { | 363 | aha1542->int_cmds[mbo] = NULL; /* This effectively frees up the mailbox slot, as |
533 | #ifdef DEBUG | 364 | far as queuecommand is concerned */ |
534 | int i; | 365 | my_done(tmp_cmd); |
535 | #endif | ||
536 | DEB(printk("aha1542_intr_handle: sense:")); | ||
537 | #ifdef DEBUG | ||
538 | for (i = 0; i < 12; i++) | ||
539 | printk("%02x ", ccb[mbo].cdb[ccb[mbo].cdblen + i]); | ||
540 | printk("\n"); | ||
541 | #endif | ||
542 | /* | ||
543 | DEB(printk("aha1542_intr_handle: buf:")); | ||
544 | for (i = 0; i < bufflen; i++) | ||
545 | printk("%02x ", ((unchar *)buff)[i]); | ||
546 | printk("\n"); | ||
547 | */ | ||
548 | } | ||
549 | DEB(if (errstatus) printk("aha1542_intr_handle: returning %6x\n", errstatus)); | ||
550 | SCtmp->result = errstatus; | ||
551 | HOSTDATA(shost)->SCint[mbo] = NULL; /* This effectively frees up the mailbox slot, as | ||
552 | far as queuecommand is concerned */ | ||
553 | my_done(SCtmp); | ||
554 | number_serviced++; | 366 | number_serviced++; |
555 | }; | 367 | }; |
556 | } | 368 | } |
557 | 369 | ||
558 | static int aha1542_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) | 370 | static int aha1542_queuecommand(struct Scsi_Host *sh, struct scsi_cmnd *cmd) |
559 | { | 371 | { |
560 | unchar ahacmd = CMD_START_SCSI; | 372 | struct aha1542_hostdata *aha1542 = shost_priv(sh); |
561 | unchar direction; | 373 | u8 direction; |
562 | unchar *cmd = (unchar *) SCpnt->cmnd; | 374 | u8 target = cmd->device->id; |
563 | unchar target = SCpnt->device->id; | 375 | u8 lun = cmd->device->lun; |
564 | unchar lun = SCpnt->device->lun; | ||
565 | unsigned long flags; | 376 | unsigned long flags; |
566 | int bufflen = scsi_bufflen(SCpnt); | 377 | int bufflen = scsi_bufflen(cmd); |
567 | int mbo; | 378 | int mbo; |
568 | struct mailbox *mb; | 379 | struct mailbox *mb = aha1542->mb; |
569 | struct ccb *ccb; | 380 | struct ccb *ccb = aha1542->ccb; |
570 | 381 | ||
571 | DEB(int i); | 382 | if (*cmd->cmnd == REQUEST_SENSE) { |
572 | |||
573 | mb = HOSTDATA(SCpnt->device->host)->mb; | ||
574 | ccb = HOSTDATA(SCpnt->device->host)->ccb; | ||
575 | |||
576 | DEB(if (target > 1) { | ||
577 | SCpnt->result = DID_TIME_OUT << 16; | ||
578 | done(SCpnt); return 0; | ||
579 | } | ||
580 | ); | ||
581 | |||
582 | if (*cmd == REQUEST_SENSE) { | ||
583 | /* Don't do the command - we have the sense data already */ | 383 | /* Don't do the command - we have the sense data already */ |
584 | #if 0 | 384 | cmd->result = 0; |
585 | /* scsi_request_sense() provides a buffer of size 256, | 385 | cmd->scsi_done(cmd); |
586 | so there is no reason to expect equality */ | ||
587 | if (bufflen != SCSI_SENSE_BUFFERSIZE) | ||
588 | printk(KERN_CRIT "aha1542: Wrong buffer length supplied " | ||
589 | "for request sense (%d)\n", bufflen); | ||
590 | #endif | ||
591 | SCpnt->result = 0; | ||
592 | done(SCpnt); | ||
593 | return 0; | 386 | return 0; |
594 | } | 387 | } |
595 | #ifdef DEBUG | 388 | #ifdef DEBUG |
596 | if (*cmd == READ_10 || *cmd == WRITE_10) | 389 | { |
597 | i = xscsi2int(cmd + 2); | 390 | int i = -1; |
598 | else if (*cmd == READ_6 || *cmd == WRITE_6) | 391 | if (*cmd->cmnd == READ_10 || *cmd->cmnd == WRITE_10) |
599 | i = scsi2int(cmd + 2); | 392 | i = xscsi2int(cmd->cmnd + 2); |
600 | else | 393 | else if (*cmd->cmnd == READ_6 || *cmd->cmnd == WRITE_6) |
601 | i = -1; | 394 | i = scsi2int(cmd->cmnd + 2); |
602 | if (done) | 395 | shost_printk(KERN_DEBUG, sh, "aha1542_queuecommand: dev %d cmd %02x pos %d len %d", |
603 | printk(KERN_DEBUG "aha1542_queuecommand: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); | 396 | target, *cmd->cmnd, i, bufflen); |
604 | else | 397 | print_hex_dump_bytes("command: ", DUMP_PREFIX_NONE, cmd->cmnd, cmd->cmd_len); |
605 | printk(KERN_DEBUG "aha1542_command: dev %d cmd %02x pos %d len %d ", target, *cmd, i, bufflen); | 398 | } |
606 | aha1542_stat(); | ||
607 | printk(KERN_DEBUG "aha1542_queuecommand: dumping scsi cmd:"); | ||
608 | for (i = 0; i < SCpnt->cmd_len; i++) | ||
609 | printk("%02x ", cmd[i]); | ||
610 | printk("\n"); | ||
611 | if (*cmd == WRITE_10 || *cmd == WRITE_6) | ||
612 | return 0; /* we are still testing, so *don't* write */ | ||
613 | #endif | 399 | #endif |
614 | /* Use the outgoing mailboxes in a round-robin fashion, because this | 400 | /* Use the outgoing mailboxes in a round-robin fashion, because this |
615 | is how the host adapter will scan for them */ | 401 | is how the host adapter will scan for them */ |
616 | 402 | ||
617 | spin_lock_irqsave(&aha1542_lock, flags); | 403 | spin_lock_irqsave(sh->host_lock, flags); |
618 | mbo = HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used + 1; | 404 | mbo = aha1542->aha1542_last_mbo_used + 1; |
619 | if (mbo >= AHA1542_MAILBOXES) | 405 | if (mbo >= AHA1542_MAILBOXES) |
620 | mbo = 0; | 406 | mbo = 0; |
621 | 407 | ||
622 | do { | 408 | do { |
623 | if (mb[mbo].status == 0 && HOSTDATA(SCpnt->device->host)->SCint[mbo] == NULL) | 409 | if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL) |
624 | break; | 410 | break; |
625 | mbo++; | 411 | mbo++; |
626 | if (mbo >= AHA1542_MAILBOXES) | 412 | if (mbo >= AHA1542_MAILBOXES) |
627 | mbo = 0; | 413 | mbo = 0; |
628 | } while (mbo != HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used); | 414 | } while (mbo != aha1542->aha1542_last_mbo_used); |
629 | 415 | ||
630 | if (mb[mbo].status || HOSTDATA(SCpnt->device->host)->SCint[mbo]) | 416 | if (mb[mbo].status || aha1542->int_cmds[mbo]) |
631 | panic("Unable to find empty mailbox for aha1542.\n"); | 417 | panic("Unable to find empty mailbox for aha1542.\n"); |
632 | 418 | ||
633 | HOSTDATA(SCpnt->device->host)->SCint[mbo] = SCpnt; /* This will effectively prevent someone else from | 419 | aha1542->int_cmds[mbo] = cmd; /* This will effectively prevent someone else from |
634 | screwing with this cdb. */ | 420 | screwing with this cdb. */ |
635 | 421 | ||
636 | HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used = mbo; | 422 | aha1542->aha1542_last_mbo_used = mbo; |
637 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
638 | 423 | ||
639 | #ifdef DEBUG | 424 | #ifdef DEBUG |
640 | printk(KERN_DEBUG "Sending command (%d %x)...", mbo, done); | 425 | shost_printk(KERN_DEBUG, sh, "Sending command (%d %p)...", mbo, cmd->scsi_done); |
641 | #endif | 426 | #endif |
642 | 427 | ||
643 | any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo])); /* This gets trashed for some reason */ | 428 | any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */ |
644 | 429 | ||
645 | memset(&ccb[mbo], 0, sizeof(struct ccb)); | 430 | memset(&ccb[mbo], 0, sizeof(struct ccb)); |
646 | 431 | ||
647 | ccb[mbo].cdblen = SCpnt->cmd_len; | 432 | ccb[mbo].cdblen = cmd->cmd_len; |
648 | 433 | ||
649 | direction = 0; | 434 | direction = 0; |
650 | if (*cmd == READ_10 || *cmd == READ_6) | 435 | if (*cmd->cmnd == READ_10 || *cmd->cmnd == READ_6) |
651 | direction = 8; | 436 | direction = 8; |
652 | else if (*cmd == WRITE_10 || *cmd == WRITE_6) | 437 | else if (*cmd->cmnd == WRITE_10 || *cmd->cmnd == WRITE_6) |
653 | direction = 16; | 438 | direction = 16; |
654 | 439 | ||
655 | memcpy(ccb[mbo].cdb, cmd, ccb[mbo].cdblen); | 440 | memcpy(ccb[mbo].cdb, cmd->cmnd, ccb[mbo].cdblen); |
656 | 441 | ||
657 | if (bufflen) { | 442 | if (bufflen) { |
658 | struct scatterlist *sg; | 443 | struct scatterlist *sg; |
659 | struct chain *cptr; | 444 | struct chain *cptr; |
660 | #ifdef DEBUG | 445 | int i, sg_count = scsi_sg_count(cmd); |
661 | unsigned char *ptr; | 446 | |
662 | #endif | ||
663 | int i, sg_count = scsi_sg_count(SCpnt); | ||
664 | ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */ | 447 | ccb[mbo].op = 2; /* SCSI Initiator Command w/scatter-gather */ |
665 | SCpnt->host_scribble = kmalloc(sizeof(*cptr)*sg_count, | 448 | cmd->host_scribble = kmalloc(sizeof(*cptr)*sg_count, |
666 | GFP_KERNEL | GFP_DMA); | 449 | GFP_KERNEL | GFP_DMA); |
667 | cptr = (struct chain *) SCpnt->host_scribble; | 450 | cptr = (struct chain *) cmd->host_scribble; |
668 | if (cptr == NULL) { | 451 | if (cptr == NULL) { |
669 | /* free the claimed mailbox slot */ | 452 | /* free the claimed mailbox slot */ |
670 | HOSTDATA(SCpnt->device->host)->SCint[mbo] = NULL; | 453 | aha1542->int_cmds[mbo] = NULL; |
454 | spin_unlock_irqrestore(sh->host_lock, flags); | ||
671 | return SCSI_MLQUEUE_HOST_BUSY; | 455 | return SCSI_MLQUEUE_HOST_BUSY; |
672 | } | 456 | } |
673 | scsi_for_each_sg(SCpnt, sg, sg_count, i) { | 457 | scsi_for_each_sg(cmd, sg, sg_count, i) { |
674 | any2scsi(cptr[i].dataptr, SCSI_SG_PA(sg)); | 458 | any2scsi(cptr[i].dataptr, isa_page_to_bus(sg_page(sg)) |
459 | + sg->offset); | ||
675 | any2scsi(cptr[i].datalen, sg->length); | 460 | any2scsi(cptr[i].datalen, sg->length); |
676 | }; | 461 | }; |
677 | any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain)); | 462 | any2scsi(ccb[mbo].datalen, sg_count * sizeof(struct chain)); |
678 | any2scsi(ccb[mbo].dataptr, SCSI_BUF_PA(cptr)); | 463 | any2scsi(ccb[mbo].dataptr, isa_virt_to_bus(cptr)); |
679 | #ifdef DEBUG | 464 | #ifdef DEBUG |
680 | printk("cptr %x: ", cptr); | 465 | shost_printk(KERN_DEBUG, sh, "cptr %p: ", cptr); |
681 | ptr = (unsigned char *) cptr; | 466 | print_hex_dump_bytes("cptr: ", DUMP_PREFIX_NONE, cptr, 18); |
682 | for (i = 0; i < 18; i++) | ||
683 | printk("%02x ", ptr[i]); | ||
684 | #endif | 467 | #endif |
685 | } else { | 468 | } else { |
686 | ccb[mbo].op = 0; /* SCSI Initiator Command */ | 469 | ccb[mbo].op = 0; /* SCSI Initiator Command */ |
687 | SCpnt->host_scribble = NULL; | 470 | cmd->host_scribble = NULL; |
688 | any2scsi(ccb[mbo].datalen, 0); | 471 | any2scsi(ccb[mbo].datalen, 0); |
689 | any2scsi(ccb[mbo].dataptr, 0); | 472 | any2scsi(ccb[mbo].dataptr, 0); |
690 | }; | 473 | }; |
@@ -694,139 +477,116 @@ static int aha1542_queuecommand_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd * | |||
694 | ccb[mbo].commlinkid = 0; | 477 | ccb[mbo].commlinkid = 0; |
695 | 478 | ||
696 | #ifdef DEBUG | 479 | #ifdef DEBUG |
697 | { | 480 | print_hex_dump_bytes("sending: ", DUMP_PREFIX_NONE, &ccb[mbo], sizeof(ccb[mbo]) - 10); |
698 | int i; | 481 | printk("aha1542_queuecommand: now waiting for interrupt "); |
699 | printk(KERN_DEBUG "aha1542_command: sending.. "); | ||
700 | for (i = 0; i < sizeof(ccb[mbo]) - 10; i++) | ||
701 | printk("%02x ", ((unchar *) & ccb[mbo])[i]); | ||
702 | }; | ||
703 | #endif | 482 | #endif |
704 | 483 | mb[mbo].status = 1; | |
705 | if (done) { | 484 | aha1542_outb(cmd->device->host->io_port, CMD_START_SCSI); |
706 | DEB(printk("aha1542_queuecommand: now waiting for interrupt "); | 485 | spin_unlock_irqrestore(sh->host_lock, flags); |
707 | aha1542_stat()); | ||
708 | SCpnt->scsi_done = done; | ||
709 | mb[mbo].status = 1; | ||
710 | aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1); /* start scsi command */ | ||
711 | DEB(aha1542_stat()); | ||
712 | } else | ||
713 | printk("aha1542_queuecommand: done can't be NULL\n"); | ||
714 | 486 | ||
715 | return 0; | 487 | return 0; |
716 | } | 488 | } |
717 | 489 | ||
718 | static DEF_SCSI_QCMD(aha1542_queuecommand) | ||
719 | |||
720 | /* Initialize mailboxes */ | 490 | /* Initialize mailboxes */ |
721 | static void setup_mailboxes(int bse, struct Scsi_Host *shpnt) | 491 | static void setup_mailboxes(struct Scsi_Host *sh) |
722 | { | 492 | { |
493 | struct aha1542_hostdata *aha1542 = shost_priv(sh); | ||
723 | int i; | 494 | int i; |
724 | struct mailbox *mb; | 495 | struct mailbox *mb = aha1542->mb; |
725 | struct ccb *ccb; | 496 | struct ccb *ccb = aha1542->ccb; |
726 | |||
727 | unchar cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0}; | ||
728 | 497 | ||
729 | mb = HOSTDATA(shpnt)->mb; | 498 | u8 mb_cmd[5] = { CMD_MBINIT, AHA1542_MAILBOXES, 0, 0, 0}; |
730 | ccb = HOSTDATA(shpnt)->ccb; | ||
731 | 499 | ||
732 | for (i = 0; i < AHA1542_MAILBOXES; i++) { | 500 | for (i = 0; i < AHA1542_MAILBOXES; i++) { |
733 | mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0; | 501 | mb[i].status = mb[AHA1542_MAILBOXES + i].status = 0; |
734 | any2scsi(mb[i].ccbptr, SCSI_BUF_PA(&ccb[i])); | 502 | any2scsi(mb[i].ccbptr, isa_virt_to_bus(&ccb[i])); |
735 | }; | 503 | }; |
736 | aha1542_intr_reset(bse); /* reset interrupts, so they don't block */ | 504 | aha1542_intr_reset(sh->io_port); /* reset interrupts, so they don't block */ |
737 | any2scsi((cmd + 2), SCSI_BUF_PA(mb)); | 505 | any2scsi((mb_cmd + 2), isa_virt_to_bus(mb)); |
738 | aha1542_out(bse, cmd, 5); | 506 | if (aha1542_out(sh->io_port, mb_cmd, 5)) |
739 | WAIT(INTRFLAGS(bse), INTRMASK, HACC, 0); | 507 | shost_printk(KERN_ERR, sh, "failed setting up mailboxes\n"); |
740 | while (0) { | 508 | aha1542_intr_reset(sh->io_port); |
741 | fail: | ||
742 | printk(KERN_ERR "aha1542_detect: failed setting up mailboxes\n"); | ||
743 | } | ||
744 | aha1542_intr_reset(bse); | ||
745 | } | 509 | } |
746 | 510 | ||
747 | static int __init aha1542_getconfig(int base_io, unsigned char *irq_level, unsigned char *dma_chan, unsigned char *scsi_id) | 511 | static int aha1542_getconfig(struct Scsi_Host *sh) |
748 | { | 512 | { |
749 | unchar inquiry_cmd[] = {CMD_RETCONF}; | 513 | u8 inquiry_result[3]; |
750 | unchar inquiry_result[3]; | ||
751 | int i; | 514 | int i; |
752 | i = inb(STATUS(base_io)); | 515 | i = inb(STATUS(sh->io_port)); |
753 | if (i & DF) { | 516 | if (i & DF) { |
754 | i = inb(DATA(base_io)); | 517 | i = inb(DATA(sh->io_port)); |
755 | }; | 518 | }; |
756 | aha1542_out(base_io, inquiry_cmd, 1); | 519 | aha1542_outb(sh->io_port, CMD_RETCONF); |
757 | aha1542_in(base_io, inquiry_result, 3); | 520 | aha1542_in(sh->io_port, inquiry_result, 3, 0); |
758 | WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); | 521 | if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0)) |
759 | while (0) { | 522 | shost_printk(KERN_ERR, sh, "error querying board settings\n"); |
760 | fail: | 523 | aha1542_intr_reset(sh->io_port); |
761 | printk(KERN_ERR "aha1542_detect: query board settings\n"); | ||
762 | } | ||
763 | aha1542_intr_reset(base_io); | ||
764 | switch (inquiry_result[0]) { | 524 | switch (inquiry_result[0]) { |
765 | case 0x80: | 525 | case 0x80: |
766 | *dma_chan = 7; | 526 | sh->dma_channel = 7; |
767 | break; | 527 | break; |
768 | case 0x40: | 528 | case 0x40: |
769 | *dma_chan = 6; | 529 | sh->dma_channel = 6; |
770 | break; | 530 | break; |
771 | case 0x20: | 531 | case 0x20: |
772 | *dma_chan = 5; | 532 | sh->dma_channel = 5; |
773 | break; | 533 | break; |
774 | case 0x01: | 534 | case 0x01: |
775 | *dma_chan = 0; | 535 | sh->dma_channel = 0; |
776 | break; | 536 | break; |
777 | case 0: | 537 | case 0: |
778 | /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel. | 538 | /* This means that the adapter, although Adaptec 1542 compatible, doesn't use a DMA channel. |
779 | Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */ | 539 | Currently only aware of the BusLogic BT-445S VL-Bus adapter which needs this. */ |
780 | *dma_chan = 0xFF; | 540 | sh->dma_channel = 0xFF; |
781 | break; | 541 | break; |
782 | default: | 542 | default: |
783 | printk(KERN_ERR "Unable to determine Adaptec DMA priority. Disabling board\n"); | 543 | shost_printk(KERN_ERR, sh, "Unable to determine DMA channel.\n"); |
784 | return -1; | 544 | return -1; |
785 | }; | 545 | }; |
786 | switch (inquiry_result[1]) { | 546 | switch (inquiry_result[1]) { |
787 | case 0x40: | 547 | case 0x40: |
788 | *irq_level = 15; | 548 | sh->irq = 15; |
789 | break; | 549 | break; |
790 | case 0x20: | 550 | case 0x20: |
791 | *irq_level = 14; | 551 | sh->irq = 14; |
792 | break; | 552 | break; |
793 | case 0x8: | 553 | case 0x8: |
794 | *irq_level = 12; | 554 | sh->irq = 12; |
795 | break; | 555 | break; |
796 | case 0x4: | 556 | case 0x4: |
797 | *irq_level = 11; | 557 | sh->irq = 11; |
798 | break; | 558 | break; |
799 | case 0x2: | 559 | case 0x2: |
800 | *irq_level = 10; | 560 | sh->irq = 10; |
801 | break; | 561 | break; |
802 | case 0x1: | 562 | case 0x1: |
803 | *irq_level = 9; | 563 | sh->irq = 9; |
804 | break; | 564 | break; |
805 | default: | 565 | default: |
806 | printk(KERN_ERR "Unable to determine Adaptec IRQ level. Disabling board\n"); | 566 | shost_printk(KERN_ERR, sh, "Unable to determine IRQ level.\n"); |
807 | return -1; | 567 | return -1; |
808 | }; | 568 | }; |
809 | *scsi_id = inquiry_result[2] & 7; | 569 | sh->this_id = inquiry_result[2] & 7; |
810 | return 0; | 570 | return 0; |
811 | } | 571 | } |
812 | 572 | ||
813 | /* This function should only be called for 1542C boards - we can detect | 573 | /* This function should only be called for 1542C boards - we can detect |
814 | the special firmware settings and unlock the board */ | 574 | the special firmware settings and unlock the board */ |
815 | 575 | ||
816 | static int __init aha1542_mbenable(int base) | 576 | static int aha1542_mbenable(struct Scsi_Host *sh) |
817 | { | 577 | { |
818 | static unchar mbenable_cmd[3]; | 578 | static u8 mbenable_cmd[3]; |
819 | static unchar mbenable_result[2]; | 579 | static u8 mbenable_result[2]; |
820 | int retval; | 580 | int retval; |
821 | 581 | ||
822 | retval = BIOS_TRANSLATION_6432; | 582 | retval = BIOS_TRANSLATION_6432; |
823 | 583 | ||
824 | mbenable_cmd[0] = CMD_EXTBIOS; | 584 | aha1542_outb(sh->io_port, CMD_EXTBIOS); |
825 | aha1542_out(base, mbenable_cmd, 1); | 585 | if (aha1542_in(sh->io_port, mbenable_result, 2, 100)) |
826 | if (aha1542_in1(base, mbenable_result, 2)) | ||
827 | return retval; | 586 | return retval; |
828 | WAITd(INTRFLAGS(base), INTRMASK, HACC, 0, 100); | 587 | if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 100)) |
829 | aha1542_intr_reset(base); | 588 | goto fail; |
589 | aha1542_intr_reset(sh->io_port); | ||
830 | 590 | ||
831 | if ((mbenable_result[0] & 0x08) || mbenable_result[1]) { | 591 | if ((mbenable_result[0] & 0x08) || mbenable_result[1]) { |
832 | mbenable_cmd[0] = CMD_MBENABLE; | 592 | mbenable_cmd[0] = CMD_MBENABLE; |
@@ -836,37 +596,34 @@ static int __init aha1542_mbenable(int base) | |||
836 | if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03)) | 596 | if ((mbenable_result[0] & 0x08) && (mbenable_result[1] & 0x03)) |
837 | retval = BIOS_TRANSLATION_25563; | 597 | retval = BIOS_TRANSLATION_25563; |
838 | 598 | ||
839 | aha1542_out(base, mbenable_cmd, 3); | 599 | if (aha1542_out(sh->io_port, mbenable_cmd, 3)) |
840 | WAIT(INTRFLAGS(base), INTRMASK, HACC, 0); | 600 | goto fail; |
841 | }; | 601 | }; |
842 | while (0) { | 602 | while (0) { |
843 | fail: | 603 | fail: |
844 | printk(KERN_ERR "aha1542_mbenable: Mailbox init failed\n"); | 604 | shost_printk(KERN_ERR, sh, "Mailbox init failed\n"); |
845 | } | 605 | } |
846 | aha1542_intr_reset(base); | 606 | aha1542_intr_reset(sh->io_port); |
847 | return retval; | 607 | return retval; |
848 | } | 608 | } |
849 | 609 | ||
850 | /* Query the board to find out if it is a 1542 or a 1740, or whatever. */ | 610 | /* Query the board to find out if it is a 1542 or a 1740, or whatever. */ |
851 | static int __init aha1542_query(int base_io, int *transl) | 611 | static int aha1542_query(struct Scsi_Host *sh) |
852 | { | 612 | { |
853 | unchar inquiry_cmd[] = {CMD_INQUIRY}; | 613 | struct aha1542_hostdata *aha1542 = shost_priv(sh); |
854 | unchar inquiry_result[4]; | 614 | u8 inquiry_result[4]; |
855 | int i; | 615 | int i; |
856 | i = inb(STATUS(base_io)); | 616 | i = inb(STATUS(sh->io_port)); |
857 | if (i & DF) { | 617 | if (i & DF) { |
858 | i = inb(DATA(base_io)); | 618 | i = inb(DATA(sh->io_port)); |
859 | }; | 619 | }; |
860 | aha1542_out(base_io, inquiry_cmd, 1); | 620 | aha1542_outb(sh->io_port, CMD_INQUIRY); |
861 | aha1542_in(base_io, inquiry_result, 4); | 621 | aha1542_in(sh->io_port, inquiry_result, 4, 0); |
862 | WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); | 622 | if (!wait_mask(INTRFLAGS(sh->io_port), INTRMASK, HACC, 0, 0)) |
863 | while (0) { | 623 | shost_printk(KERN_ERR, sh, "error querying card type\n"); |
864 | fail: | 624 | aha1542_intr_reset(sh->io_port); |
865 | printk(KERN_ERR "aha1542_detect: query card type\n"); | ||
866 | } | ||
867 | aha1542_intr_reset(base_io); | ||
868 | 625 | ||
869 | *transl = BIOS_TRANSLATION_6432; /* Default case */ | 626 | aha1542->bios_translation = BIOS_TRANSLATION_6432; /* Default case */ |
870 | 627 | ||
871 | /* For an AHA1740 series board, we ignore the board since there is a | 628 | /* For an AHA1740 series board, we ignore the board since there is a |
872 | hardware bug which can lead to wrong blocks being returned if the board | 629 | hardware bug which can lead to wrong blocks being returned if the board |
@@ -875,391 +632,198 @@ fail: | |||
875 | */ | 632 | */ |
876 | 633 | ||
877 | if (inquiry_result[0] == 0x43) { | 634 | if (inquiry_result[0] == 0x43) { |
878 | printk(KERN_INFO "aha1542.c: Emulation mode not supported for AHA 174N hardware.\n"); | 635 | shost_printk(KERN_INFO, sh, "Emulation mode not supported for AHA-1740 hardware, use aha1740 driver instead.\n"); |
879 | return 1; | 636 | return 1; |
880 | }; | 637 | }; |
881 | 638 | ||
882 | /* Always call this - boards that do not support extended bios translation | 639 | /* Always call this - boards that do not support extended bios translation |
883 | will ignore the command, and we will set the proper default */ | 640 | will ignore the command, and we will set the proper default */ |
884 | 641 | ||
885 | *transl = aha1542_mbenable(base_io); | 642 | aha1542->bios_translation = aha1542_mbenable(sh); |
886 | 643 | ||
887 | return 0; | 644 | return 0; |
888 | } | 645 | } |
889 | 646 | ||
890 | #ifndef MODULE | 647 | static u8 dma_speed_hw(int dma_speed) |
891 | static char *setup_str[MAXBOARDS] __initdata; | ||
892 | static int setup_idx = 0; | ||
893 | |||
894 | static void __init aha1542_setup(char *str, int *ints) | ||
895 | { | 648 | { |
896 | const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n"; | 649 | switch (dma_speed) { |
897 | int setup_portbase; | 650 | case 5: |
898 | 651 | return 0x00; | |
899 | if (setup_idx >= MAXBOARDS) { | 652 | case 6: |
900 | printk(KERN_ERR "aha1542: aha1542_setup called too many times! Bad LILO params ?\n"); | 653 | return 0x04; |
901 | printk(KERN_ERR " Entryline 1: %s\n", setup_str[0]); | 654 | case 7: |
902 | printk(KERN_ERR " Entryline 2: %s\n", setup_str[1]); | 655 | return 0x01; |
903 | printk(KERN_ERR " This line: %s\n", str); | 656 | case 8: |
904 | return; | 657 | return 0x02; |
905 | } | 658 | case 10: |
906 | if (ints[0] < 1 || ints[0] > 4) { | 659 | return 0x03; |
907 | printk(KERN_ERR "aha1542: %s\n", str); | ||
908 | printk(ahausage); | ||
909 | printk(KERN_ERR "aha1542: Wrong parameters may cause system malfunction.. We try anyway..\n"); | ||
910 | } | ||
911 | setup_called[setup_idx] = ints[0]; | ||
912 | setup_str[setup_idx] = str; | ||
913 | |||
914 | setup_portbase = ints[0] >= 1 ? ints[1] : 0; /* Preserve the default value.. */ | ||
915 | setup_buson[setup_idx] = ints[0] >= 2 ? ints[2] : 7; | ||
916 | setup_busoff[setup_idx] = ints[0] >= 3 ? ints[3] : 5; | ||
917 | if (ints[0] >= 4) | ||
918 | { | ||
919 | int atbt = -1; | ||
920 | switch (ints[4]) { | ||
921 | case 5: | ||
922 | atbt = 0x00; | ||
923 | break; | ||
924 | case 6: | ||
925 | atbt = 0x04; | ||
926 | break; | ||
927 | case 7: | ||
928 | atbt = 0x01; | ||
929 | break; | ||
930 | case 8: | ||
931 | atbt = 0x02; | ||
932 | break; | ||
933 | case 10: | ||
934 | atbt = 0x03; | ||
935 | break; | ||
936 | default: | ||
937 | printk(KERN_ERR "aha1542: %s\n", str); | ||
938 | printk(ahausage); | ||
939 | printk(KERN_ERR "aha1542: Valid values for DMASPEED are 5-8, 10 MB/s. Using jumper defaults.\n"); | ||
940 | break; | ||
941 | } | ||
942 | setup_dmaspeed[setup_idx] = atbt; | ||
943 | } | 660 | } |
944 | if (setup_portbase != 0) | ||
945 | bases[setup_idx] = setup_portbase; | ||
946 | 661 | ||
947 | ++setup_idx; | 662 | return 0xff; /* invalid */ |
948 | } | 663 | } |
949 | 664 | ||
950 | static int __init do_setup(char *str) | 665 | /* Set the Bus on/off-times as not to ruin floppy performance */ |
666 | static void aha1542_set_bus_times(struct Scsi_Host *sh, int bus_on, int bus_off, int dma_speed) | ||
951 | { | 667 | { |
952 | int ints[5]; | 668 | if (bus_on > 0) { |
669 | u8 oncmd[] = { CMD_BUSON_TIME, clamp(bus_on, 2, 15) }; | ||
953 | 670 | ||
954 | int count=setup_idx; | 671 | aha1542_intr_reset(sh->io_port); |
672 | if (aha1542_out(sh->io_port, oncmd, 2)) | ||
673 | goto fail; | ||
674 | } | ||
955 | 675 | ||
956 | get_options(str, ARRAY_SIZE(ints), ints); | 676 | if (bus_off > 0) { |
957 | aha1542_setup(str,ints); | 677 | u8 offcmd[] = { CMD_BUSOFF_TIME, clamp(bus_off, 1, 64) }; |
958 | 678 | ||
959 | return count<setup_idx; | 679 | aha1542_intr_reset(sh->io_port); |
960 | } | 680 | if (aha1542_out(sh->io_port, offcmd, 2)) |
681 | goto fail; | ||
682 | } | ||
961 | 683 | ||
962 | __setup("aha1542=",do_setup); | 684 | if (dma_speed_hw(dma_speed) != 0xff) { |
963 | #endif | 685 | u8 dmacmd[] = { CMD_DMASPEED, dma_speed_hw(dma_speed) }; |
686 | |||
687 | aha1542_intr_reset(sh->io_port); | ||
688 | if (aha1542_out(sh->io_port, dmacmd, 2)) | ||
689 | goto fail; | ||
690 | } | ||
691 | aha1542_intr_reset(sh->io_port); | ||
692 | return; | ||
693 | fail: | ||
694 | shost_printk(KERN_ERR, sh, "setting bus on/off-time failed\n"); | ||
695 | aha1542_intr_reset(sh->io_port); | ||
696 | } | ||
964 | 697 | ||
965 | /* return non-zero on detection */ | 698 | /* return non-zero on detection */ |
966 | static int __init aha1542_detect(struct scsi_host_template * tpnt) | 699 | static struct Scsi_Host *aha1542_hw_init(struct scsi_host_template *tpnt, struct device *pdev, int indx) |
967 | { | 700 | { |
968 | unsigned char dma_chan; | 701 | unsigned int base_io = io[indx]; |
969 | unsigned char irq_level; | 702 | struct Scsi_Host *sh; |
970 | unsigned char scsi_id; | 703 | struct aha1542_hostdata *aha1542; |
971 | unsigned long flags; | 704 | char dma_info[] = "no DMA"; |
972 | unsigned int base_io; | 705 | |
973 | int trans; | 706 | if (base_io == 0) |
974 | struct Scsi_Host *shpnt = NULL; | 707 | return NULL; |
975 | int count = 0; | 708 | |
976 | int indx; | 709 | if (!request_region(base_io, AHA1542_REGION_SIZE, "aha1542")) |
977 | 710 | return NULL; | |
978 | DEB(printk("aha1542_detect: \n")); | 711 | |
979 | 712 | sh = scsi_host_alloc(tpnt, sizeof(struct aha1542_hostdata)); | |
980 | tpnt->proc_name = "aha1542"; | 713 | if (!sh) |
981 | 714 | goto release; | |
982 | #ifdef MODULE | 715 | aha1542 = shost_priv(sh); |
983 | bases[0] = aha1542[0]; | 716 | |
984 | setup_buson[0] = aha1542[1]; | 717 | sh->unique_id = base_io; |
985 | setup_busoff[0] = aha1542[2]; | 718 | sh->io_port = base_io; |
986 | { | 719 | sh->n_io_port = AHA1542_REGION_SIZE; |
987 | int atbt = -1; | 720 | aha1542->aha1542_last_mbi_used = 2 * AHA1542_MAILBOXES - 1; |
988 | switch (aha1542[3]) { | 721 | aha1542->aha1542_last_mbo_used = AHA1542_MAILBOXES - 1; |
989 | case 5: | 722 | |
990 | atbt = 0x00; | 723 | if (!aha1542_test_port(sh)) |
991 | break; | 724 | goto unregister; |
992 | case 6: | 725 | |
993 | atbt = 0x04; | 726 | aha1542_set_bus_times(sh, bus_on[indx], bus_off[indx], dma_speed[indx]); |
994 | break; | 727 | if (aha1542_query(sh)) |
995 | case 7: | 728 | goto unregister; |
996 | atbt = 0x01; | 729 | if (aha1542_getconfig(sh) == -1) |
997 | break; | 730 | goto unregister; |
998 | case 8: | 731 | |
999 | atbt = 0x02; | 732 | if (sh->dma_channel != 0xFF) |
1000 | break; | 733 | snprintf(dma_info, sizeof(dma_info), "DMA %d", sh->dma_channel); |
1001 | case 10: | 734 | shost_printk(KERN_INFO, sh, "Adaptec AHA-1542 (SCSI-ID %d) at IO 0x%x, IRQ %d, %s\n", |
1002 | atbt = 0x03; | 735 | sh->this_id, base_io, sh->irq, dma_info); |
1003 | break; | 736 | if (aha1542->bios_translation == BIOS_TRANSLATION_25563) |
1004 | }; | 737 | shost_printk(KERN_INFO, sh, "Using extended bios translation\n"); |
1005 | setup_dmaspeed[0] = atbt; | 738 | |
739 | setup_mailboxes(sh); | ||
740 | |||
741 | if (request_irq(sh->irq, aha1542_interrupt, 0, "aha1542", sh)) { | ||
742 | shost_printk(KERN_ERR, sh, "Unable to allocate IRQ.\n"); | ||
743 | goto unregister; | ||
1006 | } | 744 | } |
1007 | #endif | 745 | if (sh->dma_channel != 0xFF) { |
1008 | 746 | if (request_dma(sh->dma_channel, "aha1542")) { | |
1009 | /* | 747 | shost_printk(KERN_ERR, sh, "Unable to allocate DMA channel.\n"); |
1010 | * Hunt for ISA Plug'n'Pray Adaptecs (AHA1535) | 748 | goto free_irq; |
1011 | */ | 749 | } |
1012 | 750 | if (sh->dma_channel == 0 || sh->dma_channel >= 5) { | |
1013 | if(isapnp) | 751 | set_dma_mode(sh->dma_channel, DMA_MODE_CASCADE); |
1014 | { | 752 | enable_dma(sh->dma_channel); |
1015 | struct pnp_dev *pdev = NULL; | ||
1016 | for(indx = 0; indx < ARRAY_SIZE(bases); indx++) { | ||
1017 | if(bases[indx]) | ||
1018 | continue; | ||
1019 | pdev = pnp_find_dev(NULL, ISAPNP_VENDOR('A', 'D', 'P'), | ||
1020 | ISAPNP_FUNCTION(0x1542), pdev); | ||
1021 | if(pdev==NULL) | ||
1022 | break; | ||
1023 | /* | ||
1024 | * Activate the PnP card | ||
1025 | */ | ||
1026 | |||
1027 | if(pnp_device_attach(pdev)<0) | ||
1028 | continue; | ||
1029 | |||
1030 | if(pnp_activate_dev(pdev)<0) { | ||
1031 | pnp_device_detach(pdev); | ||
1032 | continue; | ||
1033 | } | ||
1034 | |||
1035 | if(!pnp_port_valid(pdev, 0)) { | ||
1036 | pnp_device_detach(pdev); | ||
1037 | continue; | ||
1038 | } | ||
1039 | |||
1040 | bases[indx] = pnp_port_start(pdev, 0); | ||
1041 | |||
1042 | /* The card can be queried for its DMA, we have | ||
1043 | the DMA set up that is enough */ | ||
1044 | |||
1045 | printk(KERN_INFO "ISAPnP found an AHA1535 at I/O 0x%03X\n", bases[indx]); | ||
1046 | } | 753 | } |
1047 | } | 754 | } |
1048 | for (indx = 0; indx < ARRAY_SIZE(bases); indx++) | ||
1049 | if (bases[indx] != 0 && request_region(bases[indx], 4, "aha1542")) { | ||
1050 | shpnt = scsi_register(tpnt, | ||
1051 | sizeof(struct aha1542_hostdata)); | ||
1052 | |||
1053 | if(shpnt==NULL) { | ||
1054 | release_region(bases[indx], 4); | ||
1055 | continue; | ||
1056 | } | ||
1057 | if (!aha1542_test_port(bases[indx], shpnt)) | ||
1058 | goto unregister; | ||
1059 | |||
1060 | base_io = bases[indx]; | ||
1061 | |||
1062 | /* Set the Bus on/off-times as not to ruin floppy performance */ | ||
1063 | { | ||
1064 | unchar oncmd[] = {CMD_BUSON_TIME, 7}; | ||
1065 | unchar offcmd[] = {CMD_BUSOFF_TIME, 5}; | ||
1066 | |||
1067 | if (setup_called[indx]) { | ||
1068 | oncmd[1] = setup_buson[indx]; | ||
1069 | offcmd[1] = setup_busoff[indx]; | ||
1070 | } | ||
1071 | aha1542_intr_reset(base_io); | ||
1072 | aha1542_out(base_io, oncmd, 2); | ||
1073 | WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); | ||
1074 | aha1542_intr_reset(base_io); | ||
1075 | aha1542_out(base_io, offcmd, 2); | ||
1076 | WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); | ||
1077 | if (setup_dmaspeed[indx] >= 0) { | ||
1078 | unchar dmacmd[] = {CMD_DMASPEED, 0}; | ||
1079 | dmacmd[1] = setup_dmaspeed[indx]; | ||
1080 | aha1542_intr_reset(base_io); | ||
1081 | aha1542_out(base_io, dmacmd, 2); | ||
1082 | WAIT(INTRFLAGS(base_io), INTRMASK, HACC, 0); | ||
1083 | } | ||
1084 | while (0) { | ||
1085 | fail: | ||
1086 | printk(KERN_ERR "aha1542_detect: setting bus on/off-time failed\n"); | ||
1087 | } | ||
1088 | aha1542_intr_reset(base_io); | ||
1089 | } | ||
1090 | if (aha1542_query(base_io, &trans)) | ||
1091 | goto unregister; | ||
1092 | |||
1093 | if (aha1542_getconfig(base_io, &irq_level, &dma_chan, &scsi_id) == -1) | ||
1094 | goto unregister; | ||
1095 | |||
1096 | printk(KERN_INFO "Configuring Adaptec (SCSI-ID %d) at IO:%x, IRQ %d", scsi_id, base_io, irq_level); | ||
1097 | if (dma_chan != 0xFF) | ||
1098 | printk(", DMA priority %d", dma_chan); | ||
1099 | printk("\n"); | ||
1100 | |||
1101 | DEB(aha1542_stat()); | ||
1102 | setup_mailboxes(base_io, shpnt); | ||
1103 | |||
1104 | DEB(aha1542_stat()); | ||
1105 | |||
1106 | DEB(printk("aha1542_detect: enable interrupt channel %d\n", irq_level)); | ||
1107 | spin_lock_irqsave(&aha1542_lock, flags); | ||
1108 | if (request_irq(irq_level, do_aha1542_intr_handle, 0, | ||
1109 | "aha1542", shpnt)) { | ||
1110 | printk(KERN_ERR "Unable to allocate IRQ for adaptec controller.\n"); | ||
1111 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1112 | goto unregister; | ||
1113 | } | ||
1114 | if (dma_chan != 0xFF) { | ||
1115 | if (request_dma(dma_chan, "aha1542")) { | ||
1116 | printk(KERN_ERR "Unable to allocate DMA channel for Adaptec.\n"); | ||
1117 | free_irq(irq_level, shpnt); | ||
1118 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1119 | goto unregister; | ||
1120 | } | ||
1121 | if (dma_chan == 0 || dma_chan >= 5) { | ||
1122 | set_dma_mode(dma_chan, DMA_MODE_CASCADE); | ||
1123 | enable_dma(dma_chan); | ||
1124 | } | ||
1125 | } | ||
1126 | |||
1127 | shpnt->this_id = scsi_id; | ||
1128 | shpnt->unique_id = base_io; | ||
1129 | shpnt->io_port = base_io; | ||
1130 | shpnt->n_io_port = 4; /* Number of bytes of I/O space used */ | ||
1131 | shpnt->dma_channel = dma_chan; | ||
1132 | shpnt->irq = irq_level; | ||
1133 | HOSTDATA(shpnt)->bios_translation = trans; | ||
1134 | if (trans == BIOS_TRANSLATION_25563) | ||
1135 | printk(KERN_INFO "aha1542.c: Using extended bios translation\n"); | ||
1136 | HOSTDATA(shpnt)->aha1542_last_mbi_used = (2 * AHA1542_MAILBOXES - 1); | ||
1137 | HOSTDATA(shpnt)->aha1542_last_mbo_used = (AHA1542_MAILBOXES - 1); | ||
1138 | memset(HOSTDATA(shpnt)->SCint, 0, sizeof(HOSTDATA(shpnt)->SCint)); | ||
1139 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1140 | #if 0 | ||
1141 | DEB(printk(" *** READ CAPACITY ***\n")); | ||
1142 | |||
1143 | { | ||
1144 | unchar buf[8]; | ||
1145 | static unchar cmd[] = { READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; | ||
1146 | int i; | ||
1147 | |||
1148 | for (i = 0; i < sizeof(buf); ++i) | ||
1149 | buf[i] = 0x87; | ||
1150 | for (i = 0; i < 2; ++i) | ||
1151 | if (!aha1542_command(i, cmd, buf, sizeof(buf))) { | ||
1152 | printk(KERN_DEBUG "aha_detect: LU %d sector_size %d device_size %d\n", | ||
1153 | i, xscsi2int(buf + 4), xscsi2int(buf)); | ||
1154 | } | ||
1155 | } | ||
1156 | 755 | ||
1157 | DEB(printk(" *** NOW RUNNING MY OWN TEST *** \n")); | 756 | if (scsi_add_host(sh, pdev)) |
757 | goto free_dma; | ||
1158 | 758 | ||
1159 | for (i = 0; i < 4; ++i) { | 759 | scsi_scan_host(sh); |
1160 | unsigned char cmd[10]; | ||
1161 | static buffer[512]; | ||
1162 | 760 | ||
1163 | cmd[0] = READ_10; | 761 | return sh; |
1164 | cmd[1] = 0; | 762 | free_dma: |
1165 | xany2scsi(cmd + 2, i); | 763 | if (sh->dma_channel != 0xff) |
1166 | cmd[6] = 0; | 764 | free_dma(sh->dma_channel); |
1167 | cmd[7] = 0; | 765 | free_irq: |
1168 | cmd[8] = 1; | 766 | free_irq(sh->irq, sh); |
1169 | cmd[9] = 0; | ||
1170 | aha1542_command(0, cmd, buffer, 512); | ||
1171 | } | ||
1172 | #endif | ||
1173 | count++; | ||
1174 | continue; | ||
1175 | unregister: | 767 | unregister: |
1176 | release_region(bases[indx], 4); | 768 | scsi_host_put(sh); |
1177 | scsi_unregister(shpnt); | 769 | release: |
1178 | continue; | 770 | release_region(base_io, AHA1542_REGION_SIZE); |
1179 | 771 | ||
1180 | }; | 772 | return NULL; |
1181 | |||
1182 | return count; | ||
1183 | } | 773 | } |
1184 | 774 | ||
1185 | static int aha1542_release(struct Scsi_Host *shost) | 775 | static int aha1542_release(struct Scsi_Host *sh) |
1186 | { | 776 | { |
1187 | if (shost->irq) | 777 | scsi_remove_host(sh); |
1188 | free_irq(shost->irq, shost); | 778 | if (sh->dma_channel != 0xff) |
1189 | if (shost->dma_channel != 0xff) | 779 | free_dma(sh->dma_channel); |
1190 | free_dma(shost->dma_channel); | 780 | if (sh->irq) |
1191 | if (shost->io_port && shost->n_io_port) | 781 | free_irq(sh->irq, sh); |
1192 | release_region(shost->io_port, shost->n_io_port); | 782 | if (sh->io_port && sh->n_io_port) |
1193 | scsi_unregister(shost); | 783 | release_region(sh->io_port, sh->n_io_port); |
784 | scsi_host_put(sh); | ||
1194 | return 0; | 785 | return 0; |
1195 | } | 786 | } |
1196 | 787 | ||
1197 | static int aha1542_restart(struct Scsi_Host *shost) | ||
1198 | { | ||
1199 | int i; | ||
1200 | int count = 0; | ||
1201 | #if 0 | ||
1202 | unchar ahacmd = CMD_START_SCSI; | ||
1203 | #endif | ||
1204 | |||
1205 | for (i = 0; i < AHA1542_MAILBOXES; i++) | ||
1206 | if (HOSTDATA(shost)->SCint[i] && | ||
1207 | !(HOSTDATA(shost)->SCint[i]->device->soft_reset)) { | ||
1208 | #if 0 | ||
1209 | HOSTDATA(shost)->mb[i].status = 1; /* Indicate ready to restart... */ | ||
1210 | #endif | ||
1211 | count++; | ||
1212 | } | ||
1213 | printk(KERN_DEBUG "Potential to restart %d stalled commands...\n", count); | ||
1214 | #if 0 | ||
1215 | /* start scsi command */ | ||
1216 | if (count) | ||
1217 | aha1542_out(shost->io_port, &ahacmd, 1); | ||
1218 | #endif | ||
1219 | return 0; | ||
1220 | } | ||
1221 | 788 | ||
1222 | /* | 789 | /* |
1223 | * This is a device reset. This is handled by sending a special command | 790 | * This is a device reset. This is handled by sending a special command |
1224 | * to the device. | 791 | * to the device. |
1225 | */ | 792 | */ |
1226 | static int aha1542_dev_reset(Scsi_Cmnd * SCpnt) | 793 | static int aha1542_dev_reset(struct scsi_cmnd *cmd) |
1227 | { | 794 | { |
795 | struct Scsi_Host *sh = cmd->device->host; | ||
796 | struct aha1542_hostdata *aha1542 = shost_priv(sh); | ||
1228 | unsigned long flags; | 797 | unsigned long flags; |
1229 | struct mailbox *mb; | 798 | struct mailbox *mb = aha1542->mb; |
1230 | unchar target = SCpnt->device->id; | 799 | u8 target = cmd->device->id; |
1231 | unchar lun = SCpnt->device->lun; | 800 | u8 lun = cmd->device->lun; |
1232 | int mbo; | 801 | int mbo; |
1233 | struct ccb *ccb; | 802 | struct ccb *ccb = aha1542->ccb; |
1234 | unchar ahacmd = CMD_START_SCSI; | ||
1235 | |||
1236 | ccb = HOSTDATA(SCpnt->device->host)->ccb; | ||
1237 | mb = HOSTDATA(SCpnt->device->host)->mb; | ||
1238 | 803 | ||
1239 | spin_lock_irqsave(&aha1542_lock, flags); | 804 | spin_lock_irqsave(sh->host_lock, flags); |
1240 | mbo = HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used + 1; | 805 | mbo = aha1542->aha1542_last_mbo_used + 1; |
1241 | if (mbo >= AHA1542_MAILBOXES) | 806 | if (mbo >= AHA1542_MAILBOXES) |
1242 | mbo = 0; | 807 | mbo = 0; |
1243 | 808 | ||
1244 | do { | 809 | do { |
1245 | if (mb[mbo].status == 0 && HOSTDATA(SCpnt->device->host)->SCint[mbo] == NULL) | 810 | if (mb[mbo].status == 0 && aha1542->int_cmds[mbo] == NULL) |
1246 | break; | 811 | break; |
1247 | mbo++; | 812 | mbo++; |
1248 | if (mbo >= AHA1542_MAILBOXES) | 813 | if (mbo >= AHA1542_MAILBOXES) |
1249 | mbo = 0; | 814 | mbo = 0; |
1250 | } while (mbo != HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used); | 815 | } while (mbo != aha1542->aha1542_last_mbo_used); |
1251 | 816 | ||
1252 | if (mb[mbo].status || HOSTDATA(SCpnt->device->host)->SCint[mbo]) | 817 | if (mb[mbo].status || aha1542->int_cmds[mbo]) |
1253 | panic("Unable to find empty mailbox for aha1542.\n"); | 818 | panic("Unable to find empty mailbox for aha1542.\n"); |
1254 | 819 | ||
1255 | HOSTDATA(SCpnt->device->host)->SCint[mbo] = SCpnt; /* This will effectively | 820 | aha1542->int_cmds[mbo] = cmd; /* This will effectively |
1256 | prevent someone else from | 821 | prevent someone else from |
1257 | screwing with this cdb. */ | 822 | screwing with this cdb. */ |
1258 | 823 | ||
1259 | HOSTDATA(SCpnt->device->host)->aha1542_last_mbo_used = mbo; | 824 | aha1542->aha1542_last_mbo_used = mbo; |
1260 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1261 | 825 | ||
1262 | any2scsi(mb[mbo].ccbptr, SCSI_BUF_PA(&ccb[mbo])); /* This gets trashed for some reason */ | 826 | any2scsi(mb[mbo].ccbptr, isa_virt_to_bus(&ccb[mbo])); /* This gets trashed for some reason */ |
1263 | 827 | ||
1264 | memset(&ccb[mbo], 0, sizeof(struct ccb)); | 828 | memset(&ccb[mbo], 0, sizeof(struct ccb)); |
1265 | 829 | ||
@@ -1274,141 +838,43 @@ static int aha1542_dev_reset(Scsi_Cmnd * SCpnt) | |||
1274 | * Now tell the 1542 to flush all pending commands for this | 838 | * Now tell the 1542 to flush all pending commands for this |
1275 | * target | 839 | * target |
1276 | */ | 840 | */ |
1277 | aha1542_out(SCpnt->device->host->io_port, &ahacmd, 1); | 841 | aha1542_outb(sh->io_port, CMD_START_SCSI); |
842 | spin_unlock_irqrestore(sh->host_lock, flags); | ||
1278 | 843 | ||
1279 | scmd_printk(KERN_WARNING, SCpnt, | 844 | scmd_printk(KERN_WARNING, cmd, |
1280 | "Trying device reset for target\n"); | 845 | "Trying device reset for target\n"); |
1281 | 846 | ||
1282 | return SUCCESS; | 847 | return SUCCESS; |
1283 | |||
1284 | |||
1285 | #ifdef ERIC_neverdef | ||
1286 | /* | ||
1287 | * With the 1542 we apparently never get an interrupt to | ||
1288 | * acknowledge a device reset being sent. Then again, Leonard | ||
1289 | * says we are doing this wrong in the first place... | ||
1290 | * | ||
1291 | * Take a wait and see attitude. If we get spurious interrupts, | ||
1292 | * then the device reset is doing something sane and useful, and | ||
1293 | * we will wait for the interrupt to post completion. | ||
1294 | */ | ||
1295 | printk(KERN_WARNING "Sent BUS DEVICE RESET to target %d\n", SCpnt->target); | ||
1296 | |||
1297 | /* | ||
1298 | * Free the command block for all commands running on this | ||
1299 | * target... | ||
1300 | */ | ||
1301 | for (i = 0; i < AHA1542_MAILBOXES; i++) { | ||
1302 | if (HOSTDATA(SCpnt->host)->SCint[i] && | ||
1303 | HOSTDATA(SCpnt->host)->SCint[i]->target == SCpnt->target) { | ||
1304 | Scsi_Cmnd *SCtmp; | ||
1305 | SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; | ||
1306 | kfree(SCtmp->host_scribble); | ||
1307 | SCtmp->host_scribble = NULL; | ||
1308 | HOSTDATA(SCpnt->host)->SCint[i] = NULL; | ||
1309 | HOSTDATA(SCpnt->host)->mb[i].status = 0; | ||
1310 | } | ||
1311 | } | ||
1312 | return SUCCESS; | ||
1313 | |||
1314 | return FAILED; | ||
1315 | #endif /* ERIC_neverdef */ | ||
1316 | } | 848 | } |
1317 | 849 | ||
1318 | static int aha1542_bus_reset(Scsi_Cmnd * SCpnt) | 850 | static int aha1542_reset(struct scsi_cmnd *cmd, u8 reset_cmd) |
1319 | { | 851 | { |
852 | struct Scsi_Host *sh = cmd->device->host; | ||
853 | struct aha1542_hostdata *aha1542 = shost_priv(sh); | ||
854 | unsigned long flags; | ||
1320 | int i; | 855 | int i; |
1321 | 856 | ||
857 | spin_lock_irqsave(sh->host_lock, flags); | ||
1322 | /* | 858 | /* |
1323 | * This does a scsi reset for all devices on the bus. | 859 | * This does a scsi reset for all devices on the bus. |
1324 | * In principle, we could also reset the 1542 - should | 860 | * In principle, we could also reset the 1542 - should |
1325 | * we do this? Try this first, and we can add that later | 861 | * we do this? Try this first, and we can add that later |
1326 | * if it turns out to be useful. | 862 | * if it turns out to be useful. |
1327 | */ | 863 | */ |
1328 | outb(SCRST, CONTROL(SCpnt->device->host->io_port)); | 864 | outb(reset_cmd, CONTROL(cmd->device->host->io_port)); |
1329 | 865 | ||
1330 | /* | 866 | if (!wait_mask(STATUS(cmd->device->host->io_port), |
1331 | * Wait for the thing to settle down a bit. Unfortunately | 867 | STATMASK, IDLE, STST | DIAGF | INVDCMD | DF | CDF, 0)) { |
1332 | * this is going to basically lock up the machine while we | 868 | spin_unlock_irqrestore(sh->host_lock, flags); |
1333 | * wait for this to complete. To be 100% correct, we need to | 869 | return FAILED; |
1334 | * check for timeout, and if we are doing something like this | ||
1335 | * we are pretty desperate anyways. | ||
1336 | */ | ||
1337 | ssleep(4); | ||
1338 | |||
1339 | spin_lock_irq(SCpnt->device->host->host_lock); | ||
1340 | |||
1341 | WAIT(STATUS(SCpnt->device->host->io_port), | ||
1342 | STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF); | ||
1343 | |||
1344 | /* | ||
1345 | * Now try to pick up the pieces. For all pending commands, | ||
1346 | * free any internal data structures, and basically clear things | ||
1347 | * out. We do not try and restart any commands or anything - | ||
1348 | * the strategy handler takes care of that crap. | ||
1349 | */ | ||
1350 | printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no); | ||
1351 | |||
1352 | for (i = 0; i < AHA1542_MAILBOXES; i++) { | ||
1353 | if (HOSTDATA(SCpnt->device->host)->SCint[i] != NULL) { | ||
1354 | Scsi_Cmnd *SCtmp; | ||
1355 | SCtmp = HOSTDATA(SCpnt->device->host)->SCint[i]; | ||
1356 | |||
1357 | |||
1358 | if (SCtmp->device->soft_reset) { | ||
1359 | /* | ||
1360 | * If this device implements the soft reset option, | ||
1361 | * then it is still holding onto the command, and | ||
1362 | * may yet complete it. In this case, we don't | ||
1363 | * flush the data. | ||
1364 | */ | ||
1365 | continue; | ||
1366 | } | ||
1367 | kfree(SCtmp->host_scribble); | ||
1368 | SCtmp->host_scribble = NULL; | ||
1369 | HOSTDATA(SCpnt->device->host)->SCint[i] = NULL; | ||
1370 | HOSTDATA(SCpnt->device->host)->mb[i].status = 0; | ||
1371 | } | ||
1372 | } | 870 | } |
1373 | 871 | ||
1374 | spin_unlock_irq(SCpnt->device->host->host_lock); | ||
1375 | return SUCCESS; | ||
1376 | |||
1377 | fail: | ||
1378 | spin_unlock_irq(SCpnt->device->host->host_lock); | ||
1379 | return FAILED; | ||
1380 | } | ||
1381 | |||
1382 | static int aha1542_host_reset(Scsi_Cmnd * SCpnt) | ||
1383 | { | ||
1384 | int i; | ||
1385 | |||
1386 | /* | ||
1387 | * This does a scsi reset for all devices on the bus. | ||
1388 | * In principle, we could also reset the 1542 - should | ||
1389 | * we do this? Try this first, and we can add that later | ||
1390 | * if it turns out to be useful. | ||
1391 | */ | ||
1392 | outb(HRST | SCRST, CONTROL(SCpnt->device->host->io_port)); | ||
1393 | |||
1394 | /* | ||
1395 | * Wait for the thing to settle down a bit. Unfortunately | ||
1396 | * this is going to basically lock up the machine while we | ||
1397 | * wait for this to complete. To be 100% correct, we need to | ||
1398 | * check for timeout, and if we are doing something like this | ||
1399 | * we are pretty desperate anyways. | ||
1400 | */ | ||
1401 | ssleep(4); | ||
1402 | spin_lock_irq(SCpnt->device->host->host_lock); | ||
1403 | |||
1404 | WAIT(STATUS(SCpnt->device->host->io_port), | ||
1405 | STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF); | ||
1406 | |||
1407 | /* | 872 | /* |
1408 | * We need to do this too before the 1542 can interact with | 873 | * We need to do this too before the 1542 can interact with |
1409 | * us again. | 874 | * us again after host reset. |
1410 | */ | 875 | */ |
1411 | setup_mailboxes(SCpnt->device->host->io_port, SCpnt->device->host); | 876 | if (reset_cmd & HRST) |
877 | setup_mailboxes(cmd->device->host); | ||
1412 | 878 | ||
1413 | /* | 879 | /* |
1414 | * Now try to pick up the pieces. For all pending commands, | 880 | * Now try to pick up the pieces. For all pending commands, |
@@ -1416,14 +882,14 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt) | |||
1416 | * out. We do not try and restart any commands or anything - | 882 | * out. We do not try and restart any commands or anything - |
1417 | * the strategy handler takes care of that crap. | 883 | * the strategy handler takes care of that crap. |
1418 | */ | 884 | */ |
1419 | printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->device->host->host_no); | 885 | shost_printk(KERN_WARNING, cmd->device->host, "Sent BUS RESET to scsi host %d\n", cmd->device->host->host_no); |
1420 | 886 | ||
1421 | for (i = 0; i < AHA1542_MAILBOXES; i++) { | 887 | for (i = 0; i < AHA1542_MAILBOXES; i++) { |
1422 | if (HOSTDATA(SCpnt->device->host)->SCint[i] != NULL) { | 888 | if (aha1542->int_cmds[i] != NULL) { |
1423 | Scsi_Cmnd *SCtmp; | 889 | struct scsi_cmnd *tmp_cmd; |
1424 | SCtmp = HOSTDATA(SCpnt->device->host)->SCint[i]; | 890 | tmp_cmd = aha1542->int_cmds[i]; |
1425 | 891 | ||
1426 | if (SCtmp->device->soft_reset) { | 892 | if (tmp_cmd->device->soft_reset) { |
1427 | /* | 893 | /* |
1428 | * If this device implements the soft reset option, | 894 | * If this device implements the soft reset option, |
1429 | * then it is still holding onto the command, and | 895 | * then it is still holding onto the command, and |
@@ -1432,241 +898,51 @@ static int aha1542_host_reset(Scsi_Cmnd * SCpnt) | |||
1432 | */ | 898 | */ |
1433 | continue; | 899 | continue; |
1434 | } | 900 | } |
1435 | kfree(SCtmp->host_scribble); | 901 | kfree(tmp_cmd->host_scribble); |
1436 | SCtmp->host_scribble = NULL; | 902 | tmp_cmd->host_scribble = NULL; |
1437 | HOSTDATA(SCpnt->device->host)->SCint[i] = NULL; | 903 | aha1542->int_cmds[i] = NULL; |
1438 | HOSTDATA(SCpnt->device->host)->mb[i].status = 0; | 904 | aha1542->mb[i].status = 0; |
1439 | } | 905 | } |
1440 | } | 906 | } |
1441 | 907 | ||
1442 | spin_unlock_irq(SCpnt->device->host->host_lock); | 908 | spin_unlock_irqrestore(sh->host_lock, flags); |
1443 | return SUCCESS; | 909 | return SUCCESS; |
1444 | |||
1445 | fail: | ||
1446 | spin_unlock_irq(SCpnt->device->host->host_lock); | ||
1447 | return FAILED; | ||
1448 | } | 910 | } |
1449 | 911 | ||
1450 | #if 0 | 912 | static int aha1542_bus_reset(struct scsi_cmnd *cmd) |
1451 | /* | ||
1452 | * These are the old error handling routines. They are only temporarily | ||
1453 | * here while we play with the new error handling code. | ||
1454 | */ | ||
1455 | static int aha1542_old_abort(Scsi_Cmnd * SCpnt) | ||
1456 | { | 913 | { |
1457 | #if 0 | 914 | return aha1542_reset(cmd, SCRST); |
1458 | unchar ahacmd = CMD_START_SCSI; | ||
1459 | unsigned long flags; | ||
1460 | struct mailbox *mb; | ||
1461 | int mbi, mbo, i; | ||
1462 | |||
1463 | printk(KERN_DEBUG "In aha1542_abort: %x %x\n", | ||
1464 | inb(STATUS(SCpnt->host->io_port)), | ||
1465 | inb(INTRFLAGS(SCpnt->host->io_port))); | ||
1466 | |||
1467 | spin_lock_irqsave(&aha1542_lock, flags); | ||
1468 | mb = HOSTDATA(SCpnt->host)->mb; | ||
1469 | mbi = HOSTDATA(SCpnt->host)->aha1542_last_mbi_used + 1; | ||
1470 | if (mbi >= 2 * AHA1542_MAILBOXES) | ||
1471 | mbi = AHA1542_MAILBOXES; | ||
1472 | |||
1473 | do { | ||
1474 | if (mb[mbi].status != 0) | ||
1475 | break; | ||
1476 | mbi++; | ||
1477 | if (mbi >= 2 * AHA1542_MAILBOXES) | ||
1478 | mbi = AHA1542_MAILBOXES; | ||
1479 | } while (mbi != HOSTDATA(SCpnt->host)->aha1542_last_mbi_used); | ||
1480 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1481 | |||
1482 | if (mb[mbi].status) { | ||
1483 | printk(KERN_ERR "Lost interrupt discovered on irq %d - attempting to recover\n", | ||
1484 | SCpnt->host->irq); | ||
1485 | aha1542_intr_handle(SCpnt->host, NULL); | ||
1486 | return 0; | ||
1487 | } | ||
1488 | /* OK, no lost interrupt. Try looking to see how many pending commands | ||
1489 | we think we have. */ | ||
1490 | |||
1491 | for (i = 0; i < AHA1542_MAILBOXES; i++) | ||
1492 | if (HOSTDATA(SCpnt->host)->SCint[i]) { | ||
1493 | if (HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) { | ||
1494 | printk(KERN_ERR "Timed out command pending for %s\n", | ||
1495 | SCpnt->request->rq_disk ? | ||
1496 | SCpnt->request->rq_disk->disk_name : "?" | ||
1497 | ); | ||
1498 | if (HOSTDATA(SCpnt->host)->mb[i].status) { | ||
1499 | printk(KERN_ERR "OGMB still full - restarting\n"); | ||
1500 | aha1542_out(SCpnt->host->io_port, &ahacmd, 1); | ||
1501 | }; | ||
1502 | } else | ||
1503 | printk(KERN_ERR "Other pending command %s\n", | ||
1504 | SCpnt->request->rq_disk ? | ||
1505 | SCpnt->request->rq_disk->disk_name : "?" | ||
1506 | ); | ||
1507 | } | ||
1508 | #endif | ||
1509 | |||
1510 | DEB(printk("aha1542_abort\n")); | ||
1511 | #if 0 | ||
1512 | spin_lock_irqsave(&aha1542_lock, flags); | ||
1513 | for (mbo = 0; mbo < AHA1542_MAILBOXES; mbo++) { | ||
1514 | if (SCpnt == HOSTDATA(SCpnt->host)->SCint[mbo]) { | ||
1515 | mb[mbo].status = 2; /* Abort command */ | ||
1516 | aha1542_out(SCpnt->host->io_port, &ahacmd, 1); /* start scsi command */ | ||
1517 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1518 | break; | ||
1519 | } | ||
1520 | } | ||
1521 | if (AHA1542_MAILBOXES == mbo) | ||
1522 | spin_unlock_irqrestore(&aha1542_lock, flags); | ||
1523 | #endif | ||
1524 | return SCSI_ABORT_SNOOZE; | ||
1525 | } | 915 | } |
1526 | 916 | ||
1527 | /* We do not implement a reset function here, but the upper level code | 917 | static int aha1542_host_reset(struct scsi_cmnd *cmd) |
1528 | assumes that it will get some kind of response for the command in | ||
1529 | SCpnt. We must oblige, or the command will hang the scsi system. | ||
1530 | For a first go, we assume that the 1542 notifies us with all of the | ||
1531 | pending commands (it does implement soft reset, after all). */ | ||
1532 | |||
1533 | static int aha1542_old_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags) | ||
1534 | { | 918 | { |
1535 | unchar ahacmd = CMD_START_SCSI; | 919 | return aha1542_reset(cmd, HRST | SCRST); |
1536 | int i; | ||
1537 | |||
1538 | /* | ||
1539 | * See if a bus reset was suggested. | ||
1540 | */ | ||
1541 | if (reset_flags & SCSI_RESET_SUGGEST_BUS_RESET) { | ||
1542 | /* | ||
1543 | * This does a scsi reset for all devices on the bus. | ||
1544 | * In principle, we could also reset the 1542 - should | ||
1545 | * we do this? Try this first, and we can add that later | ||
1546 | * if it turns out to be useful. | ||
1547 | */ | ||
1548 | outb(HRST | SCRST, CONTROL(SCpnt->host->io_port)); | ||
1549 | |||
1550 | /* | ||
1551 | * Wait for the thing to settle down a bit. Unfortunately | ||
1552 | * this is going to basically lock up the machine while we | ||
1553 | * wait for this to complete. To be 100% correct, we need to | ||
1554 | * check for timeout, and if we are doing something like this | ||
1555 | * we are pretty desperate anyways. | ||
1556 | */ | ||
1557 | WAIT(STATUS(SCpnt->host->io_port), | ||
1558 | STATMASK, INIT | IDLE, STST | DIAGF | INVDCMD | DF | CDF); | ||
1559 | |||
1560 | /* | ||
1561 | * We need to do this too before the 1542 can interact with | ||
1562 | * us again. | ||
1563 | */ | ||
1564 | setup_mailboxes(SCpnt->host->io_port, SCpnt->host); | ||
1565 | |||
1566 | /* | ||
1567 | * Now try to pick up the pieces. Restart all commands | ||
1568 | * that are currently active on the bus, and reset all of | ||
1569 | * the datastructures. We have some time to kill while | ||
1570 | * things settle down, so print a nice message. | ||
1571 | */ | ||
1572 | printk(KERN_WARNING "Sent BUS RESET to scsi host %d\n", SCpnt->host->host_no); | ||
1573 | |||
1574 | for (i = 0; i < AHA1542_MAILBOXES; i++) | ||
1575 | if (HOSTDATA(SCpnt->host)->SCint[i] != NULL) { | ||
1576 | Scsi_Cmnd *SCtmp; | ||
1577 | SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; | ||
1578 | SCtmp->result = DID_RESET << 16; | ||
1579 | kfree(SCtmp->host_scribble); | ||
1580 | SCtmp->host_scribble = NULL; | ||
1581 | printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target); | ||
1582 | SCtmp->scsi_done(SCpnt); | ||
1583 | |||
1584 | HOSTDATA(SCpnt->host)->SCint[i] = NULL; | ||
1585 | HOSTDATA(SCpnt->host)->mb[i].status = 0; | ||
1586 | } | ||
1587 | /* | ||
1588 | * Now tell the mid-level code what we did here. Since | ||
1589 | * we have restarted all of the outstanding commands, | ||
1590 | * then report SUCCESS. | ||
1591 | */ | ||
1592 | return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET); | ||
1593 | fail: | ||
1594 | printk(KERN_CRIT "aha1542.c: Unable to perform hard reset.\n"); | ||
1595 | printk(KERN_CRIT "Power cycle machine to reset\n"); | ||
1596 | return (SCSI_RESET_ERROR | SCSI_RESET_BUS_RESET); | ||
1597 | |||
1598 | |||
1599 | } else { | ||
1600 | /* This does a selective reset of just the one device */ | ||
1601 | /* First locate the ccb for this command */ | ||
1602 | for (i = 0; i < AHA1542_MAILBOXES; i++) | ||
1603 | if (HOSTDATA(SCpnt->host)->SCint[i] == SCpnt) { | ||
1604 | HOSTDATA(SCpnt->host)->ccb[i].op = 0x81; /* BUS DEVICE RESET */ | ||
1605 | /* Now tell the 1542 to flush all pending commands for this target */ | ||
1606 | aha1542_out(SCpnt->host->io_port, &ahacmd, 1); | ||
1607 | |||
1608 | /* Here is the tricky part. What to do next. Do we get an interrupt | ||
1609 | for the commands that we aborted with the specified target, or | ||
1610 | do we generate this on our own? Try it without first and see | ||
1611 | what happens */ | ||
1612 | printk(KERN_WARNING "Sent BUS DEVICE RESET to target %d\n", SCpnt->target); | ||
1613 | |||
1614 | /* If the first does not work, then try the second. I think the | ||
1615 | first option is more likely to be correct. Free the command | ||
1616 | block for all commands running on this target... */ | ||
1617 | for (i = 0; i < AHA1542_MAILBOXES; i++) | ||
1618 | if (HOSTDATA(SCpnt->host)->SCint[i] && | ||
1619 | HOSTDATA(SCpnt->host)->SCint[i]->target == SCpnt->target) { | ||
1620 | Scsi_Cmnd *SCtmp; | ||
1621 | SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; | ||
1622 | SCtmp->result = DID_RESET << 16; | ||
1623 | kfree(SCtmp->host_scribble); | ||
1624 | SCtmp->host_scribble = NULL; | ||
1625 | printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target); | ||
1626 | SCtmp->scsi_done(SCpnt); | ||
1627 | |||
1628 | HOSTDATA(SCpnt->host)->SCint[i] = NULL; | ||
1629 | HOSTDATA(SCpnt->host)->mb[i].status = 0; | ||
1630 | } | ||
1631 | return SCSI_RESET_SUCCESS; | ||
1632 | } | ||
1633 | } | ||
1634 | /* No active command at this time, so this means that each time we got | ||
1635 | some kind of response the last time through. Tell the mid-level code | ||
1636 | to request sense information in order to decide what to do next. */ | ||
1637 | return SCSI_RESET_PUNT; | ||
1638 | } | 920 | } |
1639 | #endif /* end of big comment block around old_abort + old_reset */ | ||
1640 | 921 | ||
1641 | static int aha1542_biosparam(struct scsi_device *sdev, | 922 | static int aha1542_biosparam(struct scsi_device *sdev, |
1642 | struct block_device *bdev, sector_t capacity, int *ip) | 923 | struct block_device *bdev, sector_t capacity, int geom[]) |
1643 | { | 924 | { |
1644 | int translation_algorithm; | 925 | struct aha1542_hostdata *aha1542 = shost_priv(sdev->host); |
1645 | int size = capacity; | ||
1646 | |||
1647 | translation_algorithm = HOSTDATA(sdev->host)->bios_translation; | ||
1648 | 926 | ||
1649 | if ((size >> 11) > 1024 && translation_algorithm == BIOS_TRANSLATION_25563) { | 927 | if (capacity >= 0x200000 && |
928 | aha1542->bios_translation == BIOS_TRANSLATION_25563) { | ||
1650 | /* Please verify that this is the same as what DOS returns */ | 929 | /* Please verify that this is the same as what DOS returns */ |
1651 | ip[0] = 255; | 930 | geom[0] = 255; /* heads */ |
1652 | ip[1] = 63; | 931 | geom[1] = 63; /* sectors */ |
1653 | ip[2] = size / 255 / 63; | ||
1654 | } else { | 932 | } else { |
1655 | ip[0] = 64; | 933 | geom[0] = 64; /* heads */ |
1656 | ip[1] = 32; | 934 | geom[1] = 32; /* sectors */ |
1657 | ip[2] = size >> 11; | ||
1658 | } | 935 | } |
936 | geom[2] = sector_div(capacity, geom[0] * geom[1]); /* cylinders */ | ||
1659 | 937 | ||
1660 | return 0; | 938 | return 0; |
1661 | } | 939 | } |
1662 | MODULE_LICENSE("GPL"); | 940 | MODULE_LICENSE("GPL"); |
1663 | 941 | ||
1664 | |||
1665 | static struct scsi_host_template driver_template = { | 942 | static struct scsi_host_template driver_template = { |
943 | .module = THIS_MODULE, | ||
1666 | .proc_name = "aha1542", | 944 | .proc_name = "aha1542", |
1667 | .name = "Adaptec 1542", | 945 | .name = "Adaptec 1542", |
1668 | .detect = aha1542_detect, | ||
1669 | .release = aha1542_release, | ||
1670 | .queuecommand = aha1542_queuecommand, | 946 | .queuecommand = aha1542_queuecommand, |
1671 | .eh_device_reset_handler= aha1542_dev_reset, | 947 | .eh_device_reset_handler= aha1542_dev_reset, |
1672 | .eh_bus_reset_handler = aha1542_bus_reset, | 948 | .eh_bus_reset_handler = aha1542_bus_reset, |
@@ -1674,9 +950,124 @@ static struct scsi_host_template driver_template = { | |||
1674 | .bios_param = aha1542_biosparam, | 950 | .bios_param = aha1542_biosparam, |
1675 | .can_queue = AHA1542_MAILBOXES, | 951 | .can_queue = AHA1542_MAILBOXES, |
1676 | .this_id = 7, | 952 | .this_id = 7, |
1677 | .sg_tablesize = AHA1542_SCATTER, | 953 | .sg_tablesize = 16, |
1678 | .cmd_per_lun = AHA1542_CMDLUN, | 954 | .cmd_per_lun = 1, |
1679 | .unchecked_isa_dma = 1, | 955 | .unchecked_isa_dma = 1, |
1680 | .use_clustering = ENABLE_CLUSTERING, | 956 | .use_clustering = ENABLE_CLUSTERING, |
1681 | }; | 957 | }; |
1682 | #include "scsi_module.c" | 958 | |
959 | static int aha1542_isa_match(struct device *pdev, unsigned int ndev) | ||
960 | { | ||
961 | struct Scsi_Host *sh = aha1542_hw_init(&driver_template, pdev, ndev); | ||
962 | |||
963 | if (!sh) | ||
964 | return 0; | ||
965 | |||
966 | dev_set_drvdata(pdev, sh); | ||
967 | return 1; | ||
968 | } | ||
969 | |||
970 | static int aha1542_isa_remove(struct device *pdev, | ||
971 | unsigned int ndev) | ||
972 | { | ||
973 | aha1542_release(dev_get_drvdata(pdev)); | ||
974 | dev_set_drvdata(pdev, NULL); | ||
975 | return 0; | ||
976 | } | ||
977 | |||
978 | static struct isa_driver aha1542_isa_driver = { | ||
979 | .match = aha1542_isa_match, | ||
980 | .remove = aha1542_isa_remove, | ||
981 | .driver = { | ||
982 | .name = "aha1542" | ||
983 | }, | ||
984 | }; | ||
985 | static int isa_registered; | ||
986 | |||
987 | #ifdef CONFIG_PNP | ||
988 | static struct pnp_device_id aha1542_pnp_ids[] = { | ||
989 | { .id = "ADP1542" }, | ||
990 | { .id = "" } | ||
991 | }; | ||
992 | MODULE_DEVICE_TABLE(pnp, aha1542_pnp_ids); | ||
993 | |||
994 | static int aha1542_pnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *id) | ||
995 | { | ||
996 | int indx; | ||
997 | struct Scsi_Host *sh; | ||
998 | |||
999 | for (indx = 0; indx < ARRAY_SIZE(io); indx++) { | ||
1000 | if (io[indx]) | ||
1001 | continue; | ||
1002 | |||
1003 | if (pnp_activate_dev(pdev) < 0) | ||
1004 | continue; | ||
1005 | |||
1006 | io[indx] = pnp_port_start(pdev, 0); | ||
1007 | |||
1008 | /* The card can be queried for its DMA, we have | ||
1009 | the DMA set up that is enough */ | ||
1010 | |||
1011 | dev_info(&pdev->dev, "ISAPnP found an AHA1535 at I/O 0x%03X", io[indx]); | ||
1012 | } | ||
1013 | |||
1014 | sh = aha1542_hw_init(&driver_template, &pdev->dev, indx); | ||
1015 | if (!sh) | ||
1016 | return -ENODEV; | ||
1017 | |||
1018 | pnp_set_drvdata(pdev, sh); | ||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | static void aha1542_pnp_remove(struct pnp_dev *pdev) | ||
1023 | { | ||
1024 | aha1542_release(pnp_get_drvdata(pdev)); | ||
1025 | pnp_set_drvdata(pdev, NULL); | ||
1026 | } | ||
1027 | |||
1028 | static struct pnp_driver aha1542_pnp_driver = { | ||
1029 | .name = "aha1542", | ||
1030 | .id_table = aha1542_pnp_ids, | ||
1031 | .probe = aha1542_pnp_probe, | ||
1032 | .remove = aha1542_pnp_remove, | ||
1033 | }; | ||
1034 | static int pnp_registered; | ||
1035 | #endif /* CONFIG_PNP */ | ||
1036 | |||
1037 | static int __init aha1542_init(void) | ||
1038 | { | ||
1039 | int ret = 0; | ||
1040 | |||
1041 | #ifdef CONFIG_PNP | ||
1042 | if (isapnp) { | ||
1043 | ret = pnp_register_driver(&aha1542_pnp_driver); | ||
1044 | if (!ret) | ||
1045 | pnp_registered = 1; | ||
1046 | } | ||
1047 | #endif | ||
1048 | ret = isa_register_driver(&aha1542_isa_driver, MAXBOARDS); | ||
1049 | if (!ret) | ||
1050 | isa_registered = 1; | ||
1051 | |||
1052 | #ifdef CONFIG_PNP | ||
1053 | if (pnp_registered) | ||
1054 | ret = 0; | ||
1055 | #endif | ||
1056 | if (isa_registered) | ||
1057 | ret = 0; | ||
1058 | |||
1059 | return ret; | ||
1060 | } | ||
1061 | |||
1062 | static void __exit aha1542_exit(void) | ||
1063 | { | ||
1064 | #ifdef CONFIG_PNP | ||
1065 | if (pnp_registered) | ||
1066 | pnp_unregister_driver(&aha1542_pnp_driver); | ||
1067 | #endif | ||
1068 | if (isa_registered) | ||
1069 | isa_unregister_driver(&aha1542_isa_driver); | ||
1070 | } | ||
1071 | |||
1072 | module_init(aha1542_init); | ||
1073 | module_exit(aha1542_exit); | ||
diff --git a/drivers/scsi/aha1542.h b/drivers/scsi/aha1542.h index b871d2b57f93..0fe9bae1b3d1 100644 --- a/drivers/scsi/aha1542.h +++ b/drivers/scsi/aha1542.h | |||
@@ -1,64 +1,35 @@ | |||
1 | #ifndef _AHA1542_H | 1 | #ifndef _AHA1542_H_ |
2 | 2 | #define _AHA1542_H_ | |
3 | /* $Id: aha1542.h,v 1.1 1992/07/24 06:27:38 root Exp root $ | ||
4 | * | ||
5 | * Header file for the adaptec 1542 driver for Linux | ||
6 | * | ||
7 | * $Log: aha1542.h,v $ | ||
8 | * Revision 1.1 1992/07/24 06:27:38 root | ||
9 | * Initial revision | ||
10 | * | ||
11 | * Revision 1.2 1992/07/04 18:41:49 root | ||
12 | * Replaced distribution with current drivers | ||
13 | * | ||
14 | * Revision 1.3 1992/06/23 23:58:20 root | ||
15 | * Fixes. | ||
16 | * | ||
17 | * Revision 1.2 1992/05/26 22:13:23 root | ||
18 | * Changed bug that prevented DMA above first 2 mbytes. | ||
19 | * | ||
20 | * Revision 1.1 1992/05/22 21:00:29 root | ||
21 | * Initial revision | ||
22 | * | ||
23 | * Revision 1.1 1992/04/24 18:01:50 root | ||
24 | * Initial revision | ||
25 | * | ||
26 | * Revision 1.1 1992/04/02 03:23:13 drew | ||
27 | * Initial revision | ||
28 | * | ||
29 | * Revision 1.3 1992/01/27 14:46:29 tthorn | ||
30 | * *** empty log message *** | ||
31 | * | ||
32 | */ | ||
33 | 3 | ||
34 | #include <linux/types.h> | 4 | #include <linux/types.h> |
35 | 5 | ||
36 | /* I/O Port interface 4.2 */ | 6 | /* I/O Port interface 4.2 */ |
37 | /* READ */ | 7 | /* READ */ |
38 | #define STATUS(base) base | 8 | #define STATUS(base) base |
39 | #define STST 0x80 /* Self Test in Progress */ | 9 | #define STST BIT(7) /* Self Test in Progress */ |
40 | #define DIAGF 0x40 /* Internal Diagnostic Failure */ | 10 | #define DIAGF BIT(6) /* Internal Diagnostic Failure */ |
41 | #define INIT 0x20 /* Mailbox Initialization Required */ | 11 | #define INIT BIT(5) /* Mailbox Initialization Required */ |
42 | #define IDLE 0x10 /* SCSI Host Adapter Idle */ | 12 | #define IDLE BIT(4) /* SCSI Host Adapter Idle */ |
43 | #define CDF 0x08 /* Command/Data Out Port Full */ | 13 | #define CDF BIT(3) /* Command/Data Out Port Full */ |
44 | #define DF 0x04 /* Data In Port Full */ | 14 | #define DF BIT(2) /* Data In Port Full */ |
45 | #define INVDCMD 0x01 /* Invalid H A Command */ | 15 | /* BIT(1) is reserved */ |
46 | #define STATMASK 0xfd /* 0x02 is reserved */ | 16 | #define INVDCMD BIT(0) /* Invalid H A Command */ |
17 | #define STATMASK (STST | DIAGF | INIT | IDLE | CDF | DF | INVDCMD) | ||
47 | 18 | ||
48 | #define INTRFLAGS(base) (STATUS(base)+2) | 19 | #define INTRFLAGS(base) (STATUS(base)+2) |
49 | #define ANYINTR 0x80 /* Any Interrupt */ | 20 | #define ANYINTR BIT(7) /* Any Interrupt */ |
50 | #define SCRD 0x08 /* SCSI Reset Detected */ | 21 | #define SCRD BIT(3) /* SCSI Reset Detected */ |
51 | #define HACC 0x04 /* HA Command Complete */ | 22 | #define HACC BIT(2) /* HA Command Complete */ |
52 | #define MBOA 0x02 /* MBO Empty */ | 23 | #define MBOA BIT(1) /* MBO Empty */ |
53 | #define MBIF 0x01 /* MBI Full */ | 24 | #define MBIF BIT(0) /* MBI Full */ |
54 | #define INTRMASK 0x8f | 25 | #define INTRMASK (ANYINTR | SCRD | HACC | MBOA | MBIF) |
55 | 26 | ||
56 | /* WRITE */ | 27 | /* WRITE */ |
57 | #define CONTROL(base) STATUS(base) | 28 | #define CONTROL(base) STATUS(base) |
58 | #define HRST 0x80 /* Hard Reset */ | 29 | #define HRST BIT(7) /* Hard Reset */ |
59 | #define SRST 0x40 /* Soft Reset */ | 30 | #define SRST BIT(6) /* Soft Reset */ |
60 | #define IRST 0x20 /* Interrupt Reset */ | 31 | #define IRST BIT(5) /* Interrupt Reset */ |
61 | #define SCRST 0x10 /* SCSI Bus Reset */ | 32 | #define SCRST BIT(4) /* SCSI Bus Reset */ |
62 | 33 | ||
63 | /* READ/WRITE */ | 34 | /* READ/WRITE */ |
64 | #define DATA(base) (STATUS(base)+1) | 35 | #define DATA(base) (STATUS(base)+1) |
@@ -80,14 +51,14 @@ | |||
80 | 51 | ||
81 | /* Mailbox Definition 5.2.1 and 5.2.2 */ | 52 | /* Mailbox Definition 5.2.1 and 5.2.2 */ |
82 | struct mailbox { | 53 | struct mailbox { |
83 | unchar status; /* Command/Status */ | 54 | u8 status; /* Command/Status */ |
84 | unchar ccbptr[3]; /* msb, .., lsb */ | 55 | u8 ccbptr[3]; /* msb, .., lsb */ |
85 | }; | 56 | }; |
86 | 57 | ||
87 | /* This is used with scatter-gather */ | 58 | /* This is used with scatter-gather */ |
88 | struct chain { | 59 | struct chain { |
89 | unchar datalen[3]; /* Size of this part of chain */ | 60 | u8 datalen[3]; /* Size of this part of chain */ |
90 | unchar dataptr[3]; /* Location of data */ | 61 | u8 dataptr[3]; /* Location of data */ |
91 | }; | 62 | }; |
92 | 63 | ||
93 | /* These belong in scsi.h also */ | 64 | /* These belong in scsi.h also */ |
@@ -100,51 +71,32 @@ static inline void any2scsi(u8 *p, u32 v) | |||
100 | 71 | ||
101 | #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) ) | 72 | #define scsi2int(up) ( (((long)*(up)) << 16) + (((long)(up)[1]) << 8) + ((long)(up)[2]) ) |
102 | 73 | ||
103 | #define xany2scsi(up, p) \ | ||
104 | (up)[0] = ((long)(p)) >> 24; \ | ||
105 | (up)[1] = ((long)(p)) >> 16; \ | ||
106 | (up)[2] = ((long)(p)) >> 8; \ | ||
107 | (up)[3] = ((long)(p)); | ||
108 | |||
109 | #define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \ | 74 | #define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \ |
110 | + (((long)(up)[2]) << 8) + ((long)(up)[3]) ) | 75 | + (((long)(up)[2]) << 8) + ((long)(up)[3]) ) |
111 | 76 | ||
112 | #define MAX_CDB 12 | 77 | #define MAX_CDB 12 |
113 | #define MAX_SENSE 14 | 78 | #define MAX_SENSE 14 |
114 | 79 | ||
115 | struct ccb { /* Command Control Block 5.3 */ | 80 | struct ccb { /* Command Control Block 5.3 */ |
116 | unchar op; /* Command Control Block Operation Code */ | 81 | u8 op; /* Command Control Block Operation Code */ |
117 | unchar idlun; /* op=0,2:Target Id, op=1:Initiator Id */ | 82 | u8 idlun; /* op=0,2:Target Id, op=1:Initiator Id */ |
118 | /* Outbound data transfer, length is checked*/ | 83 | /* Outbound data transfer, length is checked*/ |
119 | /* Inbound data transfer, length is checked */ | 84 | /* Inbound data transfer, length is checked */ |
120 | /* Logical Unit Number */ | 85 | /* Logical Unit Number */ |
121 | unchar cdblen; /* SCSI Command Length */ | 86 | u8 cdblen; /* SCSI Command Length */ |
122 | unchar rsalen; /* Request Sense Allocation Length/Disable */ | 87 | u8 rsalen; /* Request Sense Allocation Length/Disable */ |
123 | unchar datalen[3]; /* Data Length (msb, .., lsb) */ | 88 | u8 datalen[3]; /* Data Length (msb, .., lsb) */ |
124 | unchar dataptr[3]; /* Data Pointer */ | 89 | u8 dataptr[3]; /* Data Pointer */ |
125 | unchar linkptr[3]; /* Link Pointer */ | 90 | u8 linkptr[3]; /* Link Pointer */ |
126 | unchar commlinkid; /* Command Linking Identifier */ | 91 | u8 commlinkid; /* Command Linking Identifier */ |
127 | unchar hastat; /* Host Adapter Status (HASTAT) */ | 92 | u8 hastat; /* Host Adapter Status (HASTAT) */ |
128 | unchar tarstat; /* Target Device Status */ | 93 | u8 tarstat; /* Target Device Status */ |
129 | unchar reserved[2]; | 94 | u8 reserved[2]; |
130 | unchar cdb[MAX_CDB+MAX_SENSE];/* SCSI Command Descriptor Block */ | 95 | u8 cdb[MAX_CDB+MAX_SENSE]; /* SCSI Command Descriptor Block */ |
131 | /* REQUEST SENSE */ | 96 | /* REQUEST SENSE */ |
132 | }; | 97 | }; |
133 | 98 | ||
134 | static int aha1542_detect(struct scsi_host_template *); | 99 | #define AHA1542_REGION_SIZE 4 |
135 | static int aha1542_queuecommand(struct Scsi_Host *, struct scsi_cmnd *); | ||
136 | static int aha1542_bus_reset(Scsi_Cmnd * SCpnt); | ||
137 | static int aha1542_dev_reset(Scsi_Cmnd * SCpnt); | ||
138 | static int aha1542_host_reset(Scsi_Cmnd * SCpnt); | ||
139 | #if 0 | ||
140 | static int aha1542_old_abort(Scsi_Cmnd * SCpnt); | ||
141 | static int aha1542_old_reset(Scsi_Cmnd *, unsigned int); | ||
142 | #endif | ||
143 | static int aha1542_biosparam(struct scsi_device *, struct block_device *, | ||
144 | sector_t, int *); | ||
145 | |||
146 | #define AHA1542_MAILBOXES 8 | 100 | #define AHA1542_MAILBOXES 8 |
147 | #define AHA1542_SCATTER 16 | ||
148 | #define AHA1542_CMDLUN 1 | ||
149 | 101 | ||
150 | #endif | 102 | #endif /* _AHA1542_H_ */ |
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c index 97f2accd3dbb..109e2c99e6c1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_core.c +++ b/drivers/scsi/aic7xxx/aic79xx_core.c | |||
@@ -10437,14 +10437,13 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb) | |||
10437 | return; | 10437 | return; |
10438 | } | 10438 | } |
10439 | } | 10439 | } |
10440 | lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); | 10440 | lstate = kzalloc(sizeof(*lstate), GFP_ATOMIC); |
10441 | if (lstate == NULL) { | 10441 | if (lstate == NULL) { |
10442 | xpt_print_path(ccb->ccb_h.path); | 10442 | xpt_print_path(ccb->ccb_h.path); |
10443 | printk("Couldn't allocate lstate\n"); | 10443 | printk("Couldn't allocate lstate\n"); |
10444 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; | 10444 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; |
10445 | return; | 10445 | return; |
10446 | } | 10446 | } |
10447 | memset(lstate, 0, sizeof(*lstate)); | ||
10448 | status = xpt_create_path(&lstate->path, /*periph*/NULL, | 10447 | status = xpt_create_path(&lstate->path, /*periph*/NULL, |
10449 | xpt_path_path_id(ccb->ccb_h.path), | 10448 | xpt_path_path_id(ccb->ccb_h.path), |
10450 | xpt_path_target_id(ccb->ccb_h.path), | 10449 | xpt_path_target_id(ccb->ccb_h.path), |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index d5c7b193d8d3..ce96a0be3282 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -1326,10 +1326,9 @@ int | |||
1326 | ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) | 1326 | ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg) |
1327 | { | 1327 | { |
1328 | ahd->platform_data = | 1328 | ahd->platform_data = |
1329 | kmalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC); | 1329 | kzalloc(sizeof(struct ahd_platform_data), GFP_ATOMIC); |
1330 | if (ahd->platform_data == NULL) | 1330 | if (ahd->platform_data == NULL) |
1331 | return (ENOMEM); | 1331 | return (ENOMEM); |
1332 | memset(ahd->platform_data, 0, sizeof(struct ahd_platform_data)); | ||
1333 | ahd->platform_data->irq = AHD_LINUX_NOIRQ; | 1332 | ahd->platform_data->irq = AHD_LINUX_NOIRQ; |
1334 | ahd_lockinit(ahd); | 1333 | ahd_lockinit(ahd); |
1335 | ahd->seltime = (aic79xx_seltime & 0x3) << 4; | 1334 | ahd->seltime = (aic79xx_seltime & 0x3) << 4; |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_core.c b/drivers/scsi/aic7xxx/aic7xxx_core.c index 10172a3af1b9..c4829d84b335 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_core.c +++ b/drivers/scsi/aic7xxx/aic7xxx_core.c | |||
@@ -4464,10 +4464,9 @@ ahc_softc_init(struct ahc_softc *ahc) | |||
4464 | ahc->pause = ahc->unpause | PAUSE; | 4464 | ahc->pause = ahc->unpause | PAUSE; |
4465 | /* XXX The shared scb data stuff should be deprecated */ | 4465 | /* XXX The shared scb data stuff should be deprecated */ |
4466 | if (ahc->scb_data == NULL) { | 4466 | if (ahc->scb_data == NULL) { |
4467 | ahc->scb_data = kmalloc(sizeof(*ahc->scb_data), GFP_ATOMIC); | 4467 | ahc->scb_data = kzalloc(sizeof(*ahc->scb_data), GFP_ATOMIC); |
4468 | if (ahc->scb_data == NULL) | 4468 | if (ahc->scb_data == NULL) |
4469 | return (ENOMEM); | 4469 | return (ENOMEM); |
4470 | memset(ahc->scb_data, 0, sizeof(*ahc->scb_data)); | ||
4471 | } | 4470 | } |
4472 | 4471 | ||
4473 | return (0); | 4472 | return (0); |
@@ -4780,10 +4779,10 @@ ahc_init_scbdata(struct ahc_softc *ahc) | |||
4780 | SLIST_INIT(&scb_data->sg_maps); | 4779 | SLIST_INIT(&scb_data->sg_maps); |
4781 | 4780 | ||
4782 | /* Allocate SCB resources */ | 4781 | /* Allocate SCB resources */ |
4783 | scb_data->scbarray = kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC); | 4782 | scb_data->scbarray = kzalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, |
4783 | GFP_ATOMIC); | ||
4784 | if (scb_data->scbarray == NULL) | 4784 | if (scb_data->scbarray == NULL) |
4785 | return (ENOMEM); | 4785 | return (ENOMEM); |
4786 | memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC); | ||
4787 | 4786 | ||
4788 | /* Determine the number of hardware SCBs and initialize them */ | 4787 | /* Determine the number of hardware SCBs and initialize them */ |
4789 | 4788 | ||
@@ -7558,14 +7557,13 @@ ahc_handle_en_lun(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb) | |||
7558 | return; | 7557 | return; |
7559 | } | 7558 | } |
7560 | } | 7559 | } |
7561 | lstate = kmalloc(sizeof(*lstate), GFP_ATOMIC); | 7560 | lstate = kzalloc(sizeof(*lstate), GFP_ATOMIC); |
7562 | if (lstate == NULL) { | 7561 | if (lstate == NULL) { |
7563 | xpt_print_path(ccb->ccb_h.path); | 7562 | xpt_print_path(ccb->ccb_h.path); |
7564 | printk("Couldn't allocate lstate\n"); | 7563 | printk("Couldn't allocate lstate\n"); |
7565 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; | 7564 | ccb->ccb_h.status = CAM_RESRC_UNAVAIL; |
7566 | return; | 7565 | return; |
7567 | } | 7566 | } |
7568 | memset(lstate, 0, sizeof(*lstate)); | ||
7569 | status = xpt_create_path(&lstate->path, /*periph*/NULL, | 7567 | status = xpt_create_path(&lstate->path, /*periph*/NULL, |
7570 | xpt_path_path_id(ccb->ccb_h.path), | 7568 | xpt_path_path_id(ccb->ccb_h.path), |
7571 | xpt_path_target_id(ccb->ccb_h.path), | 7569 | xpt_path_target_id(ccb->ccb_h.path), |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 88360116dbcb..a2f2c774cd6b 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -1214,10 +1214,9 @@ ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg) | |||
1214 | { | 1214 | { |
1215 | 1215 | ||
1216 | ahc->platform_data = | 1216 | ahc->platform_data = |
1217 | kmalloc(sizeof(struct ahc_platform_data), GFP_ATOMIC); | 1217 | kzalloc(sizeof(struct ahc_platform_data), GFP_ATOMIC); |
1218 | if (ahc->platform_data == NULL) | 1218 | if (ahc->platform_data == NULL) |
1219 | return (ENOMEM); | 1219 | return (ENOMEM); |
1220 | memset(ahc->platform_data, 0, sizeof(struct ahc_platform_data)); | ||
1221 | ahc->platform_data->irq = AHC_LINUX_NOIRQ; | 1220 | ahc->platform_data->irq = AHC_LINUX_NOIRQ; |
1222 | ahc_lockinit(ahc); | 1221 | ahc_lockinit(ahc); |
1223 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; | 1222 | ahc->seltime = (aic7xxx_seltime & 0x3) << 4; |
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a70255413e7f..db87ece6edb2 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c | |||
@@ -1486,7 +1486,7 @@ static int NCR5380_select(struct Scsi_Host *instance, struct scsi_cmnd *cmd) | |||
1486 | * selection. | 1486 | * selection. |
1487 | */ | 1487 | */ |
1488 | 1488 | ||
1489 | timeout = jiffies + (250 * HZ / 1000); | 1489 | timeout = jiffies + msecs_to_jiffies(250); |
1490 | 1490 | ||
1491 | /* | 1491 | /* |
1492 | * XXX very interesting - we're seeing a bounce where the BSY we | 1492 | * XXX very interesting - we're seeing a bounce where the BSY we |
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index d1c37a386947..5ede3daa93dc 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c | |||
@@ -1014,7 +1014,6 @@ static struct platform_driver atari_scsi_driver = { | |||
1014 | .remove = __exit_p(atari_scsi_remove), | 1014 | .remove = __exit_p(atari_scsi_remove), |
1015 | .driver = { | 1015 | .driver = { |
1016 | .name = DRV_MODULE_NAME, | 1016 | .name = DRV_MODULE_NAME, |
1017 | .owner = THIS_MODULE, | ||
1018 | }, | 1017 | }, |
1019 | }; | 1018 | }; |
1020 | 1019 | ||
diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index f35792f7051c..f8d2478b11cc 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c | |||
@@ -57,9 +57,9 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | /* settings for DTC3181E card with only Mustek scanner attached */ | 59 | /* settings for DTC3181E card with only Mustek scanner attached */ |
60 | #define USLEEP_POLL 1 | 60 | #define USLEEP_POLL msecs_to_jiffies(10) |
61 | #define USLEEP_SLEEP 20 | 61 | #define USLEEP_SLEEP msecs_to_jiffies(200) |
62 | #define USLEEP_WAITLONG 500 | 62 | #define USLEEP_WAITLONG msecs_to_jiffies(5000) |
63 | 63 | ||
64 | #define AUTOPROBE_IRQ | 64 | #define AUTOPROBE_IRQ |
65 | 65 | ||
@@ -723,7 +723,7 @@ module_param(ncr_53c400a, int, 0); | |||
723 | module_param(dtc_3181e, int, 0); | 723 | module_param(dtc_3181e, int, 0); |
724 | MODULE_LICENSE("GPL"); | 724 | MODULE_LICENSE("GPL"); |
725 | 725 | ||
726 | #ifndef SCSI_G_NCR5380_MEM | 726 | #if !defined(SCSI_G_NCR5380_MEM) && defined(MODULE) |
727 | static struct isapnp_device_id id_table[] = { | 727 | static struct isapnp_device_id id_table[] = { |
728 | { | 728 | { |
729 | ISAPNP_ANY_ID, ISAPNP_ANY_ID, | 729 | ISAPNP_ANY_ID, ISAPNP_ANY_ID, |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index d9afc51af7d3..882744852aac 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -99,6 +99,7 @@ static unsigned int ipr_debug = 0; | |||
99 | static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS; | 99 | static unsigned int ipr_max_devs = IPR_DEFAULT_SIS64_DEVS; |
100 | static unsigned int ipr_dual_ioa_raid = 1; | 100 | static unsigned int ipr_dual_ioa_raid = 1; |
101 | static unsigned int ipr_number_of_msix = 2; | 101 | static unsigned int ipr_number_of_msix = 2; |
102 | static unsigned int ipr_fast_reboot; | ||
102 | static DEFINE_SPINLOCK(ipr_driver_lock); | 103 | static DEFINE_SPINLOCK(ipr_driver_lock); |
103 | 104 | ||
104 | /* This table describes the differences between DMA controller chips */ | 105 | /* This table describes the differences between DMA controller chips */ |
@@ -221,6 +222,8 @@ MODULE_PARM_DESC(max_devs, "Specify the maximum number of physical devices. " | |||
221 | "[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]"); | 222 | "[Default=" __stringify(IPR_DEFAULT_SIS64_DEVS) "]"); |
222 | module_param_named(number_of_msix, ipr_number_of_msix, int, 0); | 223 | module_param_named(number_of_msix, ipr_number_of_msix, int, 0); |
223 | MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)"); | 224 | MODULE_PARM_DESC(number_of_msix, "Specify the number of MSIX interrupts to use on capable adapters (1 - 16). (default:2)"); |
225 | module_param_named(fast_reboot, ipr_fast_reboot, int, S_IRUGO | S_IWUSR); | ||
226 | MODULE_PARM_DESC(fast_reboot, "Skip adapter shutdown during reboot. Set to 1 to enable. (default: 0)"); | ||
224 | MODULE_LICENSE("GPL"); | 227 | MODULE_LICENSE("GPL"); |
225 | MODULE_VERSION(IPR_DRIVER_VERSION); | 228 | MODULE_VERSION(IPR_DRIVER_VERSION); |
226 | 229 | ||
@@ -495,6 +498,10 @@ struct ipr_error_table_t ipr_error_table[] = { | |||
495 | "4061: Multipath redundancy level got better"}, | 498 | "4061: Multipath redundancy level got better"}, |
496 | {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, | 499 | {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, |
497 | "4060: Multipath redundancy level got worse"}, | 500 | "4060: Multipath redundancy level got worse"}, |
501 | {0x06808100, 0, IPR_DEFAULT_LOG_LEVEL, | ||
502 | "9083: Device raw mode enabled"}, | ||
503 | {0x06808200, 0, IPR_DEFAULT_LOG_LEVEL, | ||
504 | "9084: Device raw mode disabled"}, | ||
498 | {0x07270000, 0, 0, | 505 | {0x07270000, 0, 0, |
499 | "Failure due to other device"}, | 506 | "Failure due to other device"}, |
500 | {0x07278000, 0, IPR_DEFAULT_LOG_LEVEL, | 507 | {0x07278000, 0, IPR_DEFAULT_LOG_LEVEL, |
@@ -1462,7 +1469,8 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) | |||
1462 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | 1469 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); |
1463 | 1470 | ||
1464 | if (ioasc) { | 1471 | if (ioasc) { |
1465 | if (ioasc != IPR_IOASC_IOA_WAS_RESET) | 1472 | if (ioasc != IPR_IOASC_IOA_WAS_RESET && |
1473 | ioasc != IPR_IOASC_ABORTED_CMD_TERM_BY_HOST) | ||
1466 | dev_err(&ioa_cfg->pdev->dev, | 1474 | dev_err(&ioa_cfg->pdev->dev, |
1467 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); | 1475 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); |
1468 | 1476 | ||
@@ -2566,7 +2574,8 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) | |||
2566 | ipr_handle_log_data(ioa_cfg, hostrcb); | 2574 | ipr_handle_log_data(ioa_cfg, hostrcb); |
2567 | if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED) | 2575 | if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED) |
2568 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); | 2576 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV); |
2569 | } else if (ioasc != IPR_IOASC_IOA_WAS_RESET) { | 2577 | } else if (ioasc != IPR_IOASC_IOA_WAS_RESET && |
2578 | ioasc != IPR_IOASC_ABORTED_CMD_TERM_BY_HOST) { | ||
2570 | dev_err(&ioa_cfg->pdev->dev, | 2579 | dev_err(&ioa_cfg->pdev->dev, |
2571 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); | 2580 | "Host RCB failed with IOASC: 0x%08X\n", ioasc); |
2572 | } | 2581 | } |
@@ -4491,11 +4500,83 @@ static struct device_attribute ipr_resource_type_attr = { | |||
4491 | .show = ipr_show_resource_type | 4500 | .show = ipr_show_resource_type |
4492 | }; | 4501 | }; |
4493 | 4502 | ||
4503 | /** | ||
4504 | * ipr_show_raw_mode - Show the adapter's raw mode | ||
4505 | * @dev: class device struct | ||
4506 | * @buf: buffer | ||
4507 | * | ||
4508 | * Return value: | ||
4509 | * number of bytes printed to buffer | ||
4510 | **/ | ||
4511 | static ssize_t ipr_show_raw_mode(struct device *dev, | ||
4512 | struct device_attribute *attr, char *buf) | ||
4513 | { | ||
4514 | struct scsi_device *sdev = to_scsi_device(dev); | ||
4515 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; | ||
4516 | struct ipr_resource_entry *res; | ||
4517 | unsigned long lock_flags = 0; | ||
4518 | ssize_t len; | ||
4519 | |||
4520 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
4521 | res = (struct ipr_resource_entry *)sdev->hostdata; | ||
4522 | if (res) | ||
4523 | len = snprintf(buf, PAGE_SIZE, "%d\n", res->raw_mode); | ||
4524 | else | ||
4525 | len = -ENXIO; | ||
4526 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
4527 | return len; | ||
4528 | } | ||
4529 | |||
4530 | /** | ||
4531 | * ipr_store_raw_mode - Change the adapter's raw mode | ||
4532 | * @dev: class device struct | ||
4533 | * @buf: buffer | ||
4534 | * | ||
4535 | * Return value: | ||
4536 | * number of bytes printed to buffer | ||
4537 | **/ | ||
4538 | static ssize_t ipr_store_raw_mode(struct device *dev, | ||
4539 | struct device_attribute *attr, | ||
4540 | const char *buf, size_t count) | ||
4541 | { | ||
4542 | struct scsi_device *sdev = to_scsi_device(dev); | ||
4543 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; | ||
4544 | struct ipr_resource_entry *res; | ||
4545 | unsigned long lock_flags = 0; | ||
4546 | ssize_t len; | ||
4547 | |||
4548 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
4549 | res = (struct ipr_resource_entry *)sdev->hostdata; | ||
4550 | if (res) { | ||
4551 | if (ioa_cfg->sis64 && ipr_is_af_dasd_device(res)) { | ||
4552 | res->raw_mode = simple_strtoul(buf, NULL, 10); | ||
4553 | len = strlen(buf); | ||
4554 | if (res->sdev) | ||
4555 | sdev_printk(KERN_INFO, res->sdev, "raw mode is %s\n", | ||
4556 | res->raw_mode ? "enabled" : "disabled"); | ||
4557 | } else | ||
4558 | len = -EINVAL; | ||
4559 | } else | ||
4560 | len = -ENXIO; | ||
4561 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
4562 | return len; | ||
4563 | } | ||
4564 | |||
4565 | static struct device_attribute ipr_raw_mode_attr = { | ||
4566 | .attr = { | ||
4567 | .name = "raw_mode", | ||
4568 | .mode = S_IRUGO | S_IWUSR, | ||
4569 | }, | ||
4570 | .show = ipr_show_raw_mode, | ||
4571 | .store = ipr_store_raw_mode | ||
4572 | }; | ||
4573 | |||
4494 | static struct device_attribute *ipr_dev_attrs[] = { | 4574 | static struct device_attribute *ipr_dev_attrs[] = { |
4495 | &ipr_adapter_handle_attr, | 4575 | &ipr_adapter_handle_attr, |
4496 | &ipr_resource_path_attr, | 4576 | &ipr_resource_path_attr, |
4497 | &ipr_device_id_attr, | 4577 | &ipr_device_id_attr, |
4498 | &ipr_resource_type_attr, | 4578 | &ipr_resource_type_attr, |
4579 | &ipr_raw_mode_attr, | ||
4499 | NULL, | 4580 | NULL, |
4500 | }; | 4581 | }; |
4501 | 4582 | ||
@@ -5379,9 +5460,6 @@ static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, | |||
5379 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 5460 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
5380 | /* Mask the interrupt */ | 5461 | /* Mask the interrupt */ |
5381 | writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.set_interrupt_mask_reg); | 5462 | writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.set_interrupt_mask_reg); |
5382 | |||
5383 | /* Clear the interrupt */ | ||
5384 | writel(IPR_PCII_IOA_TRANS_TO_OPER, ioa_cfg->regs.clr_interrupt_reg); | ||
5385 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); | 5463 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); |
5386 | 5464 | ||
5387 | list_del(&ioa_cfg->reset_cmd->queue); | 5465 | list_del(&ioa_cfg->reset_cmd->queue); |
@@ -6150,6 +6228,13 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
6150 | break; | 6228 | break; |
6151 | case IPR_IOASC_NR_INIT_CMD_REQUIRED: | 6229 | case IPR_IOASC_NR_INIT_CMD_REQUIRED: |
6152 | break; | 6230 | break; |
6231 | case IPR_IOASC_IR_NON_OPTIMIZED: | ||
6232 | if (res->raw_mode) { | ||
6233 | res->raw_mode = 0; | ||
6234 | scsi_cmd->result |= (DID_IMM_RETRY << 16); | ||
6235 | } else | ||
6236 | scsi_cmd->result |= (DID_ERROR << 16); | ||
6237 | break; | ||
6153 | default: | 6238 | default: |
6154 | if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) | 6239 | if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) |
6155 | scsi_cmd->result |= (DID_ERROR << 16); | 6240 | scsi_cmd->result |= (DID_ERROR << 16); |
@@ -6289,6 +6374,8 @@ static int ipr_queuecommand(struct Scsi_Host *shost, | |||
6289 | (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) { | 6374 | (!ipr_is_gscsi(res) || scsi_cmd->cmnd[0] == IPR_QUERY_RSRC_STATE)) { |
6290 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | 6375 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_IOACMD; |
6291 | } | 6376 | } |
6377 | if (res->raw_mode && ipr_is_af_dasd_device(res)) | ||
6378 | ioarcb->cmd_pkt.request_type = IPR_RQTYPE_PIPE; | ||
6292 | 6379 | ||
6293 | if (ioa_cfg->sis64) | 6380 | if (ioa_cfg->sis64) |
6294 | rc = ipr_build_ioadl64(ioa_cfg, ipr_cmd); | 6381 | rc = ipr_build_ioadl64(ioa_cfg, ipr_cmd); |
@@ -6402,7 +6489,6 @@ static struct scsi_host_template driver_template = { | |||
6402 | .shost_attrs = ipr_ioa_attrs, | 6489 | .shost_attrs = ipr_ioa_attrs, |
6403 | .sdev_attrs = ipr_dev_attrs, | 6490 | .sdev_attrs = ipr_dev_attrs, |
6404 | .proc_name = IPR_NAME, | 6491 | .proc_name = IPR_NAME, |
6405 | .no_write_same = 1, | ||
6406 | .use_blk_tags = 1, | 6492 | .use_blk_tags = 1, |
6407 | }; | 6493 | }; |
6408 | 6494 | ||
@@ -8318,7 +8404,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) | |||
8318 | static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | 8404 | static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) |
8319 | { | 8405 | { |
8320 | ENTER; | 8406 | ENTER; |
8321 | pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset); | ||
8322 | ipr_cmd->job_step = ipr_reset_bist_done; | 8407 | ipr_cmd->job_step = ipr_reset_bist_done; |
8323 | ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); | 8408 | ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT); |
8324 | LEAVE; | 8409 | LEAVE; |
@@ -8326,6 +8411,32 @@ static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | |||
8326 | } | 8411 | } |
8327 | 8412 | ||
8328 | /** | 8413 | /** |
8414 | * ipr_reset_reset_work - Pulse a PCIe fundamental reset | ||
8415 | * @work: work struct | ||
8416 | * | ||
8417 | * Description: This pulses warm reset to a slot. | ||
8418 | * | ||
8419 | **/ | ||
8420 | static void ipr_reset_reset_work(struct work_struct *work) | ||
8421 | { | ||
8422 | struct ipr_cmnd *ipr_cmd = container_of(work, struct ipr_cmnd, work); | ||
8423 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8424 | struct pci_dev *pdev = ioa_cfg->pdev; | ||
8425 | unsigned long lock_flags = 0; | ||
8426 | |||
8427 | ENTER; | ||
8428 | pci_set_pcie_reset_state(pdev, pcie_warm_reset); | ||
8429 | msleep(jiffies_to_msecs(IPR_PCI_RESET_TIMEOUT)); | ||
8430 | pci_set_pcie_reset_state(pdev, pcie_deassert_reset); | ||
8431 | |||
8432 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | ||
8433 | if (ioa_cfg->reset_cmd == ipr_cmd) | ||
8434 | ipr_reset_ioa_job(ipr_cmd); | ||
8435 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
8436 | LEAVE; | ||
8437 | } | ||
8438 | |||
8439 | /** | ||
8329 | * ipr_reset_slot_reset - Reset the PCI slot of the adapter. | 8440 | * ipr_reset_slot_reset - Reset the PCI slot of the adapter. |
8330 | * @ipr_cmd: ipr command struct | 8441 | * @ipr_cmd: ipr command struct |
8331 | * | 8442 | * |
@@ -8337,12 +8448,11 @@ static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd) | |||
8337 | static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) | 8448 | static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd) |
8338 | { | 8449 | { |
8339 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 8450 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
8340 | struct pci_dev *pdev = ioa_cfg->pdev; | ||
8341 | 8451 | ||
8342 | ENTER; | 8452 | ENTER; |
8343 | pci_set_pcie_reset_state(pdev, pcie_warm_reset); | 8453 | INIT_WORK(&ipr_cmd->work, ipr_reset_reset_work); |
8454 | queue_work(ioa_cfg->reset_work_q, &ipr_cmd->work); | ||
8344 | ipr_cmd->job_step = ipr_reset_slot_reset_done; | 8455 | ipr_cmd->job_step = ipr_reset_slot_reset_done; |
8345 | ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT); | ||
8346 | LEAVE; | 8456 | LEAVE; |
8347 | return IPR_RC_JOB_RETURN; | 8457 | return IPR_RC_JOB_RETURN; |
8348 | } | 8458 | } |
@@ -8480,6 +8590,122 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd) | |||
8480 | } | 8590 | } |
8481 | 8591 | ||
8482 | /** | 8592 | /** |
8593 | * ipr_reset_quiesce_done - Complete IOA disconnect | ||
8594 | * @ipr_cmd: ipr command struct | ||
8595 | * | ||
8596 | * Description: Freeze the adapter to complete quiesce processing | ||
8597 | * | ||
8598 | * Return value: | ||
8599 | * IPR_RC_JOB_CONTINUE | ||
8600 | **/ | ||
8601 | static int ipr_reset_quiesce_done(struct ipr_cmnd *ipr_cmd) | ||
8602 | { | ||
8603 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8604 | |||
8605 | ENTER; | ||
8606 | ipr_cmd->job_step = ipr_ioa_bringdown_done; | ||
8607 | ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); | ||
8608 | LEAVE; | ||
8609 | return IPR_RC_JOB_CONTINUE; | ||
8610 | } | ||
8611 | |||
8612 | /** | ||
8613 | * ipr_reset_cancel_hcam_done - Check for outstanding commands | ||
8614 | * @ipr_cmd: ipr command struct | ||
8615 | * | ||
8616 | * Description: Ensure nothing is outstanding to the IOA and | ||
8617 | * proceed with IOA disconnect. Otherwise reset the IOA. | ||
8618 | * | ||
8619 | * Return value: | ||
8620 | * IPR_RC_JOB_RETURN / IPR_RC_JOB_CONTINUE | ||
8621 | **/ | ||
8622 | static int ipr_reset_cancel_hcam_done(struct ipr_cmnd *ipr_cmd) | ||
8623 | { | ||
8624 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8625 | struct ipr_cmnd *loop_cmd; | ||
8626 | struct ipr_hrr_queue *hrrq; | ||
8627 | int rc = IPR_RC_JOB_CONTINUE; | ||
8628 | int count = 0; | ||
8629 | |||
8630 | ENTER; | ||
8631 | ipr_cmd->job_step = ipr_reset_quiesce_done; | ||
8632 | |||
8633 | for_each_hrrq(hrrq, ioa_cfg) { | ||
8634 | spin_lock(&hrrq->_lock); | ||
8635 | list_for_each_entry(loop_cmd, &hrrq->hrrq_pending_q, queue) { | ||
8636 | count++; | ||
8637 | ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE); | ||
8638 | list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); | ||
8639 | rc = IPR_RC_JOB_RETURN; | ||
8640 | break; | ||
8641 | } | ||
8642 | spin_unlock(&hrrq->_lock); | ||
8643 | |||
8644 | if (count) | ||
8645 | break; | ||
8646 | } | ||
8647 | |||
8648 | LEAVE; | ||
8649 | return rc; | ||
8650 | } | ||
8651 | |||
8652 | /** | ||
8653 | * ipr_reset_cancel_hcam - Cancel outstanding HCAMs | ||
8654 | * @ipr_cmd: ipr command struct | ||
8655 | * | ||
8656 | * Description: Cancel any oustanding HCAMs to the IOA. | ||
8657 | * | ||
8658 | * Return value: | ||
8659 | * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN | ||
8660 | **/ | ||
8661 | static int ipr_reset_cancel_hcam(struct ipr_cmnd *ipr_cmd) | ||
8662 | { | ||
8663 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | ||
8664 | int rc = IPR_RC_JOB_CONTINUE; | ||
8665 | struct ipr_cmd_pkt *cmd_pkt; | ||
8666 | struct ipr_cmnd *hcam_cmd; | ||
8667 | struct ipr_hrr_queue *hrrq = &ioa_cfg->hrrq[IPR_INIT_HRRQ]; | ||
8668 | |||
8669 | ENTER; | ||
8670 | ipr_cmd->job_step = ipr_reset_cancel_hcam_done; | ||
8671 | |||
8672 | if (!hrrq->ioa_is_dead) { | ||
8673 | if (!list_empty(&ioa_cfg->hostrcb_pending_q)) { | ||
8674 | list_for_each_entry(hcam_cmd, &hrrq->hrrq_pending_q, queue) { | ||
8675 | if (hcam_cmd->ioarcb.cmd_pkt.cdb[0] != IPR_HOST_CONTROLLED_ASYNC) | ||
8676 | continue; | ||
8677 | |||
8678 | ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); | ||
8679 | ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | ||
8680 | cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; | ||
8681 | cmd_pkt->request_type = IPR_RQTYPE_IOACMD; | ||
8682 | cmd_pkt->cdb[0] = IPR_CANCEL_REQUEST; | ||
8683 | cmd_pkt->cdb[1] = IPR_CANCEL_64BIT_IOARCB; | ||
8684 | cmd_pkt->cdb[10] = ((u64) hcam_cmd->dma_addr >> 56) & 0xff; | ||
8685 | cmd_pkt->cdb[11] = ((u64) hcam_cmd->dma_addr >> 48) & 0xff; | ||
8686 | cmd_pkt->cdb[12] = ((u64) hcam_cmd->dma_addr >> 40) & 0xff; | ||
8687 | cmd_pkt->cdb[13] = ((u64) hcam_cmd->dma_addr >> 32) & 0xff; | ||
8688 | cmd_pkt->cdb[2] = ((u64) hcam_cmd->dma_addr >> 24) & 0xff; | ||
8689 | cmd_pkt->cdb[3] = ((u64) hcam_cmd->dma_addr >> 16) & 0xff; | ||
8690 | cmd_pkt->cdb[4] = ((u64) hcam_cmd->dma_addr >> 8) & 0xff; | ||
8691 | cmd_pkt->cdb[5] = ((u64) hcam_cmd->dma_addr) & 0xff; | ||
8692 | |||
8693 | ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, | ||
8694 | IPR_CANCEL_TIMEOUT); | ||
8695 | |||
8696 | rc = IPR_RC_JOB_RETURN; | ||
8697 | ipr_cmd->job_step = ipr_reset_cancel_hcam; | ||
8698 | break; | ||
8699 | } | ||
8700 | } | ||
8701 | } else | ||
8702 | ipr_cmd->job_step = ipr_reset_alert; | ||
8703 | |||
8704 | LEAVE; | ||
8705 | return rc; | ||
8706 | } | ||
8707 | |||
8708 | /** | ||
8483 | * ipr_reset_ucode_download_done - Microcode download completion | 8709 | * ipr_reset_ucode_download_done - Microcode download completion |
8484 | * @ipr_cmd: ipr command struct | 8710 | * @ipr_cmd: ipr command struct |
8485 | * | 8711 | * |
@@ -8561,7 +8787,9 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd) | |||
8561 | int rc = IPR_RC_JOB_CONTINUE; | 8787 | int rc = IPR_RC_JOB_CONTINUE; |
8562 | 8788 | ||
8563 | ENTER; | 8789 | ENTER; |
8564 | if (shutdown_type != IPR_SHUTDOWN_NONE && | 8790 | if (shutdown_type == IPR_SHUTDOWN_QUIESCE) |
8791 | ipr_cmd->job_step = ipr_reset_cancel_hcam; | ||
8792 | else if (shutdown_type != IPR_SHUTDOWN_NONE && | ||
8565 | !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) { | 8793 | !ioa_cfg->hrrq[IPR_INIT_HRRQ].ioa_is_dead) { |
8566 | ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); | 8794 | ipr_cmd->ioarcb.res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); |
8567 | ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD; | 8795 | ipr_cmd->ioarcb.cmd_pkt.request_type = IPR_RQTYPE_IOACMD; |
@@ -8917,13 +9145,15 @@ static void ipr_free_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) | |||
8917 | { | 9145 | { |
8918 | int i; | 9146 | int i; |
8919 | 9147 | ||
8920 | for (i = 0; i < IPR_NUM_CMD_BLKS; i++) { | 9148 | if (ioa_cfg->ipr_cmnd_list) { |
8921 | if (ioa_cfg->ipr_cmnd_list[i]) | 9149 | for (i = 0; i < IPR_NUM_CMD_BLKS; i++) { |
8922 | dma_pool_free(ioa_cfg->ipr_cmd_pool, | 9150 | if (ioa_cfg->ipr_cmnd_list[i]) |
8923 | ioa_cfg->ipr_cmnd_list[i], | 9151 | dma_pool_free(ioa_cfg->ipr_cmd_pool, |
8924 | ioa_cfg->ipr_cmnd_list_dma[i]); | 9152 | ioa_cfg->ipr_cmnd_list[i], |
9153 | ioa_cfg->ipr_cmnd_list_dma[i]); | ||
8925 | 9154 | ||
8926 | ioa_cfg->ipr_cmnd_list[i] = NULL; | 9155 | ioa_cfg->ipr_cmnd_list[i] = NULL; |
9156 | } | ||
8927 | } | 9157 | } |
8928 | 9158 | ||
8929 | if (ioa_cfg->ipr_cmd_pool) | 9159 | if (ioa_cfg->ipr_cmd_pool) |
@@ -8973,26 +9203,25 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) | |||
8973 | } | 9203 | } |
8974 | 9204 | ||
8975 | /** | 9205 | /** |
8976 | * ipr_free_all_resources - Free all allocated resources for an adapter. | 9206 | * ipr_free_irqs - Free all allocated IRQs for the adapter. |
8977 | * @ipr_cmd: ipr command struct | 9207 | * @ioa_cfg: ipr cfg struct |
8978 | * | 9208 | * |
8979 | * This function frees all allocated resources for the | 9209 | * This function frees all allocated IRQs for the |
8980 | * specified adapter. | 9210 | * specified adapter. |
8981 | * | 9211 | * |
8982 | * Return value: | 9212 | * Return value: |
8983 | * none | 9213 | * none |
8984 | **/ | 9214 | **/ |
8985 | static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) | 9215 | static void ipr_free_irqs(struct ipr_ioa_cfg *ioa_cfg) |
8986 | { | 9216 | { |
8987 | struct pci_dev *pdev = ioa_cfg->pdev; | 9217 | struct pci_dev *pdev = ioa_cfg->pdev; |
8988 | 9218 | ||
8989 | ENTER; | ||
8990 | if (ioa_cfg->intr_flag == IPR_USE_MSI || | 9219 | if (ioa_cfg->intr_flag == IPR_USE_MSI || |
8991 | ioa_cfg->intr_flag == IPR_USE_MSIX) { | 9220 | ioa_cfg->intr_flag == IPR_USE_MSIX) { |
8992 | int i; | 9221 | int i; |
8993 | for (i = 0; i < ioa_cfg->nvectors; i++) | 9222 | for (i = 0; i < ioa_cfg->nvectors; i++) |
8994 | free_irq(ioa_cfg->vectors_info[i].vec, | 9223 | free_irq(ioa_cfg->vectors_info[i].vec, |
8995 | &ioa_cfg->hrrq[i]); | 9224 | &ioa_cfg->hrrq[i]); |
8996 | } else | 9225 | } else |
8997 | free_irq(pdev->irq, &ioa_cfg->hrrq[0]); | 9226 | free_irq(pdev->irq, &ioa_cfg->hrrq[0]); |
8998 | 9227 | ||
@@ -9003,7 +9232,26 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) | |||
9003 | pci_disable_msix(pdev); | 9232 | pci_disable_msix(pdev); |
9004 | ioa_cfg->intr_flag &= ~IPR_USE_MSIX; | 9233 | ioa_cfg->intr_flag &= ~IPR_USE_MSIX; |
9005 | } | 9234 | } |
9235 | } | ||
9006 | 9236 | ||
9237 | /** | ||
9238 | * ipr_free_all_resources - Free all allocated resources for an adapter. | ||
9239 | * @ipr_cmd: ipr command struct | ||
9240 | * | ||
9241 | * This function frees all allocated resources for the | ||
9242 | * specified adapter. | ||
9243 | * | ||
9244 | * Return value: | ||
9245 | * none | ||
9246 | **/ | ||
9247 | static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg) | ||
9248 | { | ||
9249 | struct pci_dev *pdev = ioa_cfg->pdev; | ||
9250 | |||
9251 | ENTER; | ||
9252 | ipr_free_irqs(ioa_cfg); | ||
9253 | if (ioa_cfg->reset_work_q) | ||
9254 | destroy_workqueue(ioa_cfg->reset_work_q); | ||
9007 | iounmap(ioa_cfg->hdw_dma_regs); | 9255 | iounmap(ioa_cfg->hdw_dma_regs); |
9008 | pci_release_regions(pdev); | 9256 | pci_release_regions(pdev); |
9009 | ipr_free_mem(ioa_cfg); | 9257 | ipr_free_mem(ioa_cfg); |
@@ -9823,6 +10071,14 @@ static int ipr_probe_ioa(struct pci_dev *pdev, | |||
9823 | (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) { | 10071 | (dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) { |
9824 | ioa_cfg->needs_warm_reset = 1; | 10072 | ioa_cfg->needs_warm_reset = 1; |
9825 | ioa_cfg->reset = ipr_reset_slot_reset; | 10073 | ioa_cfg->reset = ipr_reset_slot_reset; |
10074 | |||
10075 | ioa_cfg->reset_work_q = alloc_ordered_workqueue("ipr_reset_%d", | ||
10076 | WQ_MEM_RECLAIM, host->host_no); | ||
10077 | |||
10078 | if (!ioa_cfg->reset_work_q) { | ||
10079 | dev_err(&pdev->dev, "Couldn't register reset workqueue\n"); | ||
10080 | goto out_free_irq; | ||
10081 | } | ||
9826 | } else | 10082 | } else |
9827 | ioa_cfg->reset = ipr_reset_start_bist; | 10083 | ioa_cfg->reset = ipr_reset_start_bist; |
9828 | 10084 | ||
@@ -9834,6 +10090,8 @@ static int ipr_probe_ioa(struct pci_dev *pdev, | |||
9834 | out: | 10090 | out: |
9835 | return rc; | 10091 | return rc; |
9836 | 10092 | ||
10093 | out_free_irq: | ||
10094 | ipr_free_irqs(ioa_cfg); | ||
9837 | cleanup_nolog: | 10095 | cleanup_nolog: |
9838 | ipr_free_mem(ioa_cfg); | 10096 | ipr_free_mem(ioa_cfg); |
9839 | out_msi_disable: | 10097 | out_msi_disable: |
@@ -9914,6 +10172,8 @@ static void __ipr_remove(struct pci_dev *pdev) | |||
9914 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); | 10172 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags); |
9915 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | 10173 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); |
9916 | flush_work(&ioa_cfg->work_q); | 10174 | flush_work(&ioa_cfg->work_q); |
10175 | if (ioa_cfg->reset_work_q) | ||
10176 | flush_workqueue(ioa_cfg->reset_work_q); | ||
9917 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); | 10177 | INIT_LIST_HEAD(&ioa_cfg->used_res_q); |
9918 | spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); | 10178 | spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags); |
9919 | 10179 | ||
@@ -10036,6 +10296,7 @@ static void ipr_shutdown(struct pci_dev *pdev) | |||
10036 | { | 10296 | { |
10037 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); | 10297 | struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev); |
10038 | unsigned long lock_flags = 0; | 10298 | unsigned long lock_flags = 0; |
10299 | enum ipr_shutdown_type shutdown_type = IPR_SHUTDOWN_NORMAL; | ||
10039 | int i; | 10300 | int i; |
10040 | 10301 | ||
10041 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 10302 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
@@ -10051,9 +10312,16 @@ static void ipr_shutdown(struct pci_dev *pdev) | |||
10051 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); | 10312 | spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); |
10052 | } | 10313 | } |
10053 | 10314 | ||
10054 | ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL); | 10315 | if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) |
10316 | shutdown_type = IPR_SHUTDOWN_QUIESCE; | ||
10317 | |||
10318 | ipr_initiate_ioa_bringdown(ioa_cfg, shutdown_type); | ||
10055 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 10319 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
10056 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); | 10320 | wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); |
10321 | if (ipr_fast_reboot && system_state == SYSTEM_RESTART && ioa_cfg->sis64) { | ||
10322 | ipr_free_irqs(ioa_cfg); | ||
10323 | pci_disable_device(ioa_cfg->pdev); | ||
10324 | } | ||
10057 | } | 10325 | } |
10058 | 10326 | ||
10059 | static struct pci_device_id ipr_pci_table[] = { | 10327 | static struct pci_device_id ipr_pci_table[] = { |
@@ -10211,7 +10479,8 @@ static int ipr_halt(struct notifier_block *nb, ulong event, void *buf) | |||
10211 | 10479 | ||
10212 | list_for_each_entry(ioa_cfg, &ipr_ioa_head, queue) { | 10480 | list_for_each_entry(ioa_cfg, &ipr_ioa_head, queue) { |
10213 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); | 10481 | spin_lock_irqsave(ioa_cfg->host->host_lock, flags); |
10214 | if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) { | 10482 | if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds || |
10483 | (ipr_fast_reboot && event == SYS_RESTART && ioa_cfg->sis64)) { | ||
10215 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); | 10484 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); |
10216 | continue; | 10485 | continue; |
10217 | } | 10486 | } |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index ec03b42fa2b9..47412cf4eaac 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -39,8 +39,8 @@ | |||
39 | /* | 39 | /* |
40 | * Literals | 40 | * Literals |
41 | */ | 41 | */ |
42 | #define IPR_DRIVER_VERSION "2.6.0" | 42 | #define IPR_DRIVER_VERSION "2.6.1" |
43 | #define IPR_DRIVER_DATE "(November 16, 2012)" | 43 | #define IPR_DRIVER_DATE "(March 12, 2015)" |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding | 46 | * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding |
@@ -138,6 +138,7 @@ | |||
138 | #define IPR_IOASC_BUS_WAS_RESET 0x06290000 | 138 | #define IPR_IOASC_BUS_WAS_RESET 0x06290000 |
139 | #define IPR_IOASC_BUS_WAS_RESET_BY_OTHER 0x06298000 | 139 | #define IPR_IOASC_BUS_WAS_RESET_BY_OTHER 0x06298000 |
140 | #define IPR_IOASC_ABORTED_CMD_TERM_BY_HOST 0x0B5A0000 | 140 | #define IPR_IOASC_ABORTED_CMD_TERM_BY_HOST 0x0B5A0000 |
141 | #define IPR_IOASC_IR_NON_OPTIMIZED 0x05258200 | ||
141 | 142 | ||
142 | #define IPR_FIRST_DRIVER_IOASC 0x10000000 | 143 | #define IPR_FIRST_DRIVER_IOASC 0x10000000 |
143 | #define IPR_IOASC_IOA_WAS_RESET 0x10000001 | 144 | #define IPR_IOASC_IOA_WAS_RESET 0x10000001 |
@@ -196,6 +197,8 @@ | |||
196 | /* | 197 | /* |
197 | * Adapter Commands | 198 | * Adapter Commands |
198 | */ | 199 | */ |
200 | #define IPR_CANCEL_REQUEST 0xC0 | ||
201 | #define IPR_CANCEL_64BIT_IOARCB 0x01 | ||
199 | #define IPR_QUERY_RSRC_STATE 0xC2 | 202 | #define IPR_QUERY_RSRC_STATE 0xC2 |
200 | #define IPR_RESET_DEVICE 0xC3 | 203 | #define IPR_RESET_DEVICE 0xC3 |
201 | #define IPR_RESET_TYPE_SELECT 0x80 | 204 | #define IPR_RESET_TYPE_SELECT 0x80 |
@@ -222,6 +225,7 @@ | |||
222 | #define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ) | 225 | #define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ) |
223 | #define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ) | 226 | #define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ) |
224 | #define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 227 | #define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
228 | #define IPR_CANCEL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | ||
225 | #define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 229 | #define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
226 | #define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 230 | #define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
227 | #define IPR_INTERNAL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) | 231 | #define IPR_INTERNAL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ) |
@@ -518,6 +522,7 @@ struct ipr_cmd_pkt { | |||
518 | #define IPR_RQTYPE_IOACMD 0x01 | 522 | #define IPR_RQTYPE_IOACMD 0x01 |
519 | #define IPR_RQTYPE_HCAM 0x02 | 523 | #define IPR_RQTYPE_HCAM 0x02 |
520 | #define IPR_RQTYPE_ATA_PASSTHRU 0x04 | 524 | #define IPR_RQTYPE_ATA_PASSTHRU 0x04 |
525 | #define IPR_RQTYPE_PIPE 0x05 | ||
521 | 526 | ||
522 | u8 reserved2; | 527 | u8 reserved2; |
523 | 528 | ||
@@ -1271,6 +1276,7 @@ struct ipr_resource_entry { | |||
1271 | u8 del_from_ml:1; | 1276 | u8 del_from_ml:1; |
1272 | u8 resetting_device:1; | 1277 | u8 resetting_device:1; |
1273 | u8 reset_occurred:1; | 1278 | u8 reset_occurred:1; |
1279 | u8 raw_mode:1; | ||
1274 | 1280 | ||
1275 | u32 bus; /* AKA channel */ | 1281 | u32 bus; /* AKA channel */ |
1276 | u32 target; /* AKA id */ | 1282 | u32 target; /* AKA id */ |
@@ -1402,7 +1408,8 @@ enum ipr_shutdown_type { | |||
1402 | IPR_SHUTDOWN_NORMAL = 0x00, | 1408 | IPR_SHUTDOWN_NORMAL = 0x00, |
1403 | IPR_SHUTDOWN_PREPARE_FOR_NORMAL = 0x40, | 1409 | IPR_SHUTDOWN_PREPARE_FOR_NORMAL = 0x40, |
1404 | IPR_SHUTDOWN_ABBREV = 0x80, | 1410 | IPR_SHUTDOWN_ABBREV = 0x80, |
1405 | IPR_SHUTDOWN_NONE = 0x100 | 1411 | IPR_SHUTDOWN_NONE = 0x100, |
1412 | IPR_SHUTDOWN_QUIESCE = 0x101, | ||
1406 | }; | 1413 | }; |
1407 | 1414 | ||
1408 | struct ipr_trace_entry { | 1415 | struct ipr_trace_entry { |
@@ -1536,6 +1543,7 @@ struct ipr_ioa_cfg { | |||
1536 | u8 saved_mode_page_len; | 1543 | u8 saved_mode_page_len; |
1537 | 1544 | ||
1538 | struct work_struct work_q; | 1545 | struct work_struct work_q; |
1546 | struct workqueue_struct *reset_work_q; | ||
1539 | 1547 | ||
1540 | wait_queue_head_t reset_wait_q; | 1548 | wait_queue_head_t reset_wait_q; |
1541 | wait_queue_head_t msi_wait_q; | 1549 | wait_queue_head_t msi_wait_q; |
@@ -1587,6 +1595,7 @@ struct ipr_cmnd { | |||
1587 | struct ata_queued_cmd *qc; | 1595 | struct ata_queued_cmd *qc; |
1588 | struct completion completion; | 1596 | struct completion completion; |
1589 | struct timer_list timer; | 1597 | struct timer_list timer; |
1598 | struct work_struct work; | ||
1590 | void (*fast_done) (struct ipr_cmnd *); | 1599 | void (*fast_done) (struct ipr_cmnd *); |
1591 | void (*done) (struct ipr_cmnd *); | 1600 | void (*done) (struct ipr_cmnd *); |
1592 | int (*job_step) (struct ipr_cmnd *); | 1601 | int (*job_step) (struct ipr_cmnd *); |
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h index 434e9037908e..9b81a34d7449 100644 --- a/drivers/scsi/lpfc/lpfc.h +++ b/drivers/scsi/lpfc/lpfc.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -413,6 +413,9 @@ struct lpfc_vport { | |||
413 | uint32_t cfg_fcp_class; | 413 | uint32_t cfg_fcp_class; |
414 | uint32_t cfg_use_adisc; | 414 | uint32_t cfg_use_adisc; |
415 | uint32_t cfg_fdmi_on; | 415 | uint32_t cfg_fdmi_on; |
416 | #define LPFC_FDMI_SUPPORT 1 /* bit 0 - FDMI supported? */ | ||
417 | #define LPFC_FDMI_REG_DELAY 2 /* bit 1 - 60 sec registration delay */ | ||
418 | #define LPFC_FDMI_ALL_ATTRIB 4 /* bit 2 - register ALL attributes? */ | ||
416 | uint32_t cfg_discovery_threads; | 419 | uint32_t cfg_discovery_threads; |
417 | uint32_t cfg_log_verbose; | 420 | uint32_t cfg_log_verbose; |
418 | uint32_t cfg_max_luns; | 421 | uint32_t cfg_max_luns; |
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 2f9b96826ac0..d65bd178d131 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -406,8 +406,13 @@ lpfc_option_rom_version_show(struct device *dev, struct device_attribute *attr, | |||
406 | struct Scsi_Host *shost = class_to_shost(dev); | 406 | struct Scsi_Host *shost = class_to_shost(dev); |
407 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | 407 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; |
408 | struct lpfc_hba *phba = vport->phba; | 408 | struct lpfc_hba *phba = vport->phba; |
409 | char fwrev[FW_REV_STR_SIZE]; | ||
410 | |||
411 | if (phba->sli_rev < LPFC_SLI_REV4) | ||
412 | return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion); | ||
409 | 413 | ||
410 | return snprintf(buf, PAGE_SIZE, "%s\n", phba->OptionROMVersion); | 414 | lpfc_decode_firmware_rev(phba, fwrev, 1); |
415 | return snprintf(buf, PAGE_SIZE, "%s\n", fwrev); | ||
411 | } | 416 | } |
412 | 417 | ||
413 | /** | 418 | /** |
@@ -4568,12 +4573,18 @@ LPFC_ATTR_R(multi_ring_type, FC_TYPE_IP, 1, | |||
4568 | 4573 | ||
4569 | /* | 4574 | /* |
4570 | # lpfc_fdmi_on: controls FDMI support. | 4575 | # lpfc_fdmi_on: controls FDMI support. |
4571 | # 0 = no FDMI support | 4576 | # Set NOT Set |
4572 | # 1 = support FDMI without attribute of hostname | 4577 | # bit 0 = FDMI support no FDMI support |
4573 | # 2 = support FDMI with attribute of hostname | 4578 | # LPFC_FDMI_SUPPORT just turns basic support on/off |
4574 | # Value range [0,2]. Default value is 0. | 4579 | # bit 1 = Register delay no register delay (60 seconds) |
4580 | # LPFC_FDMI_REG_DELAY 60 sec registration delay after FDMI login | ||
4581 | # bit 2 = All attributes Use a attribute subset | ||
4582 | # LPFC_FDMI_ALL_ATTRIB applies to both port and HBA attributes | ||
4583 | # Port attrutes subset: 1 thru 6 OR all: 1 thru 0xd 0x101 0x102 0x103 | ||
4584 | # HBA attributes subset: 1 thru 0xb OR all: 1 thru 0xc | ||
4585 | # Value range [0,7]. Default value is 0. | ||
4575 | */ | 4586 | */ |
4576 | LPFC_VPORT_ATTR_RW(fdmi_on, 0, 0, 2, "Enable FDMI support"); | 4587 | LPFC_VPORT_ATTR_RW(fdmi_on, 0, 0, 7, "Enable FDMI support"); |
4577 | 4588 | ||
4578 | /* | 4589 | /* |
4579 | # Specifies the maximum number of ELS cmds we can have outstanding (for | 4590 | # Specifies the maximum number of ELS cmds we can have outstanding (for |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c index a7bf359aa0c6..b705068079c0 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.c +++ b/drivers/scsi/lpfc/lpfc_bsg.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2009-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2009-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -3194,6 +3194,7 @@ lpfc_bsg_diag_loopback_run(struct fc_bsg_job *job) | |||
3194 | cmd->unsli3.rcvsli3.ox_id = 0xffff; | 3194 | cmd->unsli3.rcvsli3.ox_id = 0xffff; |
3195 | } | 3195 | } |
3196 | cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; | 3196 | cmdiocbq->iocb_flag |= LPFC_IO_LIBDFC; |
3197 | cmdiocbq->iocb_flag |= LPFC_IO_LOOPBACK; | ||
3197 | cmdiocbq->vport = phba->pport; | 3198 | cmdiocbq->vport = phba->pport; |
3198 | cmdiocbq->iocb_cmpl = NULL; | 3199 | cmdiocbq->iocb_cmpl = NULL; |
3199 | iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, | 3200 | iocb_stat = lpfc_sli_issue_iocb_wait(phba, LPFC_ELS_RING, cmdiocbq, |
@@ -4179,6 +4180,7 @@ lpfc_bsg_handle_sli_cfg_mbox(struct lpfc_hba *phba, struct fc_bsg_job *job, | |||
4179 | switch (opcode) { | 4180 | switch (opcode) { |
4180 | case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES: | 4181 | case COMN_OPCODE_GET_CNTL_ADDL_ATTRIBUTES: |
4181 | case COMN_OPCODE_GET_CNTL_ATTRIBUTES: | 4182 | case COMN_OPCODE_GET_CNTL_ATTRIBUTES: |
4183 | case COMN_OPCODE_GET_PROFILE_CONFIG: | ||
4182 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, | 4184 | lpfc_printf_log(phba, KERN_INFO, LOG_LIBDFC, |
4183 | "3106 Handled SLI_CONFIG " | 4185 | "3106 Handled SLI_CONFIG " |
4184 | "subsys_comn, opcode:x%x\n", | 4186 | "subsys_comn, opcode:x%x\n", |
diff --git a/drivers/scsi/lpfc/lpfc_bsg.h b/drivers/scsi/lpfc/lpfc_bsg.h index 928ef609f363..e557bcdbcb19 100644 --- a/drivers/scsi/lpfc/lpfc_bsg.h +++ b/drivers/scsi/lpfc/lpfc_bsg.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2010-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2010-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -246,6 +246,7 @@ struct lpfc_sli_config_emb1_subsys { | |||
246 | #define lpfc_emb1_subcmnd_subsys_WORD word6 | 246 | #define lpfc_emb1_subcmnd_subsys_WORD word6 |
247 | /* Subsystem COMN (0x01) OpCodes */ | 247 | /* Subsystem COMN (0x01) OpCodes */ |
248 | #define SLI_CONFIG_SUBSYS_COMN 0x01 | 248 | #define SLI_CONFIG_SUBSYS_COMN 0x01 |
249 | #define COMN_OPCODE_GET_PROFILE_CONFIG 0xA4 | ||
249 | #define COMN_OPCODE_READ_OBJECT 0xAB | 250 | #define COMN_OPCODE_READ_OBJECT 0xAB |
250 | #define COMN_OPCODE_WRITE_OBJECT 0xAC | 251 | #define COMN_OPCODE_WRITE_OBJECT 0xAC |
251 | #define COMN_OPCODE_READ_OBJECT_LIST 0xAD | 252 | #define COMN_OPCODE_READ_OBJECT_LIST 0xAD |
diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 00665a5d92fd..587e3e962f2b 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -284,6 +284,7 @@ void lpfc_sli_handle_slow_ring_event(struct lpfc_hba *, | |||
284 | struct lpfc_sli_ring *, uint32_t); | 284 | struct lpfc_sli_ring *, uint32_t); |
285 | void lpfc_sli4_handle_received_buffer(struct lpfc_hba *, struct hbq_dmabuf *); | 285 | void lpfc_sli4_handle_received_buffer(struct lpfc_hba *, struct hbq_dmabuf *); |
286 | void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); | 286 | void lpfc_sli_def_mbox_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); |
287 | void lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *, LPFC_MBOXQ_t *); | ||
287 | int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, | 288 | int lpfc_sli_issue_iocb(struct lpfc_hba *, uint32_t, |
288 | struct lpfc_iocbq *, uint32_t); | 289 | struct lpfc_iocbq *, uint32_t); |
289 | void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); | 290 | void lpfc_sli_pcimem_bcopy(void *, void *, uint32_t); |
@@ -354,6 +355,7 @@ void lpfc_free_sysfs_attr(struct lpfc_vport *); | |||
354 | extern struct device_attribute *lpfc_hba_attrs[]; | 355 | extern struct device_attribute *lpfc_hba_attrs[]; |
355 | extern struct device_attribute *lpfc_vport_attrs[]; | 356 | extern struct device_attribute *lpfc_vport_attrs[]; |
356 | extern struct scsi_host_template lpfc_template; | 357 | extern struct scsi_host_template lpfc_template; |
358 | extern struct scsi_host_template lpfc_template_s3; | ||
357 | extern struct scsi_host_template lpfc_vport_template; | 359 | extern struct scsi_host_template lpfc_vport_template; |
358 | extern struct fc_function_template lpfc_transport_functions; | 360 | extern struct fc_function_template lpfc_transport_functions; |
359 | extern struct fc_function_template lpfc_vport_transport_functions; | 361 | extern struct fc_function_template lpfc_vport_transport_functions; |
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 61a32cd23f79..af129966bd11 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2013 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -555,7 +555,7 @@ lpfc_ns_rsp(struct lpfc_vport *vport, struct lpfc_dmabuf *mp, uint32_t Size) | |||
555 | } | 555 | } |
556 | } | 556 | } |
557 | } | 557 | } |
558 | if (CTentry & (be32_to_cpu(SLI_CT_LAST_ENTRY))) | 558 | if (CTentry & (cpu_to_be32(SLI_CT_LAST_ENTRY))) |
559 | goto nsout1; | 559 | goto nsout1; |
560 | Cnt -= sizeof (uint32_t); | 560 | Cnt -= sizeof (uint32_t); |
561 | } | 561 | } |
@@ -641,7 +641,7 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
641 | /* Good status, continue checking */ | 641 | /* Good status, continue checking */ |
642 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; | 642 | CTrsp = (struct lpfc_sli_ct_request *) outp->virt; |
643 | if (CTrsp->CommandResponse.bits.CmdRsp == | 643 | if (CTrsp->CommandResponse.bits.CmdRsp == |
644 | be16_to_cpu(SLI_CT_RESPONSE_FS_ACC)) { | 644 | cpu_to_be16(SLI_CT_RESPONSE_FS_ACC)) { |
645 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 645 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
646 | "0208 NameServer Rsp Data: x%x\n", | 646 | "0208 NameServer Rsp Data: x%x\n", |
647 | vport->fc_flag); | 647 | vport->fc_flag); |
@@ -1074,11 +1074,48 @@ lpfc_vport_symbolic_node_name(struct lpfc_vport *vport, char *symbol, | |||
1074 | 1074 | ||
1075 | lpfc_decode_firmware_rev(vport->phba, fwrev, 0); | 1075 | lpfc_decode_firmware_rev(vport->phba, fwrev, 0); |
1076 | 1076 | ||
1077 | n = snprintf(symbol, size, "Emulex %s FV%s DV%s", | 1077 | n = snprintf(symbol, size, "Emulex %s", vport->phba->ModelName); |
1078 | vport->phba->ModelName, fwrev, lpfc_release_version); | 1078 | |
1079 | if (size < n) | ||
1080 | return n; | ||
1081 | n += snprintf(symbol + n, size - n, " FV%s", fwrev); | ||
1082 | |||
1083 | if (size < n) | ||
1084 | return n; | ||
1085 | n += snprintf(symbol + n, size - n, " DV%s", lpfc_release_version); | ||
1086 | |||
1087 | if (size < n) | ||
1088 | return n; | ||
1089 | n += snprintf(symbol + n, size - n, " HN:%s", init_utsname()->nodename); | ||
1090 | |||
1091 | /* Note :- OS name is "Linux" */ | ||
1092 | if (size < n) | ||
1093 | return n; | ||
1094 | n += snprintf(symbol + n, size - n, " OS:%s", init_utsname()->sysname); | ||
1095 | |||
1079 | return n; | 1096 | return n; |
1080 | } | 1097 | } |
1081 | 1098 | ||
1099 | static uint32_t | ||
1100 | lpfc_find_map_node(struct lpfc_vport *vport) | ||
1101 | { | ||
1102 | struct lpfc_nodelist *ndlp, *next_ndlp; | ||
1103 | struct Scsi_Host *shost; | ||
1104 | uint32_t cnt = 0; | ||
1105 | |||
1106 | shost = lpfc_shost_from_vport(vport); | ||
1107 | spin_lock_irq(shost->host_lock); | ||
1108 | list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) { | ||
1109 | if (ndlp->nlp_type & NLP_FABRIC) | ||
1110 | continue; | ||
1111 | if ((ndlp->nlp_state == NLP_STE_MAPPED_NODE) || | ||
1112 | (ndlp->nlp_state == NLP_STE_UNMAPPED_NODE)) | ||
1113 | cnt++; | ||
1114 | } | ||
1115 | spin_unlock_irq(shost->host_lock); | ||
1116 | return cnt; | ||
1117 | } | ||
1118 | |||
1082 | /* | 1119 | /* |
1083 | * lpfc_ns_cmd | 1120 | * lpfc_ns_cmd |
1084 | * Description: | 1121 | * Description: |
@@ -1177,7 +1214,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1177 | switch (cmdcode) { | 1214 | switch (cmdcode) { |
1178 | case SLI_CTNS_GID_FT: | 1215 | case SLI_CTNS_GID_FT: |
1179 | CtReq->CommandResponse.bits.CmdRsp = | 1216 | CtReq->CommandResponse.bits.CmdRsp = |
1180 | be16_to_cpu(SLI_CTNS_GID_FT); | 1217 | cpu_to_be16(SLI_CTNS_GID_FT); |
1181 | CtReq->un.gid.Fc4Type = SLI_CTPT_FCP; | 1218 | CtReq->un.gid.Fc4Type = SLI_CTPT_FCP; |
1182 | if (vport->port_state < LPFC_NS_QRY) | 1219 | if (vport->port_state < LPFC_NS_QRY) |
1183 | vport->port_state = LPFC_NS_QRY; | 1220 | vport->port_state = LPFC_NS_QRY; |
@@ -1188,7 +1225,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1188 | 1225 | ||
1189 | case SLI_CTNS_GFF_ID: | 1226 | case SLI_CTNS_GFF_ID: |
1190 | CtReq->CommandResponse.bits.CmdRsp = | 1227 | CtReq->CommandResponse.bits.CmdRsp = |
1191 | be16_to_cpu(SLI_CTNS_GFF_ID); | 1228 | cpu_to_be16(SLI_CTNS_GFF_ID); |
1192 | CtReq->un.gff.PortId = cpu_to_be32(context); | 1229 | CtReq->un.gff.PortId = cpu_to_be32(context); |
1193 | cmpl = lpfc_cmpl_ct_cmd_gff_id; | 1230 | cmpl = lpfc_cmpl_ct_cmd_gff_id; |
1194 | break; | 1231 | break; |
@@ -1196,7 +1233,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1196 | case SLI_CTNS_RFT_ID: | 1233 | case SLI_CTNS_RFT_ID: |
1197 | vport->ct_flags &= ~FC_CT_RFT_ID; | 1234 | vport->ct_flags &= ~FC_CT_RFT_ID; |
1198 | CtReq->CommandResponse.bits.CmdRsp = | 1235 | CtReq->CommandResponse.bits.CmdRsp = |
1199 | be16_to_cpu(SLI_CTNS_RFT_ID); | 1236 | cpu_to_be16(SLI_CTNS_RFT_ID); |
1200 | CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID); | 1237 | CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID); |
1201 | CtReq->un.rft.fcpReg = 1; | 1238 | CtReq->un.rft.fcpReg = 1; |
1202 | cmpl = lpfc_cmpl_ct_cmd_rft_id; | 1239 | cmpl = lpfc_cmpl_ct_cmd_rft_id; |
@@ -1205,7 +1242,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1205 | case SLI_CTNS_RNN_ID: | 1242 | case SLI_CTNS_RNN_ID: |
1206 | vport->ct_flags &= ~FC_CT_RNN_ID; | 1243 | vport->ct_flags &= ~FC_CT_RNN_ID; |
1207 | CtReq->CommandResponse.bits.CmdRsp = | 1244 | CtReq->CommandResponse.bits.CmdRsp = |
1208 | be16_to_cpu(SLI_CTNS_RNN_ID); | 1245 | cpu_to_be16(SLI_CTNS_RNN_ID); |
1209 | CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID); | 1246 | CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID); |
1210 | memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename, | 1247 | memcpy(CtReq->un.rnn.wwnn, &vport->fc_nodename, |
1211 | sizeof (struct lpfc_name)); | 1248 | sizeof (struct lpfc_name)); |
@@ -1215,7 +1252,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1215 | case SLI_CTNS_RSPN_ID: | 1252 | case SLI_CTNS_RSPN_ID: |
1216 | vport->ct_flags &= ~FC_CT_RSPN_ID; | 1253 | vport->ct_flags &= ~FC_CT_RSPN_ID; |
1217 | CtReq->CommandResponse.bits.CmdRsp = | 1254 | CtReq->CommandResponse.bits.CmdRsp = |
1218 | be16_to_cpu(SLI_CTNS_RSPN_ID); | 1255 | cpu_to_be16(SLI_CTNS_RSPN_ID); |
1219 | CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID); | 1256 | CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID); |
1220 | size = sizeof(CtReq->un.rspn.symbname); | 1257 | size = sizeof(CtReq->un.rspn.symbname); |
1221 | CtReq->un.rspn.len = | 1258 | CtReq->un.rspn.len = |
@@ -1226,7 +1263,7 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1226 | case SLI_CTNS_RSNN_NN: | 1263 | case SLI_CTNS_RSNN_NN: |
1227 | vport->ct_flags &= ~FC_CT_RSNN_NN; | 1264 | vport->ct_flags &= ~FC_CT_RSNN_NN; |
1228 | CtReq->CommandResponse.bits.CmdRsp = | 1265 | CtReq->CommandResponse.bits.CmdRsp = |
1229 | be16_to_cpu(SLI_CTNS_RSNN_NN); | 1266 | cpu_to_be16(SLI_CTNS_RSNN_NN); |
1230 | memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename, | 1267 | memcpy(CtReq->un.rsnn.wwnn, &vport->fc_nodename, |
1231 | sizeof (struct lpfc_name)); | 1268 | sizeof (struct lpfc_name)); |
1232 | size = sizeof(CtReq->un.rsnn.symbname); | 1269 | size = sizeof(CtReq->un.rsnn.symbname); |
@@ -1238,14 +1275,14 @@ lpfc_ns_cmd(struct lpfc_vport *vport, int cmdcode, | |||
1238 | case SLI_CTNS_DA_ID: | 1275 | case SLI_CTNS_DA_ID: |
1239 | /* Implement DA_ID Nameserver request */ | 1276 | /* Implement DA_ID Nameserver request */ |
1240 | CtReq->CommandResponse.bits.CmdRsp = | 1277 | CtReq->CommandResponse.bits.CmdRsp = |
1241 | be16_to_cpu(SLI_CTNS_DA_ID); | 1278 | cpu_to_be16(SLI_CTNS_DA_ID); |
1242 | CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID); | 1279 | CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID); |
1243 | cmpl = lpfc_cmpl_ct_cmd_da_id; | 1280 | cmpl = lpfc_cmpl_ct_cmd_da_id; |
1244 | break; | 1281 | break; |
1245 | case SLI_CTNS_RFF_ID: | 1282 | case SLI_CTNS_RFF_ID: |
1246 | vport->ct_flags &= ~FC_CT_RFF_ID; | 1283 | vport->ct_flags &= ~FC_CT_RFF_ID; |
1247 | CtReq->CommandResponse.bits.CmdRsp = | 1284 | CtReq->CommandResponse.bits.CmdRsp = |
1248 | be16_to_cpu(SLI_CTNS_RFF_ID); | 1285 | cpu_to_be16(SLI_CTNS_RFF_ID); |
1249 | CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID); | 1286 | CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID); |
1250 | CtReq->un.rff.fbits = FC4_FEATURE_INIT; | 1287 | CtReq->un.rff.fbits = FC4_FEATURE_INIT; |
1251 | CtReq->un.rff.type_code = FC_TYPE_FCP; | 1288 | CtReq->un.rff.type_code = FC_TYPE_FCP; |
@@ -1299,7 +1336,6 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1299 | uint32_t latt; | 1336 | uint32_t latt; |
1300 | 1337 | ||
1301 | latt = lpfc_els_chk_latt(vport); | 1338 | latt = lpfc_els_chk_latt(vport); |
1302 | |||
1303 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, | 1339 | lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT, |
1304 | "FDMI cmpl: status:x%x/x%x latt:%d", | 1340 | "FDMI cmpl: status:x%x/x%x latt:%d", |
1305 | irsp->ulpStatus, irsp->un.ulpWord[4], latt); | 1341 | irsp->ulpStatus, irsp->un.ulpWord[4], latt); |
@@ -1310,29 +1346,49 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1310 | "ulpStatus: x%x, rid x%x\n", | 1346 | "ulpStatus: x%x, rid x%x\n", |
1311 | be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, | 1347 | be16_to_cpu(fdmi_cmd), latt, irsp->ulpStatus, |
1312 | irsp->un.ulpWord[4]); | 1348 | irsp->un.ulpWord[4]); |
1313 | lpfc_ct_free_iocb(phba, cmdiocb); | 1349 | goto fail_out; |
1314 | return; | ||
1315 | } | 1350 | } |
1316 | 1351 | ||
1317 | ndlp = lpfc_findnode_did(vport, FDMI_DID); | 1352 | ndlp = lpfc_findnode_did(vport, FDMI_DID); |
1318 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) | 1353 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) |
1319 | goto fail_out; | 1354 | goto fail_out; |
1320 | 1355 | ||
1321 | if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) { | 1356 | if (fdmi_rsp == cpu_to_be16(SLI_CT_RESPONSE_FS_RJT)) { |
1322 | /* FDMI rsp failed */ | 1357 | /* FDMI rsp failed */ |
1323 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 1358 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
1324 | "0220 FDMI rsp failed Data: x%x\n", | 1359 | "0220 FDMI rsp failed Data: x%x\n", |
1325 | be16_to_cpu(fdmi_cmd)); | 1360 | be16_to_cpu(fdmi_cmd)); |
1326 | } | 1361 | } |
1327 | 1362 | ||
1363 | fail_out: | ||
1364 | lpfc_ct_free_iocb(phba, cmdiocb); | ||
1365 | } | ||
1366 | |||
1367 | static void | ||
1368 | lpfc_cmpl_ct_disc_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | ||
1369 | struct lpfc_iocbq *rspiocb) | ||
1370 | { | ||
1371 | struct lpfc_vport *vport = cmdiocb->vport; | ||
1372 | struct lpfc_dmabuf *inp = cmdiocb->context1; | ||
1373 | struct lpfc_sli_ct_request *CTcmd = inp->virt; | ||
1374 | uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp; | ||
1375 | struct lpfc_nodelist *ndlp; | ||
1376 | |||
1377 | lpfc_cmpl_ct_cmd_fdmi(phba, cmdiocb, rspiocb); | ||
1378 | |||
1379 | ndlp = lpfc_findnode_did(vport, FDMI_DID); | ||
1380 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) | ||
1381 | return; | ||
1382 | |||
1383 | /* | ||
1384 | * Need to cycle thru FDMI registration for discovery | ||
1385 | * DHBA -> DPRT -> RHBA -> RPA | ||
1386 | */ | ||
1328 | switch (be16_to_cpu(fdmi_cmd)) { | 1387 | switch (be16_to_cpu(fdmi_cmd)) { |
1329 | case SLI_MGMT_RHBA: | 1388 | case SLI_MGMT_RHBA: |
1330 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA); | 1389 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RPA); |
1331 | break; | 1390 | break; |
1332 | 1391 | ||
1333 | case SLI_MGMT_RPA: | ||
1334 | break; | ||
1335 | |||
1336 | case SLI_MGMT_DHBA: | 1392 | case SLI_MGMT_DHBA: |
1337 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT); | 1393 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DPRT); |
1338 | break; | 1394 | break; |
@@ -1341,12 +1397,9 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
1341 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); | 1397 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_RHBA); |
1342 | break; | 1398 | break; |
1343 | } | 1399 | } |
1344 | |||
1345 | fail_out: | ||
1346 | lpfc_ct_free_iocb(phba, cmdiocb); | ||
1347 | return; | ||
1348 | } | 1400 | } |
1349 | 1401 | ||
1402 | |||
1350 | int | 1403 | int |
1351 | lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | 1404 | lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) |
1352 | { | 1405 | { |
@@ -1355,18 +1408,28 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1355 | struct lpfc_sli_ct_request *CtReq; | 1408 | struct lpfc_sli_ct_request *CtReq; |
1356 | struct ulp_bde64 *bpl; | 1409 | struct ulp_bde64 *bpl; |
1357 | uint32_t size; | 1410 | uint32_t size; |
1358 | REG_HBA *rh; | 1411 | uint32_t rsp_size; |
1359 | PORT_ENTRY *pe; | 1412 | struct lpfc_fdmi_reg_hba *rh; |
1360 | REG_PORT_ATTRIBUTE *pab; | 1413 | struct lpfc_fdmi_port_entry *pe; |
1361 | ATTRIBUTE_BLOCK *ab; | 1414 | struct lpfc_fdmi_reg_portattr *pab = NULL; |
1362 | ATTRIBUTE_ENTRY *ae; | 1415 | struct lpfc_fdmi_attr_block *ab = NULL; |
1416 | struct lpfc_fdmi_attr_entry *ae; | ||
1417 | struct lpfc_fdmi_attr_def *ad; | ||
1363 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, | 1418 | void (*cmpl) (struct lpfc_hba *, struct lpfc_iocbq *, |
1364 | struct lpfc_iocbq *); | 1419 | struct lpfc_iocbq *); |
1365 | 1420 | ||
1421 | if (ndlp == NULL) { | ||
1422 | ndlp = lpfc_findnode_did(vport, FDMI_DID); | ||
1423 | if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) | ||
1424 | return 0; | ||
1425 | cmpl = lpfc_cmpl_ct_cmd_fdmi; /* cmd interface */ | ||
1426 | } else { | ||
1427 | cmpl = lpfc_cmpl_ct_disc_fdmi; /* called from discovery */ | ||
1428 | } | ||
1366 | 1429 | ||
1367 | /* fill in BDEs for command */ | 1430 | /* fill in BDEs for command */ |
1368 | /* Allocate buffer for command payload */ | 1431 | /* Allocate buffer for command payload */ |
1369 | mp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); | 1432 | mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
1370 | if (!mp) | 1433 | if (!mp) |
1371 | goto fdmi_cmd_exit; | 1434 | goto fdmi_cmd_exit; |
1372 | 1435 | ||
@@ -1375,7 +1438,7 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1375 | goto fdmi_cmd_free_mp; | 1438 | goto fdmi_cmd_free_mp; |
1376 | 1439 | ||
1377 | /* Allocate buffer for Buffer ptr list */ | 1440 | /* Allocate buffer for Buffer ptr list */ |
1378 | bmp = kmalloc(sizeof (struct lpfc_dmabuf), GFP_KERNEL); | 1441 | bmp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL); |
1379 | if (!bmp) | 1442 | if (!bmp) |
1380 | goto fdmi_cmd_free_mpvirt; | 1443 | goto fdmi_cmd_free_mpvirt; |
1381 | 1444 | ||
@@ -1390,205 +1453,330 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1390 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, | 1453 | lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, |
1391 | "0218 FDMI Request Data: x%x x%x x%x\n", | 1454 | "0218 FDMI Request Data: x%x x%x x%x\n", |
1392 | vport->fc_flag, vport->port_state, cmdcode); | 1455 | vport->fc_flag, vport->port_state, cmdcode); |
1393 | CtReq = (struct lpfc_sli_ct_request *) mp->virt; | 1456 | CtReq = (struct lpfc_sli_ct_request *)mp->virt; |
1394 | 1457 | ||
1458 | /* First populate the CT_IU preamble */ | ||
1395 | memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request)); | 1459 | memset(CtReq, 0, sizeof(struct lpfc_sli_ct_request)); |
1396 | CtReq->RevisionId.bits.Revision = SLI_CT_REVISION; | 1460 | CtReq->RevisionId.bits.Revision = SLI_CT_REVISION; |
1397 | CtReq->RevisionId.bits.InId = 0; | 1461 | CtReq->RevisionId.bits.InId = 0; |
1398 | 1462 | ||
1399 | CtReq->FsType = SLI_CT_MANAGEMENT_SERVICE; | 1463 | CtReq->FsType = SLI_CT_MANAGEMENT_SERVICE; |
1400 | CtReq->FsSubType = SLI_CT_FDMI_Subtypes; | 1464 | CtReq->FsSubType = SLI_CT_FDMI_Subtypes; |
1465 | |||
1466 | CtReq->CommandResponse.bits.CmdRsp = cpu_to_be16(cmdcode); | ||
1467 | rsp_size = LPFC_BPL_SIZE; | ||
1401 | size = 0; | 1468 | size = 0; |
1402 | 1469 | ||
1470 | /* Next fill in the specific FDMI cmd information */ | ||
1403 | switch (cmdcode) { | 1471 | switch (cmdcode) { |
1472 | case SLI_MGMT_RHAT: | ||
1404 | case SLI_MGMT_RHBA: | 1473 | case SLI_MGMT_RHBA: |
1405 | { | 1474 | { |
1406 | lpfc_vpd_t *vp = &phba->vpd; | 1475 | lpfc_vpd_t *vp = &phba->vpd; |
1407 | uint32_t i, j, incr; | 1476 | uint32_t i, j, incr; |
1408 | int len; | 1477 | int len = 0; |
1409 | 1478 | ||
1410 | CtReq->CommandResponse.bits.CmdRsp = | 1479 | rh = (struct lpfc_fdmi_reg_hba *)&CtReq->un.PortID; |
1411 | be16_to_cpu(SLI_MGMT_RHBA); | 1480 | /* HBA Identifier */ |
1412 | CtReq->CommandResponse.bits.Size = 0; | ||
1413 | rh = (REG_HBA *) & CtReq->un.PortID; | ||
1414 | memcpy(&rh->hi.PortName, &vport->fc_sparam.portName, | 1481 | memcpy(&rh->hi.PortName, &vport->fc_sparam.portName, |
1415 | sizeof (struct lpfc_name)); | 1482 | sizeof(struct lpfc_name)); |
1416 | /* One entry (port) per adapter */ | 1483 | |
1417 | rh->rpl.EntryCnt = be32_to_cpu(1); | 1484 | if (cmdcode == SLI_MGMT_RHBA) { |
1418 | memcpy(&rh->rpl.pe, &vport->fc_sparam.portName, | 1485 | /* Registered Port List */ |
1419 | sizeof (struct lpfc_name)); | 1486 | /* One entry (port) per adapter */ |
1420 | 1487 | rh->rpl.EntryCnt = cpu_to_be32(1); | |
1421 | /* point to the HBA attribute block */ | 1488 | memcpy(&rh->rpl.pe, &vport->fc_sparam.portName, |
1422 | size = 2 * sizeof (struct lpfc_name) + FOURBYTES; | 1489 | sizeof(struct lpfc_name)); |
1423 | ab = (ATTRIBUTE_BLOCK *) ((uint8_t *) rh + size); | 1490 | |
1491 | /* point to the HBA attribute block */ | ||
1492 | size = 2 * sizeof(struct lpfc_name) + | ||
1493 | FOURBYTES; | ||
1494 | } else { | ||
1495 | size = sizeof(struct lpfc_name); | ||
1496 | } | ||
1497 | ab = (struct lpfc_fdmi_attr_block *) | ||
1498 | ((uint8_t *)rh + size); | ||
1424 | ab->EntryCnt = 0; | 1499 | ab->EntryCnt = 0; |
1500 | size += FOURBYTES; | ||
1425 | 1501 | ||
1426 | /* Point to the beginning of the first HBA attribute | 1502 | /* |
1427 | entry */ | 1503 | * Point to beginning of first HBA attribute entry |
1504 | */ | ||
1428 | /* #1 HBA attribute entry */ | 1505 | /* #1 HBA attribute entry */ |
1429 | size += FOURBYTES; | 1506 | ad = (struct lpfc_fdmi_attr_def *) |
1430 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1507 | ((uint8_t *)rh + size); |
1431 | ae->ad.bits.AttrType = be16_to_cpu(NODE_NAME); | 1508 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1432 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES | 1509 | memset(ae, 0, sizeof(struct lpfc_name)); |
1433 | + sizeof (struct lpfc_name)); | 1510 | ad->AttrType = cpu_to_be16(RHBA_NODENAME); |
1511 | ad->AttrLen = cpu_to_be16(FOURBYTES | ||
1512 | + sizeof(struct lpfc_name)); | ||
1434 | memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName, | 1513 | memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName, |
1435 | sizeof (struct lpfc_name)); | 1514 | sizeof(struct lpfc_name)); |
1436 | ab->EntryCnt++; | 1515 | ab->EntryCnt++; |
1437 | size += FOURBYTES + sizeof (struct lpfc_name); | 1516 | size += FOURBYTES + sizeof(struct lpfc_name); |
1517 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1518 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1519 | goto hba_out; | ||
1438 | 1520 | ||
1439 | /* #2 HBA attribute entry */ | 1521 | /* #2 HBA attribute entry */ |
1440 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1522 | ad = (struct lpfc_fdmi_attr_def *) |
1441 | ae->ad.bits.AttrType = be16_to_cpu(MANUFACTURER); | 1523 | ((uint8_t *)rh + size); |
1442 | strncpy(ae->un.Manufacturer, "Emulex Corporation", 64); | 1524 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1443 | len = strlen(ae->un.Manufacturer); | 1525 | memset(ae, 0, sizeof(ae->un.Manufacturer)); |
1526 | ad->AttrType = cpu_to_be16(RHBA_MANUFACTURER); | ||
1527 | strncpy(ae->un.Manufacturer, "Emulex Corporation", | ||
1528 | sizeof(ae->un.Manufacturer)); | ||
1529 | len = strnlen(ae->un.Manufacturer, | ||
1530 | sizeof(ae->un.Manufacturer)); | ||
1444 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1531 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1445 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1532 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1446 | ab->EntryCnt++; | 1533 | ab->EntryCnt++; |
1447 | size += FOURBYTES + len; | 1534 | size += FOURBYTES + len; |
1535 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1536 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1537 | goto hba_out; | ||
1448 | 1538 | ||
1449 | /* #3 HBA attribute entry */ | 1539 | /* #3 HBA attribute entry */ |
1450 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1540 | ad = (struct lpfc_fdmi_attr_def *) |
1451 | ae->ad.bits.AttrType = be16_to_cpu(SERIAL_NUMBER); | 1541 | ((uint8_t *)rh + size); |
1452 | strncpy(ae->un.SerialNumber, phba->SerialNumber, 64); | 1542 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1453 | len = strlen(ae->un.SerialNumber); | 1543 | memset(ae, 0, sizeof(ae->un.SerialNumber)); |
1544 | ad->AttrType = cpu_to_be16(RHBA_SERIAL_NUMBER); | ||
1545 | strncpy(ae->un.SerialNumber, phba->SerialNumber, | ||
1546 | sizeof(ae->un.SerialNumber)); | ||
1547 | len = strnlen(ae->un.SerialNumber, | ||
1548 | sizeof(ae->un.SerialNumber)); | ||
1454 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1549 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1455 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1550 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1456 | ab->EntryCnt++; | 1551 | ab->EntryCnt++; |
1457 | size += FOURBYTES + len; | 1552 | size += FOURBYTES + len; |
1553 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1554 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1555 | goto hba_out; | ||
1458 | 1556 | ||
1459 | /* #4 HBA attribute entry */ | 1557 | /* #4 HBA attribute entry */ |
1460 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1558 | ad = (struct lpfc_fdmi_attr_def *) |
1461 | ae->ad.bits.AttrType = be16_to_cpu(MODEL); | 1559 | ((uint8_t *)rh + size); |
1462 | strncpy(ae->un.Model, phba->ModelName, 256); | 1560 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1463 | len = strlen(ae->un.Model); | 1561 | memset(ae, 0, sizeof(ae->un.Model)); |
1562 | ad->AttrType = cpu_to_be16(RHBA_MODEL); | ||
1563 | strncpy(ae->un.Model, phba->ModelName, | ||
1564 | sizeof(ae->un.Model)); | ||
1565 | len = strnlen(ae->un.Model, sizeof(ae->un.Model)); | ||
1464 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1566 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1465 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1567 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1466 | ab->EntryCnt++; | 1568 | ab->EntryCnt++; |
1467 | size += FOURBYTES + len; | 1569 | size += FOURBYTES + len; |
1570 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1571 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1572 | goto hba_out; | ||
1468 | 1573 | ||
1469 | /* #5 HBA attribute entry */ | 1574 | /* #5 HBA attribute entry */ |
1470 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1575 | ad = (struct lpfc_fdmi_attr_def *) |
1471 | ae->ad.bits.AttrType = be16_to_cpu(MODEL_DESCRIPTION); | 1576 | ((uint8_t *)rh + size); |
1472 | strncpy(ae->un.ModelDescription, phba->ModelDesc, 256); | 1577 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1473 | len = strlen(ae->un.ModelDescription); | 1578 | memset(ae, 0, sizeof(ae->un.ModelDescription)); |
1579 | ad->AttrType = cpu_to_be16(RHBA_MODEL_DESCRIPTION); | ||
1580 | strncpy(ae->un.ModelDescription, phba->ModelDesc, | ||
1581 | sizeof(ae->un.ModelDescription)); | ||
1582 | len = strnlen(ae->un.ModelDescription, | ||
1583 | sizeof(ae->un.ModelDescription)); | ||
1474 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1584 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1475 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1585 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1476 | ab->EntryCnt++; | 1586 | ab->EntryCnt++; |
1477 | size += FOURBYTES + len; | 1587 | size += FOURBYTES + len; |
1588 | if ((size + 8) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1589 | goto hba_out; | ||
1478 | 1590 | ||
1479 | /* #6 HBA attribute entry */ | 1591 | /* #6 HBA attribute entry */ |
1480 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1592 | ad = (struct lpfc_fdmi_attr_def *) |
1481 | ae->ad.bits.AttrType = be16_to_cpu(HARDWARE_VERSION); | 1593 | ((uint8_t *)rh + size); |
1482 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 8); | 1594 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1595 | memset(ae, 0, 8); | ||
1596 | ad->AttrType = cpu_to_be16(RHBA_HARDWARE_VERSION); | ||
1597 | ad->AttrLen = cpu_to_be16(FOURBYTES + 8); | ||
1483 | /* Convert JEDEC ID to ascii for hardware version */ | 1598 | /* Convert JEDEC ID to ascii for hardware version */ |
1484 | incr = vp->rev.biuRev; | 1599 | incr = vp->rev.biuRev; |
1485 | for (i = 0; i < 8; i++) { | 1600 | for (i = 0; i < 8; i++) { |
1486 | j = (incr & 0xf); | 1601 | j = (incr & 0xf); |
1487 | if (j <= 9) | 1602 | if (j <= 9) |
1488 | ae->un.HardwareVersion[7 - i] = | 1603 | ae->un.HardwareVersion[7 - i] = |
1489 | (char)((uint8_t) 0x30 + | 1604 | (char)((uint8_t)0x30 + |
1490 | (uint8_t) j); | 1605 | (uint8_t)j); |
1491 | else | 1606 | else |
1492 | ae->un.HardwareVersion[7 - i] = | 1607 | ae->un.HardwareVersion[7 - i] = |
1493 | (char)((uint8_t) 0x61 + | 1608 | (char)((uint8_t)0x61 + |
1494 | (uint8_t) (j - 10)); | 1609 | (uint8_t)(j - 10)); |
1495 | incr = (incr >> 4); | 1610 | incr = (incr >> 4); |
1496 | } | 1611 | } |
1497 | ab->EntryCnt++; | 1612 | ab->EntryCnt++; |
1498 | size += FOURBYTES + 8; | 1613 | size += FOURBYTES + 8; |
1614 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1615 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1616 | goto hba_out; | ||
1499 | 1617 | ||
1500 | /* #7 HBA attribute entry */ | 1618 | /* #7 HBA attribute entry */ |
1501 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1619 | ad = (struct lpfc_fdmi_attr_def *) |
1502 | ae->ad.bits.AttrType = be16_to_cpu(DRIVER_VERSION); | 1620 | ((uint8_t *)rh + size); |
1503 | strncpy(ae->un.DriverVersion, | 1621 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1504 | lpfc_release_version, 256); | 1622 | memset(ae, 0, sizeof(ae->un.DriverVersion)); |
1505 | len = strlen(ae->un.DriverVersion); | 1623 | ad->AttrType = cpu_to_be16(RHBA_DRIVER_VERSION); |
1624 | strncpy(ae->un.DriverVersion, lpfc_release_version, | ||
1625 | sizeof(ae->un.DriverVersion)); | ||
1626 | len = strnlen(ae->un.DriverVersion, | ||
1627 | sizeof(ae->un.DriverVersion)); | ||
1506 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1628 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1507 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1629 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1508 | ab->EntryCnt++; | 1630 | ab->EntryCnt++; |
1509 | size += FOURBYTES + len; | 1631 | size += FOURBYTES + len; |
1632 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1633 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1634 | goto hba_out; | ||
1510 | 1635 | ||
1511 | /* #8 HBA attribute entry */ | 1636 | /* #8 HBA attribute entry */ |
1512 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1637 | ad = (struct lpfc_fdmi_attr_def *) |
1513 | ae->ad.bits.AttrType = be16_to_cpu(OPTION_ROM_VERSION); | 1638 | ((uint8_t *)rh + size); |
1514 | strncpy(ae->un.OptionROMVersion, | 1639 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1515 | phba->OptionROMVersion, 256); | 1640 | memset(ae, 0, sizeof(ae->un.OptionROMVersion)); |
1516 | len = strlen(ae->un.OptionROMVersion); | 1641 | ad->AttrType = cpu_to_be16(RHBA_OPTION_ROM_VERSION); |
1642 | strncpy(ae->un.OptionROMVersion, phba->OptionROMVersion, | ||
1643 | sizeof(ae->un.OptionROMVersion)); | ||
1644 | len = strnlen(ae->un.OptionROMVersion, | ||
1645 | sizeof(ae->un.OptionROMVersion)); | ||
1517 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1646 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1518 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1647 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1519 | ab->EntryCnt++; | 1648 | ab->EntryCnt++; |
1520 | size += FOURBYTES + len; | 1649 | size += FOURBYTES + len; |
1650 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1651 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1652 | goto hba_out; | ||
1521 | 1653 | ||
1522 | /* #9 HBA attribute entry */ | 1654 | /* #9 HBA attribute entry */ |
1523 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1655 | ad = (struct lpfc_fdmi_attr_def *) |
1524 | ae->ad.bits.AttrType = be16_to_cpu(FIRMWARE_VERSION); | 1656 | ((uint8_t *)rh + size); |
1657 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1658 | memset(ae, 0, sizeof(ae->un.FirmwareVersion)); | ||
1659 | ad->AttrType = cpu_to_be16(RHBA_FIRMWARE_VERSION); | ||
1525 | lpfc_decode_firmware_rev(phba, ae->un.FirmwareVersion, | 1660 | lpfc_decode_firmware_rev(phba, ae->un.FirmwareVersion, |
1526 | 1); | 1661 | 1); |
1527 | len = strlen(ae->un.FirmwareVersion); | 1662 | len = strnlen(ae->un.FirmwareVersion, |
1663 | sizeof(ae->un.FirmwareVersion)); | ||
1528 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1664 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1529 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1665 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1530 | ab->EntryCnt++; | 1666 | ab->EntryCnt++; |
1531 | size += FOURBYTES + len; | 1667 | size += FOURBYTES + len; |
1668 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1669 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1670 | goto hba_out; | ||
1532 | 1671 | ||
1533 | /* #10 HBA attribute entry */ | 1672 | /* #10 HBA attribute entry */ |
1534 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1673 | ad = (struct lpfc_fdmi_attr_def *) |
1535 | ae->ad.bits.AttrType = be16_to_cpu(OS_NAME_VERSION); | 1674 | ((uint8_t *)rh + size); |
1536 | sprintf(ae->un.OsNameVersion, "%s %s %s", | 1675 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1537 | init_utsname()->sysname, | 1676 | memset(ae, 0, sizeof(ae->un.OsNameVersion)); |
1538 | init_utsname()->release, | 1677 | ad->AttrType = cpu_to_be16(RHBA_OS_NAME_VERSION); |
1539 | init_utsname()->version); | 1678 | snprintf(ae->un.OsNameVersion, |
1540 | len = strlen(ae->un.OsNameVersion); | 1679 | sizeof(ae->un.OsNameVersion), |
1680 | "%s %s %s", | ||
1681 | init_utsname()->sysname, | ||
1682 | init_utsname()->release, | ||
1683 | init_utsname()->version); | ||
1684 | len = strnlen(ae->un.OsNameVersion, | ||
1685 | sizeof(ae->un.OsNameVersion)); | ||
1541 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1686 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1542 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1687 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1543 | ab->EntryCnt++; | 1688 | ab->EntryCnt++; |
1544 | size += FOURBYTES + len; | 1689 | size += FOURBYTES + len; |
1690 | if ((size + 4) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1691 | goto hba_out; | ||
1545 | 1692 | ||
1546 | /* #11 HBA attribute entry */ | 1693 | /* #11 HBA attribute entry */ |
1547 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size); | 1694 | ad = (struct lpfc_fdmi_attr_def *) |
1548 | ae->ad.bits.AttrType = be16_to_cpu(MAX_CT_PAYLOAD_LEN); | 1695 | ((uint8_t *)rh + size); |
1549 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); | 1696 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1550 | ae->un.MaxCTPayloadLen = (65 * 4096); | 1697 | ad->AttrType = |
1698 | cpu_to_be16(RHBA_MAX_CT_PAYLOAD_LEN); | ||
1699 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
1700 | ae->un.MaxCTPayloadLen = cpu_to_be32(LPFC_MAX_CT_SIZE); | ||
1551 | ab->EntryCnt++; | 1701 | ab->EntryCnt++; |
1552 | size += FOURBYTES + 4; | 1702 | size += FOURBYTES + 4; |
1703 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1704 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1705 | goto hba_out; | ||
1553 | 1706 | ||
1554 | ab->EntryCnt = be32_to_cpu(ab->EntryCnt); | 1707 | /* |
1708 | * Currently switches don't seem to support the | ||
1709 | * following extended HBA attributes. | ||
1710 | */ | ||
1711 | if (!(vport->cfg_fdmi_on & LPFC_FDMI_ALL_ATTRIB)) | ||
1712 | goto hba_out; | ||
1713 | |||
1714 | /* #12 HBA attribute entry */ | ||
1715 | ad = (struct lpfc_fdmi_attr_def *) | ||
1716 | ((uint8_t *)rh + size); | ||
1717 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1718 | memset(ae, 0, sizeof(ae->un.NodeSymName)); | ||
1719 | ad->AttrType = cpu_to_be16(RHBA_SYM_NODENAME); | ||
1720 | len = lpfc_vport_symbolic_node_name(vport, | ||
1721 | ae->un.NodeSymName, sizeof(ae->un.NodeSymName)); | ||
1722 | len += (len & 3) ? (4 - (len & 3)) : 4; | ||
1723 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); | ||
1724 | ab->EntryCnt++; | ||
1725 | size += FOURBYTES + len; | ||
1726 | hba_out: | ||
1727 | ab->EntryCnt = cpu_to_be32(ab->EntryCnt); | ||
1555 | /* Total size */ | 1728 | /* Total size */ |
1556 | size = GID_REQUEST_SZ - 4 + size; | 1729 | size = GID_REQUEST_SZ - 4 + size; |
1557 | } | 1730 | } |
1558 | break; | 1731 | break; |
1559 | 1732 | ||
1733 | case SLI_MGMT_RPRT: | ||
1560 | case SLI_MGMT_RPA: | 1734 | case SLI_MGMT_RPA: |
1561 | { | 1735 | { |
1562 | lpfc_vpd_t *vp; | 1736 | lpfc_vpd_t *vp; |
1563 | struct serv_parm *hsp; | 1737 | struct serv_parm *hsp; |
1564 | int len; | 1738 | int len = 0; |
1565 | 1739 | ||
1566 | vp = &phba->vpd; | 1740 | vp = &phba->vpd; |
1567 | 1741 | ||
1568 | CtReq->CommandResponse.bits.CmdRsp = | 1742 | if (cmdcode == SLI_MGMT_RPRT) { |
1569 | be16_to_cpu(SLI_MGMT_RPA); | 1743 | rh = (struct lpfc_fdmi_reg_hba *) |
1570 | CtReq->CommandResponse.bits.Size = 0; | 1744 | &CtReq->un.PortID; |
1571 | pab = (REG_PORT_ATTRIBUTE *) & CtReq->un.PortID; | 1745 | /* HBA Identifier */ |
1572 | size = sizeof (struct lpfc_name) + FOURBYTES; | 1746 | memcpy(&rh->hi.PortName, |
1573 | memcpy((uint8_t *) & pab->PortName, | 1747 | &vport->fc_sparam.portName, |
1574 | (uint8_t *) & vport->fc_sparam.portName, | 1748 | sizeof(struct lpfc_name)); |
1575 | sizeof (struct lpfc_name)); | 1749 | pab = (struct lpfc_fdmi_reg_portattr *) |
1750 | &rh->rpl.EntryCnt; | ||
1751 | } else | ||
1752 | pab = (struct lpfc_fdmi_reg_portattr *) | ||
1753 | &CtReq->un.PortID; | ||
1754 | size = sizeof(struct lpfc_name) + FOURBYTES; | ||
1755 | memcpy((uint8_t *)&pab->PortName, | ||
1756 | (uint8_t *)&vport->fc_sparam.portName, | ||
1757 | sizeof(struct lpfc_name)); | ||
1576 | pab->ab.EntryCnt = 0; | 1758 | pab->ab.EntryCnt = 0; |
1577 | 1759 | ||
1578 | /* #1 Port attribute entry */ | 1760 | /* #1 Port attribute entry */ |
1579 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); | 1761 | ad = (struct lpfc_fdmi_attr_def *) |
1580 | ae->ad.bits.AttrType = be16_to_cpu(SUPPORTED_FC4_TYPES); | 1762 | ((uint8_t *)pab + size); |
1581 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 32); | 1763 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1582 | ae->un.SupportFC4Types[2] = 1; | 1764 | memset(ae, 0, sizeof(ae->un.FC4Types)); |
1583 | ae->un.SupportFC4Types[7] = 1; | 1765 | ad->AttrType = |
1766 | cpu_to_be16(RPRT_SUPPORTED_FC4_TYPES); | ||
1767 | ad->AttrLen = cpu_to_be16(FOURBYTES + 32); | ||
1768 | ae->un.FC4Types[0] = 0x40; /* Type 1 - ELS */ | ||
1769 | ae->un.FC4Types[1] = 0x80; /* Type 8 - FCP */ | ||
1770 | ae->un.FC4Types[4] = 0x80; /* Type 32 - CT */ | ||
1584 | pab->ab.EntryCnt++; | 1771 | pab->ab.EntryCnt++; |
1585 | size += FOURBYTES + 32; | 1772 | size += FOURBYTES + 32; |
1586 | 1773 | ||
1587 | /* #2 Port attribute entry */ | 1774 | /* #2 Port attribute entry */ |
1588 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); | 1775 | ad = (struct lpfc_fdmi_attr_def *) |
1589 | ae->ad.bits.AttrType = be16_to_cpu(SUPPORTED_SPEED); | 1776 | ((uint8_t *)pab + size); |
1590 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); | 1777 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1591 | 1778 | ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_SPEED); | |
1779 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
1592 | ae->un.SupportSpeed = 0; | 1780 | ae->un.SupportSpeed = 0; |
1593 | if (phba->lmt & LMT_16Gb) | 1781 | if (phba->lmt & LMT_16Gb) |
1594 | ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT; | 1782 | ae->un.SupportSpeed |= HBA_PORTSPEED_16GBIT; |
@@ -1602,15 +1790,19 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1602 | ae->un.SupportSpeed |= HBA_PORTSPEED_2GBIT; | 1790 | ae->un.SupportSpeed |= HBA_PORTSPEED_2GBIT; |
1603 | if (phba->lmt & LMT_1Gb) | 1791 | if (phba->lmt & LMT_1Gb) |
1604 | ae->un.SupportSpeed |= HBA_PORTSPEED_1GBIT; | 1792 | ae->un.SupportSpeed |= HBA_PORTSPEED_1GBIT; |
1793 | ae->un.SupportSpeed = | ||
1794 | cpu_to_be32(ae->un.SupportSpeed); | ||
1605 | 1795 | ||
1606 | pab->ab.EntryCnt++; | 1796 | pab->ab.EntryCnt++; |
1607 | size += FOURBYTES + 4; | 1797 | size += FOURBYTES + 4; |
1608 | 1798 | ||
1609 | /* #3 Port attribute entry */ | 1799 | /* #3 Port attribute entry */ |
1610 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); | 1800 | ad = (struct lpfc_fdmi_attr_def *) |
1611 | ae->ad.bits.AttrType = be16_to_cpu(PORT_SPEED); | 1801 | ((uint8_t *)pab + size); |
1612 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); | 1802 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1613 | switch(phba->fc_linkspeed) { | 1803 | ad->AttrType = cpu_to_be16(RPRT_PORT_SPEED); |
1804 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
1805 | switch (phba->fc_linkspeed) { | ||
1614 | case LPFC_LINK_SPEED_1GHZ: | 1806 | case LPFC_LINK_SPEED_1GHZ: |
1615 | ae->un.PortSpeed = HBA_PORTSPEED_1GBIT; | 1807 | ae->un.PortSpeed = HBA_PORTSPEED_1GBIT; |
1616 | break; | 1808 | break; |
@@ -1633,93 +1825,273 @@ lpfc_fdmi_cmd(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, int cmdcode) | |||
1633 | ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN; | 1825 | ae->un.PortSpeed = HBA_PORTSPEED_UNKNOWN; |
1634 | break; | 1826 | break; |
1635 | } | 1827 | } |
1828 | ae->un.PortSpeed = cpu_to_be32(ae->un.PortSpeed); | ||
1636 | pab->ab.EntryCnt++; | 1829 | pab->ab.EntryCnt++; |
1637 | size += FOURBYTES + 4; | 1830 | size += FOURBYTES + 4; |
1638 | 1831 | ||
1639 | /* #4 Port attribute entry */ | 1832 | /* #4 Port attribute entry */ |
1640 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); | 1833 | ad = (struct lpfc_fdmi_attr_def *) |
1641 | ae->ad.bits.AttrType = be16_to_cpu(MAX_FRAME_SIZE); | 1834 | ((uint8_t *)pab + size); |
1642 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + 4); | 1835 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1643 | hsp = (struct serv_parm *) & vport->fc_sparam; | 1836 | ad->AttrType = cpu_to_be16(RPRT_MAX_FRAME_SIZE); |
1837 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
1838 | hsp = (struct serv_parm *)&vport->fc_sparam; | ||
1644 | ae->un.MaxFrameSize = | 1839 | ae->un.MaxFrameSize = |
1645 | (((uint32_t) hsp->cmn. | 1840 | (((uint32_t)hsp->cmn. |
1646 | bbRcvSizeMsb) << 8) | (uint32_t) hsp->cmn. | 1841 | bbRcvSizeMsb) << 8) | (uint32_t)hsp->cmn. |
1647 | bbRcvSizeLsb; | 1842 | bbRcvSizeLsb; |
1843 | ae->un.MaxFrameSize = | ||
1844 | cpu_to_be32(ae->un.MaxFrameSize); | ||
1648 | pab->ab.EntryCnt++; | 1845 | pab->ab.EntryCnt++; |
1649 | size += FOURBYTES + 4; | 1846 | size += FOURBYTES + 4; |
1847 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1848 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1849 | goto port_out; | ||
1650 | 1850 | ||
1651 | /* #5 Port attribute entry */ | 1851 | /* #5 Port attribute entry */ |
1652 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + size); | 1852 | ad = (struct lpfc_fdmi_attr_def *) |
1653 | ae->ad.bits.AttrType = be16_to_cpu(OS_DEVICE_NAME); | 1853 | ((uint8_t *)pab + size); |
1654 | strcpy((char *)ae->un.OsDeviceName, LPFC_DRIVER_NAME); | 1854 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1655 | len = strlen((char *)ae->un.OsDeviceName); | 1855 | memset(ae, 0, sizeof(ae->un.OsDeviceName)); |
1856 | ad->AttrType = cpu_to_be16(RPRT_OS_DEVICE_NAME); | ||
1857 | strncpy((char *)ae->un.OsDeviceName, LPFC_DRIVER_NAME, | ||
1858 | sizeof(ae->un.OsDeviceName)); | ||
1859 | len = strnlen((char *)ae->un.OsDeviceName, | ||
1860 | sizeof(ae->un.OsDeviceName)); | ||
1656 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1861 | len += (len & 3) ? (4 - (len & 3)) : 4; |
1657 | ae->ad.bits.AttrLen = be16_to_cpu(FOURBYTES + len); | 1862 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); |
1658 | pab->ab.EntryCnt++; | 1863 | pab->ab.EntryCnt++; |
1659 | size += FOURBYTES + len; | 1864 | size += FOURBYTES + len; |
1865 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1866 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1867 | goto port_out; | ||
1868 | |||
1869 | /* #6 Port attribute entry */ | ||
1870 | ad = (struct lpfc_fdmi_attr_def *) | ||
1871 | ((uint8_t *)pab + size); | ||
1872 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1873 | memset(ae, 0, sizeof(ae->un.HostName)); | ||
1874 | snprintf(ae->un.HostName, sizeof(ae->un.HostName), "%s", | ||
1875 | init_utsname()->nodename); | ||
1876 | ad->AttrType = cpu_to_be16(RPRT_HOST_NAME); | ||
1877 | len = strnlen(ae->un.HostName, | ||
1878 | sizeof(ae->un.HostName)); | ||
1879 | len += (len & 3) ? (4 - (len & 3)) : 4; | ||
1880 | ad->AttrLen = | ||
1881 | cpu_to_be16(FOURBYTES + len); | ||
1882 | pab->ab.EntryCnt++; | ||
1883 | size += FOURBYTES + len; | ||
1884 | if ((size + sizeof(struct lpfc_name)) > | ||
1885 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1886 | goto port_out; | ||
1660 | 1887 | ||
1661 | if (vport->cfg_fdmi_on == 2) { | 1888 | /* |
1662 | /* #6 Port attribute entry */ | 1889 | * Currently switches don't seem to support the |
1663 | ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) pab + | 1890 | * following extended Port attributes. |
1664 | size); | 1891 | */ |
1665 | ae->ad.bits.AttrType = be16_to_cpu(HOST_NAME); | 1892 | if (!(vport->cfg_fdmi_on & LPFC_FDMI_ALL_ATTRIB)) |
1666 | sprintf(ae->un.HostName, "%s", | 1893 | goto port_out; |
1667 | init_utsname()->nodename); | 1894 | |
1668 | len = strlen(ae->un.HostName); | 1895 | /* #7 Port attribute entry */ |
1669 | len += (len & 3) ? (4 - (len & 3)) : 4; | 1896 | ad = (struct lpfc_fdmi_attr_def *) |
1670 | ae->ad.bits.AttrLen = | 1897 | ((uint8_t *)pab + size); |
1671 | be16_to_cpu(FOURBYTES + len); | 1898 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; |
1672 | pab->ab.EntryCnt++; | 1899 | memset(ae, 0, sizeof(struct lpfc_name)); |
1673 | size += FOURBYTES + len; | 1900 | ad->AttrType = cpu_to_be16(RPRT_NODENAME); |
1674 | } | 1901 | ad->AttrLen = cpu_to_be16(FOURBYTES |
1675 | 1902 | + sizeof(struct lpfc_name)); | |
1676 | pab->ab.EntryCnt = be32_to_cpu(pab->ab.EntryCnt); | 1903 | memcpy(&ae->un.NodeName, &vport->fc_sparam.nodeName, |
1904 | sizeof(struct lpfc_name)); | ||
1905 | pab->ab.EntryCnt++; | ||
1906 | size += FOURBYTES + sizeof(struct lpfc_name); | ||
1907 | if ((size + sizeof(struct lpfc_name)) > | ||
1908 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1909 | goto port_out; | ||
1910 | |||
1911 | /* #8 Port attribute entry */ | ||
1912 | ad = (struct lpfc_fdmi_attr_def *) | ||
1913 | ((uint8_t *)pab + size); | ||
1914 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1915 | memset(ae, 0, sizeof(struct lpfc_name)); | ||
1916 | ad->AttrType = cpu_to_be16(RPRT_PORTNAME); | ||
1917 | ad->AttrLen = cpu_to_be16(FOURBYTES | ||
1918 | + sizeof(struct lpfc_name)); | ||
1919 | memcpy(&ae->un.PortName, &vport->fc_sparam.portName, | ||
1920 | sizeof(struct lpfc_name)); | ||
1921 | pab->ab.EntryCnt++; | ||
1922 | size += FOURBYTES + sizeof(struct lpfc_name); | ||
1923 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1924 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1925 | goto port_out; | ||
1926 | |||
1927 | /* #9 Port attribute entry */ | ||
1928 | ad = (struct lpfc_fdmi_attr_def *) | ||
1929 | ((uint8_t *)pab + size); | ||
1930 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1931 | memset(ae, 0, sizeof(ae->un.NodeSymName)); | ||
1932 | ad->AttrType = cpu_to_be16(RPRT_SYM_PORTNAME); | ||
1933 | len = lpfc_vport_symbolic_port_name(vport, | ||
1934 | ae->un.NodeSymName, sizeof(ae->un.NodeSymName)); | ||
1935 | len += (len & 3) ? (4 - (len & 3)) : 4; | ||
1936 | ad->AttrLen = cpu_to_be16(FOURBYTES + len); | ||
1937 | pab->ab.EntryCnt++; | ||
1938 | size += FOURBYTES + len; | ||
1939 | if ((size + 4) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1940 | goto port_out; | ||
1941 | |||
1942 | /* #10 Port attribute entry */ | ||
1943 | ad = (struct lpfc_fdmi_attr_def *) | ||
1944 | ((uint8_t *)pab + size); | ||
1945 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1946 | ad->AttrType = cpu_to_be16(RPRT_PORT_TYPE); | ||
1947 | ae->un.PortState = 0; | ||
1948 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
1949 | pab->ab.EntryCnt++; | ||
1950 | size += FOURBYTES + 4; | ||
1951 | if ((size + 4) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1952 | goto port_out; | ||
1953 | |||
1954 | /* #11 Port attribute entry */ | ||
1955 | ad = (struct lpfc_fdmi_attr_def *) | ||
1956 | ((uint8_t *)pab + size); | ||
1957 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1958 | ad->AttrType = cpu_to_be16(RPRT_SUPPORTED_CLASS); | ||
1959 | ae->un.SupportClass = | ||
1960 | cpu_to_be32(FC_COS_CLASS2 | FC_COS_CLASS3); | ||
1961 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
1962 | pab->ab.EntryCnt++; | ||
1963 | size += FOURBYTES + 4; | ||
1964 | if ((size + sizeof(struct lpfc_name)) > | ||
1965 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1966 | goto port_out; | ||
1967 | |||
1968 | /* #12 Port attribute entry */ | ||
1969 | ad = (struct lpfc_fdmi_attr_def *) | ||
1970 | ((uint8_t *)pab + size); | ||
1971 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1972 | memset(ae, 0, sizeof(struct lpfc_name)); | ||
1973 | ad->AttrType = cpu_to_be16(RPRT_FABRICNAME); | ||
1974 | ad->AttrLen = cpu_to_be16(FOURBYTES | ||
1975 | + sizeof(struct lpfc_name)); | ||
1976 | memcpy(&ae->un.FabricName, &vport->fabric_nodename, | ||
1977 | sizeof(struct lpfc_name)); | ||
1978 | pab->ab.EntryCnt++; | ||
1979 | size += FOURBYTES + sizeof(struct lpfc_name); | ||
1980 | if ((size + LPFC_FDMI_MAX_AE_SIZE) > | ||
1981 | (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1982 | goto port_out; | ||
1983 | |||
1984 | /* #13 Port attribute entry */ | ||
1985 | ad = (struct lpfc_fdmi_attr_def *) | ||
1986 | ((uint8_t *)pab + size); | ||
1987 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
1988 | memset(ae, 0, sizeof(ae->un.FC4Types)); | ||
1989 | ad->AttrType = | ||
1990 | cpu_to_be16(RPRT_ACTIVE_FC4_TYPES); | ||
1991 | ad->AttrLen = cpu_to_be16(FOURBYTES + 32); | ||
1992 | ae->un.FC4Types[0] = 0x40; /* Type 1 - ELS */ | ||
1993 | ae->un.FC4Types[1] = 0x80; /* Type 8 - FCP */ | ||
1994 | ae->un.FC4Types[4] = 0x80; /* Type 32 - CT */ | ||
1995 | pab->ab.EntryCnt++; | ||
1996 | size += FOURBYTES + 32; | ||
1997 | if ((size + 4) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
1998 | goto port_out; | ||
1999 | |||
2000 | /* #257 Port attribute entry */ | ||
2001 | ad = (struct lpfc_fdmi_attr_def *) | ||
2002 | ((uint8_t *)pab + size); | ||
2003 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
2004 | ad->AttrType = cpu_to_be16(RPRT_PORT_STATE); | ||
2005 | ae->un.PortState = 0; | ||
2006 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
2007 | pab->ab.EntryCnt++; | ||
2008 | size += FOURBYTES + 4; | ||
2009 | if ((size + 4) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
2010 | goto port_out; | ||
2011 | |||
2012 | /* #258 Port attribute entry */ | ||
2013 | ad = (struct lpfc_fdmi_attr_def *) | ||
2014 | ((uint8_t *)pab + size); | ||
2015 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
2016 | ad->AttrType = cpu_to_be16(RPRT_DISC_PORT); | ||
2017 | ae->un.PortState = lpfc_find_map_node(vport); | ||
2018 | ae->un.PortState = cpu_to_be32(ae->un.PortState); | ||
2019 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
2020 | pab->ab.EntryCnt++; | ||
2021 | size += FOURBYTES + 4; | ||
2022 | if ((size + 4) > (LPFC_BPL_SIZE - LPFC_CT_PREAMBLE)) | ||
2023 | goto port_out; | ||
2024 | |||
2025 | /* #259 Port attribute entry */ | ||
2026 | ad = (struct lpfc_fdmi_attr_def *) | ||
2027 | ((uint8_t *)pab + size); | ||
2028 | ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; | ||
2029 | ad->AttrType = cpu_to_be16(RPRT_PORT_ID); | ||
2030 | ae->un.PortId = cpu_to_be32(vport->fc_myDID); | ||
2031 | ad->AttrLen = cpu_to_be16(FOURBYTES + 4); | ||
2032 | pab->ab.EntryCnt++; | ||
2033 | size += FOURBYTES + 4; | ||
2034 | port_out: | ||
2035 | pab->ab.EntryCnt = cpu_to_be32(pab->ab.EntryCnt); | ||
1677 | /* Total size */ | 2036 | /* Total size */ |
1678 | size = GID_REQUEST_SZ - 4 + size; | 2037 | size = GID_REQUEST_SZ - 4 + size; |
1679 | } | 2038 | } |
1680 | break; | 2039 | break; |
1681 | 2040 | ||
2041 | case SLI_MGMT_GHAT: | ||
2042 | case SLI_MGMT_GRPL: | ||
2043 | rsp_size = FC_MAX_NS_RSP; | ||
1682 | case SLI_MGMT_DHBA: | 2044 | case SLI_MGMT_DHBA: |
1683 | CtReq->CommandResponse.bits.CmdRsp = be16_to_cpu(SLI_MGMT_DHBA); | 2045 | case SLI_MGMT_DHAT: |
1684 | CtReq->CommandResponse.bits.Size = 0; | 2046 | pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID; |
1685 | pe = (PORT_ENTRY *) & CtReq->un.PortID; | 2047 | memcpy((uint8_t *)&pe->PortName, |
1686 | memcpy((uint8_t *) & pe->PortName, | 2048 | (uint8_t *)&vport->fc_sparam.portName, |
1687 | (uint8_t *) & vport->fc_sparam.portName, | 2049 | sizeof(struct lpfc_name)); |
1688 | sizeof (struct lpfc_name)); | 2050 | size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name); |
1689 | size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name); | ||
1690 | break; | 2051 | break; |
1691 | 2052 | ||
2053 | case SLI_MGMT_GPAT: | ||
2054 | case SLI_MGMT_GPAS: | ||
2055 | rsp_size = FC_MAX_NS_RSP; | ||
1692 | case SLI_MGMT_DPRT: | 2056 | case SLI_MGMT_DPRT: |
1693 | CtReq->CommandResponse.bits.CmdRsp = be16_to_cpu(SLI_MGMT_DPRT); | 2057 | case SLI_MGMT_DPA: |
1694 | CtReq->CommandResponse.bits.Size = 0; | 2058 | pe = (struct lpfc_fdmi_port_entry *)&CtReq->un.PortID; |
1695 | pe = (PORT_ENTRY *) & CtReq->un.PortID; | 2059 | memcpy((uint8_t *)&pe->PortName, |
1696 | memcpy((uint8_t *) & pe->PortName, | 2060 | (uint8_t *)&vport->fc_sparam.portName, |
1697 | (uint8_t *) & vport->fc_sparam.portName, | 2061 | sizeof(struct lpfc_name)); |
1698 | sizeof (struct lpfc_name)); | 2062 | size = GID_REQUEST_SZ - 4 + sizeof(struct lpfc_name); |
1699 | size = GID_REQUEST_SZ - 4 + sizeof (struct lpfc_name); | 2063 | break; |
2064 | case SLI_MGMT_GRHL: | ||
2065 | size = GID_REQUEST_SZ - 4; | ||
1700 | break; | 2066 | break; |
2067 | default: | ||
2068 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_DISCOVERY, | ||
2069 | "0298 FDMI cmdcode x%x not supported\n", | ||
2070 | cmdcode); | ||
2071 | goto fdmi_cmd_free_bmpvirt; | ||
1701 | } | 2072 | } |
2073 | CtReq->CommandResponse.bits.Size = cpu_to_be16(rsp_size); | ||
1702 | 2074 | ||
1703 | bpl = (struct ulp_bde64 *) bmp->virt; | 2075 | bpl = (struct ulp_bde64 *)bmp->virt; |
1704 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys) ); | 2076 | bpl->addrHigh = le32_to_cpu(putPaddrHigh(mp->phys)); |
1705 | bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys) ); | 2077 | bpl->addrLow = le32_to_cpu(putPaddrLow(mp->phys)); |
1706 | bpl->tus.f.bdeFlags = 0; | 2078 | bpl->tus.f.bdeFlags = 0; |
1707 | bpl->tus.f.bdeSize = size; | 2079 | bpl->tus.f.bdeSize = size; |
1708 | bpl->tus.w = le32_to_cpu(bpl->tus.w); | ||
1709 | |||
1710 | cmpl = lpfc_cmpl_ct_cmd_fdmi; | ||
1711 | 2080 | ||
1712 | /* The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count | 2081 | /* |
2082 | * The lpfc_ct_cmd/lpfc_get_req shall increment ndlp reference count | ||
1713 | * to hold ndlp reference for the corresponding callback function. | 2083 | * to hold ndlp reference for the corresponding callback function. |
1714 | */ | 2084 | */ |
1715 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, FC_MAX_NS_RSP, 0)) | 2085 | if (!lpfc_ct_cmd(vport, mp, bmp, ndlp, cmpl, rsp_size, 0)) |
1716 | return 0; | 2086 | return 0; |
1717 | 2087 | ||
1718 | /* Decrement ndlp reference count to release ndlp reference held | 2088 | /* |
2089 | * Decrement ndlp reference count to release ndlp reference held | ||
1719 | * for the failed command's callback function. | 2090 | * for the failed command's callback function. |
1720 | */ | 2091 | */ |
1721 | lpfc_nlp_put(ndlp); | 2092 | lpfc_nlp_put(ndlp); |
1722 | 2093 | ||
2094 | fdmi_cmd_free_bmpvirt: | ||
1723 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); | 2095 | lpfc_mbuf_free(phba, bmp->virt, bmp->phys); |
1724 | fdmi_cmd_free_bmp: | 2096 | fdmi_cmd_free_bmp: |
1725 | kfree(bmp); | 2097 | kfree(bmp); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 5633e7dadc08..513edcb0c2da 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2007-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2007-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index c66088d0fd2a..851e8efe364e 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -2243,8 +2243,7 @@ lpfc_adisc_done(struct lpfc_vport *vport) | |||
2243 | */ | 2243 | */ |
2244 | if (vport->port_state < LPFC_VPORT_READY) { | 2244 | if (vport->port_state < LPFC_VPORT_READY) { |
2245 | /* If we get here, there is nothing to ADISC */ | 2245 | /* If we get here, there is nothing to ADISC */ |
2246 | if (vport->port_type == LPFC_PHYSICAL_PORT) | 2246 | lpfc_issue_clear_la(phba, vport); |
2247 | lpfc_issue_clear_la(phba, vport); | ||
2248 | if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) { | 2247 | if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) { |
2249 | vport->num_disc_nodes = 0; | 2248 | vport->num_disc_nodes = 0; |
2250 | /* go thru NPR list, issue ELS PLOGIs */ | 2249 | /* go thru NPR list, issue ELS PLOGIs */ |
@@ -3338,7 +3337,11 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, | |||
3338 | /* FLOGI retry policy */ | 3337 | /* FLOGI retry policy */ |
3339 | retry = 1; | 3338 | retry = 1; |
3340 | /* retry FLOGI forever */ | 3339 | /* retry FLOGI forever */ |
3341 | maxretry = 0; | 3340 | if (phba->link_flag != LS_LOOPBACK_MODE) |
3341 | maxretry = 0; | ||
3342 | else | ||
3343 | maxretry = 2; | ||
3344 | |||
3342 | if (cmdiocb->retry >= 100) | 3345 | if (cmdiocb->retry >= 100) |
3343 | delay = 5000; | 3346 | delay = 5000; |
3344 | else if (cmdiocb->retry >= 32) | 3347 | else if (cmdiocb->retry >= 32) |
@@ -3701,6 +3704,11 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3701 | kfree(mp); | 3704 | kfree(mp); |
3702 | mempool_free(pmb, phba->mbox_mem_pool); | 3705 | mempool_free(pmb, phba->mbox_mem_pool); |
3703 | if (ndlp) { | 3706 | if (ndlp) { |
3707 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, | ||
3708 | "0006 rpi%x DID:%x flg:%x %d map:%x %p\n", | ||
3709 | ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, | ||
3710 | atomic_read(&ndlp->kref.refcount), | ||
3711 | ndlp->nlp_usg_map, ndlp); | ||
3704 | if (NLP_CHK_NODE_ACT(ndlp)) { | 3712 | if (NLP_CHK_NODE_ACT(ndlp)) { |
3705 | lpfc_nlp_put(ndlp); | 3713 | lpfc_nlp_put(ndlp); |
3706 | /* This is the end of the default RPI cleanup logic for | 3714 | /* This is the end of the default RPI cleanup logic for |
@@ -5198,7 +5206,6 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb, | |||
5198 | port_state = vport->port_state; | 5206 | port_state = vport->port_state; |
5199 | vport->fc_flag |= FC_PT2PT; | 5207 | vport->fc_flag |= FC_PT2PT; |
5200 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); | 5208 | vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP); |
5201 | vport->port_state = LPFC_FLOGI; | ||
5202 | spin_unlock_irq(shost->host_lock); | 5209 | spin_unlock_irq(shost->host_lock); |
5203 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, | 5210 | lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS, |
5204 | "3311 Rcv Flogi PS x%x new PS x%x " | 5211 | "3311 Rcv Flogi PS x%x new PS x%x " |
@@ -7173,7 +7180,7 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport) | |||
7173 | return; | 7180 | return; |
7174 | } | 7181 | } |
7175 | 7182 | ||
7176 | if (vport->cfg_fdmi_on) { | 7183 | if (vport->cfg_fdmi_on & LPFC_FDMI_SUPPORT) { |
7177 | /* If this is the first time, allocate an ndlp and initialize | 7184 | /* If this is the first time, allocate an ndlp and initialize |
7178 | * it. Otherwise, make sure the node is enabled and then do the | 7185 | * it. Otherwise, make sure the node is enabled and then do the |
7179 | * login. | 7186 | * login. |
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 5452f1f4220e..2500f15d437f 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -3439,6 +3439,11 @@ lpfc_mbx_cmpl_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
3439 | pmb->context1 = NULL; | 3439 | pmb->context1 = NULL; |
3440 | pmb->context2 = NULL; | 3440 | pmb->context2 = NULL; |
3441 | 3441 | ||
3442 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | ||
3443 | "0002 rpi:%x DID:%x flg:%x %d map:%x %p\n", | ||
3444 | ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, | ||
3445 | atomic_read(&ndlp->kref.refcount), | ||
3446 | ndlp->nlp_usg_map, ndlp); | ||
3442 | if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) | 3447 | if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) |
3443 | ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; | 3448 | ndlp->nlp_flag &= ~NLP_REG_LOGIN_SEND; |
3444 | 3449 | ||
@@ -3855,6 +3860,11 @@ out: | |||
3855 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 3860 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
3856 | ndlp->nlp_type |= NLP_FABRIC; | 3861 | ndlp->nlp_type |= NLP_FABRIC; |
3857 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 3862 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
3863 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | ||
3864 | "0003 rpi:%x DID:%x flg:%x %d map%x %p\n", | ||
3865 | ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, | ||
3866 | atomic_read(&ndlp->kref.refcount), | ||
3867 | ndlp->nlp_usg_map, ndlp); | ||
3858 | 3868 | ||
3859 | if (vport->port_state < LPFC_VPORT_READY) { | 3869 | if (vport->port_state < LPFC_VPORT_READY) { |
3860 | /* Link up discovery requires Fabric registration. */ | 3870 | /* Link up discovery requires Fabric registration. */ |
@@ -4250,8 +4260,15 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
4250 | ndlp->active_rrqs_xri_bitmap = active_rrqs_xri_bitmap; | 4260 | ndlp->active_rrqs_xri_bitmap = active_rrqs_xri_bitmap; |
4251 | 4261 | ||
4252 | spin_unlock_irqrestore(&phba->ndlp_lock, flags); | 4262 | spin_unlock_irqrestore(&phba->ndlp_lock, flags); |
4253 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | 4263 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { |
4254 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | 4264 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); |
4265 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, | ||
4266 | "0008 rpi:%x DID:%x flg:%x refcnt:%d " | ||
4267 | "map:%x %p\n", ndlp->nlp_rpi, ndlp->nlp_DID, | ||
4268 | ndlp->nlp_flag, | ||
4269 | atomic_read(&ndlp->kref.refcount), | ||
4270 | ndlp->nlp_usg_map, ndlp); | ||
4271 | } | ||
4255 | 4272 | ||
4256 | 4273 | ||
4257 | if (state != NLP_STE_UNUSED_NODE) | 4274 | if (state != NLP_STE_UNUSED_NODE) |
@@ -4276,9 +4293,12 @@ lpfc_drop_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4276 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) | 4293 | if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) |
4277 | return; | 4294 | return; |
4278 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); | 4295 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE); |
4279 | if (vport->phba->sli_rev == LPFC_SLI_REV4) | 4296 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { |
4280 | lpfc_cleanup_vports_rrqs(vport, ndlp); | 4297 | lpfc_cleanup_vports_rrqs(vport, ndlp); |
4281 | lpfc_nlp_put(ndlp); | 4298 | lpfc_unreg_rpi(vport, ndlp); |
4299 | } else { | ||
4300 | lpfc_nlp_put(ndlp); | ||
4301 | } | ||
4282 | return; | 4302 | return; |
4283 | } | 4303 | } |
4284 | 4304 | ||
@@ -4515,7 +4535,17 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4515 | mbox->context1 = ndlp; | 4535 | mbox->context1 = ndlp; |
4516 | mbox->mbox_cmpl = lpfc_nlp_logo_unreg; | 4536 | mbox->mbox_cmpl = lpfc_nlp_logo_unreg; |
4517 | } else { | 4537 | } else { |
4518 | mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl; | 4538 | if (phba->sli_rev == LPFC_SLI_REV4 && |
4539 | (!(vport->load_flag & FC_UNLOADING)) && | ||
4540 | (bf_get(lpfc_sli_intf_if_type, | ||
4541 | &phba->sli4_hba.sli_intf) == | ||
4542 | LPFC_SLI_INTF_IF_TYPE_2)) { | ||
4543 | mbox->context1 = lpfc_nlp_get(ndlp); | ||
4544 | mbox->mbox_cmpl = | ||
4545 | lpfc_sli4_unreg_rpi_cmpl_clr; | ||
4546 | } else | ||
4547 | mbox->mbox_cmpl = | ||
4548 | lpfc_sli_def_mbox_cmpl; | ||
4519 | } | 4549 | } |
4520 | 4550 | ||
4521 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); | 4551 | rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT); |
@@ -4741,6 +4771,11 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) | |||
4741 | /* For this case we need to cleanup the default rpi | 4771 | /* For this case we need to cleanup the default rpi |
4742 | * allocated by the firmware. | 4772 | * allocated by the firmware. |
4743 | */ | 4773 | */ |
4774 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, | ||
4775 | "0005 rpi:%x DID:%x flg:%x %d map:%x %p\n", | ||
4776 | ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, | ||
4777 | atomic_read(&ndlp->kref.refcount), | ||
4778 | ndlp->nlp_usg_map, ndlp); | ||
4744 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) | 4779 | if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL)) |
4745 | != NULL) { | 4780 | != NULL) { |
4746 | rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, | 4781 | rc = lpfc_reg_rpi(phba, vport->vpi, ndlp->nlp_DID, |
@@ -5070,8 +5105,7 @@ lpfc_disc_start(struct lpfc_vport *vport) | |||
5070 | !(vport->fc_flag & FC_PT2PT) && | 5105 | !(vport->fc_flag & FC_PT2PT) && |
5071 | !(vport->fc_flag & FC_RSCN_MODE) && | 5106 | !(vport->fc_flag & FC_RSCN_MODE) && |
5072 | (phba->sli_rev < LPFC_SLI_REV4)) { | 5107 | (phba->sli_rev < LPFC_SLI_REV4)) { |
5073 | if (vport->port_type == LPFC_PHYSICAL_PORT) | 5108 | lpfc_issue_clear_la(phba, vport); |
5074 | lpfc_issue_clear_la(phba, vport); | ||
5075 | lpfc_issue_reg_vpi(phba, vport); | 5109 | lpfc_issue_reg_vpi(phba, vport); |
5076 | return; | 5110 | return; |
5077 | } | 5111 | } |
@@ -5082,8 +5116,7 @@ lpfc_disc_start(struct lpfc_vport *vport) | |||
5082 | */ | 5116 | */ |
5083 | if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) { | 5117 | if (vport->port_state < LPFC_VPORT_READY && !clear_la_pending) { |
5084 | /* If we get here, there is nothing to ADISC */ | 5118 | /* If we get here, there is nothing to ADISC */ |
5085 | if (vport->port_type == LPFC_PHYSICAL_PORT) | 5119 | lpfc_issue_clear_la(phba, vport); |
5086 | lpfc_issue_clear_la(phba, vport); | ||
5087 | 5120 | ||
5088 | if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) { | 5121 | if (!(vport->fc_flag & FC_ABORT_DISCOVERY)) { |
5089 | vport->num_disc_nodes = 0; | 5122 | vport->num_disc_nodes = 0; |
@@ -5484,18 +5517,22 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
5484 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; | 5517 | ndlp->nlp_flag |= NLP_RPI_REGISTERED; |
5485 | ndlp->nlp_type |= NLP_FABRIC; | 5518 | ndlp->nlp_type |= NLP_FABRIC; |
5486 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); | 5519 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); |
5487 | 5520 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | |
5521 | "0004 rpi:%x DID:%x flg:%x %d map:%x %p\n", | ||
5522 | ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, | ||
5523 | atomic_read(&ndlp->kref.refcount), | ||
5524 | ndlp->nlp_usg_map, ndlp); | ||
5488 | /* | 5525 | /* |
5489 | * Start issuing Fabric-Device Management Interface (FDMI) command to | 5526 | * Start issuing Fabric-Device Management Interface (FDMI) command to |
5490 | * 0xfffffa (FDMI well known port) or Delay issuing FDMI command if | 5527 | * 0xfffffa (FDMI well known port) or Delay issuing FDMI command if |
5491 | * fdmi-on=2 (supporting RPA/hostnmae) | 5528 | * fdmi-on=2 (supporting RPA/hostnmae) |
5492 | */ | 5529 | */ |
5493 | 5530 | ||
5494 | if (vport->cfg_fdmi_on == 1) | 5531 | if (vport->cfg_fdmi_on & LPFC_FDMI_REG_DELAY) |
5495 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); | ||
5496 | else | ||
5497 | mod_timer(&vport->fc_fdmitmo, | 5532 | mod_timer(&vport->fc_fdmitmo, |
5498 | jiffies + msecs_to_jiffies(1000 * 60)); | 5533 | jiffies + msecs_to_jiffies(1000 * 60)); |
5534 | else | ||
5535 | lpfc_fdmi_cmd(vport, ndlp, SLI_MGMT_DHBA); | ||
5499 | 5536 | ||
5500 | /* decrement the node reference count held for this callback | 5537 | /* decrement the node reference count held for this callback |
5501 | * function. | 5538 | * function. |
@@ -5650,6 +5687,13 @@ lpfc_nlp_init(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
5650 | INIT_LIST_HEAD(&ndlp->nlp_listp); | 5687 | INIT_LIST_HEAD(&ndlp->nlp_listp); |
5651 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { | 5688 | if (vport->phba->sli_rev == LPFC_SLI_REV4) { |
5652 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); | 5689 | ndlp->nlp_rpi = lpfc_sli4_alloc_rpi(vport->phba); |
5690 | lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, | ||
5691 | "0007 rpi:%x DID:%x flg:%x refcnt:%d " | ||
5692 | "map:%x %p\n", ndlp->nlp_rpi, ndlp->nlp_DID, | ||
5693 | ndlp->nlp_flag, | ||
5694 | atomic_read(&ndlp->kref.refcount), | ||
5695 | ndlp->nlp_usg_map, ndlp); | ||
5696 | |||
5653 | ndlp->active_rrqs_xri_bitmap = | 5697 | ndlp->active_rrqs_xri_bitmap = |
5654 | mempool_alloc(vport->phba->active_rrq_pool, | 5698 | mempool_alloc(vport->phba->active_rrq_pool, |
5655 | GFP_KERNEL); | 5699 | GFP_KERNEL); |
@@ -5684,9 +5728,9 @@ lpfc_nlp_release(struct kref *kref) | |||
5684 | 5728 | ||
5685 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, | 5729 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, |
5686 | "0279 lpfc_nlp_release: ndlp:x%p did %x " | 5730 | "0279 lpfc_nlp_release: ndlp:x%p did %x " |
5687 | "usgmap:x%x refcnt:%d\n", | 5731 | "usgmap:x%x refcnt:%d rpi:%x\n", |
5688 | (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map, | 5732 | (void *)ndlp, ndlp->nlp_DID, ndlp->nlp_usg_map, |
5689 | atomic_read(&ndlp->kref.refcount)); | 5733 | atomic_read(&ndlp->kref.refcount), ndlp->nlp_rpi); |
5690 | 5734 | ||
5691 | /* remove ndlp from action. */ | 5735 | /* remove ndlp from action. */ |
5692 | lpfc_nlp_remove(ndlp->vport, ndlp); | 5736 | lpfc_nlp_remove(ndlp->vport, ndlp); |
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h index 236259252379..37beb9dc1311 100644 --- a/drivers/scsi/lpfc/lpfc_hw.h +++ b/drivers/scsi/lpfc/lpfc_hw.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -107,6 +107,7 @@ struct lpfc_sli_ct_request { | |||
107 | uint8_t ReasonCode; | 107 | uint8_t ReasonCode; |
108 | uint8_t Explanation; | 108 | uint8_t Explanation; |
109 | uint8_t VendorUnique; | 109 | uint8_t VendorUnique; |
110 | #define LPFC_CT_PREAMBLE 20 /* Size of CTReq + 4 up to here */ | ||
110 | 111 | ||
111 | union { | 112 | union { |
112 | uint32_t PortID; | 113 | uint32_t PortID; |
@@ -170,6 +171,8 @@ struct lpfc_sli_ct_request { | |||
170 | } un; | 171 | } un; |
171 | }; | 172 | }; |
172 | 173 | ||
174 | #define LPFC_MAX_CT_SIZE (60 * 4096) | ||
175 | |||
173 | #define SLI_CT_REVISION 1 | 176 | #define SLI_CT_REVISION 1 |
174 | #define GID_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ | 177 | #define GID_REQUEST_SZ (offsetof(struct lpfc_sli_ct_request, un) + \ |
175 | sizeof(struct gid)) | 178 | sizeof(struct gid)) |
@@ -1007,78 +1010,45 @@ typedef struct _ELS_PKT { /* Structure is in Big Endian format */ | |||
1007 | } un; | 1010 | } un; |
1008 | } ELS_PKT; | 1011 | } ELS_PKT; |
1009 | 1012 | ||
1010 | /* | 1013 | /******** FDMI ********/ |
1011 | * FDMI | ||
1012 | * HBA MAnagement Operations Command Codes | ||
1013 | */ | ||
1014 | #define SLI_MGMT_GRHL 0x100 /* Get registered HBA list */ | ||
1015 | #define SLI_MGMT_GHAT 0x101 /* Get HBA attributes */ | ||
1016 | #define SLI_MGMT_GRPL 0x102 /* Get registered Port list */ | ||
1017 | #define SLI_MGMT_GPAT 0x110 /* Get Port attributes */ | ||
1018 | #define SLI_MGMT_RHBA 0x200 /* Register HBA */ | ||
1019 | #define SLI_MGMT_RHAT 0x201 /* Register HBA attributes */ | ||
1020 | #define SLI_MGMT_RPRT 0x210 /* Register Port */ | ||
1021 | #define SLI_MGMT_RPA 0x211 /* Register Port attributes */ | ||
1022 | #define SLI_MGMT_DHBA 0x300 /* De-register HBA */ | ||
1023 | #define SLI_MGMT_DPRT 0x310 /* De-register Port */ | ||
1024 | 1014 | ||
1025 | /* | 1015 | /* lpfc_sli_ct_request defines the CT_IU preamble for FDMI commands */ |
1026 | * Management Service Subtypes | 1016 | #define SLI_CT_FDMI_Subtypes 0x10 /* Management Service Subtype */ |
1027 | */ | ||
1028 | #define SLI_CT_FDMI_Subtypes 0x10 | ||
1029 | 1017 | ||
1030 | /* | 1018 | /* |
1031 | * HBA Management Service Reject Code | 1019 | * Registered Port List Format |
1032 | */ | 1020 | */ |
1033 | #define REJECT_CODE 0x9 /* Unable to perform command request */ | 1021 | struct lpfc_fdmi_reg_port_list { |
1022 | uint32_t EntryCnt; | ||
1023 | uint32_t pe; /* Variable-length array */ | ||
1024 | }; | ||
1034 | 1025 | ||
1035 | /* | ||
1036 | * HBA Management Service Reject Reason Code | ||
1037 | * Please refer to the Reason Codes above | ||
1038 | */ | ||
1039 | 1026 | ||
1040 | /* | 1027 | /* Definitions for HBA / Port attribute entries */ |
1041 | * HBA Attribute Types | ||
1042 | */ | ||
1043 | #define NODE_NAME 0x1 | ||
1044 | #define MANUFACTURER 0x2 | ||
1045 | #define SERIAL_NUMBER 0x3 | ||
1046 | #define MODEL 0x4 | ||
1047 | #define MODEL_DESCRIPTION 0x5 | ||
1048 | #define HARDWARE_VERSION 0x6 | ||
1049 | #define DRIVER_VERSION 0x7 | ||
1050 | #define OPTION_ROM_VERSION 0x8 | ||
1051 | #define FIRMWARE_VERSION 0x9 | ||
1052 | #define OS_NAME_VERSION 0xa | ||
1053 | #define MAX_CT_PAYLOAD_LEN 0xb | ||
1054 | 1028 | ||
1055 | /* | 1029 | struct lpfc_fdmi_attr_def { /* Defined in TLV format */ |
1056 | * Port Attrubute Types | ||
1057 | */ | ||
1058 | #define SUPPORTED_FC4_TYPES 0x1 | ||
1059 | #define SUPPORTED_SPEED 0x2 | ||
1060 | #define PORT_SPEED 0x3 | ||
1061 | #define MAX_FRAME_SIZE 0x4 | ||
1062 | #define OS_DEVICE_NAME 0x5 | ||
1063 | #define HOST_NAME 0x6 | ||
1064 | |||
1065 | union AttributesDef { | ||
1066 | /* Structure is in Big Endian format */ | 1030 | /* Structure is in Big Endian format */ |
1067 | struct { | 1031 | uint32_t AttrType:16; |
1068 | uint32_t AttrType:16; | 1032 | uint32_t AttrLen:16; |
1069 | uint32_t AttrLen:16; | 1033 | uint32_t AttrValue; /* Marks start of Value (ATTRIBUTE_ENTRY) */ |
1070 | } bits; | ||
1071 | uint32_t word; | ||
1072 | }; | 1034 | }; |
1073 | 1035 | ||
1074 | 1036 | ||
1075 | /* | 1037 | /* Attribute Entry */ |
1076 | * HBA Attribute Entry (8 - 260 bytes) | 1038 | struct lpfc_fdmi_attr_entry { |
1077 | */ | ||
1078 | typedef struct { | ||
1079 | union AttributesDef ad; | ||
1080 | union { | 1039 | union { |
1081 | uint32_t VendorSpecific; | 1040 | uint32_t VendorSpecific; |
1041 | uint32_t SupportClass; | ||
1042 | uint32_t SupportSpeed; | ||
1043 | uint32_t PortSpeed; | ||
1044 | uint32_t MaxFrameSize; | ||
1045 | uint32_t MaxCTPayloadLen; | ||
1046 | uint32_t PortState; | ||
1047 | uint32_t PortId; | ||
1048 | struct lpfc_name NodeName; | ||
1049 | struct lpfc_name PortName; | ||
1050 | struct lpfc_name FabricName; | ||
1051 | uint8_t FC4Types[32]; | ||
1082 | uint8_t Manufacturer[64]; | 1052 | uint8_t Manufacturer[64]; |
1083 | uint8_t SerialNumber[64]; | 1053 | uint8_t SerialNumber[64]; |
1084 | uint8_t Model[256]; | 1054 | uint8_t Model[256]; |
@@ -1087,97 +1057,115 @@ typedef struct { | |||
1087 | uint8_t DriverVersion[256]; | 1057 | uint8_t DriverVersion[256]; |
1088 | uint8_t OptionROMVersion[256]; | 1058 | uint8_t OptionROMVersion[256]; |
1089 | uint8_t FirmwareVersion[256]; | 1059 | uint8_t FirmwareVersion[256]; |
1090 | struct lpfc_name NodeName; | 1060 | uint8_t OsHostName[256]; |
1091 | uint8_t SupportFC4Types[32]; | 1061 | uint8_t NodeSymName[256]; |
1092 | uint32_t SupportSpeed; | ||
1093 | uint32_t PortSpeed; | ||
1094 | uint32_t MaxFrameSize; | ||
1095 | uint8_t OsDeviceName[256]; | 1062 | uint8_t OsDeviceName[256]; |
1096 | uint8_t OsNameVersion[256]; | 1063 | uint8_t OsNameVersion[256]; |
1097 | uint32_t MaxCTPayloadLen; | ||
1098 | uint8_t HostName[256]; | 1064 | uint8_t HostName[256]; |
1099 | } un; | 1065 | } un; |
1100 | } ATTRIBUTE_ENTRY; | 1066 | }; |
1067 | |||
1068 | #define LPFC_FDMI_MAX_AE_SIZE sizeof(struct lpfc_fdmi_attr_entry) | ||
1101 | 1069 | ||
1102 | /* | 1070 | /* |
1103 | * HBA Attribute Block | 1071 | * HBA Attribute Block |
1104 | */ | 1072 | */ |
1105 | typedef struct { | 1073 | struct lpfc_fdmi_attr_block { |
1106 | uint32_t EntryCnt; /* Number of HBA attribute entries */ | 1074 | uint32_t EntryCnt; /* Number of HBA attribute entries */ |
1107 | ATTRIBUTE_ENTRY Entry; /* Variable-length array */ | 1075 | struct lpfc_fdmi_attr_entry Entry; /* Variable-length array */ |
1108 | } ATTRIBUTE_BLOCK; | 1076 | }; |
1109 | 1077 | ||
1110 | /* | 1078 | /* |
1111 | * Port Entry | 1079 | * Port Entry |
1112 | */ | 1080 | */ |
1113 | typedef struct { | 1081 | struct lpfc_fdmi_port_entry { |
1114 | struct lpfc_name PortName; | 1082 | struct lpfc_name PortName; |
1115 | } PORT_ENTRY; | 1083 | }; |
1116 | 1084 | ||
1117 | /* | 1085 | /* |
1118 | * HBA Identifier | 1086 | * HBA Identifier |
1119 | */ | 1087 | */ |
1120 | typedef struct { | 1088 | struct lpfc_fdmi_hba_ident { |
1121 | struct lpfc_name PortName; | 1089 | struct lpfc_name PortName; |
1122 | } HBA_IDENTIFIER; | 1090 | }; |
1123 | |||
1124 | /* | ||
1125 | * Registered Port List Format | ||
1126 | */ | ||
1127 | typedef struct { | ||
1128 | uint32_t EntryCnt; | ||
1129 | PORT_ENTRY pe; /* Variable-length array */ | ||
1130 | } REG_PORT_LIST; | ||
1131 | 1091 | ||
1132 | /* | 1092 | /* |
1133 | * Register HBA(RHBA) | 1093 | * Register HBA(RHBA) |
1134 | */ | 1094 | */ |
1135 | typedef struct { | 1095 | struct lpfc_fdmi_reg_hba { |
1136 | HBA_IDENTIFIER hi; | 1096 | struct lpfc_fdmi_hba_ident hi; |
1137 | REG_PORT_LIST rpl; /* variable-length array */ | 1097 | struct lpfc_fdmi_reg_port_list rpl; /* variable-length array */ |
1138 | /* ATTRIBUTE_BLOCK ab; */ | 1098 | /* struct lpfc_fdmi_attr_block ab; */ |
1139 | } REG_HBA; | 1099 | }; |
1140 | 1100 | ||
1141 | /* | 1101 | /* |
1142 | * Register HBA Attributes (RHAT) | 1102 | * Register HBA Attributes (RHAT) |
1143 | */ | 1103 | */ |
1144 | typedef struct { | 1104 | struct lpfc_fdmi_reg_hbaattr { |
1145 | struct lpfc_name HBA_PortName; | 1105 | struct lpfc_name HBA_PortName; |
1146 | ATTRIBUTE_BLOCK ab; | 1106 | struct lpfc_fdmi_attr_block ab; |
1147 | } REG_HBA_ATTRIBUTE; | 1107 | }; |
1148 | 1108 | ||
1149 | /* | 1109 | /* |
1150 | * Register Port Attributes (RPA) | 1110 | * Register Port Attributes (RPA) |
1151 | */ | 1111 | */ |
1152 | typedef struct { | 1112 | struct lpfc_fdmi_reg_portattr { |
1153 | struct lpfc_name PortName; | 1113 | struct lpfc_name PortName; |
1154 | ATTRIBUTE_BLOCK ab; | 1114 | struct lpfc_fdmi_attr_block ab; |
1155 | } REG_PORT_ATTRIBUTE; | 1115 | }; |
1156 | 1116 | ||
1157 | /* | 1117 | /* |
1158 | * Get Registered HBA List (GRHL) Accept Payload Format | 1118 | * HBA MAnagement Operations Command Codes |
1159 | */ | 1119 | */ |
1160 | typedef struct { | 1120 | #define SLI_MGMT_GRHL 0x100 /* Get registered HBA list */ |
1161 | uint32_t HBA__Entry_Cnt; /* Number of Registered HBA Identifiers */ | 1121 | #define SLI_MGMT_GHAT 0x101 /* Get HBA attributes */ |
1162 | struct lpfc_name HBA_PortName; /* Variable-length array */ | 1122 | #define SLI_MGMT_GRPL 0x102 /* Get registered Port list */ |
1163 | } GRHL_ACC_PAYLOAD; | 1123 | #define SLI_MGMT_GPAT 0x110 /* Get Port attributes */ |
1124 | #define SLI_MGMT_GPAS 0x120 /* Get Port Statistics */ | ||
1125 | #define SLI_MGMT_RHBA 0x200 /* Register HBA */ | ||
1126 | #define SLI_MGMT_RHAT 0x201 /* Register HBA attributes */ | ||
1127 | #define SLI_MGMT_RPRT 0x210 /* Register Port */ | ||
1128 | #define SLI_MGMT_RPA 0x211 /* Register Port attributes */ | ||
1129 | #define SLI_MGMT_DHBA 0x300 /* De-register HBA */ | ||
1130 | #define SLI_MGMT_DHAT 0x301 /* De-register HBA attributes */ | ||
1131 | #define SLI_MGMT_DPRT 0x310 /* De-register Port */ | ||
1132 | #define SLI_MGMT_DPA 0x311 /* De-register Port attributes */ | ||
1164 | 1133 | ||
1165 | /* | 1134 | /* |
1166 | * Get Registered Port List (GRPL) Accept Payload Format | 1135 | * HBA Attribute Types |
1167 | */ | 1136 | */ |
1168 | typedef struct { | 1137 | #define RHBA_NODENAME 0x1 /* 8 byte WWNN */ |
1169 | uint32_t RPL_Entry_Cnt; /* Number of Registered Port Entries */ | 1138 | #define RHBA_MANUFACTURER 0x2 /* 4 to 64 byte ASCII string */ |
1170 | PORT_ENTRY Reg_Port_Entry[1]; /* Variable-length array */ | 1139 | #define RHBA_SERIAL_NUMBER 0x3 /* 4 to 64 byte ASCII string */ |
1171 | } GRPL_ACC_PAYLOAD; | 1140 | #define RHBA_MODEL 0x4 /* 4 to 256 byte ASCII string */ |
1141 | #define RHBA_MODEL_DESCRIPTION 0x5 /* 4 to 256 byte ASCII string */ | ||
1142 | #define RHBA_HARDWARE_VERSION 0x6 /* 4 to 256 byte ASCII string */ | ||
1143 | #define RHBA_DRIVER_VERSION 0x7 /* 4 to 256 byte ASCII string */ | ||
1144 | #define RHBA_OPTION_ROM_VERSION 0x8 /* 4 to 256 byte ASCII string */ | ||
1145 | #define RHBA_FIRMWARE_VERSION 0x9 /* 4 to 256 byte ASCII string */ | ||
1146 | #define RHBA_OS_NAME_VERSION 0xa /* 4 to 256 byte ASCII string */ | ||
1147 | #define RHBA_MAX_CT_PAYLOAD_LEN 0xb /* 32-bit unsigned int */ | ||
1148 | #define RHBA_SYM_NODENAME 0xc /* 4 to 256 byte ASCII string */ | ||
1172 | 1149 | ||
1173 | /* | 1150 | /* |
1174 | * Get Port Attributes (GPAT) Accept Payload Format | 1151 | * Port Attrubute Types |
1175 | */ | 1152 | */ |
1176 | 1153 | #define RPRT_SUPPORTED_FC4_TYPES 0x1 /* 32 byte binary array */ | |
1177 | typedef struct { | 1154 | #define RPRT_SUPPORTED_SPEED 0x2 /* 32-bit unsigned int */ |
1178 | ATTRIBUTE_BLOCK pab; | 1155 | #define RPRT_PORT_SPEED 0x3 /* 32-bit unsigned int */ |
1179 | } GPAT_ACC_PAYLOAD; | 1156 | #define RPRT_MAX_FRAME_SIZE 0x4 /* 32-bit unsigned int */ |
1180 | 1157 | #define RPRT_OS_DEVICE_NAME 0x5 /* 4 to 256 byte ASCII string */ | |
1158 | #define RPRT_HOST_NAME 0x6 /* 4 to 256 byte ASCII string */ | ||
1159 | #define RPRT_NODENAME 0x7 /* 8 byte WWNN */ | ||
1160 | #define RPRT_PORTNAME 0x8 /* 8 byte WWNN */ | ||
1161 | #define RPRT_SYM_PORTNAME 0x9 /* 4 to 256 byte ASCII string */ | ||
1162 | #define RPRT_PORT_TYPE 0xa /* 32-bit unsigned int */ | ||
1163 | #define RPRT_SUPPORTED_CLASS 0xb /* 32-bit unsigned int */ | ||
1164 | #define RPRT_FABRICNAME 0xc /* 8 byte Fabric WWNN */ | ||
1165 | #define RPRT_ACTIVE_FC4_TYPES 0xd /* 32 byte binary array */ | ||
1166 | #define RPRT_PORT_STATE 0x101 /* 32-bit unsigned int */ | ||
1167 | #define RPRT_DISC_PORT 0x102 /* 32-bit unsigned int */ | ||
1168 | #define RPRT_PORT_ID 0x103 /* 32-bit unsigned int */ | ||
1181 | 1169 | ||
1182 | /* | 1170 | /* |
1183 | * Begin HBA configuration parameters. | 1171 | * Begin HBA configuration parameters. |
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index f432ec180cf8..1813c45946f4 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2009-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2009-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -3085,6 +3085,9 @@ struct lpfc_acqe_link { | |||
3085 | #define LPFC_ASYNC_LINK_SPEED_100MBPS 0x2 | 3085 | #define LPFC_ASYNC_LINK_SPEED_100MBPS 0x2 |
3086 | #define LPFC_ASYNC_LINK_SPEED_1GBPS 0x3 | 3086 | #define LPFC_ASYNC_LINK_SPEED_1GBPS 0x3 |
3087 | #define LPFC_ASYNC_LINK_SPEED_10GBPS 0x4 | 3087 | #define LPFC_ASYNC_LINK_SPEED_10GBPS 0x4 |
3088 | #define LPFC_ASYNC_LINK_SPEED_20GBPS 0x5 | ||
3089 | #define LPFC_ASYNC_LINK_SPEED_25GBPS 0x6 | ||
3090 | #define LPFC_ASYNC_LINK_SPEED_40GBPS 0x7 | ||
3088 | #define lpfc_acqe_link_duplex_SHIFT 16 | 3091 | #define lpfc_acqe_link_duplex_SHIFT 16 |
3089 | #define lpfc_acqe_link_duplex_MASK 0x000000FF | 3092 | #define lpfc_acqe_link_duplex_MASK 0x000000FF |
3090 | #define lpfc_acqe_link_duplex_WORD word0 | 3093 | #define lpfc_acqe_link_duplex_WORD word0 |
@@ -3166,7 +3169,7 @@ struct lpfc_acqe_fc_la { | |||
3166 | #define lpfc_acqe_fc_la_speed_SHIFT 24 | 3169 | #define lpfc_acqe_fc_la_speed_SHIFT 24 |
3167 | #define lpfc_acqe_fc_la_speed_MASK 0x000000FF | 3170 | #define lpfc_acqe_fc_la_speed_MASK 0x000000FF |
3168 | #define lpfc_acqe_fc_la_speed_WORD word0 | 3171 | #define lpfc_acqe_fc_la_speed_WORD word0 |
3169 | #define LPFC_FC_LA_SPEED_UNKOWN 0x0 | 3172 | #define LPFC_FC_LA_SPEED_UNKNOWN 0x0 |
3170 | #define LPFC_FC_LA_SPEED_1G 0x1 | 3173 | #define LPFC_FC_LA_SPEED_1G 0x1 |
3171 | #define LPFC_FC_LA_SPEED_2G 0x2 | 3174 | #define LPFC_FC_LA_SPEED_2G 0x2 |
3172 | #define LPFC_FC_LA_SPEED_4G 0x4 | 3175 | #define LPFC_FC_LA_SPEED_4G 0x4 |
@@ -3244,6 +3247,7 @@ struct lpfc_acqe_sli { | |||
3244 | #define LPFC_SLI_EVENT_TYPE_NVLOG_POST 0x4 | 3247 | #define LPFC_SLI_EVENT_TYPE_NVLOG_POST 0x4 |
3245 | #define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5 | 3248 | #define LPFC_SLI_EVENT_TYPE_DIAG_DUMP 0x5 |
3246 | #define LPFC_SLI_EVENT_TYPE_MISCONFIGURED 0x9 | 3249 | #define LPFC_SLI_EVENT_TYPE_MISCONFIGURED 0x9 |
3250 | #define LPFC_SLI_EVENT_TYPE_REMOTE_DPORT 0xA | ||
3247 | }; | 3251 | }; |
3248 | 3252 | ||
3249 | /* | 3253 | /* |
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 0b2c53af85c7..e8c8c1ecc1f5 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -1330,13 +1330,14 @@ lpfc_offline_eratt(struct lpfc_hba *phba) | |||
1330 | void | 1330 | void |
1331 | lpfc_sli4_offline_eratt(struct lpfc_hba *phba) | 1331 | lpfc_sli4_offline_eratt(struct lpfc_hba *phba) |
1332 | { | 1332 | { |
1333 | spin_lock_irq(&phba->hbalock); | ||
1334 | phba->link_state = LPFC_HBA_ERROR; | ||
1335 | spin_unlock_irq(&phba->hbalock); | ||
1336 | |||
1333 | lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); | 1337 | lpfc_offline_prep(phba, LPFC_MBX_NO_WAIT); |
1334 | lpfc_offline(phba); | 1338 | lpfc_offline(phba); |
1335 | lpfc_sli4_brdreset(phba); | ||
1336 | lpfc_hba_down_post(phba); | 1339 | lpfc_hba_down_post(phba); |
1337 | lpfc_sli4_post_status_check(phba); | ||
1338 | lpfc_unblock_mgmt_io(phba); | 1340 | lpfc_unblock_mgmt_io(phba); |
1339 | phba->link_state = LPFC_HBA_ERROR; | ||
1340 | } | 1341 | } |
1341 | 1342 | ||
1342 | /** | 1343 | /** |
@@ -1629,6 +1630,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) | |||
1629 | uint32_t uerrlo_reg, uemasklo_reg; | 1630 | uint32_t uerrlo_reg, uemasklo_reg; |
1630 | uint32_t pci_rd_rc1, pci_rd_rc2; | 1631 | uint32_t pci_rd_rc1, pci_rd_rc2; |
1631 | bool en_rn_msg = true; | 1632 | bool en_rn_msg = true; |
1633 | struct temp_event temp_event_data; | ||
1632 | int rc; | 1634 | int rc; |
1633 | 1635 | ||
1634 | /* If the pci channel is offline, ignore possible errors, since | 1636 | /* If the pci channel is offline, ignore possible errors, since |
@@ -1636,9 +1638,6 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) | |||
1636 | */ | 1638 | */ |
1637 | if (pci_channel_offline(phba->pcidev)) | 1639 | if (pci_channel_offline(phba->pcidev)) |
1638 | return; | 1640 | return; |
1639 | /* If resets are disabled then leave the HBA alone and return */ | ||
1640 | if (!phba->cfg_enable_hba_reset) | ||
1641 | return; | ||
1642 | 1641 | ||
1643 | if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); | 1642 | if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf); |
1644 | switch (if_type) { | 1643 | switch (if_type) { |
@@ -1654,6 +1653,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) | |||
1654 | return; | 1653 | return; |
1655 | lpfc_sli4_offline_eratt(phba); | 1654 | lpfc_sli4_offline_eratt(phba); |
1656 | break; | 1655 | break; |
1656 | |||
1657 | case LPFC_SLI_INTF_IF_TYPE_2: | 1657 | case LPFC_SLI_INTF_IF_TYPE_2: |
1658 | pci_rd_rc1 = lpfc_readl( | 1658 | pci_rd_rc1 = lpfc_readl( |
1659 | phba->sli4_hba.u.if_type2.STATUSregaddr, | 1659 | phba->sli4_hba.u.if_type2.STATUSregaddr, |
@@ -1668,15 +1668,27 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) | |||
1668 | reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr); | 1668 | reg_err1 = readl(phba->sli4_hba.u.if_type2.ERR1regaddr); |
1669 | reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); | 1669 | reg_err2 = readl(phba->sli4_hba.u.if_type2.ERR2regaddr); |
1670 | if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) { | 1670 | if (bf_get(lpfc_sliport_status_oti, &portstat_reg)) { |
1671 | /* TODO: Register for Overtemp async events. */ | ||
1672 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 1671 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
1673 | "2889 Port Overtemperature event, " | 1672 | "2889 Port Overtemperature event, " |
1674 | "taking port offline\n"); | 1673 | "taking port offline Data: x%x x%x\n", |
1674 | reg_err1, reg_err2); | ||
1675 | |||
1676 | temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; | ||
1677 | temp_event_data.event_code = LPFC_CRIT_TEMP; | ||
1678 | temp_event_data.data = 0xFFFFFFFF; | ||
1679 | |||
1680 | shost = lpfc_shost_from_vport(phba->pport); | ||
1681 | fc_host_post_vendor_event(shost, fc_get_event_number(), | ||
1682 | sizeof(temp_event_data), | ||
1683 | (char *)&temp_event_data, | ||
1684 | SCSI_NL_VID_TYPE_PCI | ||
1685 | | PCI_VENDOR_ID_EMULEX); | ||
1686 | |||
1675 | spin_lock_irq(&phba->hbalock); | 1687 | spin_lock_irq(&phba->hbalock); |
1676 | phba->over_temp_state = HBA_OVER_TEMP; | 1688 | phba->over_temp_state = HBA_OVER_TEMP; |
1677 | spin_unlock_irq(&phba->hbalock); | 1689 | spin_unlock_irq(&phba->hbalock); |
1678 | lpfc_sli4_offline_eratt(phba); | 1690 | lpfc_sli4_offline_eratt(phba); |
1679 | break; | 1691 | return; |
1680 | } | 1692 | } |
1681 | if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && | 1693 | if (reg_err1 == SLIPORT_ERR1_REG_ERR_CODE_2 && |
1682 | reg_err2 == SLIPORT_ERR2_REG_FW_RESTART) { | 1694 | reg_err2 == SLIPORT_ERR2_REG_FW_RESTART) { |
@@ -1693,6 +1705,10 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba) | |||
1693 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 1705 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
1694 | "3145 Port Down: Provisioning\n"); | 1706 | "3145 Port Down: Provisioning\n"); |
1695 | 1707 | ||
1708 | /* If resets are disabled then leave the HBA alone and return */ | ||
1709 | if (!phba->cfg_enable_hba_reset) | ||
1710 | return; | ||
1711 | |||
1696 | /* Check port status register for function reset */ | 1712 | /* Check port status register for function reset */ |
1697 | rc = lpfc_sli4_port_sta_fn_reset(phba, LPFC_MBX_NO_WAIT, | 1713 | rc = lpfc_sli4_port_sta_fn_reset(phba, LPFC_MBX_NO_WAIT, |
1698 | en_rn_msg); | 1714 | en_rn_msg); |
@@ -2759,9 +2775,19 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba) | |||
2759 | list_for_each_entry_safe(ndlp, next_ndlp, | 2775 | list_for_each_entry_safe(ndlp, next_ndlp, |
2760 | &vports[i]->fc_nodes, | 2776 | &vports[i]->fc_nodes, |
2761 | nlp_listp) { | 2777 | nlp_listp) { |
2762 | if (NLP_CHK_NODE_ACT(ndlp)) | 2778 | if (NLP_CHK_NODE_ACT(ndlp)) { |
2763 | ndlp->nlp_rpi = | 2779 | ndlp->nlp_rpi = |
2764 | lpfc_sli4_alloc_rpi(phba); | 2780 | lpfc_sli4_alloc_rpi(phba); |
2781 | lpfc_printf_vlog(ndlp->vport, KERN_INFO, | ||
2782 | LOG_NODE, | ||
2783 | "0009 rpi:%x DID:%x " | ||
2784 | "flg:%x map:%x %p\n", | ||
2785 | ndlp->nlp_rpi, | ||
2786 | ndlp->nlp_DID, | ||
2787 | ndlp->nlp_flag, | ||
2788 | ndlp->nlp_usg_map, | ||
2789 | ndlp); | ||
2790 | } | ||
2765 | } | 2791 | } |
2766 | } | 2792 | } |
2767 | } | 2793 | } |
@@ -2925,8 +2951,18 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) | |||
2925 | * RPI. Get a new RPI when the adapter port | 2951 | * RPI. Get a new RPI when the adapter port |
2926 | * comes back online. | 2952 | * comes back online. |
2927 | */ | 2953 | */ |
2928 | if (phba->sli_rev == LPFC_SLI_REV4) | 2954 | if (phba->sli_rev == LPFC_SLI_REV4) { |
2955 | lpfc_printf_vlog(ndlp->vport, | ||
2956 | KERN_INFO, LOG_NODE, | ||
2957 | "0011 lpfc_offline: " | ||
2958 | "ndlp:x%p did %x " | ||
2959 | "usgmap:x%x rpi:%x\n", | ||
2960 | ndlp, ndlp->nlp_DID, | ||
2961 | ndlp->nlp_usg_map, | ||
2962 | ndlp->nlp_rpi); | ||
2963 | |||
2929 | lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); | 2964 | lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); |
2965 | } | ||
2930 | lpfc_unreg_rpi(vports[i], ndlp); | 2966 | lpfc_unreg_rpi(vports[i], ndlp); |
2931 | } | 2967 | } |
2932 | } | 2968 | } |
@@ -3241,12 +3277,17 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) | |||
3241 | struct Scsi_Host *shost; | 3277 | struct Scsi_Host *shost; |
3242 | int error = 0; | 3278 | int error = 0; |
3243 | 3279 | ||
3244 | if (dev != &phba->pcidev->dev) | 3280 | if (dev != &phba->pcidev->dev) { |
3245 | shost = scsi_host_alloc(&lpfc_vport_template, | 3281 | shost = scsi_host_alloc(&lpfc_vport_template, |
3246 | sizeof(struct lpfc_vport)); | 3282 | sizeof(struct lpfc_vport)); |
3247 | else | 3283 | } else { |
3248 | shost = scsi_host_alloc(&lpfc_template, | 3284 | if (phba->sli_rev == LPFC_SLI_REV4) |
3285 | shost = scsi_host_alloc(&lpfc_template, | ||
3249 | sizeof(struct lpfc_vport)); | 3286 | sizeof(struct lpfc_vport)); |
3287 | else | ||
3288 | shost = scsi_host_alloc(&lpfc_template_s3, | ||
3289 | sizeof(struct lpfc_vport)); | ||
3290 | } | ||
3250 | if (!shost) | 3291 | if (!shost) |
3251 | goto out; | 3292 | goto out; |
3252 | 3293 | ||
@@ -3685,6 +3726,11 @@ lpfc_sli4_parse_latt_link_speed(struct lpfc_hba *phba, | |||
3685 | case LPFC_ASYNC_LINK_SPEED_10GBPS: | 3726 | case LPFC_ASYNC_LINK_SPEED_10GBPS: |
3686 | link_speed = LPFC_LINK_SPEED_10GHZ; | 3727 | link_speed = LPFC_LINK_SPEED_10GHZ; |
3687 | break; | 3728 | break; |
3729 | case LPFC_ASYNC_LINK_SPEED_20GBPS: | ||
3730 | case LPFC_ASYNC_LINK_SPEED_25GBPS: | ||
3731 | case LPFC_ASYNC_LINK_SPEED_40GBPS: | ||
3732 | link_speed = LPFC_LINK_SPEED_UNKNOWN; | ||
3733 | break; | ||
3688 | default: | 3734 | default: |
3689 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 3735 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
3690 | "0483 Invalid link-attention link speed: x%x\n", | 3736 | "0483 Invalid link-attention link speed: x%x\n", |
@@ -3756,46 +3802,55 @@ lpfc_sli4_port_speed_parse(struct lpfc_hba *phba, uint32_t evt_code, | |||
3756 | switch (evt_code) { | 3802 | switch (evt_code) { |
3757 | case LPFC_TRAILER_CODE_LINK: | 3803 | case LPFC_TRAILER_CODE_LINK: |
3758 | switch (speed_code) { | 3804 | switch (speed_code) { |
3759 | case LPFC_EVT_CODE_LINK_NO_LINK: | 3805 | case LPFC_ASYNC_LINK_SPEED_ZERO: |
3760 | port_speed = 0; | 3806 | port_speed = 0; |
3761 | break; | 3807 | break; |
3762 | case LPFC_EVT_CODE_LINK_10_MBIT: | 3808 | case LPFC_ASYNC_LINK_SPEED_10MBPS: |
3763 | port_speed = 10; | 3809 | port_speed = 10; |
3764 | break; | 3810 | break; |
3765 | case LPFC_EVT_CODE_LINK_100_MBIT: | 3811 | case LPFC_ASYNC_LINK_SPEED_100MBPS: |
3766 | port_speed = 100; | 3812 | port_speed = 100; |
3767 | break; | 3813 | break; |
3768 | case LPFC_EVT_CODE_LINK_1_GBIT: | 3814 | case LPFC_ASYNC_LINK_SPEED_1GBPS: |
3769 | port_speed = 1000; | 3815 | port_speed = 1000; |
3770 | break; | 3816 | break; |
3771 | case LPFC_EVT_CODE_LINK_10_GBIT: | 3817 | case LPFC_ASYNC_LINK_SPEED_10GBPS: |
3772 | port_speed = 10000; | 3818 | port_speed = 10000; |
3773 | break; | 3819 | break; |
3820 | case LPFC_ASYNC_LINK_SPEED_20GBPS: | ||
3821 | port_speed = 20000; | ||
3822 | break; | ||
3823 | case LPFC_ASYNC_LINK_SPEED_25GBPS: | ||
3824 | port_speed = 25000; | ||
3825 | break; | ||
3826 | case LPFC_ASYNC_LINK_SPEED_40GBPS: | ||
3827 | port_speed = 40000; | ||
3828 | break; | ||
3774 | default: | 3829 | default: |
3775 | port_speed = 0; | 3830 | port_speed = 0; |
3776 | } | 3831 | } |
3777 | break; | 3832 | break; |
3778 | case LPFC_TRAILER_CODE_FC: | 3833 | case LPFC_TRAILER_CODE_FC: |
3779 | switch (speed_code) { | 3834 | switch (speed_code) { |
3780 | case LPFC_EVT_CODE_FC_NO_LINK: | 3835 | case LPFC_FC_LA_SPEED_UNKNOWN: |
3781 | port_speed = 0; | 3836 | port_speed = 0; |
3782 | break; | 3837 | break; |
3783 | case LPFC_EVT_CODE_FC_1_GBAUD: | 3838 | case LPFC_FC_LA_SPEED_1G: |
3784 | port_speed = 1000; | 3839 | port_speed = 1000; |
3785 | break; | 3840 | break; |
3786 | case LPFC_EVT_CODE_FC_2_GBAUD: | 3841 | case LPFC_FC_LA_SPEED_2G: |
3787 | port_speed = 2000; | 3842 | port_speed = 2000; |
3788 | break; | 3843 | break; |
3789 | case LPFC_EVT_CODE_FC_4_GBAUD: | 3844 | case LPFC_FC_LA_SPEED_4G: |
3790 | port_speed = 4000; | 3845 | port_speed = 4000; |
3791 | break; | 3846 | break; |
3792 | case LPFC_EVT_CODE_FC_8_GBAUD: | 3847 | case LPFC_FC_LA_SPEED_8G: |
3793 | port_speed = 8000; | 3848 | port_speed = 8000; |
3794 | break; | 3849 | break; |
3795 | case LPFC_EVT_CODE_FC_10_GBAUD: | 3850 | case LPFC_FC_LA_SPEED_10G: |
3796 | port_speed = 10000; | 3851 | port_speed = 10000; |
3797 | break; | 3852 | break; |
3798 | case LPFC_EVT_CODE_FC_16_GBAUD: | 3853 | case LPFC_FC_LA_SPEED_16G: |
3799 | port_speed = 16000; | 3854 | port_speed = 16000; |
3800 | break; | 3855 | break; |
3801 | default: | 3856 | default: |
@@ -4044,18 +4099,21 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli) | |||
4044 | char port_name; | 4099 | char port_name; |
4045 | char message[128]; | 4100 | char message[128]; |
4046 | uint8_t status; | 4101 | uint8_t status; |
4102 | uint8_t evt_type; | ||
4103 | struct temp_event temp_event_data; | ||
4047 | struct lpfc_acqe_misconfigured_event *misconfigured; | 4104 | struct lpfc_acqe_misconfigured_event *misconfigured; |
4105 | struct Scsi_Host *shost; | ||
4106 | |||
4107 | evt_type = bf_get(lpfc_trailer_type, acqe_sli); | ||
4048 | 4108 | ||
4049 | /* special case misconfigured event as it contains data for all ports */ | 4109 | /* Special case Lancer */ |
4050 | if ((bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != | 4110 | if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) != |
4051 | LPFC_SLI_INTF_IF_TYPE_2) || | 4111 | LPFC_SLI_INTF_IF_TYPE_2) { |
4052 | (bf_get(lpfc_trailer_type, acqe_sli) != | ||
4053 | LPFC_SLI_EVENT_TYPE_MISCONFIGURED)) { | ||
4054 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | 4112 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
4055 | "2901 Async SLI event - Event Data1:x%08x Event Data2:" | 4113 | "2901 Async SLI event - Event Data1:x%08x Event Data2:" |
4056 | "x%08x SLI Event Type:%d\n", | 4114 | "x%08x SLI Event Type:%d\n", |
4057 | acqe_sli->event_data1, acqe_sli->event_data2, | 4115 | acqe_sli->event_data1, acqe_sli->event_data2, |
4058 | bf_get(lpfc_trailer_type, acqe_sli)); | 4116 | evt_type); |
4059 | return; | 4117 | return; |
4060 | } | 4118 | } |
4061 | 4119 | ||
@@ -4063,58 +4121,107 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli) | |||
4063 | if (port_name == 0x00) | 4121 | if (port_name == 0x00) |
4064 | port_name = '?'; /* get port name is empty */ | 4122 | port_name = '?'; /* get port name is empty */ |
4065 | 4123 | ||
4066 | misconfigured = (struct lpfc_acqe_misconfigured_event *) | 4124 | switch (evt_type) { |
4125 | case LPFC_SLI_EVENT_TYPE_OVER_TEMP: | ||
4126 | temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; | ||
4127 | temp_event_data.event_code = LPFC_THRESHOLD_TEMP; | ||
4128 | temp_event_data.data = (uint32_t)acqe_sli->event_data1; | ||
4129 | |||
4130 | lpfc_printf_log(phba, KERN_WARNING, LOG_SLI, | ||
4131 | "3190 Over Temperature:%d Celsius- Port Name %c\n", | ||
4132 | acqe_sli->event_data1, port_name); | ||
4133 | |||
4134 | shost = lpfc_shost_from_vport(phba->pport); | ||
4135 | fc_host_post_vendor_event(shost, fc_get_event_number(), | ||
4136 | sizeof(temp_event_data), | ||
4137 | (char *)&temp_event_data, | ||
4138 | SCSI_NL_VID_TYPE_PCI | ||
4139 | | PCI_VENDOR_ID_EMULEX); | ||
4140 | break; | ||
4141 | case LPFC_SLI_EVENT_TYPE_NORM_TEMP: | ||
4142 | temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT; | ||
4143 | temp_event_data.event_code = LPFC_NORMAL_TEMP; | ||
4144 | temp_event_data.data = (uint32_t)acqe_sli->event_data1; | ||
4145 | |||
4146 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
4147 | "3191 Normal Temperature:%d Celsius - Port Name %c\n", | ||
4148 | acqe_sli->event_data1, port_name); | ||
4149 | |||
4150 | shost = lpfc_shost_from_vport(phba->pport); | ||
4151 | fc_host_post_vendor_event(shost, fc_get_event_number(), | ||
4152 | sizeof(temp_event_data), | ||
4153 | (char *)&temp_event_data, | ||
4154 | SCSI_NL_VID_TYPE_PCI | ||
4155 | | PCI_VENDOR_ID_EMULEX); | ||
4156 | break; | ||
4157 | case LPFC_SLI_EVENT_TYPE_MISCONFIGURED: | ||
4158 | misconfigured = (struct lpfc_acqe_misconfigured_event *) | ||
4067 | &acqe_sli->event_data1; | 4159 | &acqe_sli->event_data1; |
4068 | 4160 | ||
4069 | /* fetch the status for this port */ | 4161 | /* fetch the status for this port */ |
4070 | switch (phba->sli4_hba.lnk_info.lnk_no) { | 4162 | switch (phba->sli4_hba.lnk_info.lnk_no) { |
4071 | case LPFC_LINK_NUMBER_0: | 4163 | case LPFC_LINK_NUMBER_0: |
4072 | status = bf_get(lpfc_sli_misconfigured_port0, | 4164 | status = bf_get(lpfc_sli_misconfigured_port0, |
4073 | &misconfigured->theEvent); | 4165 | &misconfigured->theEvent); |
4074 | break; | 4166 | break; |
4075 | case LPFC_LINK_NUMBER_1: | 4167 | case LPFC_LINK_NUMBER_1: |
4076 | status = bf_get(lpfc_sli_misconfigured_port1, | 4168 | status = bf_get(lpfc_sli_misconfigured_port1, |
4077 | &misconfigured->theEvent); | 4169 | &misconfigured->theEvent); |
4078 | break; | 4170 | break; |
4079 | case LPFC_LINK_NUMBER_2: | 4171 | case LPFC_LINK_NUMBER_2: |
4080 | status = bf_get(lpfc_sli_misconfigured_port2, | 4172 | status = bf_get(lpfc_sli_misconfigured_port2, |
4081 | &misconfigured->theEvent); | 4173 | &misconfigured->theEvent); |
4082 | break; | 4174 | break; |
4083 | case LPFC_LINK_NUMBER_3: | 4175 | case LPFC_LINK_NUMBER_3: |
4084 | status = bf_get(lpfc_sli_misconfigured_port3, | 4176 | status = bf_get(lpfc_sli_misconfigured_port3, |
4085 | &misconfigured->theEvent); | 4177 | &misconfigured->theEvent); |
4086 | break; | 4178 | break; |
4087 | default: | 4179 | default: |
4088 | status = ~LPFC_SLI_EVENT_STATUS_VALID; | 4180 | status = ~LPFC_SLI_EVENT_STATUS_VALID; |
4089 | break; | 4181 | break; |
4090 | } | 4182 | } |
4091 | 4183 | ||
4092 | switch (status) { | 4184 | switch (status) { |
4093 | case LPFC_SLI_EVENT_STATUS_VALID: | 4185 | case LPFC_SLI_EVENT_STATUS_VALID: |
4094 | return; /* no message if the sfp is okay */ | 4186 | return; /* no message if the sfp is okay */ |
4095 | case LPFC_SLI_EVENT_STATUS_NOT_PRESENT: | 4187 | case LPFC_SLI_EVENT_STATUS_NOT_PRESENT: |
4096 | sprintf(message, "Optics faulted/incorrectly installed/not " \ | 4188 | sprintf(message, "Optics faulted/incorrectly " |
4097 | "installed - Reseat optics, if issue not " | 4189 | "installed/not installed - Reseat optics, " |
4098 | "resolved, replace."); | 4190 | "if issue not resolved, replace."); |
4099 | break; | 4191 | break; |
4100 | case LPFC_SLI_EVENT_STATUS_WRONG_TYPE: | 4192 | case LPFC_SLI_EVENT_STATUS_WRONG_TYPE: |
4101 | sprintf(message, | 4193 | sprintf(message, |
4102 | "Optics of two types installed - Remove one optic or " \ | 4194 | "Optics of two types installed - Remove one " |
4103 | "install matching pair of optics."); | 4195 | "optic or install matching pair of optics."); |
4104 | break; | 4196 | break; |
4105 | case LPFC_SLI_EVENT_STATUS_UNSUPPORTED: | 4197 | case LPFC_SLI_EVENT_STATUS_UNSUPPORTED: |
4106 | sprintf(message, "Incompatible optics - Replace with " \ | 4198 | sprintf(message, "Incompatible optics - Replace with " |
4107 | "compatible optics for card to function."); | 4199 | "compatible optics for card to function."); |
4200 | break; | ||
4201 | default: | ||
4202 | /* firmware is reporting a status we don't know about */ | ||
4203 | sprintf(message, "Unknown event status x%02x", status); | ||
4204 | break; | ||
4205 | } | ||
4206 | |||
4207 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
4208 | "3176 Misconfigured Physical Port - " | ||
4209 | "Port Name %c %s\n", port_name, message); | ||
4210 | break; | ||
4211 | case LPFC_SLI_EVENT_TYPE_REMOTE_DPORT: | ||
4212 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
4213 | "3192 Remote DPort Test Initiated - " | ||
4214 | "Event Data1:x%08x Event Data2: x%08x\n", | ||
4215 | acqe_sli->event_data1, acqe_sli->event_data2); | ||
4108 | break; | 4216 | break; |
4109 | default: | 4217 | default: |
4110 | /* firmware is reporting a status we don't know about */ | 4218 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, |
4111 | sprintf(message, "Unknown event status x%02x", status); | 4219 | "3193 Async SLI event - Event Data1:x%08x Event Data2:" |
4220 | "x%08x SLI Event Type:%d\n", | ||
4221 | acqe_sli->event_data1, acqe_sli->event_data2, | ||
4222 | evt_type); | ||
4112 | break; | 4223 | break; |
4113 | } | 4224 | } |
4114 | |||
4115 | lpfc_printf_log(phba, KERN_ERR, LOG_SLI, | ||
4116 | "3176 Misconfigured Physical Port - " | ||
4117 | "Port Name %c %s\n", port_name, message); | ||
4118 | } | 4225 | } |
4119 | 4226 | ||
4120 | /** | 4227 | /** |
@@ -5183,6 +5290,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) | |||
5183 | rc = lpfc_pci_function_reset(phba); | 5290 | rc = lpfc_pci_function_reset(phba); |
5184 | if (unlikely(rc)) | 5291 | if (unlikely(rc)) |
5185 | return -ENODEV; | 5292 | return -ENODEV; |
5293 | phba->temp_sensor_support = 1; | ||
5186 | } | 5294 | } |
5187 | 5295 | ||
5188 | /* Create the bootstrap mailbox command */ | 5296 | /* Create the bootstrap mailbox command */ |
@@ -7647,6 +7755,14 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba) | |||
7647 | goto out_destroy_els_rq; | 7755 | goto out_destroy_els_rq; |
7648 | } | 7756 | } |
7649 | } | 7757 | } |
7758 | |||
7759 | /* | ||
7760 | * Configure EQ delay multipier for interrupt coalescing using | ||
7761 | * MODIFY_EQ_DELAY for all EQs created, LPFC_MAX_EQ_DELAY at a time. | ||
7762 | */ | ||
7763 | for (fcp_eqidx = 0; fcp_eqidx < phba->cfg_fcp_io_channel; | ||
7764 | fcp_eqidx += LPFC_MAX_EQ_DELAY) | ||
7765 | lpfc_modify_fcp_eq_delay(phba, fcp_eqidx); | ||
7650 | return 0; | 7766 | return 0; |
7651 | 7767 | ||
7652 | out_destroy_els_rq: | 7768 | out_destroy_els_rq: |
@@ -7953,7 +8069,7 @@ wait: | |||
7953 | * up to 30 seconds. If the port doesn't respond, treat | 8069 | * up to 30 seconds. If the port doesn't respond, treat |
7954 | * it as an error. | 8070 | * it as an error. |
7955 | */ | 8071 | */ |
7956 | for (rdy_chk = 0; rdy_chk < 3000; rdy_chk++) { | 8072 | for (rdy_chk = 0; rdy_chk < 1500; rdy_chk++) { |
7957 | if (lpfc_readl(phba->sli4_hba.u.if_type2. | 8073 | if (lpfc_readl(phba->sli4_hba.u.if_type2. |
7958 | STATUSregaddr, ®_data.word0)) { | 8074 | STATUSregaddr, ®_data.word0)) { |
7959 | rc = -ENODEV; | 8075 | rc = -ENODEV; |
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c index 06241f590c1e..816f596cda60 100644 --- a/drivers/scsi/lpfc/lpfc_mbox.c +++ b/drivers/scsi/lpfc/lpfc_mbox.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2013 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index 5cc1103d811e..4cb9882af157 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2013 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -276,6 +276,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
276 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 276 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
277 | struct lpfc_hba *phba = vport->phba; | 277 | struct lpfc_hba *phba = vport->phba; |
278 | struct lpfc_dmabuf *pcmd; | 278 | struct lpfc_dmabuf *pcmd; |
279 | uint64_t nlp_portwwn = 0; | ||
279 | uint32_t *lp; | 280 | uint32_t *lp; |
280 | IOCB_t *icmd; | 281 | IOCB_t *icmd; |
281 | struct serv_parm *sp; | 282 | struct serv_parm *sp; |
@@ -332,6 +333,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
332 | NULL); | 333 | NULL); |
333 | return 0; | 334 | return 0; |
334 | } | 335 | } |
336 | |||
337 | nlp_portwwn = wwn_to_u64(ndlp->nlp_portname.u.wwn); | ||
335 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) { | 338 | if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3, 0) == 0)) { |
336 | /* Reject this request because invalid parameters */ | 339 | /* Reject this request because invalid parameters */ |
337 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; | 340 | stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC; |
@@ -367,7 +370,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
367 | ndlp->nlp_maxframe = | 370 | ndlp->nlp_maxframe = |
368 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; | 371 | ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb; |
369 | 372 | ||
370 | /* no need to reg_login if we are already in one of these states */ | 373 | /* if already logged in, do implicit logout */ |
371 | switch (ndlp->nlp_state) { | 374 | switch (ndlp->nlp_state) { |
372 | case NLP_STE_NPR_NODE: | 375 | case NLP_STE_NPR_NODE: |
373 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) | 376 | if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) |
@@ -376,8 +379,26 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, | |||
376 | case NLP_STE_PRLI_ISSUE: | 379 | case NLP_STE_PRLI_ISSUE: |
377 | case NLP_STE_UNMAPPED_NODE: | 380 | case NLP_STE_UNMAPPED_NODE: |
378 | case NLP_STE_MAPPED_NODE: | 381 | case NLP_STE_MAPPED_NODE: |
379 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL); | 382 | /* lpfc_plogi_confirm_nport skips fabric did, handle it here */ |
380 | return 1; | 383 | if (!(ndlp->nlp_type & NLP_FABRIC)) { |
384 | lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, | ||
385 | ndlp, NULL); | ||
386 | return 1; | ||
387 | } | ||
388 | if (nlp_portwwn != 0 && | ||
389 | nlp_portwwn != wwn_to_u64(sp->portName.u.wwn)) | ||
390 | lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS, | ||
391 | "0143 PLOGI recv'd from DID: x%x " | ||
392 | "WWPN changed: old %llx new %llx\n", | ||
393 | ndlp->nlp_DID, | ||
394 | (unsigned long long)nlp_portwwn, | ||
395 | (unsigned long long) | ||
396 | wwn_to_u64(sp->portName.u.wwn)); | ||
397 | |||
398 | ndlp->nlp_prev_state = ndlp->nlp_state; | ||
399 | /* rport needs to be unregistered first */ | ||
400 | lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE); | ||
401 | break; | ||
381 | } | 402 | } |
382 | 403 | ||
383 | /* Check for Nport to NPort pt2pt protocol */ | 404 | /* Check for Nport to NPort pt2pt protocol */ |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 4f9222eb2266..cb73cf9e9ba5 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -1130,6 +1130,25 @@ lpfc_release_scsi_buf(struct lpfc_hba *phba, struct lpfc_scsi_buf *psb) | |||
1130 | } | 1130 | } |
1131 | 1131 | ||
1132 | /** | 1132 | /** |
1133 | * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB | ||
1134 | * @data: A pointer to the immediate command data portion of the IOCB. | ||
1135 | * @fcp_cmnd: The FCP Command that is provided by the SCSI layer. | ||
1136 | * | ||
1137 | * The routine copies the entire FCP command from @fcp_cmnd to @data while | ||
1138 | * byte swapping the data to big endian format for transmission on the wire. | ||
1139 | **/ | ||
1140 | static void | ||
1141 | lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd) | ||
1142 | { | ||
1143 | int i, j; | ||
1144 | |||
1145 | for (i = 0, j = 0; i < sizeof(struct fcp_cmnd); | ||
1146 | i += sizeof(uint32_t), j++) { | ||
1147 | ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]); | ||
1148 | } | ||
1149 | } | ||
1150 | |||
1151 | /** | ||
1133 | * lpfc_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec | 1152 | * lpfc_scsi_prep_dma_buf_s3 - DMA mapping for scsi buffer to SLI3 IF spec |
1134 | * @phba: The Hba for which this call is being executed. | 1153 | * @phba: The Hba for which this call is being executed. |
1135 | * @lpfc_cmd: The scsi buffer which is going to be mapped. | 1154 | * @lpfc_cmd: The scsi buffer which is going to be mapped. |
@@ -1264,6 +1283,7 @@ lpfc_scsi_prep_dma_buf_s3(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd) | |||
1264 | * we need to set word 4 of IOCB here | 1283 | * we need to set word 4 of IOCB here |
1265 | */ | 1284 | */ |
1266 | iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd); | 1285 | iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd); |
1286 | lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); | ||
1267 | return 0; | 1287 | return 0; |
1268 | } | 1288 | } |
1269 | 1289 | ||
@@ -4127,24 +4147,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, | |||
4127 | } | 4147 | } |
4128 | 4148 | ||
4129 | /** | 4149 | /** |
4130 | * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB | ||
4131 | * @data: A pointer to the immediate command data portion of the IOCB. | ||
4132 | * @fcp_cmnd: The FCP Command that is provided by the SCSI layer. | ||
4133 | * | ||
4134 | * The routine copies the entire FCP command from @fcp_cmnd to @data while | ||
4135 | * byte swapping the data to big endian format for transmission on the wire. | ||
4136 | **/ | ||
4137 | static void | ||
4138 | lpfc_fcpcmd_to_iocb(uint8_t *data, struct fcp_cmnd *fcp_cmnd) | ||
4139 | { | ||
4140 | int i, j; | ||
4141 | for (i = 0, j = 0; i < sizeof(struct fcp_cmnd); | ||
4142 | i += sizeof(uint32_t), j++) { | ||
4143 | ((uint32_t *)data)[j] = cpu_to_be32(((uint32_t *)fcp_cmnd)[j]); | ||
4144 | } | ||
4145 | } | ||
4146 | |||
4147 | /** | ||
4148 | * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit | 4150 | * lpfc_scsi_prep_cmnd - Wrapper func for convert scsi cmnd to FCP info unit |
4149 | * @vport: The virtual port for which this call is being executed. | 4151 | * @vport: The virtual port for which this call is being executed. |
4150 | * @lpfc_cmd: The scsi command which needs to send. | 4152 | * @lpfc_cmd: The scsi command which needs to send. |
@@ -4223,9 +4225,6 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, | |||
4223 | fcp_cmnd->fcpCntl3 = 0; | 4225 | fcp_cmnd->fcpCntl3 = 0; |
4224 | phba->fc4ControlRequests++; | 4226 | phba->fc4ControlRequests++; |
4225 | } | 4227 | } |
4226 | if (phba->sli_rev == 3 && | ||
4227 | !(phba->sli3_options & LPFC_SLI3_BG_ENABLED)) | ||
4228 | lpfc_fcpcmd_to_iocb(iocb_cmd->unsli3.fcp_ext.icd, fcp_cmnd); | ||
4229 | /* | 4228 | /* |
4230 | * Finish initializing those IOCB fields that are independent | 4229 | * Finish initializing those IOCB fields that are independent |
4231 | * of the scsi_cmnd request_buffer | 4230 | * of the scsi_cmnd request_buffer |
@@ -5118,9 +5117,10 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) | |||
5118 | int status; | 5117 | int status; |
5119 | 5118 | ||
5120 | rdata = lpfc_rport_data_from_scsi_device(cmnd->device); | 5119 | rdata = lpfc_rport_data_from_scsi_device(cmnd->device); |
5121 | if (!rdata) { | 5120 | if (!rdata || !rdata->pnode) { |
5122 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 5121 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
5123 | "0798 Device Reset rport failure: rdata x%p\n", rdata); | 5122 | "0798 Device Reset rport failure: rdata x%p\n", |
5123 | rdata); | ||
5124 | return FAILED; | 5124 | return FAILED; |
5125 | } | 5125 | } |
5126 | pnode = rdata->pnode; | 5126 | pnode = rdata->pnode; |
@@ -5202,10 +5202,12 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) | |||
5202 | if (status == FAILED) { | 5202 | if (status == FAILED) { |
5203 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, | 5203 | lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, |
5204 | "0722 Target Reset rport failure: rdata x%p\n", rdata); | 5204 | "0722 Target Reset rport failure: rdata x%p\n", rdata); |
5205 | spin_lock_irq(shost->host_lock); | 5205 | if (pnode) { |
5206 | pnode->nlp_flag &= ~NLP_NPR_ADISC; | 5206 | spin_lock_irq(shost->host_lock); |
5207 | pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; | 5207 | pnode->nlp_flag &= ~NLP_NPR_ADISC; |
5208 | spin_unlock_irq(shost->host_lock); | 5208 | pnode->nlp_fcp_info &= ~NLP_FCP_2_DEVICE; |
5209 | spin_unlock_irq(shost->host_lock); | ||
5210 | } | ||
5209 | lpfc_reset_flush_io_context(vport, tgt_id, lun_id, | 5211 | lpfc_reset_flush_io_context(vport, tgt_id, lun_id, |
5210 | LPFC_CTX_TGT); | 5212 | LPFC_CTX_TGT); |
5211 | return FAST_IO_FAIL; | 5213 | return FAST_IO_FAIL; |
@@ -5857,6 +5859,31 @@ lpfc_disable_oas_lun(struct lpfc_hba *phba, struct lpfc_name *vport_wwpn, | |||
5857 | return false; | 5859 | return false; |
5858 | } | 5860 | } |
5859 | 5861 | ||
5862 | struct scsi_host_template lpfc_template_s3 = { | ||
5863 | .module = THIS_MODULE, | ||
5864 | .name = LPFC_DRIVER_NAME, | ||
5865 | .info = lpfc_info, | ||
5866 | .queuecommand = lpfc_queuecommand, | ||
5867 | .eh_abort_handler = lpfc_abort_handler, | ||
5868 | .eh_device_reset_handler = lpfc_device_reset_handler, | ||
5869 | .eh_target_reset_handler = lpfc_target_reset_handler, | ||
5870 | .eh_bus_reset_handler = lpfc_bus_reset_handler, | ||
5871 | .slave_alloc = lpfc_slave_alloc, | ||
5872 | .slave_configure = lpfc_slave_configure, | ||
5873 | .slave_destroy = lpfc_slave_destroy, | ||
5874 | .scan_finished = lpfc_scan_finished, | ||
5875 | .this_id = -1, | ||
5876 | .sg_tablesize = LPFC_DEFAULT_SG_SEG_CNT, | ||
5877 | .cmd_per_lun = LPFC_CMD_PER_LUN, | ||
5878 | .use_clustering = ENABLE_CLUSTERING, | ||
5879 | .shost_attrs = lpfc_hba_attrs, | ||
5880 | .max_sectors = 0xFFFF, | ||
5881 | .vendor_id = LPFC_NL_VENDOR_ID, | ||
5882 | .change_queue_depth = scsi_change_queue_depth, | ||
5883 | .use_blk_tags = 1, | ||
5884 | .track_queue_depth = 1, | ||
5885 | }; | ||
5886 | |||
5860 | struct scsi_host_template lpfc_template = { | 5887 | struct scsi_host_template lpfc_template = { |
5861 | .module = THIS_MODULE, | 5888 | .module = THIS_MODULE, |
5862 | .name = LPFC_DRIVER_NAME, | 5889 | .name = LPFC_DRIVER_NAME, |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index 0389ac1e7b83..474e30cdee6e 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 207a43d952fa..56f73682d4bd 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * | 7 | * Portions Copyright (C) 2004-2005 Christoph Hellwig * |
@@ -918,12 +918,16 @@ __lpfc_sli_get_sglq(struct lpfc_hba *phba, struct lpfc_iocbq *piocbq) | |||
918 | lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1; | 918 | lpfc_cmd = (struct lpfc_scsi_buf *) piocbq->context1; |
919 | ndlp = lpfc_cmd->rdata->pnode; | 919 | ndlp = lpfc_cmd->rdata->pnode; |
920 | } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && | 920 | } else if ((piocbq->iocb.ulpCommand == CMD_GEN_REQUEST64_CR) && |
921 | !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) | 921 | !(piocbq->iocb_flag & LPFC_IO_LIBDFC)) { |
922 | ndlp = piocbq->context_un.ndlp; | 922 | ndlp = piocbq->context_un.ndlp; |
923 | else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) | 923 | } else if (piocbq->iocb_flag & LPFC_IO_LIBDFC) { |
924 | ndlp = piocbq->context_un.ndlp; | 924 | if (piocbq->iocb_flag & LPFC_IO_LOOPBACK) |
925 | else | 925 | ndlp = NULL; |
926 | else | ||
927 | ndlp = piocbq->context_un.ndlp; | ||
928 | } else { | ||
926 | ndlp = piocbq->context1; | 929 | ndlp = piocbq->context1; |
930 | } | ||
927 | 931 | ||
928 | list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list); | 932 | list_remove_head(lpfc_sgl_list, sglq, struct lpfc_sglq, list); |
929 | start_sglq = sglq; | 933 | start_sglq = sglq; |
@@ -2213,6 +2217,46 @@ lpfc_sli_def_mbox_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | |||
2213 | else | 2217 | else |
2214 | mempool_free(pmb, phba->mbox_mem_pool); | 2218 | mempool_free(pmb, phba->mbox_mem_pool); |
2215 | } | 2219 | } |
2220 | /** | ||
2221 | * lpfc_sli4_unreg_rpi_cmpl_clr - mailbox completion handler | ||
2222 | * @phba: Pointer to HBA context object. | ||
2223 | * @pmb: Pointer to mailbox object. | ||
2224 | * | ||
2225 | * This function is the unreg rpi mailbox completion handler. It | ||
2226 | * frees the memory resources associated with the completed mailbox | ||
2227 | * command. An additional refrenece is put on the ndlp to prevent | ||
2228 | * lpfc_nlp_release from freeing the rpi bit in the bitmask before | ||
2229 | * the unreg mailbox command completes, this routine puts the | ||
2230 | * reference back. | ||
2231 | * | ||
2232 | **/ | ||
2233 | void | ||
2234 | lpfc_sli4_unreg_rpi_cmpl_clr(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) | ||
2235 | { | ||
2236 | struct lpfc_vport *vport = pmb->vport; | ||
2237 | struct lpfc_nodelist *ndlp; | ||
2238 | |||
2239 | ndlp = pmb->context1; | ||
2240 | if (pmb->u.mb.mbxCommand == MBX_UNREG_LOGIN) { | ||
2241 | if (phba->sli_rev == LPFC_SLI_REV4 && | ||
2242 | (bf_get(lpfc_sli_intf_if_type, | ||
2243 | &phba->sli4_hba.sli_intf) == | ||
2244 | LPFC_SLI_INTF_IF_TYPE_2)) { | ||
2245 | if (ndlp) { | ||
2246 | lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, | ||
2247 | "0010 UNREG_LOGIN vpi:%x " | ||
2248 | "rpi:%x DID:%x map:%x %p\n", | ||
2249 | vport->vpi, ndlp->nlp_rpi, | ||
2250 | ndlp->nlp_DID, | ||
2251 | ndlp->nlp_usg_map, ndlp); | ||
2252 | |||
2253 | lpfc_nlp_put(ndlp); | ||
2254 | } | ||
2255 | } | ||
2256 | } | ||
2257 | |||
2258 | mempool_free(pmb, phba->mbox_mem_pool); | ||
2259 | } | ||
2216 | 2260 | ||
2217 | /** | 2261 | /** |
2218 | * lpfc_sli_handle_mb_event - Handle mailbox completions from firmware | 2262 | * lpfc_sli_handle_mb_event - Handle mailbox completions from firmware |
@@ -12842,7 +12886,7 @@ lpfc_dual_chute_pci_bar_map(struct lpfc_hba *phba, uint16_t pci_barset) | |||
12842 | * fails this function will return -ENXIO. | 12886 | * fails this function will return -ENXIO. |
12843 | **/ | 12887 | **/ |
12844 | int | 12888 | int |
12845 | lpfc_modify_fcp_eq_delay(struct lpfc_hba *phba, uint16_t startq) | 12889 | lpfc_modify_fcp_eq_delay(struct lpfc_hba *phba, uint32_t startq) |
12846 | { | 12890 | { |
12847 | struct lpfc_mbx_modify_eq_delay *eq_delay; | 12891 | struct lpfc_mbx_modify_eq_delay *eq_delay; |
12848 | LPFC_MBOXQ_t *mbox; | 12892 | LPFC_MBOXQ_t *mbox; |
@@ -12959,11 +13003,8 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax) | |||
12959 | bf_set(lpfc_eq_context_size, &eq_create->u.request.context, | 13003 | bf_set(lpfc_eq_context_size, &eq_create->u.request.context, |
12960 | LPFC_EQE_SIZE); | 13004 | LPFC_EQE_SIZE); |
12961 | bf_set(lpfc_eq_context_valid, &eq_create->u.request.context, 1); | 13005 | bf_set(lpfc_eq_context_valid, &eq_create->u.request.context, 1); |
12962 | /* Calculate delay multiper from maximum interrupt per second */ | 13006 | /* don't setup delay multiplier using EQ_CREATE */ |
12963 | if (imax > LPFC_DMULT_CONST) | 13007 | dmult = 0; |
12964 | dmult = 0; | ||
12965 | else | ||
12966 | dmult = LPFC_DMULT_CONST/imax - 1; | ||
12967 | bf_set(lpfc_eq_context_delay_multi, &eq_create->u.request.context, | 13008 | bf_set(lpfc_eq_context_delay_multi, &eq_create->u.request.context, |
12968 | dmult); | 13009 | dmult); |
12969 | switch (eq->entry_count) { | 13010 | switch (eq->entry_count) { |
@@ -15662,14 +15703,14 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15662 | struct lpfc_rpi_hdr *rpi_hdr; | 15703 | struct lpfc_rpi_hdr *rpi_hdr; |
15663 | unsigned long iflag; | 15704 | unsigned long iflag; |
15664 | 15705 | ||
15665 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; | ||
15666 | rpi_limit = phba->sli4_hba.next_rpi; | ||
15667 | |||
15668 | /* | 15706 | /* |
15669 | * Fetch the next logical rpi. Because this index is logical, | 15707 | * Fetch the next logical rpi. Because this index is logical, |
15670 | * the driver starts at 0 each time. | 15708 | * the driver starts at 0 each time. |
15671 | */ | 15709 | */ |
15672 | spin_lock_irqsave(&phba->hbalock, iflag); | 15710 | spin_lock_irqsave(&phba->hbalock, iflag); |
15711 | max_rpi = phba->sli4_hba.max_cfg_param.max_rpi; | ||
15712 | rpi_limit = phba->sli4_hba.next_rpi; | ||
15713 | |||
15673 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, 0); | 15714 | rpi = find_next_zero_bit(phba->sli4_hba.rpi_bmask, rpi_limit, 0); |
15674 | if (rpi >= rpi_limit) | 15715 | if (rpi >= rpi_limit) |
15675 | rpi = LPFC_RPI_ALLOC_ERROR; | 15716 | rpi = LPFC_RPI_ALLOC_ERROR; |
@@ -15678,6 +15719,9 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) | |||
15678 | phba->sli4_hba.max_cfg_param.rpi_used++; | 15719 | phba->sli4_hba.max_cfg_param.rpi_used++; |
15679 | phba->sli4_hba.rpi_count++; | 15720 | phba->sli4_hba.rpi_count++; |
15680 | } | 15721 | } |
15722 | lpfc_printf_log(phba, KERN_INFO, LOG_SLI, | ||
15723 | "0001 rpi:%x max:%x lim:%x\n", | ||
15724 | (int) rpi, max_rpi, rpi_limit); | ||
15681 | 15725 | ||
15682 | /* | 15726 | /* |
15683 | * Don't try to allocate more rpi header regions if the device limit | 15727 | * Don't try to allocate more rpi header regions if the device limit |
diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index 4a01452415cf..7fe99ff80846 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -80,6 +80,7 @@ struct lpfc_iocbq { | |||
80 | 80 | ||
81 | #define LPFC_IO_OAS 0x10000 /* OAS FCP IO */ | 81 | #define LPFC_IO_OAS 0x10000 /* OAS FCP IO */ |
82 | #define LPFC_IO_FOF 0x20000 /* FOF FCP IO */ | 82 | #define LPFC_IO_FOF 0x20000 /* FOF FCP IO */ |
83 | #define LPFC_IO_LOOPBACK 0x40000 /* Loopback IO */ | ||
83 | 84 | ||
84 | uint32_t drvrTimeout; /* driver timeout in seconds */ | 85 | uint32_t drvrTimeout; /* driver timeout in seconds */ |
85 | uint32_t fcp_wqidx; /* index to FCP work queue */ | 86 | uint32_t fcp_wqidx; /* index to FCP work queue */ |
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h index 22ceb2b05ba1..6eca3b8124d3 100644 --- a/drivers/scsi/lpfc/lpfc_sli4.h +++ b/drivers/scsi/lpfc/lpfc_sli4.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2009-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2009-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -671,7 +671,7 @@ struct lpfc_queue *lpfc_sli4_queue_alloc(struct lpfc_hba *, uint32_t, | |||
671 | uint32_t); | 671 | uint32_t); |
672 | void lpfc_sli4_queue_free(struct lpfc_queue *); | 672 | void lpfc_sli4_queue_free(struct lpfc_queue *); |
673 | int lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t); | 673 | int lpfc_eq_create(struct lpfc_hba *, struct lpfc_queue *, uint32_t); |
674 | int lpfc_modify_fcp_eq_delay(struct lpfc_hba *, uint16_t); | 674 | int lpfc_modify_fcp_eq_delay(struct lpfc_hba *, uint32_t); |
675 | int lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *, | 675 | int lpfc_cq_create(struct lpfc_hba *, struct lpfc_queue *, |
676 | struct lpfc_queue *, uint32_t, uint32_t); | 676 | struct lpfc_queue *, uint32_t, uint32_t); |
677 | int32_t lpfc_mq_create(struct lpfc_hba *, struct lpfc_queue *, | 677 | int32_t lpfc_mq_create(struct lpfc_hba *, struct lpfc_queue *, |
diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index 89413add2252..c37bb9f91c3b 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /******************************************************************* | 1 | /******************************************************************* |
2 | * This file is part of the Emulex Linux Device Driver for * | 2 | * This file is part of the Emulex Linux Device Driver for * |
3 | * Fibre Channel Host Bus Adapters. * | 3 | * Fibre Channel Host Bus Adapters. * |
4 | * Copyright (C) 2004-2014 Emulex. All rights reserved. * | 4 | * Copyright (C) 2004-2015 Emulex. All rights reserved. * |
5 | * EMULEX and SLI are trademarks of Emulex. * | 5 | * EMULEX and SLI are trademarks of Emulex. * |
6 | * www.emulex.com * | 6 | * www.emulex.com * |
7 | * * | 7 | * * |
@@ -18,7 +18,7 @@ | |||
18 | * included with this package. * | 18 | * included with this package. * |
19 | *******************************************************************/ | 19 | *******************************************************************/ |
20 | 20 | ||
21 | #define LPFC_DRIVER_VERSION "10.4.8000.0." | 21 | #define LPFC_DRIVER_VERSION "10.5.0.0." |
22 | #define LPFC_DRIVER_NAME "lpfc" | 22 | #define LPFC_DRIVER_NAME "lpfc" |
23 | 23 | ||
24 | /* Used for SLI 2/3 */ | 24 | /* Used for SLI 2/3 */ |
@@ -30,4 +30,4 @@ | |||
30 | 30 | ||
31 | #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ | 31 | #define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \ |
32 | LPFC_DRIVER_VERSION | 32 | LPFC_DRIVER_VERSION |
33 | #define LPFC_COPYRIGHT "Copyright(c) 2004-2014 Emulex. All rights reserved." | 33 | #define LPFC_COPYRIGHT "Copyright(c) 2004-2015 Emulex. All rights reserved." |
diff --git a/drivers/scsi/mac_scsi.c b/drivers/scsi/mac_scsi.c index 1e85c07e3b62..d64a769b8155 100644 --- a/drivers/scsi/mac_scsi.c +++ b/drivers/scsi/mac_scsi.c | |||
@@ -483,7 +483,6 @@ static struct platform_driver mac_scsi_driver = { | |||
483 | .remove = __exit_p(mac_scsi_remove), | 483 | .remove = __exit_p(mac_scsi_remove), |
484 | .driver = { | 484 | .driver = { |
485 | .name = DRV_MODULE_NAME, | 485 | .name = DRV_MODULE_NAME, |
486 | .owner = THIS_MODULE, | ||
487 | }, | 486 | }, |
488 | }; | 487 | }; |
489 | 488 | ||
diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 113e6c9826a1..33f60c92e20e 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig | |||
@@ -18,6 +18,9 @@ config SCSI_QLA_FC | |||
18 | 2322, 6322 ql2322_fw.bin | 18 | 2322, 6322 ql2322_fw.bin |
19 | 24xx, 54xx ql2400_fw.bin | 19 | 24xx, 54xx ql2400_fw.bin |
20 | 25xx ql2500_fw.bin | 20 | 25xx ql2500_fw.bin |
21 | 2031 ql2600_fw.bin | ||
22 | 8031 ql8300_fw.bin | ||
23 | 27xx ql2700_fw.bin | ||
21 | 24 | ||
22 | Upon request, the driver caches the firmware image until | 25 | Upon request, the driver caches the firmware image until |
23 | the driver is unloaded. | 26 | the driver is unloaded. |
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index d77fe43793b6..0e6ee3ca30e6 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c | |||
@@ -11,9 +11,9 @@ | |||
11 | * ---------------------------------------------------------------------- | 11 | * ---------------------------------------------------------------------- |
12 | * | Level | Last Value Used | Holes | | 12 | * | Level | Last Value Used | Holes | |
13 | * ---------------------------------------------------------------------- | 13 | * ---------------------------------------------------------------------- |
14 | * | Module Init and Probe | 0x017d | 0x0144,0x0146 | | 14 | * | Module Init and Probe | 0x017f | 0x0146 | |
15 | * | | | 0x015b-0x0160 | | 15 | * | | | 0x015b-0x0160 | |
16 | * | | | 0x016e-0x0170 | | 16 | * | | | 0x016e-0x0170 | |
17 | * | Mailbox commands | 0x118d | 0x1115-0x1116 | | 17 | * | Mailbox commands | 0x118d | 0x1115-0x1116 | |
18 | * | | | 0x111a-0x111b | | 18 | * | | | 0x111a-0x111b | |
19 | * | Device Discovery | 0x2016 | 0x2020-0x2022, | | 19 | * | Device Discovery | 0x2016 | 0x2020-0x2022, | |
@@ -60,7 +60,7 @@ | |||
60 | * | | | 0xb13c-0xb140 | | 60 | * | | | 0xb13c-0xb140 | |
61 | * | | | 0xb149 | | 61 | * | | | 0xb149 | |
62 | * | MultiQ | 0xc00c | | | 62 | * | MultiQ | 0xc00c | | |
63 | * | Misc | 0xd213 | 0xd011-0xd017 | | 63 | * | Misc | 0xd300 | 0xd016-0xd017 | |
64 | * | | | 0xd021,0xd024 | | 64 | * | | | 0xd021,0xd024 | |
65 | * | | | 0xd025,0xd029 | | 65 | * | | | 0xd025,0xd029 | |
66 | * | | | 0xd02a,0xd02e | | 66 | * | | | 0xd02a,0xd02e | |
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 5f6b2960cccb..e86201d3b8c6 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h | |||
@@ -2163,7 +2163,7 @@ struct ct_fdmi_hba_attr { | |||
2163 | uint8_t node_name[WWN_SIZE]; | 2163 | uint8_t node_name[WWN_SIZE]; |
2164 | uint8_t manufacturer[64]; | 2164 | uint8_t manufacturer[64]; |
2165 | uint8_t serial_num[32]; | 2165 | uint8_t serial_num[32]; |
2166 | uint8_t model[16]; | 2166 | uint8_t model[16+1]; |
2167 | uint8_t model_desc[80]; | 2167 | uint8_t model_desc[80]; |
2168 | uint8_t hw_version[32]; | 2168 | uint8_t hw_version[32]; |
2169 | uint8_t driver_version[32]; | 2169 | uint8_t driver_version[32]; |
@@ -2184,9 +2184,9 @@ struct ct_fdmiv2_hba_attr { | |||
2184 | uint16_t len; | 2184 | uint16_t len; |
2185 | union { | 2185 | union { |
2186 | uint8_t node_name[WWN_SIZE]; | 2186 | uint8_t node_name[WWN_SIZE]; |
2187 | uint8_t manufacturer[32]; | 2187 | uint8_t manufacturer[64]; |
2188 | uint8_t serial_num[32]; | 2188 | uint8_t serial_num[32]; |
2189 | uint8_t model[16]; | 2189 | uint8_t model[16+1]; |
2190 | uint8_t model_desc[80]; | 2190 | uint8_t model_desc[80]; |
2191 | uint8_t hw_version[16]; | 2191 | uint8_t hw_version[16]; |
2192 | uint8_t driver_version[32]; | 2192 | uint8_t driver_version[32]; |
@@ -2252,7 +2252,7 @@ struct ct_fdmiv2_port_attr { | |||
2252 | uint32_t cur_speed; | 2252 | uint32_t cur_speed; |
2253 | uint32_t max_frame_size; | 2253 | uint32_t max_frame_size; |
2254 | uint8_t os_dev_name[32]; | 2254 | uint8_t os_dev_name[32]; |
2255 | uint8_t host_name[32]; | 2255 | uint8_t host_name[256]; |
2256 | uint8_t node_name[WWN_SIZE]; | 2256 | uint8_t node_name[WWN_SIZE]; |
2257 | uint8_t port_name[WWN_SIZE]; | 2257 | uint8_t port_name[WWN_SIZE]; |
2258 | uint8_t port_sym_name[128]; | 2258 | uint8_t port_sym_name[128]; |
@@ -2283,7 +2283,7 @@ struct ct_fdmi_port_attr { | |||
2283 | uint32_t cur_speed; | 2283 | uint32_t cur_speed; |
2284 | uint32_t max_frame_size; | 2284 | uint32_t max_frame_size; |
2285 | uint8_t os_dev_name[32]; | 2285 | uint8_t os_dev_name[32]; |
2286 | uint8_t host_name[32]; | 2286 | uint8_t host_name[256]; |
2287 | } a; | 2287 | } a; |
2288 | }; | 2288 | }; |
2289 | 2289 | ||
@@ -3132,7 +3132,8 @@ struct qla_hw_data { | |||
3132 | IS_QLA25XX(ha) || IS_QLA81XX(ha) || \ | 3132 | IS_QLA25XX(ha) || IS_QLA81XX(ha) || \ |
3133 | IS_QLA82XX(ha) || IS_QLA83XX(ha) || \ | 3133 | IS_QLA82XX(ha) || IS_QLA83XX(ha) || \ |
3134 | IS_QLA8044(ha) || IS_QLA27XX(ha)) | 3134 | IS_QLA8044(ha) || IS_QLA27XX(ha)) |
3135 | #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha)) | 3135 | #define IS_MSIX_NACK_CAPABLE(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ |
3136 | IS_QLA27XX(ha)) | ||
3136 | #define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled) | 3137 | #define IS_NOPOLLING_TYPE(ha) (IS_QLA81XX(ha) && (ha)->flags.msix_enabled) |
3137 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ | 3138 | #define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha) || IS_QLA83XX(ha) || \ |
3138 | IS_QLA27XX(ha)) | 3139 | IS_QLA27XX(ha)) |
@@ -3300,6 +3301,8 @@ struct qla_hw_data { | |||
3300 | #define RISC_RDY_AFT_RESET 3 | 3301 | #define RISC_RDY_AFT_RESET 3 |
3301 | #define RISC_SRAM_DUMP_CMPL 4 | 3302 | #define RISC_SRAM_DUMP_CMPL 4 |
3302 | #define RISC_EXT_MEM_DUMP_CMPL 5 | 3303 | #define RISC_EXT_MEM_DUMP_CMPL 5 |
3304 | #define ISP_MBX_RDY 6 | ||
3305 | #define ISP_SOFT_RESET_CMPL 7 | ||
3303 | int fw_dump_reading; | 3306 | int fw_dump_reading; |
3304 | int prev_minidump_failed; | 3307 | int prev_minidump_failed; |
3305 | dma_addr_t eft_dma; | 3308 | dma_addr_t eft_dma; |
@@ -3587,6 +3590,7 @@ typedef struct scsi_qla_host { | |||
3587 | #define VP_BIND_NEEDED 2 | 3590 | #define VP_BIND_NEEDED 2 |
3588 | #define VP_DELETE_NEEDED 3 | 3591 | #define VP_DELETE_NEEDED 3 |
3589 | #define VP_SCR_NEEDED 4 /* State Change Request registration */ | 3592 | #define VP_SCR_NEEDED 4 /* State Change Request registration */ |
3593 | #define VP_CONFIG_OK 5 /* Flag to cfg VP, if FW is ready */ | ||
3590 | atomic_t vp_state; | 3594 | atomic_t vp_state; |
3591 | #define VP_OFFLINE 0 | 3595 | #define VP_OFFLINE 0 |
3592 | #define VP_ACTIVE 1 | 3596 | #define VP_ACTIVE 1 |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 5bb57c5282c9..285cb204f300 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -1121,7 +1121,7 @@ qla81xx_reset_mpi(scsi_qla_host_t *vha) | |||
1121 | * | 1121 | * |
1122 | * Returns 0 on success. | 1122 | * Returns 0 on success. |
1123 | */ | 1123 | */ |
1124 | static inline void | 1124 | static inline int |
1125 | qla24xx_reset_risc(scsi_qla_host_t *vha) | 1125 | qla24xx_reset_risc(scsi_qla_host_t *vha) |
1126 | { | 1126 | { |
1127 | unsigned long flags = 0; | 1127 | unsigned long flags = 0; |
@@ -1130,6 +1130,7 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) | |||
1130 | uint32_t cnt, d2; | 1130 | uint32_t cnt, d2; |
1131 | uint16_t wd; | 1131 | uint16_t wd; |
1132 | static int abts_cnt; /* ISP abort retry counts */ | 1132 | static int abts_cnt; /* ISP abort retry counts */ |
1133 | int rval = QLA_SUCCESS; | ||
1133 | 1134 | ||
1134 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1135 | spin_lock_irqsave(&ha->hardware_lock, flags); |
1135 | 1136 | ||
@@ -1142,26 +1143,57 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) | |||
1142 | udelay(10); | 1143 | udelay(10); |
1143 | } | 1144 | } |
1144 | 1145 | ||
1146 | if (!(RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE)) | ||
1147 | set_bit(DMA_SHUTDOWN_CMPL, &ha->fw_dump_cap_flags); | ||
1148 | |||
1149 | ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017e, | ||
1150 | "HCCR: 0x%x, Control Status %x, DMA active status:0x%x\n", | ||
1151 | RD_REG_DWORD(®->hccr), | ||
1152 | RD_REG_DWORD(®->ctrl_status), | ||
1153 | (RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE)); | ||
1154 | |||
1145 | WRT_REG_DWORD(®->ctrl_status, | 1155 | WRT_REG_DWORD(®->ctrl_status, |
1146 | CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); | 1156 | CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); |
1147 | pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); | 1157 | pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); |
1148 | 1158 | ||
1149 | udelay(100); | 1159 | udelay(100); |
1160 | |||
1150 | /* Wait for firmware to complete NVRAM accesses. */ | 1161 | /* Wait for firmware to complete NVRAM accesses. */ |
1151 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | 1162 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); |
1152 | for (cnt = 10000 ; cnt && d2; cnt--) { | 1163 | for (cnt = 10000; RD_REG_WORD(®->mailbox0) != 0 && |
1153 | udelay(5); | 1164 | rval == QLA_SUCCESS; cnt--) { |
1154 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
1155 | barrier(); | 1165 | barrier(); |
1166 | if (cnt) | ||
1167 | udelay(5); | ||
1168 | else | ||
1169 | rval = QLA_FUNCTION_TIMEOUT; | ||
1156 | } | 1170 | } |
1157 | 1171 | ||
1172 | if (rval == QLA_SUCCESS) | ||
1173 | set_bit(ISP_MBX_RDY, &ha->fw_dump_cap_flags); | ||
1174 | |||
1175 | ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x017f, | ||
1176 | "HCCR: 0x%x, MailBox0 Status 0x%x\n", | ||
1177 | RD_REG_DWORD(®->hccr), | ||
1178 | RD_REG_DWORD(®->mailbox0)); | ||
1179 | |||
1158 | /* Wait for soft-reset to complete. */ | 1180 | /* Wait for soft-reset to complete. */ |
1159 | d2 = RD_REG_DWORD(®->ctrl_status); | 1181 | d2 = RD_REG_DWORD(®->ctrl_status); |
1160 | for (cnt = 6000000 ; cnt && (d2 & CSRX_ISP_SOFT_RESET); cnt--) { | 1182 | for (cnt = 0; cnt < 6000000; cnt++) { |
1161 | udelay(5); | ||
1162 | d2 = RD_REG_DWORD(®->ctrl_status); | ||
1163 | barrier(); | 1183 | barrier(); |
1184 | if ((RD_REG_DWORD(®->ctrl_status) & | ||
1185 | CSRX_ISP_SOFT_RESET) == 0) | ||
1186 | break; | ||
1187 | |||
1188 | udelay(5); | ||
1164 | } | 1189 | } |
1190 | if (!(RD_REG_DWORD(®->ctrl_status) & CSRX_ISP_SOFT_RESET)) | ||
1191 | set_bit(ISP_SOFT_RESET_CMPL, &ha->fw_dump_cap_flags); | ||
1192 | |||
1193 | ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015d, | ||
1194 | "HCCR: 0x%x, Soft Reset status: 0x%x\n", | ||
1195 | RD_REG_DWORD(®->hccr), | ||
1196 | RD_REG_DWORD(®->ctrl_status)); | ||
1165 | 1197 | ||
1166 | /* If required, do an MPI FW reset now */ | 1198 | /* If required, do an MPI FW reset now */ |
1167 | if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) { | 1199 | if (test_and_clear_bit(MPI_RESET_NEEDED, &vha->dpc_flags)) { |
@@ -1190,16 +1222,32 @@ qla24xx_reset_risc(scsi_qla_host_t *vha) | |||
1190 | RD_REG_DWORD(®->hccr); | 1222 | RD_REG_DWORD(®->hccr); |
1191 | 1223 | ||
1192 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | 1224 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); |
1193 | for (cnt = 6000000 ; cnt && d2; cnt--) { | 1225 | for (cnt = 6000000; RD_REG_WORD(®->mailbox0) != 0 && |
1194 | udelay(5); | 1226 | rval == QLA_SUCCESS; cnt--) { |
1195 | d2 = (uint32_t) RD_REG_WORD(®->mailbox0); | ||
1196 | barrier(); | 1227 | barrier(); |
1228 | if (cnt) | ||
1229 | udelay(5); | ||
1230 | else | ||
1231 | rval = QLA_FUNCTION_TIMEOUT; | ||
1197 | } | 1232 | } |
1233 | if (rval == QLA_SUCCESS) | ||
1234 | set_bit(RISC_RDY_AFT_RESET, &ha->fw_dump_cap_flags); | ||
1235 | |||
1236 | ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015e, | ||
1237 | "Host Risc 0x%x, mailbox0 0x%x\n", | ||
1238 | RD_REG_DWORD(®->hccr), | ||
1239 | RD_REG_WORD(®->mailbox0)); | ||
1198 | 1240 | ||
1199 | spin_unlock_irqrestore(&ha->hardware_lock, flags); | 1241 | spin_unlock_irqrestore(&ha->hardware_lock, flags); |
1200 | 1242 | ||
1243 | ql_dbg(ql_dbg_init + ql_dbg_verbose, vha, 0x015f, | ||
1244 | "Driver in %s mode\n", | ||
1245 | IS_NOPOLLING_TYPE(ha) ? "Interrupt" : "Polling"); | ||
1246 | |||
1201 | if (IS_NOPOLLING_TYPE(ha)) | 1247 | if (IS_NOPOLLING_TYPE(ha)) |
1202 | ha->isp_ops->enable_intrs(ha); | 1248 | ha->isp_ops->enable_intrs(ha); |
1249 | |||
1250 | return rval; | ||
1203 | } | 1251 | } |
1204 | 1252 | ||
1205 | static void | 1253 | static void |
@@ -2243,8 +2291,11 @@ qla2x00_fw_ready(scsi_qla_host_t *vha) | |||
2243 | 2291 | ||
2244 | rval = QLA_SUCCESS; | 2292 | rval = QLA_SUCCESS; |
2245 | 2293 | ||
2246 | /* 20 seconds for loop down. */ | 2294 | /* Time to wait for loop down */ |
2247 | min_wait = 20; | 2295 | if (IS_P3P_TYPE(ha)) |
2296 | min_wait = 30; | ||
2297 | else | ||
2298 | min_wait = 20; | ||
2248 | 2299 | ||
2249 | /* | 2300 | /* |
2250 | * Firmware should take at most one RATOV to login, plus 5 seconds for | 2301 | * Firmware should take at most one RATOV to login, plus 5 seconds for |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a04a1b1f7f32..6dc14cd782b2 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -756,11 +756,21 @@ skip_rio: | |||
756 | /* | 756 | /* |
757 | * In case of loop down, restore WWPN from | 757 | * In case of loop down, restore WWPN from |
758 | * NVRAM in case of FA-WWPN capable ISP | 758 | * NVRAM in case of FA-WWPN capable ISP |
759 | * Restore for Physical Port only | ||
759 | */ | 760 | */ |
760 | if (ha->flags.fawwpn_enabled) { | 761 | if (!vha->vp_idx) { |
761 | void *wwpn = ha->init_cb->port_name; | 762 | if (ha->flags.fawwpn_enabled) { |
763 | void *wwpn = ha->init_cb->port_name; | ||
764 | memcpy(vha->port_name, wwpn, WWN_SIZE); | ||
765 | fc_host_port_name(vha->host) = | ||
766 | wwn_to_u64(vha->port_name); | ||
767 | ql_dbg(ql_dbg_init + ql_dbg_verbose, | ||
768 | vha, 0x0144, "LOOP DOWN detected," | ||
769 | "restore WWPN %016llx\n", | ||
770 | wwn_to_u64(vha->port_name)); | ||
771 | } | ||
762 | 772 | ||
763 | memcpy(vha->port_name, wwpn, WWN_SIZE); | 773 | clear_bit(VP_CONFIG_OK, &vha->vp_flags); |
764 | } | 774 | } |
765 | 775 | ||
766 | vha->device_flags |= DFLG_NO_CABLE; | 776 | vha->device_flags |= DFLG_NO_CABLE; |
@@ -947,6 +957,7 @@ skip_rio: | |||
947 | 957 | ||
948 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); | 958 | set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); |
949 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); | 959 | set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); |
960 | set_bit(VP_CONFIG_OK, &vha->vp_flags); | ||
950 | 961 | ||
951 | qlt_async_event(mb[0], vha, mb); | 962 | qlt_async_event(mb[0], vha, mb); |
952 | break; | 963 | break; |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 72971daa2552..02b1c1c5355b 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -33,7 +33,7 @@ | |||
33 | static int | 33 | static int |
34 | qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | 34 | qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) |
35 | { | 35 | { |
36 | int rval; | 36 | int rval, i; |
37 | unsigned long flags = 0; | 37 | unsigned long flags = 0; |
38 | device_reg_t *reg; | 38 | device_reg_t *reg; |
39 | uint8_t abort_active; | 39 | uint8_t abort_active; |
@@ -43,10 +43,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp) | |||
43 | uint16_t __iomem *optr; | 43 | uint16_t __iomem *optr; |
44 | uint32_t cnt; | 44 | uint32_t cnt; |
45 | uint32_t mboxes; | 45 | uint32_t mboxes; |
46 | uint16_t __iomem *mbx_reg; | ||
46 | unsigned long wait_time; | 47 | unsigned long wait_time; |
47 | struct qla_hw_data *ha = vha->hw; | 48 | struct qla_hw_data *ha = vha->hw; |
48 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | 49 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); |
49 | 50 | ||
51 | |||
50 | ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); | 52 | ql_dbg(ql_dbg_mbx, vha, 0x1000, "Entered %s.\n", __func__); |
51 | 53 | ||
52 | if (ha->pdev->error_state > pci_channel_io_frozen) { | 54 | if (ha->pdev->error_state > pci_channel_io_frozen) { |
@@ -376,6 +378,18 @@ mbx_done: | |||
376 | ql_dbg(ql_dbg_disc, base_vha, 0x1020, | 378 | ql_dbg(ql_dbg_disc, base_vha, 0x1020, |
377 | "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n", | 379 | "**** Failed mbx[0]=%x, mb[1]=%x, mb[2]=%x, mb[3]=%x, cmd=%x ****.\n", |
378 | mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command); | 380 | mcp->mb[0], mcp->mb[1], mcp->mb[2], mcp->mb[3], command); |
381 | |||
382 | ql_dbg(ql_dbg_disc, vha, 0x1115, | ||
383 | "host status: 0x%x, flags:0x%lx, intr ctrl reg:0x%x, intr status:0x%x\n", | ||
384 | RD_REG_DWORD(®->isp24.host_status), | ||
385 | ha->fw_dump_cap_flags, | ||
386 | RD_REG_DWORD(®->isp24.ictrl), | ||
387 | RD_REG_DWORD(®->isp24.istatus)); | ||
388 | |||
389 | mbx_reg = ®->isp24.mailbox0; | ||
390 | for (i = 0; i < 6; i++) | ||
391 | ql_dbg(ql_dbg_disc + ql_dbg_verbose, vha, 0x1116, | ||
392 | "mbox[%d] 0x%04x\n", i, RD_REG_WORD(mbx_reg++)); | ||
379 | } else { | 393 | } else { |
380 | ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__); | 394 | ql_dbg(ql_dbg_mbx, base_vha, 0x1021, "Done %s.\n", __func__); |
381 | } | 395 | } |
@@ -2838,7 +2852,7 @@ qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data) | |||
2838 | mbx_cmd_t mc; | 2852 | mbx_cmd_t mc; |
2839 | mbx_cmd_t *mcp = &mc; | 2853 | mbx_cmd_t *mcp = &mc; |
2840 | 2854 | ||
2841 | if (!IS_QLA2031(vha->hw)) | 2855 | if (!IS_QLA2031(vha->hw) && !IS_QLA27XX(vha->hw)) |
2842 | return QLA_FUNCTION_FAILED; | 2856 | return QLA_FUNCTION_FAILED; |
2843 | 2857 | ||
2844 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182, | 2858 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1182, |
@@ -2846,7 +2860,11 @@ qla2x00_write_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t data) | |||
2846 | 2860 | ||
2847 | mcp->mb[0] = MBC_WRITE_SERDES; | 2861 | mcp->mb[0] = MBC_WRITE_SERDES; |
2848 | mcp->mb[1] = addr; | 2862 | mcp->mb[1] = addr; |
2849 | mcp->mb[2] = data & 0xff; | 2863 | if (IS_QLA2031(vha->hw)) |
2864 | mcp->mb[2] = data & 0xff; | ||
2865 | else | ||
2866 | mcp->mb[2] = data; | ||
2867 | |||
2850 | mcp->mb[3] = 0; | 2868 | mcp->mb[3] = 0; |
2851 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; | 2869 | mcp->out_mb = MBX_3|MBX_2|MBX_1|MBX_0; |
2852 | mcp->in_mb = MBX_0; | 2870 | mcp->in_mb = MBX_0; |
@@ -2872,7 +2890,7 @@ qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data) | |||
2872 | mbx_cmd_t mc; | 2890 | mbx_cmd_t mc; |
2873 | mbx_cmd_t *mcp = &mc; | 2891 | mbx_cmd_t *mcp = &mc; |
2874 | 2892 | ||
2875 | if (!IS_QLA2031(vha->hw)) | 2893 | if (!IS_QLA2031(vha->hw) && !IS_QLA27XX(vha->hw)) |
2876 | return QLA_FUNCTION_FAILED; | 2894 | return QLA_FUNCTION_FAILED; |
2877 | 2895 | ||
2878 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185, | 2896 | ql_dbg(ql_dbg_mbx + ql_dbg_verbose, vha, 0x1185, |
@@ -2887,7 +2905,10 @@ qla2x00_read_serdes_word(scsi_qla_host_t *vha, uint16_t addr, uint16_t *data) | |||
2887 | mcp->flags = 0; | 2905 | mcp->flags = 0; |
2888 | rval = qla2x00_mailbox_command(vha, mcp); | 2906 | rval = qla2x00_mailbox_command(vha, mcp); |
2889 | 2907 | ||
2890 | *data = mcp->mb[1] & 0xff; | 2908 | if (IS_QLA2031(vha->hw)) |
2909 | *data = mcp->mb[1] & 0xff; | ||
2910 | else | ||
2911 | *data = mcp->mb[1]; | ||
2891 | 2912 | ||
2892 | if (rval != QLA_SUCCESS) { | 2913 | if (rval != QLA_SUCCESS) { |
2893 | ql_dbg(ql_dbg_mbx, vha, 0x1186, | 2914 | ql_dbg(ql_dbg_mbx, vha, 0x1186, |
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index ca3804e34833..cc94192511cf 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c | |||
@@ -306,19 +306,25 @@ qla2x00_vp_abort_isp(scsi_qla_host_t *vha) | |||
306 | static int | 306 | static int |
307 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) | 307 | qla2x00_do_dpc_vp(scsi_qla_host_t *vha) |
308 | { | 308 | { |
309 | struct qla_hw_data *ha = vha->hw; | ||
310 | scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); | ||
311 | |||
309 | ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012, | 312 | ql_dbg(ql_dbg_dpc + ql_dbg_verbose, vha, 0x4012, |
310 | "Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags); | 313 | "Entering %s vp_flags: 0x%lx.\n", __func__, vha->vp_flags); |
311 | 314 | ||
312 | qla2x00_do_work(vha); | 315 | qla2x00_do_work(vha); |
313 | 316 | ||
314 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { | 317 | /* Check if Fw is ready to configure VP first */ |
315 | /* VP acquired. complete port configuration */ | 318 | if (test_bit(VP_CONFIG_OK, &base_vha->vp_flags)) { |
316 | ql_dbg(ql_dbg_dpc, vha, 0x4014, | 319 | if (test_and_clear_bit(VP_IDX_ACQUIRED, &vha->vp_flags)) { |
317 | "Configure VP scheduled.\n"); | 320 | /* VP acquired. complete port configuration */ |
318 | qla24xx_configure_vp(vha); | 321 | ql_dbg(ql_dbg_dpc, vha, 0x4014, |
319 | ql_dbg(ql_dbg_dpc, vha, 0x4015, | 322 | "Configure VP scheduled.\n"); |
320 | "Configure VP end.\n"); | 323 | qla24xx_configure_vp(vha); |
321 | return 0; | 324 | ql_dbg(ql_dbg_dpc, vha, 0x4015, |
325 | "Configure VP end.\n"); | ||
326 | return 0; | ||
327 | } | ||
322 | } | 328 | } |
323 | 329 | ||
324 | if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) { | 330 | if (test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags)) { |
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5319b3cb219e..7462dd70b150 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c | |||
@@ -5834,3 +5834,6 @@ MODULE_FIRMWARE(FW_FILE_ISP2300); | |||
5834 | MODULE_FIRMWARE(FW_FILE_ISP2322); | 5834 | MODULE_FIRMWARE(FW_FILE_ISP2322); |
5835 | MODULE_FIRMWARE(FW_FILE_ISP24XX); | 5835 | MODULE_FIRMWARE(FW_FILE_ISP24XX); |
5836 | MODULE_FIRMWARE(FW_FILE_ISP25XX); | 5836 | MODULE_FIRMWARE(FW_FILE_ISP25XX); |
5837 | MODULE_FIRMWARE(FW_FILE_ISP2031); | ||
5838 | MODULE_FIRMWARE(FW_FILE_ISP8031); | ||
5839 | MODULE_FIRMWARE(FW_FILE_ISP27XX); | ||
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index b656a05613e8..028e8c8a7de9 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c | |||
@@ -1718,13 +1718,16 @@ qla83xx_beacon_blink(struct scsi_qla_host *vha) | |||
1718 | uint16_t orig_led_cfg[6]; | 1718 | uint16_t orig_led_cfg[6]; |
1719 | uint32_t led_10_value, led_43_value; | 1719 | uint32_t led_10_value, led_43_value; |
1720 | 1720 | ||
1721 | if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha)) | 1721 | if (!IS_QLA83XX(ha) && !IS_QLA81XX(ha) && !IS_QLA27XX(ha)) |
1722 | return; | 1722 | return; |
1723 | 1723 | ||
1724 | if (!ha->beacon_blink_led) | 1724 | if (!ha->beacon_blink_led) |
1725 | return; | 1725 | return; |
1726 | 1726 | ||
1727 | if (IS_QLA2031(ha)) { | 1727 | if (IS_QLA27XX(ha)) { |
1728 | qla2x00_write_ram_word(vha, 0x1003, 0x40000230); | ||
1729 | qla2x00_write_ram_word(vha, 0x1004, 0x40000230); | ||
1730 | } else if (IS_QLA2031(ha)) { | ||
1728 | led_select_value = qla83xx_select_led_port(ha); | 1731 | led_select_value = qla83xx_select_led_port(ha); |
1729 | 1732 | ||
1730 | qla83xx_wr_reg(vha, led_select_value, 0x40000230); | 1733 | qla83xx_wr_reg(vha, led_select_value, 0x40000230); |
@@ -1811,7 +1814,7 @@ qla24xx_beacon_on(struct scsi_qla_host *vha) | |||
1811 | return QLA_FUNCTION_FAILED; | 1814 | return QLA_FUNCTION_FAILED; |
1812 | } | 1815 | } |
1813 | 1816 | ||
1814 | if (IS_QLA2031(ha)) | 1817 | if (IS_QLA2031(ha) || IS_QLA27XX(ha)) |
1815 | goto skip_gpio; | 1818 | goto skip_gpio; |
1816 | 1819 | ||
1817 | spin_lock_irqsave(&ha->hardware_lock, flags); | 1820 | spin_lock_irqsave(&ha->hardware_lock, flags); |
@@ -1848,7 +1851,7 @@ qla24xx_beacon_off(struct scsi_qla_host *vha) | |||
1848 | 1851 | ||
1849 | ha->beacon_blink_led = 0; | 1852 | ha->beacon_blink_led = 0; |
1850 | 1853 | ||
1851 | if (IS_QLA2031(ha)) | 1854 | if (IS_QLA2031(ha) || IS_QLA27XX(ha)) |
1852 | goto set_fw_options; | 1855 | goto set_fw_options; |
1853 | 1856 | ||
1854 | if (IS_QLA8031(ha) || IS_QLA81XX(ha)) | 1857 | if (IS_QLA8031(ha) || IS_QLA81XX(ha)) |
diff --git a/drivers/scsi/qla2xxx/qla_tmpl.c b/drivers/scsi/qla2xxx/qla_tmpl.c index a8c0c7362e48..962cb89fe0ae 100644 --- a/drivers/scsi/qla2xxx/qla_tmpl.c +++ b/drivers/scsi/qla2xxx/qla_tmpl.c | |||
@@ -190,7 +190,7 @@ static inline void | |||
190 | qla27xx_write_reg(__iomem struct device_reg_24xx *reg, | 190 | qla27xx_write_reg(__iomem struct device_reg_24xx *reg, |
191 | uint offset, uint32_t data, void *buf) | 191 | uint offset, uint32_t data, void *buf) |
192 | { | 192 | { |
193 | __iomem void *window = reg + offset; | 193 | __iomem void *window = (void __iomem *)reg + offset; |
194 | 194 | ||
195 | if (buf) { | 195 | if (buf) { |
196 | WRT_REG_DWORD(window, data); | 196 | WRT_REG_DWORD(window, data); |
@@ -219,6 +219,8 @@ qla27xx_skip_entry(struct qla27xx_fwdt_entry *ent, void *buf) | |||
219 | { | 219 | { |
220 | if (buf) | 220 | if (buf) |
221 | ent->hdr.driver_flags |= DRIVER_FLAG_SKIP_ENTRY; | 221 | ent->hdr.driver_flags |= DRIVER_FLAG_SKIP_ENTRY; |
222 | ql_dbg(ql_dbg_misc + ql_dbg_verbose, NULL, 0xd011, | ||
223 | "Skipping entry %d\n", ent->hdr.entry_type); | ||
222 | } | 224 | } |
223 | 225 | ||
224 | static int | 226 | static int |
@@ -784,6 +786,13 @@ qla27xx_walk_template(struct scsi_qla_host *vha, | |||
784 | 786 | ||
785 | ql_dbg(ql_dbg_misc, vha, 0xd01b, | 787 | ql_dbg(ql_dbg_misc, vha, 0xd01b, |
786 | "%s: len=%lx\n", __func__, *len); | 788 | "%s: len=%lx\n", __func__, *len); |
789 | |||
790 | if (buf) { | ||
791 | ql_log(ql_log_warn, vha, 0xd015, | ||
792 | "Firmware dump saved to temp buffer (%ld/%p)\n", | ||
793 | vha->host_no, vha->hw->fw_dump); | ||
794 | qla2x00_post_uevent_work(vha, QLA_UEVENT_CODE_FW_DUMP); | ||
795 | } | ||
787 | } | 796 | } |
788 | 797 | ||
789 | static void | 798 | static void |
@@ -938,6 +947,10 @@ qla27xx_fwdump(scsi_qla_host_t *vha, int hardware_locked) | |||
938 | ql_log(ql_log_warn, vha, 0xd01e, "fwdump buffer missing.\n"); | 947 | ql_log(ql_log_warn, vha, 0xd01e, "fwdump buffer missing.\n"); |
939 | else if (!vha->hw->fw_dump_template) | 948 | else if (!vha->hw->fw_dump_template) |
940 | ql_log(ql_log_warn, vha, 0xd01f, "fwdump template missing.\n"); | 949 | ql_log(ql_log_warn, vha, 0xd01f, "fwdump template missing.\n"); |
950 | else if (vha->hw->fw_dumped) | ||
951 | ql_log(ql_log_warn, vha, 0xd300, | ||
952 | "Firmware has been previously dumped (%p)," | ||
953 | " -- ignoring request\n", vha->hw->fw_dump); | ||
941 | else | 954 | else |
942 | qla27xx_execute_fwdt_template(vha); | 955 | qla27xx_execute_fwdt_template(vha); |
943 | 956 | ||
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index d88b86214ec5..2ed9ab90a455 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,7 +7,7 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.07.00.16-k" | 10 | #define QLA2XXX_VERSION "8.07.00.18-k" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 7 | 13 | #define QLA_DRIVER_MINOR_VER 7 |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index c9c3b579eece..3833bf59fb66 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -972,18 +972,24 @@ EXPORT_SYMBOL(scsi_report_opcode); | |||
972 | * Description: Gets a reference to the scsi_device and increments the use count | 972 | * Description: Gets a reference to the scsi_device and increments the use count |
973 | * of the underlying LLDD module. You must hold host_lock of the | 973 | * of the underlying LLDD module. You must hold host_lock of the |
974 | * parent Scsi_Host or already have a reference when calling this. | 974 | * parent Scsi_Host or already have a reference when calling this. |
975 | * | ||
976 | * This will fail if a device is deleted or cancelled, or when the LLD module | ||
977 | * is in the process of being unloaded. | ||
975 | */ | 978 | */ |
976 | int scsi_device_get(struct scsi_device *sdev) | 979 | int scsi_device_get(struct scsi_device *sdev) |
977 | { | 980 | { |
978 | if (sdev->sdev_state == SDEV_DEL) | 981 | if (sdev->sdev_state == SDEV_DEL || sdev->sdev_state == SDEV_CANCEL) |
979 | return -ENXIO; | 982 | goto fail; |
980 | if (!get_device(&sdev->sdev_gendev)) | 983 | if (!get_device(&sdev->sdev_gendev)) |
981 | return -ENXIO; | 984 | goto fail; |
982 | /* We can fail try_module_get if we're doing SCSI operations | 985 | if (!try_module_get(sdev->host->hostt->module)) |
983 | * from module exit (like cache flush) */ | 986 | goto fail_put_device; |
984 | __module_get(sdev->host->hostt->module); | ||
985 | |||
986 | return 0; | 987 | return 0; |
988 | |||
989 | fail_put_device: | ||
990 | put_device(&sdev->sdev_gendev); | ||
991 | fail: | ||
992 | return -ENXIO; | ||
987 | } | 993 | } |
988 | EXPORT_SYMBOL(scsi_device_get); | 994 | EXPORT_SYMBOL(scsi_device_get); |
989 | 995 | ||
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 9c0a520d933c..60aae01caa89 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -1570,16 +1570,15 @@ EXPORT_SYMBOL(scsi_add_device); | |||
1570 | 1570 | ||
1571 | void scsi_rescan_device(struct device *dev) | 1571 | void scsi_rescan_device(struct device *dev) |
1572 | { | 1572 | { |
1573 | if (!dev->driver) | 1573 | device_lock(dev); |
1574 | return; | 1574 | if (dev->driver && try_module_get(dev->driver->owner)) { |
1575 | |||
1576 | if (try_module_get(dev->driver->owner)) { | ||
1577 | struct scsi_driver *drv = to_scsi_driver(dev->driver); | 1575 | struct scsi_driver *drv = to_scsi_driver(dev->driver); |
1578 | 1576 | ||
1579 | if (drv->rescan) | 1577 | if (drv->rescan) |
1580 | drv->rescan(dev); | 1578 | drv->rescan(dev); |
1581 | module_put(dev->driver->owner); | 1579 | module_put(dev->driver->owner); |
1582 | } | 1580 | } |
1581 | device_unlock(dev); | ||
1583 | } | 1582 | } |
1584 | EXPORT_SYMBOL(scsi_rescan_device); | 1583 | EXPORT_SYMBOL(scsi_rescan_device); |
1585 | 1584 | ||
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 5d6f348eb3d8..24eaaf66af71 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c | |||
@@ -265,6 +265,7 @@ static const struct { | |||
265 | { FC_PORTSPEED_40GBIT, "40 Gbit" }, | 265 | { FC_PORTSPEED_40GBIT, "40 Gbit" }, |
266 | { FC_PORTSPEED_50GBIT, "50 Gbit" }, | 266 | { FC_PORTSPEED_50GBIT, "50 Gbit" }, |
267 | { FC_PORTSPEED_100GBIT, "100 Gbit" }, | 267 | { FC_PORTSPEED_100GBIT, "100 Gbit" }, |
268 | { FC_PORTSPEED_25GBIT, "25 Gbit" }, | ||
268 | { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, | 269 | { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, |
269 | }; | 270 | }; |
270 | fc_bitfield_name_search(port_speed, fc_port_speed_names) | 271 | fc_bitfield_name_search(port_speed, fc_port_speed_names) |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6b78476d04bb..dcc42446f58a 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -564,10 +564,12 @@ static int sd_major(int major_idx) | |||
564 | } | 564 | } |
565 | } | 565 | } |
566 | 566 | ||
567 | static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) | 567 | static struct scsi_disk *scsi_disk_get(struct gendisk *disk) |
568 | { | 568 | { |
569 | struct scsi_disk *sdkp = NULL; | 569 | struct scsi_disk *sdkp = NULL; |
570 | 570 | ||
571 | mutex_lock(&sd_ref_mutex); | ||
572 | |||
571 | if (disk->private_data) { | 573 | if (disk->private_data) { |
572 | sdkp = scsi_disk(disk); | 574 | sdkp = scsi_disk(disk); |
573 | if (scsi_device_get(sdkp->device) == 0) | 575 | if (scsi_device_get(sdkp->device) == 0) |
@@ -575,27 +577,6 @@ static struct scsi_disk *__scsi_disk_get(struct gendisk *disk) | |||
575 | else | 577 | else |
576 | sdkp = NULL; | 578 | sdkp = NULL; |
577 | } | 579 | } |
578 | return sdkp; | ||
579 | } | ||
580 | |||
581 | static struct scsi_disk *scsi_disk_get(struct gendisk *disk) | ||
582 | { | ||
583 | struct scsi_disk *sdkp; | ||
584 | |||
585 | mutex_lock(&sd_ref_mutex); | ||
586 | sdkp = __scsi_disk_get(disk); | ||
587 | mutex_unlock(&sd_ref_mutex); | ||
588 | return sdkp; | ||
589 | } | ||
590 | |||
591 | static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev) | ||
592 | { | ||
593 | struct scsi_disk *sdkp; | ||
594 | |||
595 | mutex_lock(&sd_ref_mutex); | ||
596 | sdkp = dev_get_drvdata(dev); | ||
597 | if (sdkp) | ||
598 | sdkp = __scsi_disk_get(sdkp->disk); | ||
599 | mutex_unlock(&sd_ref_mutex); | 580 | mutex_unlock(&sd_ref_mutex); |
600 | return sdkp; | 581 | return sdkp; |
601 | } | 582 | } |
@@ -610,8 +591,6 @@ static void scsi_disk_put(struct scsi_disk *sdkp) | |||
610 | mutex_unlock(&sd_ref_mutex); | 591 | mutex_unlock(&sd_ref_mutex); |
611 | } | 592 | } |
612 | 593 | ||
613 | |||
614 | |||
615 | static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, | 594 | static unsigned char sd_setup_protect_cmnd(struct scsi_cmnd *scmd, |
616 | unsigned int dix, unsigned int dif) | 595 | unsigned int dix, unsigned int dif) |
617 | { | 596 | { |
@@ -1525,12 +1504,9 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
1525 | 1504 | ||
1526 | static void sd_rescan(struct device *dev) | 1505 | static void sd_rescan(struct device *dev) |
1527 | { | 1506 | { |
1528 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 1507 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
1529 | 1508 | ||
1530 | if (sdkp) { | 1509 | revalidate_disk(sdkp->disk); |
1531 | revalidate_disk(sdkp->disk); | ||
1532 | scsi_disk_put(sdkp); | ||
1533 | } | ||
1534 | } | 1510 | } |
1535 | 1511 | ||
1536 | 1512 | ||
@@ -2235,11 +2211,11 @@ got_data: | |||
2235 | 2211 | ||
2236 | { | 2212 | { |
2237 | char cap_str_2[10], cap_str_10[10]; | 2213 | char cap_str_2[10], cap_str_10[10]; |
2238 | u64 sz = (u64)sdkp->capacity << ilog2(sector_size); | ||
2239 | 2214 | ||
2240 | string_get_size(sz, STRING_UNITS_2, cap_str_2, | 2215 | string_get_size(sdkp->capacity, sector_size, |
2241 | sizeof(cap_str_2)); | 2216 | STRING_UNITS_2, cap_str_2, sizeof(cap_str_2)); |
2242 | string_get_size(sz, STRING_UNITS_10, cap_str_10, | 2217 | string_get_size(sdkp->capacity, sector_size, |
2218 | STRING_UNITS_10, cap_str_10, | ||
2243 | sizeof(cap_str_10)); | 2219 | sizeof(cap_str_10)); |
2244 | 2220 | ||
2245 | if (sdkp->first_scan || old_capacity != sdkp->capacity) { | 2221 | if (sdkp->first_scan || old_capacity != sdkp->capacity) { |
@@ -3149,13 +3125,13 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) | |||
3149 | */ | 3125 | */ |
3150 | static void sd_shutdown(struct device *dev) | 3126 | static void sd_shutdown(struct device *dev) |
3151 | { | 3127 | { |
3152 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3128 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
3153 | 3129 | ||
3154 | if (!sdkp) | 3130 | if (!sdkp) |
3155 | return; /* this can happen */ | 3131 | return; /* this can happen */ |
3156 | 3132 | ||
3157 | if (pm_runtime_suspended(dev)) | 3133 | if (pm_runtime_suspended(dev)) |
3158 | goto exit; | 3134 | return; |
3159 | 3135 | ||
3160 | if (sdkp->WCE && sdkp->media_present) { | 3136 | if (sdkp->WCE && sdkp->media_present) { |
3161 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); | 3137 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); |
@@ -3166,14 +3142,11 @@ static void sd_shutdown(struct device *dev) | |||
3166 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); | 3142 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); |
3167 | sd_start_stop_device(sdkp, 0); | 3143 | sd_start_stop_device(sdkp, 0); |
3168 | } | 3144 | } |
3169 | |||
3170 | exit: | ||
3171 | scsi_disk_put(sdkp); | ||
3172 | } | 3145 | } |
3173 | 3146 | ||
3174 | static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) | 3147 | static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) |
3175 | { | 3148 | { |
3176 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3149 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
3177 | int ret = 0; | 3150 | int ret = 0; |
3178 | 3151 | ||
3179 | if (!sdkp) | 3152 | if (!sdkp) |
@@ -3199,7 +3172,6 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) | |||
3199 | } | 3172 | } |
3200 | 3173 | ||
3201 | done: | 3174 | done: |
3202 | scsi_disk_put(sdkp); | ||
3203 | return ret; | 3175 | return ret; |
3204 | } | 3176 | } |
3205 | 3177 | ||
@@ -3215,18 +3187,13 @@ static int sd_suspend_runtime(struct device *dev) | |||
3215 | 3187 | ||
3216 | static int sd_resume(struct device *dev) | 3188 | static int sd_resume(struct device *dev) |
3217 | { | 3189 | { |
3218 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3190 | struct scsi_disk *sdkp = dev_get_drvdata(dev); |
3219 | int ret = 0; | ||
3220 | 3191 | ||
3221 | if (!sdkp->device->manage_start_stop) | 3192 | if (!sdkp->device->manage_start_stop) |
3222 | goto done; | 3193 | return 0; |
3223 | 3194 | ||
3224 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); | 3195 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); |
3225 | ret = sd_start_stop_device(sdkp, 1); | 3196 | return sd_start_stop_device(sdkp, 1); |
3226 | |||
3227 | done: | ||
3228 | scsi_disk_put(sdkp); | ||
3229 | return ret; | ||
3230 | } | 3197 | } |
3231 | 3198 | ||
3232 | /** | 3199 | /** |
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index efc6e446b6c8..d9dad90344d5 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c | |||
@@ -308,11 +308,16 @@ enum storvsc_request_type { | |||
308 | * This is the end of Protocol specific defines. | 308 | * This is the end of Protocol specific defines. |
309 | */ | 309 | */ |
310 | 310 | ||
311 | static int storvsc_ringbuffer_size = (20 * PAGE_SIZE); | 311 | static int storvsc_ringbuffer_size = (256 * PAGE_SIZE); |
312 | static u32 max_outstanding_req_per_channel; | ||
313 | |||
314 | static int storvsc_vcpus_per_sub_channel = 4; | ||
312 | 315 | ||
313 | module_param(storvsc_ringbuffer_size, int, S_IRUGO); | 316 | module_param(storvsc_ringbuffer_size, int, S_IRUGO); |
314 | MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); | 317 | MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); |
315 | 318 | ||
319 | module_param(storvsc_vcpus_per_sub_channel, int, S_IRUGO); | ||
320 | MODULE_PARM_DESC(vcpus_per_sub_channel, "Ratio of VCPUs to subchannels"); | ||
316 | /* | 321 | /* |
317 | * Timeout in seconds for all devices managed by this driver. | 322 | * Timeout in seconds for all devices managed by this driver. |
318 | */ | 323 | */ |
@@ -320,7 +325,6 @@ static int storvsc_timeout = 180; | |||
320 | 325 | ||
321 | static int msft_blist_flags = BLIST_TRY_VPD_PAGES; | 326 | static int msft_blist_flags = BLIST_TRY_VPD_PAGES; |
322 | 327 | ||
323 | #define STORVSC_MAX_IO_REQUESTS 200 | ||
324 | 328 | ||
325 | static void storvsc_on_channel_callback(void *context); | 329 | static void storvsc_on_channel_callback(void *context); |
326 | 330 | ||
@@ -347,7 +351,10 @@ struct storvsc_cmd_request { | |||
347 | /* Synchronize the request/response if needed */ | 351 | /* Synchronize the request/response if needed */ |
348 | struct completion wait_event; | 352 | struct completion wait_event; |
349 | 353 | ||
350 | struct hv_multipage_buffer data_buffer; | 354 | struct vmbus_channel_packet_multipage_buffer mpb; |
355 | struct vmbus_packet_mpb_array *payload; | ||
356 | u32 payload_sz; | ||
357 | |||
351 | struct vstor_packet vstor_packet; | 358 | struct vstor_packet vstor_packet; |
352 | }; | 359 | }; |
353 | 360 | ||
@@ -373,6 +380,10 @@ struct storvsc_device { | |||
373 | unsigned char path_id; | 380 | unsigned char path_id; |
374 | unsigned char target_id; | 381 | unsigned char target_id; |
375 | 382 | ||
383 | /* | ||
384 | * Max I/O, the device can support. | ||
385 | */ | ||
386 | u32 max_transfer_bytes; | ||
376 | /* Used for vsc/vsp channel reset process */ | 387 | /* Used for vsc/vsp channel reset process */ |
377 | struct storvsc_cmd_request init_request; | 388 | struct storvsc_cmd_request init_request; |
378 | struct storvsc_cmd_request reset_request; | 389 | struct storvsc_cmd_request reset_request; |
@@ -618,19 +629,6 @@ cleanup: | |||
618 | return NULL; | 629 | return NULL; |
619 | } | 630 | } |
620 | 631 | ||
621 | /* Disgusting wrapper functions */ | ||
622 | static inline unsigned long sg_kmap_atomic(struct scatterlist *sgl, int idx) | ||
623 | { | ||
624 | void *addr = kmap_atomic(sg_page(sgl + idx)); | ||
625 | return (unsigned long)addr; | ||
626 | } | ||
627 | |||
628 | static inline void sg_kunmap_atomic(unsigned long addr) | ||
629 | { | ||
630 | kunmap_atomic((void *)addr); | ||
631 | } | ||
632 | |||
633 | |||
634 | /* Assume the original sgl has enough room */ | 632 | /* Assume the original sgl has enough room */ |
635 | static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, | 633 | static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, |
636 | struct scatterlist *bounce_sgl, | 634 | struct scatterlist *bounce_sgl, |
@@ -645,32 +643,38 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, | |||
645 | unsigned long bounce_addr = 0; | 643 | unsigned long bounce_addr = 0; |
646 | unsigned long dest_addr = 0; | 644 | unsigned long dest_addr = 0; |
647 | unsigned long flags; | 645 | unsigned long flags; |
646 | struct scatterlist *cur_dest_sgl; | ||
647 | struct scatterlist *cur_src_sgl; | ||
648 | 648 | ||
649 | local_irq_save(flags); | 649 | local_irq_save(flags); |
650 | 650 | cur_dest_sgl = orig_sgl; | |
651 | cur_src_sgl = bounce_sgl; | ||
651 | for (i = 0; i < orig_sgl_count; i++) { | 652 | for (i = 0; i < orig_sgl_count; i++) { |
652 | dest_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset; | 653 | dest_addr = (unsigned long) |
654 | kmap_atomic(sg_page(cur_dest_sgl)) + | ||
655 | cur_dest_sgl->offset; | ||
653 | dest = dest_addr; | 656 | dest = dest_addr; |
654 | destlen = orig_sgl[i].length; | 657 | destlen = cur_dest_sgl->length; |
655 | 658 | ||
656 | if (bounce_addr == 0) | 659 | if (bounce_addr == 0) |
657 | bounce_addr = sg_kmap_atomic(bounce_sgl,j); | 660 | bounce_addr = (unsigned long)kmap_atomic( |
661 | sg_page(cur_src_sgl)); | ||
658 | 662 | ||
659 | while (destlen) { | 663 | while (destlen) { |
660 | src = bounce_addr + bounce_sgl[j].offset; | 664 | src = bounce_addr + cur_src_sgl->offset; |
661 | srclen = bounce_sgl[j].length - bounce_sgl[j].offset; | 665 | srclen = cur_src_sgl->length - cur_src_sgl->offset; |
662 | 666 | ||
663 | copylen = min(srclen, destlen); | 667 | copylen = min(srclen, destlen); |
664 | memcpy((void *)dest, (void *)src, copylen); | 668 | memcpy((void *)dest, (void *)src, copylen); |
665 | 669 | ||
666 | total_copied += copylen; | 670 | total_copied += copylen; |
667 | bounce_sgl[j].offset += copylen; | 671 | cur_src_sgl->offset += copylen; |
668 | destlen -= copylen; | 672 | destlen -= copylen; |
669 | dest += copylen; | 673 | dest += copylen; |
670 | 674 | ||
671 | if (bounce_sgl[j].offset == bounce_sgl[j].length) { | 675 | if (cur_src_sgl->offset == cur_src_sgl->length) { |
672 | /* full */ | 676 | /* full */ |
673 | sg_kunmap_atomic(bounce_addr); | 677 | kunmap_atomic((void *)bounce_addr); |
674 | j++; | 678 | j++; |
675 | 679 | ||
676 | /* | 680 | /* |
@@ -684,21 +688,27 @@ static unsigned int copy_from_bounce_buffer(struct scatterlist *orig_sgl, | |||
684 | /* | 688 | /* |
685 | * We are done; cleanup and return. | 689 | * We are done; cleanup and return. |
686 | */ | 690 | */ |
687 | sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); | 691 | kunmap_atomic((void *)(dest_addr - |
692 | cur_dest_sgl->offset)); | ||
688 | local_irq_restore(flags); | 693 | local_irq_restore(flags); |
689 | return total_copied; | 694 | return total_copied; |
690 | } | 695 | } |
691 | 696 | ||
692 | /* if we need to use another bounce buffer */ | 697 | /* if we need to use another bounce buffer */ |
693 | if (destlen || i != orig_sgl_count - 1) | 698 | if (destlen || i != orig_sgl_count - 1) { |
694 | bounce_addr = sg_kmap_atomic(bounce_sgl,j); | 699 | cur_src_sgl = sg_next(cur_src_sgl); |
700 | bounce_addr = (unsigned long) | ||
701 | kmap_atomic( | ||
702 | sg_page(cur_src_sgl)); | ||
703 | } | ||
695 | } else if (destlen == 0 && i == orig_sgl_count - 1) { | 704 | } else if (destlen == 0 && i == orig_sgl_count - 1) { |
696 | /* unmap the last bounce that is < PAGE_SIZE */ | 705 | /* unmap the last bounce that is < PAGE_SIZE */ |
697 | sg_kunmap_atomic(bounce_addr); | 706 | kunmap_atomic((void *)bounce_addr); |
698 | } | 707 | } |
699 | } | 708 | } |
700 | 709 | ||
701 | sg_kunmap_atomic(dest_addr - orig_sgl[i].offset); | 710 | kunmap_atomic((void *)(dest_addr - cur_dest_sgl->offset)); |
711 | cur_dest_sgl = sg_next(cur_dest_sgl); | ||
702 | } | 712 | } |
703 | 713 | ||
704 | local_irq_restore(flags); | 714 | local_irq_restore(flags); |
@@ -719,48 +729,62 @@ static unsigned int copy_to_bounce_buffer(struct scatterlist *orig_sgl, | |||
719 | unsigned long bounce_addr = 0; | 729 | unsigned long bounce_addr = 0; |
720 | unsigned long src_addr = 0; | 730 | unsigned long src_addr = 0; |
721 | unsigned long flags; | 731 | unsigned long flags; |
732 | struct scatterlist *cur_src_sgl; | ||
733 | struct scatterlist *cur_dest_sgl; | ||
722 | 734 | ||
723 | local_irq_save(flags); | 735 | local_irq_save(flags); |
724 | 736 | ||
737 | cur_src_sgl = orig_sgl; | ||
738 | cur_dest_sgl = bounce_sgl; | ||
739 | |||
725 | for (i = 0; i < orig_sgl_count; i++) { | 740 | for (i = 0; i < orig_sgl_count; i++) { |
726 | src_addr = sg_kmap_atomic(orig_sgl,i) + orig_sgl[i].offset; | 741 | src_addr = (unsigned long) |
742 | kmap_atomic(sg_page(cur_src_sgl)) + | ||
743 | cur_src_sgl->offset; | ||
727 | src = src_addr; | 744 | src = src_addr; |
728 | srclen = orig_sgl[i].length; | 745 | srclen = cur_src_sgl->length; |
729 | 746 | ||
730 | if (bounce_addr == 0) | 747 | if (bounce_addr == 0) |
731 | bounce_addr = sg_kmap_atomic(bounce_sgl,j); | 748 | bounce_addr = (unsigned long) |
749 | kmap_atomic(sg_page(cur_dest_sgl)); | ||
732 | 750 | ||
733 | while (srclen) { | 751 | while (srclen) { |
734 | /* assume bounce offset always == 0 */ | 752 | /* assume bounce offset always == 0 */ |
735 | dest = bounce_addr + bounce_sgl[j].length; | 753 | dest = bounce_addr + cur_dest_sgl->length; |
736 | destlen = PAGE_SIZE - bounce_sgl[j].length; | 754 | destlen = PAGE_SIZE - cur_dest_sgl->length; |
737 | 755 | ||
738 | copylen = min(srclen, destlen); | 756 | copylen = min(srclen, destlen); |
739 | memcpy((void *)dest, (void *)src, copylen); | 757 | memcpy((void *)dest, (void *)src, copylen); |
740 | 758 | ||
741 | total_copied += copylen; | 759 | total_copied += copylen; |
742 | bounce_sgl[j].length += copylen; | 760 | cur_dest_sgl->length += copylen; |
743 | srclen -= copylen; | 761 | srclen -= copylen; |
744 | src += copylen; | 762 | src += copylen; |
745 | 763 | ||
746 | if (bounce_sgl[j].length == PAGE_SIZE) { | 764 | if (cur_dest_sgl->length == PAGE_SIZE) { |
747 | /* full..move to next entry */ | 765 | /* full..move to next entry */ |
748 | sg_kunmap_atomic(bounce_addr); | 766 | kunmap_atomic((void *)bounce_addr); |
767 | bounce_addr = 0; | ||
749 | j++; | 768 | j++; |
769 | } | ||
750 | 770 | ||
751 | /* if we need to use another bounce buffer */ | 771 | /* if we need to use another bounce buffer */ |
752 | if (srclen || i != orig_sgl_count - 1) | 772 | if (srclen && bounce_addr == 0) { |
753 | bounce_addr = sg_kmap_atomic(bounce_sgl,j); | 773 | cur_dest_sgl = sg_next(cur_dest_sgl); |
754 | 774 | bounce_addr = (unsigned long) | |
755 | } else if (srclen == 0 && i == orig_sgl_count - 1) { | 775 | kmap_atomic( |
756 | /* unmap the last bounce that is < PAGE_SIZE */ | 776 | sg_page(cur_dest_sgl)); |
757 | sg_kunmap_atomic(bounce_addr); | ||
758 | } | 777 | } |
778 | |||
759 | } | 779 | } |
760 | 780 | ||
761 | sg_kunmap_atomic(src_addr - orig_sgl[i].offset); | 781 | kunmap_atomic((void *)(src_addr - cur_src_sgl->offset)); |
782 | cur_src_sgl = sg_next(cur_src_sgl); | ||
762 | } | 783 | } |
763 | 784 | ||
785 | if (bounce_addr) | ||
786 | kunmap_atomic((void *)bounce_addr); | ||
787 | |||
764 | local_irq_restore(flags); | 788 | local_irq_restore(flags); |
765 | 789 | ||
766 | return total_copied; | 790 | return total_copied; |
@@ -970,6 +994,8 @@ static int storvsc_channel_init(struct hv_device *device) | |||
970 | STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) | 994 | STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) |
971 | process_sub_channels = true; | 995 | process_sub_channels = true; |
972 | } | 996 | } |
997 | stor_device->max_transfer_bytes = | ||
998 | vstor_packet->storage_channel_properties.max_transfer_bytes; | ||
973 | 999 | ||
974 | memset(vstor_packet, 0, sizeof(struct vstor_packet)); | 1000 | memset(vstor_packet, 0, sizeof(struct vstor_packet)); |
975 | vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; | 1001 | vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; |
@@ -1080,6 +1106,8 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
1080 | struct Scsi_Host *host; | 1106 | struct Scsi_Host *host; |
1081 | struct storvsc_device *stor_dev; | 1107 | struct storvsc_device *stor_dev; |
1082 | struct hv_device *dev = host_dev->dev; | 1108 | struct hv_device *dev = host_dev->dev; |
1109 | u32 payload_sz = cmd_request->payload_sz; | ||
1110 | void *payload = cmd_request->payload; | ||
1083 | 1111 | ||
1084 | stor_dev = get_in_stor_device(dev); | 1112 | stor_dev = get_in_stor_device(dev); |
1085 | host = stor_dev->host; | 1113 | host = stor_dev->host; |
@@ -1109,10 +1137,14 @@ static void storvsc_command_completion(struct storvsc_cmd_request *cmd_request) | |||
1109 | sense_hdr.ascq); | 1137 | sense_hdr.ascq); |
1110 | 1138 | ||
1111 | scsi_set_resid(scmnd, | 1139 | scsi_set_resid(scmnd, |
1112 | cmd_request->data_buffer.len - | 1140 | cmd_request->payload->range.len - |
1113 | vm_srb->data_transfer_length); | 1141 | vm_srb->data_transfer_length); |
1114 | 1142 | ||
1115 | scmnd->scsi_done(scmnd); | 1143 | scmnd->scsi_done(scmnd); |
1144 | |||
1145 | if (payload_sz > | ||
1146 | sizeof(struct vmbus_channel_packet_multipage_buffer)) | ||
1147 | kfree(payload); | ||
1116 | } | 1148 | } |
1117 | 1149 | ||
1118 | static void storvsc_on_io_completion(struct hv_device *device, | 1150 | static void storvsc_on_io_completion(struct hv_device *device, |
@@ -1314,7 +1346,7 @@ static int storvsc_dev_remove(struct hv_device *device) | |||
1314 | } | 1346 | } |
1315 | 1347 | ||
1316 | static int storvsc_do_io(struct hv_device *device, | 1348 | static int storvsc_do_io(struct hv_device *device, |
1317 | struct storvsc_cmd_request *request) | 1349 | struct storvsc_cmd_request *request) |
1318 | { | 1350 | { |
1319 | struct storvsc_device *stor_device; | 1351 | struct storvsc_device *stor_device; |
1320 | struct vstor_packet *vstor_packet; | 1352 | struct vstor_packet *vstor_packet; |
@@ -1346,19 +1378,20 @@ static int storvsc_do_io(struct hv_device *device, | |||
1346 | 1378 | ||
1347 | 1379 | ||
1348 | vstor_packet->vm_srb.data_transfer_length = | 1380 | vstor_packet->vm_srb.data_transfer_length = |
1349 | request->data_buffer.len; | 1381 | request->payload->range.len; |
1350 | 1382 | ||
1351 | vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; | 1383 | vstor_packet->operation = VSTOR_OPERATION_EXECUTE_SRB; |
1352 | 1384 | ||
1353 | if (request->data_buffer.len) { | 1385 | if (request->payload->range.len) { |
1354 | ret = vmbus_sendpacket_multipagebuffer(outgoing_channel, | 1386 | |
1355 | &request->data_buffer, | 1387 | ret = vmbus_sendpacket_mpb_desc(outgoing_channel, |
1388 | request->payload, request->payload_sz, | ||
1356 | vstor_packet, | 1389 | vstor_packet, |
1357 | (sizeof(struct vstor_packet) - | 1390 | (sizeof(struct vstor_packet) - |
1358 | vmscsi_size_delta), | 1391 | vmscsi_size_delta), |
1359 | (unsigned long)request); | 1392 | (unsigned long)request); |
1360 | } else { | 1393 | } else { |
1361 | ret = vmbus_sendpacket(device->channel, vstor_packet, | 1394 | ret = vmbus_sendpacket(outgoing_channel, vstor_packet, |
1362 | (sizeof(struct vstor_packet) - | 1395 | (sizeof(struct vstor_packet) - |
1363 | vmscsi_size_delta), | 1396 | vmscsi_size_delta), |
1364 | (unsigned long)request, | 1397 | (unsigned long)request, |
@@ -1376,7 +1409,6 @@ static int storvsc_do_io(struct hv_device *device, | |||
1376 | 1409 | ||
1377 | static int storvsc_device_configure(struct scsi_device *sdevice) | 1410 | static int storvsc_device_configure(struct scsi_device *sdevice) |
1378 | { | 1411 | { |
1379 | scsi_change_queue_depth(sdevice, STORVSC_MAX_IO_REQUESTS); | ||
1380 | 1412 | ||
1381 | blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); | 1413 | blk_queue_max_segment_size(sdevice->request_queue, PAGE_SIZE); |
1382 | 1414 | ||
@@ -1526,6 +1558,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) | |||
1526 | struct scatterlist *sgl; | 1558 | struct scatterlist *sgl; |
1527 | unsigned int sg_count = 0; | 1559 | unsigned int sg_count = 0; |
1528 | struct vmscsi_request *vm_srb; | 1560 | struct vmscsi_request *vm_srb; |
1561 | struct scatterlist *cur_sgl; | ||
1562 | struct vmbus_packet_mpb_array *payload; | ||
1563 | u32 payload_sz; | ||
1564 | u32 length; | ||
1529 | 1565 | ||
1530 | if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { | 1566 | if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { |
1531 | /* | 1567 | /* |
@@ -1579,46 +1615,71 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) | |||
1579 | 1615 | ||
1580 | memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); | 1616 | memcpy(vm_srb->cdb, scmnd->cmnd, vm_srb->cdb_length); |
1581 | 1617 | ||
1582 | cmd_request->data_buffer.len = scsi_bufflen(scmnd); | 1618 | sgl = (struct scatterlist *)scsi_sglist(scmnd); |
1583 | if (scsi_sg_count(scmnd)) { | 1619 | sg_count = scsi_sg_count(scmnd); |
1584 | sgl = (struct scatterlist *)scsi_sglist(scmnd); | 1620 | |
1585 | sg_count = scsi_sg_count(scmnd); | 1621 | length = scsi_bufflen(scmnd); |
1622 | payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; | ||
1623 | payload_sz = sizeof(cmd_request->mpb); | ||
1586 | 1624 | ||
1625 | if (sg_count) { | ||
1587 | /* check if we need to bounce the sgl */ | 1626 | /* check if we need to bounce the sgl */ |
1588 | if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { | 1627 | if (do_bounce_buffer(sgl, scsi_sg_count(scmnd)) != -1) { |
1589 | cmd_request->bounce_sgl = | 1628 | cmd_request->bounce_sgl = |
1590 | create_bounce_buffer(sgl, scsi_sg_count(scmnd), | 1629 | create_bounce_buffer(sgl, sg_count, |
1591 | scsi_bufflen(scmnd), | 1630 | length, |
1592 | vm_srb->data_in); | 1631 | vm_srb->data_in); |
1593 | if (!cmd_request->bounce_sgl) | 1632 | if (!cmd_request->bounce_sgl) |
1594 | return SCSI_MLQUEUE_HOST_BUSY; | 1633 | return SCSI_MLQUEUE_HOST_BUSY; |
1595 | 1634 | ||
1596 | cmd_request->bounce_sgl_count = | 1635 | cmd_request->bounce_sgl_count = |
1597 | ALIGN(scsi_bufflen(scmnd), PAGE_SIZE) >> | 1636 | ALIGN(length, PAGE_SIZE) >> PAGE_SHIFT; |
1598 | PAGE_SHIFT; | ||
1599 | 1637 | ||
1600 | if (vm_srb->data_in == WRITE_TYPE) | 1638 | if (vm_srb->data_in == WRITE_TYPE) |
1601 | copy_to_bounce_buffer(sgl, | 1639 | copy_to_bounce_buffer(sgl, |
1602 | cmd_request->bounce_sgl, | 1640 | cmd_request->bounce_sgl, sg_count); |
1603 | scsi_sg_count(scmnd)); | ||
1604 | 1641 | ||
1605 | sgl = cmd_request->bounce_sgl; | 1642 | sgl = cmd_request->bounce_sgl; |
1606 | sg_count = cmd_request->bounce_sgl_count; | 1643 | sg_count = cmd_request->bounce_sgl_count; |
1607 | } | 1644 | } |
1608 | 1645 | ||
1609 | cmd_request->data_buffer.offset = sgl[0].offset; | ||
1610 | 1646 | ||
1611 | for (i = 0; i < sg_count; i++) | 1647 | if (sg_count > MAX_PAGE_BUFFER_COUNT) { |
1612 | cmd_request->data_buffer.pfn_array[i] = | 1648 | |
1613 | page_to_pfn(sg_page((&sgl[i]))); | 1649 | payload_sz = (sg_count * sizeof(void *) + |
1650 | sizeof(struct vmbus_packet_mpb_array)); | ||
1651 | payload = kmalloc(payload_sz, GFP_ATOMIC); | ||
1652 | if (!payload) { | ||
1653 | if (cmd_request->bounce_sgl_count) | ||
1654 | destroy_bounce_buffer( | ||
1655 | cmd_request->bounce_sgl, | ||
1656 | cmd_request->bounce_sgl_count); | ||
1657 | |||
1658 | return SCSI_MLQUEUE_DEVICE_BUSY; | ||
1659 | } | ||
1660 | } | ||
1661 | |||
1662 | payload->range.len = length; | ||
1663 | payload->range.offset = sgl[0].offset; | ||
1664 | |||
1665 | cur_sgl = sgl; | ||
1666 | for (i = 0; i < sg_count; i++) { | ||
1667 | payload->range.pfn_array[i] = | ||
1668 | page_to_pfn(sg_page((cur_sgl))); | ||
1669 | cur_sgl = sg_next(cur_sgl); | ||
1670 | } | ||
1614 | 1671 | ||
1615 | } else if (scsi_sglist(scmnd)) { | 1672 | } else if (scsi_sglist(scmnd)) { |
1616 | cmd_request->data_buffer.offset = | 1673 | payload->range.len = length; |
1674 | payload->range.offset = | ||
1617 | virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); | 1675 | virt_to_phys(scsi_sglist(scmnd)) & (PAGE_SIZE-1); |
1618 | cmd_request->data_buffer.pfn_array[0] = | 1676 | payload->range.pfn_array[0] = |
1619 | virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; | 1677 | virt_to_phys(scsi_sglist(scmnd)) >> PAGE_SHIFT; |
1620 | } | 1678 | } |
1621 | 1679 | ||
1680 | cmd_request->payload = payload; | ||
1681 | cmd_request->payload_sz = payload_sz; | ||
1682 | |||
1622 | /* Invokes the vsc to start an IO */ | 1683 | /* Invokes the vsc to start an IO */ |
1623 | ret = storvsc_do_io(dev, cmd_request); | 1684 | ret = storvsc_do_io(dev, cmd_request); |
1624 | 1685 | ||
@@ -1646,12 +1707,8 @@ static struct scsi_host_template scsi_driver = { | |||
1646 | .eh_timed_out = storvsc_eh_timed_out, | 1707 | .eh_timed_out = storvsc_eh_timed_out, |
1647 | .slave_configure = storvsc_device_configure, | 1708 | .slave_configure = storvsc_device_configure, |
1648 | .cmd_per_lun = 255, | 1709 | .cmd_per_lun = 255, |
1649 | .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, | ||
1650 | .this_id = -1, | 1710 | .this_id = -1, |
1651 | /* no use setting to 0 since ll_blk_rw reset it to 1 */ | 1711 | .use_clustering = ENABLE_CLUSTERING, |
1652 | /* currently 32 */ | ||
1653 | .sg_tablesize = MAX_MULTIPAGE_BUFFER_COUNT, | ||
1654 | .use_clustering = DISABLE_CLUSTERING, | ||
1655 | /* Make sure we dont get a sg segment crosses a page boundary */ | 1712 | /* Make sure we dont get a sg segment crosses a page boundary */ |
1656 | .dma_boundary = PAGE_SIZE-1, | 1713 | .dma_boundary = PAGE_SIZE-1, |
1657 | .no_write_same = 1, | 1714 | .no_write_same = 1, |
@@ -1686,6 +1743,7 @@ static int storvsc_probe(struct hv_device *device, | |||
1686 | const struct hv_vmbus_device_id *dev_id) | 1743 | const struct hv_vmbus_device_id *dev_id) |
1687 | { | 1744 | { |
1688 | int ret; | 1745 | int ret; |
1746 | int num_cpus = num_online_cpus(); | ||
1689 | struct Scsi_Host *host; | 1747 | struct Scsi_Host *host; |
1690 | struct hv_host_device *host_dev; | 1748 | struct hv_host_device *host_dev; |
1691 | bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); | 1749 | bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); |
@@ -1694,6 +1752,7 @@ static int storvsc_probe(struct hv_device *device, | |||
1694 | int max_luns_per_target; | 1752 | int max_luns_per_target; |
1695 | int max_targets; | 1753 | int max_targets; |
1696 | int max_channels; | 1754 | int max_channels; |
1755 | int max_sub_channels = 0; | ||
1697 | 1756 | ||
1698 | /* | 1757 | /* |
1699 | * Based on the windows host we are running on, | 1758 | * Based on the windows host we are running on, |
@@ -1719,12 +1778,18 @@ static int storvsc_probe(struct hv_device *device, | |||
1719 | max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; | 1778 | max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; |
1720 | max_targets = STORVSC_MAX_TARGETS; | 1779 | max_targets = STORVSC_MAX_TARGETS; |
1721 | max_channels = STORVSC_MAX_CHANNELS; | 1780 | max_channels = STORVSC_MAX_CHANNELS; |
1781 | /* | ||
1782 | * On Windows8 and above, we support sub-channels for storage. | ||
1783 | * The number of sub-channels offerred is based on the number of | ||
1784 | * VCPUs in the guest. | ||
1785 | */ | ||
1786 | max_sub_channels = (num_cpus / storvsc_vcpus_per_sub_channel); | ||
1722 | break; | 1787 | break; |
1723 | } | 1788 | } |
1724 | 1789 | ||
1725 | if (dev_id->driver_data == SFC_GUID) | 1790 | scsi_driver.can_queue = (max_outstanding_req_per_channel * |
1726 | scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * | 1791 | (max_sub_channels + 1)); |
1727 | STORVSC_FC_MAX_TARGETS); | 1792 | |
1728 | host = scsi_host_alloc(&scsi_driver, | 1793 | host = scsi_host_alloc(&scsi_driver, |
1729 | sizeof(struct hv_host_device)); | 1794 | sizeof(struct hv_host_device)); |
1730 | if (!host) | 1795 | if (!host) |
@@ -1780,6 +1845,12 @@ static int storvsc_probe(struct hv_device *device, | |||
1780 | /* max cmd length */ | 1845 | /* max cmd length */ |
1781 | host->max_cmd_len = STORVSC_MAX_CMD_LEN; | 1846 | host->max_cmd_len = STORVSC_MAX_CMD_LEN; |
1782 | 1847 | ||
1848 | /* | ||
1849 | * set the table size based on the info we got | ||
1850 | * from the host. | ||
1851 | */ | ||
1852 | host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT); | ||
1853 | |||
1783 | /* Register the HBA and start the scsi bus scan */ | 1854 | /* Register the HBA and start the scsi bus scan */ |
1784 | ret = scsi_add_host(host, &device->device); | 1855 | ret = scsi_add_host(host, &device->device); |
1785 | if (ret != 0) | 1856 | if (ret != 0) |
@@ -1837,7 +1908,6 @@ static struct hv_driver storvsc_drv = { | |||
1837 | 1908 | ||
1838 | static int __init storvsc_drv_init(void) | 1909 | static int __init storvsc_drv_init(void) |
1839 | { | 1910 | { |
1840 | u32 max_outstanding_req_per_channel; | ||
1841 | 1911 | ||
1842 | /* | 1912 | /* |
1843 | * Divide the ring buffer data size (which is 1 page less | 1913 | * Divide the ring buffer data size (which is 1 page less |
@@ -1852,10 +1922,6 @@ static int __init storvsc_drv_init(void) | |||
1852 | vmscsi_size_delta, | 1922 | vmscsi_size_delta, |
1853 | sizeof(u64))); | 1923 | sizeof(u64))); |
1854 | 1924 | ||
1855 | if (max_outstanding_req_per_channel < | ||
1856 | STORVSC_MAX_IO_REQUESTS) | ||
1857 | return -EINVAL; | ||
1858 | |||
1859 | return vmbus_driver_register(&storvsc_drv); | 1925 | return vmbus_driver_register(&storvsc_drv); |
1860 | } | 1926 | } |
1861 | 1927 | ||
diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 2a906d1d34ba..22a42836d193 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c | |||
@@ -676,7 +676,6 @@ static struct platform_driver sun3_scsi_driver = { | |||
676 | .remove = __exit_p(sun3_scsi_remove), | 676 | .remove = __exit_p(sun3_scsi_remove), |
677 | .driver = { | 677 | .driver = { |
678 | .name = DRV_MODULE_NAME, | 678 | .name = DRV_MODULE_NAME, |
679 | .owner = THIS_MODULE, | ||
680 | }, | 679 | }, |
681 | }; | 680 | }; |
682 | 681 | ||
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c index 9217af9bf734..6652a8171de6 100644 --- a/drivers/scsi/ufs/ufs-qcom.c +++ b/drivers/scsi/ufs/ufs-qcom.c | |||
@@ -214,8 +214,6 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) | |||
214 | struct ufs_qcom_host *host = hba->priv; | 214 | struct ufs_qcom_host *host = hba->priv; |
215 | struct phy *phy = host->generic_phy; | 215 | struct phy *phy = host->generic_phy; |
216 | int ret = 0; | 216 | int ret = 0; |
217 | u8 major; | ||
218 | u16 minor, step; | ||
219 | bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B) | 217 | bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B) |
220 | ? true : false; | 218 | ? true : false; |
221 | 219 | ||
@@ -224,8 +222,6 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba) | |||
224 | /* provide 1ms delay to let the reset pulse propagate */ | 222 | /* provide 1ms delay to let the reset pulse propagate */ |
225 | usleep_range(1000, 1100); | 223 | usleep_range(1000, 1100); |
226 | 224 | ||
227 | ufs_qcom_get_controller_revision(hba, &major, &minor, &step); | ||
228 | ufs_qcom_phy_save_controller_version(phy, major, minor, step); | ||
229 | ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B); | 225 | ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B); |
230 | if (ret) { | 226 | if (ret) { |
231 | dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n", | 227 | dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret = %d\n", |
@@ -698,16 +694,24 @@ out: | |||
698 | */ | 694 | */ |
699 | static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) | 695 | static void ufs_qcom_advertise_quirks(struct ufs_hba *hba) |
700 | { | 696 | { |
701 | u8 major; | 697 | struct ufs_qcom_host *host = hba->priv; |
702 | u16 minor, step; | ||
703 | 698 | ||
704 | ufs_qcom_get_controller_revision(hba, &major, &minor, &step); | 699 | if (host->hw_ver.major == 0x1) |
700 | hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS; | ||
705 | 701 | ||
706 | /* | 702 | if (host->hw_ver.major >= 0x2) { |
707 | * TBD | 703 | if (!ufs_qcom_cap_qunipro(host)) |
708 | * here we should be advertising controller quirks according to | 704 | /* Legacy UniPro mode still need following quirks */ |
709 | * controller version. | 705 | hba->quirks |= UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS; |
710 | */ | 706 | } |
707 | } | ||
708 | |||
709 | static void ufs_qcom_set_caps(struct ufs_hba *hba) | ||
710 | { | ||
711 | struct ufs_qcom_host *host = hba->priv; | ||
712 | |||
713 | if (host->hw_ver.major >= 0x2) | ||
714 | host->caps = UFS_QCOM_CAP_QUNIPRO; | ||
711 | } | 715 | } |
712 | 716 | ||
713 | static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, | 717 | static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host, |
@@ -929,6 +933,13 @@ static int ufs_qcom_init(struct ufs_hba *hba) | |||
929 | if (err) | 933 | if (err) |
930 | goto out_host_free; | 934 | goto out_host_free; |
931 | 935 | ||
936 | ufs_qcom_get_controller_revision(hba, &host->hw_ver.major, | ||
937 | &host->hw_ver.minor, &host->hw_ver.step); | ||
938 | |||
939 | /* update phy revision information before calling phy_init() */ | ||
940 | ufs_qcom_phy_save_controller_version(host->generic_phy, | ||
941 | host->hw_ver.major, host->hw_ver.minor, host->hw_ver.step); | ||
942 | |||
932 | phy_init(host->generic_phy); | 943 | phy_init(host->generic_phy); |
933 | err = phy_power_on(host->generic_phy); | 944 | err = phy_power_on(host->generic_phy); |
934 | if (err) | 945 | if (err) |
@@ -938,6 +949,7 @@ static int ufs_qcom_init(struct ufs_hba *hba) | |||
938 | if (err) | 949 | if (err) |
939 | goto out_disable_phy; | 950 | goto out_disable_phy; |
940 | 951 | ||
952 | ufs_qcom_set_caps(hba); | ||
941 | ufs_qcom_advertise_quirks(hba); | 953 | ufs_qcom_advertise_quirks(hba); |
942 | 954 | ||
943 | hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING; | 955 | hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING; |
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h index 9a6febd007df..db2c0a00e846 100644 --- a/drivers/scsi/ufs/ufs-qcom.h +++ b/drivers/scsi/ufs/ufs-qcom.h | |||
@@ -151,7 +151,23 @@ struct ufs_qcom_bus_vote { | |||
151 | struct device_attribute max_bus_bw; | 151 | struct device_attribute max_bus_bw; |
152 | }; | 152 | }; |
153 | 153 | ||
154 | /* Host controller hardware version: major.minor.step */ | ||
155 | struct ufs_hw_version { | ||
156 | u16 step; | ||
157 | u16 minor; | ||
158 | u8 major; | ||
159 | }; | ||
154 | struct ufs_qcom_host { | 160 | struct ufs_qcom_host { |
161 | |||
162 | /* | ||
163 | * Set this capability if host controller supports the QUniPro mode | ||
164 | * and if driver wants the Host controller to operate in QUniPro mode. | ||
165 | * Note: By default this capability will be kept enabled if host | ||
166 | * controller supports the QUniPro mode. | ||
167 | */ | ||
168 | #define UFS_QCOM_CAP_QUNIPRO UFS_BIT(0) | ||
169 | u32 caps; | ||
170 | |||
155 | struct phy *generic_phy; | 171 | struct phy *generic_phy; |
156 | struct ufs_hba *hba; | 172 | struct ufs_hba *hba; |
157 | struct ufs_qcom_bus_vote bus_vote; | 173 | struct ufs_qcom_bus_vote bus_vote; |
@@ -161,10 +177,20 @@ struct ufs_qcom_host { | |||
161 | struct clk *rx_l1_sync_clk; | 177 | struct clk *rx_l1_sync_clk; |
162 | struct clk *tx_l1_sync_clk; | 178 | struct clk *tx_l1_sync_clk; |
163 | bool is_lane_clks_enabled; | 179 | bool is_lane_clks_enabled; |
180 | |||
181 | struct ufs_hw_version hw_ver; | ||
164 | }; | 182 | }; |
165 | 183 | ||
166 | #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) | 184 | #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) |
167 | #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) | 185 | #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) |
168 | #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) | 186 | #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) |
169 | 187 | ||
188 | static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host) | ||
189 | { | ||
190 | if (host->caps & UFS_QCOM_CAP_QUNIPRO) | ||
191 | return true; | ||
192 | else | ||
193 | return false; | ||
194 | } | ||
195 | |||
170 | #endif /* UFS_QCOM_H_ */ | 196 | #endif /* UFS_QCOM_H_ */ |
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 2aa85e398f76..648a44675880 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c | |||
@@ -183,6 +183,7 @@ static int __ufshcd_setup_clocks(struct ufs_hba *hba, bool on, | |||
183 | static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); | 183 | static int ufshcd_setup_clocks(struct ufs_hba *hba, bool on); |
184 | static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); | 184 | static int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); |
185 | static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); | 185 | static int ufshcd_uic_hibern8_enter(struct ufs_hba *hba); |
186 | static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba); | ||
186 | static int ufshcd_host_reset_and_restore(struct ufs_hba *hba); | 187 | static int ufshcd_host_reset_and_restore(struct ufs_hba *hba); |
187 | static irqreturn_t ufshcd_intr(int irq, void *__hba); | 188 | static irqreturn_t ufshcd_intr(int irq, void *__hba); |
188 | static int ufshcd_config_pwr_mode(struct ufs_hba *hba, | 189 | static int ufshcd_config_pwr_mode(struct ufs_hba *hba, |
@@ -972,6 +973,8 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd) | |||
972 | 973 | ||
973 | ufshcd_hold(hba, false); | 974 | ufshcd_hold(hba, false); |
974 | mutex_lock(&hba->uic_cmd_mutex); | 975 | mutex_lock(&hba->uic_cmd_mutex); |
976 | ufshcd_add_delay_before_dme_cmd(hba); | ||
977 | |||
975 | spin_lock_irqsave(hba->host->host_lock, flags); | 978 | spin_lock_irqsave(hba->host->host_lock, flags); |
976 | ret = __ufshcd_send_uic_cmd(hba, uic_cmd); | 979 | ret = __ufshcd_send_uic_cmd(hba, uic_cmd); |
977 | spin_unlock_irqrestore(hba->host->host_lock, flags); | 980 | spin_unlock_irqrestore(hba->host->host_lock, flags); |
@@ -2058,6 +2061,37 @@ static int ufshcd_dme_link_startup(struct ufs_hba *hba) | |||
2058 | return ret; | 2061 | return ret; |
2059 | } | 2062 | } |
2060 | 2063 | ||
2064 | static inline void ufshcd_add_delay_before_dme_cmd(struct ufs_hba *hba) | ||
2065 | { | ||
2066 | #define MIN_DELAY_BEFORE_DME_CMDS_US 1000 | ||
2067 | unsigned long min_sleep_time_us; | ||
2068 | |||
2069 | if (!(hba->quirks & UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS)) | ||
2070 | return; | ||
2071 | |||
2072 | /* | ||
2073 | * last_dme_cmd_tstamp will be 0 only for 1st call to | ||
2074 | * this function | ||
2075 | */ | ||
2076 | if (unlikely(!ktime_to_us(hba->last_dme_cmd_tstamp))) { | ||
2077 | min_sleep_time_us = MIN_DELAY_BEFORE_DME_CMDS_US; | ||
2078 | } else { | ||
2079 | unsigned long delta = | ||
2080 | (unsigned long) ktime_to_us( | ||
2081 | ktime_sub(ktime_get(), | ||
2082 | hba->last_dme_cmd_tstamp)); | ||
2083 | |||
2084 | if (delta < MIN_DELAY_BEFORE_DME_CMDS_US) | ||
2085 | min_sleep_time_us = | ||
2086 | MIN_DELAY_BEFORE_DME_CMDS_US - delta; | ||
2087 | else | ||
2088 | return; /* no more delay required */ | ||
2089 | } | ||
2090 | |||
2091 | /* allow sleep for extra 50us if needed */ | ||
2092 | usleep_range(min_sleep_time_us, min_sleep_time_us + 50); | ||
2093 | } | ||
2094 | |||
2061 | /** | 2095 | /** |
2062 | * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET | 2096 | * ufshcd_dme_set_attr - UIC command for DME_SET, DME_PEER_SET |
2063 | * @hba: per adapter instance | 2097 | * @hba: per adapter instance |
@@ -2157,6 +2191,7 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd) | |||
2157 | 2191 | ||
2158 | mutex_lock(&hba->uic_cmd_mutex); | 2192 | mutex_lock(&hba->uic_cmd_mutex); |
2159 | init_completion(&uic_async_done); | 2193 | init_completion(&uic_async_done); |
2194 | ufshcd_add_delay_before_dme_cmd(hba); | ||
2160 | 2195 | ||
2161 | spin_lock_irqsave(hba->host->host_lock, flags); | 2196 | spin_lock_irqsave(hba->host->host_lock, flags); |
2162 | hba->uic_async_done = &uic_async_done; | 2197 | hba->uic_async_done = &uic_async_done; |
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 4a574aa45855..b47ff07698e8 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h | |||
@@ -366,6 +366,7 @@ struct ufs_init_prefetch { | |||
366 | * @saved_err: sticky error mask | 366 | * @saved_err: sticky error mask |
367 | * @saved_uic_err: sticky UIC error mask | 367 | * @saved_uic_err: sticky UIC error mask |
368 | * @dev_cmd: ufs device management command information | 368 | * @dev_cmd: ufs device management command information |
369 | * @last_dme_cmd_tstamp: time stamp of the last completed DME command | ||
369 | * @auto_bkops_enabled: to track whether bkops is enabled in device | 370 | * @auto_bkops_enabled: to track whether bkops is enabled in device |
370 | * @vreg_info: UFS device voltage regulator information | 371 | * @vreg_info: UFS device voltage regulator information |
371 | * @clk_list_head: UFS host controller clocks list node head | 372 | * @clk_list_head: UFS host controller clocks list node head |
@@ -416,6 +417,13 @@ struct ufs_hba { | |||
416 | unsigned int irq; | 417 | unsigned int irq; |
417 | bool is_irq_enabled; | 418 | bool is_irq_enabled; |
418 | 419 | ||
420 | /* | ||
421 | * delay before each dme command is required as the unipro | ||
422 | * layer has shown instabilities | ||
423 | */ | ||
424 | #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS UFS_BIT(0) | ||
425 | |||
426 | unsigned int quirks; /* Deviations from standard UFSHCI spec. */ | ||
419 | 427 | ||
420 | wait_queue_head_t tm_wq; | 428 | wait_queue_head_t tm_wq; |
421 | wait_queue_head_t tm_tag_wq; | 429 | wait_queue_head_t tm_tag_wq; |
@@ -446,6 +454,7 @@ struct ufs_hba { | |||
446 | 454 | ||
447 | /* Device management request data */ | 455 | /* Device management request data */ |
448 | struct ufs_dev_cmd dev_cmd; | 456 | struct ufs_dev_cmd dev_cmd; |
457 | ktime_t last_dme_cmd_tstamp; | ||
449 | 458 | ||
450 | /* Keeps information of the UFS device connected to this host */ | 459 | /* Keeps information of the UFS device connected to this host */ |
451 | struct ufs_dev_info dev_info; | 460 | struct ufs_dev_info dev_info; |
diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h index 0991913f4953..71f711db4500 100644 --- a/include/linux/string_helpers.h +++ b/include/linux/string_helpers.h | |||
@@ -10,7 +10,7 @@ enum string_size_units { | |||
10 | STRING_UNITS_2, /* use binary powers of 2^10 */ | 10 | STRING_UNITS_2, /* use binary powers of 2^10 */ |
11 | }; | 11 | }; |
12 | 12 | ||
13 | void string_get_size(u64 size, enum string_size_units units, | 13 | void string_get_size(u64 size, u64 blk_size, enum string_size_units units, |
14 | char *buf, int len); | 14 | char *buf, int len); |
15 | 15 | ||
16 | #define UNESCAPE_SPACE 0x01 | 16 | #define UNESCAPE_SPACE 0x01 |
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 007a0bc01b74..784bc2c0929f 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h | |||
@@ -135,6 +135,7 @@ enum fc_vport_state { | |||
135 | #define FC_PORTSPEED_40GBIT 0x100 | 135 | #define FC_PORTSPEED_40GBIT 0x100 |
136 | #define FC_PORTSPEED_50GBIT 0x200 | 136 | #define FC_PORTSPEED_50GBIT 0x200 |
137 | #define FC_PORTSPEED_100GBIT 0x400 | 137 | #define FC_PORTSPEED_100GBIT 0x400 |
138 | #define FC_PORTSPEED_25GBIT 0x800 | ||
138 | #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ | 139 | #define FC_PORTSPEED_NOT_NEGOTIATED (1 << 15) /* Speed not established */ |
139 | 140 | ||
140 | /* | 141 | /* |
diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 1826c7407258..c98ae818eb4e 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright 31 August 2008 James Bottomley | 4 | * Copyright 31 August 2008 James Bottomley |
5 | * Copyright (C) 2013, Intel Corporation | 5 | * Copyright (C) 2013, Intel Corporation |
6 | */ | 6 | */ |
7 | #include <linux/bug.h> | ||
7 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
8 | #include <linux/math64.h> | 9 | #include <linux/math64.h> |
9 | #include <linux/export.h> | 10 | #include <linux/export.h> |
@@ -14,7 +15,8 @@ | |||
14 | 15 | ||
15 | /** | 16 | /** |
16 | * string_get_size - get the size in the specified units | 17 | * string_get_size - get the size in the specified units |
17 | * @size: The size to be converted | 18 | * @size: The size to be converted in blocks |
19 | * @blk_size: Size of the block (use 1 for size in bytes) | ||
18 | * @units: units to use (powers of 1000 or 1024) | 20 | * @units: units to use (powers of 1000 or 1024) |
19 | * @buf: buffer to format to | 21 | * @buf: buffer to format to |
20 | * @len: length of buffer | 22 | * @len: length of buffer |
@@ -24,14 +26,14 @@ | |||
24 | * at least 9 bytes and will always be zero terminated. | 26 | * at least 9 bytes and will always be zero terminated. |
25 | * | 27 | * |
26 | */ | 28 | */ |
27 | void string_get_size(u64 size, const enum string_size_units units, | 29 | void string_get_size(u64 size, u64 blk_size, const enum string_size_units units, |
28 | char *buf, int len) | 30 | char *buf, int len) |
29 | { | 31 | { |
30 | static const char *const units_10[] = { | 32 | static const char *const units_10[] = { |
31 | "B", "kB", "MB", "GB", "TB", "PB", "EB" | 33 | "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" |
32 | }; | 34 | }; |
33 | static const char *const units_2[] = { | 35 | static const char *const units_2[] = { |
34 | "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB" | 36 | "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" |
35 | }; | 37 | }; |
36 | static const char *const *const units_str[] = { | 38 | static const char *const *const units_str[] = { |
37 | [STRING_UNITS_10] = units_10, | 39 | [STRING_UNITS_10] = units_10, |
@@ -42,31 +44,57 @@ void string_get_size(u64 size, const enum string_size_units units, | |||
42 | [STRING_UNITS_2] = 1024, | 44 | [STRING_UNITS_2] = 1024, |
43 | }; | 45 | }; |
44 | int i, j; | 46 | int i, j; |
45 | u32 remainder = 0, sf_cap; | 47 | u32 remainder = 0, sf_cap, exp; |
46 | char tmp[8]; | 48 | char tmp[8]; |
49 | const char *unit; | ||
47 | 50 | ||
48 | tmp[0] = '\0'; | 51 | tmp[0] = '\0'; |
49 | i = 0; | 52 | i = 0; |
50 | if (size >= divisor[units]) { | 53 | if (!size) |
51 | while (size >= divisor[units]) { | 54 | goto out; |
52 | remainder = do_div(size, divisor[units]); | ||
53 | i++; | ||
54 | } | ||
55 | 55 | ||
56 | sf_cap = size; | 56 | while (blk_size >= divisor[units]) { |
57 | for (j = 0; sf_cap*10 < 1000; j++) | 57 | remainder = do_div(blk_size, divisor[units]); |
58 | sf_cap *= 10; | 58 | i++; |
59 | } | ||
59 | 60 | ||
60 | if (j) { | 61 | exp = divisor[units] / (u32)blk_size; |
61 | remainder *= 1000; | 62 | if (size >= exp) { |
62 | remainder /= divisor[units]; | 63 | remainder = do_div(size, divisor[units]); |
63 | snprintf(tmp, sizeof(tmp), ".%03u", remainder); | 64 | remainder *= blk_size; |
64 | tmp[j+1] = '\0'; | 65 | i++; |
65 | } | 66 | } else { |
67 | remainder *= size; | ||
68 | } | ||
69 | |||
70 | size *= blk_size; | ||
71 | size += remainder / divisor[units]; | ||
72 | remainder %= divisor[units]; | ||
73 | |||
74 | while (size >= divisor[units]) { | ||
75 | remainder = do_div(size, divisor[units]); | ||
76 | i++; | ||
66 | } | 77 | } |
67 | 78 | ||
79 | sf_cap = size; | ||
80 | for (j = 0; sf_cap*10 < 1000; j++) | ||
81 | sf_cap *= 10; | ||
82 | |||
83 | if (j) { | ||
84 | remainder *= 1000; | ||
85 | remainder /= divisor[units]; | ||
86 | snprintf(tmp, sizeof(tmp), ".%03u", remainder); | ||
87 | tmp[j+1] = '\0'; | ||
88 | } | ||
89 | |||
90 | out: | ||
91 | if (i >= ARRAY_SIZE(units_2)) | ||
92 | unit = "UNK"; | ||
93 | else | ||
94 | unit = units_str[units][i]; | ||
95 | |||
68 | snprintf(buf, len, "%u%s %s", (u32)size, | 96 | snprintf(buf, len, "%u%s %s", (u32)size, |
69 | tmp, units_str[units][i]); | 97 | tmp, unit); |
70 | } | 98 | } |
71 | EXPORT_SYMBOL(string_get_size); | 99 | EXPORT_SYMBOL(string_get_size); |
72 | 100 | ||