diff options
Diffstat (limited to 'drivers/usb/storage/protocol.c')
-rw-r--r-- | drivers/usb/storage/protocol.c | 20 |
1 files changed, 11 insertions, 9 deletions
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index 9ad30428d2dd..cc8f7c52c729 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c | |||
@@ -157,7 +157,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, | |||
157 | * pick up from where this one left off. */ | 157 | * pick up from where this one left off. */ |
158 | 158 | ||
159 | unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, | 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 | unsigned int *offset, enum xfer_buf_dir dir) | 161 | unsigned int *offset, enum xfer_buf_dir dir) |
162 | { | 162 | { |
163 | unsigned int cnt; | 163 | unsigned int cnt; |
@@ -184,16 +184,17 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, | |||
184 | * located in high memory -- then kmap() will map it to a temporary | 184 | * located in high memory -- then kmap() will map it to a temporary |
185 | * position in the kernel's virtual address space. */ | 185 | * position in the kernel's virtual address space. */ |
186 | } else { | 186 | } else { |
187 | struct scatterlist *sg = | 187 | struct scatterlist *sg = *sgptr; |
188 | (struct scatterlist *) srb->request_buffer | 188 | |
189 | + *index; | 189 | if (!sg) |
190 | sg = (struct scatterlist *) srb->request_buffer; | ||
190 | 191 | ||
191 | /* This loop handles a single s-g list entry, which may | 192 | /* This loop handles a single s-g list entry, which may |
192 | * include multiple pages. Find the initial page structure | 193 | * include multiple pages. Find the initial page structure |
193 | * and the starting offset within the page, and update | 194 | * and the starting offset within the page, and update |
194 | * the *offset and *index values for the next loop. */ | 195 | * the *offset and *index values for the next loop. */ |
195 | cnt = 0; | 196 | cnt = 0; |
196 | while (cnt < buflen && *index < srb->use_sg) { | 197 | while (cnt < buflen) { |
197 | struct page *page = sg->page + | 198 | struct page *page = sg->page + |
198 | ((sg->offset + *offset) >> PAGE_SHIFT); | 199 | ((sg->offset + *offset) >> PAGE_SHIFT); |
199 | unsigned int poff = | 200 | unsigned int poff = |
@@ -209,8 +210,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, | |||
209 | 210 | ||
210 | /* Transfer continues to next s-g entry */ | 211 | /* Transfer continues to next s-g entry */ |
211 | *offset = 0; | 212 | *offset = 0; |
212 | ++*index; | 213 | sg = sg_next(sg); |
213 | ++sg; | ||
214 | } | 214 | } |
215 | 215 | ||
216 | /* Transfer the data for all the pages in this | 216 | /* Transfer the data for all the pages in this |
@@ -234,6 +234,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, | |||
234 | sglen -= plen; | 234 | sglen -= plen; |
235 | } | 235 | } |
236 | } | 236 | } |
237 | *sgptr = sg; | ||
237 | } | 238 | } |
238 | 239 | ||
239 | /* Return the amount actually transferred */ | 240 | /* Return the amount actually transferred */ |
@@ -245,9 +246,10 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, | |||
245 | void usb_stor_set_xfer_buf(unsigned char *buffer, | 246 | void usb_stor_set_xfer_buf(unsigned char *buffer, |
246 | unsigned int buflen, struct scsi_cmnd *srb) | 247 | unsigned int buflen, struct scsi_cmnd *srb) |
247 | { | 248 | { |
248 | unsigned int index = 0, offset = 0; | 249 | unsigned int offset = 0; |
250 | struct scatterlist *sg = NULL; | ||
249 | 251 | ||
250 | usb_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset, | 252 | usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset, |
251 | TO_XFER_BUF); | 253 | TO_XFER_BUF); |
252 | if (buflen < srb->request_bufflen) | 254 | if (buflen < srb->request_bufflen) |
253 | srb->resid = srb->request_bufflen - buflen; | 255 | srb->resid = srb->request_bufflen - buflen; |