From 2f98382dcdfe1f0048b447da35f34507ffb514dc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 5 Apr 2011 11:40:54 +0900 Subject: usb: renesas_usbhs: Add Renesas USBHS Gadget This patch add usb gadget code to SuperH USBHS. Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 18 ++++++++++++++++++ drivers/usb/gadget/gadget_chips.h | 9 +++++++++ 2 files changed, 27 insertions(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index bc5123c..4c02b9f 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -260,6 +260,24 @@ config USB_R8A66597 default USB_GADGET select USB_GADGET_SELECTED +config USB_GADGET_RENESAS_USBHS + boolean "Renesas USBHS" + depends on USB_RENESAS_USBHS + select USB_GADGET_DUALSPEED + help + Renesas USBHS is a discrete USB host and peripheral controller + chip that supports both full and high speed USB 2.0 data transfers. + platform is able to configure endpoint (pipe) style + + Say "y" to enable the gadget specific portion of the USBHS driver. + + +config USB_RENESAS_USBHS_UDC + tristate + depends on USB_GADGET_RENESAS_USBHS + default USB_GADGET + select USB_GADGET_SELECTED + config USB_GADGET_PXA27X boolean "PXA 27x" depends on ARCH_PXA && (PXA27x || PXA3xx) diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index e896f635..ec3fd97 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -148,6 +148,12 @@ #define gadget_is_ci13xxx_msm(g) 0 #endif +#ifdef CONFIG_USB_GADGET_RENESAS_USBHS +#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name)) +#else +#define gadget_is_renesas_usbhs(g) 0 +#endif + /** * usb_gadget_controller_number - support bcdDevice id convention * @gadget: the controller being driven @@ -207,6 +213,9 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x27; else if (gadget_is_ci13xxx_msm(gadget)) return 0x28; + else if (gadget_is_renesas_usbhs(gadget)) + return 0x29; + return -ENOENT; } -- cgit v1.1 From 806e8f8fcc27e1753947bd9f059ba2316cf8f92a Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Thu, 24 Mar 2011 12:20:13 +0100 Subject: usb: usb_storage: do not align length of request for CBW to maxp size Mass-storage and file-storage gadgets align the length to maximum-packet-size when preparing the request to receive CBW. This is unnecessary and prevents the controller driver from knowing that a short-packet is expected. It is incorrect to set short_not_ok when preparing the request to receive CBW. CBW will be a short-packet so short_not_ok must not be set. This makes bh->bulk_out_intended_length unnecessary so it is also removed. Signed-off-by: Mian Yousaf Kaukab Acked-by: Michal Nazarewicz Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 24 ++++-------------------- drivers/usb/gadget/file_storage.c | 28 ++++++---------------------- drivers/usb/gadget/storage_common.c | 7 ------- 3 files changed, 10 insertions(+), 49 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 6d8e533..125587a 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -474,20 +474,6 @@ static int exception_in_progress(struct fsg_common *common) return common->state > FSG_STATE_IDLE; } -/* Make bulk-out requests be divisible by the maxpacket size */ -static void set_bulk_out_req_length(struct fsg_common *common, - struct fsg_buffhd *bh, unsigned int length) -{ - unsigned int rem; - - bh->bulk_out_intended_length = length; - rem = length % common->bulk_out_maxpacket; - if (rem > 0) - length += common->bulk_out_maxpacket - rem; - bh->outreq->length = length; -} - - /*-------------------------------------------------------------------------*/ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) @@ -586,9 +572,9 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) struct fsg_buffhd *bh = req->context; dump_msg(common, "bulk-out", req->buf, req->actual); - if (req->status || req->actual != bh->bulk_out_intended_length) + if (req->status || req->actual != req->length) DBG(common, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, bh->bulk_out_intended_length); + req->status, req->actual, req->length); if (req->status == -ECONNRESET) /* Request was cancelled */ usb_ep_fifo_flush(ep); @@ -975,7 +961,6 @@ static int do_write(struct fsg_common *common) * the bulk-out maxpacket size */ bh->outreq->length = amount; - bh->bulk_out_intended_length = amount; bh->outreq->short_not_ok = 1; if (!start_out_transfer(common, bh)) /* Dunno what to do if common->fsg is NULL */ @@ -1652,7 +1637,6 @@ static int throw_away_data(struct fsg_common *common) * the bulk-out maxpacket size. */ bh->outreq->length = amount; - bh->bulk_out_intended_length = amount; bh->outreq->short_not_ok = 1; if (!start_out_transfer(common, bh)) /* Dunno what to do if common->fsg is NULL */ @@ -2322,8 +2306,8 @@ 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; + bh->outreq->length = USB_BULK_CB_WRAP_LEN; + bh->outreq->short_not_ok = 0; if (!start_out_transfer(common, bh)) /* Don't know what to do if common->fsg is NULL */ return -EIO; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a6eacb5..d04e0e6 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -497,19 +497,6 @@ static int exception_in_progress(struct fsg_dev *fsg) return (fsg->state > FSG_STATE_IDLE); } -/* Make bulk-out requests be divisible by the maxpacket size */ -static void set_bulk_out_req_length(struct fsg_dev *fsg, - struct fsg_buffhd *bh, unsigned int length) -{ - unsigned int rem; - - bh->bulk_out_intended_length = length; - rem = length % fsg->bulk_out_maxpacket; - if (rem > 0) - length += fsg->bulk_out_maxpacket - rem; - bh->outreq->length = length; -} - static struct fsg_dev *the_fsg; static struct usb_gadget_driver fsg_driver; @@ -730,10 +717,9 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) struct fsg_buffhd *bh = req->context; dump_msg(fsg, "bulk-out", req->buf, req->actual); - if (req->status || req->actual != bh->bulk_out_intended_length) + if (req->status || req->actual != req->length) DBG(fsg, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, - bh->bulk_out_intended_length); + req->status, req->actual, req->length); if (req->status == -ECONNRESET) // Request was cancelled usb_ep_fifo_flush(ep); @@ -1349,8 +1335,7 @@ static int do_write(struct fsg_dev *fsg) /* amount is always divisible by 512, hence by * the bulk-out maxpacket size */ - bh->outreq->length = bh->bulk_out_intended_length = - amount; + bh->outreq->length = amount; bh->outreq->short_not_ok = 1; start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); @@ -2010,8 +1995,7 @@ static int throw_away_data(struct fsg_dev *fsg) /* amount is always divisible by 512, hence by * the bulk-out maxpacket size */ - bh->outreq->length = bh->bulk_out_intended_length = - amount; + bh->outreq->length = amount; bh->outreq->short_not_ok = 1; start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); @@ -2688,8 +2672,8 @@ 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; + bh->outreq->length = USB_BULK_CB_WRAP_LEN; + bh->outreq->short_not_ok = 0; start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index b015561..3179b8b 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -286,13 +286,6 @@ struct fsg_buffhd { enum fsg_buffer_state state; struct fsg_buffhd *next; - /* - * The NetChip 2280 is faster, and handles some protocol faults - * better, if we don't submit any short bulk-out read requests. - * So we will record the intended request length here. - */ - unsigned int bulk_out_intended_length; - struct usb_request *inreq; int inreq_busy; struct usb_request *outreq; -- cgit v1.1 From ee81b3e086c907a3347b15ef219a24fc8bf900f6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 25 Mar 2011 11:46:27 -0400 Subject: USB: g_file_storage: don't send padding when stall=n This patch (as1455) removes the extra padding sent by g_file_storage and g_mass_storage when the gadget wants to send less data than requested by the host and isn't allowed to halt the bulk-IN endpoint. Although the Bulk-Only Transport specification requires the padding to be present, it isn't truly needed since the transfer will be terminated by a short packet anyway. Furthermore, many existing devices don't bother to send any padding. Signed-off-by: Alan Stern Acked-By: Michal Nazarewicz CC: Roger Quadros Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 54 ++++++++----------------------------- drivers/usb/gadget/file_storage.c | 53 +++++++++--------------------------- 2 files changed, 23 insertions(+), 84 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 125587a..98d6b390 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -1569,37 +1569,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) return rc; } -static int pad_with_zeros(struct fsg_dev *fsg) -{ - struct fsg_buffhd *bh = fsg->common->next_buffhd_to_fill; - u32 nkeep = bh->inreq->length; - u32 nsend; - int rc; - - bh->state = BUF_STATE_EMPTY; /* For the first iteration */ - fsg->common->usb_amount_left = nkeep + fsg->common->residue; - while (fsg->common->usb_amount_left > 0) { - - /* Wait for the next buffer to be free */ - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(fsg->common); - if (rc) - return rc; - } - - nsend = min(fsg->common->usb_amount_left, FSG_BUFLEN); - memset(bh->buf + nkeep, 0, nsend - nkeep); - bh->inreq->length = nsend; - bh->inreq->zero = 0; - start_transfer(fsg, fsg->bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state); - bh = fsg->common->next_buffhd_to_fill = bh->next; - fsg->common->usb_amount_left -= nsend; - nkeep = 0; - } - return 0; -} - static int throw_away_data(struct fsg_common *common) { struct fsg_buffhd *bh; @@ -1686,6 +1655,10 @@ static int finish_reply(struct fsg_common *common) if (common->data_size == 0) { /* Nothing to send */ + /* Don't know what to do if common->fsg is NULL */ + } else if (!fsg_is_set(common)) { + rc = -EIO; + /* If there's no residue, simply send the last buffer */ } else if (common->residue == 0) { bh->inreq->zero = 0; @@ -1694,24 +1667,19 @@ static int finish_reply(struct fsg_common *common) common->next_buffhd_to_fill = bh->next; /* - * For Bulk-only, if we're allowed to stall then send the - * short packet and halt the bulk-in endpoint. If we can't - * stall, pad out the remaining data with 0's. + * For Bulk-only, mark the end of the data with a short + * packet. If we are allowed to stall, halt the bulk-in + * endpoint. (Note: This violates the Bulk-Only Transport + * specification, which requires us to pad the data if we + * don't halt the endpoint. Presumably nobody will mind.) */ - } else if (common->can_stall) { + } else { bh->inreq->zero = 1; if (!start_in_transfer(common, bh)) - /* Don't know what to do if - * common->fsg is NULL */ rc = -EIO; common->next_buffhd_to_fill = bh->next; - if (common->fsg) + if (common->can_stall) rc = halt_bulk_in_endpoint(common->fsg); - } else if (fsg_is_set(common)) { - rc = pad_with_zeros(common->fsg); - } else { - /* Don't know what to do if common->fsg is NULL */ - rc = -EIO; } break; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index d04e0e6..aebfb81 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1932,37 +1932,6 @@ static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) return rc; } -static int pad_with_zeros(struct fsg_dev *fsg) -{ - struct fsg_buffhd *bh = fsg->next_buffhd_to_fill; - u32 nkeep = bh->inreq->length; - u32 nsend; - int rc; - - bh->state = BUF_STATE_EMPTY; // For the first iteration - fsg->usb_amount_left = nkeep + fsg->residue; - while (fsg->usb_amount_left > 0) { - - /* Wait for the next buffer to be free */ - while (bh->state != BUF_STATE_EMPTY) { - rc = sleep_thread(fsg); - if (rc) - return rc; - } - - nsend = min(fsg->usb_amount_left, (u32) mod_data.buflen); - memset(bh->buf + nkeep, 0, nsend - nkeep); - bh->inreq->length = nsend; - bh->inreq->zero = 0; - start_transfer(fsg, fsg->bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state); - bh = fsg->next_buffhd_to_fill = bh->next; - fsg->usb_amount_left -= nsend; - nkeep = 0; - } - return 0; -} - static int throw_away_data(struct fsg_dev *fsg) { struct fsg_buffhd *bh; @@ -2066,18 +2035,20 @@ static int finish_reply(struct fsg_dev *fsg) } } - /* For Bulk-only, if we're allowed to stall then send the - * short packet and halt the bulk-in endpoint. If we can't - * stall, pad out the remaining data with 0's. */ + /* + * For Bulk-only, mark the end of the data with a short + * packet. If we are allowed to stall, halt the bulk-in + * endpoint. (Note: This violates the Bulk-Only Transport + * specification, which requires us to pad the data if we + * don't halt the endpoint. Presumably nobody will mind.) + */ else { - if (mod_data.can_stall) { - bh->inreq->zero = 1; - start_transfer(fsg, fsg->bulk_in, bh->inreq, - &bh->inreq_busy, &bh->state); - fsg->next_buffhd_to_fill = bh->next; + bh->inreq->zero = 1; + start_transfer(fsg, fsg->bulk_in, bh->inreq, + &bh->inreq_busy, &bh->state); + fsg->next_buffhd_to_fill = bh->next; + if (mod_data.can_stall) rc = halt_bulk_in_endpoint(fsg); - } else - rc = pad_with_zeros(fsg); } break; -- cgit v1.1 From 73ee4da994e7b97bd8241e39099cf3dd94675d79 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 5 Apr 2011 18:36:38 +0300 Subject: usb: gadget: f_mass_storage: Fix Bulk-only RESET handling The ep0 request tag was not recorded thus resulting in phase problems while sending status/response in handle_execption() handler. This was resulting in MSC compliance test failures with USBCV tool. With this patch, the Bulk-Only Mass storage RESET request is handled correctly and the MSC compliance tests pass. Signed-off-by: Roger Quadros Acked-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 98d6b390..e9de33d 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -599,6 +599,11 @@ static int fsg_setup(struct usb_function *f, if (!fsg_is_set(fsg->common)) return -EOPNOTSUPP; + ++fsg->common->ep0_req_tag; /* Record arrival of a new request */ + req->context = NULL; + req->length = 0; + dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); + switch (ctrl->bRequest) { case USB_BULK_RESET_REQUEST: -- cgit v1.1 From 3c624d4962a583516acadcbf60a8ca2a48421f5c Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 5 Apr 2011 18:36:39 +0300 Subject: usb: gadget: f_mass_storage: If 'ro'/'cdrom' specified, open file as read-only If we don't need Write access then attempt to open backing file in Read Only mode instead of bailing out too soon. Signed-off-by: Roger Quadros Acked-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index e9de33d..7d95a2c 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2757,6 +2757,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { curlun->cdrom = !!lcfg->cdrom; curlun->ro = lcfg->cdrom || lcfg->ro; + curlun->initially_ro = curlun->ro; curlun->removable = lcfg->removable; curlun->dev.release = fsg_lun_release; curlun->dev.parent = &gadget->dev; -- cgit v1.1 From 74d1dc8d8d13fef55c33b49f06ab84eeebf967c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Weiping=20Pan=28=E6=BD=98=E5=8D=AB=E5=B9=B3=29?= Date: Mon, 11 Apr 2011 18:16:15 +0800 Subject: usb: fix a typo in a comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit replace tranmitted with transmitted. Signed-off-by: Weiping Pan(潘卫平) Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_qe_udc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/fsl_qe_udc.h b/drivers/usb/gadget/fsl_qe_udc.h index e35e24f..1da5fb0 100644 --- a/drivers/usb/gadget/fsl_qe_udc.h +++ b/drivers/usb/gadget/fsl_qe_udc.h @@ -207,7 +207,7 @@ struct qe_frame{ /* Frame status field */ /* Receive side */ -#define FRAME_OK 0x00000000 /* Frame tranmitted or received OK */ +#define FRAME_OK 0x00000000 /* Frame transmitted or received OK */ #define FRAME_ERROR 0x80000000 /* Error occurred on frame */ #define START_FRAME_LOST 0x40000000 /* START_FRAME_LOST */ #define END_FRAME_LOST 0x20000000 /* END_FRAME_LOST */ -- cgit v1.1 From db8fa2852ed5b46c05148db87be135300f17b8ce Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Thu, 14 Apr 2011 00:37:00 +0200 Subject: usb: gadget: storage_common: use kstrto*() This commit replaces the usage of strict_strtoul() (which became deprecated after commit 33ee3b2e) with kstrtouint(). Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/storage_common.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 3179b8b..86fcebd 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -704,10 +704,11 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, ssize_t rc = count; struct fsg_lun *curlun = fsg_lun_from_dev(dev); struct rw_semaphore *filesem = dev_get_drvdata(dev); - unsigned long ro; + unsigned ro; - if (strict_strtoul(buf, 2, &ro)) - return -EINVAL; + rc = kstrtouint(buf, 2, &ro); + if (rc) + return rc; /* * Allow the write-enable status to change only while the @@ -731,10 +732,12 @@ static ssize_t fsg_store_nofua(struct device *dev, const char *buf, size_t count) { struct fsg_lun *curlun = fsg_lun_from_dev(dev); - unsigned long nofua; + unsigned nofua; + int ret; - if (strict_strtoul(buf, 2, &nofua)) - return -EINVAL; + ret = kstrtouint(buf, 2, &nofua); + if (ret) + return ret; /* Sync data when switching from async mode to sync */ if (!nofua && curlun->nofua) -- cgit v1.1 From 98346f7db014614a4814eb60639f651f8bbc591d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 14 Apr 2011 13:42:46 -0700 Subject: Revert "usb: usb_storage: do not align length of request for CBW to maxp size" This reverts commit 806e8f8fcc27e1753947bd9f059ba2316cf8f92a. To quote Alan Stern: The necessity for this patch has been under discussion. It turns out the UDC that Mian has been working on and Felipe's UDC have contradictory requirements. Mian's UDC driver wants a bulk-OUT transfer length to be shorter than the maxpacket size if a short packet is expected, whereas Felipe's UDC hardware always needs bulk-OUT transfer lengths to be evenly divisible by the maxpacket size. Mian has agreed to go back over the driver to resolve this conflict. This means we probably will not want this patch after all. (In fact, we may ultimately decide to change the gadget framework to require that bulk-OUT transfer lengths _always_ be divisible by the maxpacket size -- only the g_file_storage and g_mass_storage gadgets would need to be changed.) Cc: Mian Yousaf Kaukab Cc: Michal Nazarewicz Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_mass_storage.c | 24 ++++++++++++++++++++---- drivers/usb/gadget/file_storage.c | 28 ++++++++++++++++++++++------ drivers/usb/gadget/storage_common.c | 7 +++++++ 3 files changed, 49 insertions(+), 10 deletions(-) (limited to 'drivers/usb/gadget') diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 7d95a2c..01ae27b 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -474,6 +474,20 @@ static int exception_in_progress(struct fsg_common *common) return common->state > FSG_STATE_IDLE; } +/* Make bulk-out requests be divisible by the maxpacket size */ +static void set_bulk_out_req_length(struct fsg_common *common, + struct fsg_buffhd *bh, unsigned int length) +{ + unsigned int rem; + + bh->bulk_out_intended_length = length; + rem = length % common->bulk_out_maxpacket; + if (rem > 0) + length += common->bulk_out_maxpacket - rem; + bh->outreq->length = length; +} + + /*-------------------------------------------------------------------------*/ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) @@ -572,9 +586,9 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) struct fsg_buffhd *bh = req->context; dump_msg(common, "bulk-out", req->buf, req->actual); - if (req->status || req->actual != req->length) + if (req->status || req->actual != bh->bulk_out_intended_length) DBG(common, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, req->length); + req->status, req->actual, bh->bulk_out_intended_length); if (req->status == -ECONNRESET) /* Request was cancelled */ usb_ep_fifo_flush(ep); @@ -966,6 +980,7 @@ static int do_write(struct fsg_common *common) * the bulk-out maxpacket size */ bh->outreq->length = amount; + bh->bulk_out_intended_length = amount; bh->outreq->short_not_ok = 1; if (!start_out_transfer(common, bh)) /* Dunno what to do if common->fsg is NULL */ @@ -1611,6 +1626,7 @@ static int throw_away_data(struct fsg_common *common) * the bulk-out maxpacket size. */ bh->outreq->length = amount; + bh->bulk_out_intended_length = amount; bh->outreq->short_not_ok = 1; if (!start_out_transfer(common, bh)) /* Dunno what to do if common->fsg is NULL */ @@ -2279,8 +2295,8 @@ static int get_next_command(struct fsg_common *common) } /* Queue a request to read a Bulk-only CBW */ - bh->outreq->length = USB_BULK_CB_WRAP_LEN; - bh->outreq->short_not_ok = 0; + 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; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index aebfb81..fcfc77c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -497,6 +497,19 @@ static int exception_in_progress(struct fsg_dev *fsg) return (fsg->state > FSG_STATE_IDLE); } +/* Make bulk-out requests be divisible by the maxpacket size */ +static void set_bulk_out_req_length(struct fsg_dev *fsg, + struct fsg_buffhd *bh, unsigned int length) +{ + unsigned int rem; + + bh->bulk_out_intended_length = length; + rem = length % fsg->bulk_out_maxpacket; + if (rem > 0) + length += fsg->bulk_out_maxpacket - rem; + bh->outreq->length = length; +} + static struct fsg_dev *the_fsg; static struct usb_gadget_driver fsg_driver; @@ -717,9 +730,10 @@ static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) struct fsg_buffhd *bh = req->context; dump_msg(fsg, "bulk-out", req->buf, req->actual); - if (req->status || req->actual != req->length) + if (req->status || req->actual != bh->bulk_out_intended_length) DBG(fsg, "%s --> %d, %u/%u\n", __func__, - req->status, req->actual, req->length); + req->status, req->actual, + bh->bulk_out_intended_length); if (req->status == -ECONNRESET) // Request was cancelled usb_ep_fifo_flush(ep); @@ -1335,7 +1349,8 @@ static int do_write(struct fsg_dev *fsg) /* amount is always divisible by 512, hence by * the bulk-out maxpacket size */ - bh->outreq->length = amount; + bh->outreq->length = bh->bulk_out_intended_length = + amount; bh->outreq->short_not_ok = 1; start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); @@ -1964,7 +1979,8 @@ static int throw_away_data(struct fsg_dev *fsg) /* amount is always divisible by 512, hence by * the bulk-out maxpacket size */ - bh->outreq->length = amount; + bh->outreq->length = bh->bulk_out_intended_length = + amount; bh->outreq->short_not_ok = 1; start_transfer(fsg, fsg->bulk_out, bh->outreq, &bh->outreq_busy, &bh->state); @@ -2643,8 +2659,8 @@ static int get_next_command(struct fsg_dev *fsg) } /* Queue a request to read a Bulk-only CBW */ - bh->outreq->length = USB_BULK_CB_WRAP_LEN; - bh->outreq->short_not_ok = 0; + 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); diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 86fcebd..109635a 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -286,6 +286,13 @@ struct fsg_buffhd { enum fsg_buffer_state state; struct fsg_buffhd *next; + /* + * The NetChip 2280 is faster, and handles some protocol faults + * better, if we don't submit any short bulk-out read requests. + * So we will record the intended request length here. + */ + unsigned int bulk_out_intended_length; + struct usb_request *inreq; int inreq_busy; struct usb_request *outreq; -- cgit v1.1