diff options
Diffstat (limited to 'drivers/usb/wusbcore')
-rw-r--r-- | drivers/usb/wusbcore/wa-hc.h | 11 | ||||
-rw-r--r-- | drivers/usb/wusbcore/wa-xfer.c | 83 |
2 files changed, 60 insertions, 34 deletions
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h index a2ef84b8397..7510960588d 100644 --- a/drivers/usb/wusbcore/wa-hc.h +++ b/drivers/usb/wusbcore/wa-hc.h @@ -134,8 +134,18 @@ enum wa_quirks { * requests to be concatenated and not sent as separate packets. */ WUSB_QUIRK_ALEREON_HWA_CONCAT_ISOC = 0x01, + /* + * The Alereon HWA can be instructed to not send transfer notifications + * as an optimization. + */ + WUSB_QUIRK_ALEREON_HWA_DISABLE_XFER_NOTIFICATIONS = 0x02, }; +enum wa_vendor_specific_requests { + WA_REQ_ALEREON_DISABLE_XFER_NOTIFICATIONS = 0x4C, + WA_REQ_ALEREON_FEATURE_SET = 0x01, + WA_REQ_ALEREON_FEATURE_CLEAR = 0x00, +}; /** * Instance of a HWA Host Controller * @@ -234,6 +244,7 @@ struct wahc { extern int wa_create(struct wahc *wa, struct usb_interface *iface, kernel_ulong_t); extern void __wa_destroy(struct wahc *wa); +extern int wa_dti_start(struct wahc *wa); void wa_reset_all(struct wahc *wa); diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index cf7c95ceebe..52c7259705e 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -2741,41 +2741,15 @@ out: } /* - * Transfer complete notification - * - * Called from the notif.c code. We get a notification on EP2 saying - * that some endpoint has some transfer result data available. We are - * about to read it. - * - * To speed up things, we always have a URB reading the DTI URB; we - * don't really set it up and start it until the first xfer complete - * notification arrives, which is what we do here. - * - * Follow up in wa_dti_cb(), as that's where the whole state - * machine starts. - * - * So here we just initialize the DTI URB for reading transfer result - * notifications and also the buffer-in URB, for reading buffers. Then - * we just submit the DTI URB. - * - * @wa shall be referenced + * Initialize the DTI URB for reading transfer result notifications and also + * the buffer-in URB, for reading buffers. Then we just submit the DTI URB. */ -void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) +int wa_dti_start(struct wahc *wa) { - int result; - struct device *dev = &wa->usb_iface->dev; - struct wa_notif_xfer *notif_xfer; const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd; + struct device *dev = &wa->usb_iface->dev; + int result = -ENOMEM; - notif_xfer = container_of(notif_hdr, struct wa_notif_xfer, hdr); - BUG_ON(notif_hdr->bNotifyType != WA_NOTIF_TRANSFER); - - if ((0x80 | notif_xfer->bEndpoint) != dti_epd->bEndpointAddress) { - /* FIXME: hardcoded limitation, adapt */ - dev_err(dev, "BUG: DTI ep is %u, not %u (hack me)\n", - notif_xfer->bEndpoint, dti_epd->bEndpointAddress); - goto error; - } if (wa->dti_urb != NULL) /* DTI URB already started */ goto out; @@ -2786,7 +2760,7 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) } usb_fill_bulk_urb( wa->dti_urb, wa->usb_dev, - usb_rcvbulkpipe(wa->usb_dev, 0x80 | notif_xfer->bEndpoint), + usb_rcvbulkpipe(wa->usb_dev, 0x80 | dti_epd->bEndpointAddress), wa->dti_buf, wa->dti_buf_size, wa_dti_cb, wa); @@ -2797,7 +2771,7 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) } usb_fill_bulk_urb( wa->buf_in_urb, wa->usb_dev, - usb_rcvbulkpipe(wa->usb_dev, 0x80 | notif_xfer->bEndpoint), + usb_rcvbulkpipe(wa->usb_dev, 0x80 | dti_epd->bEndpointAddress), NULL, 0, wa_buf_in_cb, wa); result = usb_submit_urb(wa->dti_urb, GFP_KERNEL); if (result < 0) { @@ -2806,7 +2780,7 @@ void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) goto error_dti_urb_submit; } out: - return; + return 0; error_dti_urb_submit: usb_put_urb(wa->buf_in_urb); @@ -2815,6 +2789,47 @@ error_buf_in_urb_alloc: usb_put_urb(wa->dti_urb); wa->dti_urb = NULL; error_dti_urb_alloc: + return result; +} +EXPORT_SYMBOL_GPL(wa_dti_start); +/* + * Transfer complete notification + * + * Called from the notif.c code. We get a notification on EP2 saying + * that some endpoint has some transfer result data available. We are + * about to read it. + * + * To speed up things, we always have a URB reading the DTI URB; we + * don't really set it up and start it until the first xfer complete + * notification arrives, which is what we do here. + * + * Follow up in wa_dti_cb(), as that's where the whole state + * machine starts. + * + * @wa shall be referenced + */ +void wa_handle_notif_xfer(struct wahc *wa, struct wa_notif_hdr *notif_hdr) +{ + struct device *dev = &wa->usb_iface->dev; + struct wa_notif_xfer *notif_xfer; + const struct usb_endpoint_descriptor *dti_epd = wa->dti_epd; + + notif_xfer = container_of(notif_hdr, struct wa_notif_xfer, hdr); + BUG_ON(notif_hdr->bNotifyType != WA_NOTIF_TRANSFER); + + if ((0x80 | notif_xfer->bEndpoint) != dti_epd->bEndpointAddress) { + /* FIXME: hardcoded limitation, adapt */ + dev_err(dev, "BUG: DTI ep is %u, not %u (hack me)\n", + notif_xfer->bEndpoint, dti_epd->bEndpointAddress); + goto error; + } + + /* attempt to start the DTI ep processing. */ + if (wa_dti_start(wa) < 0) + goto error; + + return; + error: wa_reset_all(wa); } |