summaryrefslogtreecommitdiffstats
path: root/drivers/usb/storage/protocol.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-21 16:20:22 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-21 16:20:22 -0800
commitc6b083466818e674d479cfeb847061a57658bcba (patch)
treec7cf12be0eb0a742dbb543248c0906f5de15fefb /drivers/usb/storage/protocol.c
parent5d637c4a5146f803a872275c139fc11914056d74 (diff)
parentb5937a415fc0387c18c40d618c7e98d1e2f65b42 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (23 commits) ehci-fsl: add PPC_MPC837x to default y USB: POWERPC: ehci: fix ppc build USB: usb-storage: don't access beyond the end of the sg buffer USB: quirks and unusual_devs entry for Actions flash drive USB: usb-storage: unusual_devs entry for Oracom MP3 player USB: serial: move zte MF330 from sierra to option USB: add new vernier product id to ldusb.c USB: gadget: queue usb USB_CDC_GET_ENCAPSULATED_RESPONSE message USB: Add another Novatel U727 ID to the device table for usbserial USB: storage: Nikon D80 new FW still needs Fixup USB: usb-storage: don't clear-halt when Get-Max-LUN stalls USB: option: Added vendor id for Dell 5720 broadband modem USB: option: Add Kyocera KPC680 ids USB: quirks for known quirky audio devices USB: fix previous sparse fix which was incorrect USB: fix error handling in trancevibrator USB: g_printer, fix empty if statement USB: ehci-fsl: mpc834x config symbol is PPC_MPC834x, not MPC834x USB: fix usb open suspend race in cdc-acm USB: usb: yet another Dell wireless CDMA/EVDO modem ...
Diffstat (limited to 'drivers/usb/storage/protocol.c')
-rw-r--r--drivers/usb/storage/protocol.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
index a41ce21c069..958f5b17847 100644
--- a/drivers/usb/storage/protocol.c
+++ b/drivers/usb/storage/protocol.c
@@ -150,13 +150,14 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb,
/* Copy a buffer of length buflen to/from the srb's transfer buffer.
* Update the **sgptr and *offset variables so that the next copy will
- * pick up from where this one left off. */
-
+ * pick up from where this one left off.
+ */
unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb, struct scatterlist **sgptr,
unsigned int *offset, enum xfer_buf_dir dir)
{
unsigned int cnt;
+ struct scatterlist *sg = *sgptr;
/* We have to go through the list one entry
* at a time. Each s-g entry contains some number of pages, and
@@ -164,22 +165,23 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
* in kernel-addressable memory then kmap() will return its address.
* If the page is not directly accessible -- such as a user buffer
* located in high memory -- then kmap() will map it to a temporary
- * position in the kernel's virtual address space. */
- struct scatterlist *sg = *sgptr;
+ * position in the kernel's virtual address space.
+ */
if (!sg)
sg = scsi_sglist(srb);
+ buflen = min(buflen, scsi_bufflen(srb));
/* This loop handles a single s-g list entry, which may
- * include multiple pages. Find the initial page structure
- * and the starting offset within the page, and update
- * the *offset and **sgptr values for the next loop. */
+ * include multiple pages. Find the initial page structure
+ * and the starting offset within the page, and update
+ * the *offset and **sgptr values for the next loop.
+ */
cnt = 0;
- while (cnt < buflen) {
+ while (cnt < buflen && sg) {
struct page *page = sg_page(sg) +
((sg->offset + *offset) >> PAGE_SHIFT);
- unsigned int poff =
- (sg->offset + *offset) & (PAGE_SIZE-1);
+ unsigned int poff = (sg->offset + *offset) & (PAGE_SIZE-1);
unsigned int sglen = sg->length - *offset;
if (sglen > buflen - cnt) {
@@ -222,14 +224,15 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer,
}
/* Store the contents of buffer into srb's transfer buffer and set the
- * SCSI residue. */
+ * SCSI residue.
+ */
void usb_stor_set_xfer_buf(unsigned char *buffer,
unsigned int buflen, struct scsi_cmnd *srb)
{
unsigned int offset = 0;
struct scatterlist *sg = NULL;
- usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
+ buflen = usb_stor_access_xfer_buf(buffer, buflen, srb, &sg, &offset,
TO_XFER_BUF);
if (buflen < scsi_bufflen(srb))
scsi_set_resid(srb, scsi_bufflen(srb) - buflen);