diff options
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 181 |
1 files changed, 152 insertions, 29 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index b03c8dee76b7..d6c999cd7f78 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -133,6 +133,7 @@ struct inquiry_data { | |||
133 | 133 | ||
134 | static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); | 134 | static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap); |
135 | static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); | 135 | static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg); |
136 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg); | ||
136 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); | 137 | static int aac_send_srb_fib(struct scsi_cmnd* scsicmd); |
137 | #ifdef AAC_DETAILED_STATUS_INFO | 138 | #ifdef AAC_DETAILED_STATUS_INFO |
138 | static char *aac_get_status_string(u32 status); | 139 | static char *aac_get_status_string(u32 status); |
@@ -777,34 +778,36 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
777 | /* | 778 | /* |
778 | * 57 scatter gather elements | 779 | * 57 scatter gather elements |
779 | */ | 780 | */ |
780 | dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - | 781 | if (!(dev->raw_io_interface)) { |
781 | sizeof(struct aac_fibhdr) - | 782 | dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size - |
782 | sizeof(struct aac_write) + sizeof(struct sgmap)) / | ||
783 | sizeof(struct sgmap); | ||
784 | if (dev->dac_support) { | ||
785 | /* | ||
786 | * 38 scatter gather elements | ||
787 | */ | ||
788 | dev->scsi_host_ptr->sg_tablesize = | ||
789 | (dev->max_fib_size - | ||
790 | sizeof(struct aac_fibhdr) - | 783 | sizeof(struct aac_fibhdr) - |
791 | sizeof(struct aac_write64) + | 784 | sizeof(struct aac_write) + sizeof(struct sgmap)) / |
792 | sizeof(struct sgmap64)) / | 785 | sizeof(struct sgmap); |
793 | sizeof(struct sgmap64); | 786 | if (dev->dac_support) { |
794 | } | 787 | /* |
795 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; | 788 | * 38 scatter gather elements |
796 | if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { | 789 | */ |
797 | /* | 790 | dev->scsi_host_ptr->sg_tablesize = |
798 | * Worst case size that could cause sg overflow when | 791 | (dev->max_fib_size - |
799 | * we break up SG elements that are larger than 64KB. | 792 | sizeof(struct aac_fibhdr) - |
800 | * Would be nice if we could tell the SCSI layer what | 793 | sizeof(struct aac_write64) + |
801 | * the maximum SG element size can be. Worst case is | 794 | sizeof(struct sgmap64)) / |
802 | * (sg_tablesize-1) 4KB elements with one 64KB | 795 | sizeof(struct sgmap64); |
803 | * element. | 796 | } |
804 | * 32bit -> 468 or 238KB 64bit -> 424 or 212KB | 797 | dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT; |
805 | */ | 798 | if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) { |
806 | dev->scsi_host_ptr->max_sectors = | 799 | /* |
807 | (dev->scsi_host_ptr->sg_tablesize * 8) + 112; | 800 | * Worst case size that could cause sg overflow when |
801 | * we break up SG elements that are larger than 64KB. | ||
802 | * Would be nice if we could tell the SCSI layer what | ||
803 | * the maximum SG element size can be. Worst case is | ||
804 | * (sg_tablesize-1) 4KB elements with one 64KB | ||
805 | * element. | ||
806 | * 32bit -> 468 or 238KB 64bit -> 424 or 212KB | ||
807 | */ | ||
808 | dev->scsi_host_ptr->max_sectors = | ||
809 | (dev->scsi_host_ptr->sg_tablesize * 8) + 112; | ||
810 | } | ||
808 | } | 811 | } |
809 | 812 | ||
810 | fib_complete(fibptr); | 813 | fib_complete(fibptr); |
@@ -905,7 +908,32 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
905 | 908 | ||
906 | fib_init(cmd_fibcontext); | 909 | fib_init(cmd_fibcontext); |
907 | 910 | ||
908 | if (dev->dac_support == 1) { | 911 | if (dev->raw_io_interface) { |
912 | struct aac_raw_io *readcmd; | ||
913 | readcmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); | ||
914 | readcmd->block[0] = cpu_to_le32(lba); | ||
915 | readcmd->block[1] = 0; | ||
916 | readcmd->count = cpu_to_le32(count<<9); | ||
917 | readcmd->cid = cpu_to_le16(cid); | ||
918 | readcmd->flags = cpu_to_le16(1); | ||
919 | readcmd->bpTotal = 0; | ||
920 | readcmd->bpComplete = 0; | ||
921 | |||
922 | aac_build_sgraw(scsicmd, &readcmd->sg); | ||
923 | fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(readcmd->sg.count) - 1) * sizeof (struct sgentryraw)); | ||
924 | if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) | ||
925 | BUG(); | ||
926 | /* | ||
927 | * Now send the Fib to the adapter | ||
928 | */ | ||
929 | status = fib_send(ContainerRawIo, | ||
930 | cmd_fibcontext, | ||
931 | fibsize, | ||
932 | FsaNormal, | ||
933 | 0, 1, | ||
934 | (fib_callback) io_callback, | ||
935 | (void *) scsicmd); | ||
936 | } else if (dev->dac_support == 1) { | ||
909 | struct aac_read64 *readcmd; | 937 | struct aac_read64 *readcmd; |
910 | readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); | 938 | readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext); |
911 | readcmd->command = cpu_to_le32(VM_CtHostRead64); | 939 | readcmd->command = cpu_to_le32(VM_CtHostRead64); |
@@ -1012,7 +1040,32 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) | |||
1012 | } | 1040 | } |
1013 | fib_init(cmd_fibcontext); | 1041 | fib_init(cmd_fibcontext); |
1014 | 1042 | ||
1015 | if(dev->dac_support == 1) { | 1043 | if (dev->raw_io_interface) { |
1044 | struct aac_raw_io *writecmd; | ||
1045 | writecmd = (struct aac_raw_io *) fib_data(cmd_fibcontext); | ||
1046 | writecmd->block[0] = cpu_to_le32(lba); | ||
1047 | writecmd->block[1] = 0; | ||
1048 | writecmd->count = cpu_to_le32(count<<9); | ||
1049 | writecmd->cid = cpu_to_le16(cid); | ||
1050 | writecmd->flags = 0; | ||
1051 | writecmd->bpTotal = 0; | ||
1052 | writecmd->bpComplete = 0; | ||
1053 | |||
1054 | aac_build_sgraw(scsicmd, &writecmd->sg); | ||
1055 | fibsize = sizeof(struct aac_raw_io) + ((le32_to_cpu(writecmd->sg.count) - 1) * sizeof (struct sgentryraw)); | ||
1056 | if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) | ||
1057 | BUG(); | ||
1058 | /* | ||
1059 | * Now send the Fib to the adapter | ||
1060 | */ | ||
1061 | status = fib_send(ContainerRawIo, | ||
1062 | cmd_fibcontext, | ||
1063 | fibsize, | ||
1064 | FsaNormal, | ||
1065 | 0, 1, | ||
1066 | (fib_callback) io_callback, | ||
1067 | (void *) scsicmd); | ||
1068 | } else if (dev->dac_support == 1) { | ||
1016 | struct aac_write64 *writecmd; | 1069 | struct aac_write64 *writecmd; |
1017 | writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); | 1070 | writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext); |
1018 | writecmd->command = cpu_to_le32(VM_CtHostWrite64); | 1071 | writecmd->command = cpu_to_le32(VM_CtHostWrite64); |
@@ -2028,6 +2081,76 @@ static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* p | |||
2028 | return byte_count; | 2081 | return byte_count; |
2029 | } | 2082 | } |
2030 | 2083 | ||
2084 | static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg) | ||
2085 | { | ||
2086 | struct Scsi_Host *host = scsicmd->device->host; | ||
2087 | struct aac_dev *dev = (struct aac_dev *)host->hostdata; | ||
2088 | unsigned long byte_count = 0; | ||
2089 | |||
2090 | // Get rid of old data | ||
2091 | psg->count = 0; | ||
2092 | psg->sg[0].next = 0; | ||
2093 | psg->sg[0].prev = 0; | ||
2094 | psg->sg[0].addr[0] = 0; | ||
2095 | psg->sg[0].addr[1] = 0; | ||
2096 | psg->sg[0].count = 0; | ||
2097 | psg->sg[0].flags = 0; | ||
2098 | if (scsicmd->use_sg) { | ||
2099 | struct scatterlist *sg; | ||
2100 | int i; | ||
2101 | int sg_count; | ||
2102 | sg = (struct scatterlist *) scsicmd->request_buffer; | ||
2103 | |||
2104 | sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg, | ||
2105 | scsicmd->sc_data_direction); | ||
2106 | |||
2107 | for (i = 0; i < sg_count; i++) { | ||
2108 | int count = sg_dma_len(sg); | ||
2109 | u64 addr = sg_dma_address(sg); | ||
2110 | psg->sg[i].next = 0; | ||
2111 | psg->sg[i].prev = 0; | ||
2112 | psg->sg[i].addr[1] = cpu_to_le32((u32)(addr>>32)); | ||
2113 | psg->sg[i].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | ||
2114 | psg->sg[i].count = cpu_to_le32(count); | ||
2115 | psg->sg[i].flags = 0; | ||
2116 | byte_count += count; | ||
2117 | sg++; | ||
2118 | } | ||
2119 | psg->count = cpu_to_le32(sg_count); | ||
2120 | /* hba wants the size to be exact */ | ||
2121 | if(byte_count > scsicmd->request_bufflen){ | ||
2122 | u32 temp = le32_to_cpu(psg->sg[i-1].count) - | ||
2123 | (byte_count - scsicmd->request_bufflen); | ||
2124 | psg->sg[i-1].count = cpu_to_le32(temp); | ||
2125 | byte_count = scsicmd->request_bufflen; | ||
2126 | } | ||
2127 | /* Check for command underflow */ | ||
2128 | if(scsicmd->underflow && (byte_count < scsicmd->underflow)){ | ||
2129 | printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n", | ||
2130 | byte_count, scsicmd->underflow); | ||
2131 | } | ||
2132 | } | ||
2133 | else if(scsicmd->request_bufflen) { | ||
2134 | int count; | ||
2135 | u64 addr; | ||
2136 | scsicmd->SCp.dma_handle = pci_map_single(dev->pdev, | ||
2137 | scsicmd->request_buffer, | ||
2138 | scsicmd->request_bufflen, | ||
2139 | scsicmd->sc_data_direction); | ||
2140 | addr = scsicmd->SCp.dma_handle; | ||
2141 | count = scsicmd->request_bufflen; | ||
2142 | psg->count = cpu_to_le32(1); | ||
2143 | psg->sg[0].next = 0; | ||
2144 | psg->sg[0].prev = 0; | ||
2145 | psg->sg[0].addr[1] = cpu_to_le32((u32)(addr>>32)); | ||
2146 | psg->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff)); | ||
2147 | psg->sg[0].count = cpu_to_le32(count); | ||
2148 | psg->sg[0].flags = 0; | ||
2149 | byte_count = scsicmd->request_bufflen; | ||
2150 | } | ||
2151 | return byte_count; | ||
2152 | } | ||
2153 | |||
2031 | #ifdef AAC_DETAILED_STATUS_INFO | 2154 | #ifdef AAC_DETAILED_STATUS_INFO |
2032 | 2155 | ||
2033 | struct aac_srb_status_info { | 2156 | struct aac_srb_status_info { |