Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

USB storage: sg chaining support

[PATCH] USB storage: sg chaining support

Modify usb_stor_access_xfer_buf() to take a pointer to an sg
entry pointer, so we can keep track of that instead of passing
around an integer index (which we can't use when dealing with
multiple scatterlist arrays).

Signed-off-by: Jens Axboe <jens.axboe@oracle.com>

+62 -45
+10 -6
drivers/usb/storage/alauda.c
··· 798 798 { 799 799 unsigned char *buffer; 800 800 u16 lba, max_lba; 801 - unsigned int page, len, index, offset; 801 + unsigned int page, len, offset; 802 802 unsigned int blockshift = MEDIA_INFO(us).blockshift; 803 803 unsigned int pageshift = MEDIA_INFO(us).pageshift; 804 804 unsigned int blocksize = MEDIA_INFO(us).blocksize; 805 805 unsigned int pagesize = MEDIA_INFO(us).pagesize; 806 806 unsigned int uzonesize = MEDIA_INFO(us).uzonesize; 807 + struct scatterlist *sg; 807 808 int result; 808 809 809 810 /* ··· 828 827 max_lba = MEDIA_INFO(us).capacity >> (blockshift + pageshift); 829 828 830 829 result = USB_STOR_TRANSPORT_GOOD; 831 - index = offset = 0; 830 + offset = 0; 831 + sg = NULL; 832 832 833 833 while (sectors > 0) { 834 834 unsigned int zone = lba / uzonesize; /* integer division */ ··· 875 873 876 874 /* Store the data in the transfer buffer */ 877 875 usb_stor_access_xfer_buf(buffer, len, us->srb, 878 - &index, &offset, TO_XFER_BUF); 876 + &sg, &offset, TO_XFER_BUF); 879 877 880 878 page = 0; 881 879 lba++; ··· 893 891 unsigned int sectors) 894 892 { 895 893 unsigned char *buffer, *blockbuffer; 896 - unsigned int page, len, index, offset; 894 + unsigned int page, len, offset; 897 895 unsigned int blockshift = MEDIA_INFO(us).blockshift; 898 896 unsigned int pageshift = MEDIA_INFO(us).pageshift; 899 897 unsigned int blocksize = MEDIA_INFO(us).blocksize; 900 898 unsigned int pagesize = MEDIA_INFO(us).pagesize; 899 + struct scatterlist *sg; 901 900 u16 lba, max_lba; 902 901 int result; 903 902 ··· 932 929 max_lba = MEDIA_INFO(us).capacity >> (pageshift + blockshift); 933 930 934 931 result = USB_STOR_TRANSPORT_GOOD; 935 - index = offset = 0; 932 + offset = 0; 933 + sg = NULL; 936 934 937 935 while (sectors > 0) { 938 936 /* Write as many sectors as possible in this block */ ··· 950 946 951 947 /* Get the data from the transfer buffer */ 952 948 usb_stor_access_xfer_buf(buffer, len, us->srb, 953 - &index, &offset, FROM_XFER_BUF); 949 + &sg, &offset, FROM_XFER_BUF); 954 950 955 951 result = alauda_write_lba(us, lba, page, pages, buffer, 956 952 blockbuffer);
+6 -4
drivers/usb/storage/datafab.c
··· 98 98 unsigned char thistime; 99 99 unsigned int totallen, alloclen; 100 100 int len, result; 101 - unsigned int sg_idx = 0, sg_offset = 0; 101 + unsigned int sg_offset = 0; 102 + struct scatterlist *sg = NULL; 102 103 103 104 // we're working in LBA mode. according to the ATA spec, 104 105 // we can support up to 28-bit addressing. I don't know if Datafab ··· 156 155 157 156 // Store the data in the transfer buffer 158 157 usb_stor_access_xfer_buf(buffer, len, us->srb, 159 - &sg_idx, &sg_offset, TO_XFER_BUF); 158 + &sg, &sg_offset, TO_XFER_BUF); 160 159 161 160 sector += thistime; 162 161 totallen -= len; ··· 182 181 unsigned char thistime; 183 182 unsigned int totallen, alloclen; 184 183 int len, result; 185 - unsigned int sg_idx = 0, sg_offset = 0; 184 + unsigned int sg_offset = 0; 185 + struct scatterlist *sg = NULL; 186 186 187 187 // we're working in LBA mode. according to the ATA spec, 188 188 // we can support up to 28-bit addressing. I don't know if Datafab ··· 219 217 220 218 // Get the data from the transfer buffer 221 219 usb_stor_access_xfer_buf(buffer, len, us->srb, 222 - &sg_idx, &sg_offset, FROM_XFER_BUF); 220 + &sg, &sg_offset, FROM_XFER_BUF); 223 221 224 222 command[0] = 0; 225 223 command[1] = thistime;
+6 -4
drivers/usb/storage/jumpshot.c
··· 119 119 unsigned char thistime; 120 120 unsigned int totallen, alloclen; 121 121 int len, result; 122 - unsigned int sg_idx = 0, sg_offset = 0; 122 + unsigned int sg_offset = 0; 123 + struct scatterlist *sg = NULL; 123 124 124 125 // we're working in LBA mode. according to the ATA spec, 125 126 // we can support up to 28-bit addressing. I don't know if Jumpshot ··· 171 170 172 171 // Store the data in the transfer buffer 173 172 usb_stor_access_xfer_buf(buffer, len, us->srb, 174 - &sg_idx, &sg_offset, TO_XFER_BUF); 173 + &sg, &sg_offset, TO_XFER_BUF); 175 174 176 175 sector += thistime; 177 176 totallen -= len; ··· 196 195 unsigned char thistime; 197 196 unsigned int totallen, alloclen; 198 197 int len, result, waitcount; 199 - unsigned int sg_idx = 0, sg_offset = 0; 198 + unsigned int sg_offset = 0; 199 + struct scatterlist *sg = NULL; 200 200 201 201 // we're working in LBA mode. according to the ATA spec, 202 202 // we can support up to 28-bit addressing. I don't know if Jumpshot ··· 227 225 228 226 // Get the data from the transfer buffer 229 227 usb_stor_access_xfer_buf(buffer, len, us->srb, 230 - &sg_idx, &sg_offset, FROM_XFER_BUF); 228 + &sg, &sg_offset, FROM_XFER_BUF); 231 229 232 230 command[0] = 0; 233 231 command[1] = thistime;
+11 -9
drivers/usb/storage/protocol.c
··· 157 157 * pick up from where this one left off. */ 158 158 159 159 unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, 160 - unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, 160 + unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr, 161 161 unsigned int *offset, enum xfer_buf_dir dir) 162 162 { 163 163 unsigned int cnt; ··· 184 184 * located in high memory -- then kmap() will map it to a temporary 185 185 * position in the kernel's virtual address space. */ 186 186 } else { 187 - struct scatterlist *sg = 188 - (struct scatterlist *) srb->request_buffer 189 - + *index; 187 + struct scatterlist *sg = *sgptr; 188 + 189 + if (!sg) 190 + sg = (struct scatterlist *) srb->request_buffer; 190 191 191 192 /* This loop handles a single s-g list entry, which may 192 193 * include multiple pages. Find the initial page structure 193 194 * and the starting offset within the page, and update 194 195 * the *offset and *index values for the next loop. */ 195 196 cnt = 0; 196 - while (cnt < buflen && *index < srb->use_sg) { 197 + while (cnt < buflen) { 197 198 struct page *page = sg->page + 198 199 ((sg->offset + *offset) >> PAGE_SHIFT); 199 200 unsigned int poff = ··· 210 209 211 210 /* Transfer continues to next s-g entry */ 212 211 *offset = 0; 213 - ++*index; 214 - ++sg; 212 + sg = sg_next(sg); 215 213 } 216 214 217 215 /* Transfer the data for all the pages in this ··· 234 234 sglen -= plen; 235 235 } 236 236 } 237 + *sgptr = sg; 237 238 } 238 239 239 240 /* Return the amount actually transferred */ ··· 246 245 void usb_stor_set_xfer_buf(unsigned char *buffer, 247 246 unsigned int buflen, struct scsi_cmnd *srb) 248 247 { 249 - unsigned int index = 0, offset = 0; 248 + unsigned int offset = 0; 249 + struct scatterlist *sg = NULL; 250 250 251 - usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, 251 + usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset, 252 252 TO_XFER_BUF); 253 253 if (buflen < srb->request_bufflen) 254 254 srb->resid = srb->request_bufflen - buflen;
+1 -1
drivers/usb/storage/protocol.h
··· 52 52 enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF}; 53 53 54 54 extern unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, 55 - unsigned int buflen, struct scsi_cmnd *srb, unsigned int *index, 55 + unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **, 56 56 unsigned int *offset, enum xfer_buf_dir dir); 57 57 58 58 extern void usb_stor_set_xfer_buf(unsigned char *buffer,
+10 -6
drivers/usb/storage/sddr09.c
··· 705 705 unsigned char *buffer; 706 706 unsigned int lba, maxlba, pba; 707 707 unsigned int page, pages; 708 - unsigned int len, index, offset; 708 + unsigned int len, offset; 709 + struct scatterlist *sg; 709 710 int result; 710 711 711 712 // Figure out the initial LBA and page ··· 731 730 // contiguous LBA's. Another exercise left to the student. 732 731 733 732 result = 0; 734 - index = offset = 0; 733 + offset = 0; 734 + sg = NULL; 735 735 736 736 while (sectors > 0) { 737 737 ··· 779 777 780 778 // Store the data in the transfer buffer 781 779 usb_stor_access_xfer_buf(buffer, len, us->srb, 782 - &index, &offset, TO_XFER_BUF); 780 + &sg, &offset, TO_XFER_BUF); 783 781 784 782 page = 0; 785 783 lba++; ··· 933 931 unsigned int pagelen, blocklen; 934 932 unsigned char *blockbuffer; 935 933 unsigned char *buffer; 936 - unsigned int len, index, offset; 934 + unsigned int len, offset; 935 + struct scatterlist *sg; 937 936 int result; 938 937 939 938 // Figure out the initial LBA and page ··· 971 968 } 972 969 973 970 result = 0; 974 - index = offset = 0; 971 + offset = 0; 972 + sg = NULL; 975 973 976 974 while (sectors > 0) { 977 975 ··· 991 987 992 988 // Get the data from the transfer buffer 993 989 usb_stor_access_xfer_buf(buffer, len, us->srb, 994 - &index, &offset, FROM_XFER_BUF); 990 + &sg, &offset, FROM_XFER_BUF); 995 991 996 992 result = sddr09_write_lba(us, lba, page, pages, 997 993 buffer, blockbuffer);
+10 -6
drivers/usb/storage/sddr55.c
··· 167 167 unsigned long address; 168 168 169 169 unsigned short pages; 170 - unsigned int len, index, offset; 170 + unsigned int len, offset; 171 + struct scatterlist *sg; 171 172 172 173 // Since we only read in one block at a time, we have to create 173 174 // a bounce buffer and move the data a piece at a time between the ··· 179 178 buffer = kmalloc(len, GFP_NOIO); 180 179 if (buffer == NULL) 181 180 return USB_STOR_TRANSPORT_ERROR; /* out of memory */ 182 - index = offset = 0; 181 + offset = 0; 182 + sg = NULL; 183 183 184 184 while (sectors>0) { 185 185 ··· 257 255 258 256 // Store the data in the transfer buffer 259 257 usb_stor_access_xfer_buf(buffer, len, us->srb, 260 - &index, &offset, TO_XFER_BUF); 258 + &sg, &offset, TO_XFER_BUF); 261 259 262 260 page = 0; 263 261 lba++; ··· 289 287 290 288 unsigned short pages; 291 289 int i; 292 - unsigned int len, index, offset; 290 + unsigned int len, offset; 291 + struct scatterlist *sg; 293 292 294 293 /* check if we are allowed to write */ 295 294 if (info->read_only || info->force_read_only) { ··· 307 304 buffer = kmalloc(len, GFP_NOIO); 308 305 if (buffer == NULL) 309 306 return USB_STOR_TRANSPORT_ERROR; 310 - index = offset = 0; 307 + offset = 0; 308 + sg = NULL; 311 309 312 310 while (sectors > 0) { 313 311 ··· 326 322 327 323 // Get the data from the transfer buffer 328 324 usb_stor_access_xfer_buf(buffer, len, us->srb, 329 - &index, &offset, FROM_XFER_BUF); 325 + &sg, &offset, FROM_XFER_BUF); 330 326 331 327 US_DEBUGP("Write %02X pages, to PBA %04X" 332 328 " (LBA %04X) page %02X\n",
+8 -9
drivers/usb/storage/shuttle_usbat.c
··· 993 993 unsigned char thistime; 994 994 unsigned int totallen, alloclen; 995 995 int len, result; 996 - unsigned int sg_idx = 0, sg_offset = 0; 996 + unsigned int sg_offset = 0; 997 + struct scatterlist *sg = NULL; 997 998 998 999 result = usbat_flash_check_media(us, info); 999 1000 if (result != USB_STOR_TRANSPORT_GOOD) ··· 1048 1047 1049 1048 /* Store the data in the transfer buffer */ 1050 1049 usb_stor_access_xfer_buf(buffer, len, us->srb, 1051 - &sg_idx, &sg_offset, TO_XFER_BUF); 1050 + &sg, &sg_offset, TO_XFER_BUF); 1052 1051 1053 1052 sector += thistime; 1054 1053 totallen -= len; ··· 1084 1083 unsigned char thistime; 1085 1084 unsigned int totallen, alloclen; 1086 1085 int len, result; 1087 - unsigned int sg_idx = 0, sg_offset = 0; 1086 + unsigned int sg_offset = 0; 1087 + struct scatterlist *sg = NULL; 1088 1088 1089 1089 result = usbat_flash_check_media(us, info); 1090 1090 if (result != USB_STOR_TRANSPORT_GOOD) ··· 1124 1122 1125 1123 /* Get the data from the transfer buffer */ 1126 1124 usb_stor_access_xfer_buf(buffer, len, us->srb, 1127 - &sg_idx, &sg_offset, FROM_XFER_BUF); 1125 + &sg, &sg_offset, FROM_XFER_BUF); 1128 1126 1129 1127 /* ATA command 0x30 (WRITE SECTORS) */ 1130 1128 usbat_pack_ata_sector_cmd(command, thistime, sector, 0x30); ··· 1164 1162 unsigned char *buffer; 1165 1163 unsigned int len; 1166 1164 unsigned int sector; 1167 - unsigned int sg_segment = 0; 1168 1165 unsigned int sg_offset = 0; 1166 + struct scatterlist *sg = NULL; 1169 1167 1170 1168 US_DEBUGP("handle_read10: transfersize %d\n", 1171 1169 srb->transfersize); ··· 1222 1220 sector |= short_pack(data[7+5], data[7+4]); 1223 1221 transferred = 0; 1224 1222 1225 - sg_segment = 0; /* for keeping track of where we are in */ 1226 - sg_offset = 0; /* the scatter/gather list */ 1227 - 1228 1223 while (transferred != srb->request_bufflen) { 1229 1224 1230 1225 if (len > srb->request_bufflen - transferred) ··· 1254 1255 1255 1256 /* Store the data in the transfer buffer */ 1256 1257 usb_stor_access_xfer_buf(buffer, len, srb, 1257 - &sg_segment, &sg_offset, TO_XFER_BUF); 1258 + &sg, &sg_offset, TO_XFER_BUF); 1258 1259 1259 1260 /* Update the amount transferred and the sector number */ 1260 1261