Skip to content

Commit

Permalink
usb: gadget: storage: fix mass storage gadgets to work with Synopsys UDC
Browse files Browse the repository at this point in the history
The Synopsys USB device controller requires all OUT transfer request
lengths to be aligned to max packet size. The mass storage gadgets do
not meet this requirement for Super Speed. The gadgets already have a
function which performs this alignment for CBW packets, so use it for
data packets too.

The alternative would be to implement bounce buffers in the DWC3
driver, but that could have a significant impact on performance.

This version is based upon a more-correct patch written by Alan
Stern.

Signed-off-by: Paul Zimmerman <paulz@synopsys.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Paul Zimmerman authored and Felipe Balbi committed Oct 13, 2011
1 parent c8933c3 commit fe69676
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 18 deletions.
18 changes: 9 additions & 9 deletions drivers/usb/gadget/f_mass_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -958,9 +958,7 @@ static int do_write(struct fsg_common *common)
* equal to the buffer size, which is divisible by
* the bulk-out maxpacket size.
*/
bh->outreq->length = amount;
bh->bulk_out_intended_length = amount;
bh->outreq->short_not_ok = 1;
set_bulk_out_req_length(common, bh, amount);
if (!start_out_transfer(common, bh))
/* Dunno what to do if common->fsg is NULL */
return -EIO;
Expand Down Expand Up @@ -995,6 +993,11 @@ static int do_write(struct fsg_common *common)
amount = curlun->file_length - file_offset;
}

/* Don't accept excess data. The spec doesn't say
* what to do in this case. We'll ignore the error.
*/
amount = min(amount, bh->bulk_out_intended_length);

/* Don't write a partial block */
amount = round_down(amount, curlun->blksize);
if (amount == 0)
Expand Down Expand Up @@ -1034,7 +1037,7 @@ static int do_write(struct fsg_common *common)

empty_write:
/* Did the host decide to stop early? */
if (bh->outreq->actual != bh->outreq->length) {
if (bh->outreq->actual < bh->bulk_out_intended_length) {
common->short_packet_received = 1;
break;
}
Expand Down Expand Up @@ -1592,7 +1595,7 @@ static int throw_away_data(struct fsg_common *common)
common->next_buffhd_to_drain = bh->next;

/* A short packet or an error ends everything */
if (bh->outreq->actual != bh->outreq->length ||
if (bh->outreq->actual < bh->bulk_out_intended_length ||
bh->outreq->status != 0) {
raise_exception(common,
FSG_STATE_ABORT_BULK_OUT);
Expand All @@ -1612,9 +1615,7 @@ static int throw_away_data(struct fsg_common *common)
* equal to the buffer size, which is divisible by
* the bulk-out maxpacket size.
*/
bh->outreq->length = amount;
bh->bulk_out_intended_length = amount;
bh->outreq->short_not_ok = 1;
set_bulk_out_req_length(common, bh, amount);
if (!start_out_transfer(common, bh))
/* Dunno what to do if common->fsg is NULL */
return -EIO;
Expand Down Expand Up @@ -2289,7 +2290,6 @@ static int get_next_command(struct fsg_common *common)

/* Queue a request to read a Bulk-only CBW */
set_bulk_out_req_length(common, bh, USB_BULK_CB_WRAP_LEN);
bh->outreq->short_not_ok = 1;
if (!start_out_transfer(common, bh))
/* Don't know what to do if common->fsg is NULL */
return -EIO;
Expand Down
18 changes: 9 additions & 9 deletions drivers/usb/gadget/file_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -1335,9 +1335,7 @@ static int do_write(struct fsg_dev *fsg)
* equal to the buffer size, which is divisible by
* the bulk-out maxpacket size.
*/
bh->outreq->length = bh->bulk_out_intended_length =
amount;
bh->outreq->short_not_ok = 1;
set_bulk_out_req_length(fsg, bh, amount);
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
Expand Down Expand Up @@ -1370,6 +1368,11 @@ static int do_write(struct fsg_dev *fsg)
amount = curlun->file_length - file_offset;
}

/* Don't accept excess data. The spec doesn't say
* what to do in this case. We'll ignore the error.
*/
amount = min(amount, bh->bulk_out_intended_length);

/* Don't write a partial block */
amount = round_down(amount, curlun->blksize);
if (amount == 0)
Expand Down Expand Up @@ -1409,7 +1412,7 @@ static int do_write(struct fsg_dev *fsg)

empty_write:
/* Did the host decide to stop early? */
if (bh->outreq->actual != bh->outreq->length) {
if (bh->outreq->actual < bh->bulk_out_intended_length) {
fsg->short_packet_received = 1;
break;
}
Expand Down Expand Up @@ -1953,7 +1956,7 @@ static int throw_away_data(struct fsg_dev *fsg)
fsg->next_buffhd_to_drain = bh->next;

/* A short packet or an error ends everything */
if (bh->outreq->actual != bh->outreq->length ||
if (bh->outreq->actual < bh->bulk_out_intended_length ||
bh->outreq->status != 0) {
raise_exception(fsg, FSG_STATE_ABORT_BULK_OUT);
return -EINTR;
Expand All @@ -1971,9 +1974,7 @@ static int throw_away_data(struct fsg_dev *fsg)
* equal to the buffer size, which is divisible by
* the bulk-out maxpacket size.
*/
bh->outreq->length = bh->bulk_out_intended_length =
amount;
bh->outreq->short_not_ok = 1;
set_bulk_out_req_length(fsg, bh, amount);
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);
fsg->next_buffhd_to_fill = bh->next;
Expand Down Expand Up @@ -2652,7 +2653,6 @@ static int get_next_command(struct fsg_dev *fsg)

/* Queue a request to read a Bulk-only CBW */
set_bulk_out_req_length(fsg, bh, USB_BULK_CB_WRAP_LEN);
bh->outreq->short_not_ok = 1;
start_transfer(fsg, fsg->bulk_out, bh->outreq,
&bh->outreq_busy, &bh->state);

Expand Down

0 comments on commit fe69676

Please sign in to comment.