From 939f325f4a0fb7eb189268a4593e427d3a075514 Mon Sep 17 00:00:00 2001 From: "kuninori.morimoto.gx@renesas.com" Date: Mon, 25 Jul 2011 00:39:30 -0700 Subject: usb: add usb_endpoint_maxp() macro Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ch9.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 0fd3fbdd8283..e809deabf503 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -34,6 +34,7 @@ #define __LINUX_USB_CH9_H #include /* __u8 etc */ +#include /* le16_to_cpu */ /*-------------------------------------------------------------------------*/ @@ -570,6 +571,17 @@ static inline int usb_endpoint_is_isoc_out( return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd); } +/** + * usb_endpoint_maxp - get endpoint's max packet size + * @epd: endpoint to be checked + * + * Returns @epd's max packet + */ +static inline int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) +{ + return le16_to_cpu(epd->wMaxPacketSize); +} + /*-------------------------------------------------------------------------*/ /* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ -- cgit v1.2.3 From da6819dbffb34861b79d91c05c4eeb37a3792433 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 19 Aug 2011 18:10:56 +0300 Subject: usb: ch9: add function defines from ch9, USB 3.0 spec not to confuse with Table 9-7 in USB 2.0 spec Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ch9.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index e809deabf503..1ded281eff88 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -144,6 +144,11 @@ #define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */ #define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00 +/* + * Suspend Options, Table 9-7 USB 3.0 spec + */ +#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) +#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ -- cgit v1.2.3 From 29cc88979a8818cd8c5019426e945aed118b400e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 23 Aug 2011 03:12:03 -0700 Subject: USB: use usb_endpoint_maxp() instead of le16_to_cpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now ${LINUX}/drivers/usb/* can use usb_endpoint_maxp(desc) to get maximum packet size instead of le16_to_cpu(desc->wMaxPacketSize). This patch fix it up Cc: Armin Fuerst Cc: Pavel Machek Cc: Johannes Erdfelt Cc: Vojtech Pavlik Cc: Oliver Neukum Cc: David Kubicek Cc: Johan Hovold Cc: Brad Hards Acked-by: Felipe Balbi Cc: Sebastian Andrzej Siewior Cc: Thomas Dahlmann Cc: David Brownell Cc: David Lopo Cc: Alan Stern Cc: Michal Nazarewicz Cc: Xie Xiaobo Cc: Li Yang Cc: Jiang Bo Cc: Yuan-hsin Chen Cc: Darius Augulis Cc: Xiaochen Shen Cc: Yoshihiro Shimoda Cc: OKI SEMICONDUCTOR, Cc: Robert Jarzmik Cc: Ben Dooks Cc: Thomas Abraham Cc: Herbert Pötzl Cc: Arnaud Patard Cc: Roman Weissgaerber Acked-by: Sarah Sharp Cc: Tony Olech Cc: Florian Floe Echtler Cc: Christian Lucht Cc: Juergen Stuber Cc: Georges Toth Cc: Bill Ryder Cc: Kuba Ober Cc: Inaky Perez-Gonzalez Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 +++--- drivers/usb/class/cdc-wdm.c | 2 +- drivers/usb/class/usbtmc.c | 5 ++--- drivers/usb/core/config.c | 8 ++++---- drivers/usb/core/devices.c | 4 ++-- drivers/usb/core/endpoint.c | 2 +- drivers/usb/core/hub.c | 2 +- drivers/usb/core/urb.c | 2 +- drivers/usb/dwc3/gadget.c | 3 +-- drivers/usb/gadget/amd5536udc.c | 2 +- drivers/usb/gadget/at91_udc.c | 2 +- drivers/usb/gadget/atmel_usba_udc.c | 4 ++-- drivers/usb/gadget/ci13xxx_udc.c | 2 +- drivers/usb/gadget/composite.c | 2 +- drivers/usb/gadget/dummy_hcd.c | 4 ++-- drivers/usb/gadget/epautoconf.c | 2 +- drivers/usb/gadget/f_mass_storage.c | 3 +-- drivers/usb/gadget/file_storage.c | 2 +- drivers/usb/gadget/fsl_qe_udc.c | 2 +- drivers/usb/gadget/fsl_udc_core.c | 2 +- drivers/usb/gadget/fusb300_udc.c | 2 +- drivers/usb/gadget/imx_udc.c | 2 +- drivers/usb/gadget/langwell_udc.c | 2 +- drivers/usb/gadget/m66592-udc.c | 4 ++-- drivers/usb/gadget/mv_udc_core.c | 2 +- drivers/usb/gadget/net2272.c | 2 +- drivers/usb/gadget/net2280.c | 4 ++-- drivers/usb/gadget/omap_udc.c | 7 +++---- drivers/usb/gadget/pch_udc.c | 6 +++--- drivers/usb/gadget/pxa25x_udc.c | 14 ++++++-------- drivers/usb/gadget/pxa27x_udc.c | 2 +- drivers/usb/gadget/r8a66597-udc.c | 4 ++-- drivers/usb/gadget/s3c-hsotg.c | 2 +- drivers/usb/gadget/s3c-hsudc.c | 6 +++--- drivers/usb/gadget/s3c2410_udc.c | 2 +- drivers/usb/host/ohci-q.c | 4 ++-- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/uhci-q.c | 6 +++--- drivers/usb/host/xhci-mem.c | 10 +++++----- drivers/usb/host/xhci-ring.c | 8 ++++---- drivers/usb/host/xhci.c | 2 +- drivers/usb/misc/adutux.c | 14 +++++++------- drivers/usb/misc/ftdi-elan.c | 2 +- drivers/usb/misc/idmouse.c | 2 +- drivers/usb/misc/iowarrior.c | 2 +- drivers/usb/misc/ldusb.c | 4 ++-- drivers/usb/misc/legousbtower.c | 4 ++-- drivers/usb/misc/usblcd.c | 2 +- drivers/usb/misc/usbtest.c | 6 +++--- drivers/usb/musb/musb_gadget.c | 2 +- drivers/usb/musb/musb_host.c | 2 +- drivers/usb/serial/ftdi_sio.c | 2 +- drivers/usb/serial/io_edgeport.c | 4 ++-- drivers/usb/serial/opticon.c | 2 +- drivers/usb/serial/symbolserial.c | 2 +- drivers/usb/serial/usb-serial.c | 8 ++++---- drivers/usb/usb-skeleton.c | 2 +- drivers/usb/wusbcore/wa-hc.c | 2 +- include/linux/usb.h | 2 +- 59 files changed, 106 insertions(+), 112 deletions(-) (limited to 'include') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index dac7676ce21b..f69a1854a59c 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1058,11 +1058,11 @@ made_compressed_probe: goto alloc_fail; } - ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); - readsize = le16_to_cpu(epread->wMaxPacketSize) * + ctrlsize = usb_endpoint_maxp(epctrl); + readsize = usb_endpoint_maxp(epread) * (quirks == SINGLE_RX_URB ? 1 : 2); acm->combined_interfaces = combined_interfaces; - acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; + acm->writesize = usb_endpoint_maxp(epwrite) * 20; acm->control = control_interface; acm->data = data_interface; acm->minor = minor; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 2b9ff518b509..1d26a7135dd9 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -682,7 +682,7 @@ next_desc: if (!ep || !usb_endpoint_is_int_in(ep)) goto err; - desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize); + desc->wMaxPacketSize = usb_endpoint_maxp(ep); desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0; desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 3f94ac34dce3..12cf5e7395a8 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -186,8 +186,7 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data) for (n = 0; n < current_setting->desc.bNumEndpoints; n++) if (current_setting->endpoint[n].desc.bEndpointAddress == data->bulk_in) - max_size = le16_to_cpu(current_setting->endpoint[n]. - desc.wMaxPacketSize); + max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc); if (max_size == 0) { dev_err(dev, "Couldn't get wMaxPacketSize\n"); @@ -636,7 +635,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data) for (n = 0; n < current_setting->desc.bNumEndpoints; n++) { desc = ¤t_setting->endpoint[n].desc; if (desc->bEndpointAddress == data->bulk_in) - max_size = le16_to_cpu(desc->wMaxPacketSize); + max_size = usb_endpoint_maxp(desc); } if (max_size == 0) { diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 26678cadfb21..9d5e07af55be 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -124,9 +124,9 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, if (usb_endpoint_xfer_isoc(&ep->desc)) max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) * - le16_to_cpu(ep->desc.wMaxPacketSize); + usb_endpoint_maxp(&ep->desc); else if (usb_endpoint_xfer_int(&ep->desc)) - max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) * + max_tx = usb_endpoint_maxp(&ep->desc) * (desc->bMaxBurst + 1); else max_tx = 999999; @@ -241,7 +241,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, cfgno, inum, asnum, d->bEndpointAddress); endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT; endpoint->desc.bInterval = 1; - if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8) + if (usb_endpoint_maxp(&endpoint->desc) > 8) endpoint->desc.wMaxPacketSize = cpu_to_le16(8); } @@ -254,7 +254,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum, && usb_endpoint_xfer_bulk(d)) { unsigned maxp; - maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff; + maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff; if (maxp != 512) dev_warn(ddev, "config %d interface %d altsetting %d " "bulk endpoint 0x%X has invalid maxpacket %d\n", diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 0149c0976e9c..d95696584762 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -190,7 +190,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, dir = usb_endpoint_dir_in(desc) ? 'I' : 'O'; if (speed == USB_SPEED_HIGH) { - switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) { + switch (usb_endpoint_maxp(desc) & (0x03 << 11)) { case 1 << 11: bandwidth = 2; break; case 2 << 11: @@ -240,7 +240,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, start += sprintf(start, format_endpt, desc->bEndpointAddress, dir, desc->bmAttributes, type, - (le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) * + (usb_endpoint_maxp(desc) & 0x07ff) * bandwidth, interval, unit); return start; diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index df502a98d0df..db7fe50c23d4 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -56,7 +56,7 @@ static ssize_t show_ep_wMaxPacketSize(struct device *dev, { struct ep_device *ep = to_ep_device(dev); return sprintf(buf, "%04x\n", - le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff); + usb_endpoint_maxp(ep->desc) & 0x07ff); } static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 99fff6be3641..338f91ff54cb 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3018,7 +3018,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, i = 512; else i = udev->descriptor.bMaxPacketSize0; - if (le16_to_cpu(udev->ep0.desc.wMaxPacketSize) != i) { + if (usb_endpoint_maxp(&udev->ep0.desc) != i) { if (udev->speed == USB_SPEED_LOW || !(i == 8 || i == 16 || i == 32 || i == 64)) { dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i); diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index ae334b067c13..909625b91eb3 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -350,7 +350,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) dev->state < USB_STATE_CONFIGURED) return -ENODEV; - max = le16_to_cpu(ep->desc.wMaxPacketSize); + max = usb_endpoint_maxp(&ep->desc); if (max <= 0) { dev_dbg(&dev->dev, "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index de5f0afa890a..cebaef720cd4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -254,8 +254,7 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, memset(¶ms, 0x00, sizeof(params)); params.param0.depcfg.ep_type = usb_endpoint_type(desc); - params.param0.depcfg.max_packet_size = - le16_to_cpu(desc->wMaxPacketSize); + params.param0.depcfg.max_packet_size = usb_endpoint_maxp(desc); params.param1.depcfg.xfer_complete_enable = true; params.param1.depcfg.xfer_not_ready_enable = true; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 70f2b376c86d..d65d8392be75 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -354,7 +354,7 @@ udc_ep_enable(struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc) writel(tmp, &dev->ep[ep->num].regs->ctl); /* set max packet size */ - maxpacket = le16_to_cpu(desc->wMaxPacketSize); + maxpacket = usb_endpoint_maxp(desc); tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt); tmp = AMD_ADDBITS(tmp, maxpacket, UDC_EP_MAX_PKT_SIZE); ep->ep.maxpacket = maxpacket; diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index ddb118a76807..d01fa5badd66 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -487,7 +487,7 @@ static int at91_ep_enable(struct usb_ep *_ep, || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT - || (maxpacket = le16_to_cpu(desc->wMaxPacketSize)) == 0 + || (maxpacket = usb_endpoint_maxp(desc)) == 0 || maxpacket > ep->maxpacket) { DBG("bad ep or descriptor\n"); return -EINVAL; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 5b1665eb1bef..722c468e9b3c 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -527,7 +527,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) DBG(DBG_GADGET, "%s: ep_enable: desc=%p\n", ep->ep.name, desc); - maxpacket = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff; + maxpacket = usb_endpoint_maxp(desc) & 0x7ff; if (((desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) != ep->index) || ep->index == 0 @@ -571,7 +571,7 @@ usba_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) * Bits 11:12 specify number of _additional_ * transactions per microframe. */ - nr_trans = ((le16_to_cpu(desc->wMaxPacketSize) >> 11) & 3) + 1; + nr_trans = ((usb_endpoint_maxp(desc) >> 11) & 3) + 1; if (nr_trans > 3) return -EINVAL; diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index 1265a8502ea0..83428f56253b 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2101,7 +2101,7 @@ static int ep_enable(struct usb_ep *ep, mEp->num = usb_endpoint_num(desc); mEp->type = usb_endpoint_type(desc); - mEp->ep.maxpacket = __constant_le16_to_cpu(desc->wMaxPacketSize); + mEp->ep.maxpacket = usb_endpoint_maxp(desc); dbg_event(_usb_addr(mEp), "ENABLE", 0); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index aef47414f5d5..8065464523b1 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -164,7 +164,7 @@ int config_ep_by_speed(struct usb_gadget *g, ep_found: /* commit results */ - _ep->maxpacket = le16_to_cpu(chosen_desc->wMaxPacketSize); + _ep->maxpacket = usb_endpoint_maxp(chosen_desc); _ep->desc = chosen_desc; _ep->comp_desc = NULL; _ep->maxburst = 0; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index e755a9d267fc..7b06d39d6203 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -439,7 +439,7 @@ dummy_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) * maximum packet size. * For SS devices the wMaxPacketSize is limited by 1024. */ - max = le16_to_cpu(desc->wMaxPacketSize) & 0x7ff; + max = usb_endpoint_maxp(desc) & 0x7ff; /* drivers must not request bad settings, since lower levels * (hardware or its drivers) may not check. some endpoints @@ -1277,7 +1277,7 @@ static int periodic_bytes (struct dummy *dum, struct dummy_ep *ep) int tmp; /* high bandwidth mode */ - tmp = le16_to_cpu(ep->desc->wMaxPacketSize); + tmp = usb_endpoint_maxp(ep->desc); tmp = (tmp >> 11) & 0x03; tmp *= 8 /* applies to entire frame */; limit += limit * tmp; diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 7a7e6b7e1fd6..cdca7ebb7b48 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -158,7 +158,7 @@ ep_matches ( * where it's an output parameter representing the full speed limit. * the usb spec fixes high speed bulk maxpacket at 512 bytes. */ - max = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); + max = 0x7ff & usb_endpoint_maxp(desc); switch (type) { case USB_ENDPOINT_XFER_INT: /* INT: limit 64 bytes full speed, 1024 high/super speed */ diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 5b9339582007..4ce3decda1db 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2401,8 +2401,7 @@ reset: goto reset; fsg->bulk_out->driver_data = common; fsg->bulk_out_enabled = 1; - common->bulk_out_maxpacket = - le16_to_cpu(fsg->bulk_out->desc->wMaxPacketSize); + common->bulk_out_maxpacket = usb_endpoint_maxp(fsg->bulk_out->desc); clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); /* Allocate the requests */ diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 639e14a2fd15..39ece40a045f 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -2801,7 +2801,7 @@ reset: if ((rc = enable_endpoint(fsg, fsg->bulk_out, d)) != 0) goto reset; fsg->bulk_out_enabled = 1; - fsg->bulk_out_maxpacket = le16_to_cpu(d->wMaxPacketSize); + fsg->bulk_out_maxpacket = usb_endpoint_maxp(d); clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); if (transport_is_cbi()) { diff --git a/drivers/usb/gadget/fsl_qe_udc.c b/drivers/usb/gadget/fsl_qe_udc.c index 3bf872e1ad39..2a03e4de11c1 100644 --- a/drivers/usb/gadget/fsl_qe_udc.c +++ b/drivers/usb/gadget/fsl_qe_udc.c @@ -540,7 +540,7 @@ static int qe_ep_init(struct qe_udc *udc, int reval = 0; u16 max = 0; - max = le16_to_cpu(desc->wMaxPacketSize); + max = usb_endpoint_maxp(desc); /* check the max package size validate for this endpoint */ /* Refer to USB2.0 spec table 9-13, diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index de24a4233c25..d6993507165b 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -559,7 +559,7 @@ static int fsl_ep_enable(struct usb_ep *_ep, if (!udc->driver || (udc->gadget.speed == USB_SPEED_UNKNOWN)) return -ESHUTDOWN; - max = le16_to_cpu(desc->wMaxPacketSize); + max = usb_endpoint_maxp(desc); /* Disable automatic zlp generation. Driver is responsible to indicate * explicitly through req->req.zero. This is needed to enable multi-td diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index 4ec888f90002..d9ee6c37a6c1 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -220,7 +220,7 @@ static int config_ep(struct fusb300_ep *ep, info.type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; info.dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0; - info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + info.maxpacket = usb_endpoint_maxp(desc); info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; if ((info.type == USB_ENDPOINT_XFER_INT) || diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 692fd9b2248b..bf08bfcd90b8 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -689,7 +689,7 @@ static int imx_ep_enable(struct usb_ep *usb_ep, return -EINVAL; } - if (imx_ep->fifosize < le16_to_cpu(desc->wMaxPacketSize)) { + if (imx_ep->fifosize < usb_endpoint_maxp(desc)) { D_ERR(imx_usb->dev, "<%s> bad %s maxpacket\n", __func__, usb_ep->name); return -ERANGE; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index a06e2c27b435..5bf9942eb454 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -283,7 +283,7 @@ static int langwell_ep_enable(struct usb_ep *_ep, if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - max = le16_to_cpu(desc->wMaxPacketSize); + max = usb_endpoint_maxp(desc); /* * disable HW zero length termination select diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index 491f825ed5c9..5e597c3c44f3 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -370,7 +370,7 @@ static void m66592_ep_setting(struct m66592 *m66592, struct m66592_ep *ep, ep->pipectr = get_pipectr_addr(pipenum); ep->pipenum = pipenum; - ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + ep->ep.maxpacket = usb_endpoint_maxp(desc); m66592->pipenum2ep[pipenum] = ep; m66592->epaddr2ep[desc->bEndpointAddress&USB_ENDPOINT_NUMBER_MASK] = ep; INIT_LIST_HEAD(&ep->queue); @@ -447,7 +447,7 @@ static int alloc_pipe_config(struct m66592_ep *ep, ep->type = info.type; info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + info.maxpacket = usb_endpoint_maxp(desc); info.interval = desc->bInterval; if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) info.dir_in = 1; diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index ce1ac2bcb314..263dec40af32 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -493,7 +493,7 @@ static int mv_ep_enable(struct usb_ep *_ep, return -ESHUTDOWN; direction = ep_dir(ep); - max = le16_to_cpu(desc->wMaxPacketSize); + max = usb_endpoint_maxp(desc); /* * disable HW zero length termination select diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index ab98ea926a11..6fef1c02448e 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -204,7 +204,7 @@ net2272_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; + max = usb_endpoint_maxp(desc) & 0x1fff; spin_lock_irqsave(&dev->lock, flags); _ep->maxpacket = max & 0x7fff; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3dd40b4e675c..8d3673fadfe1 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -169,7 +169,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) return -EDOM; /* sanity check ep-e/ep-f since their fifos are small */ - max = le16_to_cpu (desc->wMaxPacketSize) & 0x1fff; + max = usb_endpoint_maxp (desc) & 0x1fff; if (ep->num > 4 && max > 64) return -ERANGE; @@ -1640,7 +1640,7 @@ show_queues (struct device *_dev, struct device_attribute *attr, char *buf) default: val = "iso"; break; }; val; }), - le16_to_cpu (d->wMaxPacketSize) & 0x1fff, + usb_endpoint_maxp (d) & 0x1fff, ep->dma ? "dma" : "pio", ep->fifo_size ); } else /* ep0 should only have one transfer queued */ diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 740c7daed279..b7a7799ddd4f 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -166,15 +166,14 @@ static int omap_ep_enable(struct usb_ep *_ep, if (!_ep || !desc || ep->desc || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress - || ep->maxpacket < le16_to_cpu - (desc->wMaxPacketSize)) { + || ep->maxpacket < usb_endpoint_maxp(desc)) { DBG("%s, bad ep or descriptor\n", __func__); return -EINVAL; } - maxp = le16_to_cpu (desc->wMaxPacketSize); + maxp = usb_endpoint_maxp(desc); if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK && maxp != ep->maxpacket) - || le16_to_cpu(desc->wMaxPacketSize) > ep->maxpacket + || usb_endpoint_maxp(desc) > ep->maxpacket || !desc->wMaxPacketSize) { DBG("%s, bad %s maxpacket\n", __func__, _ep->name); return -ERANGE; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index f96615ab6b77..b69ae3eec687 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -947,7 +947,7 @@ static void pch_udc_ep_enable(struct pch_udc_ep *ep, else buff_size = UDC_EPOUT_BUFF_SIZE; pch_udc_ep_set_bufsz(ep, buff_size, ep->in); - pch_udc_ep_set_maxpkt(ep, le16_to_cpu(desc->wMaxPacketSize)); + pch_udc_ep_set_maxpkt(ep, usb_endpoint_maxp(desc)); pch_udc_ep_set_nak(ep); pch_udc_ep_fifo_flush(ep, ep->in); /* Configure the endpoint */ @@ -957,7 +957,7 @@ static void pch_udc_ep_enable(struct pch_udc_ep *ep, (cfg->cur_cfg << UDC_CSR_NE_CFG_SHIFT) | (cfg->cur_intf << UDC_CSR_NE_INTF_SHIFT) | (cfg->cur_alt << UDC_CSR_NE_ALT_SHIFT) | - le16_to_cpu(desc->wMaxPacketSize) << UDC_CSR_NE_MAX_PKT_SHIFT; + usb_endpoint_maxp(desc) << UDC_CSR_NE_MAX_PKT_SHIFT; if (ep->in) pch_udc_write_csr(ep->dev, val, UDC_EPIN_IDX(ep->num)); @@ -1466,7 +1466,7 @@ static int pch_udc_pcd_ep_enable(struct usb_ep *usbep, ep->desc = desc; ep->halted = 0; pch_udc_ep_enable(ep, &ep->dev->cfg_data, desc); - ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + ep->ep.maxpacket = usb_endpoint_maxp(desc); pch_udc_enable_ep_interrupts(ep->dev, PCH_UDC_EPINT(ep->in, ep->num)); spin_unlock_irqrestore(&dev->lock, iflags); return 0; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index e4e59b4de25d..7862465291d1 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -232,8 +232,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, if (!_ep || !desc || ep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || ep->bEndpointAddress != desc->bEndpointAddress - || ep->fifo_size < le16_to_cpu - (desc->wMaxPacketSize)) { + || ep->fifo_size < usb_endpoint_maxp (desc)) { DMSG("%s, bad ep or descriptor\n", __func__); return -EINVAL; } @@ -248,7 +247,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, /* hardware _could_ do smaller, but driver doesn't */ if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu (desc->wMaxPacketSize) + && usb_endpoint_maxp (desc) != BULK_FIFO_SIZE) || !desc->wMaxPacketSize) { DMSG("%s, bad %s maxpacket\n", __func__, _ep->name); @@ -264,7 +263,7 @@ static int pxa25x_ep_enable (struct usb_ep *_ep, ep->desc = desc; ep->stopped = 0; ep->pio_irqs = 0; - ep->ep.maxpacket = le16_to_cpu (desc->wMaxPacketSize); + ep->ep.maxpacket = usb_endpoint_maxp (desc); /* flush fifo (mostly for OUT buffers) */ pxa25x_ep_fifo_flush (_ep); @@ -401,7 +400,7 @@ write_fifo (struct pxa25x_ep *ep, struct pxa25x_request *req) { unsigned max; - max = le16_to_cpu(ep->desc->wMaxPacketSize); + max = usb_endpoint_maxp(ep->desc); do { unsigned count; int is_last, is_short; @@ -671,8 +670,7 @@ pxa25x_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) * we can report per-packet status. that also helps with dma. */ if (unlikely (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC - && req->req.length > le16_to_cpu - (ep->desc->wMaxPacketSize))) + && req->req.length > usb_endpoint_maxp (ep->desc))) return -EMSGSIZE; DBG(DBG_NOISY, "%s queue req %p, len %d buf %p\n", @@ -1105,7 +1103,7 @@ udc_seq_show(struct seq_file *m, void *_d) tmp = *dev->ep [i].reg_udccs; seq_printf(m, "%s max %d %s udccs %02x irqs %lu\n", - ep->ep.name, le16_to_cpu(desc->wMaxPacketSize), + ep->ep.name, usb_endpoint_maxp(desc), "pio", tmp, ep->pio_irqs); /* TODO translate all five groups of udccs bits! */ diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 85b68c75dc9d..d21455f457e2 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1439,7 +1439,7 @@ static int pxa_ep_enable(struct usb_ep *_ep, return -EINVAL; } - if (ep->fifo_size < le16_to_cpu(desc->wMaxPacketSize)) { + if (ep->fifo_size < usb_endpoint_maxp(desc)) { ep_err(ep, "bad maxpacket\n"); return -ERANGE; } diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 50991e5bd5e8..61d0c65802e8 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -341,7 +341,7 @@ static void r8a66597_ep_setting(struct r8a66597 *r8a66597, ep->pipectr = get_pipectr_addr(pipenum); ep->pipenum = pipenum; - ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + ep->ep.maxpacket = usb_endpoint_maxp(desc); r8a66597->pipenum2ep[pipenum] = ep; r8a66597->epaddr2ep[desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK] = ep; @@ -420,7 +420,7 @@ static int alloc_pipe_config(struct r8a66597_ep *ep, ep->type = info.type; info.epnum = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - info.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + info.maxpacket = usb_endpoint_maxp(desc); info.interval = desc->bInterval; if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) info.dir_in = 1; diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 8bdee67ce09a..39b134dec94c 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2297,7 +2297,7 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, return -EINVAL; } - mps = le16_to_cpu(desc->wMaxPacketSize); + mps = usb_endpoint_maxp(desc); /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 3e96cc5bb77f..25829b4398da 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -761,11 +761,11 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, if (!_ep || !desc || hsep->desc || _ep->name == ep0name || desc->bDescriptorType != USB_DT_ENDPOINT || hsep->bEndpointAddress != desc->bEndpointAddress - || ep_maxpacket(hsep) < le16_to_cpu(desc->wMaxPacketSize)) + || ep_maxpacket(hsep) < usb_endpoint_maxp(desc)) return -EINVAL; if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK - && le16_to_cpu(desc->wMaxPacketSize) != ep_maxpacket(hsep)) + && usb_endpoint_maxp(desc) != ep_maxpacket(hsep)) || !desc->wMaxPacketSize) return -ERANGE; @@ -781,7 +781,7 @@ static int s3c_hsudc_ep_enable(struct usb_ep *_ep, hsep->stopped = hsep->wedge = 0; hsep->desc = desc; - hsep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize); + hsep->ep.maxpacket = usb_endpoint_maxp(desc); s3c_hsudc_set_halt(_ep, 0); __set_bit(ep_index(hsep), hsudc->regs + S3C_EIER); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 8d31848aab09..257285448678 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1082,7 +1082,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) return -ESHUTDOWN; - max = le16_to_cpu(desc->wMaxPacketSize) & 0x1fff; + max = usb_endpoint_maxp(desc) & 0x1fff; local_irq_save (flags); _ep->maxpacket = max & 0x7ff; diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index dd24fc115e48..15dc51ded61a 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -428,7 +428,7 @@ static struct ed *ed_get ( ed->type = usb_pipetype(pipe); info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << 7; - info |= le16_to_cpu(ep->desc.wMaxPacketSize) << 16; + info |= usb_endpoint_maxp(&ep->desc) << 16; if (udev->speed == USB_SPEED_LOW) info |= ED_LOWSPEED; /* only control transfers store pids in tds */ @@ -444,7 +444,7 @@ static struct ed *ed_get ( ed->load = usb_calc_bus_time ( udev->speed, !is_out, ed->type == PIPE_ISOCHRONOUS, - le16_to_cpu(ep->desc.wMaxPacketSize)) + usb_endpoint_maxp(&ep->desc)) / 1000; } } diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 40a0d8b03ad7..a6f256436e77 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -959,7 +959,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.pipenum = get_empty_pipenum(r8a66597, ep); info.address = get_urb_to_r8a66597_addr(r8a66597, urb); info.epnum = usb_endpoint_num(ep); - info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); + info.maxpacket = usb_endpoint_maxp(ep); info.type = get_r8a66597_type(usb_endpoint_type(ep)); info.bufnum = get_bufnum(info.pipenum); info.buf_bsize = get_buf_bsize(info.pipenum); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 84ed28b34f93..f6ca80ee4cec 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -280,7 +280,7 @@ static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, qh->load = usb_calc_bus_time(udev->speed, usb_endpoint_dir_in(&hep->desc), qh->type == USB_ENDPOINT_XFER_ISOC, - le16_to_cpu(hep->desc.wMaxPacketSize)) + usb_endpoint_maxp(&hep->desc)) / 1000 + 1; } else { /* Skeleton QH */ @@ -792,7 +792,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, { struct uhci_td *td; unsigned long destination, status; - int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); + int maxsze = usb_endpoint_maxp(&qh->hep->desc); int len = urb->transfer_buffer_length; dma_addr_t data = urb->transfer_dma; __hc32 *plink; @@ -918,7 +918,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, { struct uhci_td *td; unsigned long destination, status; - int maxsze = le16_to_cpu(qh->hep->desc.wMaxPacketSize); + int maxsze = usb_endpoint_maxp(&qh->hep->desc); int len = urb->transfer_buffer_length; int this_sg_len; dma_addr_t data; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index d446886b22b0..d873a0330c9e 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1141,8 +1141,8 @@ static u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci, if (udev->speed == USB_SPEED_SUPER) return le16_to_cpu(ep->ss_ep_comp.wBytesPerInterval); - max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize)); - max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) & 0x1800) >> 11; + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; /* A 0 in max burst means 1 transfer per ESIT */ return max_packet * (max_burst + 1); } @@ -1211,7 +1211,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, /* Set the max packet size and max burst */ switch (udev->speed) { case USB_SPEED_SUPER: - max_packet = le16_to_cpu(ep->desc.wMaxPacketSize); + max_packet = usb_endpoint_maxp(&ep->desc); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); /* dig out max burst from ep companion desc */ max_packet = ep->ss_ep_comp.bMaxBurst; @@ -1223,14 +1223,14 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, */ if (usb_endpoint_xfer_isoc(&ep->desc) || usb_endpoint_xfer_int(&ep->desc)) { - max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) + max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst)); } /* Fall through */ case USB_SPEED_FULL: case USB_SPEED_LOW: - max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize)); + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); break; default: diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 7113d16e2d3a..bf0b52c6c960 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2676,7 +2676,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, * running_total. */ packets_transferred = (running_total + trb_buff_len) / - le16_to_cpu(urb->ep->desc.wMaxPacketSize); + usb_endpoint_maxp(&urb->ep->desc); return xhci_td_remainder(total_packet_count - packets_transferred); } @@ -2706,7 +2706,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs = count_sg_trbs_needed(xhci, urb); num_sgs = urb->num_sgs; total_packet_count = roundup(urb->transfer_buffer_length, - le16_to_cpu(urb->ep->desc.wMaxPacketSize)); + usb_endpoint_maxp(&urb->ep->desc)); trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], ep_index, urb->stream_id, @@ -2913,7 +2913,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total = 0; total_packet_count = roundup(urb->transfer_buffer_length, - le16_to_cpu(urb->ep->desc.wMaxPacketSize)); + usb_endpoint_maxp(&urb->ep->desc)); /* How much data is in the first TRB? */ addr = (u64) urb->transfer_dma; trb_buff_len = TRB_MAX_BUFF_SIZE - @@ -3239,7 +3239,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td_remain_len = td_len; /* FIXME: Ignoring zero-length packets, can those happen? */ total_packet_count = roundup(td_len, - le16_to_cpu(urb->ep->desc.wMaxPacketSize)); + usb_endpoint_maxp(&urb->ep->desc)); burst_count = xhci_get_burst_count(xhci, urb->dev, urb, total_packet_count); residue = xhci_get_last_burst_packet_count(xhci, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1c4432d8fc10..f53596b16dec 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -987,7 +987,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, out_ctx = xhci->devs[slot_id]->out_ctx; ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2)); - max_packet_size = le16_to_cpu(urb->dev->ep0.desc.wMaxPacketSize); + max_packet_size = usb_endpoint_maxp(&urb->dev->ep0.desc); if (hw_max_packet_size != max_packet_size) { xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n"); xhci_dbg(xhci, "Max packet size in usb_device = %d\n", diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index a6afd15f6a46..fe858711651c 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -213,7 +213,7 @@ static void adu_interrupt_in_callback(struct urb *urb) if (urb->actual_length > 0 && dev->interrupt_in_buffer[0] != 0x00) { if (dev->read_buffer_length < - (4 * le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize)) - + (4 * usb_endpoint_maxp(dev->interrupt_in_endpoint)) - (urb->actual_length)) { memcpy (dev->read_buffer_primary + dev->read_buffer_length, @@ -315,7 +315,7 @@ static int adu_open(struct inode *inode, struct file *file) usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); dev->read_urb_finished = 0; @@ -483,7 +483,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); @@ -536,7 +536,7 @@ static ssize_t adu_read(struct file *file, __user char *buffer, size_t count, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), adu_interrupt_in_callback, dev, dev->interrupt_in_endpoint->bInterval); @@ -622,7 +622,7 @@ static ssize_t adu_write(struct file *file, const __user char *buffer, dbg(4," %s : sending, count = %Zd", __func__, count); /* write the data into interrupt_out_buffer from userspace */ - buffer_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); bytes_to_write = count > buffer_size ? buffer_size : count; dbg(4," %s : buffer_size = %Zd, count = %Zd, bytes_to_write = %Zd", __func__, buffer_size, count, bytes_to_write); @@ -752,8 +752,8 @@ static int adu_probe(struct usb_interface *interface, goto error; } - in_end_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); - out_end_size = le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize); + in_end_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); + out_end_size = usb_endpoint_maxp(dev->interrupt_out_endpoint); dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL); if (!dev->read_buffer_primary) { diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 2f41089cd854..2dbe600fbc11 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -2777,7 +2777,7 @@ static int ftdi_elan_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (!ftdi->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); ftdi->bulk_in_size = buffer_size; ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; ftdi->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); diff --git a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c index c6184b4d1695..515b67fffab1 100644 --- a/drivers/usb/misc/idmouse.c +++ b/drivers/usb/misc/idmouse.c @@ -359,7 +359,7 @@ static int idmouse_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[0].desc; if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize); + dev->orig_bi_size = usb_endpoint_maxp(endpoint); dev->bulk_in_size = 0x200; /* works _much_ faster */ dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index a2190b983f52..81457904d6ba 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -803,7 +803,7 @@ static int iowarrior_probe(struct usb_interface *interface, dev->int_out_endpoint = endpoint; } /* we have to check the report_size often, so remember it in the endianess suitable for our machine */ - dev->report_size = le16_to_cpu(dev->int_in_endpoint->wMaxPacketSize); + dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56)) /* IOWarrior56 has wMaxPacketSize different from report size */ diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index cb4096201e29..48c166f0d764 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -721,7 +721,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * if (dev->interrupt_out_endpoint == NULL) dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n"); - dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize); + dev->interrupt_in_endpoint_size = usb_endpoint_maxp(dev->interrupt_in_endpoint); dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL); if (!dev->ring_buffer) { dev_err(&intf->dev, "Couldn't allocate ring_buffer\n"); @@ -737,7 +737,7 @@ static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id * dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n"); goto error; } - dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) : + dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? usb_endpoint_maxp(dev->interrupt_out_endpoint) : udev->descriptor.bMaxPacketSize0; dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL); if (!dev->interrupt_out_buffer) { diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index 6482c6e2e6bd..a989356f693e 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -409,7 +409,7 @@ static int tower_open (struct inode *inode, struct file *file) dev->udev, usb_rcvintpipe(dev->udev, dev->interrupt_in_endpoint->bEndpointAddress), dev->interrupt_in_buffer, - le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), + usb_endpoint_maxp(dev->interrupt_in_endpoint), tower_interrupt_in_callback, dev, dev->interrupt_in_interval); @@ -928,7 +928,7 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device err("Couldn't allocate read_buffer"); goto error; } - dev->interrupt_in_buffer = kmalloc (le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize), GFP_KERNEL); + dev->interrupt_in_buffer = kmalloc (usb_endpoint_maxp(dev->interrupt_in_endpoint), GFP_KERNEL); if (!dev->interrupt_in_buffer) { err("Couldn't allocate interrupt_in_buffer"); goto error; diff --git a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c index 6ac106952e95..1871cdf10da3 100644 --- a/drivers/usb/misc/usblcd.c +++ b/drivers/usb/misc/usblcd.c @@ -347,7 +347,7 @@ static int lcd_probe(struct usb_interface *interface, if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index bd715006b056..930962f49276 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1585,8 +1585,8 @@ static struct urb *iso_alloc_urb( if (bytes < 0 || !desc) return NULL; - maxp = 0x7ff & le16_to_cpu(desc->wMaxPacketSize); - maxp *= 1 + (0x3 & (le16_to_cpu(desc->wMaxPacketSize) >> 11)); + maxp = 0x7ff & usb_endpoint_maxp(desc); + maxp *= 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)); packets = DIV_ROUND_UP(bytes, maxp); urb = usb_alloc_urb(packets, GFP_KERNEL); @@ -1656,7 +1656,7 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, "... iso period %d %sframes, wMaxPacket %04x\n", 1 << (desc->bInterval - 1), (udev->speed == USB_SPEED_HIGH) ? "micro" : "", - le16_to_cpu(desc->wMaxPacketSize)); + usb_endpoint_maxp(desc)); for (i = 0; i < param->sglen; i++) { urbs[i] = iso_alloc_urb(udev, pipe, desc, diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 8c41a2e6ea77..44b331a74d58 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1020,7 +1020,7 @@ static int musb_gadget_enable(struct usb_ep *ep, goto fail; /* REVISIT this rules out high bandwidth periodic transfers */ - tmp = le16_to_cpu(desc->wMaxPacketSize); + tmp = usb_endpoint_maxp(desc); if (tmp & ~0x07ff) { int ok; diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 8b2473fa0f47..60ddba8066ea 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -1932,7 +1932,7 @@ static int musb_urb_enqueue( INIT_LIST_HEAD(&qh->ring); qh->is_ready = 1; - qh->maxpacket = le16_to_cpu(epd->wMaxPacketSize); + qh->maxpacket = usb_endpoint_maxp(epd); qh->type = usb_endpoint_type(epd); /* Bits 11 & 12 of wMaxPacketSize encode high bandwidth multiplier. diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 78a2cf9551cc..8aee28b89c36 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1480,7 +1480,7 @@ static void ftdi_set_max_packet_size(struct usb_serial_port *port) } /* set max packet size based on descriptor */ - priv->max_packet_size = le16_to_cpu(ep_desc->wMaxPacketSize); + priv->max_packet_size = usb_endpoint_maxp(ep_desc); dev_info(&udev->dev, "Setting MaxPacketSize %d\n", priv->max_packet_size); } diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index abf095be5753..2ee807523f53 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -3042,7 +3042,7 @@ static int edge_startup(struct usb_serial *serial) endpoint = &serial->interface->altsetting[0]. endpoint[i].desc; - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); if (!interrupt_in_found && (usb_endpoint_is_int_in(endpoint))) { /* we found a interrupt in endpoint */ @@ -3107,7 +3107,7 @@ static int edge_startup(struct usb_serial *serial) usb_rcvbulkpipe(dev, endpoint->bEndpointAddress), edge_serial->bulk_in_buffer, - le16_to_cpu(endpoint->wMaxPacketSize), + usb_endpoint_maxp(endpoint), edge_bulk_in_callback, edge_serial); bulk_in_found = true; diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 96423f3c8ef3..c248a9147439 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -523,7 +523,7 @@ static int opticon_startup(struct usb_serial *serial) goto error; } - priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; + priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; priv->bulk_in_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); if (!priv->bulk_in_buffer) { dev_err(&priv->udev->dev, "out of memory\n"); diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index d9457bd4fe10..7096f799b071 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -226,7 +226,7 @@ static int symbol_startup(struct usb_serial *serial) goto error; } - priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; + priv->buffer_size = usb_endpoint_maxp(endpoint) * 2; priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); if (!priv->int_buffer) { dev_err(&priv->udev->dev, "out of memory\n"); diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 1c031309ab25..cc274fdf2627 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -912,7 +912,7 @@ int usb_serial_probe(struct usb_interface *interface, goto probe_error; } buffer_size = max_t(int, serial->type->bulk_in_size, - le16_to_cpu(endpoint->wMaxPacketSize)); + usb_endpoint_maxp(endpoint)); port->bulk_in_size = buffer_size; port->bulk_in_endpointAddress = endpoint->bEndpointAddress; port->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); @@ -942,7 +942,7 @@ int usb_serial_probe(struct usb_interface *interface, goto probe_error; buffer_size = serial->type->bulk_out_size; if (!buffer_size) - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); port->bulk_out_size = buffer_size; port->bulk_out_endpointAddress = endpoint->bEndpointAddress; port->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); @@ -990,7 +990,7 @@ int usb_serial_probe(struct usb_interface *interface, "No free urbs available\n"); goto probe_error; } - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); port->interrupt_in_endpointAddress = endpoint->bEndpointAddress; port->interrupt_in_buffer = kmalloc(buffer_size, @@ -1021,7 +1021,7 @@ int usb_serial_probe(struct usb_interface *interface, "No free urbs available\n"); goto probe_error; } - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); port->interrupt_out_size = buffer_size; port->interrupt_out_endpointAddress = endpoint->bEndpointAddress; diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index e24ce3123071..32d6fc953904 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -555,7 +555,7 @@ static int skel_probe(struct usb_interface *interface, if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + buffer_size = usb_endpoint_maxp(endpoint); dev->bulk_in_size = buffer_size; dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; dev->bulk_in_buffer = kmalloc(buffer_size, GFP_KERNEL); diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c index 59a748a0e5da..0d1863c9edde 100644 --- a/drivers/usb/wusbcore/wa-hc.c +++ b/drivers/usb/wusbcore/wa-hc.c @@ -43,7 +43,7 @@ int wa_create(struct wahc *wa, struct usb_interface *iface) /* Fill up Data Transfer EP pointers */ wa->dti_epd = &iface->cur_altsetting->endpoint[1].desc; wa->dto_epd = &iface->cur_altsetting->endpoint[2].desc; - wa->xfer_result_size = le16_to_cpu(wa->dti_epd->wMaxPacketSize); + wa->xfer_result_size = usb_endpoint_maxp(wa->dti_epd); wa->xfer_result = kmalloc(wa->xfer_result_size, GFP_KERNEL); if (wa->xfer_result == NULL) goto error_xfer_result_alloc; diff --git a/include/linux/usb.h b/include/linux/usb.h index 73c7df489607..c19f9100c307 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1574,7 +1574,7 @@ usb_maxpacket(struct usb_device *udev, int pipe, int is_out) return 0; /* NOTE: only 0x07ff bits are for packet size... */ - return le16_to_cpu(ep->desc.wMaxPacketSize); + return usb_endpoint_maxp(&ep->desc); } /* ----------------------------------------------------------------------- */ -- cgit v1.2.3 From 9962444f592a53c08ce439b6dc362bba7ce5fd7e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 1 Sep 2011 22:26:25 +0300 Subject: usb: dwc3: omap: distinguish between SW and HW modes The OMAP wrapper allows us to either control internal OTG signals via SW or HW. Different boards might wish to use one or the other mode of operation. Let's have have that information passed via platform_data for now. After DT conversion is finished for OMAP, we can easily convert this to a DT attribute. Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/dwc3-omap.c | 22 +++++++++++++++ include/linux/platform_data/dwc3-omap.h | 47 +++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 include/linux/platform_data/dwc3-omap.h (limited to 'include') diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 17d1822f7687..ddbf38a94017 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -193,6 +194,7 @@ static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) static int __devinit dwc3_omap_probe(struct platform_device *pdev) { + struct dwc3_omap_data *pdata = pdev->dev.platform_data; struct platform_device *dwc3; struct dwc3_omap *omap; struct resource *res; @@ -258,6 +260,26 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) omap->base = base; omap->dwc3 = dwc3; + reg = dwc3_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS); + + if (!pdata) { + dev_dbg(&pdev->dev, "missing platform data\n"); + } else { + switch (pdata->utmi_mode) { + case DWC3_OMAP_UTMI_MODE_SW: + reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + case DWC3_OMAP_UTMI_MODE_HW: + reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE; + break; + default: + dev_dbg(&pdev->dev, "UNKNOWN utmi mode %d\n", + pdata->utmi_mode); + } + } + + dwc3_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS, reg); + /* check the DMA Status */ reg = dwc3_readl(omap->base, USBOTGSS_SYSCONFIG); omap->dma_status = !!(reg & USBOTGSS_SYSCONFIG_DMADISABLE); diff --git a/include/linux/platform_data/dwc3-omap.h b/include/linux/platform_data/dwc3-omap.h new file mode 100644 index 000000000000..ada401244e0b --- /dev/null +++ b/include/linux/platform_data/dwc3-omap.h @@ -0,0 +1,47 @@ +/** + * dwc3-omap.h - OMAP Specific Glue layer, header. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com + * All rights reserved. + * + * Author: Felipe Balbi + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") version 2, as published by the Free + * Software Foundation. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +enum dwc3_omap_utmi_mode { + DWC3_OMAP_UTMI_MODE_UNKNOWN = 0, + DWC3_OMAP_UTMI_MODE_HW, + DWC3_OMAP_UTMI_MODE_SW, +}; + +struct dwc3_omap_data { + enum dwc3_omap_utmi_mode utmi_mode; +}; -- cgit v1.2.3 From e538dfdae85244fd2c4231725d82cc1f1bc4942c Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 30 Aug 2011 17:11:19 +0200 Subject: usb: Provide usb_speed_string() function In a few places in the kernel, the code prints a human-readable USB device speed (eg. "high speed"). This involves a switch statement sometimes wrapped around in ({ ... }) block leading to code repetition. To mitigate this issue, this commit introduces usb_speed_string() function, which returns a human-readable name of provided speed. It also changes a few places switch was used to use this new function. This changes a bit the way the speed is printed in few instances at the same time standardising it. Signed-off-by: Michal Nazarewicz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Kconfig | 5 ++++ drivers/usb/Makefile | 2 ++ drivers/usb/core/hub.c | 27 +++++++------------ drivers/usb/gadget/amd5536udc.c | 9 ++----- drivers/usb/gadget/atmel_usba_udc.c | 9 +++---- drivers/usb/gadget/composite.c | 22 +++------------ drivers/usb/gadget/file_storage.c | 15 +++-------- drivers/usb/gadget/fsl_udc_core.c | 53 +++++++++++++------------------------ drivers/usb/gadget/gmidi.c | 11 +------- drivers/usb/gadget/langwell_udc.c | 50 ++++++++++++---------------------- drivers/usb/gadget/net2272.c | 4 +-- drivers/usb/gadget/net2280.c | 4 +-- drivers/usb/gadget/printer.c | 14 +++------- drivers/usb/gadget/s3c-hsotg.c | 8 ++---- drivers/usb/gadget/udc-core.c | 19 ++----------- drivers/usb/misc/usbtest.c | 21 ++------------- drivers/usb/usb-common.c | 35 ++++++++++++++++++++++++ include/linux/usb/ch9.h | 12 +++++++++ 18 files changed, 125 insertions(+), 195 deletions(-) create mode 100644 drivers/usb/usb-common.c (limited to 'include') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 2651852952be..97c4cc724189 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -12,6 +12,11 @@ menuconfig USB_SUPPORT if USB_SUPPORT +config USB_COMMON + tristate + default y + depends on USB || USB_GADGET + # Host-side USB depends on having a host controller # NOTE: dummy_hcd is always an option, but it's ignored here ... # NOTE: SL-811 option should be board-specific ... diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 969b0a50bc98..75eca7645227 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -53,3 +53,5 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb/ obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/ obj-$(CONFIG_USB_OTG_UTILS) += otg/ obj-$(CONFIG_USB_GADGET) += gadget/ + +obj-$(CONFIG_USB_COMMON) += usb-common.o diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 338f91ff54cb..3edc01bc41f7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2793,7 +2793,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, int i, j, retval; unsigned delay = HUB_SHORT_RESET_TIME; enum usb_device_speed oldspeed = udev->speed; - char *speed, *type; + const char *speed; int devnum = udev->devnum; /* root hub ports have a slightly longer reset period @@ -2853,25 +2853,16 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, default: goto fail; } - - type = ""; - switch (udev->speed) { - case USB_SPEED_LOW: speed = "low"; break; - case USB_SPEED_FULL: speed = "full"; break; - case USB_SPEED_HIGH: speed = "high"; break; - case USB_SPEED_SUPER: - speed = "super"; - break; - case USB_SPEED_WIRELESS: - speed = "variable"; - type = "Wireless "; - break; - default: speed = "?"; break; - } + + if (udev->speed == USB_SPEED_WIRELESS) + speed = "variable speed Wireless"; + else + speed = usb_speed_string(udev->speed); + if (udev->speed != USB_SPEED_SUPER) dev_info(&udev->dev, - "%s %s speed %sUSB device number %d using %s\n", - (udev->config) ? "reset" : "new", speed, type, + "%s %s USB device number %d using %s\n", + (udev->config) ? "reset" : "new", speed, devnum, udev->bus->controller->driver->name); /* Set up TT records, if needed */ diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index ded8d6fddb53..4730016d7cd4 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3005,13 +3005,8 @@ __acquires(dev->lock) /* link up all endpoints */ udc_setup_endpoints(dev); - if (dev->gadget.speed == USB_SPEED_HIGH) { - dev_info(&dev->pdev->dev, "Connect: speed = %s\n", - "high"); - } else if (dev->gadget.speed == USB_SPEED_FULL) { - dev_info(&dev->pdev->dev, "Connect: speed = %s\n", - "full"); - } + dev_info(&dev->pdev->dev, "Connect: %s\n", + usb_speed_string(dev->gadget.speed)); /* init ep 0 */ activate_control_endpoints(dev); diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 722c468e9b3c..271a9d873608 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1718,13 +1718,12 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) spin_lock(&udc->lock); } - if (status & USBA_HIGH_SPEED) { - DBG(DBG_BUS, "High-speed bus reset detected\n"); + if (status & USBA_HIGH_SPEED) udc->gadget.speed = USB_SPEED_HIGH; - } else { - DBG(DBG_BUS, "Full-speed bus reset detected\n"); + else udc->gadget.speed = USB_SPEED_FULL; - } + DBG(DBG_BUS, "%s bus reset detected\n", + usb_speed_string(udc->gadget.speed)); ep0 = &usba_ep[0]; ep0->desc = &usba_ep0_desc; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index c77aca11ad53..e74fd55c33d9 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -617,25 +617,9 @@ static int set_config(struct usb_composite_dev *cdev, result = 0; } - INFO(cdev, "%s speed config #%d: %s\n", - ({ char *speed; - switch (gadget->speed) { - case USB_SPEED_LOW: - speed = "low"; - break; - case USB_SPEED_FULL: - speed = "full"; - break; - case USB_SPEED_HIGH: - speed = "high"; - break; - case USB_SPEED_SUPER: - speed = "super"; - break; - default: - speed = "?"; - break; - } ; speed; }), number, c ? c->label : "unconfigured"); + INFO(cdev, "%s config #%d: %s\n", + usb_speed_string(gadget->speed), + number, c ? c->label : "unconfigured"); if (!c) goto done; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 39ece40a045f..4ac8084b579c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -2862,17 +2862,10 @@ static int do_set_config(struct fsg_dev *fsg, u8 new_config) fsg->config = new_config; if ((rc = do_set_interface(fsg, 0)) != 0) fsg->config = 0; // Reset on errors - else { - char *speed; - - switch (fsg->gadget->speed) { - case USB_SPEED_LOW: speed = "low"; break; - case USB_SPEED_FULL: speed = "full"; break; - case USB_SPEED_HIGH: speed = "high"; break; - default: speed = "?"; break; - } - INFO(fsg, "%s speed config #%d\n", speed, fsg->config); - } + else + INFO(fsg, "%s config #%d\n", + usb_speed_string(fsg->gadget->speed), + fsg->config); } return rc; } diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index d6993507165b..b2c44e1d5813 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1715,34 +1715,31 @@ static void dtd_complete_irq(struct fsl_udc *udc) } } +static inline enum usb_device_speed portscx_device_speed(u32 reg) +{ + switch (speed & PORTSCX_PORT_SPEED_MASK) { + case PORTSCX_PORT_SPEED_HIGH: + return USB_SPEED_HIGH; + case PORTSCX_PORT_SPEED_FULL: + return USB_SPEED_FULL; + case PORTSCX_PORT_SPEED_LOW: + return USB_SPEED_LOW; + default: + return USB_SPEED_UNKNOWN; + } +} + /* Process a port change interrupt */ static void port_change_irq(struct fsl_udc *udc) { - u32 speed; - if (udc->bus_reset) udc->bus_reset = 0; /* Bus resetting is finished */ - if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) { + if (!(fsl_readl(&dr_regs->portsc1) & PORTSCX_PORT_RESET)) /* Get the speed */ - speed = (fsl_readl(&dr_regs->portsc1) - & PORTSCX_PORT_SPEED_MASK); - switch (speed) { - case PORTSCX_PORT_SPEED_HIGH: - udc->gadget.speed = USB_SPEED_HIGH; - break; - case PORTSCX_PORT_SPEED_FULL: - udc->gadget.speed = USB_SPEED_FULL; - break; - case PORTSCX_PORT_SPEED_LOW: - udc->gadget.speed = USB_SPEED_LOW; - break; - default: - udc->gadget.speed = USB_SPEED_UNKNOWN; - break; - } - } + udc->gadget.speed = + portscx_device_speed(fsl_readl(&dr_regs->portsc1)); /* Update USB state */ if (!udc->resume_state) @@ -2167,20 +2164,8 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count, default: s = "None"; break; } - s;} ), ( { - char *s; - switch (tmp_reg & PORTSCX_PORT_SPEED_UNDEF) { - case PORTSCX_PORT_SPEED_FULL: - s = "Full Speed"; break; - case PORTSCX_PORT_SPEED_LOW: - s = "Low Speed"; break; - case PORTSCX_PORT_SPEED_HIGH: - s = "High Speed"; break; - default: - s = "Undefined"; break; - } - s; - } ), + s;} ), + usb_speed_string(portscx_device_speed(tmp_reg)), (tmp_reg & PORTSCX_PHY_LOW_POWER_SPD) ? "Normal PHY mode" : "Low power mode", (tmp_reg & PORTSCX_PORT_RESET) ? "In Reset" : diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 8b9220e128a7..893b967b0aff 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -640,17 +640,8 @@ gmidi_set_config(struct gmidi_device *dev, unsigned number, gfp_t gfp_flags) if (result) { gmidi_reset_config(dev); } else { - char *speed; - - switch (gadget->speed) { - case USB_SPEED_LOW: speed = "low"; break; - case USB_SPEED_FULL: speed = "full"; break; - case USB_SPEED_HIGH: speed = "high"; break; - default: speed = "?"; break; - } - dev->config = number; - INFO(dev, "%s speed\n", speed); + INFO(dev, "%s speed\n", usb_speed_string(gadget->speed)); } return result; } diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index 6e444995d398..c88158f307a8 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -1690,20 +1690,7 @@ static ssize_t show_langwell_udc(struct device *_dev, "BmAttributes: %d\n\n", LPM_PTS(tmp_reg), (tmp_reg & LPM_STS) ? 1 : 0, - ({ - char *s; - switch (LPM_PSPD(tmp_reg)) { - case LPM_SPEED_FULL: - s = "Full Speed"; break; - case LPM_SPEED_LOW: - s = "Low Speed"; break; - case LPM_SPEED_HIGH: - s = "High Speed"; break; - default: - s = "Unknown Speed"; break; - } - s; - }), + usb_speed_string(lpm_device_speed(tmp_reg)), (tmp_reg & LPM_PFSC) ? "Force Full Speed" : "Not Force", (tmp_reg & LPM_PHCD) ? "Disabled" : "Enabled", LPM_BA(tmp_reg)); @@ -2647,12 +2634,24 @@ done: dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__); } +static inline enum usb_device_speed lpm_device_speed(u32 reg) +{ + switch (LPM_PSPD(reg)) { + case LPM_SPEED_HIGH: + return USB_SPEED_HIGH; + case LPM_SPEED_FULL: + return USB_SPEED_FULL; + case LPM_SPEED_LOW: + return USB_SPEED_LOW; + default: + return USB_SPEED_UNKNOWN; + } +} /* port change detect interrupt handler */ static void handle_port_change(struct langwell_udc *dev) { u32 portsc1, devlc; - u32 speed; dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__); @@ -2667,24 +2666,9 @@ static void handle_port_change(struct langwell_udc *dev) /* bus reset is finished */ if (!(portsc1 & PORTS_PR)) { /* get the speed */ - speed = LPM_PSPD(devlc); - switch (speed) { - case LPM_SPEED_HIGH: - dev->gadget.speed = USB_SPEED_HIGH; - break; - case LPM_SPEED_FULL: - dev->gadget.speed = USB_SPEED_FULL; - break; - case LPM_SPEED_LOW: - dev->gadget.speed = USB_SPEED_LOW; - break; - default: - dev->gadget.speed = USB_SPEED_UNKNOWN; - break; - } - dev_vdbg(&dev->pdev->dev, - "speed = %d, dev->gadget.speed = %d\n", - speed, dev->gadget.speed); + dev->gadget.speed = lpm_device_speed(devlc); + dev_vdbg(&dev->pdev->dev, "dev->gadget.speed = %d\n", + dev->gadget.speed); } /* LPM L0 to L1 */ diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index 6fef1c02448e..08a4a36550d2 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c @@ -1764,8 +1764,8 @@ net2272_handle_stat0_irqs(struct net2272 *dev, u8 stat) dev->gadget.speed = USB_SPEED_HIGH; else dev->gadget.speed = USB_SPEED_FULL; - dev_dbg(dev->dev, "%s speed\n", - (dev->gadget.speed == USB_SPEED_HIGH) ? "high" : "full"); + dev_dbg(dev->dev, "%s\n", + usb_speed_string(dev->gadget.speed)); } ep = &dev->ep[0]; diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 3c14c4ea8efd..db508d0bb3af 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -2257,9 +2257,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) else dev->gadget.speed = USB_SPEED_FULL; net2280_led_speed (dev, dev->gadget.speed); - DEBUG (dev, "%s speed\n", - (dev->gadget.speed == USB_SPEED_HIGH) - ? "high" : "full"); + DEBUG(dev, "%s\n", usb_speed_string(dev->gadget.speed)); } ep = &dev->ep [0]; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 5d3e697b7d5d..68a0efbc2719 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -962,23 +962,15 @@ printer_set_config(struct printer_dev *dev, unsigned number) usb_gadget_vbus_draw(dev->gadget, dev->gadget->is_otg ? 8 : 100); } else { - char *speed; unsigned power; power = 2 * config_desc.bMaxPower; usb_gadget_vbus_draw(dev->gadget, power); - switch (gadget->speed) { - case USB_SPEED_FULL: speed = "full"; break; -#ifdef CONFIG_USB_GADGET_DUALSPEED - case USB_SPEED_HIGH: speed = "high"; break; -#endif - default: speed = "?"; break; - } - dev->config = number; - INFO(dev, "%s speed config #%d: %d mA, %s\n", - speed, number, power, driver_desc); + INFO(dev, "%s config #%d: %d mA, %s\n", + usb_speed_string(gadget->speed), + number, power, driver_desc); } return result; } diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 39b134dec94c..a552453dc946 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -1951,30 +1951,26 @@ static void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) case S3C_DSTS_EnumSpd_FS: case S3C_DSTS_EnumSpd_FS48: hsotg->gadget.speed = USB_SPEED_FULL; - dev_info(hsotg->dev, "new device is full-speed\n"); - ep0_mps = EP0_MPS_LIMIT; ep_mps = 64; break; case S3C_DSTS_EnumSpd_HS: - dev_info(hsotg->dev, "new device is high-speed\n"); hsotg->gadget.speed = USB_SPEED_HIGH; - ep0_mps = EP0_MPS_LIMIT; ep_mps = 512; break; case S3C_DSTS_EnumSpd_LS: hsotg->gadget.speed = USB_SPEED_LOW; - dev_info(hsotg->dev, "new device is low-speed\n"); - /* note, we don't actually support LS in this driver at the * moment, and the documentation seems to imply that it isn't * supported by the PHYs on some of the devices. */ break; } + dev_info(hsotg->dev, "new device is %s\n", + usb_speed_string(hsotg->gadget.speed)); /* we should now know the maximum packet size for an * endpoint, so set the endpoints to a default value. */ diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 05ba47214361..5e77a46a429a 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -375,23 +375,8 @@ static ssize_t usb_udc_speed_show(struct device *dev, struct device_attribute *attr, char *buf) { struct usb_udc *udc = container_of(dev, struct usb_udc, dev); - struct usb_gadget *gadget = udc->gadget; - - switch (gadget->speed) { - case USB_SPEED_LOW: - return snprintf(buf, PAGE_SIZE, "low-speed\n"); - case USB_SPEED_FULL: - return snprintf(buf, PAGE_SIZE, "full-speed\n"); - case USB_SPEED_HIGH: - return snprintf(buf, PAGE_SIZE, "high-speed\n"); - case USB_SPEED_WIRELESS: - return snprintf(buf, PAGE_SIZE, "wireless\n"); - case USB_SPEED_SUPER: - return snprintf(buf, PAGE_SIZE, "super-speed\n"); - case USB_SPEED_UNKNOWN: /* FALLTHROUGH */ - default: - return snprintf(buf, PAGE_SIZE, "UNKNOWN\n"); - } + return snprintf(buf, PAGE_SIZE, "%s\n", + usb_speed_string(udc->gadget->speed)); } static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL); diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 930962f49276..bd6d00802eab 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -2300,25 +2300,8 @@ usbtest_probe(struct usb_interface *intf, const struct usb_device_id *id) usb_set_intfdata(intf, dev); dev_info(&intf->dev, "%s\n", info->name); - dev_info(&intf->dev, "%s speed {control%s%s%s%s%s} tests%s\n", - ({ char *tmp; - switch (udev->speed) { - case USB_SPEED_LOW: - tmp = "low"; - break; - case USB_SPEED_FULL: - tmp = "full"; - break; - case USB_SPEED_HIGH: - tmp = "high"; - break; - case USB_SPEED_SUPER: - tmp = "super"; - break; - default: - tmp = "unknown"; - break; - }; tmp; }), + dev_info(&intf->dev, "%s {control%s%s%s%s%s} tests%s\n", + usb_speed_string(udev->speed), info->ctrl_out ? " in/out" : "", rtest, wtest, irtest, iwtest, diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c new file mode 100644 index 000000000000..d29503e954ab --- /dev/null +++ b/drivers/usb/usb-common.c @@ -0,0 +1,35 @@ +/* + * Provides code common for host and device side USB. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2. + * + * If either host side (ie. CONFIG_USB=y) or device side USB stack + * (ie. CONFIG_USB_GADGET=y) is compiled in the kernel, this module is + * compiled-in as well. Otherwise, if either of the two stacks is + * compiled as module, this file is compiled as module as well. + */ + +#include +#include +#include + +const char *usb_speed_string(enum usb_device_speed speed) +{ + static const char *const names[] = { + [USB_SPEED_UNKNOWN] = "UNKNOWN", + [USB_SPEED_LOW] = "low-speed", + [USB_SPEED_FULL] = "full-speed", + [USB_SPEED_HIGH] = "high-speed", + [USB_SPEED_WIRELESS] = "wireless", + [USB_SPEED_SUPER] = "super-speed", + }; + + if (speed < 0 || speed >= ARRAY_SIZE(names)) + speed = USB_SPEED_UNKNOWN; + return names[speed]; +} +EXPORT_SYMBOL_GPL(usb_speed_string); + +MODULE_LICENSE("GPL"); diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 1ded281eff88..f32a64e57f97 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -868,6 +868,18 @@ enum usb_device_speed { USB_SPEED_SUPER, /* usb 3.0 */ }; +#ifdef __KERNEL__ + +/** + * usb_speed_string() - Returns human readable-name of the speed. + * @speed: The speed to return human-readable name for. If it's not + * any of the speeds defined in usb_device_speed enum, string for + * USB_SPEED_UNKNOWN will be returned. + */ +extern const char *usb_speed_string(enum usb_device_speed speed); + +#endif + enum usb_device_state { /* NOTATTACHED isn't in the USB spec, and this state acts * the same as ATTACHED ... but it's clearer this way. -- cgit v1.2.3 From 3148bf041d169a083aa31bd69bedd5bfb7ffe215 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Fri, 23 Sep 2011 14:19:47 -0700 Subject: usbcore: get BOS descriptor set This commit gets BOS(Binary Device Object Store) descriptor set for Super Speed devices and High Speed devices which support BOS descriptor. BOS descriptor is used to report additional USB device-level capabilities that are not reported via the Device descriptor. By getting BOS descriptor set, driver can check device's device-level capability such as LPM capability. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/core/hub.c | 3 ++ drivers/usb/core/usb.c | 1 + drivers/usb/core/usb.h | 2 + include/linux/usb.h | 12 ++++++ 5 files changed, 121 insertions(+) (limited to 'include') diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 9d5e07af55be..f4bdd0ce8d56 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -755,3 +755,106 @@ err2: dev_err(ddev, "out of memory\n"); return result; } + +void usb_release_bos_descriptor(struct usb_device *dev) +{ + if (dev->bos) { + kfree(dev->bos->desc); + kfree(dev->bos); + dev->bos = NULL; + } +} + +/* Get BOS descriptor set */ +int usb_get_bos_descriptor(struct usb_device *dev) +{ + struct device *ddev = &dev->dev; + struct usb_bos_descriptor *bos; + struct usb_dev_cap_header *cap; + unsigned char *buffer; + int length, total_len, num, i; + int ret; + + bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL); + if (!bos) + return -ENOMEM; + + /* Get BOS descriptor */ + ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE); + if (ret < USB_DT_BOS_SIZE) { + dev_err(ddev, "unable to get BOS descriptor\n"); + if (ret >= 0) + ret = -ENOMSG; + kfree(bos); + return ret; + } + + length = bos->bLength; + total_len = le16_to_cpu(bos->wTotalLength); + num = bos->bNumDeviceCaps; + kfree(bos); + if (total_len < length) + return -EINVAL; + + dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL); + if (!dev->bos) + return -ENOMEM; + + /* Now let's get the whole BOS descriptor set */ + buffer = kzalloc(total_len, GFP_KERNEL); + if (!buffer) { + ret = -ENOMEM; + goto err; + } + dev->bos->desc = (struct usb_bos_descriptor *)buffer; + + ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len); + if (ret < total_len) { + dev_err(ddev, "unable to get BOS descriptor set\n"); + if (ret >= 0) + ret = -ENOMSG; + goto err; + } + total_len -= length; + + for (i = 0; i < num; i++) { + buffer += length; + cap = (struct usb_dev_cap_header *)buffer; + length = cap->bLength; + + if (total_len < length) + break; + total_len -= length; + + if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { + dev_warn(ddev, "descriptor type invalid, skip\n"); + continue; + } + + switch (cap->bDevCapabilityType) { + case USB_CAP_TYPE_WIRELESS_USB: + /* Wireless USB cap descriptor is handled by wusb */ + break; + case USB_CAP_TYPE_EXT: + dev->bos->ext_cap = + (struct usb_ext_cap_descriptor *)buffer; + break; + case USB_SS_CAP_TYPE: + dev->bos->ss_cap = + (struct usb_ss_cap_descriptor *)buffer; + break; + case CONTAINER_ID_TYPE: + dev->bos->ss_id = + (struct usb_ss_container_id_descriptor *)buffer; + break; + default: + break; + } + } + + return 0; + +err: + usb_release_bos_descriptor(dev); + return ret; +} diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1c155123c32f..7a2514322bfd 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3083,6 +3083,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; } + if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) + usb_get_bos_descriptor(udev); + retval = 0; /* notify HCD that we have a device connected and addressed */ if (hcd->driver->update_device) diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 8706fc97e60f..73cd90012ec5 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -225,6 +225,7 @@ static void usb_release_dev(struct device *dev) hcd = bus_to_hcd(udev->bus); usb_destroy_configuration(udev); + usb_release_bos_descriptor(udev); usb_put_hcd(hcd); kfree(udev->product); kfree(udev->manufacturer); diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index d44d4b7bbf17..0d023cd2c149 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -28,6 +28,8 @@ extern int usb_remove_device(struct usb_device *udev); extern int usb_get_device_descriptor(struct usb_device *dev, unsigned int size); +extern int usb_get_bos_descriptor(struct usb_device *dev); +extern void usb_release_bos_descriptor(struct usb_device *dev); extern char *usb_cache_string(struct usb_device *udev, int index); extern int usb_set_configuration(struct usb_device *dev, int configuration); extern int usb_choose_configuration(struct usb_device *udev); diff --git a/include/linux/usb.h b/include/linux/usb.h index c19f9100c307..90ab9dc1f080 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -292,6 +292,16 @@ struct usb_host_config { int extralen; }; +/* USB2.0 and USB3.0 device BOS descriptor set */ +struct usb_host_bos { + struct usb_bos_descriptor *desc; + + /* wireless cap descriptor is handled by wusb */ + struct usb_ext_cap_descriptor *ext_cap; + struct usb_ss_cap_descriptor *ss_cap; + struct usb_ss_container_id_descriptor *ss_id; +}; + int __usb_get_extra_descriptor(char *buffer, unsigned size, unsigned char type, void **ptr); #define usb_get_extra_descriptor(ifpoint, type, ptr) \ @@ -381,6 +391,7 @@ struct usb_tt; * @ep0: endpoint 0 data (default control pipe) * @dev: generic device interface * @descriptor: USB device descriptor + * @bos: USB device BOS descriptor set * @config: all of the device's configs * @actconfig: the active configuration * @ep_in: array of IN endpoints @@ -442,6 +453,7 @@ struct usb_device { struct device dev; struct usb_device_descriptor descriptor; + struct usb_host_bos *bos; struct usb_host_config *config; struct usb_host_config *actconfig; -- cgit v1.2.3 From 1ff4df56846d10379939166713bb2908e6a5ee0e Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Fri, 23 Sep 2011 14:19:48 -0700 Subject: usbcore: check device's LPM capability Check device's LPM capability by examining the bmAttibutes field of the USB2.0 Extension Descriptor. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 10 ++++++++-- include/linux/usb.h | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7a2514322bfd..4ffc3d1bd9e7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3083,8 +3083,14 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, goto fail; } - if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) - usb_get_bos_descriptor(udev); + if (udev->wusb == 0 && le16_to_cpu(udev->descriptor.bcdUSB) >= 0x0201) { + retval = usb_get_bos_descriptor(udev); + if (!retval) { + if (udev->bos->ext_cap && (USB_LPM_SUPPORT & + le32_to_cpu(udev->bos->ext_cap->bmAttributes))) + udev->lpm_capable = 1; + } + } retval = 0; /* notify HCD that we have a device connected and addressed */ diff --git a/include/linux/usb.h b/include/linux/usb.h index 90ab9dc1f080..1d00d9bc5d65 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -410,6 +410,7 @@ struct usb_tt; * FIXME -- complete doc * @authenticated: Crypto authentication passed * @wusb: device is Wireless USB + * @lpm_capable: device supports LPM * @string_langid: language ID for strings * @product: iProduct string, if present (static) * @manufacturer: iManufacturer string, if present (static) @@ -472,6 +473,7 @@ struct usb_device { unsigned authorized:1; unsigned authenticated:1; unsigned wusb:1; + unsigned lpm_capable:1; int string_langid; /* static strings from the device */ -- cgit v1.2.3 From 65580b4321eb36f16ae8b5987bfa1bb948fc5112 Mon Sep 17 00:00:00 2001 From: Andiry Xu Date: Fri, 23 Sep 2011 14:19:52 -0700 Subject: xHCI: set USB2 hardware LPM If the device pass the USB2 software LPM and the host supports hardware LPM, enable hardware LPM for the device to let the host decide when to put the link into lower power state. If hardware LPM is enabled for a port and driver wants to put it into suspend, it must first disable hardware LPM, resume the port into U0, and then suspend the port. Signed-off-by: Andiry Xu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 14 +++++++++ drivers/usb/core/hub.c | 9 ++++++ drivers/usb/core/usb.h | 5 +++ drivers/usb/host/xhci-hub.c | 9 ++++++ drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci.c | 74 ++++++++++++++++++++++++++++++++++++++++++++- drivers/usb/host/xhci.h | 4 +++ include/linux/usb.h | 4 +++ include/linux/usb/hcd.h | 1 + 9 files changed, 120 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 14b83f2a4e87..adf5ca8a2396 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1700,6 +1700,20 @@ int usb_runtime_idle(struct device *dev) return 0; } +int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) +{ + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + int ret = -EPERM; + + if (hcd->driver->set_usb2_hw_lpm) { + ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable); + if (!ret) + udev->usb2_hw_lpm_enabled = enable; + } + + return ret; +} + #endif /* CONFIG_USB_SUSPEND */ struct bus_type usb_bus_type = { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4ffc3d1bd9e7..d6cc83249341 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2392,6 +2392,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) } } + /* disable USB2 hardware LPM */ + if (udev->usb2_hw_lpm_enabled == 1) + usb_set_usb2_hardware_lpm(udev, 0); + /* see 7.1.7.6 */ if (hub_is_superspeed(hub->hdev)) status = set_port_feature(hub->hdev, @@ -2603,7 +2607,12 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) if (status < 0) { dev_dbg(&udev->dev, "can't resume, status %d\n", status); hub_port_logical_disconnect(hub, port1); + } else { + /* Try to enable USB2 hardware LPM */ + if (udev->usb2_hw_lpm_capable == 1) + usb_set_usb2_hardware_lpm(udev, 1); } + return status; } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 0d023cd2c149..3888778582c4 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -82,6 +82,7 @@ extern int usb_remote_wakeup(struct usb_device *dev); extern int usb_runtime_suspend(struct device *dev); extern int usb_runtime_resume(struct device *dev); extern int usb_runtime_idle(struct device *dev); +extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); #else @@ -96,6 +97,10 @@ static inline int usb_remote_wakeup(struct usb_device *udev) return 0; } +static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) +{ + return 0; +} #endif extern struct bus_type usb_bus_type; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index d7be6d7324d3..9f844d45c667 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -574,10 +574,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case USB_PORT_FEAT_SUSPEND: temp = xhci_readl(xhci, port_array[wIndex]); + if ((temp & PORT_PLS_MASK) != XDEV_U0) { + /* Resume the port to U0 first */ + xhci_set_link_state(xhci, port_array, wIndex, + XDEV_U0); + spin_unlock_irqrestore(&xhci->lock, flags); + msleep(10); + spin_lock_irqsave(&xhci->lock, flags); + } /* In spec software should not attempt to suspend * a port unless the port reports that it is in the * enabled (PED = ‘1’,PLS < ‘3’) state. */ + temp = xhci_readl(xhci, port_array[wIndex]); if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) || (temp & PORT_PLS_MASK) >= XDEV_U3) { xhci_warn(xhci, "USB core suspending device " diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 213a7d73b118..e66e2b03fbbe 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -349,6 +349,7 @@ static const struct hc_driver xhci_pci_hc_driver = { * call back when device connected and addressed */ .update_device = xhci_update_device, + .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, }; /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b0649a4bd315..4648cc0c5721 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -3286,6 +3286,11 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) del_timer_sync(&virt_dev->eps[i].stop_cmd_timer); } + if (udev->usb2_hw_lpm_enabled) { + xhci_set_usb2_hardware_lpm(hcd, udev, 0); + udev->usb2_hw_lpm_enabled = 0; + } + spin_lock_irqsave(&xhci->lock, flags); /* Don't disable the slot if the host controller is dead. */ state = xhci_readl(xhci, &xhci->op_regs->status); @@ -3699,20 +3704,87 @@ finish: return ret; } +int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, + struct usb_device *udev, int enable) +{ + struct xhci_hcd *xhci = hcd_to_xhci(hcd); + __le32 __iomem **port_array; + __le32 __iomem *pm_addr; + u32 temp; + unsigned int port_num; + unsigned long flags; + int u2del, hird; + + if (hcd->speed == HCD_USB3 || !xhci->hw_lpm_support || + !udev->lpm_capable) + return -EPERM; + + if (!udev->parent || udev->parent->parent || + udev->descriptor.bDeviceClass == USB_CLASS_HUB) + return -EPERM; + + if (udev->usb2_hw_lpm_capable != 1) + return -EPERM; + + spin_lock_irqsave(&xhci->lock, flags); + + port_array = xhci->usb2_ports; + port_num = udev->portnum - 1; + pm_addr = port_array[port_num] + 1; + temp = xhci_readl(xhci, pm_addr); + + xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", + enable ? "enable" : "disable", port_num); + + u2del = HCS_U2_LATENCY(xhci->hcs_params3); + if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2)) + hird = xhci_calculate_hird_besl(u2del, 1); + else + hird = xhci_calculate_hird_besl(u2del, 0); + + if (enable) { + temp &= ~PORT_HIRD_MASK; + temp |= PORT_HIRD(hird) | PORT_RWE; + xhci_writel(xhci, temp, pm_addr); + temp = xhci_readl(xhci, pm_addr); + temp |= PORT_HLE; + xhci_writel(xhci, temp, pm_addr); + } else { + temp &= ~(PORT_HLE | PORT_RWE | PORT_HIRD_MASK); + xhci_writel(xhci, temp, pm_addr); + } + + spin_unlock_irqrestore(&xhci->lock, flags); + return 0; +} + int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; ret = xhci_usb2_software_lpm_test(hcd, udev); - if (!ret) + if (!ret) { xhci_dbg(xhci, "software LPM test succeed\n"); + if (xhci->hw_lpm_support == 1) { + udev->usb2_hw_lpm_capable = 1; + ret = xhci_set_usb2_hardware_lpm(hcd, udev, 1); + if (!ret) + udev->usb2_hw_lpm_enabled = 1; + } + } return 0; } #else +int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, + struct usb_device *udev, int enable) +{ + return 0; +} + int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev) { return 0; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index b24c4fce457e..e738466703a5 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -367,7 +367,9 @@ struct xhci_op_regs { #define PORT_L1S_SUCCESS 1 #define PORT_RWE (1 << 3) #define PORT_HIRD(p) (((p) & 0xf) << 4) +#define PORT_HIRD_MASK (0xf << 4) #define PORT_L1DS(p) (((p) & 0xff) << 8) +#define PORT_HLE (1 << 16) /** * struct xhci_intr_reg - Interrupt Register Set @@ -1677,6 +1679,8 @@ int xhci_free_streams(struct usb_hcd *hcd, struct usb_device *udev, gfp_t mem_flags); int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev); +int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, + struct usb_device *udev, int enable); int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, struct usb_tt *tt, gfp_t mem_flags); int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); diff --git a/include/linux/usb.h b/include/linux/usb.h index 1d00d9bc5d65..6f49a1b39fa6 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -411,6 +411,8 @@ struct usb_tt; * @authenticated: Crypto authentication passed * @wusb: device is Wireless USB * @lpm_capable: device supports LPM + * @usb2_hw_lpm_capable: device can perform USB2 hardware LPM + * @usb2_hw_lpm_enabled: USB2 hardware LPM enabled * @string_langid: language ID for strings * @product: iProduct string, if present (static) * @manufacturer: iManufacturer string, if present (static) @@ -474,6 +476,8 @@ struct usb_device { unsigned authenticated:1; unsigned wusb:1; unsigned lpm_capable:1; + unsigned usb2_hw_lpm_capable:1; + unsigned usb2_hw_lpm_enabled:1; int string_langid; /* static strings from the device */ diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 0097136ba45d..a4cd6c58870a 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -343,6 +343,7 @@ struct hc_driver { * address is set */ int (*update_device)(struct usb_hcd *, struct usb_device *); + int (*set_usb2_hw_lpm)(struct usb_hcd *, struct usb_device *, int); }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); -- cgit v1.2.3 From d178bc3a708f39cbfefc3fab37032d3f2511b4ec Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Mon, 26 Sep 2011 10:45:18 -0500 Subject: user namespace: usb: make usb urbs user namespace aware (v2) Add to the dev_state and alloc_async structures the user namespace corresponding to the uid and euid. Pass these to kill_pid_info_as_uid(), which can then implement a proper, user-namespace-aware uid check. Changelog: Sep 20: Per Oleg's suggestion: Instead of caching and passing user namespace, uid, and euid each separately, pass a struct cred. Sep 26: Address Alan Stern's comments: don't define a struct cred at usbdev_open(), and take and put a cred at async_completed() to ensure it lasts for the duration of kill_pid_info_as_cred(). Signed-off-by: Serge Hallyn Cc: Oleg Nesterov Cc: "Eric W. Biederman" Cc: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 30 +++++++++++++----------------- include/linux/sched.h | 3 ++- kernel/signal.c | 24 ++++++++++++++++-------- 3 files changed, 31 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 0ca54e22d319..e3beaf229ee3 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,7 @@ struct dev_state { wait_queue_head_t wait; /* wake up if a request completed */ unsigned int discsignr; struct pid *disc_pid; - uid_t disc_uid, disc_euid; + const struct cred *cred; void __user *disccontext; unsigned long ifclaimed; u32 secid; @@ -79,7 +80,7 @@ struct async { struct list_head asynclist; struct dev_state *ps; struct pid *pid; - uid_t uid, euid; + const struct cred *cred; unsigned int signr; unsigned int ifnum; void __user *userbuffer; @@ -248,6 +249,7 @@ static struct async *alloc_async(unsigned int numisoframes) static void free_async(struct async *as) { put_pid(as->pid); + put_cred(as->cred); kfree(as->urb->transfer_buffer); kfree(as->urb->setup_packet); usb_free_urb(as->urb); @@ -393,9 +395,8 @@ static void async_completed(struct urb *urb) struct dev_state *ps = as->ps; struct siginfo sinfo; struct pid *pid = NULL; - uid_t uid = 0; - uid_t euid = 0; u32 secid = 0; + const struct cred *cred = NULL; int signr; spin_lock(&ps->lock); @@ -408,8 +409,7 @@ static void async_completed(struct urb *urb) sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = as->userurb; pid = get_pid(as->pid); - uid = as->uid; - euid = as->euid; + cred = get_cred(as->cred); secid = as->secid; } snoop(&urb->dev->dev, "urb complete\n"); @@ -423,9 +423,9 @@ static void async_completed(struct urb *urb) spin_unlock(&ps->lock); if (signr) { - kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid, - euid, secid); + kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid); put_pid(pid); + put_cred(cred); } wake_up(&ps->wait); @@ -672,7 +672,6 @@ static int usbdev_open(struct inode *inode, struct file *file) { struct usb_device *dev = NULL; struct dev_state *ps; - const struct cred *cred = current_cred(); int ret; ret = -ENOMEM; @@ -722,8 +721,7 @@ static int usbdev_open(struct inode *inode, struct file *file) init_waitqueue_head(&ps->wait); ps->discsignr = 0; ps->disc_pid = get_pid(task_pid(current)); - ps->disc_uid = cred->uid; - ps->disc_euid = cred->euid; + ps->cred = get_current_cred(); ps->disccontext = NULL; ps->ifclaimed = 0; security_task_getsecid(current, &ps->secid); @@ -765,6 +763,7 @@ static int usbdev_release(struct inode *inode, struct file *file) usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); + put_cred(ps->cred); as = async_getcompleted(ps); while (as) { @@ -1065,7 +1064,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, struct usb_host_endpoint *ep; struct async *as; struct usb_ctrlrequest *dr = NULL; - const struct cred *cred = current_cred(); unsigned int u, totlen, isofrmlen; int ret, ifnum = -1; int is_in; @@ -1279,8 +1277,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, as->signr = uurb->signr; as->ifnum = ifnum; as->pid = get_pid(task_pid(current)); - as->uid = cred->uid; - as->euid = cred->euid; + as->cred = get_current_cred(); security_task_getsecid(current, &as->secid); if (!is_in && uurb->buffer_length > 0) { if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, @@ -1998,9 +1995,8 @@ static void usbdev_remove(struct usb_device *udev) sinfo.si_errno = EPIPE; sinfo.si_code = SI_ASYNCIO; sinfo.si_addr = ps->disccontext; - kill_pid_info_as_uid(ps->discsignr, &sinfo, - ps->disc_pid, ps->disc_uid, - ps->disc_euid, ps->secid); + kill_pid_info_as_cred(ps->discsignr, &sinfo, + ps->disc_pid, ps->cred, ps->secid); } } } diff --git a/include/linux/sched.h b/include/linux/sched.h index 4ac2c0578e0f..57ddb5283d9f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2166,7 +2166,8 @@ extern int force_sigsegv(int, struct task_struct *); extern int force_sig_info(int, struct siginfo *, struct task_struct *); extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp); extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid); -extern int kill_pid_info_as_uid(int, struct siginfo *, struct pid *, uid_t, uid_t, u32); +extern int kill_pid_info_as_cred(int, struct siginfo *, struct pid *, + const struct cred *, u32); extern int kill_pgrp(struct pid *pid, int sig, int priv); extern int kill_pid(struct pid *pid, int sig, int priv); extern int kill_proc_info(int, struct siginfo *, pid_t); diff --git a/kernel/signal.c b/kernel/signal.c index 291c9700be75..d252be2d3de5 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1344,13 +1344,24 @@ int kill_proc_info(int sig, struct siginfo *info, pid_t pid) return error; } +static int kill_as_cred_perm(const struct cred *cred, + struct task_struct *target) +{ + const struct cred *pcred = __task_cred(target); + if (cred->user_ns != pcred->user_ns) + return 0; + if (cred->euid != pcred->suid && cred->euid != pcred->uid && + cred->uid != pcred->suid && cred->uid != pcred->uid) + return 0; + return 1; +} + /* like kill_pid_info(), but doesn't use uid/euid of "current" */ -int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, - uid_t uid, uid_t euid, u32 secid) +int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid, + const struct cred *cred, u32 secid) { int ret = -EINVAL; struct task_struct *p; - const struct cred *pcred; unsigned long flags; if (!valid_signal(sig)) @@ -1362,10 +1373,7 @@ int kill_pid_info_as_uid(int sig, struct siginfo *info, struct pid *pid, ret = -ESRCH; goto out_unlock; } - pcred = __task_cred(p); - if (si_fromuser(info) && - euid != pcred->suid && euid != pcred->uid && - uid != pcred->suid && uid != pcred->uid) { + if (si_fromuser(info) && !kill_as_cred_perm(cred, p)) { ret = -EPERM; goto out_unlock; } @@ -1384,7 +1392,7 @@ out_unlock: rcu_read_unlock(); return ret; } -EXPORT_SYMBOL_GPL(kill_pid_info_as_uid); +EXPORT_SYMBOL_GPL(kill_pid_info_as_cred); /* * kill_something_info() interprets pid in interesting ways just like kill(2). -- cgit v1.2.3 From 276532ba9666b36974cbe16f303fc8be99c9da17 Mon Sep 17 00:00:00 2001 From: Harro Haan Date: Mon, 10 Oct 2011 14:38:27 +0200 Subject: USB: fix ehci alignment error The Kirkwood gave an unaligned memory access error on line 742 of drivers/usb/host/echi-hcd.c: "ehci->last_periodic_enable = ktime_get_real();" Signed-off-by: Harro Haan Cc: stable Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/hcd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index a4cd6c58870a..03354d557b79 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -178,7 +178,7 @@ struct usb_hcd { * this structure. */ unsigned long hcd_priv[0] - __attribute__ ((aligned(sizeof(unsigned long)))); + __attribute__ ((aligned(sizeof(s64)))); }; /* 2.4 does this a bit differently ... */ -- cgit v1.2.3 From b8a56e17e18cca2402b390c10b8d7f3cd0f6265b Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Fri, 30 Sep 2011 20:07:38 +0900 Subject: usb: gadget: r8a66597-udc: add support for SUDMAC SH7757 has a USB function with internal DMA controller (SUDMAC). This patch supports the SUDMAC. The SUDMAC is incompatible with general-purpose DMAC. So, it doesn't use dmaengine. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi --- drivers/usb/gadget/r8a66597-udc.c | 364 ++++++++++++++++++++++++++++++++++++-- drivers/usb/gadget/r8a66597-udc.h | 26 ++- include/linux/usb/r8a66597.h | 60 +++++++ 3 files changed, 430 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 34abb12a88e8..035879b98dd9 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -18,13 +18,14 @@ #include #include #include +#include #include #include #include "r8a66597-udc.h" -#define DRIVER_VERSION "2009-08-18" +#define DRIVER_VERSION "2011-09-26" static const char udc_name[] = "r8a66597_udc"; static const char *r8a66597_ep_name[] = { @@ -184,6 +185,54 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum) } } +static void control_reg_sqset(struct r8a66597 *r8a66597, u16 pipenum) +{ + unsigned long offset; + + pipe_stop(r8a66597, pipenum); + + if (pipenum == 0) { + r8a66597_bset(r8a66597, SQSET, DCPCTR); + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { + offset = get_pipectr_addr(pipenum); + r8a66597_bset(r8a66597, SQSET, offset); + } else { + dev_err(r8a66597_to_dev(r8a66597), + "unexpect pipe num(%d)\n", pipenum); + } +} + +static u16 control_reg_sqmon(struct r8a66597 *r8a66597, u16 pipenum) +{ + unsigned long offset; + + if (pipenum == 0) { + return r8a66597_read(r8a66597, DCPCTR) & SQMON; + } else if (pipenum < R8A66597_MAX_NUM_PIPE) { + offset = get_pipectr_addr(pipenum); + return r8a66597_read(r8a66597, offset) & SQMON; + } else { + dev_err(r8a66597_to_dev(r8a66597), + "unexpect pipe num(%d)\n", pipenum); + } + + return 0; +} + +static u16 save_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum) +{ + return control_reg_sqmon(r8a66597, pipenum); +} + +static void restore_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum, + u16 toggle) +{ + if (toggle) + control_reg_sqset(r8a66597, pipenum); + else + control_reg_sqclr(r8a66597, pipenum); +} + static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum) { u16 tmp; @@ -220,18 +269,51 @@ static inline unsigned short mbw_value(struct r8a66597 *r8a66597) return MBW_16; } +static void r8a66597_change_curpipe(struct r8a66597 *r8a66597, u16 pipenum, + u16 isel, u16 fifosel) +{ + u16 tmp, mask, loop; + int i = 0; + + if (!pipenum) { + mask = ISEL | CURPIPE; + loop = isel; + } else { + mask = CURPIPE; + loop = pipenum; + } + r8a66597_mdfy(r8a66597, loop, mask, fifosel); + + do { + tmp = r8a66597_read(r8a66597, fifosel); + if (i++ > 1000000) { + dev_err(r8a66597_to_dev(r8a66597), + "r8a66597: register%x, loop %x " + "is timeout\n", fifosel, loop); + break; + } + ndelay(1); + } while ((tmp & mask) != loop); +} + static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum) { struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; if (ep->use_dma) - return; + r8a66597_bclr(r8a66597, DREQE, ep->fifosel); r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel); ndelay(450); - r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); + if (r8a66597_is_sudmac(r8a66597) && ep->use_dma) + r8a66597_bclr(r8a66597, mbw_value(r8a66597), ep->fifosel); + else + r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); + + if (ep->use_dma) + r8a66597_bset(r8a66597, DREQE, ep->fifosel); } static int pipe_buffer_setting(struct r8a66597 *r8a66597, @@ -336,9 +418,15 @@ static void r8a66597_ep_setting(struct r8a66597 *r8a66597, ep->fifoaddr = CFIFO; ep->fifosel = CFIFOSEL; ep->fifoctr = CFIFOCTR; - ep->fifotrn = 0; ep->pipectr = get_pipectr_addr(pipenum); + if (is_bulk_pipe(pipenum) || is_isoc_pipe(pipenum)) { + ep->pipetre = get_pipetre_addr(pipenum); + ep->pipetrn = get_pipetrn_addr(pipenum); + } else { + ep->pipetre = 0; + ep->pipetrn = 0; + } ep->pipenum = pipenum; ep->ep.maxpacket = usb_endpoint_maxp(desc); r8a66597->pipenum2ep[pipenum] = ep; @@ -498,6 +586,124 @@ static void start_ep0_write(struct r8a66597_ep *ep, } } +static void disable_fifosel(struct r8a66597 *r8a66597, u16 pipenum, + u16 fifosel) +{ + u16 tmp; + + tmp = r8a66597_read(r8a66597, fifosel) & CURPIPE; + if (tmp == pipenum) + r8a66597_change_curpipe(r8a66597, 0, 0, fifosel); +} + +static void change_bfre_mode(struct r8a66597 *r8a66597, u16 pipenum, + int enable) +{ + struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; + u16 tmp, toggle; + + /* check current BFRE bit */ + r8a66597_write(r8a66597, pipenum, PIPESEL); + tmp = r8a66597_read(r8a66597, PIPECFG) & R8A66597_BFRE; + if ((enable && tmp) || (!enable && !tmp)) + return; + + /* change BFRE bit */ + pipe_stop(r8a66597, pipenum); + disable_fifosel(r8a66597, pipenum, CFIFOSEL); + disable_fifosel(r8a66597, pipenum, D0FIFOSEL); + disable_fifosel(r8a66597, pipenum, D1FIFOSEL); + + toggle = save_usb_toggle(r8a66597, pipenum); + + r8a66597_write(r8a66597, pipenum, PIPESEL); + if (enable) + r8a66597_bset(r8a66597, R8A66597_BFRE, PIPECFG); + else + r8a66597_bclr(r8a66597, R8A66597_BFRE, PIPECFG); + + /* initialize for internal BFRE flag */ + r8a66597_bset(r8a66597, ACLRM, ep->pipectr); + r8a66597_bclr(r8a66597, ACLRM, ep->pipectr); + + restore_usb_toggle(r8a66597, pipenum, toggle); +} + +static int sudmac_alloc_channel(struct r8a66597 *r8a66597, + struct r8a66597_ep *ep, + struct r8a66597_request *req) +{ + struct r8a66597_dma *dma; + + if (!r8a66597_is_sudmac(r8a66597)) + return -ENODEV; + + /* Check transfer type */ + if (!is_bulk_pipe(ep->pipenum)) + return -EIO; + + if (r8a66597->dma.used) + return -EBUSY; + + /* set SUDMAC parameters */ + dma = &r8a66597->dma; + dma->used = 1; + if (ep->desc->bEndpointAddress & USB_DIR_IN) { + dma->dir = 1; + } else { + dma->dir = 0; + change_bfre_mode(r8a66597, ep->pipenum, 1); + } + + /* set r8a66597_ep paramters */ + ep->use_dma = 1; + ep->dma = dma; + ep->fifoaddr = D0FIFO; + ep->fifosel = D0FIFOSEL; + ep->fifoctr = D0FIFOCTR; + + /* dma mapping */ + req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597), + req->req.buf, req->req.length, + dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + + return 0; +} + +static void sudmac_free_channel(struct r8a66597 *r8a66597, + struct r8a66597_ep *ep, + struct r8a66597_request *req) +{ + if (!r8a66597_is_sudmac(r8a66597)) + return; + + dma_unmap_single(r8a66597_to_dev(ep->r8a66597), + req->req.dma, req->req.length, + ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + + r8a66597_bclr(r8a66597, DREQE, ep->fifosel); + r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel); + + ep->dma->used = 0; + ep->use_dma = 0; + ep->fifoaddr = CFIFO; + ep->fifosel = CFIFOSEL; + ep->fifoctr = CFIFOCTR; +} + +static void sudmac_start(struct r8a66597 *r8a66597, struct r8a66597_ep *ep, + struct r8a66597_request *req) +{ + BUG_ON(req->req.length == 0); + + r8a66597_sudmac_write(r8a66597, LBA_WAIT, CH0CFG); + r8a66597_sudmac_write(r8a66597, req->req.dma, CH0BA); + r8a66597_sudmac_write(r8a66597, req->req.length, CH0BBC); + r8a66597_sudmac_write(r8a66597, CH0ENDE, DINTCTRL); + + r8a66597_sudmac_write(r8a66597, DEN, CH0DEN); +} + static void start_packet_write(struct r8a66597_ep *ep, struct r8a66597_request *req) { @@ -508,11 +714,29 @@ static void start_packet_write(struct r8a66597_ep *ep, disable_irq_empty(r8a66597, ep->pipenum); pipe_start(r8a66597, ep->pipenum); - tmp = r8a66597_read(r8a66597, ep->fifoctr); - if (unlikely((tmp & FRDY) == 0)) - pipe_irq_enable(r8a66597, ep->pipenum); - else - irq_packet_write(ep, req); + if (req->req.length == 0) { + transfer_complete(ep, req, 0); + } else { + r8a66597_write(r8a66597, ~(1 << ep->pipenum), BRDYSTS); + if (sudmac_alloc_channel(r8a66597, ep, req) < 0) { + /* PIO mode */ + pipe_change(r8a66597, ep->pipenum); + disable_irq_empty(r8a66597, ep->pipenum); + pipe_start(r8a66597, ep->pipenum); + tmp = r8a66597_read(r8a66597, ep->fifoctr); + if (unlikely((tmp & FRDY) == 0)) + pipe_irq_enable(r8a66597, ep->pipenum); + else + irq_packet_write(ep, req); + } else { + /* DMA mode */ + pipe_change(r8a66597, ep->pipenum); + disable_irq_nrdy(r8a66597, ep->pipenum); + pipe_start(r8a66597, ep->pipenum); + enable_irq_nrdy(r8a66597, ep->pipenum); + sudmac_start(r8a66597, ep, req); + } + } } static void start_packet_read(struct r8a66597_ep *ep, @@ -527,17 +751,26 @@ static void start_packet_read(struct r8a66597_ep *ep, pipe_start(r8a66597, pipenum); pipe_irq_enable(r8a66597, pipenum); } else { - if (ep->use_dma) { - r8a66597_bset(r8a66597, TRCLR, ep->fifosel); - pipe_change(r8a66597, pipenum); - r8a66597_bset(r8a66597, TRENB, ep->fifosel); + pipe_stop(r8a66597, pipenum); + if (ep->pipetre) { + enable_irq_nrdy(r8a66597, pipenum); + r8a66597_write(r8a66597, TRCLR, ep->pipetre); r8a66597_write(r8a66597, - (req->req.length + ep->ep.maxpacket - 1) - / ep->ep.maxpacket, - ep->fifotrn); + DIV_ROUND_UP(req->req.length, ep->ep.maxpacket), + ep->pipetrn); + r8a66597_bset(r8a66597, TRENB, ep->pipetre); + } + + if (sudmac_alloc_channel(r8a66597, ep, req) < 0) { + /* PIO mode */ + change_bfre_mode(r8a66597, ep->pipenum, 0); + pipe_start(r8a66597, pipenum); /* trigger once */ + pipe_irq_enable(r8a66597, pipenum); + } else { + pipe_change(r8a66597, pipenum); + sudmac_start(r8a66597, ep, req); + pipe_start(r8a66597, pipenum); /* trigger once */ } - pipe_start(r8a66597, pipenum); /* trigger once */ - pipe_irq_enable(r8a66597, pipenum); } } @@ -694,6 +927,9 @@ __acquires(r8a66597->lock) if (!list_empty(&ep->queue)) restart = 1; + if (ep->use_dma) + sudmac_free_channel(ep->r8a66597, ep, req); + spin_unlock(&ep->r8a66597->lock); req->req.complete(&ep->ep, &req->req); spin_lock(&ep->r8a66597->lock); @@ -1170,6 +1406,65 @@ __acquires(r8a66597->lock) } } +static void sudmac_finish(struct r8a66597 *r8a66597, struct r8a66597_ep *ep) +{ + u16 pipenum; + struct r8a66597_request *req; + u32 len; + int i = 0; + + pipenum = ep->pipenum; + pipe_change(r8a66597, pipenum); + + while (!(r8a66597_read(r8a66597, ep->fifoctr) & FRDY)) { + udelay(1); + if (unlikely(i++ >= 10000)) { /* timeout = 10 msec */ + dev_err(r8a66597_to_dev(r8a66597), + "%s: FRDY was not set (%d)\n", + __func__, pipenum); + return; + } + } + + r8a66597_bset(r8a66597, BCLR, ep->fifoctr); + req = get_request_from_ep(ep); + + /* prepare parameters */ + len = r8a66597_sudmac_read(r8a66597, CH0CBC); + req->req.actual += len; + + /* clear */ + r8a66597_sudmac_write(r8a66597, CH0STCLR, DSTSCLR); + + /* check transfer finish */ + if ((!req->req.zero && (req->req.actual == req->req.length)) + || (len % ep->ep.maxpacket)) { + if (ep->dma->dir) { + disable_irq_ready(r8a66597, pipenum); + enable_irq_empty(r8a66597, pipenum); + } else { + /* Clear the interrupt flag for next transfer */ + r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); + transfer_complete(ep, req, 0); + } + } +} + +static void r8a66597_sudmac_irq(struct r8a66597 *r8a66597) +{ + u32 irqsts; + struct r8a66597_ep *ep; + u16 pipenum; + + irqsts = r8a66597_sudmac_read(r8a66597, DINTSTS); + if (irqsts & CH0ENDS) { + r8a66597_sudmac_write(r8a66597, CH0ENDC, DINTSTSCLR); + pipenum = (r8a66597_read(r8a66597, D0FIFOSEL) & CURPIPE); + ep = r8a66597->pipenum2ep[pipenum]; + sudmac_finish(r8a66597, ep); + } +} + static irqreturn_t r8a66597_irq(int irq, void *_r8a66597) { struct r8a66597 *r8a66597 = _r8a66597; @@ -1180,6 +1475,9 @@ static irqreturn_t r8a66597_irq(int irq, void *_r8a66597) u16 savepipe; u16 mask0; + if (r8a66597_is_sudmac(r8a66597)) + r8a66597_sudmac_irq(r8a66597); + spin_lock(&r8a66597->lock); intsts0 = r8a66597_read(r8a66597, INTSTS0); @@ -1556,6 +1854,8 @@ static int __exit r8a66597_remove(struct platform_device *pdev) usb_del_gadget_udc(&r8a66597->gadget); del_timer_sync(&r8a66597->timer); iounmap(r8a66597->reg); + if (r8a66597->pdata->sudmac) + iounmap(r8a66597->sudmac_reg); free_irq(platform_get_irq(pdev, 0), r8a66597); r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); #ifdef CONFIG_HAVE_CLK @@ -1572,6 +1872,26 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r) { } +static int __init r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597, + struct platform_device *pdev) +{ + struct resource *res; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac"); + if (!res) { + dev_err(&pdev->dev, "platform_get_resource error(sudmac).\n"); + return -ENODEV; + } + + r8a66597->sudmac_reg = ioremap(res->start, resource_size(res)); + if (r8a66597->sudmac_reg == NULL) { + dev_err(&pdev->dev, "ioremap error(sudmac).\n"); + return -ENOMEM; + } + + return 0; +} + static int __init r8a66597_probe(struct platform_device *pdev) { #ifdef CONFIG_HAVE_CLK @@ -1649,6 +1969,11 @@ static int __init r8a66597_probe(struct platform_device *pdev) clk_enable(r8a66597->clk); } #endif + if (r8a66597->pdata->sudmac) { + ret = r8a66597_sudmac_ioremap(r8a66597, pdev); + if (ret < 0) + goto clean_up2; + } disable_controller(r8a66597); /* make sure controller is disabled */ @@ -1681,7 +2006,6 @@ static int __init r8a66597_probe(struct platform_device *pdev) r8a66597->ep[0].fifoaddr = CFIFO; r8a66597->ep[0].fifosel = CFIFOSEL; r8a66597->ep[0].fifoctr = CFIFOCTR; - r8a66597->ep[0].fifotrn = 0; r8a66597->ep[0].pipectr = get_pipectr_addr(0); r8a66597->pipenum2ep[0] = &r8a66597->ep[0]; r8a66597->epaddr2ep[0] = &r8a66597->ep[0]; @@ -1714,6 +2038,8 @@ clean_up2: #endif clean_up: if (r8a66597) { + if (r8a66597->sudmac_reg) + iounmap(r8a66597->sudmac_reg); if (r8a66597->ep0_req) r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req); diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index 832ee59c8e45..8e3de61cd4b8 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -43,6 +43,7 @@ ((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \ (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC))) +#define r8a66597_is_sudmac(r8a66597) (r8a66597->pdata->sudmac) struct r8a66597_pipe_info { u16 pipe; u16 epnum; @@ -60,6 +61,7 @@ struct r8a66597_request { struct r8a66597_ep { struct usb_ep ep; struct r8a66597 *r8a66597; + struct r8a66597_dma *dma; struct list_head queue; unsigned busy:1; @@ -75,13 +77,20 @@ struct r8a66597_ep { unsigned char fifoaddr; unsigned char fifosel; unsigned char fifoctr; - unsigned char fifotrn; unsigned char pipectr; + unsigned char pipetre; + unsigned char pipetrn; +}; + +struct r8a66597_dma { + unsigned used:1; + unsigned dir:1; /* 1 = IN(write), 0 = OUT(read) */ }; struct r8a66597 { spinlock_t lock; void __iomem *reg; + void __iomem *sudmac_reg; #ifdef CONFIG_HAVE_CLK struct clk *clk; @@ -94,6 +103,7 @@ struct r8a66597 { struct r8a66597_ep ep[R8A66597_MAX_NUM_PIPE]; struct r8a66597_ep *pipenum2ep[R8A66597_MAX_NUM_PIPE]; struct r8a66597_ep *epaddr2ep[16]; + struct r8a66597_dma dma; struct timer_list timer; struct usb_request *ep0_req; /* for internal request */ @@ -251,7 +261,21 @@ static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata) return clock; } +static inline u32 r8a66597_sudmac_read(struct r8a66597 *r8a66597, + unsigned long offset) +{ + return ioread32(r8a66597->sudmac_reg + offset); +} + +static inline void r8a66597_sudmac_write(struct r8a66597 *r8a66597, u32 val, + unsigned long offset) +{ + iowrite32(val, r8a66597->sudmac_reg + offset); +} + #define get_pipectr_addr(pipenum) (PIPE1CTR + (pipenum - 1) * 2) +#define get_pipetre_addr(pipenum) (PIPE1TRE + (pipenum - 1) * 4) +#define get_pipetrn_addr(pipenum) (PIPE1TRN + (pipenum - 1) * 4) #define enable_irq_ready(r8a66597, pipenum) \ enable_pipe_irq(r8a66597, pipenum, BRDYENB) diff --git a/include/linux/usb/r8a66597.h b/include/linux/usb/r8a66597.h index b6b8660d0c68..55805f9dcf21 100644 --- a/include/linux/usb/r8a66597.h +++ b/include/linux/usb/r8a66597.h @@ -48,6 +48,9 @@ struct r8a66597_platdata { /* (external controller only) set one = WR0_N shorted to WR1_N */ unsigned wr0_shorted_to_wr1:1; + + /* set one = using SUDMAC */ + unsigned sudmac:1; }; /* Register definitions */ @@ -417,5 +420,62 @@ struct r8a66597_platdata { #define USBSPD 0x00C0 #define RTPORT 0x0001 +/* SUDMAC registers */ +#define CH0CFG 0x00 +#define CH1CFG 0x04 +#define CH0BA 0x10 +#define CH1BA 0x14 +#define CH0BBC 0x18 +#define CH1BBC 0x1C +#define CH0CA 0x20 +#define CH1CA 0x24 +#define CH0CBC 0x28 +#define CH1CBC 0x2C +#define CH0DEN 0x30 +#define CH1DEN 0x34 +#define DSTSCLR 0x38 +#define DBUFCTRL 0x3C +#define DINTCTRL 0x40 +#define DINTSTS 0x44 +#define DINTSTSCLR 0x48 +#define CH0SHCTRL 0x50 +#define CH1SHCTRL 0x54 + +/* SUDMAC Configuration Registers */ +#define SENDBUFM 0x1000 /* b12: Transmit Buffer Mode */ +#define RCVENDM 0x0100 /* b8: Receive Data Transfer End Mode */ +#define LBA_WAIT 0x0030 /* b5-4: Local Bus Access Wait */ + +/* DMA Enable Registers */ +#define DEN 0x0001 /* b1: DMA Transfer Enable */ + +/* DMA Status Clear Register */ +#define CH1STCLR 0x0002 /* b2: Ch1 DMA Status Clear */ +#define CH0STCLR 0x0001 /* b1: Ch0 DMA Status Clear */ + +/* DMA Buffer Control Register */ +#define CH1BUFW 0x0200 /* b9: Ch1 DMA Buffer Data Transfer Enable */ +#define CH0BUFW 0x0100 /* b8: Ch0 DMA Buffer Data Transfer Enable */ +#define CH1BUFS 0x0002 /* b2: Ch1 DMA Buffer Data Status */ +#define CH0BUFS 0x0001 /* b1: Ch0 DMA Buffer Data Status */ + +/* DMA Interrupt Control Register */ +#define CH1ERRE 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Enable */ +#define CH0ERRE 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Enable */ +#define CH1ENDE 0x0002 /* b2: Ch1 DMA Transfer End Int Enable */ +#define CH0ENDE 0x0001 /* b1: Ch0 DMA Transfer End Int Enable */ + +/* DMA Interrupt Status Register */ +#define CH1ERRS 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Status */ +#define CH0ERRS 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Status */ +#define CH1ENDS 0x0002 /* b2: Ch1 DMA Transfer End Int Status */ +#define CH0ENDS 0x0001 /* b1: Ch0 DMA Transfer End Int Status */ + +/* DMA Interrupt Status Clear Register */ +#define CH1ERRC 0x0200 /* b9: Ch1 SHwy Res Err Detect Int Stat Clear */ +#define CH0ERRC 0x0100 /* b8: Ch0 SHwy Res Err Detect Int Stat Clear */ +#define CH1ENDC 0x0002 /* b2: Ch1 DMA Transfer End Int Stat Clear */ +#define CH0ENDC 0x0001 /* b1: Ch0 DMA Transfer End Int Stat Clear */ + #endif /* __LINUX_USB_R8A66597_H */ -- cgit v1.2.3 From 089b837a39552ee49a4ea4c188e8c3517473f10c Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 10 Oct 2011 09:43:44 +0300 Subject: usb: gadget: fix typo for default U1/U2 exit latencies s/DEFULT/DEFAULT/, no functional changes. Signed-off-by: Felipe Balbi --- drivers/usb/gadget/composite.c | 4 ++-- include/linux/usb/gadget.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index e74fd55c33d9..8a5529d214fb 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -542,9 +542,9 @@ static int bos_desc(struct usb_composite_dev *cdev) if (cdev->gadget->ops->get_config_params) cdev->gadget->ops->get_config_params(&dcd_config_params); else { - dcd_config_params.bU1devExitLat = USB_DEFULT_U1_DEV_EXIT_LAT; + dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT; dcd_config_params.bU2DevExitLat = - cpu_to_le16(USB_DEFULT_U2_DEV_EXIT_LAT); + cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); } ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 087f4b931833..1d3a67523ffc 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -437,9 +437,9 @@ static inline void usb_ep_fifo_flush(struct usb_ep *ep) struct usb_dcd_config_params { __u8 bU1devExitLat; /* U1 Device exit Latency */ -#define USB_DEFULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ +#define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ __le16 bU2DevExitLat; /* U2 Device exit Latency */ -#define USB_DEFULT_U2_DEV_EXIT_LAT 0x1F4 /* Less then 500 microsec */ +#define USB_DEFAULT_U2_DEV_EXIT_LAT 0x1F4 /* Less then 500 microsec */ }; -- cgit v1.2.3 From 11935de5579a5d01b3c89d69b4fc7a38b4dd8eae Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:01:28 -0700 Subject: usb: gadget: renesas_usbhs: change usbhsc_bus_ctrl() to usbsc_set_buswait() renesas_usbhs will have register DVSTCTR control function for HOST support. This patch changes usbhsc_bus_ctrl() to usbsc_set_buswait(), to remove DVSTCTR access from it, Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/common.c | 15 +++++---------- include/linux/usb/renesas_usbhs.h | 2 ++ 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 319ed47153d7..fd43fdd6cd81 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -149,17 +149,13 @@ int usbhs_frame_get_num(struct usbhs_priv *priv) /* * local functions */ -static void usbhsc_bus_ctrl(struct usbhs_priv *priv, int enable) +static void usbhsc_set_buswait(struct usbhs_priv *priv) { int wait = usbhs_get_dparam(priv, buswait_bwait); - u16 data = 0; - if (enable) { - /* set bus wait if platform have */ - if (wait) - usbhs_bset(priv, BUSWAIT, 0x000F, wait); - } - usbhs_write(priv, DVSTCTR, data); + /* set bus wait if platform have */ + if (wait) + usbhs_bset(priv, BUSWAIT, 0x000F, wait); } /* @@ -191,10 +187,9 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable) /* USB on */ usbhs_sys_clock_ctrl(priv, enable); - usbhsc_bus_ctrl(priv, enable); + usbhsc_set_buswait(priv); } else { /* USB off */ - usbhsc_bus_ctrl(priv, enable); usbhs_sys_clock_ctrl(priv, enable); /* disable PM */ diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 8977431259c6..959af02d3af6 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -101,6 +101,8 @@ struct renesas_usbhs_driver_param { * option: * * for BUSWAIT :: BWAIT + * see + * renesas_usbhs/common.c :: usbhsc_set_buswait() * */ int buswait_bwait; -- cgit v1.2.3 From 258485d9904703c4cb3a2b3ee38fe2a0cbf01f48 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:01:40 -0700 Subject: usb: gadget: renesas_usbhs: add bus control functions this patch add DVSTCTR control function for HOST support Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- drivers/usb/renesas_usbhs/common.c | 35 ++++++++++++++++++++++++++++++++++- drivers/usb/renesas_usbhs/common.h | 9 +++++++++ include/linux/usb/renesas_usbhs.h | 7 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index fd43fdd6cd81..243512d93e58 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -146,6 +146,33 @@ int usbhs_frame_get_num(struct usbhs_priv *priv) return usbhs_read(priv, FRMNUM) & FRNM_MASK; } +/* + * bus/vbus functions + */ +void usbhs_bus_send_sof_enable(struct usbhs_priv *priv) +{ + usbhs_bset(priv, DVSTCTR, (USBRST | UACT), UACT); +} + +void usbhs_bus_send_reset(struct usbhs_priv *priv) +{ + usbhs_bset(priv, DVSTCTR, (USBRST | UACT), USBRST); +} + +int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable) +{ + struct platform_device *pdev = usbhs_priv_to_pdev(priv); + + return usbhs_platform_call(priv, set_vbus, pdev, enable); +} + +static void usbhsc_bus_init(struct usbhs_priv *priv) +{ + usbhs_write(priv, DVSTCTR, 0); + + usbhs_vbus_ctrl(priv, 0); +} + /* * local functions */ @@ -187,7 +214,6 @@ static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable) /* USB on */ usbhs_sys_clock_ctrl(priv, enable); - usbhsc_set_buswait(priv); } else { /* USB off */ usbhs_sys_clock_ctrl(priv, enable); @@ -229,6 +255,10 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, enable); + /* bus init */ + usbhsc_set_buswait(priv); + usbhsc_bus_init(priv); + /* module start */ usbhs_mod_call(priv, start, priv); @@ -238,6 +268,9 @@ static void usbhsc_hotplug(struct usbhs_priv *priv) /* module stop */ usbhs_mod_call(priv, stop, priv); + /* bus init */ + usbhsc_bus_init(priv); + /* power off */ if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) usbhsc_power_ctrl(priv, enable); diff --git a/drivers/usb/renesas_usbhs/common.h b/drivers/usb/renesas_usbhs/common.h index b410463a1212..54b5924baae7 100644 --- a/drivers/usb/renesas_usbhs/common.h +++ b/drivers/usb/renesas_usbhs/common.h @@ -102,6 +102,8 @@ struct usbhs_priv; /* DVSTCTR */ #define EXTLP (1 << 10) /* Controls the EXTLP pin output state */ #define PWEN (1 << 9) /* Controls the PWEN pin output state */ +#define USBRST (1 << 6) /* Bus Reset Output */ +#define UACT (1 << 4) /* USB Bus Enable */ #define RHST (0x7) /* Reset Handshake */ #define RHST_LOW_SPEED 1 /* Low-speed connection */ #define RHST_FULL_SPEED 2 /* Full-speed connection */ @@ -257,6 +259,13 @@ void usbhs_sys_usb_ctrl(struct usbhs_priv *priv, int enable); void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable); void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable); +/* + * bus + */ +void usbhs_bus_send_sof_enable(struct usbhs_priv *priv); +void usbhs_bus_send_reset(struct usbhs_priv *priv); +int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable); + /* * frame */ diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 959af02d3af6..040d8bb2b5a2 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -82,6 +82,13 @@ struct renesas_usbhs_platform_callback { * get VBUS status function. */ int (*get_vbus)(struct platform_device *pdev); + + /* + * option: + * + * VBUS control is needed for Host + */ + int (*set_vbus)(struct platform_device *pdev, int enable); }; /* -- cgit v1.2.3 From f427eb64f4c5433a91da5eb139970dd5cbad9082 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Oct 2011 22:06:12 -0700 Subject: usb: gadget: renesas_usbhs: support otg pin control some renesas_usbhs device is supporting OTG external device interface. In that device, it is necessary to control PWEN/EXTLP on DVSTCTR. This patch support it. But renesas_usbhs driver doesn't have OTG support for now. Signed-off-by: Kuninori Morimoto Signed-off-by: Felipe Balbi --- arch/arm/mach-shmobile/board-mackerel.c | 1 + drivers/usb/renesas_usbhs/common.c | 4 ++++ include/linux/usb/renesas_usbhs.h | 5 +++++ 3 files changed, 10 insertions(+) (limited to 'include') diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 0ea71f8d4b89..c20612ea5d0e 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -808,6 +808,7 @@ static struct usbhs_private usbhs1_private = { }, .driver_param = { .buswait_bwait = 4, + .has_otg = 1, .pipe_type = usbhs1_pipe_cfg, .pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg), }, diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index b327458f5cad..1161d78e1665 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -114,6 +114,10 @@ void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable) { u16 mask = DCFM | DRPD | DPRPU; u16 val = DCFM | DRPD; + int has_otg = usbhs_get_dparam(priv, has_otg); + + if (has_otg) + usbhs_bset(priv, DVSTCTR, (EXTLP | PWEN), (EXTLP | PWEN)); /* * if enable diff --git a/include/linux/usb/renesas_usbhs.h b/include/linux/usb/renesas_usbhs.h index 040d8bb2b5a2..e5a40c318548 100644 --- a/include/linux/usb/renesas_usbhs.h +++ b/include/linux/usb/renesas_usbhs.h @@ -136,6 +136,11 @@ struct renesas_usbhs_driver_param { * pio <--> dma border. */ int pio_dma_border; /* default is 64byte */ + + /* + * option: + */ + u32 has_otg:1; /* for controlling PWEN/EXTLP */ }; /* -- cgit v1.2.3 From dde34cc5019b51088c18ca789d4b1a20cf9bc617 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Wed, 12 Oct 2011 16:49:24 +0800 Subject: usb: gadget: mv_udc: refine the driver structure This patch do the following things: 1. Add header and Copyright for marvell usb driver. 2. Add mv_usb.h in include/linux/platform_data, make the driver fits all the marvell platform using the same ChipIdea usb ip. 3. Some SOC may has mutiple clock sources, so let me define it in mv_usb_platform_data and give two helper functions named udc_clock_enable/udc_clock_disable to deal with the clocks. 4. Different SOCs will have some difference in PHY initialization, so we will remove file mv_udc_phy.c and add two funtions in mv_usb_platform_data, let the platform relative driver to realize it. 5. Rewrite probe function according to the modification list above. Find it will kernel panic when probe failed. The root cause is as follows: When probe failed, the error handle may call device_unregister() which in return will call gadget_release.In current code, gadget_release have two issues: 1: the_controller is a NULL pointer. 2: if we free udc here, then the following code in probe will access NULL pointer. Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi --- drivers/usb/gadget/Makefile | 2 +- drivers/usb/gadget/mv_udc.h | 17 ++- drivers/usb/gadget/mv_udc_core.c | 158 +++++++++++++++++++------- drivers/usb/gadget/mv_udc_phy.c | 214 ----------------------------------- include/linux/platform_data/mv_usb.h | 50 ++++++++ 5 files changed, 182 insertions(+), 259 deletions(-) delete mode 100644 drivers/usb/gadget/mv_udc_phy.c create mode 100644 include/linux/platform_data/mv_usb.h (limited to 'include') diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 9ba725af4a08..c36da63009db 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -28,7 +28,7 @@ obj-$(CONFIG_USB_S3C_HSUDC) += s3c-hsudc.o obj-$(CONFIG_USB_LANGWELL) += langwell_udc.o obj-$(CONFIG_USB_EG20T) += pch_udc.o obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o -mv_udc-y := mv_udc_core.o mv_udc_phy.o +mv_udc-y := mv_udc_core.o obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/mv_udc.h index 65f1f7c3bd4e..d3d26454b8bb 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/mv_udc.h @@ -1,3 +1,11 @@ +/* + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ #ifndef __MV_UDC_H #define __MV_UDC_H @@ -201,7 +209,12 @@ struct mv_udc { remote_wakeup:1, softconnected:1, force_fs:1; - struct clk *clk; + + struct mv_usb_platform_data *pdata; + + /* some SOC has mutiple clock sources for USB*/ + unsigned int clknum; + struct clk *clk[0]; }; /* endpoint data structure */ @@ -289,6 +302,4 @@ struct mv_dtd { struct mv_dtd *next_dtd_virt; }; -extern int mv_udc_phy_init(unsigned int base); - #endif diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 0d0e9e39f8b2..40a25e75cc6a 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1,3 +1,14 @@ +/* + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. + * Author: Chao Xie + * Neil Zhang + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + #include #include #include @@ -22,6 +33,7 @@ #include #include #include +#include #include #include @@ -45,6 +57,8 @@ #define LOOPS_USEC (1 << LOOPS_USEC_SHIFT) #define LOOPS(timeout) ((timeout) >> LOOPS_USEC_SHIFT) +static DECLARE_COMPLETION(release_done); + static const char driver_name[] = "mv_udc"; static const char driver_desc[] = DRIVER_DESC; @@ -987,6 +1001,22 @@ static struct usb_ep_ops mv_ep_ops = { .fifo_flush = mv_ep_fifo_flush, /* flush fifo */ }; +static void udc_clock_enable(struct mv_udc *udc) +{ + unsigned int i; + + for (i = 0; i < udc->clknum; i++) + clk_enable(udc->clk[i]); +} + +static void udc_clock_disable(struct mv_udc *udc) +{ + unsigned int i; + + for (i = 0; i < udc->clknum; i++) + clk_disable(udc->clk[i]); +} + static void udc_stop(struct mv_udc *udc) { u32 tmp; @@ -1877,18 +1907,15 @@ static void gadget_release(struct device *_dev) struct mv_udc *udc = the_controller; complete(udc->done); - kfree(udc); } static int mv_udc_remove(struct platform_device *dev) { struct mv_udc *udc = the_controller; - DECLARE_COMPLETION(done); + int clk_i; usb_del_gadget_udc(&udc->gadget); - udc->done = &done; - /* free memory allocated in probe */ if (udc->dtd_pool) dma_pool_destroy(udc->dtd_pool); @@ -1915,10 +1942,14 @@ static int mv_udc_remove(struct platform_device *dev) kfree(udc->status_req); } + for (clk_i = 0; clk_i <= udc->clknum; clk_i++) + clk_put(udc->clk[clk_i]); + device_unregister(&udc->gadget.dev); /* free dev, wait for the release() finished */ - wait_for_completion(&done); + wait_for_completion(udc->done); + kfree(udc); the_controller = NULL; @@ -1927,33 +1958,46 @@ static int mv_udc_remove(struct platform_device *dev) int mv_udc_probe(struct platform_device *dev) { + struct mv_usb_platform_data *pdata = dev->dev.platform_data; struct mv_udc *udc; int retval = 0; + int clk_i = 0; struct resource *r; size_t size; - udc = kzalloc(sizeof *udc, GFP_KERNEL); + if (pdata == NULL) { + dev_err(&dev->dev, "missing platform_data\n"); + return -ENODEV; + } + + size = sizeof(*udc) + sizeof(struct clk *) * pdata->clknum; + udc = kzalloc(size, GFP_KERNEL); if (udc == NULL) { dev_err(&dev->dev, "failed to allocate memory for udc\n"); - retval = -ENOMEM; - goto error; + return -ENOMEM; } + the_controller = udc; + udc->done = &release_done; + udc->pdata = dev->dev.platform_data; spin_lock_init(&udc->lock); udc->dev = dev; - udc->clk = clk_get(&dev->dev, "U2OCLK"); - if (IS_ERR(udc->clk)) { - retval = PTR_ERR(udc->clk); - goto error; + udc->clknum = pdata->clknum; + for (clk_i = 0; clk_i < udc->clknum; clk_i++) { + udc->clk[clk_i] = clk_get(&dev->dev, pdata->clkname[clk_i]); + if (IS_ERR(udc->clk[clk_i])) { + retval = PTR_ERR(udc->clk[clk_i]); + goto err_put_clk; + } } - r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "u2o"); + r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "capregs"); if (r == NULL) { dev_err(&dev->dev, "no I/O memory resource defined\n"); retval = -ENODEV; - goto error; + goto err_put_clk; } udc->cap_regs = (struct mv_cap_regs __iomem *) @@ -1961,29 +2005,31 @@ int mv_udc_probe(struct platform_device *dev) if (udc->cap_regs == NULL) { dev_err(&dev->dev, "failed to map I/O memory\n"); retval = -EBUSY; - goto error; + goto err_put_clk; } - r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "u2ophy"); + r = platform_get_resource_byname(udc->dev, IORESOURCE_MEM, "phyregs"); if (r == NULL) { dev_err(&dev->dev, "no phy I/O memory resource defined\n"); retval = -ENODEV; - goto error; + goto err_iounmap_capreg; } udc->phy_regs = (unsigned int)ioremap(r->start, resource_size(r)); if (udc->phy_regs == 0) { dev_err(&dev->dev, "failed to map phy I/O memory\n"); retval = -EBUSY; - goto error; + goto err_iounmap_capreg; } /* we will acces controller register, so enable the clk */ - clk_enable(udc->clk); - retval = mv_udc_phy_init(udc->phy_regs); - if (retval) { - dev_err(&dev->dev, "phy initialization error %d\n", retval); - goto error; + udc_clock_enable(udc); + if (pdata->phy_init) { + retval = pdata->phy_init(udc->phy_regs); + if (retval) { + dev_err(&dev->dev, "phy init error %d\n", retval); + goto err_iounmap_phyreg; + } } udc->op_regs = (struct mv_op_regs __iomem *)((u32)udc->cap_regs @@ -1999,7 +2045,7 @@ int mv_udc_probe(struct platform_device *dev) if (udc->ep_dqh == NULL) { dev_err(&dev->dev, "allocate dQH memory failed\n"); retval = -ENOMEM; - goto error; + goto err_disable_clock; } udc->ep_dqh_size = size; @@ -2012,7 +2058,7 @@ int mv_udc_probe(struct platform_device *dev) if (!udc->dtd_pool) { retval = -ENOMEM; - goto error; + goto err_free_dma; } size = udc->max_eps * sizeof(struct mv_ep) *2; @@ -2020,7 +2066,7 @@ int mv_udc_probe(struct platform_device *dev) if (udc->eps == NULL) { dev_err(&dev->dev, "allocate ep memory failed\n"); retval = -ENOMEM; - goto error; + goto err_destroy_dma; } /* initialize ep0 status request structure */ @@ -2028,7 +2074,7 @@ int mv_udc_probe(struct platform_device *dev) if (!udc->status_req) { dev_err(&dev->dev, "allocate status_req memory failed\n"); retval = -ENOMEM; - goto error; + goto err_free_eps; } INIT_LIST_HEAD(&udc->status_req->queue); @@ -2045,7 +2091,7 @@ int mv_udc_probe(struct platform_device *dev) if (r == NULL) { dev_err(&dev->dev, "no IRQ resource defined\n"); retval = -ENODEV; - goto error; + goto err_free_status_req; } udc->irq = r->start; if (request_irq(udc->irq, mv_udc_irq, @@ -2053,7 +2099,7 @@ int mv_udc_probe(struct platform_device *dev) dev_err(&dev->dev, "Request irq %d for UDC failed\n", udc->irq); retval = -ENODEV; - goto error; + goto err_free_status_req; } /* initialize gadget structure */ @@ -2072,18 +2118,43 @@ int mv_udc_probe(struct platform_device *dev) retval = device_register(&udc->gadget.dev); if (retval) - goto error; + goto err_free_irq; eps_init(udc); - the_controller = udc; - retval = usb_add_gadget_udc(&dev->dev, &udc->gadget); - if (!retval) - return retval; -error: - if (udc) - mv_udc_remove(udc->dev); + if (retval) + goto err_unregister; + + return 0; + +err_unregister: + device_unregister(&udc->gadget.dev); +err_free_irq: + free_irq(udc->irq, &dev->dev); +err_free_status_req: + kfree(udc->status_req->req.buf); + kfree(udc->status_req); +err_free_eps: + kfree(udc->eps); +err_destroy_dma: + dma_pool_destroy(udc->dtd_pool); +err_free_dma: + dma_free_coherent(&dev->dev, udc->ep_dqh_size, + udc->ep_dqh, udc->ep_dqh_dma); +err_disable_clock: + if (udc->pdata->phy_deinit) + udc->pdata->phy_deinit(udc->phy_regs); + udc_clock_disable(udc); +err_iounmap_phyreg: + iounmap((void *)udc->phy_regs); +err_iounmap_capreg: + iounmap(udc->cap_regs); +err_put_clk: + for (clk_i--; clk_i >= 0; clk_i--) + clk_put(udc->clk[clk_i]); + the_controller = NULL; + kfree(udc); return retval; } @@ -2102,11 +2173,16 @@ static int mv_udc_resume(struct device *_dev) struct mv_udc *udc = the_controller; int retval; - retval = mv_udc_phy_init(udc->phy_regs); - if (retval) { - dev_err(_dev, "phy initialization error %d\n", retval); - return retval; + if (udc->pdata->phy_init) { + retval = udc->pdata->phy_init(udc->phy_regs); + if (retval) { + dev_err(&udc->dev->dev, + "init phy error %d when resume back\n", + retval); + return retval; + } } + udc_reset(udc); ep0_reset(udc); udc_start(udc); diff --git a/drivers/usb/gadget/mv_udc_phy.c b/drivers/usb/gadget/mv_udc_phy.c deleted file mode 100644 index d4dea97e38a5..000000000000 --- a/drivers/usb/gadget/mv_udc_phy.c +++ /dev/null @@ -1,214 +0,0 @@ -#include -#include -#include -#include - -#include - -#ifdef CONFIG_ARCH_MMP - -#define UTMI_REVISION 0x0 -#define UTMI_CTRL 0x4 -#define UTMI_PLL 0x8 -#define UTMI_TX 0xc -#define UTMI_RX 0x10 -#define UTMI_IVREF 0x14 -#define UTMI_T0 0x18 -#define UTMI_T1 0x1c -#define UTMI_T2 0x20 -#define UTMI_T3 0x24 -#define UTMI_T4 0x28 -#define UTMI_T5 0x2c -#define UTMI_RESERVE 0x30 -#define UTMI_USB_INT 0x34 -#define UTMI_DBG_CTL 0x38 -#define UTMI_OTG_ADDON 0x3c - -/* For UTMICTRL Register */ -#define UTMI_CTRL_USB_CLK_EN (1 << 31) -/* pxa168 */ -#define UTMI_CTRL_SUSPEND_SET1 (1 << 30) -#define UTMI_CTRL_SUSPEND_SET2 (1 << 29) -#define UTMI_CTRL_RXBUF_PDWN (1 << 24) -#define UTMI_CTRL_TXBUF_PDWN (1 << 11) - -#define UTMI_CTRL_INPKT_DELAY_SHIFT 30 -#define UTMI_CTRL_INPKT_DELAY_SOF_SHIFT 28 -#define UTMI_CTRL_PU_REF_SHIFT 20 -#define UTMI_CTRL_ARC_PULLDN_SHIFT 12 -#define UTMI_CTRL_PLL_PWR_UP_SHIFT 1 -#define UTMI_CTRL_PWR_UP_SHIFT 0 -/* For UTMI_PLL Register */ -#define UTMI_PLL_CLK_BLK_EN_SHIFT 24 -#define UTMI_PLL_FBDIV_SHIFT 4 -#define UTMI_PLL_REFDIV_SHIFT 0 -#define UTMI_PLL_FBDIV_MASK 0x00000FF0 -#define UTMI_PLL_REFDIV_MASK 0x0000000F -#define UTMI_PLL_ICP_MASK 0x00007000 -#define UTMI_PLL_KVCO_MASK 0x00031000 -#define UTMI_PLL_PLLCALI12_SHIFT 29 -#define UTMI_PLL_PLLCALI12_MASK (0x3 << 29) -#define UTMI_PLL_PLLVDD18_SHIFT 27 -#define UTMI_PLL_PLLVDD18_MASK (0x3 << 27) -#define UTMI_PLL_PLLVDD12_SHIFT 25 -#define UTMI_PLL_PLLVDD12_MASK (0x3 << 25) -#define UTMI_PLL_KVCO_SHIFT 15 -#define UTMI_PLL_ICP_SHIFT 12 -/* For UTMI_TX Register */ -#define UTMI_TX_REG_EXT_FS_RCAL_SHIFT 27 -#define UTMI_TX_REG_EXT_FS_RCAL_MASK (0xf << 27) -#define UTMI_TX_REG_EXT_FS_RCAL_EN_MASK 26 -#define UTMI_TX_REG_EXT_FS_RCAL_EN (0x1 << 26) -#define UTMI_TX_LOW_VDD_EN_SHIFT 11 -#define UTMI_TX_IMPCAL_VTH_SHIFT 14 -#define UTMI_TX_IMPCAL_VTH_MASK (0x7 << 14) -#define UTMI_TX_CK60_PHSEL_SHIFT 17 -#define UTMI_TX_CK60_PHSEL_MASK (0xf << 17) -#define UTMI_TX_TXVDD12_SHIFT 22 -#define UTMI_TX_TXVDD12_MASK (0x3 << 22) -#define UTMI_TX_AMP_SHIFT 0 -#define UTMI_TX_AMP_MASK (0x7 << 0) -/* For UTMI_RX Register */ -#define UTMI_RX_SQ_THRESH_SHIFT 4 -#define UTMI_RX_SQ_THRESH_MASK (0xf << 4) -#define UTMI_REG_SQ_LENGTH_SHIFT 15 -#define UTMI_REG_SQ_LENGTH_MASK (0x3 << 15) - -#define REG_RCAL_START 0x00001000 -#define VCOCAL_START 0x00200000 -#define KVCO_EXT 0x00400000 -#define PLL_READY 0x00800000 -#define CLK_BLK_EN 0x01000000 -#endif - -static unsigned int u2o_read(unsigned int base, unsigned int offset) -{ - return readl(base + offset); -} - -static void u2o_set(unsigned int base, unsigned int offset, unsigned int value) -{ - unsigned int reg; - - reg = readl(base + offset); - reg |= value; - writel(reg, base + offset); - readl(base + offset); -} - -static void u2o_clear(unsigned int base, unsigned int offset, - unsigned int value) -{ - unsigned int reg; - - reg = readl(base + offset); - reg &= ~value; - writel(reg, base + offset); - readl(base + offset); -} - -static void u2o_write(unsigned int base, unsigned int offset, - unsigned int value) -{ - writel(value, base + offset); - readl(base + offset); -} - -#ifdef CONFIG_ARCH_MMP -int mv_udc_phy_init(unsigned int base) -{ - unsigned long timeout; - - /* Initialize the USB PHY power */ - if (cpu_is_pxa910()) { - u2o_set(base, UTMI_CTRL, (1 << UTMI_CTRL_INPKT_DELAY_SOF_SHIFT) - | (1 << UTMI_CTRL_PU_REF_SHIFT)); - } - - u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PLL_PWR_UP_SHIFT); - u2o_set(base, UTMI_CTRL, 1 << UTMI_CTRL_PWR_UP_SHIFT); - - /* UTMI_PLL settings */ - u2o_clear(base, UTMI_PLL, UTMI_PLL_PLLVDD18_MASK - | UTMI_PLL_PLLVDD12_MASK | UTMI_PLL_PLLCALI12_MASK - | UTMI_PLL_FBDIV_MASK | UTMI_PLL_REFDIV_MASK - | UTMI_PLL_ICP_MASK | UTMI_PLL_KVCO_MASK); - - u2o_set(base, UTMI_PLL, (0xee << UTMI_PLL_FBDIV_SHIFT) - | (0xb << UTMI_PLL_REFDIV_SHIFT) - | (3 << UTMI_PLL_PLLVDD18_SHIFT) - | (3 << UTMI_PLL_PLLVDD12_SHIFT) - | (3 << UTMI_PLL_PLLCALI12_SHIFT) - | (1 << UTMI_PLL_ICP_SHIFT) | (3 << UTMI_PLL_KVCO_SHIFT)); - - /* UTMI_TX */ - u2o_clear(base, UTMI_TX, UTMI_TX_REG_EXT_FS_RCAL_EN_MASK - | UTMI_TX_TXVDD12_MASK - | UTMI_TX_CK60_PHSEL_MASK | UTMI_TX_IMPCAL_VTH_MASK - | UTMI_TX_REG_EXT_FS_RCAL_MASK | UTMI_TX_AMP_MASK); - u2o_set(base, UTMI_TX, (3 << UTMI_TX_TXVDD12_SHIFT) - | (4 << UTMI_TX_CK60_PHSEL_SHIFT) - | (4 << UTMI_TX_IMPCAL_VTH_SHIFT) - | (8 << UTMI_TX_REG_EXT_FS_RCAL_SHIFT) - | (3 << UTMI_TX_AMP_SHIFT)); - - /* UTMI_RX */ - u2o_clear(base, UTMI_RX, UTMI_RX_SQ_THRESH_MASK - | UTMI_REG_SQ_LENGTH_MASK); - if (cpu_is_pxa168()) - u2o_set(base, UTMI_RX, (7 << UTMI_RX_SQ_THRESH_SHIFT) - | (2 << UTMI_REG_SQ_LENGTH_SHIFT)); - else - u2o_set(base, UTMI_RX, (0x7 << UTMI_RX_SQ_THRESH_SHIFT) - | (2 << UTMI_REG_SQ_LENGTH_SHIFT)); - - /* UTMI_IVREF */ - if (cpu_is_pxa168()) - /* - * fixing Microsoft Altair board interface with NEC hub issue - - * Set UTMI_IVREF from 0x4a3 to 0x4bf - */ - u2o_write(base, UTMI_IVREF, 0x4bf); - - /* calibrate */ - timeout = jiffies + 100; - while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) { - if (time_after(jiffies, timeout)) - return -ETIME; - cpu_relax(); - } - - /* toggle VCOCAL_START bit of UTMI_PLL */ - udelay(200); - u2o_set(base, UTMI_PLL, VCOCAL_START); - udelay(40); - u2o_clear(base, UTMI_PLL, VCOCAL_START); - - /* toggle REG_RCAL_START bit of UTMI_TX */ - udelay(200); - u2o_set(base, UTMI_TX, REG_RCAL_START); - udelay(40); - u2o_clear(base, UTMI_TX, REG_RCAL_START); - udelay(200); - - /* make sure phy is ready */ - timeout = jiffies + 100; - while ((u2o_read(base, UTMI_PLL) & PLL_READY) == 0) { - if (time_after(jiffies, timeout)) - return -ETIME; - cpu_relax(); - } - - if (cpu_is_pxa168()) { - u2o_set(base, UTMI_RESERVE, 1 << 5); - /* Turn on UTMI PHY OTG extension */ - u2o_write(base, UTMI_OTG_ADDON, 1); - } - return 0; -} -#else -int mv_udc_phy_init(unsigned int base) -{ - return 0; -} -#endif diff --git a/include/linux/platform_data/mv_usb.h b/include/linux/platform_data/mv_usb.h new file mode 100644 index 000000000000..e9d9149ddf38 --- /dev/null +++ b/include/linux/platform_data/mv_usb.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#ifndef __MV_PLATFORM_USB_H +#define __MV_PLATFORM_USB_H + +enum pxa_ehci_type { + EHCI_UNDEFINED = 0, + PXA_U2OEHCI, /* pxa 168, 9xx */ + PXA_SPH, /* pxa 168, 9xx SPH */ + MMP3_HSIC, /* mmp3 hsic */ + MMP3_FSIC, /* mmp3 fsic */ +}; + +enum { + MV_USB_MODE_OTG, + MV_USB_MODE_HOST, +}; + +enum { + VBUS_LOW = 0, + VBUS_HIGH = 1 << 0, +}; + +struct mv_usb_addon_irq { + unsigned int irq; + int (*poll)(void); +}; + +struct mv_usb_platform_data { + unsigned int clknum; + char **clkname; + struct mv_usb_addon_irq *id; /* Only valid for OTG. ID pin change*/ + struct mv_usb_addon_irq *vbus; /* valid for OTG/UDC. VBUS change*/ + + /* only valid for HCD. OTG or Host only*/ + unsigned int mode; + + int (*phy_init)(unsigned int regbase); + void (*phy_deinit)(unsigned int regbase); + int (*set_vbus)(unsigned int vbus); +}; + +#endif -- cgit v1.2.3