diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-07-15 12:41:29 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2010-07-15 12:41:29 +1000 |
commit | 516c5bb5a0d2e8744f42d5ed8956e18385210663 (patch) | |
tree | 2df21b515785a589407530c133af2a2c3c738f83 /drivers | |
parent | c9248bc4d914e3283601c3267b64682de6ac7dfe (diff) | |
parent | b9e0f0e917461425ea17308ecc3d7d02961b2b30 (diff) |
Merge branch 'quilt/usb'
Conflicts:
drivers/media/video/uvc/uvcvideo.h
include/linux/usb/video.h
Diffstat (limited to 'drivers')
88 files changed, 1518 insertions, 1392 deletions
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 47b20e7e3786..af000f67181d 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -196,24 +196,6 @@ struct uvc_device; /* TODO: Put the most frequently accessed fields at the beginning of * structures to maximize cache efficiency. */ -struct uvc_streaming_control { - __u16 bmHint; - __u8 bFormatIndex; - __u8 bFrameIndex; - __u32 dwFrameInterval; - __u16 wKeyFrameRate; - __u16 wPFrameRate; - __u16 wCompQuality; - __u16 wCompWindowSize; - __u16 wDelay; - __u32 dwMaxVideoFrameSize; - __u32 dwMaxPayloadTransferSize; - __u32 dwClockFrequency; - __u8 bmFramingInfo; - __u8 bPreferedVersion; - __u8 bMinVersion; - __u8 bMaxVersion; -}; struct uvc_control_info { struct list_head list; diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index be5d8db98165..0574d848b900 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c @@ -215,7 +215,7 @@ static int vhci_hub_status(struct usb_hcd *hcd, char *buf) vhci = hcd_to_vhci(hcd); spin_lock_irqsave(&vhci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { usbip_dbg_vhci_rh("hw accessible flag in on?\n"); goto done; } @@ -269,7 +269,7 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u32 prev_port_status[VHCI_NPORTS]; - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) return -ETIMEDOUT; /* @@ -1041,7 +1041,7 @@ static int vhci_bus_resume(struct usb_hcd *hcd) dev_dbg(&hcd->self.root_hub->dev, "%s\n", __func__); spin_lock_irq(&vhci->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { rc = -ESHUTDOWN; } else { /* vhci->rh_state = DUMMY_RH_RUNNING; diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 80b4008c89ba..239f050efa35 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ -obj-y += early/ +obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 101ffc965ee0..593fc5e2d2e6 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -564,7 +564,7 @@ static void cxacru_timeout_kill(unsigned long data) } static int cxacru_start_wait_urb(struct urb *urb, struct completion *done, - int* actual_length) + int *actual_length) { struct timer_list timer; @@ -952,7 +952,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, put_unaligned(cpu_to_le32(addr), (__le32 *)(buf + offb)); offb += 4; addr += l; - if(l) + if (l) memcpy(buf + offb, data + offd, l); if (l < stride) memset(buf + offb + l, 0, stride - l); @@ -967,7 +967,7 @@ static int cxacru_fw(struct usb_device *usb_dev, enum cxacru_fw_request fw, } offb = 0; } - } while(offd < size); + } while (offd < size); dbg("sent fw %#x", fw); ret = 0; @@ -1043,8 +1043,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, if (instance->modem_type->boot_rom_patch) { val = cpu_to_le32(BR_ADDR); ret = cxacru_fw(usb_dev, FW_WRITE_MEM, 0x2, 0x0, BR_STACK_ADDR, (u8 *) &val, 4); - } - else { + } else { ret = cxacru_fw(usb_dev, FW_GOTO_MEM, 0x0, 0x0, FW_ADDR, NULL, 0); } if (ret) { @@ -1068,7 +1067,7 @@ static void cxacru_upload_firmware(struct cxacru_data *instance, } static int cxacru_find_firmware(struct cxacru_data *instance, - char* phase, const struct firmware **fw_p) + char *phase, const struct firmware **fw_p) { struct usbatm_data *usbatm = instance->usbatm; struct device *dev = &usbatm->usb_intf->dev; diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c index 80f9617d3a15..4716e707de59 100644 --- a/drivers/usb/atm/speedtch.c +++ b/drivers/usb/atm/speedtch.c @@ -753,11 +753,13 @@ static struct usb_driver speedtch_usb_driver = { .id_table = speedtch_usb_ids }; -static void speedtch_release_interfaces(struct usb_device *usb_dev, int num_interfaces) { +static void speedtch_release_interfaces(struct usb_device *usb_dev, + int num_interfaces) +{ struct usb_interface *cur_intf; int i; - for(i = 0; i < num_interfaces; i++) + for (i = 0; i < num_interfaces; i++) if ((cur_intf = usb_ifnum_to_if(usb_dev, i))) { usb_set_intfdata(cur_intf, NULL); usb_driver_release_interface(&speedtch_usb_driver, cur_intf); @@ -792,7 +794,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, /* claim all interfaces */ - for (i=0; i < num_interfaces; i++) { + for (i = 0; i < num_interfaces; i++) { cur_intf = usb_ifnum_to_if(usb_dev, i); if ((i != ifnum) && cur_intf) { @@ -842,7 +844,7 @@ static int speedtch_bind(struct usbatm_data *usbatm, use_isoc = 0; /* fall back to bulk if endpoint not found */ - for (i=0; i<desc->desc.bNumEndpoints; i++) { + for (i = 0; i < desc->desc.bNumEndpoints; i++) { const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; if ((endpoint_desc->bEndpointAddress == target_address)) { diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index 0d6b5209747a..ea071a5b6eee 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -67,6 +67,7 @@ #include <linux/mutex.h> #include <linux/freezer.h> #include <linux/slab.h> +#include <linux/kernel.h> #include <asm/unaligned.h> @@ -2438,7 +2439,6 @@ UEA_ATTR(firmid, 0); /* Retrieve the device End System Identifier (MAC) */ -#define htoi(x) (isdigit(x) ? x-'0' : toupper(x)-'A'+10) static int uea_getesi(struct uea_softc *sc, u_char * esi) { unsigned char mac_str[2 * ETH_ALEN + 1]; @@ -2449,7 +2449,8 @@ static int uea_getesi(struct uea_softc *sc, u_char * esi) return 1; for (i = 0; i < ETH_ALEN; i++) - esi[i] = htoi(mac_str[2 * i]) * 16 + htoi(mac_str[2 * i + 1]); + esi[i] = hex_to_bin(mac_str[2 * i]) * 16 + + hex_to_bin(mac_str[2 * i + 1]); return 0; } diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index 9b53e8df4648..05bf5a27b5b0 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -84,8 +84,8 @@ #ifdef VERBOSE_DEBUG static int usbatm_print_packet(const unsigned char *data, int len); -#define PACKETDEBUG(arg...) usbatm_print_packet (arg) -#define vdbg(arg...) dbg (arg) +#define PACKETDEBUG(arg...) usbatm_print_packet(arg) +#define vdbg(arg...) dbg(arg) #else #define PACKETDEBUG(arg...) #define vdbg(arg...) @@ -273,8 +273,7 @@ static void usbatm_complete(struct urb *urb) if (unlikely(status) && (!(channel->usbatm->flags & UDSL_IGNORE_EILSEQ) || - status != -EILSEQ )) - { + status != -EILSEQ)) { if (status == -ESHUTDOWN) return; @@ -494,7 +493,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, ptr += data_len; __skb_pull(skb, data_len); - if(!left) + if (!left) continue; memset(ptr, 0, left); @@ -506,7 +505,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, trailer[2] = ctrl->len >> 8; trailer[3] = ctrl->len; - ctrl->crc = ~ crc32_be(ctrl->crc, ptr, left - 4); + ctrl->crc = ~crc32_be(ctrl->crc, ptr, left - 4); trailer[4] = ctrl->crc >> 24; trailer[5] = ctrl->crc >> 16; @@ -516,8 +515,7 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, target[3] |= 0x2; /* adjust PTI */ ctrl->len = 0; /* tag this skb finished */ - } - else + } else ctrl->crc = crc32_be(ctrl->crc, ptr, left); } @@ -1146,7 +1144,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out); /* tx buffer size must be a positive multiple of the stride */ - instance->tx_channel.buf_size = max (instance->tx_channel.stride, + instance->tx_channel.buf_size = max(instance->tx_channel.stride, snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride)); /* rx buffer size must be a positive multiple of the endpoint maxpacket */ @@ -1159,7 +1157,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, goto fail_unbind; } - num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ + num_packets = max(1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */ if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE) num_packets--; @@ -1262,7 +1260,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, usb_free_urb(instance->urbs[i]); } - kfree (instance); + kfree(instance); return error; } @@ -1390,9 +1388,8 @@ static int usbatm_print_packet(const unsigned char *data, int len) for (i = 0; i < len;) { buffer[0] = '\0'; sprintf(buffer, "%.3d :", i); - for (j = 0; (j < 16) && (i < len); j++, i++) { + for (j = 0; (j < 16) && (i < len); j++, i++) sprintf(buffer, "%s %2.2x", buffer, data[i]); - } dbg("%s", buffer); } return i; diff --git a/drivers/usb/atm/usbatm.h b/drivers/usb/atm/usbatm.h index 0863f85fcc26..5fc489405217 100644 --- a/drivers/usb/atm/usbatm.h +++ b/drivers/usb/atm/usbatm.h @@ -48,7 +48,7 @@ dev_warn(&(instance)->usb_intf->dev, \ "failed assertion '%s' at line %d", \ __stringify(x), __LINE__); \ - } while(0) + } while (0) #endif #define usb_err(instance, format, arg...) \ @@ -59,7 +59,7 @@ dev_warn(&(instance)->usb_intf->dev , format , ## arg) #ifdef DEBUG #define usb_dbg(instance, format, arg...) \ - dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) + dev_printk(KERN_DEBUG , &(instance)->usb_intf->dev , format , ## arg) #else #define usb_dbg(instance, format, arg...) \ do {} while (0) @@ -104,21 +104,21 @@ struct usbatm_data; /* * Assuming all methods exist and succeed, they are called in this order: * -* bind, heavy_init, atm_start, ..., atm_stop, unbind +* bind, heavy_init, atm_start, ..., atm_stop, unbind */ struct usbatm_driver { const char *driver_name; /* init device ... can sleep, or cause probe() failure */ - int (*bind) (struct usbatm_data *, struct usb_interface *, + int (*bind) (struct usbatm_data *, struct usb_interface *, const struct usb_device_id *id); /* additional device initialization that is too slow to be done in probe() */ - int (*heavy_init) (struct usbatm_data *, struct usb_interface *); + int (*heavy_init) (struct usbatm_data *, struct usb_interface *); /* cleanup device ... can sleep, but can't fail */ - void (*unbind) (struct usbatm_data *, struct usb_interface *); + void (*unbind) (struct usbatm_data *, struct usb_interface *); /* init ATM device ... can sleep, or cause ATM initialization failure */ int (*atm_start) (struct usbatm_data *, struct atm_dev *); @@ -126,9 +126,9 @@ struct usbatm_driver { /* cleanup ATM device ... can sleep, but can't fail */ void (*atm_stop) (struct usbatm_data *, struct atm_dev *); - int bulk_in; /* bulk rx endpoint */ - int isoc_in; /* isochronous rx endpoint */ - int bulk_out; /* bulk tx endpoint */ + int bulk_in; /* bulk rx endpoint */ + int isoc_in; /* isochronous rx endpoint */ + int bulk_out; /* bulk tx endpoint */ unsigned rx_padding; unsigned tx_padding; @@ -156,7 +156,7 @@ struct usbatm_channel { struct usbatm_data { /****************** * public fields * - ******************/ + ******************/ /* mini driver */ struct usbatm_driver *driver; @@ -174,7 +174,7 @@ struct usbatm_data { /******************************** * private fields - do not use * - ********************************/ + ********************************/ struct kref refcount; struct mutex serialize; diff --git a/drivers/usb/atm/xusbatm.c b/drivers/usb/atm/xusbatm.c index 17d167bbd2dc..48ee0c5ff282 100644 --- a/drivers/usb/atm/xusbatm.c +++ b/drivers/usb/atm/xusbatm.c @@ -49,13 +49,13 @@ static struct usbatm_driver xusbatm_drivers[XUSBATM_DRIVERS_MAX]; static struct usb_device_id xusbatm_usb_ids[XUSBATM_DRIVERS_MAX + 1]; static struct usb_driver xusbatm_usb_driver; -static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int altsetting, u8 ep) +static struct usb_interface *xusbatm_find_intf(struct usb_device *usb_dev, int altsetting, u8 ep) { struct usb_host_interface *alt; struct usb_interface *intf; int i, j; - for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) + for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) if ((intf = usb_dev->actconfig->interface[i]) && (alt = usb_altnum_to_altsetting(intf, altsetting))) for (j = 0; j < alt->desc.bNumEndpoints; j++) if (alt->endpoint[j].desc.bEndpointAddress == ep) @@ -63,7 +63,7 @@ static struct usb_interface *xusbatm_find_intf (struct usb_device *usb_dev, int return NULL; } -static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device *usb_dev, +static int xusbatm_capture_intf(struct usbatm_data *usbatm, struct usb_device *usb_dev, struct usb_interface *intf, int altsetting, int claim) { int ifnum = intf->altsetting->desc.bInterfaceNumber; @@ -80,7 +80,7 @@ static int xusbatm_capture_intf (struct usbatm_data *usbatm, struct usb_device * return 0; } -static void xusbatm_release_intf (struct usb_device *usb_dev, struct usb_interface *intf, int claimed) +static void xusbatm_release_intf(struct usb_device *usb_dev, struct usb_interface *intf, int claimed) { if (claimed) { usb_set_intfdata(intf, NULL); @@ -147,7 +147,7 @@ static void xusbatm_unbind(struct usbatm_data *usbatm, usb_dbg(usbatm, "%s entered\n", __func__); - for(i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { + for (i = 0; i < usb_dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *cur_intf = usb_dev->actconfig->interface[i]; if (cur_intf && (usb_get_intfdata(cur_intf) == usbatm)) { diff --git a/drivers/usb/c67x00/c67x00-hcd.c b/drivers/usb/c67x00/c67x00-hcd.c index a22b887f4e9e..d3e1356d091e 100644 --- a/drivers/usb/c67x00/c67x00-hcd.c +++ b/drivers/usb/c67x00/c67x00-hcd.c @@ -264,7 +264,7 @@ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg) if (unlikely(hcd->state == HC_STATE_HALT)) return; - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) return; /* Handle Start of frame events */ @@ -282,7 +282,7 @@ static int c67x00_hcd_start(struct usb_hcd *hcd) { hcd->uses_new_polling = 1; hcd->state = HC_STATE_RUNNING; - hcd->poll_rh = 1; + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); return 0; } diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 2250095db0a0..74759df84926 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -135,7 +135,7 @@ MFG:HEWLETT-PACKARD;MDL:DESKJET 970C;CMD:MLC,PCL,PML;CLASS:PRINTER;DESCRIPTION:H * ->lock locks what interrupt accesses. */ struct usblp { - struct usb_device *dev; /* USB device */ + struct usb_device *dev; /* USB device */ struct mutex wmut; struct mutex mut; spinlock_t lock; /* locks rcomplete, wcomplete */ @@ -169,7 +169,8 @@ struct usblp { }; #ifdef DEBUG -static void usblp_dump(struct usblp *usblp) { +static void usblp_dump(struct usblp *usblp) +{ int p; dbg("usblp=0x%p", usblp); @@ -216,8 +217,8 @@ static const struct quirk_printer_struct quirk_printers[] = { { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */ { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */ { 0x03f0, 0x0504, USBLP_QUIRK_BIDIR }, /* HP DeskJet 885C */ - { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */ - { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */ + { 0x03f0, 0x0604, USBLP_QUIRK_BIDIR }, /* HP DeskJet 840C */ + { 0x03f0, 0x0804, USBLP_QUIRK_BIDIR }, /* HP DeskJet 816C */ { 0x03f0, 0x1104, USBLP_QUIRK_BIDIR }, /* HP Deskjet 959C */ { 0x0409, 0xefbe, USBLP_QUIRK_BIDIR }, /* NEC Picty900 (HP OEM) */ { 0x0409, 0xbef4, USBLP_QUIRK_BIDIR }, /* NEC Picty760 (HP OEM) */ @@ -254,9 +255,8 @@ static int usblp_ctrl_msg(struct usblp *usblp, int request, int type, int dir, i /* High byte has the interface index. Low byte has the alternate setting. */ - if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) { - index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting; - } + if ((request == USBLP_REQ_GET_ID) && (type == USB_TYPE_CLASS)) + index = (usblp->ifnum<<8)|usblp->protocol[usblp->current_protocol].alt_setting; retval = usb_control_msg(usblp->dev, dir ? usb_rcvctrlpipe(usblp->dev, 0) : usb_sndctrlpipe(usblp->dev, 0), @@ -372,7 +372,7 @@ static int usblp_check_status(struct usblp *usblp, int err) return newerr; } -static int handle_bidir (struct usblp *usblp) +static int handle_bidir(struct usblp *usblp) { if (usblp->bidir && usblp->used) { if (usblp_submit_read(usblp) < 0) @@ -395,14 +395,13 @@ static int usblp_open(struct inode *inode, struct file *file) if (minor < 0) return -ENODEV; - mutex_lock (&usblp_mutex); + mutex_lock(&usblp_mutex); retval = -ENODEV; intf = usb_find_interface(&usblp_driver, minor); - if (!intf) { + if (!intf) goto out; - } - usblp = usb_get_intfdata (intf); + usblp = usb_get_intfdata(intf); if (!usblp || !usblp->dev || !usblp->present) goto out; @@ -433,18 +432,18 @@ static int usblp_open(struct inode *inode, struct file *file) retval = -EIO; } out: - mutex_unlock (&usblp_mutex); + mutex_unlock(&usblp_mutex); return retval; } -static void usblp_cleanup (struct usblp *usblp) +static void usblp_cleanup(struct usblp *usblp) { printk(KERN_INFO "usblp%d: removed\n", usblp->minor); kfree(usblp->readbuf); - kfree (usblp->device_id_string); - kfree (usblp->statusbuf); - kfree (usblp); + kfree(usblp->device_id_string); + kfree(usblp->statusbuf); + kfree(usblp); } static void usblp_unlink_urbs(struct usblp *usblp) @@ -458,14 +457,14 @@ static int usblp_release(struct inode *inode, struct file *file) usblp->flags &= ~LP_ABORT; - mutex_lock (&usblp_mutex); + mutex_lock(&usblp_mutex); usblp->used = 0; if (usblp->present) { usblp_unlink_urbs(usblp); usb_autopm_put_interface(usblp->intf); - } else /* finish cleanup from disconnect */ - usblp_cleanup (usblp); - mutex_unlock (&usblp_mutex); + } else /* finish cleanup from disconnect */ + usblp_cleanup(usblp); + mutex_unlock(&usblp_mutex); return 0; } @@ -495,190 +494,190 @@ static long usblp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) int twoints[2]; int retval = 0; - mutex_lock (&usblp->mut); + mutex_lock(&usblp->mut); if (!usblp->present) { retval = -ENODEV; goto done; } dbg("usblp_ioctl: cmd=0x%x (%c nr=%d len=%d dir=%d)", cmd, _IOC_TYPE(cmd), - _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd) ); + _IOC_NR(cmd), _IOC_SIZE(cmd), _IOC_DIR(cmd)); if (_IOC_TYPE(cmd) == 'P') /* new-style ioctl number */ switch (_IOC_NR(cmd)) { - case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ - if (_IOC_DIR(cmd) != _IOC_READ) { - retval = -EINVAL; - goto done; - } + case IOCNR_GET_DEVICE_ID: /* get the DEVICE_ID string */ + if (_IOC_DIR(cmd) != _IOC_READ) { + retval = -EINVAL; + goto done; + } - length = usblp_cache_device_id_string(usblp); - if (length < 0) { - retval = length; - goto done; - } - if (length > _IOC_SIZE(cmd)) - length = _IOC_SIZE(cmd); /* truncate */ - - if (copy_to_user((void __user *) arg, - usblp->device_id_string, - (unsigned long) length)) { - retval = -EFAULT; - goto done; - } + length = usblp_cache_device_id_string(usblp); + if (length < 0) { + retval = length; + goto done; + } + if (length > _IOC_SIZE(cmd)) + length = _IOC_SIZE(cmd); /* truncate */ + + if (copy_to_user((void __user *) arg, + usblp->device_id_string, + (unsigned long) length)) { + retval = -EFAULT; + goto done; + } - break; + break; - case IOCNR_GET_PROTOCOLS: - if (_IOC_DIR(cmd) != _IOC_READ || - _IOC_SIZE(cmd) < sizeof(twoints)) { - retval = -EINVAL; - goto done; - } + case IOCNR_GET_PROTOCOLS: + if (_IOC_DIR(cmd) != _IOC_READ || + _IOC_SIZE(cmd) < sizeof(twoints)) { + retval = -EINVAL; + goto done; + } - twoints[0] = usblp->current_protocol; - twoints[1] = 0; - for (i = USBLP_FIRST_PROTOCOL; - i <= USBLP_LAST_PROTOCOL; i++) { - if (usblp->protocol[i].alt_setting >= 0) - twoints[1] |= (1<<i); - } + twoints[0] = usblp->current_protocol; + twoints[1] = 0; + for (i = USBLP_FIRST_PROTOCOL; + i <= USBLP_LAST_PROTOCOL; i++) { + if (usblp->protocol[i].alt_setting >= 0) + twoints[1] |= (1<<i); + } - if (copy_to_user((void __user *)arg, - (unsigned char *)twoints, - sizeof(twoints))) { - retval = -EFAULT; - goto done; - } + if (copy_to_user((void __user *)arg, + (unsigned char *)twoints, + sizeof(twoints))) { + retval = -EFAULT; + goto done; + } - break; + break; - case IOCNR_SET_PROTOCOL: - if (_IOC_DIR(cmd) != _IOC_WRITE) { - retval = -EINVAL; - goto done; - } + case IOCNR_SET_PROTOCOL: + if (_IOC_DIR(cmd) != _IOC_WRITE) { + retval = -EINVAL; + goto done; + } #ifdef DEBUG - if (arg == -10) { - usblp_dump(usblp); - break; - } + if (arg == -10) { + usblp_dump(usblp); + break; + } #endif - usblp_unlink_urbs(usblp); - retval = usblp_set_protocol(usblp, arg); - if (retval < 0) { - usblp_set_protocol(usblp, - usblp->current_protocol); - } - break; + usblp_unlink_urbs(usblp); + retval = usblp_set_protocol(usblp, arg); + if (retval < 0) { + usblp_set_protocol(usblp, + usblp->current_protocol); + } + break; - case IOCNR_HP_SET_CHANNEL: - if (_IOC_DIR(cmd) != _IOC_WRITE || - le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 || - usblp->quirks & USBLP_QUIRK_BIDIR) { - retval = -EINVAL; - goto done; - } + case IOCNR_HP_SET_CHANNEL: + if (_IOC_DIR(cmd) != _IOC_WRITE || + le16_to_cpu(usblp->dev->descriptor.idVendor) != 0x03F0 || + usblp->quirks & USBLP_QUIRK_BIDIR) { + retval = -EINVAL; + goto done; + } - err = usblp_hp_channel_change_request(usblp, - arg, &newChannel); - if (err < 0) { - dev_err(&usblp->dev->dev, - "usblp%d: error = %d setting " - "HP channel\n", - usblp->minor, err); - retval = -EIO; - goto done; - } + err = usblp_hp_channel_change_request(usblp, + arg, &newChannel); + if (err < 0) { + dev_err(&usblp->dev->dev, + "usblp%d: error = %d setting " + "HP channel\n", + usblp->minor, err); + retval = -EIO; + goto done; + } - dbg("usblp%d requested/got HP channel %ld/%d", - usblp->minor, arg, newChannel); - break; + dbg("usblp%d requested/got HP channel %ld/%d", + usblp->minor, arg, newChannel); + break; - case IOCNR_GET_BUS_ADDRESS: - if (_IOC_DIR(cmd) != _IOC_READ || - _IOC_SIZE(cmd) < sizeof(twoints)) { - retval = -EINVAL; - goto done; - } + case IOCNR_GET_BUS_ADDRESS: + if (_IOC_DIR(cmd) != _IOC_READ || + _IOC_SIZE(cmd) < sizeof(twoints)) { + retval = -EINVAL; + goto done; + } - twoints[0] = usblp->dev->bus->busnum; - twoints[1] = usblp->dev->devnum; - if (copy_to_user((void __user *)arg, - (unsigned char *)twoints, - sizeof(twoints))) { - retval = -EFAULT; - goto done; - } + twoints[0] = usblp->dev->bus->busnum; + twoints[1] = usblp->dev->devnum; + if (copy_to_user((void __user *)arg, + (unsigned char *)twoints, + sizeof(twoints))) { + retval = -EFAULT; + goto done; + } - dbg("usblp%d is bus=%d, device=%d", - usblp->minor, twoints[0], twoints[1]); - break; + dbg("usblp%d is bus=%d, device=%d", + usblp->minor, twoints[0], twoints[1]); + break; - case IOCNR_GET_VID_PID: - if (_IOC_DIR(cmd) != _IOC_READ || - _IOC_SIZE(cmd) < sizeof(twoints)) { - retval = -EINVAL; - goto done; - } + case IOCNR_GET_VID_PID: + if (_IOC_DIR(cmd) != _IOC_READ || + _IOC_SIZE(cmd) < sizeof(twoints)) { + retval = -EINVAL; + goto done; + } - twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor); - twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct); - if (copy_to_user((void __user *)arg, - (unsigned char *)twoints, - sizeof(twoints))) { - retval = -EFAULT; - goto done; - } + twoints[0] = le16_to_cpu(usblp->dev->descriptor.idVendor); + twoints[1] = le16_to_cpu(usblp->dev->descriptor.idProduct); + if (copy_to_user((void __user *)arg, + (unsigned char *)twoints, + sizeof(twoints))) { + retval = -EFAULT; + goto done; + } - dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X", - usblp->minor, twoints[0], twoints[1]); - break; + dbg("usblp%d is VID=0x%4.4X, PID=0x%4.4X", + usblp->minor, twoints[0], twoints[1]); + break; - case IOCNR_SOFT_RESET: - if (_IOC_DIR(cmd) != _IOC_NONE) { - retval = -EINVAL; - goto done; - } - retval = usblp_reset(usblp); - break; - default: - retval = -ENOTTY; + case IOCNR_SOFT_RESET: + if (_IOC_DIR(cmd) != _IOC_NONE) { + retval = -EINVAL; + goto done; + } + retval = usblp_reset(usblp); + break; + default: + retval = -ENOTTY; } else /* old-style ioctl value */ switch (cmd) { - case LPGETSTATUS: - if ((retval = usblp_read_status(usblp, usblp->statusbuf))) { - if (printk_ratelimit()) - printk(KERN_ERR "usblp%d:" - "failed reading printer status (%d)\n", - usblp->minor, retval); - retval = -EIO; - goto done; - } - status = *usblp->statusbuf; - if (copy_to_user ((void __user *)arg, &status, sizeof(int))) - retval = -EFAULT; - break; + case LPGETSTATUS: + if ((retval = usblp_read_status(usblp, usblp->statusbuf))) { + if (printk_ratelimit()) + printk(KERN_ERR "usblp%d:" + "failed reading printer status (%d)\n", + usblp->minor, retval); + retval = -EIO; + goto done; + } + status = *usblp->statusbuf; + if (copy_to_user((void __user *)arg, &status, sizeof(int))) + retval = -EFAULT; + break; - case LPABORT: - if (arg) - usblp->flags |= LP_ABORT; - else - usblp->flags &= ~LP_ABORT; - break; + case LPABORT: + if (arg) + usblp->flags |= LP_ABORT; + else + usblp->flags &= ~LP_ABORT; + break; - default: - retval = -ENOTTY; + default: + retval = -ENOTTY; } done: - mutex_unlock (&usblp->mut); + mutex_unlock(&usblp->mut); return retval; } @@ -840,7 +839,7 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, lo } done: - mutex_unlock (&usblp->mut); + mutex_unlock(&usblp->mut); return count; } @@ -1023,7 +1022,7 @@ raise_urb: * while you are sending print data, and you don't try to query the * printer status every couple of milliseconds, you will probably be OK. */ -static unsigned int usblp_quirks (__u16 vendor, __u16 product) +static unsigned int usblp_quirks(__u16 vendor, __u16 product) { int i; @@ -1031,7 +1030,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product) if (vendor == quirk_printers[i].vendorId && product == quirk_printers[i].productId) return quirk_printers[i].quirks; - } + } return 0; } @@ -1061,7 +1060,7 @@ static struct usb_class_driver usblp_class = { static ssize_t usblp_show_ieee1284_id(struct device *dev, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(dev); - struct usblp *usblp = usb_get_intfdata (intf); + struct usblp *usblp = usb_get_intfdata(intf); if (usblp->device_id_string[0] == 0 && usblp->device_id_string[1] == 0) @@ -1075,7 +1074,7 @@ static DEVICE_ATTR(ieee1284_id, S_IRUGO, usblp_show_ieee1284_id, NULL); static int usblp_probe(struct usb_interface *intf, const struct usb_device_id *id) { - struct usb_device *dev = interface_to_usbdev (intf); + struct usb_device *dev = interface_to_usbdev(intf); struct usblp *usblp; int protocol; int retval; @@ -1089,7 +1088,7 @@ static int usblp_probe(struct usb_interface *intf, } usblp->dev = dev; mutex_init(&usblp->wmut); - mutex_init (&usblp->mut); + mutex_init(&usblp->mut); spin_lock_init(&usblp->lock); init_waitqueue_head(&usblp->rwait); init_waitqueue_head(&usblp->wwait); @@ -1153,7 +1152,7 @@ static int usblp_probe(struct usb_interface *intf, usblp_check_status(usblp, 0); #endif - usb_set_intfdata (intf, usblp); + usb_set_intfdata(intf, usblp); usblp->present = 1; @@ -1177,7 +1176,7 @@ static int usblp_probe(struct usb_interface *intf, return 0; abort_intfdata: - usb_set_intfdata (intf, NULL); + usb_set_intfdata(intf, NULL); device_remove_file(&intf->dev, &dev_attr_ieee1284_id); abort: kfree(usblp->readbuf); @@ -1340,35 +1339,35 @@ static int usblp_cache_device_id_string(struct usblp *usblp) static void usblp_disconnect(struct usb_interface *intf) { - struct usblp *usblp = usb_get_intfdata (intf); + struct usblp *usblp = usb_get_intfdata(intf); usb_deregister_dev(intf, &usblp_class); if (!usblp || !usblp->dev) { dev_err(&intf->dev, "bogus disconnect\n"); - BUG (); + BUG(); } device_remove_file(&intf->dev, &dev_attr_ieee1284_id); - mutex_lock (&usblp_mutex); - mutex_lock (&usblp->mut); + mutex_lock(&usblp_mutex); + mutex_lock(&usblp->mut); usblp->present = 0; wake_up(&usblp->wwait); wake_up(&usblp->rwait); - usb_set_intfdata (intf, NULL); + usb_set_intfdata(intf, NULL); usblp_unlink_urbs(usblp); - mutex_unlock (&usblp->mut); + mutex_unlock(&usblp->mut); if (!usblp->used) - usblp_cleanup (usblp); - mutex_unlock (&usblp_mutex); + usblp_cleanup(usblp); + mutex_unlock(&usblp_mutex); } static int usblp_suspend(struct usb_interface *intf, pm_message_t message) { - struct usblp *usblp = usb_get_intfdata (intf); + struct usblp *usblp = usb_get_intfdata(intf); usblp_unlink_urbs(usblp); #if 0 /* XXX Do we want this? What if someone is reading, should we fail? */ @@ -1382,10 +1381,10 @@ static int usblp_suspend(struct usb_interface *intf, pm_message_t message) static int usblp_resume(struct usb_interface *intf) { - struct usblp *usblp = usb_get_intfdata (intf); + struct usblp *usblp = usb_get_intfdata(intf); int r; - r = handle_bidir (usblp); + r = handle_bidir(usblp); return r; } @@ -1401,7 +1400,7 @@ static const struct usb_device_id usblp_ids[] = { { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, usblp_ids); +MODULE_DEVICE_TABLE(usb, usblp_ids); static struct usb_driver usblp_driver = { .name = "usblp", @@ -1426,8 +1425,8 @@ static void __exit usblp_exit(void) module_init(usblp_init); module_exit(usblp_exit); -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); module_param(proto_bias, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(proto_bias, "Favourite protocol number"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index c2f62a3993d2..f1aaff6202a5 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1668,13 +1668,10 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) default: if (intf->dev.driver) driver = to_usb_driver(intf->dev.driver); - if (driver == NULL || driver->ioctl == NULL) { + if (driver == NULL || driver->unlocked_ioctl == NULL) { retval = -ENOTTY; } else { - /* keep API that guarantees BKL */ - lock_kernel(); - retval = driver->ioctl(intf, ctl->ioctl_code, buf); - unlock_kernel(); + retval = driver->unlocked_ioctl(intf, ctl->ioctl_code, buf); if (retval == -ENOIOCTLCMD) retval = -ENOTTY; } diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index a6bd53ace035..880f65baf581 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1742,9 +1742,8 @@ static int usb_runtime_suspend(struct device *dev) } /* Prevent the parent from suspending immediately after */ - else if (udev->parent) { + else if (udev->parent) udev->parent->last_busy = jiffies; - } } /* Runtime suspend for a USB interface doesn't mean anything. */ @@ -1786,7 +1785,7 @@ static int usb_runtime_idle(struct device *dev) return 0; } -static struct dev_pm_ops usb_bus_pm_ops = { +static const struct dev_pm_ops usb_bus_pm_ops = { .runtime_suspend = usb_runtime_suspend, .runtime_resume = usb_runtime_resume, .runtime_idle = usb_runtime_idle, @@ -1794,7 +1793,7 @@ static struct dev_pm_ops usb_bus_pm_ops = { #else -#define usb_bus_pm_ops (*(struct dev_pm_ops *) NULL) +#define usb_bus_pm_ops (*(const struct dev_pm_ops *) NULL) #endif /* CONFIG_USB_SUSPEND */ diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 4f84a41ee7a8..3788e738e265 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -96,16 +96,21 @@ static ssize_t show_ep_interval(struct device *dev, switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: - if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ + if (ep->udev->speed == USB_SPEED_HIGH) + /* uframes per NAK */ interval = ep->desc->bInterval; break; + case USB_ENDPOINT_XFER_ISOC: interval = 1 << (ep->desc->bInterval - 1); break; + case USB_ENDPOINT_XFER_BULK: - if (ep->udev->speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ + if (ep->udev->speed == USB_SPEED_HIGH && !in) + /* uframes per NAK */ interval = ep->desc->bInterval; break; + case USB_ENDPOINT_XFER_INT: if (ep->udev->speed == USB_SPEED_HIGH) interval = 1 << (ep->desc->bInterval - 1); diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 1cf2d1e79a5c..c3f98543caaf 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -66,10 +66,7 @@ static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd, * vice versa. */ companion = NULL; - for (;;) { - companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion); - if (!companion) - break; + for_each_pci_dev(companion) { if (companion->bus != pdev->bus || PCI_SLOT(companion->devfn) != slot) continue; @@ -250,6 +247,9 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (retval != 0) goto err4; set_hs_companion(dev, hcd); + + if (pci_dev_run_wake(dev)) + pm_runtime_put_noidle(&dev->dev); return retval; err4: @@ -292,6 +292,17 @@ void usb_hcd_pci_remove(struct pci_dev *dev) if (!hcd) return; + if (pci_dev_run_wake(dev)) + pm_runtime_get_noresume(&dev->dev); + + /* Fake an interrupt request in order to give the driver a chance + * to test whether the controller hardware has been removed (e.g., + * cardbus physical eject). + */ + local_irq_disable(); + usb_hcd_irq(0, hcd); + local_irq_enable(); + usb_remove_hcd(hcd); if (hcd->driver->flags & HCD_MEMORY) { iounmap(hcd->regs); @@ -317,12 +328,34 @@ void usb_hcd_pci_shutdown(struct pci_dev *dev) if (!hcd) return; - if (hcd->driver->shutdown) + if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && + hcd->driver->shutdown) hcd->driver->shutdown(hcd); } EXPORT_SYMBOL_GPL(usb_hcd_pci_shutdown); -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_PM_OPS + +#ifdef CONFIG_PPC_PMAC +static void powermac_set_asic(struct pci_dev *pci_dev, int enable) +{ + /* Enanble or disable ASIC clocks for USB */ + if (machine_is(powermac)) { + struct device_node *of_node; + + of_node = pci_device_to_OF_node(pci_dev); + if (of_node) + pmac_call_feature(PMAC_FTR_USB_ENABLE, + of_node, 0, enable); + } +} + +#else + +static inline void powermac_set_asic(struct pci_dev *pci_dev, int enable) +{} + +#endif /* CONFIG_PPC_PMAC */ static int check_root_hub_suspended(struct device *dev) { @@ -337,7 +370,7 @@ static int check_root_hub_suspended(struct device *dev) return 0; } -static int hcd_pci_suspend(struct device *dev) +static int suspend_common(struct device *dev, bool do_wakeup) { struct pci_dev *pci_dev = to_pci_dev(dev); struct usb_hcd *hcd = pci_get_drvdata(pci_dev); @@ -352,13 +385,21 @@ static int hcd_pci_suspend(struct device *dev) if (retval) return retval; - /* We might already be suspended (runtime PM -- not yet written) */ - if (pci_dev->current_state != PCI_D0) - return retval; - if (hcd->driver->pci_suspend) { - retval = hcd->driver->pci_suspend(hcd); + /* Optimization: Don't suspend if a root-hub wakeup is + * pending and it would cause the HCD to wake up anyway. + */ + if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) + return -EBUSY; + retval = hcd->driver->pci_suspend(hcd, do_wakeup); suspend_report_result(hcd->driver->pci_suspend, retval); + + /* Check again in case wakeup raced with pci_suspend */ + if (retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) { + if (hcd->driver->pci_resume) + hcd->driver->pci_resume(hcd, false); + retval = -EBUSY; + } if (retval) return retval; } @@ -374,6 +415,48 @@ static int hcd_pci_suspend(struct device *dev) return retval; } +static int resume_common(struct device *dev, int event) +{ + struct pci_dev *pci_dev = to_pci_dev(dev); + struct usb_hcd *hcd = pci_get_drvdata(pci_dev); + int retval; + + if (hcd->state != HC_STATE_SUSPENDED) { + dev_dbg(dev, "can't resume, not suspended!\n"); + return 0; + } + + retval = pci_enable_device(pci_dev); + if (retval < 0) { + dev_err(dev, "can't re-enable after resume, %d!\n", retval); + return retval; + } + + pci_set_master(pci_dev); + + clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); + + if (hcd->driver->pci_resume) { + if (event != PM_EVENT_AUTO_RESUME) + wait_for_companions(pci_dev, hcd); + + retval = hcd->driver->pci_resume(hcd, + event == PM_EVENT_RESTORE); + if (retval) { + dev_err(dev, "PCI post-resume error %d!\n", retval); + usb_hc_died(hcd); + } + } + return retval; +} + +#ifdef CONFIG_PM_SLEEP + +static int hcd_pci_suspend(struct device *dev) +{ + return suspend_common(dev, device_may_wakeup(dev)); +} + static int hcd_pci_suspend_noirq(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); @@ -408,16 +491,7 @@ static int hcd_pci_suspend_noirq(struct device *dev) return retval; } -#ifdef CONFIG_PPC_PMAC - /* Disable ASIC clocks for USB */ - if (machine_is(powermac)) { - struct device_node *of_node; - - of_node = pci_device_to_OF_node(pci_dev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, of_node, 0, 0); - } -#endif + powermac_set_asic(pci_dev, 0); return retval; } @@ -425,69 +499,63 @@ static int hcd_pci_resume_noirq(struct device *dev) { struct pci_dev *pci_dev = to_pci_dev(dev); -#ifdef CONFIG_PPC_PMAC - /* Reenable ASIC clocks for USB */ - if (machine_is(powermac)) { - struct device_node *of_node; - - of_node = pci_device_to_OF_node(pci_dev); - if (of_node) - pmac_call_feature(PMAC_FTR_USB_ENABLE, - of_node, 0, 1); - } -#endif + powermac_set_asic(pci_dev, 1); /* Go back to D0 and disable remote wakeup */ pci_back_from_sleep(pci_dev); return 0; } -static int resume_common(struct device *dev, bool hibernated) +static int hcd_pci_resume(struct device *dev) { - struct pci_dev *pci_dev = to_pci_dev(dev); - struct usb_hcd *hcd = pci_get_drvdata(pci_dev); - int retval; + return resume_common(dev, PM_EVENT_RESUME); +} - if (hcd->state != HC_STATE_SUSPENDED) { - dev_dbg(dev, "can't resume, not suspended!\n"); - return 0; - } +static int hcd_pci_restore(struct device *dev) +{ + return resume_common(dev, PM_EVENT_RESTORE); +} - retval = pci_enable_device(pci_dev); - if (retval < 0) { - dev_err(dev, "can't re-enable after resume, %d!\n", retval); - return retval; - } +#else - pci_set_master(pci_dev); +#define hcd_pci_suspend NULL +#define hcd_pci_suspend_noirq NULL +#define hcd_pci_resume_noirq NULL +#define hcd_pci_resume NULL +#define hcd_pci_restore NULL - clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); +#endif /* CONFIG_PM_SLEEP */ - if (hcd->driver->pci_resume) { - /* This call should be made only during system resume, - * not during runtime resume. - */ - wait_for_companions(pci_dev, hcd); +#ifdef CONFIG_PM_RUNTIME - retval = hcd->driver->pci_resume(hcd, hibernated); - if (retval) { - dev_err(dev, "PCI post-resume error %d!\n", retval); - usb_hc_died(hcd); - } - } +static int hcd_pci_runtime_suspend(struct device *dev) +{ + int retval; + + retval = suspend_common(dev, true); + if (retval == 0) + powermac_set_asic(to_pci_dev(dev), 0); + dev_dbg(dev, "hcd_pci_runtime_suspend: %d\n", retval); return retval; } -static int hcd_pci_resume(struct device *dev) +static int hcd_pci_runtime_resume(struct device *dev) { - return resume_common(dev, false); -} + int retval; -static int hcd_pci_restore(struct device *dev) -{ - return resume_common(dev, true); + powermac_set_asic(to_pci_dev(dev), 1); + retval = resume_common(dev, PM_EVENT_AUTO_RESUME); + dev_dbg(dev, "hcd_pci_runtime_resume: %d\n", retval); + return retval; } +#else + +#define hcd_pci_runtime_suspend NULL +#define hcd_pci_runtime_resume NULL + +#endif /* CONFIG_PM_RUNTIME */ + const struct dev_pm_ops usb_hcd_pci_pm_ops = { .suspend = hcd_pci_suspend, .suspend_noirq = hcd_pci_suspend_noirq, @@ -501,7 +569,9 @@ const struct dev_pm_ops usb_hcd_pci_pm_ops = { .poweroff_noirq = hcd_pci_suspend_noirq, .restore_noirq = hcd_pci_resume_noirq, .restore = hcd_pci_restore, + .runtime_suspend = hcd_pci_runtime_suspend, + .runtime_resume = hcd_pci_runtime_resume, }; EXPORT_SYMBOL_GPL(usb_hcd_pci_pm_ops); -#endif /* CONFIG_PM_SLEEP */ +#endif /* CONFIG_PM_OPS */ diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 12742f152f43..c5753c797735 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -667,7 +667,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) unsigned long flags; char buffer[6]; /* Any root hubs with > 31 ports? */ - if (unlikely(!hcd->rh_registered)) + if (unlikely(!hcd->rh_pollable)) return; if (!hcd->uses_new_polling && !hcd->status_urb) return; @@ -679,7 +679,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) spin_lock_irqsave(&hcd_root_hub_lock, flags); urb = hcd->status_urb; if (urb) { - hcd->poll_pending = 0; + clear_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); hcd->status_urb = NULL; urb->actual_length = length; memcpy(urb->transfer_buffer, buffer, length); @@ -690,7 +690,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) spin_lock(&hcd_root_hub_lock); } else { length = 0; - hcd->poll_pending = 1; + set_bit(HCD_FLAG_POLL_PENDING, &hcd->flags); } spin_unlock_irqrestore(&hcd_root_hub_lock, flags); } @@ -699,7 +699,7 @@ void usb_hcd_poll_rh_status(struct usb_hcd *hcd) * exceed that limit if HZ is 100. The math is more clunky than * maybe expected, this is to make sure that all timers for USB devices * fire at the same time to give the CPU a break inbetween */ - if (hcd->uses_new_polling ? hcd->poll_rh : + if (hcd->uses_new_polling ? HCD_POLL_RH(hcd) : (length == 0 && hcd->status_urb != NULL)) mod_timer (&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); } @@ -736,7 +736,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) mod_timer(&hcd->rh_timer, (jiffies/(HZ/4) + 1) * (HZ/4)); /* If a status change has already occurred, report it ASAP */ - else if (hcd->poll_pending) + else if (HCD_POLL_PENDING(hcd)) mod_timer(&hcd->rh_timer, jiffies); retval = 0; done: @@ -1150,8 +1150,7 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, * finish unlinking the initial failed usb_set_address() * or device descriptor fetch. */ - if (!test_bit(HCD_FLAG_SAW_IRQ, &hcd->flags) && - !is_root_hub(urb->dev)) { + if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) { dev_warn(hcd->self.controller, "Unlink after no-IRQ? " "Controller is probably using the wrong IRQ.\n"); set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); @@ -1219,6 +1218,11 @@ static int hcd_alloc_coherent(struct usb_bus *bus, { unsigned char *vaddr; + if (*vaddr_handle == NULL) { + WARN_ON_ONCE(1); + return -EFAULT; + } + vaddr = hcd_buffer_alloc(bus, size + sizeof(vaddr), mem_flags, dma_handle); if (!vaddr) @@ -1941,6 +1945,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) dev_dbg(&rhdev->dev, "usb %s%s\n", (msg.event & PM_EVENT_AUTO ? "auto-" : ""), "resume"); + clear_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); if (!hcd->driver->bus_resume) return -ENOENT; if (hcd->state == HC_STATE_RUNNING) @@ -1994,8 +1999,10 @@ void usb_hcd_resume_root_hub (struct usb_hcd *hcd) unsigned long flags; spin_lock_irqsave (&hcd_root_hub_lock, flags); - if (hcd->rh_registered) + if (hcd->rh_registered) { + set_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags); queue_work(pm_wq, &hcd->wakeup_work); + } spin_unlock_irqrestore (&hcd_root_hub_lock, flags); } EXPORT_SYMBOL_GPL(usb_hcd_resume_root_hub); @@ -2063,8 +2070,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) */ local_irq_save(flags); - if (unlikely(hcd->state == HC_STATE_HALT || - !test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + if (unlikely(hcd->state == HC_STATE_HALT || !HCD_HW_ACCESSIBLE(hcd))) { rc = IRQ_NONE; } else if (hcd->driver->irq(hcd) == IRQ_NONE) { rc = IRQ_NONE; @@ -2098,7 +2104,7 @@ void usb_hc_died (struct usb_hcd *hcd) spin_lock_irqsave (&hcd_root_hub_lock, flags); if (hcd->rh_registered) { - hcd->poll_rh = 0; + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); /* make khubd clean up old urbs and devices */ usb_set_device_state (hcd->self.root_hub, @@ -2217,6 +2223,7 @@ int usb_add_hcd(struct usb_hcd *hcd, retval = -ENOMEM; goto err_allocate_root_hub; } + hcd->self.root_hub = rhdev; switch (hcd->driver->flags & HCD_MASK) { case HCD_USB11: @@ -2229,9 +2236,8 @@ int usb_add_hcd(struct usb_hcd *hcd, rhdev->speed = USB_SPEED_SUPER; break; default: - goto err_allocate_root_hub; + goto err_set_rh_speed; } - hcd->self.root_hub = rhdev; /* wakeup flag init defaults to "everything works" for root hubs, * but drivers can override it in reset() if needed, along with @@ -2246,6 +2252,7 @@ int usb_add_hcd(struct usb_hcd *hcd, dev_err(hcd->self.controller, "can't setup\n"); goto err_hcd_driver_setup; } + hcd->rh_pollable = 1; /* NOTE: root hub and controller capabilities may not be the same */ if (device_can_wakeup(hcd->self.controller) @@ -2300,23 +2307,38 @@ int usb_add_hcd(struct usb_hcd *hcd, retval); goto error_create_attr_group; } - if (hcd->uses_new_polling && hcd->poll_rh) + if (hcd->uses_new_polling && HCD_POLL_RH(hcd)) usb_hcd_poll_rh_status(hcd); return retval; error_create_attr_group: + if (HC_IS_RUNNING(hcd->state)) + hcd->state = HC_STATE_QUIESCING; + spin_lock_irq(&hcd_root_hub_lock); + hcd->rh_registered = 0; + spin_unlock_irq(&hcd_root_hub_lock); + +#ifdef CONFIG_USB_SUSPEND + cancel_work_sync(&hcd->wakeup_work); +#endif mutex_lock(&usb_bus_list_lock); - usb_disconnect(&hcd->self.root_hub); + usb_disconnect(&rhdev); /* Sets rhdev to NULL */ mutex_unlock(&usb_bus_list_lock); err_register_root_hub: + hcd->rh_pollable = 0; + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); hcd->driver->stop(hcd); + hcd->state = HC_STATE_HALT; + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); err_hcd_driver_start: if (hcd->irq >= 0) free_irq(irqnum, hcd); err_request_irq: err_hcd_driver_setup: - hcd->self.root_hub = NULL; - usb_put_dev(rhdev); +err_set_rh_speed: + usb_put_dev(hcd->self.root_hub); err_allocate_root_hub: usb_deregister_bus(&hcd->self); err_register_bus: @@ -2335,8 +2357,13 @@ EXPORT_SYMBOL_GPL(usb_add_hcd); */ void usb_remove_hcd(struct usb_hcd *hcd) { + struct usb_device *rhdev = hcd->self.root_hub; + dev_info(hcd->self.controller, "remove, state %x\n", hcd->state); + usb_get_dev(rhdev); + sysfs_remove_group(&rhdev->dev.kobj, &usb_bus_attr_group); + if (HC_IS_RUNNING (hcd->state)) hcd->state = HC_STATE_QUIESCING; @@ -2349,19 +2376,30 @@ void usb_remove_hcd(struct usb_hcd *hcd) cancel_work_sync(&hcd->wakeup_work); #endif - sysfs_remove_group(&hcd->self.root_hub->dev.kobj, &usb_bus_attr_group); mutex_lock(&usb_bus_list_lock); - usb_disconnect(&hcd->self.root_hub); + usb_disconnect(&rhdev); /* Sets rhdev to NULL */ mutex_unlock(&usb_bus_list_lock); + /* Prevent any more root-hub status calls from the timer. + * The HCD might still restart the timer (if a port status change + * interrupt occurs), but usb_hcd_poll_rh_status() won't invoke + * the hub_status_data() callback. + */ + hcd->rh_pollable = 0; + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + hcd->driver->stop(hcd); hcd->state = HC_STATE_HALT; - hcd->poll_rh = 0; + /* In case the HCD restarted the timer, stop it again. */ + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); del_timer_sync(&hcd->rh_timer); if (hcd->irq >= 0) free_irq(hcd->irq, hcd); + + usb_put_dev(hcd->self.root_hub); usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 70cccc75a362..d337ef80bf43 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1294,6 +1294,7 @@ descriptor_error: return -ENODEV; } +/* No BKL needed */ static int hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) { @@ -2880,7 +2881,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, } retval = 0; - + /* notify HCD that we have a device connected and addressed */ + if (hcd->driver->update_device) + hcd->driver->update_device(hcd, udev); fail: if (retval) { hub_port_disable(hub, port1, 0); @@ -3463,7 +3466,7 @@ static struct usb_driver hub_driver = { .reset_resume = hub_reset_resume, .pre_reset = hub_pre_reset, .post_reset = hub_post_reset, - .ioctl = hub_ioctl, + .unlocked_ioctl = hub_ioctl, .id_table = hub_id_table, .supports_autosuspend = 1, }; diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 1a27618b67d6..095fa5366690 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c @@ -265,13 +265,9 @@ static int remount(struct super_block *sb, int *flags, char *data) return -EINVAL; } - lock_kernel(); - if (usbfs_mount && usbfs_mount->mnt_sb) update_sb(usbfs_mount->mnt_sb); - unlock_kernel(); - return 0; } diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 591ae9fde199..dd3b25101858 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -714,6 +714,7 @@ config USB_GADGETFS config USB_FUNCTIONFS tristate "Function Filesystem (EXPERIMENTAL)" depends on EXPERIMENTAL + select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) help The Function Filesystem (FunctioFS) lets one create USB composite functions in user space in the same way as GadgetFS @@ -722,31 +723,31 @@ config USB_FUNCTIONFS implemented in kernel space (for instance Ethernet, serial or mass storage) and other are implemented in user space. + If you say "y" or "m" here you will be able what kind of + configurations the gadget will provide. + Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_ffs". config USB_FUNCTIONFS_ETH - bool "Include CDC ECM (Ethernet) function" + bool "Include configuration with CDC ECM (Ethernet)" depends on USB_FUNCTIONFS && NET help - Include an CDC ECM (Ethernet) funcion in the CDC ECM (Funcion) - Filesystem. If you also say "y" to the RNDIS query below the - gadget will have two configurations. + Include a configuration with CDC ECM funcion (Ethernet) and the + Funcion Filesystem. config USB_FUNCTIONFS_RNDIS - bool "Include RNDIS (Ethernet) function" + bool "Include configuration with RNDIS (Ethernet)" depends on USB_FUNCTIONFS && NET help - Include an RNDIS (Ethernet) funcion in the Funcion Filesystem. - If you also say "y" to the CDC ECM query above the gadget will - have two configurations. + Include a configuration with RNDIS funcion (Ethernet) and the Filesystem. config USB_FUNCTIONFS_GENERIC bool "Include 'pure' configuration" - depends on USB_FUNCTIONFS && (USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) + depends on USB_FUNCTIONFS help - Include a configuration with FunctionFS and no Ethernet - configuration. + Include a configuration with the Function Filesystem alone with + no Ethernet interface. config USB_FILE_STORAGE tristate "File-backed Storage Gadget" @@ -863,6 +864,7 @@ config USB_G_NOKIA config USB_G_MULTI tristate "Multifunction Composite Gadget (EXPERIMENTAL)" depends on BLOCK && NET + select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS help The Multifunction Composite Gadget provides Ethernet (RNDIS and/or CDC Ethernet), mass storage and ACM serial link diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index a62af7b59094..b744ccd0f34d 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -89,7 +89,7 @@ static const struct usb_descriptor_header *otg_desc[] = { /*-------------------------------------------------------------------------*/ -static int __init audio_do_config(struct usb_configuration *c) +static int __ref audio_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -113,7 +113,7 @@ static struct usb_configuration audio_config_driver = { /*-------------------------------------------------------------------------*/ -static int __init audio_bind(struct usb_composite_dev *cdev) +static int __ref audio_bind(struct usb_composite_dev *cdev) { int gcnum; int status; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 928137d3dbdc..1f5ba2fd4c1f 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -129,7 +129,7 @@ static u8 hostaddr[ETH_ALEN]; /* * We _always_ have both CDC ECM and CDC ACM functions. */ -static int __init cdc_do_config(struct usb_configuration *c) +static int __ref cdc_do_config(struct usb_configuration *c) { int status; @@ -159,7 +159,7 @@ static struct usb_configuration cdc_config_driver = { /*-------------------------------------------------------------------------*/ -static int __init cdc_bind(struct usb_composite_dev *cdev) +static int __ref cdc_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 391d169f8d07..e483f80822d2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -673,20 +673,83 @@ static int get_string(struct usb_composite_dev *cdev, * string IDs. Drivers for functions, configurations, or gadgets will * then store that ID in the appropriate descriptors and string table. * - * All string identifier should be allocated using this routine, to - * ensure that for example different functions don't wrongly assign - * different meanings to the same identifier. + * All string identifier should be allocated using this, + * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure + * that for example different functions don't wrongly assign different + * meanings to the same identifier. */ int usb_string_id(struct usb_composite_dev *cdev) { if (cdev->next_string_id < 254) { - /* string id 0 is reserved */ + /* string id 0 is reserved by USB spec for list of + * supported languages */ + /* 255 reserved as well? -- mina86 */ cdev->next_string_id++; return cdev->next_string_id; } return -ENODEV; } +/** + * usb_string_ids() - allocate unused string IDs in batch + * @cdev: the device whose string descriptor IDs are being allocated + * @str: an array of usb_string objects to assign numbers to + * Context: single threaded during gadget setup + * + * @usb_string_ids() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then copy IDs from the string table to the appropriate descriptors + * and string table for other languages. + * + * All string identifier should be allocated using this, + * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for + * example different functions don't wrongly assign different meanings + * to the same identifier. + */ +int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) +{ + int next = cdev->next_string_id; + + for (; str->s; ++str) { + if (unlikely(next >= 254)) + return -ENODEV; + str->id = ++next; + } + + cdev->next_string_id = next; + + return 0; +} + +/** + * usb_string_ids_n() - allocate unused string IDs in batch + * @cdev: the device whose string descriptor IDs are being allocated + * @n: number of string IDs to allocate + * Context: single threaded during gadget setup + * + * Returns the first requested ID. This ID and next @n-1 IDs are now + * valid IDs. At least providind that @n is non zore because if it + * is, returns last requested ID which is now very useful information. + * + * @usb_string_ids_n() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then store that ID in the appropriate descriptors and string table. + * + * All string identifier should be allocated using this, + * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for + * example different functions don't wrongly assign different meanings + * to the same identifier. + */ +int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) +{ + unsigned next = c->next_string_id; + if (unlikely(n > 254 || (unsigned)next + n > 254)) + return -ENODEV; + c->next_string_id += n; + return next + 1; +} + + /*-------------------------------------------------------------------------*/ static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) @@ -893,6 +956,8 @@ static void composite_disconnect(struct usb_gadget *gadget) spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) reset_config(cdev); + if (composite->disconnect) + composite->disconnect(cdev); spin_unlock_irqrestore(&cdev->lock, flags); } diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 4f9e578cde9d..dc6546248ed9 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1542,7 +1542,7 @@ static int dummy_hub_status (struct usb_hcd *hcd, char *buf) dum = hcd_to_dummy (hcd); spin_lock_irqsave (&dum->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) goto done; if (dum->resuming && time_after_eq (jiffies, dum->re_timeout)) { @@ -1588,7 +1588,7 @@ static int dummy_hub_control ( int retval = 0; unsigned long flags; - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) return -ETIMEDOUT; dum = hcd_to_dummy (hcd); @@ -1739,7 +1739,7 @@ static int dummy_bus_resume (struct usb_hcd *hcd) dev_dbg (&hcd->self.root_hub->dev, "%s\n", __func__); spin_lock_irq (&dum->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { rc = -ESHUTDOWN; } else { dum->rh_state = DUMMY_RH_RUNNING; diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 400f80372d93..114fa024c22c 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -237,7 +237,7 @@ static u8 hostaddr[ETH_ALEN]; * the first one present. That's to make Microsoft's drivers happy, * and to follow DOCSIS 1.0 (cable modem standard). */ -static int __init rndis_do_config(struct usb_configuration *c) +static int __ref rndis_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -270,7 +270,7 @@ MODULE_PARM_DESC(use_eem, "use CDC EEM mode"); /* * We _always_ have an ECM, CDC Subset, or EEM configuration. */ -static int __init eth_do_config(struct usb_configuration *c) +static int __ref eth_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -297,7 +297,7 @@ static struct usb_configuration eth_config_driver = { /*-------------------------------------------------------------------------*/ -static int __init eth_bind(struct usb_composite_dev *cdev) +static int __ref eth_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index d69eccf5f197..15489bfb33f8 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -714,9 +714,7 @@ static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) struct ffs_function *func = ffs->func; ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; } else if (gadget->ops->ioctl) { - lock_kernel(); ret = gadget->ops->ioctl(gadget, code, value); - unlock_kernel(); } else { ret = -ENOTTY; } @@ -1377,7 +1375,8 @@ static void ffs_data_reset(struct ffs_data *ffs) static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) { - unsigned i, count; + struct usb_gadget_strings **lang; + int first_id; ENTER(); @@ -1385,7 +1384,9 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) return -EBADFD; - ffs_data_get(ffs); + first_id = usb_string_ids_n(cdev, ffs->strings_count); + if (unlikely(first_id < 0)) + return first_id; ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); if (unlikely(!ffs->ep0req)) @@ -1393,25 +1394,16 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) ffs->ep0req->complete = ffs_ep0_complete; ffs->ep0req->context = ffs; - /* Get strings identifiers */ - for (count = ffs->strings_count, i = 0; i < count; ++i) { - struct usb_gadget_strings **lang; - - int id = usb_string_id(cdev); - if (unlikely(id < 0)) { - usb_ep_free_request(cdev->gadget->ep0, ffs->ep0req); - ffs->ep0req = NULL; - return id; - } - - lang = ffs->stringtabs; - do { - (*lang)->strings[i].id = id; - ++lang; - } while (*lang); + lang = ffs->stringtabs; + for (lang = ffs->stringtabs; *lang; ++lang) { + struct usb_string *str = (*lang)->strings; + int id = first_id; + for (; str->s; ++id, ++str) + str->id = id; } ffs->gadget = cdev->gadget; + ffs_data_get(ffs); return 0; } @@ -1480,9 +1472,9 @@ static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) } -static int functionfs_add(struct usb_composite_dev *cdev, - struct usb_configuration *c, - struct ffs_data *ffs) +static int functionfs_bind_config(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct ffs_data *ffs) { struct ffs_function *func; int ret; diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index e91d1b16d9be..43225879c3cd 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -324,7 +324,7 @@ static void loopback_disable(struct usb_function *f) /*-------------------------------------------------------------------------*/ -static int __init loopback_bind_config(struct usb_configuration *c) +static int __ref loopback_bind_config(struct usb_configuration *c) { struct f_loopback *loop; int status; @@ -346,7 +346,7 @@ static int __init loopback_bind_config(struct usb_configuration *c) return status; } -static struct usb_configuration loopback_driver = { +static struct usb_configuration loopback_driver = { .label = "loopback", .strings = loopback_strings, .bind = loopback_bind_config, diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 4ce899c9b165..32cce029f65c 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -316,6 +316,27 @@ static const char fsg_string_interface[] = "Mass Storage"; /*-------------------------------------------------------------------------*/ struct fsg_dev; +struct fsg_common; + +/* FSF callback functions */ +struct fsg_operations { + /* Callback function to call when thread exits. If no + * callback is set or it returns value lower then zero MSF + * will force eject all LUNs it operates on (including those + * marked as non-removable or with prevent_medium_removal flag + * set). */ + int (*thread_exits)(struct fsg_common *common); + + /* Called prior to ejection. Negative return means error, + * zero means to continue with ejection, positive means not to + * eject. */ + int (*pre_eject)(struct fsg_common *common, + struct fsg_lun *lun, int num); + /* Called after ejection. Negative return means error, zero + * or positive is just a success. */ + int (*post_eject)(struct fsg_common *common, + struct fsg_lun *lun, int num); +}; /* Data shared by all the FSG instances. */ @@ -333,7 +354,6 @@ struct fsg_common { struct usb_ep *ep0; /* Copy of gadget->ep0 */ struct usb_request *ep0req; /* Copy of cdev->req */ unsigned int ep0_req_tag; - const char *ep0req_name; struct fsg_buffhd *next_buffhd_to_fill; struct fsg_buffhd *next_buffhd_to_drain; @@ -369,8 +389,8 @@ struct fsg_common { struct completion thread_notifier; struct task_struct *thread_task; - /* Callback function to call when thread exits. */ - int (*thread_exits)(struct fsg_common *common); + /* Callback functions. */ + const struct fsg_operations *ops; /* Gadget's private data. */ void *private_data; @@ -394,12 +414,8 @@ struct fsg_config { const char *lun_name_format; const char *thread_name; - /* Callback function to call when thread exits. If no - * callback is set or it returns value lower then zero MSF - * will force eject all LUNs it operates on (including those - * marked as non-removable or with prevent_medium_removal flag - * set). */ - int (*thread_exits)(struct fsg_common *common); + /* Callback functions. */ + const struct fsg_operations *ops; /* Gadget's private data. */ void *private_data; @@ -435,6 +451,7 @@ static inline int __fsg_is_set(struct fsg_common *common, if (common->fsg) return 1; ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); + WARN_ON(1); return 0; } @@ -623,8 +640,6 @@ static int fsg_setup(struct usb_function *f, /* Respond with data/status */ req->length = min((u16)1, w_length); - fsg->common->ep0req_name = - ctrl->bRequestType & USB_DIR_IN ? "ep0-in" : "ep0-out"; return ep0_queue(fsg->common); } @@ -1395,43 +1410,55 @@ static int do_start_stop(struct fsg_common *common) } else if (!curlun->removable) { curlun->sense_data = SS_INVALID_COMMAND; return -EINVAL; - } - - loej = common->cmnd[4] & 0x02; - start = common->cmnd[4] & 0x01; - - /* eject code from file_storage.c:do_start_stop() */ - - if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */ - (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */ + } else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */ + (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */ curlun->sense_data = SS_INVALID_FIELD_IN_CDB; return -EINVAL; } - if (!start) { - /* Are we allowed to unload the media? */ - if (curlun->prevent_medium_removal) { - LDBG(curlun, "unload attempt prevented\n"); - curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; - return -EINVAL; - } - if (loej) { /* Simulate an unload/eject */ - up_read(&common->filesem); - down_write(&common->filesem); - fsg_lun_close(curlun); - up_write(&common->filesem); - down_read(&common->filesem); - } - } else { + loej = common->cmnd[4] & 0x02; + start = common->cmnd[4] & 0x01; - /* Our emulation doesn't support mounting; the medium is - * available for use as soon as it is loaded. */ + /* Our emulation doesn't support mounting; the medium is + * available for use as soon as it is loaded. */ + if (start) { if (!fsg_lun_is_open(curlun)) { curlun->sense_data = SS_MEDIUM_NOT_PRESENT; return -EINVAL; } + return 0; } - return 0; + + /* Are we allowed to unload the media? */ + if (curlun->prevent_medium_removal) { + LDBG(curlun, "unload attempt prevented\n"); + curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; + return -EINVAL; + } + + if (!loej) + return 0; + + /* Simulate an unload/eject */ + if (common->ops && common->ops->pre_eject) { + int r = common->ops->pre_eject(common, curlun, + curlun - common->luns); + if (unlikely(r < 0)) + return r; + else if (r) + return 0; + } + + up_read(&common->filesem); + down_write(&common->filesem); + fsg_lun_close(curlun); + up_write(&common->filesem); + down_read(&common->filesem); + + return common->ops && common->ops->post_eject + ? min(0, common->ops->post_eject(common, curlun, + curlun - common->luns)) + : 0; } @@ -2610,7 +2637,8 @@ static int fsg_main_thread(void *common_) common->thread_task = NULL; spin_unlock_irq(&common->lock); - if (!common->thread_exits || common->thread_exits(common) < 0) { + if (!common->ops || !common->ops->thread_exits + || common->ops->thread_exits(common) < 0) { struct fsg_lun *curlun = common->luns; unsigned i = common->nluns; @@ -2686,6 +2714,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, common->free_storage_on_release = 0; } + common->ops = cfg->ops; common->private_data = cfg->private_data; common->gadget = gadget; @@ -2807,7 +2836,6 @@ buffhds_first_it: /* Tell the thread to start working */ - common->thread_exits = cfg->thread_exits; common->thread_task = kthread_create(fsg_main_thread, common, OR(cfg->thread_name, "file-storage")); @@ -2990,9 +3018,9 @@ static struct usb_gadget_strings *fsg_strings_array[] = { NULL, }; -static int fsg_add(struct usb_composite_dev *cdev, - struct usb_configuration *c, - struct fsg_common *common) +static int fsg_bind_config(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct fsg_common *common) { struct fsg_dev *fsg; int rc; @@ -3024,6 +3052,13 @@ static int fsg_add(struct usb_composite_dev *cdev, return rc; } +static inline int __deprecated __maybe_unused +fsg_add(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct fsg_common *common) +{ + return fsg_bind_config(cdev, c, common); +} /************************* Module parameters *************************/ @@ -3096,8 +3131,8 @@ fsg_config_from_params(struct fsg_config *cfg, cfg->product_name = 0; cfg->release = 0xffff; - cfg->thread_exits = 0; - cfg->private_data = 0; + cfg->ops = NULL; + cfg->private_data = NULL; /* Finalise */ cfg->can_stall = params->stall; diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 6d3cc443d914..685d768f336e 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -404,7 +404,7 @@ static void sourcesink_disable(struct usb_function *f) /*-------------------------------------------------------------------------*/ -static int __init sourcesink_bind_config(struct usb_configuration *c) +static int __ref sourcesink_bind_config(struct usb_configuration *c) { struct f_sourcesink *ss; int status; diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index dbe6db0184fd..be446b7e7eaa 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -61,12 +61,12 @@ static struct usb_gadget_strings *uvc_function_strings[] = { #define UVC_INTF_VIDEO_STREAMING 1 static struct usb_interface_assoc_descriptor uvc_iad __initdata = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bLength = sizeof(uvc_iad), .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, .bFirstInterface = 0, .bInterfaceCount = 2, .bFunctionClass = USB_CLASS_VIDEO, - .bFunctionSubClass = 0x03, + .bFunctionSubClass = UVC_SC_VIDEO_INTERFACE_COLLECTION, .bFunctionProtocol = 0x00, .iFunction = 0, }; @@ -78,7 +78,7 @@ static struct usb_interface_descriptor uvc_control_intf __initdata = { .bAlternateSetting = 0, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 0x01, + .bInterfaceSubClass = UVC_SC_VIDEOCONTROL, .bInterfaceProtocol = 0x00, .iInterface = 0, }; @@ -106,7 +106,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt0 __initdata = { .bAlternateSetting = 0, .bNumEndpoints = 0, .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 0x02, + .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, .bInterfaceProtocol = 0x00, .iInterface = 0, }; @@ -118,7 +118,7 @@ static struct usb_interface_descriptor uvc_streaming_intf_alt1 __initdata = { .bAlternateSetting = 1, .bNumEndpoints = 1, .bInterfaceClass = USB_CLASS_VIDEO, - .bInterfaceSubClass = 0x02, + .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING, .bInterfaceProtocol = 0x00, .iInterface = 0, }; @@ -603,15 +603,15 @@ uvc_bind_config(struct usb_configuration *c, /* Validate the descriptors. */ if (control == NULL || control[0] == NULL || - control[0]->bDescriptorSubType != UVC_DT_HEADER) + control[0]->bDescriptorSubType != UVC_VC_HEADER) goto error; if (fs_streaming == NULL || fs_streaming[0] == NULL || - fs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER) + fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; if (hs_streaming == NULL || hs_streaming[0] == NULL || - hs_streaming[0]->bDescriptorSubType != UVC_DT_INPUT_HEADER) + hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER) goto error; uvc->desc.control = control; diff --git a/drivers/usb/gadget/f_uvc.h b/drivers/usb/gadget/f_uvc.h index 8a5db7c4fe7c..e18a6636c283 100644 --- a/drivers/usb/gadget/f_uvc.h +++ b/drivers/usb/gadget/f_uvc.h @@ -15,357 +15,7 @@ #define _F_UVC_H_ #include <linux/usb/composite.h> - -#define USB_CLASS_VIDEO_CONTROL 1 -#define USB_CLASS_VIDEO_STREAMING 2 - -struct uvc_descriptor_header { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; -} __attribute__ ((packed)); - -struct uvc_header_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u16 bcdUVC; - __u16 wTotalLength; - __u32 dwClockFrequency; - __u8 bInCollection; - __u8 baInterfaceNr[]; -} __attribute__((__packed__)); - -#define UVC_HEADER_DESCRIPTOR(n) uvc_header_descriptor_##n - -#define DECLARE_UVC_HEADER_DESCRIPTOR(n) \ -struct UVC_HEADER_DESCRIPTOR(n) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u16 bcdUVC; \ - __u16 wTotalLength; \ - __u32 dwClockFrequency; \ - __u8 bInCollection; \ - __u8 baInterfaceNr[n]; \ -} __attribute__ ((packed)) - -struct uvc_input_terminal_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bTerminalID; - __u16 wTerminalType; - __u8 bAssocTerminal; - __u8 iTerminal; -} __attribute__((__packed__)); - -struct uvc_output_terminal_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bTerminalID; - __u16 wTerminalType; - __u8 bAssocTerminal; - __u8 bSourceID; - __u8 iTerminal; -} __attribute__((__packed__)); - -struct uvc_camera_terminal_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bTerminalID; - __u16 wTerminalType; - __u8 bAssocTerminal; - __u8 iTerminal; - __u16 wObjectiveFocalLengthMin; - __u16 wObjectiveFocalLengthMax; - __u16 wOcularFocalLength; - __u8 bControlSize; - __u8 bmControls[3]; -} __attribute__((__packed__)); - -struct uvc_selector_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bUnitID; - __u8 bNrInPins; - __u8 baSourceID[0]; - __u8 iSelector; -} __attribute__((__packed__)); - -#define UVC_SELECTOR_UNIT_DESCRIPTOR(n) \ - uvc_selector_unit_descriptor_##n - -#define DECLARE_UVC_SELECTOR_UNIT_DESCRIPTOR(n) \ -struct UVC_SELECTOR_UNIT_DESCRIPTOR(n) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u8 bUnitID; \ - __u8 bNrInPins; \ - __u8 baSourceID[n]; \ - __u8 iSelector; \ -} __attribute__ ((packed)) - -struct uvc_processing_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bUnitID; - __u8 bSourceID; - __u16 wMaxMultiplier; - __u8 bControlSize; - __u8 bmControls[2]; - __u8 iProcessing; -} __attribute__((__packed__)); - -struct uvc_extension_unit_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bUnitID; - __u8 guidExtensionCode[16]; - __u8 bNumControls; - __u8 bNrInPins; - __u8 baSourceID[0]; - __u8 bControlSize; - __u8 bmControls[0]; - __u8 iExtension; -} __attribute__((__packed__)); - -#define UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \ - uvc_extension_unit_descriptor_##p_##n - -#define DECLARE_UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) \ -struct UVC_EXTENSION_UNIT_DESCRIPTOR(p, n) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u8 bUnitID; \ - __u8 guidExtensionCode[16]; \ - __u8 bNumControls; \ - __u8 bNrInPins; \ - __u8 baSourceID[p]; \ - __u8 bControlSize; \ - __u8 bmControls[n]; \ - __u8 iExtension; \ -} __attribute__ ((packed)) - -struct uvc_control_endpoint_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u16 wMaxTransferSize; -} __attribute__((__packed__)); - -#define UVC_DT_HEADER 1 -#define UVC_DT_INPUT_TERMINAL 2 -#define UVC_DT_OUTPUT_TERMINAL 3 -#define UVC_DT_SELECTOR_UNIT 4 -#define UVC_DT_PROCESSING_UNIT 5 -#define UVC_DT_EXTENSION_UNIT 6 - -#define UVC_DT_HEADER_SIZE(n) (12+(n)) -#define UVC_DT_INPUT_TERMINAL_SIZE 8 -#define UVC_DT_OUTPUT_TERMINAL_SIZE 9 -#define UVC_DT_CAMERA_TERMINAL_SIZE(n) (15+(n)) -#define UVC_DT_SELECTOR_UNIT_SIZE(n) (6+(n)) -#define UVC_DT_PROCESSING_UNIT_SIZE(n) (9+(n)) -#define UVC_DT_EXTENSION_UNIT_SIZE(p,n) (24+(p)+(n)) -#define UVC_DT_CONTROL_ENDPOINT_SIZE 5 - -struct uvc_input_header_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bNumFormats; - __u16 wTotalLength; - __u8 bEndpointAddress; - __u8 bmInfo; - __u8 bTerminalLink; - __u8 bStillCaptureMethod; - __u8 bTriggerSupport; - __u8 bTriggerUsage; - __u8 bControlSize; - __u8 bmaControls[]; -} __attribute__((__packed__)); - -#define UVC_INPUT_HEADER_DESCRIPTOR(n, p) \ - uvc_input_header_descriptor_##n_##p - -#define DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(n, p) \ -struct UVC_INPUT_HEADER_DESCRIPTOR(n, p) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u8 bNumFormats; \ - __u16 wTotalLength; \ - __u8 bEndpointAddress; \ - __u8 bmInfo; \ - __u8 bTerminalLink; \ - __u8 bStillCaptureMethod; \ - __u8 bTriggerSupport; \ - __u8 bTriggerUsage; \ - __u8 bControlSize; \ - __u8 bmaControls[p][n]; \ -} __attribute__ ((packed)) - -struct uvc_output_header_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bNumFormats; - __u16 wTotalLength; - __u8 bEndpointAddress; - __u8 bTerminalLink; - __u8 bControlSize; - __u8 bmaControls[]; -} __attribute__((__packed__)); - -#define UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \ - uvc_output_header_descriptor_##n_##p - -#define DECLARE_UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) \ -struct UVC_OUTPUT_HEADER_DESCRIPTOR(n, p) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u8 bNumFormats; \ - __u16 wTotalLength; \ - __u8 bEndpointAddress; \ - __u8 bTerminalLink; \ - __u8 bControlSize; \ - __u8 bmaControls[p][n]; \ -} __attribute__ ((packed)) - -struct uvc_format_uncompressed { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bFormatIndex; - __u8 bNumFrameDescriptors; - __u8 guidFormat[16]; - __u8 bBitsPerPixel; - __u8 bDefaultFrameIndex; - __u8 bAspectRatioX; - __u8 bAspectRatioY; - __u8 bmInterfaceFlags; - __u8 bCopyProtect; -} __attribute__((__packed__)); - -struct uvc_frame_uncompressed { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bFrameIndex; - __u8 bmCapabilities; - __u16 wWidth; - __u16 wHeight; - __u32 dwMinBitRate; - __u32 dwMaxBitRate; - __u32 dwMaxVideoFrameBufferSize; - __u32 dwDefaultFrameInterval; - __u8 bFrameIntervalType; - __u32 dwFrameInterval[]; -} __attribute__((__packed__)); - -#define UVC_FRAME_UNCOMPRESSED(n) \ - uvc_frame_uncompressed_##n - -#define DECLARE_UVC_FRAME_UNCOMPRESSED(n) \ -struct UVC_FRAME_UNCOMPRESSED(n) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u8 bFrameIndex; \ - __u8 bmCapabilities; \ - __u16 wWidth; \ - __u16 wHeight; \ - __u32 dwMinBitRate; \ - __u32 dwMaxBitRate; \ - __u32 dwMaxVideoFrameBufferSize; \ - __u32 dwDefaultFrameInterval; \ - __u8 bFrameIntervalType; \ - __u32 dwFrameInterval[n]; \ -} __attribute__ ((packed)) - -struct uvc_format_mjpeg { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bFormatIndex; - __u8 bNumFrameDescriptors; - __u8 bmFlags; - __u8 bDefaultFrameIndex; - __u8 bAspectRatioX; - __u8 bAspectRatioY; - __u8 bmInterfaceFlags; - __u8 bCopyProtect; -} __attribute__((__packed__)); - -struct uvc_frame_mjpeg { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bFrameIndex; - __u8 bmCapabilities; - __u16 wWidth; - __u16 wHeight; - __u32 dwMinBitRate; - __u32 dwMaxBitRate; - __u32 dwMaxVideoFrameBufferSize; - __u32 dwDefaultFrameInterval; - __u8 bFrameIntervalType; - __u32 dwFrameInterval[]; -} __attribute__((__packed__)); - -#define UVC_FRAME_MJPEG(n) \ - uvc_frame_mjpeg_##n - -#define DECLARE_UVC_FRAME_MJPEG(n) \ -struct UVC_FRAME_MJPEG(n) { \ - __u8 bLength; \ - __u8 bDescriptorType; \ - __u8 bDescriptorSubType; \ - __u8 bFrameIndex; \ - __u8 bmCapabilities; \ - __u16 wWidth; \ - __u16 wHeight; \ - __u32 dwMinBitRate; \ - __u32 dwMaxBitRate; \ - __u32 dwMaxVideoFrameBufferSize; \ - __u32 dwDefaultFrameInterval; \ - __u8 bFrameIntervalType; \ - __u32 dwFrameInterval[n]; \ -} __attribute__ ((packed)) - -struct uvc_color_matching_descriptor { - __u8 bLength; - __u8 bDescriptorType; - __u8 bDescriptorSubType; - __u8 bColorPrimaries; - __u8 bTransferCharacteristics; - __u8 bMatrixCoefficients; -} __attribute__((__packed__)); - -#define UVC_DT_INPUT_HEADER 1 -#define UVC_DT_OUTPUT_HEADER 2 -#define UVC_DT_FORMAT_UNCOMPRESSED 4 -#define UVC_DT_FRAME_UNCOMPRESSED 5 -#define UVC_DT_FORMAT_MJPEG 6 -#define UVC_DT_FRAME_MJPEG 7 -#define UVC_DT_COLOR_MATCHING 13 - -#define UVC_DT_INPUT_HEADER_SIZE(n, p) (13+(n*p)) -#define UVC_DT_OUTPUT_HEADER_SIZE(n, p) (9+(n*p)) -#define UVC_DT_FORMAT_UNCOMPRESSED_SIZE 27 -#define UVC_DT_FRAME_UNCOMPRESSED_SIZE(n) (26+4*(n)) -#define UVC_DT_FORMAT_MJPEG_SIZE 11 -#define UVC_DT_FRAME_MJPEG_SIZE(n) (26+4*(n)) -#define UVC_DT_COLOR_MATCHING_SIZE 6 +#include <linux/usb/video.h> extern int uvc_bind_config(struct usb_configuration *c, const struct uvc_descriptor_header * const *control, diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index b49d86e3e45b..d57c09f764d6 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -56,7 +56,7 @@ * following protocols: RBC (0x01), ATAPI or SFF-8020i (0x02), QIC-157 (0c03), * UFI (0x04), SFF-8070i (0x05), and transparent SCSI (0x06), selected by * the optional "protocol" module parameter. In addition, the default - * Vendor ID, Product ID, and release number can be overridden. + * Vendor ID, Product ID, release number and serial number can be overridden. * * There is support for multiple logical units (LUNs), each of which has * its own backing file. The number of LUNs can be set using the optional @@ -106,6 +106,7 @@ * vendor=0xVVVV Default 0x0525 (NetChip), USB Vendor ID * product=0xPPPP Default 0xa4a5 (FSG), USB Product ID * release=0xRRRR Override the USB release number (bcdDevice) + * serial=HHHH... Override serial number (string of hex chars) * buflen=N Default N=16384, buffer size used (will be * rounded down to a multiple of * PAGE_CACHE_SIZE) @@ -270,6 +271,8 @@ #define DRIVER_DESC "File-backed Storage Gadget" #define DRIVER_NAME "g_file_storage" +/* DRIVER_VERSION must be at least 6 characters long, as it is used + * to generate a fallback serial number. */ #define DRIVER_VERSION "20 November 2008" static char fsg_string_manufacturer[64]; @@ -314,6 +317,7 @@ static struct { unsigned short vendor; unsigned short product; unsigned short release; + char *serial_parm; unsigned int buflen; int transport_type; @@ -374,6 +378,9 @@ MODULE_PARM_DESC(product, "USB Product ID"); module_param_named(release, mod_data.release, ushort, S_IRUGO); MODULE_PARM_DESC(release, "USB release number"); +module_param_named(serial, mod_data.serial_parm, charp, S_IRUGO); +MODULE_PARM_DESC(serial, "USB serial number"); + module_param_named(buflen, mod_data.buflen, uint, S_IRUGO); MODULE_PARM_DESC(buflen, "I/O buffer size"); @@ -3197,6 +3204,7 @@ static int __init check_parameters(struct fsg_dev *fsg) { int prot; int gcnum; + int i; /* Store the default values */ mod_data.transport_type = USB_PR_BULK; @@ -3272,13 +3280,62 @@ static int __init check_parameters(struct fsg_dev *fsg) ERROR(fsg, "invalid buflen\n"); return -ETOOSMALL; } + + /* Serial string handling. + * On a real device, the serial string would be loaded + * from permanent storage. */ + if (mod_data.serial_parm) { + const char *ch; + unsigned len = 0; + + /* Sanity check : + * The CB[I] specification limits the serial string to + * 12 uppercase hexadecimal characters. + * BBB need at least 12 uppercase hexadecimal characters, + * with a maximum of 126. */ + for (ch = mod_data.serial_parm; *ch; ++ch) { + ++len; + if ((*ch < '0' || *ch > '9') && + (*ch < 'A' || *ch > 'F')) { /* not uppercase hex */ + WARNING(fsg, + "Invalid serial string character: %c; " + "Failing back to default\n", + *ch); + goto fill_serial; + } + } + if (len > 126 || + (mod_data.transport_type == USB_PR_BULK && len < 12) || + (mod_data.transport_type != USB_PR_BULK && len > 12)) { + WARNING(fsg, + "Invalid serial string length; " + "Failing back to default\n"); + goto fill_serial; + } + fsg_strings[FSG_STRING_SERIAL - 1].s = mod_data.serial_parm; + } else { +fill_serial: + /* Serial number not specified or invalid, make our own. + * We just encode it from the driver version string, + * 12 characters to comply with both CB[I] and BBB spec. + * Warning : Two devices running the same kernel will have + * the same fallback serial number. */ + for (i = 0; i < 12; i += 2) { + unsigned char c = DRIVER_VERSION[i / 2]; + + if (!c) + break; + sprintf(&fsg_string_serial[i], "%02X", c); + } + } + #endif /* CONFIG_USB_FILE_STORAGE_TEST */ return 0; } -static int __init fsg_bind(struct usb_gadget *gadget) +static int __ref fsg_bind(struct usb_gadget *gadget) { struct fsg_dev *fsg = the_fsg; int rc; @@ -3447,16 +3504,6 @@ static int __init fsg_bind(struct usb_gadget *gadget) init_utsname()->sysname, init_utsname()->release, gadget->name); - /* On a real device, serial[] would be loaded from permanent - * storage. We just encode it from the driver version string. */ - for (i = 0; i < sizeof fsg_string_serial - 2; i += 2) { - unsigned char c = DRIVER_VERSION[i / 2]; - - if (!c) - break; - sprintf(&fsg_string_serial[i], "%02X", c); - } - fsg->thread_task = kthread_create(fsg_main_thread, fsg, "file-storage-gadget"); if (IS_ERR(fsg->thread_task)) { diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index d1af253a9105..a9474f8d5325 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -32,12 +32,13 @@ # include "u_ether.c" static u8 gfs_hostaddr[ETH_ALEN]; -#else -# if !defined CONFIG_USB_FUNCTIONFS_GENERIC -# define CONFIG_USB_FUNCTIONFS_GENERIC +# ifdef CONFIG_USB_FUNCTIONFS_ETH +static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); # endif +#else # define gether_cleanup() do { } while (0) # define gether_setup(gadget, hostaddr) ((int)0) +# define gfs_hostaddr NULL #endif #include "f_fs.c" @@ -107,15 +108,7 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = { enum { GFS_STRING_MANUFACTURER_IDX, GFS_STRING_PRODUCT_IDX, -#ifdef CONFIG_USB_FUNCTIONFS_RNDIS - GFS_STRING_RNDIS_CONFIG_IDX, -#endif -#ifdef CONFIG_USB_FUNCTIONFS_ETH - GFS_STRING_ECM_CONFIG_IDX, -#endif -#ifdef CONFIG_USB_FUNCTIONFS_GENERIC - GFS_STRING_GENERIC_CONFIG_IDX, -#endif + GFS_STRING_FIRST_CONFIG_IDX, }; static char gfs_manufacturer[50]; @@ -126,13 +119,13 @@ static struct usb_string gfs_strings[] = { [GFS_STRING_MANUFACTURER_IDX].s = gfs_manufacturer, [GFS_STRING_PRODUCT_IDX].s = gfs_driver_desc, #ifdef CONFIG_USB_FUNCTIONFS_RNDIS - [GFS_STRING_RNDIS_CONFIG_IDX].s = "FunctionFS + RNDIS", + { .s = "FunctionFS + RNDIS" }, #endif #ifdef CONFIG_USB_FUNCTIONFS_ETH - [GFS_STRING_ECM_CONFIG_IDX].s = "FunctionFS + ECM", + { .s = "FunctionFS + ECM" }, #endif #ifdef CONFIG_USB_FUNCTIONFS_GENERIC - [GFS_STRING_GENERIC_CONFIG_IDX].s = "FunctionFS", + { .s = "FunctionFS" }, #endif { } /* end of list */ }; @@ -146,59 +139,33 @@ static struct usb_gadget_strings *gfs_dev_strings[] = { }; + +struct gfs_configuration { + struct usb_configuration c; + int (*eth)(struct usb_configuration *c, u8 *ethaddr); +} gfs_configurations[] = { #ifdef CONFIG_USB_FUNCTIONFS_RNDIS -static int gfs_do_rndis_config(struct usb_configuration *c); - -static struct usb_configuration gfs_rndis_config_driver = { - .label = "FunctionFS + RNDIS", - .bind = gfs_do_rndis_config, - .bConfigurationValue = 1, - /* .iConfiguration = DYNAMIC */ - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -}; -# define gfs_add_rndis_config(cdev) \ - usb_add_config(cdev, &gfs_rndis_config_driver) -#else -# define gfs_add_rndis_config(cdev) 0 + { + .eth = rndis_bind_config, + }, #endif - #ifdef CONFIG_USB_FUNCTIONFS_ETH -static int gfs_do_ecm_config(struct usb_configuration *c); - -static struct usb_configuration gfs_ecm_config_driver = { - .label = "FunctionFS + ECM", - .bind = gfs_do_ecm_config, - .bConfigurationValue = 1, - /* .iConfiguration = DYNAMIC */ - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -}; -# define gfs_add_ecm_config(cdev) \ - usb_add_config(cdev, &gfs_ecm_config_driver) -#else -# define gfs_add_ecm_config(cdev) 0 + { + .eth = eth_bind_config, + }, #endif - #ifdef CONFIG_USB_FUNCTIONFS_GENERIC -static int gfs_do_generic_config(struct usb_configuration *c); - -static struct usb_configuration gfs_generic_config_driver = { - .label = "FunctionFS", - .bind = gfs_do_generic_config, - .bConfigurationValue = 2, - /* .iConfiguration = DYNAMIC */ - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -}; -# define gfs_add_generic_config(cdev) \ - usb_add_config(cdev, &gfs_generic_config_driver) -#else -# define gfs_add_generic_config(cdev) 0 + { + }, #endif +}; static int gfs_bind(struct usb_composite_dev *cdev); static int gfs_unbind(struct usb_composite_dev *cdev); +static int gfs_do_config(struct usb_configuration *c); static struct usb_composite_driver gfs_driver = { .name = gfs_short_name, @@ -267,7 +234,7 @@ static int functionfs_check_dev_callback(const char *dev_name) static int gfs_bind(struct usb_composite_dev *cdev) { - int ret; + int ret, i; ENTER(); @@ -284,57 +251,32 @@ static int gfs_bind(struct usb_composite_dev *cdev) snprintf(gfs_manufacturer, sizeof gfs_manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, cdev->gadget->name); - ret = usb_string_id(cdev); - if (unlikely(ret < 0)) - goto error; - gfs_strings[GFS_STRING_MANUFACTURER_IDX].id = ret; - gfs_dev_desc.iManufacturer = ret; - - ret = usb_string_id(cdev); - if (unlikely(ret < 0)) - goto error; - gfs_strings[GFS_STRING_PRODUCT_IDX].id = ret; - gfs_dev_desc.iProduct = ret; - -#ifdef CONFIG_USB_FUNCTIONFS_RNDIS - ret = usb_string_id(cdev); - if (unlikely(ret < 0)) - goto error; - gfs_strings[GFS_STRING_RNDIS_CONFIG_IDX].id = ret; - gfs_rndis_config_driver.iConfiguration = ret; -#endif -#ifdef CONFIG_USB_FUNCTIONFS_ETH - ret = usb_string_id(cdev); + ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) goto error; - gfs_strings[GFS_STRING_ECM_CONFIG_IDX].id = ret; - gfs_ecm_config_driver.iConfiguration = ret; -#endif -#ifdef CONFIG_USB_FUNCTIONFS_GENERIC - ret = usb_string_id(cdev); - if (unlikely(ret < 0)) - goto error; - gfs_strings[GFS_STRING_GENERIC_CONFIG_IDX].id = ret; - gfs_generic_config_driver.iConfiguration = ret; -#endif + gfs_dev_desc.iManufacturer = gfs_strings[GFS_STRING_MANUFACTURER_IDX].id; + gfs_dev_desc.iProduct = gfs_strings[GFS_STRING_PRODUCT_IDX].id; ret = functionfs_bind(gfs_ffs_data, cdev); if (unlikely(ret < 0)) goto error; - ret = gfs_add_rndis_config(cdev); - if (unlikely(ret < 0)) - goto error_unbind; + for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { + struct gfs_configuration *c = gfs_configurations + i; - ret = gfs_add_ecm_config(cdev); - if (unlikely(ret < 0)) - goto error_unbind; + ret = GFS_STRING_FIRST_CONFIG_IDX + i; + c->c.label = gfs_strings[ret].s; + c->c.iConfiguration = gfs_strings[ret].id; + c->c.bind = gfs_do_config; + c->c.bConfigurationValue = 1 + i; + c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; - ret = gfs_add_generic_config(cdev); - if (unlikely(ret < 0)) - goto error_unbind; + ret = usb_add_config(cdev, &c->c); + if (unlikely(ret < 0)) + goto error_unbind; + } return 0; @@ -368,10 +310,10 @@ static int gfs_unbind(struct usb_composite_dev *cdev) } -static int __gfs_do_config(struct usb_configuration *c, - int (*eth)(struct usb_configuration *c, u8 *ethaddr), - u8 *ethaddr) +static int gfs_do_config(struct usb_configuration *c) { + struct gfs_configuration *gc = + container_of(c, struct gfs_configuration, c); int ret; if (WARN_ON(!gfs_ffs_data)) @@ -382,13 +324,13 @@ static int __gfs_do_config(struct usb_configuration *c, c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - if (eth) { - ret = eth(c, ethaddr); + if (gc->eth) { + ret = gc->eth(c, gfs_hostaddr); if (unlikely(ret < 0)) return ret; } - ret = functionfs_add(c->cdev, c, gfs_ffs_data); + ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data); if (unlikely(ret < 0)) return ret; @@ -406,32 +348,12 @@ static int __gfs_do_config(struct usb_configuration *c, return 0; } -#ifdef CONFIG_USB_FUNCTIONFS_RNDIS -static int gfs_do_rndis_config(struct usb_configuration *c) -{ - ENTER(); - - return __gfs_do_config(c, rndis_bind_config, gfs_hostaddr); -} -#endif #ifdef CONFIG_USB_FUNCTIONFS_ETH -static int gfs_do_ecm_config(struct usb_configuration *c) -{ - ENTER(); - - return __gfs_do_config(c, - can_support_ecm(c->cdev->gadget) - ? ecm_bind_config : geth_bind_config, - gfs_hostaddr); -} -#endif - -#ifdef CONFIG_USB_FUNCTIONFS_GENERIC -static int gfs_do_generic_config(struct usb_configuration *c) +static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) { - ENTER(); - - return __gfs_do_config(c, NULL, NULL); + return can_support_ecm(c->cdev->gadget) + ? ecm_bind_config(c, ethaddr) + : geth_bind_config(c, ethaddr); } #endif diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index b7bf88019b06..1b413a5cc3f6 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -1157,7 +1157,7 @@ fail: /* * Creates an output endpoint, and initializes output ports. */ -static int __init gmidi_bind(struct usb_gadget *gadget) +static int __ref gmidi_bind(struct usb_gadget *gadget) { struct gmidi_device *dev; struct usb_ep *in_ep, *out_ep; diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 775722686ed8..735495bf8411 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -127,7 +127,7 @@ static struct usb_gadget_strings *dev_strings[] = { /****************************** Configurations ******************************/ -static int __init do_config(struct usb_configuration *c) +static int __ref do_config(struct usb_configuration *c) { struct hidg_func_node *e; int func = 0, status = 0; @@ -156,7 +156,7 @@ static struct usb_configuration config_driver = { /****************************** Gadget Bind ******************************/ -static int __init hid_bind(struct usb_composite_dev *cdev) +static int __ref hid_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; struct list_head *tmp; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index de8a83803505..fc35406fc80c 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1299,11 +1299,9 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) struct usb_gadget *gadget = dev->gadget; long ret = -ENOTTY; - if (gadget->ops->ioctl) { - lock_kernel(); + if (gadget->ops->ioctl) ret = gadget->ops->ioctl (gadget, code, value); - unlock_kernel(); - } + return ret; } @@ -1867,13 +1865,9 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) buf += 4; length -= 4; - kbuf = kmalloc (length, GFP_KERNEL); - if (!kbuf) - return -ENOMEM; - if (copy_from_user (kbuf, buf, length)) { - kfree (kbuf); - return -EFAULT; - } + kbuf = memdup_user(buf, length); + if (IS_ERR(kbuf)) + return PTR_ERR(kbuf); spin_lock_irq (&dev->lock); value = -EINVAL; diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index a3913519fd58..c2d2a201f84b 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -842,9 +842,9 @@ static int langwell_ep_queue(struct usb_ep *_ep, struct usb_request *_req, VDBG(dev, "req->mapped = 0\n"); } - DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08x\n", - _ep->name, - _req, _req->length, _req->buf, _req->dma); + DBG(dev, "%s queue req %p, len %u, buf %p, dma 0x%08llx\n", + _ep->name, + _req, _req->length, _req->buf, (unsigned long long)_req->dma); _req->status = -EINPROGRESS; _req->actual = 0; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 705cc1f76327..585f2559484d 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -141,9 +141,14 @@ static int msg_thread_exits(struct fsg_common *common) return 0; } -static int __init msg_do_config(struct usb_configuration *c) +static int __ref msg_do_config(struct usb_configuration *c) { - struct fsg_common *common; + static const struct fsg_operations ops = { + .thread_exits = msg_thread_exits, + }; + static struct fsg_common common; + + struct fsg_common *retp; struct fsg_config config; int ret; @@ -153,13 +158,14 @@ static int __init msg_do_config(struct usb_configuration *c) } fsg_config_from_params(&config, &mod_data); - config.thread_exits = msg_thread_exits; - common = fsg_common_init(0, c->cdev, &config); - if (IS_ERR(common)) - return PTR_ERR(common); + config.ops = &ops; + + retp = fsg_common_init(&common, c->cdev, &config); + if (IS_ERR(retp)) + return PTR_ERR(retp); - ret = fsg_add(c->cdev, c, common); - fsg_common_put(common); + ret = fsg_bind_config(c->cdev, c, &common); + fsg_common_put(&common); return ret; } @@ -176,7 +182,7 @@ static struct usb_configuration msg_config_driver = { /****************************** Gadget Bind ******************************/ -static int __init msg_bind(struct usb_composite_dev *cdev) +static int __ref msg_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; int status; diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index a930d7fd7e7a..795d76232167 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -24,6 +24,7 @@ #include <linux/kernel.h> #include <linux/utsname.h> +#include <linux/module.h> #if defined USB_ETH_RNDIS @@ -35,14 +36,13 @@ #define DRIVER_DESC "Multifunction Composite Gadget" -#define DRIVER_VERSION "2009/07/21" -/*-------------------------------------------------------------------------*/ +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_AUTHOR("Michal Nazarewicz"); +MODULE_LICENSE("GPL"); -#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ -#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ -/*-------------------------------------------------------------------------*/ +/***************************** All the files... *****************************/ /* * kbuild is not very cooperative with respect to linking separately @@ -57,6 +57,8 @@ #include "config.c" #include "epautoconf.c" +#include "f_mass_storage.c" + #include "u_serial.c" #include "f_acm.c" @@ -68,13 +70,24 @@ #endif #include "u_ether.c" -#undef DBG /* u_ether.c has broken idea about macros */ -#undef VDBG /* so clean up after it */ -#undef ERROR -#undef INFO -#include "f_mass_storage.c" -/*-------------------------------------------------------------------------*/ + +/***************************** Device Descriptor ****************************/ + +#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */ +#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */ + + +enum { + __MULTI_NO_CONFIG, +#ifdef CONFIG_USB_G_MULTI_RNDIS + MULTI_RNDIS_CONFIG_NUM, +#endif +#ifdef CONFIG_USB_G_MULTI_CDC + MULTI_CDC_CONFIG_NUM, +#endif +}; + static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, @@ -82,80 +95,82 @@ static struct usb_device_descriptor device_desc = { .bcdUSB = cpu_to_le16(0x0200), - /* .bDeviceClass = USB_CLASS_COMM, */ - /* .bDeviceSubClass = 0, */ - /* .bDeviceProtocol = 0, */ - .bDeviceClass = 0xEF, + .bDeviceClass = USB_CLASS_MISC /* 0xEF */, .bDeviceSubClass = 2, .bDeviceProtocol = 1, - /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id can be overridden by module parameters. */ .idVendor = cpu_to_le16(MULTI_VENDOR_NUM), .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM), - /* .bcdDevice = f(hardware) */ - /* .iManufacturer = DYNAMIC */ - /* .iProduct = DYNAMIC */ - /* NO SERIAL NUMBER */ - .bNumConfigurations = 1, }; -static struct usb_otg_descriptor otg_descriptor = { - .bLength = sizeof otg_descriptor, - .bDescriptorType = USB_DT_OTG, - - /* REVISIT SRP-only hardware is possible, although - * it would not be called "OTG" ... - */ - .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, -}; static const struct usb_descriptor_header *otg_desc[] = { - (struct usb_descriptor_header *) &otg_descriptor, + (struct usb_descriptor_header *) &(struct usb_otg_descriptor){ + .bLength = sizeof(struct usb_otg_descriptor), + .bDescriptorType = USB_DT_OTG, + + /* + * REVISIT SRP-only hardware is possible, although + * it would not be called "OTG" ... + */ + .bmAttributes = USB_OTG_SRP | USB_OTG_HNP, + }, NULL, }; -/* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 +enum { + MULTI_STRING_MANUFACTURER_IDX, + MULTI_STRING_PRODUCT_IDX, +#ifdef CONFIG_USB_G_MULTI_RNDIS + MULTI_STRING_RNDIS_CONFIG_IDX, +#endif +#ifdef CONFIG_USB_G_MULTI_CDC + MULTI_STRING_CDC_CONFIG_IDX, +#endif +}; static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [MULTI_STRING_MANUFACTURER_IDX].s = manufacturer, + [MULTI_STRING_PRODUCT_IDX].s = DRIVER_DESC, +#ifdef CONFIG_USB_G_MULTI_RNDIS + [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", +#endif +#ifdef CONFIG_USB_G_MULTI_CDC + [MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM", +#endif { } /* end of list */ }; -static struct usb_gadget_strings stringtab_dev = { - .language = 0x0409, /* en-us */ - .strings = strings_dev, -}; - static struct usb_gadget_strings *dev_strings[] = { - &stringtab_dev, + &(struct usb_gadget_strings){ + .language = 0x0409, /* en-us */ + .strings = strings_dev, + }, NULL, }; -static u8 hostaddr[ETH_ALEN]; /****************************** Configurations ******************************/ -static struct fsg_module_parameters mod_data = { - .stall = 1 -}; -FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); +static struct fsg_module_parameters fsg_mod_data = { .stall = 1 }; +FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data); + +static struct fsg_common fsg_common; + +static u8 hostaddr[ETH_ALEN]; -static struct fsg_common *fsg_common; +/********** RNDIS **********/ #ifdef USB_ETH_RNDIS -static int __init rndis_do_config(struct usb_configuration *c) +static __ref int rndis_do_config(struct usb_configuration *c) { int ret; @@ -172,26 +187,42 @@ static int __init rndis_do_config(struct usb_configuration *c) if (ret < 0) return ret; - ret = fsg_add(c->cdev, c, fsg_common); + ret = fsg_bind_config(c->cdev, c, &fsg_common); if (ret < 0) return ret; return 0; } -static struct usb_configuration rndis_config_driver = { - .label = "Multifunction Composite (RNDIS + MS + ACM)", - .bind = rndis_do_config, - .bConfigurationValue = 2, - /* .iConfiguration = DYNAMIC */ - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -}; +static int rndis_config_register(struct usb_composite_dev *cdev) +{ + static struct usb_configuration config = { + .bind = rndis_do_config, + .bConfigurationValue = MULTI_RNDIS_CONFIG_NUM, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + }; + + config.label = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s; + config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id; + + return usb_add_config(cdev, &config); +} + +#else + +static int rndis_config_register(struct usb_composite_dev *cdev) +{ + return 0; +} #endif + +/********** CDC ECM **********/ + #ifdef CONFIG_USB_G_MULTI_CDC -static int __init cdc_do_config(struct usb_configuration *c) +static __ref int cdc_do_config(struct usb_configuration *c) { int ret; @@ -208,20 +239,33 @@ static int __init cdc_do_config(struct usb_configuration *c) if (ret < 0) return ret; - ret = fsg_add(c->cdev, c, fsg_common); + ret = fsg_bind_config(c->cdev, c, &fsg_common); if (ret < 0) return ret; return 0; } -static struct usb_configuration cdc_config_driver = { - .label = "Multifunction Composite (CDC + MS + ACM)", - .bind = cdc_do_config, - .bConfigurationValue = 1, - /* .iConfiguration = DYNAMIC */ - .bmAttributes = USB_CONFIG_ATT_SELFPOWER, -}; +static int cdc_config_register(struct usb_composite_dev *cdev) +{ + static struct usb_configuration config = { + .bind = cdc_do_config, + .bConfigurationValue = MULTI_CDC_CONFIG_NUM, + .bmAttributes = USB_CONFIG_ATT_SELFPOWER, + }; + + config.label = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s; + config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id; + + return usb_add_config(cdev, &config); +} + +#else + +static int cdc_config_register(struct usb_composite_dev *cdev) +{ + return 0; +} #endif @@ -230,7 +274,7 @@ static struct usb_configuration cdc_config_driver = { /****************************** Gadget Bind ******************************/ -static int __init multi_bind(struct usb_composite_dev *cdev) +static int __ref multi_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; int status, gcnum; @@ -252,67 +296,56 @@ static int __init multi_bind(struct usb_composite_dev *cdev) goto fail0; /* set up mass storage function */ - fsg_common = fsg_common_from_params(0, cdev, &mod_data); - if (IS_ERR(fsg_common)) { - status = PTR_ERR(fsg_common); - goto fail1; + { + void *retp; + retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data); + if (IS_ERR(retp)) { + status = PTR_ERR(retp); + goto fail1; + } } - + /* set bcdDevice */ gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) + if (gcnum >= 0) { device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else { - /* We assume that can_support_ecm() tells the truth; - * but if the controller isn't recognized at all then - * that assumption is a bit more likely to be wrong. - */ - WARNING(cdev, "controller '%s' not recognized\n", - gadget->name); + } else { + WARNING(cdev, "controller '%s' not recognized\n", gadget->name); device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); } - - /* Allocate string descriptor numbers ... note that string - * contents can be overridden by the composite_dev glue. - */ - - /* device descriptor strings: manufacturer, product */ + /* allocate string descriptor numbers */ snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); - if (status < 0) - goto fail2; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - status = usb_string_id(cdev); - if (status < 0) + status = usb_string_ids_tab(cdev, strings_dev); + if (unlikely(status < 0)) goto fail2; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; -#ifdef USB_ETH_RNDIS - /* register our first configuration */ - status = usb_add_config(cdev, &rndis_config_driver); - if (status < 0) + device_desc.iManufacturer = + strings_dev[MULTI_STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = + strings_dev[MULTI_STRING_PRODUCT_IDX].id; + + /* register configurations */ + status = rndis_config_register(cdev); + if (unlikely(status < 0)) goto fail2; -#endif -#ifdef CONFIG_USB_G_MULTI_CDC - /* register our second configuration */ - status = usb_add_config(cdev, &cdc_config_driver); - if (status < 0) + status = cdc_config_register(cdev); + if (unlikely(status < 0)) goto fail2; -#endif - dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); - fsg_common_put(fsg_common); + /* we're done */ + dev_info(&gadget->dev, DRIVER_DESC "\n"); + fsg_common_put(&fsg_common); return 0; + + /* error recovery */ fail2: - fsg_common_put(fsg_common); + fsg_common_put(&fsg_common); fail1: gserial_cleanup(); fail0: @@ -339,18 +372,15 @@ static struct usb_composite_driver multi_driver = { .unbind = __exit_p(multi_unbind), }; -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("Michal Nazarewicz"); -MODULE_LICENSE("GPL"); -static int __init g_multi_init(void) +static int __init multi_init(void) { return usb_composite_register(&multi_driver); } -module_init(g_multi_init); +module_init(multi_init); -static void __exit g_multi_cleanup(void) +static void __exit multi_exit(void) { usb_composite_unregister(&multi_driver); } -module_exit(g_multi_cleanup); +module_exit(multi_exit); diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 4c3ac5c42237..88f05996aa02 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1346,7 +1346,7 @@ printer_unbind(struct usb_gadget *gadget) set_gadget_data(gadget, NULL); } -static int __init +static int __ref printer_bind(struct usb_gadget *gadget) { struct printer_dev *dev; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index f46a60962dab..b22eedbc7dc5 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -137,7 +137,7 @@ MODULE_PARM_DESC(n_ports, "number of ports to create, default=1"); /*-------------------------------------------------------------------------*/ -static int __init serial_bind_config(struct usb_configuration *c) +static int __ref serial_bind_config(struct usb_configuration *c) { unsigned i; int status = 0; @@ -161,7 +161,7 @@ static struct usb_configuration serial_config_driver = { .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; -static int __init gs_bind(struct usb_composite_dev *cdev) +static int __ref gs_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c index 04c462ff0ea6..a10faecfabcd 100644 --- a/drivers/usb/gadget/storage_common.c +++ b/drivers/usb/gadget/storage_common.c @@ -57,10 +57,12 @@ #include <asm/unaligned.h> -/* Thanks to NetChip Technologies for donating this product ID. +/* + * Thanks to NetChip Technologies for donating this product ID. * * DO NOT REUSE THESE IDs with any other driver!! Ever!! - * Instead: allocate your own, using normal USB-IF procedures. */ + * Instead: allocate your own, using normal USB-IF procedures. + */ #define FSG_VENDOR_ID 0x0525 /* NetChip */ #define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ @@ -84,14 +86,27 @@ #define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) #define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) -/* Keep those macros in sync with thos in - * include/linux/ubs/composite.h or else GCC will complain. If they +/* + * Keep those macros in sync with those in + * include/linux/usb/composite.h or else GCC will complain. If they * are identical (the same names of arguments, white spaces in the * same places) GCC will allow redefinition otherwise (even if some - * white space is removed or added) warning will be issued. No - * checking if those symbols is defined is performed because warning - * is desired when those macros were defined by someone else to mean - * something else. */ + * white space is removed or added) warning will be issued. + * + * Those macros are needed here because File Storage Gadget does not + * include the composite.h header. For composite gadgets those macros + * are redundant since composite.h is included any way. + * + * One could check whether those macros are already defined (which + * would indicate composite.h had been included) or not (which would + * indicate we were in FSG) but this is not done because a warning is + * desired if definitions here differ from the ones in composite.h. + * + * We want the definitions to match and be the same in File Storage + * Gadget as well as Mass Storage Function (and so composite gadgets + * using MSF). If someone changes them in composite.h it will produce + * a warning in this file when building MSF. + */ #define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) #define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) #define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) @@ -313,9 +328,11 @@ struct fsg_buffhd { enum fsg_buffer_state state; struct fsg_buffhd *next; - /* The NetChip 2280 is faster, and handles some protocol faults + /* + * The NetChip 2280 is faster, and handles some protocol faults * better, if we don't submit any short bulk-out read requests. - * So we will record the intended request length here. */ + * So we will record the intended request length here. + */ unsigned int bulk_out_intended_length; struct usb_request *inreq; @@ -395,8 +412,10 @@ fsg_intf_desc = { .iInterface = FSG_STRING_INTERFACE, }; -/* Three full-speed endpoint descriptors: bulk-in, bulk-out, - * and interrupt-in. */ +/* + * Three full-speed endpoint descriptors: bulk-in, bulk-out, and + * interrupt-in. + */ static struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = { @@ -459,7 +478,7 @@ static struct usb_descriptor_header *fsg_fs_function[] = { * * That means alternate endpoint descriptors (bigger packets) * and a "device qualifier" ... plus more construction options - * for the config descriptor. + * for the configuration descriptor. */ static struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = { @@ -547,8 +566,10 @@ static struct usb_gadget_strings fsg_stringtab = { /*-------------------------------------------------------------------------*/ -/* If the next two routines are called while the gadget is registered, - * the caller must own fsg->filesem for writing. */ +/* + * If the next two routines are called while the gadget is registered, + * the caller must own fsg->filesem for writing. + */ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) { @@ -587,8 +608,10 @@ static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) goto out; } - /* If we can't read the file, it's no good. - * If we can't write the file, use it read-only. */ + /* + * If we can't read the file, it's no good. + * If we can't write the file, use it read-only. + */ if (!filp->f_op || !(filp->f_op->read || filp->f_op->aio_read)) { LINFO(curlun, "file not readable: %s\n", filename); goto out; @@ -646,8 +669,10 @@ static void fsg_lun_close(struct fsg_lun *curlun) /*-------------------------------------------------------------------------*/ -/* Sync the file data, don't bother with the metadata. - * This code was copied from fs/buffer.c:sys_fdatasync(). */ +/* + * Sync the file data, don't bother with the metadata. + * This code was copied from fs/buffer.c:sys_fdatasync(). + */ static int fsg_lun_fsync_sub(struct fsg_lun *curlun) { struct file *filp = curlun->filp; @@ -728,8 +753,10 @@ static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, if (sscanf(buf, "%d", &i) != 1) return -EINVAL; - /* Allow the write-enable status to change only while the backing file - * is closed. */ + /* + * Allow the write-enable status to change only while the + * backing file is closed. + */ down_read(filesem); if (fsg_lun_is_open(curlun)) { LDBG(curlun, "read-only status change prevented\n"); diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 1da755a1c855..6bb876d65252 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -704,17 +704,6 @@ static char *host_addr; module_param(host_addr, charp, S_IRUGO); MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); - -static u8 __init nibble(unsigned char c) -{ - if (isdigit(c)) - return c - '0'; - c = toupper(c); - if (isxdigit(c)) - return 10 + c - 'A'; - return 0; -} - static int get_ether_addr(const char *str, u8 *dev_addr) { if (str) { @@ -725,8 +714,8 @@ static int get_ether_addr(const char *str, u8 *dev_addr) if ((*str == '.') || (*str == ':')) str++; - num = nibble(*str++) << 4; - num |= (nibble(*str++)); + num = hex_to_bin(*str++) << 4; + num |= hex_to_bin(*str++); dev_addr [i] = num; } if (is_valid_ether_addr(dev_addr)) diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 3e8dcb5455e3..01e5354a4c20 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -18,6 +18,7 @@ /* #define VERBOSE_DEBUG */ #include <linux/kernel.h> +#include <linux/sched.h> #include <linux/interrupt.h> #include <linux/device.h> #include <linux/delay.h> diff --git a/drivers/usb/gadget/uvc.h b/drivers/usb/gadget/uvc.h index e92454cddd7d..5b7919460fd2 100644 --- a/drivers/usb/gadget/uvc.h +++ b/drivers/usb/gadget/uvc.h @@ -48,39 +48,6 @@ struct uvc_event #define UVC_INTF_STREAMING 1 /* ------------------------------------------------------------------------ - * UVC constants & structures - */ - -/* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ -#define UVC_STREAM_EOH (1 << 7) -#define UVC_STREAM_ERR (1 << 6) -#define UVC_STREAM_STI (1 << 5) -#define UVC_STREAM_RES (1 << 4) -#define UVC_STREAM_SCR (1 << 3) -#define UVC_STREAM_PTS (1 << 2) -#define UVC_STREAM_EOF (1 << 1) -#define UVC_STREAM_FID (1 << 0) - -struct uvc_streaming_control { - __u16 bmHint; - __u8 bFormatIndex; - __u8 bFrameIndex; - __u32 dwFrameInterval; - __u16 wKeyFrameRate; - __u16 wPFrameRate; - __u16 wCompQuality; - __u16 wCompWindowSize; - __u16 wDelay; - __u32 dwMaxVideoFrameSize; - __u32 dwMaxPayloadTransferSize; - __u32 dwClockFrequency; - __u8 bmFramingInfo; - __u8 bPreferedVersion; - __u8 bMinVersion; - __u8 bMaxVersion; -} __attribute__((__packed__)); - -/* ------------------------------------------------------------------------ * Debugging, printing and logging */ @@ -137,9 +104,6 @@ extern unsigned int uvc_gadget_trace_param; #define UVC_MAX_REQUEST_SIZE 64 #define UVC_MAX_EVENTS 4 -#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8 -#define USB_CLASS_MISC 0xef - /* ------------------------------------------------------------------------ * Structures */ diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index f5f3030cc416..de1deb7a3c63 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -90,7 +90,7 @@ DECLARE_UVC_HEADER_DESCRIPTOR(1); static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { .bLength = UVC_DT_HEADER_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_HEADER, + .bDescriptorSubType = UVC_VC_HEADER, .bcdUVC = cpu_to_le16(0x0100), .wTotalLength = 0, /* dynamic */ .dwClockFrequency = cpu_to_le32(48000000), @@ -101,7 +101,7 @@ static const struct UVC_HEADER_DESCRIPTOR(1) uvc_control_header = { static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = { .bLength = UVC_DT_CAMERA_TERMINAL_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_INPUT_TERMINAL, + .bDescriptorSubType = UVC_VC_INPUT_TERMINAL, .bTerminalID = 1, .wTerminalType = cpu_to_le16(0x0201), .bAssocTerminal = 0, @@ -118,7 +118,7 @@ static const struct uvc_camera_terminal_descriptor uvc_camera_terminal = { static const struct uvc_processing_unit_descriptor uvc_processing = { .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_PROCESSING_UNIT, + .bDescriptorSubType = UVC_VC_PROCESSING_UNIT, .bUnitID = 2, .bSourceID = 1, .wMaxMultiplier = cpu_to_le16(16*1024), @@ -131,7 +131,7 @@ static const struct uvc_processing_unit_descriptor uvc_processing = { static const struct uvc_output_terminal_descriptor uvc_output_terminal = { .bLength = UVC_DT_OUTPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_OUTPUT_TERMINAL, + .bDescriptorSubType = UVC_VC_OUTPUT_TERMINAL, .bTerminalID = 3, .wTerminalType = cpu_to_le16(0x0101), .bAssocTerminal = 0, @@ -144,7 +144,7 @@ DECLARE_UVC_INPUT_HEADER_DESCRIPTOR(1, 2); static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = { .bLength = UVC_DT_INPUT_HEADER_SIZE(1, 2), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_INPUT_HEADER, + .bDescriptorSubType = UVC_VS_INPUT_HEADER, .bNumFormats = 2, .wTotalLength = 0, /* dynamic */ .bEndpointAddress = 0, /* dynamic */ @@ -161,7 +161,7 @@ static const struct UVC_INPUT_HEADER_DESCRIPTOR(1, 2) uvc_input_header = { static const struct uvc_format_uncompressed uvc_format_yuv = { .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_FORMAT_UNCOMPRESSED, + .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED, .bFormatIndex = 1, .bNumFrameDescriptors = 2, .guidFormat = @@ -181,7 +181,7 @@ DECLARE_UVC_FRAME_UNCOMPRESSED(3); static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = { .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_FRAME_UNCOMPRESSED, + .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, .bFrameIndex = 1, .bmCapabilities = 0, .wWidth = cpu_to_le16(640), @@ -199,7 +199,7 @@ static const struct UVC_FRAME_UNCOMPRESSED(3) uvc_frame_yuv_360p = { static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = { .bLength = UVC_DT_FRAME_UNCOMPRESSED_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_FRAME_UNCOMPRESSED, + .bDescriptorSubType = UVC_VS_FRAME_UNCOMPRESSED, .bFrameIndex = 2, .bmCapabilities = 0, .wWidth = cpu_to_le16(1280), @@ -215,7 +215,7 @@ static const struct UVC_FRAME_UNCOMPRESSED(1) uvc_frame_yuv_720p = { static const struct uvc_format_mjpeg uvc_format_mjpg = { .bLength = UVC_DT_FORMAT_MJPEG_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_FORMAT_MJPEG, + .bDescriptorSubType = UVC_VS_FORMAT_MJPEG, .bFormatIndex = 2, .bNumFrameDescriptors = 2, .bmFlags = 0, @@ -232,7 +232,7 @@ DECLARE_UVC_FRAME_MJPEG(3); static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_FRAME_MJPEG, + .bDescriptorSubType = UVC_VS_FRAME_MJPEG, .bFrameIndex = 1, .bmCapabilities = 0, .wWidth = cpu_to_le16(640), @@ -250,7 +250,7 @@ static const struct UVC_FRAME_MJPEG(3) uvc_frame_mjpg_360p = { static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_FRAME_MJPEG, + .bDescriptorSubType = UVC_VS_FRAME_MJPEG, .bFrameIndex = 2, .bmCapabilities = 0, .wWidth = cpu_to_le16(1280), @@ -266,7 +266,7 @@ static const struct UVC_FRAME_MJPEG(1) uvc_frame_mjpg_720p = { static const struct uvc_color_matching_descriptor uvc_color_matching = { .bLength = UVC_DT_COLOR_MATCHING_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubType = UVC_DT_COLOR_MATCHING, + .bDescriptorSubType = UVC_VS_COLORFORMAT, .bColorPrimaries = 1, .bTransferCharacteristics = 1, .bMatrixCoefficients = 4, @@ -308,7 +308,7 @@ static const struct uvc_descriptor_header * const uvc_hs_streaming_cls[] = { * USB configuration */ -static int __init +static int __ref webcam_config_bind(struct usb_configuration *c) { return uvc_bind_config(c, uvc_control_cls, uvc_fs_streaming_cls, @@ -330,7 +330,7 @@ webcam_unbind(struct usb_composite_dev *cdev) return 0; } -static int __init +static int __ref webcam_bind(struct usb_composite_dev *cdev) { int ret; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 807280d069f9..cf353920bb1c 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -264,7 +264,7 @@ static void zero_resume(struct usb_composite_dev *cdev) /*-------------------------------------------------------------------------*/ -static int __init zero_bind(struct usb_composite_dev *cdev) +static int __ref zero_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index f865be2276d4..2d926cec0725 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -72,8 +72,9 @@ config USB_EHCI_ROOT_HUB_TT from ARC, and has since changed hands a few times. config USB_EHCI_TT_NEWSCHED - bool "Improved Transaction Translator scheduling (EXPERIMENTAL)" - depends on USB_EHCI_HCD && EXPERIMENTAL + bool "Improved Transaction Translator scheduling" + depends on USB_EHCI_HCD + default y ---help--- This changes the periodic scheduling code to fill more of the low and full speed bandwidth available from the Transaction Translator @@ -84,9 +85,11 @@ config USB_EHCI_TT_NEWSCHED If you have multiple periodic low/fullspeed devices connected to a highspeed USB hub which is connected to a highspeed USB Host Controller, and some of those devices will not work correctly - (possibly due to "ENOSPC" or "-28" errors), say Y. + (possibly due to "ENOSPC" or "-28" errors), say Y. Conversely, if + you have only one such device and it doesn't work, you could try + saying N. - If unsure, say N. + If unsure, say Y. config USB_EHCI_BIG_ENDIAN_MMIO bool diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index faa61748db70..2baf8a849086 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -228,7 +228,7 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) * the root hub is either suspended or stopped. */ spin_lock_irqsave(&ehci->lock, flags); - ehci_prepare_ports_for_controller_suspend(ehci); + ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); ehci_writel(ehci, 0, &ehci->regs->intr_enable); (void)ehci_readl(ehci, &ehci->regs->intr_enable); diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 874d2000bf92..4498efb49b95 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -98,13 +98,18 @@ static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); } else { ehci_dbg (ehci, - "%s hcc_params %04x thresh %d uframes %s%s%s\n", + "%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n", label, params, HCC_ISOC_THRES(params), HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", HCC_CANPARK(params) ? " park" : "", - HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); + HCC_64BIT_ADDR(params) ? " 64 bit addr" : "", + HCC_LPM(params) ? " LPM" : "", + HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "", + HCC_HW_PREFETCH(params) ? " hw prefetch" : "", + HCC_32FRAME_PERIODIC_LIST(params) ? + " 32 peridic list" : ""); } } #else @@ -191,8 +196,9 @@ static int __maybe_unused dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) { return scnprintf (buf, len, - "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s", + "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", status, + (status & STS_PPCE_MASK) ? " PPCE" : "", (status & STS_ASS) ? " Async" : "", (status & STS_PSS) ? " Periodic" : "", (status & STS_RECL) ? " Recl" : "", @@ -210,8 +216,9 @@ static int __maybe_unused dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) { return scnprintf (buf, len, - "%s%sintrenable %02x%s%s%s%s%s%s", + "%s%sintrenable %02x%s%s%s%s%s%s%s", label, label [0] ? " " : "", enable, + (enable & STS_PPCE_MASK) ? " PPCE" : "", (enable & STS_IAA) ? " IAA" : "", (enable & STS_FATAL) ? " FATAL" : "", (enable & STS_FLR) ? " FLR" : "", @@ -228,9 +235,15 @@ static int dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) { return scnprintf (buf, len, - "%s%scommand %06x %s=%d ithresh=%d%s%s%s%s period=%s%s %s", + "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " + "period=%s%s %s", label, label [0] ? " " : "", command, - (command & CMD_PARK) ? "park" : "(park)", + (command & CMD_HIRD) ? " HIRD" : "", + (command & CMD_PPCEE) ? " PPCEE" : "", + (command & CMD_FSP) ? " FSP" : "", + (command & CMD_ASPE) ? " ASPE" : "", + (command & CMD_PSPE) ? " PSPE" : "", + (command & CMD_PARK) ? " park" : "(park)", CMD_PARK_CNT (command), (command >> 16) & 0x3f, (command & CMD_LRESET) ? " LReset" : "", @@ -257,11 +270,22 @@ dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) } return scnprintf (buf, len, - "%s%sport %d status %06x%s%s sig=%s%s%s%s%s%s%s%s%s%s", + "%s%sport:%d status %06x %d %s%s%s%s%s%s " + "sig=%s%s%s%s%s%s%s%s%s%s%s", label, label [0] ? " " : "", port, status, + status>>25,/*device address */ + (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? + " ACK" : "", + (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ? + " NYET" : "", + (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ? + " STALL" : "", + (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ? + " ERR" : "", (status & PORT_POWER) ? " POWER" : "", (status & PORT_OWNER) ? " OWNER" : "", sig, + (status & PORT_LPM) ? " LPM" : "", (status & PORT_RESET) ? " RESET" : "", (status & PORT_SUSPEND) ? " SUSPEND" : "", (status & PORT_RESUME) ? " RESUME" : "", @@ -330,6 +354,13 @@ static int debug_async_open(struct inode *, struct file *); static int debug_periodic_open(struct inode *, struct file *); static int debug_registers_open(struct inode *, struct file *); static int debug_async_open(struct inode *, struct file *); +static int debug_lpm_open(struct inode *, struct file *); +static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos); +static ssize_t debug_lpm_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos); +static int debug_lpm_close(struct inode *inode, struct file *file); + static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); static int debug_close(struct inode *, struct file *); @@ -351,6 +382,13 @@ static const struct file_operations debug_registers_fops = { .read = debug_output, .release = debug_close, }; +static const struct file_operations debug_lpm_fops = { + .owner = THIS_MODULE, + .open = debug_lpm_open, + .read = debug_lpm_read, + .write = debug_lpm_write, + .release = debug_lpm_close, +}; static struct dentry *ehci_debug_root; @@ -674,7 +712,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) spin_lock_irqsave (&ehci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { size = scnprintf (next, size, "bus %s, device %s\n" "%s\n" @@ -917,6 +955,94 @@ static int debug_registers_open(struct inode *inode, struct file *file) return file->private_data ? 0 : -ENOMEM; } +static int debug_lpm_open(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +static int debug_lpm_close(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t debug_lpm_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + /* TODO: show lpm stats */ + return 0; +} + +static ssize_t debug_lpm_write(struct file *file, const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct usb_hcd *hcd; + struct ehci_hcd *ehci; + char buf[50]; + size_t len; + u32 temp; + unsigned long port; + u32 __iomem *portsc ; + u32 params; + + hcd = bus_to_hcd(file->private_data); + ehci = hcd_to_ehci(hcd); + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + buf[len] = '\0'; + if (len > 0 && buf[len - 1] == '\n') + buf[len - 1] = '\0'; + + if (strncmp(buf, "enable", 5) == 0) { + if (strict_strtoul(buf + 7, 10, &port)) + return -EINVAL; + params = ehci_readl(ehci, &ehci->caps->hcs_params); + if (port > HCS_N_PORTS(params)) { + ehci_dbg(ehci, "ERR: LPM on bad port %lu\n", port); + return -ENODEV; + } + portsc = &ehci->regs->port_status[port-1]; + temp = ehci_readl(ehci, portsc); + if (!(temp & PORT_DEV_ADDR)) { + ehci_dbg(ehci, "LPM: no device attached\n"); + return -ENODEV; + } + temp |= PORT_LPM; + ehci_writel(ehci, temp, portsc); + printk(KERN_INFO "force enable LPM for port %lu\n", port); + } else if (strncmp(buf, "hird=", 5) == 0) { + unsigned long hird; + if (strict_strtoul(buf + 5, 16, &hird)) + return -EINVAL; + printk(KERN_INFO "setting hird %s %lu\n", buf + 6, hird); + temp = ehci_readl(ehci, &ehci->regs->command); + temp &= ~CMD_HIRD; + temp |= hird << 24; + ehci_writel(ehci, temp, &ehci->regs->command); + } else if (strncmp(buf, "disable", 7) == 0) { + if (strict_strtoul(buf + 8, 10, &port)) + return -EINVAL; + params = ehci_readl(ehci, &ehci->caps->hcs_params); + if (port > HCS_N_PORTS(params)) { + ehci_dbg(ehci, "ERR: LPM off bad port %lu\n", port); + return -ENODEV; + } + portsc = &ehci->regs->port_status[port-1]; + temp = ehci_readl(ehci, portsc); + if (!(temp & PORT_DEV_ADDR)) { + ehci_dbg(ehci, "ERR: no device attached\n"); + return -ENODEV; + } + temp &= ~PORT_LPM; + ehci_writel(ehci, temp, portsc); + printk(KERN_INFO "disabled LPM for port %lu\n", port); + } else + return -EOPNOTSUPP; + return count; +} + static inline void create_debug_files (struct ehci_hcd *ehci) { struct usb_bus *bus = &ehci_to_hcd(ehci)->self; @@ -940,6 +1066,10 @@ static inline void create_debug_files (struct ehci_hcd *ehci) ehci->debug_registers = debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, &debug_registers_fops); + + ehci->debug_registers = debugfs_create_file("lpm", S_IRUGO|S_IWUGO, + ehci->debug_dir, bus, + &debug_lpm_fops); if (!ehci->debug_registers) goto registers_error; return; diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 5cd967d28938..a416421abfa2 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -313,7 +313,8 @@ static int ehci_fsl_drv_suspend(struct device *dev) struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); void __iomem *non_ehci = hcd->regs; - ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd)); + ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), + device_may_wakeup(dev)); if (!fsl_deep_sleep()) return 0; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a3ef2a9d9dc2..2e704fa3cedf 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -36,6 +36,7 @@ #include <linux/dma-mapping.h> #include <linux/debugfs.h> #include <linux/slab.h> +#include <linux/uaccess.h> #include <asm/byteorder.h> #include <asm/io.h> @@ -100,6 +101,11 @@ static int ignore_oc = 0; module_param (ignore_oc, bool, S_IRUGO); MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); +/* for link power management(LPM) feature */ +static unsigned int hird; +module_param(hird, int, S_IRUGO); +MODULE_PARM_DESC(hird, "host initiated resume duration, +1 for each 75us\n"); + #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) /*-------------------------------------------------------------------------*/ @@ -304,6 +310,7 @@ static void end_unlink_async(struct ehci_hcd *ehci); static void ehci_work(struct ehci_hcd *ehci); #include "ehci-hub.c" +#include "ehci-lpm.c" #include "ehci-mem.c" #include "ehci-q.c" #include "ehci-sched.c" @@ -577,6 +584,11 @@ static int ehci_init(struct usb_hcd *hcd) if (log2_irq_thresh < 0 || log2_irq_thresh > 6) log2_irq_thresh = 0; temp = 1 << (16 + log2_irq_thresh); + if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) { + ehci->has_ppcd = 1; + ehci_dbg(ehci, "enable per-port change event\n"); + temp |= CMD_PPCEE; + } if (HCC_CANPARK(hcc_params)) { /* HW default park == 3, on hardware that supports it (like * NVidia and ALI silicon), maximizes throughput on the async @@ -603,10 +615,22 @@ static int ehci_init(struct usb_hcd *hcd) default: BUG(); } } + if (HCC_LPM(hcc_params)) { + /* support link power management EHCI 1.1 addendum */ + ehci_dbg(ehci, "support lpm\n"); + ehci->has_lpm = 1; + if (hird > 0xf) { + ehci_dbg(ehci, "hird %d invalid, use default 0", + hird); + hird = 0; + } + temp |= hird << 24; + } ehci->command = temp; /* Accept arbitrarily long scatter-gather lists */ - hcd->self.sg_tablesize = ~0; + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; return 0; } @@ -619,7 +643,6 @@ static int ehci_run (struct usb_hcd *hcd) u32 hcc_params; hcd->uses_new_polling = 1; - hcd->poll_rh = 0; /* EHCI spec section 4.1 */ if ((retval = ehci_reset(ehci)) != 0) { @@ -764,6 +787,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) /* remote wakeup [4.3.1] */ if (status & STS_PCD) { unsigned i = HCS_N_PORTS (ehci->hcs_params); + u32 ppcd = 0; /* kick root hub later */ pcd_status = status; @@ -772,9 +796,18 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) if (!(cmd & CMD_RUN)) usb_hcd_resume_root_hub(hcd); + /* get per-port change detect bits */ + if (ehci->has_ppcd) + ppcd = status >> 16; + while (i--) { - int pstatus = ehci_readl(ehci, - &ehci->regs->port_status [i]); + int pstatus; + + /* leverage per-port change bits feature */ + if (ehci->has_ppcd && !(ppcd & (1 << i))) + continue; + pstatus = ehci_readl(ehci, + &ehci->regs->port_status[i]); if (pstatus & PORT_OWNER) continue; diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index e7d3d8def282..796ea0c8900f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) } static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - bool suspending) + bool suspending, bool do_wakeup) { int port; u32 temp; @@ -117,8 +117,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, * when the controller is suspended or resumed. In all other * cases they don't need to be changed. */ - if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || - device_may_wakeup(ehci_to_hcd(ehci)->self.controller)) + if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) return; /* clear phy low-power mode before changing wakeup flags */ @@ -167,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); } } + + /* Does the root hub have a port wakeup pending? */ + if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) + usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); } static int ehci_bus_suspend (struct usb_hcd *hcd) @@ -316,7 +319,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd) if (time_before (jiffies, ehci->next_statechange)) msleep(5); spin_lock_irq (&ehci->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { spin_unlock_irq(&ehci->lock); return -ESHUTDOWN; } @@ -603,6 +606,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) u32 mask; int ports, i, retval = 1; unsigned long flags; + u32 ppcd = 0; /* if !USB_SUSPEND, root hub timers won't get shut down ... */ if (!HC_IS_RUNNING(hcd->state)) @@ -632,7 +636,15 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) /* port N changes (bit N)? */ spin_lock_irqsave (&ehci->lock, flags); + + /* get per-port change detect bits */ + if (ehci->has_ppcd) + ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16; + for (i = 0; i < ports; i++) { + /* leverage per-port change bits feature */ + if (ehci->has_ppcd && !(ppcd & (1 << i))) + continue; temp = ehci_readl(ehci, &ehci->regs->port_status [i]); /* @@ -790,6 +802,11 @@ static int ehci_hub_control ( status_reg); break; case USB_PORT_FEAT_C_CONNECTION: + if (ehci->has_lpm) { + /* clear PORTSC bits on disconnect */ + temp &= ~PORT_LPM; + temp &= ~PORT_DEV_ADDR; + } ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, status_reg); break; diff --git a/drivers/usb/host/ehci-lpm.c b/drivers/usb/host/ehci-lpm.c new file mode 100644 index 000000000000..b4d4d63c13ed --- /dev/null +++ b/drivers/usb/host/ehci-lpm.c @@ -0,0 +1,83 @@ +/* ehci-lpm.c EHCI HCD LPM support code + * Copyright (c) 2008 - 2010, Intel Corporation. + * Author: Jacob Pan <jacob.jun.pan@intel.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* this file is part of ehci-hcd.c */ +static int ehci_lpm_set_da(struct ehci_hcd *ehci, int dev_addr, int port_num) +{ + u32 __iomem portsc; + + ehci_dbg(ehci, "set dev address %d for port %d\n", dev_addr, port_num); + if (port_num > HCS_N_PORTS(ehci->hcs_params)) { + ehci_dbg(ehci, "invalid port number %d\n", port_num); + return -ENODEV; + } + portsc = ehci_readl(ehci, &ehci->regs->port_status[port_num-1]); + portsc &= ~PORT_DEV_ADDR; + portsc |= dev_addr<<25; + ehci_writel(ehci, portsc, &ehci->regs->port_status[port_num-1]); + return 0; +} + +/* + * this function is used to check if the device support LPM + * if yes, mark the PORTSC register with PORT_LPM bit + */ +static int ehci_lpm_check(struct ehci_hcd *ehci, int port) +{ + u32 __iomem *portsc ; + u32 val32; + int retval; + + portsc = &ehci->regs->port_status[port-1]; + val32 = ehci_readl(ehci, portsc); + if (!(val32 & PORT_DEV_ADDR)) { + ehci_dbg(ehci, "LPM: no device attached\n"); + return -ENODEV; + } + val32 |= PORT_LPM; + ehci_writel(ehci, val32, portsc); + msleep(5); + val32 |= PORT_SUSPEND; + ehci_dbg(ehci, "Sending LPM 0x%08x to port %d\n", val32, port); + ehci_writel(ehci, val32, portsc); + /* wait for ACK */ + msleep(10); + retval = handshake(ehci, &ehci->regs->port_status[port-1], PORT_SSTS, + PORTSC_SUSPEND_STS_ACK, 125); + dbg_port(ehci, "LPM", port, val32); + if (retval != -ETIMEDOUT) { + ehci_dbg(ehci, "LPM: device ACK for LPM\n"); + val32 |= PORT_LPM; + /* + * now device should be in L1 sleep, let's wake up the device + * so that we can complete enumeration. + */ + ehci_writel(ehci, val32, portsc); + msleep(10); + val32 |= PORT_RESUME; + ehci_writel(ehci, val32, portsc); + } else { + ehci_dbg(ehci, "LPM: device does not ACK, disable LPM %d\n", + retval); + val32 &= ~PORT_LPM; + retval = -ETIMEDOUT; + ehci_writel(ehci, val32, portsc); + } + + return retval; +} diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 5450e628157f..116ae280053a 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -38,6 +38,7 @@ #include <linux/gpio.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> +#include <linux/usb/ulpi.h> #include <plat/usb.h> /* @@ -236,6 +237,35 @@ static void omap_usb_utmi_init(struct ehci_hcd_omap *omap, u8 tll_channel_mask) /*-------------------------------------------------------------------------*/ +static void omap_ehci_soft_phy_reset(struct ehci_hcd_omap *omap, u8 port) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(1000); + unsigned reg = 0; + + reg = ULPI_FUNC_CTRL_RESET + /* FUNCTION_CTRL_SET register */ + | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) + /* Write */ + | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) + /* PORTn */ + | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) + /* start ULPI access*/ + | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); + + ehci_omap_writel(omap->ehci_base, EHCI_INSNREG05_ULPI, reg); + + /* Wait for ULPI access completion */ + while ((ehci_omap_readl(omap->ehci_base, EHCI_INSNREG05_ULPI) + & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) { + cpu_relax(); + + if (time_after(jiffies, timeout)) { + dev_dbg(omap->dev, "phy reset operation timed out\n"); + break; + } + } +} + /* omap_start_ehc * - Start the TI USBHOST controller */ @@ -425,6 +455,12 @@ static int omap_start_ehc(struct ehci_hcd_omap *omap, struct usb_hcd *hcd) gpio_set_value(omap->reset_gpio_port[1], 1); } + /* Soft reset the PHY using PHY reset command over ULPI */ + if (omap->port_mode[0] == EHCI_HCD_OMAP_MODE_PHY) + omap_ehci_soft_phy_reset(omap, 0); + if (omap->port_mode[1] == EHCI_HCD_OMAP_MODE_PHY) + omap_ehci_soft_phy_reset(omap, 1); + return 0; err_sys_status: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index d43d176161aa..f555e4f35a04 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -277,7 +277,7 @@ done: * Also they depend on separate root hub suspend/resume. */ -static int ehci_pci_suspend(struct usb_hcd *hcd) +static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned long flags; @@ -291,7 +291,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd) * the root hub is either suspended or stopped. */ spin_lock_irqsave (&ehci->lock, flags); - ehci_prepare_ports_for_controller_suspend(ehci); + ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); ehci_writel(ehci, 0, &ehci->regs->intr_enable); (void)ehci_readl(ehci, &ehci->regs->intr_enable); @@ -361,6 +361,22 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) } #endif +static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int rc = 0; + + if (!udev->parent) /* udev is root hub itself, impossible */ + rc = -1; + /* we only support lpm device connected to root hub yet */ + if (ehci->has_lpm && !udev->parent->parent) { + rc = ehci_lpm_set_da(ehci, udev->devnum, udev->portnum); + if (!rc) + rc = ehci_lpm_check(ehci, udev->portnum); + } + return rc; +} + static const struct hc_driver ehci_pci_hc_driver = { .description = hcd_name, .product_desc = "EHCI Host Controller", @@ -407,6 +423,11 @@ static const struct hc_driver ehci_pci_hc_driver = { .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, + /* + * call back when device connected and addressed + */ + .update_device = ehci_update_device, + .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 11a79c4f4a9d..233c288e3f93 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1126,8 +1126,7 @@ submit_async ( #endif spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, - &ehci_to_hcd(ehci)->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { rc = -ESHUTDOWN; goto done; } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 805ec633a652..d640346f9b56 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -880,8 +880,7 @@ static int intr_submit ( spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, - &ehci_to_hcd(ehci)->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; } @@ -1815,8 +1814,7 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, - &ehci_to_hcd(ehci)->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; } @@ -2201,8 +2199,7 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, /* schedule ... need to lock */ spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, - &ehci_to_hcd(ehci)->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { status = -ESHUTDOWN; goto done_not_linked; } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 650a687f2854..a4a63ce290e9 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -140,7 +140,8 @@ struct ehci_hcd { /* one per controller */ #define OHCI_HCCTRL_LEN 0x4 __hc32 *ohci_hcctrl_reg; unsigned has_hostpc:1; - + unsigned has_lpm:1; /* support link power management */ + unsigned has_ppcd:1; /* support per-port change bits */ u8 sbrn; /* packed release number */ /* irq statistics */ @@ -157,6 +158,7 @@ struct ehci_hcd { /* one per controller */ struct dentry *debug_async; struct dentry *debug_periodic; struct dentry *debug_registers; + struct dentry *debug_lpm; #endif }; @@ -538,11 +540,11 @@ struct ehci_fstn { /* Prepare the PORTSC wakeup flags during controller suspend/resume */ -#define ehci_prepare_ports_for_controller_suspend(ehci) \ - ehci_adjust_port_wakeup_flags(ehci, true); +#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ + ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup); -#define ehci_prepare_ports_for_controller_resume(ehci) \ - ehci_adjust_port_wakeup_flags(ehci, false); +#define ehci_prepare_ports_for_controller_resume(ehci) \ + ehci_adjust_port_wakeup_flags(ehci, false, false); /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 35742f8c7cda..9bfac657572e 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -159,7 +159,7 @@ static int hwahc_op_start(struct usb_hcd *usb_hcd) goto error_set_cluster_id; usb_hcd->uses_new_polling = 1; - usb_hcd->poll_rh = 1; + set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags); usb_hcd->state = HC_STATE_RUNNING; result = 0; out: @@ -776,7 +776,7 @@ static int hwahc_probe(struct usb_interface *usb_iface, goto error_alloc; } usb_hcd->wireless = 1; - usb_hcd->flags |= HCD_FLAG_SAW_IRQ; + set_bit(HCD_FLAG_SAW_IRQ, &usb_hcd->flags); wusbhc = usb_hcd_to_wusbhc(usb_hcd); hwahc = container_of(wusbhc, struct hwahc, wusbhc); hwahc_init(hwahc); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index dbcafa29c775..d1a3dfc9a408 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -482,7 +482,6 @@ static int isp1760_run(struct usb_hcd *hcd) u32 chipid; hcd->uses_new_polling = 1; - hcd->poll_rh = 0; hcd->state = HC_STATE_RUNNING; isp1760_enable_interrupts(hcd); @@ -1450,7 +1449,7 @@ static int isp1760_prepare_enqueue(struct isp1760_hcd *priv, struct urb *urb, epnum = urb->ep->desc.bEndpointAddress; spin_lock_irqsave(&priv->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &priv_to_hcd(priv)->flags)) { + if (!HCD_HW_ACCESSIBLE(priv_to_hcd(priv))) { rc = -ESHUTDOWN; goto done; } diff --git a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c index 8ad2441b0284..36abd2baa3ea 100644 --- a/drivers/usb/host/ohci-dbg.c +++ b/drivers/usb/host/ohci-dbg.c @@ -645,7 +645,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) hcd->product_desc, hcd_name); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { size -= scnprintf (next, size, "SUSPENDED (no register access)\n"); goto done; @@ -687,7 +687,7 @@ static ssize_t fill_registers_buffer(struct debug_buffer *buf) next += temp; temp = scnprintf (next, size, "hub poll timer %s\n", - ohci_to_hcd(ohci)->poll_rh ? "ON" : "off"); + HCD_POLL_RH(ohci_to_hcd(ohci)) ? "ON" : "off"); size -= temp; next += temp; diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index fc576557d8a5..a16eabc0cf41 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -212,7 +212,7 @@ static int ohci_urb_enqueue ( spin_lock_irqsave (&ohci->lock, flags); /* don't submit to a dead HC */ - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { retval = -ENODEV; goto fail; } @@ -685,7 +685,7 @@ retry: } /* use rhsc irqs after khubd is fully initialized */ - hcd->poll_rh = 1; + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); hcd->uses_new_polling = 1; /* start controller operations */ @@ -822,7 +822,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd) else if (ints & OHCI_INTR_RD) { ohci_vdbg(ohci, "resume detect\n"); ohci_writel(ohci, OHCI_INTR_RD, ®s->intrstatus); - hcd->poll_rh = 1; + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); if (ohci->autostop) { spin_lock (&ohci->lock); ohci_rh_resume (ohci); diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 65cac8cc8921..cddcda95b579 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -284,7 +284,7 @@ static int ohci_bus_suspend (struct usb_hcd *hcd) spin_lock_irq (&ohci->lock); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) rc = -ESHUTDOWN; else rc = ohci_rh_suspend (ohci, 0); @@ -302,7 +302,7 @@ static int ohci_bus_resume (struct usb_hcd *hcd) spin_lock_irq (&ohci->lock); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) rc = -ESHUTDOWN; else rc = ohci_rh_resume (ohci); @@ -355,6 +355,11 @@ static void ohci_finish_controller_resume(struct usb_hcd *hcd) ohci_readl(ohci, &ohci->regs->intrenable); msleep(20); } + + /* Does the root hub have a port wakeup pending? */ + if (ohci_readl(ohci, &ohci->regs->intrstatus) & + (OHCI_INTR_RD | OHCI_INTR_RHSC)) + usb_hcd_resume_root_hub(hcd); } /* Carry out polling-, autostop-, and autoresume-related state changes */ @@ -364,7 +369,7 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int poll_rh = 1; int rhsc_enable; - /* Some broken controllers never turn off RHCS in the interrupt + /* Some broken controllers never turn off RHSC in the interrupt * status register. For their sake we won't re-enable RHSC * interrupts if the interrupt bit is already active. */ @@ -489,7 +494,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) unsigned long flags; spin_lock_irqsave (&ohci->lock, flags); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) goto done; /* undocumented erratum seen on at least rev D */ @@ -533,8 +538,12 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf) } } - hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed, - any_connected, rhsc_status); + if (ohci_root_hub_state_changes(ohci, changed, + any_connected, rhsc_status)) + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + else + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + done: spin_unlock_irqrestore (&ohci->lock, flags); @@ -701,7 +710,7 @@ static int ohci_hub_control ( u32 temp; int retval = 0; - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) return -ESHUTDOWN; switch (typeReq) { diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index b8a1148f248e..6bdc8b25a6a1 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -392,7 +392,7 @@ static int __devinit ohci_pci_start (struct usb_hcd *hcd) #ifdef CONFIG_PM -static int ohci_pci_suspend(struct usb_hcd *hcd) +static int ohci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); unsigned long flags; diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index f608dfd09a8a..d9c85a292737 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -1641,8 +1641,7 @@ static int submit_async(struct oxu_hcd *oxu, struct urb *urb, #endif spin_lock_irqsave(&oxu->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, - &oxu_to_hcd(oxu)->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) { rc = -ESHUTDOWN; goto done; } @@ -2209,8 +2208,7 @@ static int intr_submit(struct oxu_hcd *oxu, struct urb *urb, spin_lock_irqsave(&oxu->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, - &oxu_to_hcd(oxu)->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(oxu_to_hcd(oxu)))) { status = -ESHUTDOWN; goto done; } @@ -2715,7 +2713,6 @@ static int oxu_run(struct usb_hcd *hcd) u32 temp, hcc_params; hcd->uses_new_polling = 1; - hcd->poll_rh = 0; /* EHCI spec section 4.1 */ retval = ehci_reset(oxu); diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 98cf0b26b968..c168999722d1 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -495,18 +495,16 @@ static int uhci_debug_open(struct inode *inode, struct file *file) { struct uhci_hcd *uhci = inode->i_private; struct uhci_debug *up; - int ret = -ENOMEM; unsigned long flags; - lock_kernel(); up = kmalloc(sizeof(*up), GFP_KERNEL); if (!up) - goto out; + return -ENOMEM; up->data = kmalloc(MAX_OUTPUT, GFP_KERNEL); if (!up->data) { kfree(up); - goto out; + return -ENOMEM; } up->size = 0; @@ -517,10 +515,7 @@ static int uhci_debug_open(struct inode *inode, struct file *file) file->private_data = up; - ret = 0; -out: - unlock_kernel(); - return ret; + return 0; } static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) @@ -528,9 +523,9 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) struct uhci_debug *up; loff_t new = -1; - lock_kernel(); up = file->private_data; + /* XXX: atomic 64bit seek access, but that needs to be fixed in the VFS */ switch (whence) { case 0: new = off; @@ -539,11 +534,10 @@ static loff_t uhci_debug_lseek(struct file *file, loff_t off, int whence) new = file->f_pos + off; break; } - if (new < 0 || new > up->size) { - unlock_kernel(); + + if (new < 0 || new > up->size) return -EINVAL; - } - unlock_kernel(); + return (file->f_pos = new); } diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 6637e52736dd..b04506036b64 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -140,7 +140,7 @@ static void finish_reset(struct uhci_hcd *uhci) uhci->rh_state = UHCI_RH_RESET; uhci->is_stopped = UHCI_IS_STOPPED; uhci_to_hcd(uhci)->state = HC_STATE_HALT; - uhci_to_hcd(uhci)->poll_rh = 0; + clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); uhci->dead = 0; /* Full reset resurrects the controller */ } @@ -176,6 +176,8 @@ static void check_and_reset_hc(struct uhci_hcd *uhci) */ static void configure_hc(struct uhci_hcd *uhci) { + struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci)); + /* Set the frame length to the default: 1 ms exactly */ outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); @@ -191,8 +193,11 @@ static void configure_hc(struct uhci_hcd *uhci) mb(); /* Enable PIRQ */ - pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, - USBLEGSUP_DEFAULT); + pci_write_config_word(pdev, USBLEGSUP, USBLEGSUP_DEFAULT); + + /* Disable platform-specific non-PME# wakeup */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + pci_write_config_byte(pdev, USBRES_INTEL, 0); } @@ -344,7 +349,10 @@ __acquires(uhci->lock) /* If interrupts don't work and remote wakeup is enabled then * the suspended root hub needs to be polled. */ - uhci_to_hcd(uhci)->poll_rh = (!int_enable && wakeup_enable); + if (!int_enable && wakeup_enable) + set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); + else + clear_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); uhci_scan_schedule(uhci); uhci_fsbr_off(uhci); @@ -363,7 +371,7 @@ static void start_rh(struct uhci_hcd *uhci) uhci->io_addr + USBINTR); mb(); uhci->rh_state = UHCI_RH_RUNNING; - uhci_to_hcd(uhci)->poll_rh = 1; + set_bit(HCD_FLAG_POLL_RH, &uhci_to_hcd(uhci)->flags); } static void wakeup_rh(struct uhci_hcd *uhci) @@ -691,7 +699,9 @@ static int uhci_start(struct usb_hcd *hcd) configure_hc(uhci); uhci->is_initialized = 1; + spin_lock_irq(&uhci->lock); start_rh(uhci); + spin_unlock_irq(&uhci->lock); return 0; /* @@ -731,7 +741,7 @@ static void uhci_stop(struct usb_hcd *hcd) struct uhci_hcd *uhci = hcd_to_uhci(hcd); spin_lock_irq(&uhci->lock); - if (test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) && !uhci->dead) + if (HCD_HW_ACCESSIBLE(hcd) && !uhci->dead) uhci_hc_died(uhci); uhci_scan_schedule(uhci); spin_unlock_irq(&uhci->lock); @@ -748,7 +758,7 @@ static int uhci_rh_suspend(struct usb_hcd *hcd) int rc = 0; spin_lock_irq(&uhci->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) rc = -ESHUTDOWN; else if (uhci->dead) ; /* Dead controllers tell no tales */ @@ -775,7 +785,7 @@ static int uhci_rh_resume(struct usb_hcd *hcd) int rc = 0; spin_lock_irq(&uhci->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + if (!HCD_HW_ACCESSIBLE(hcd)) rc = -ESHUTDOWN; else if (!uhci->dead) wakeup_rh(uhci); @@ -783,15 +793,16 @@ static int uhci_rh_resume(struct usb_hcd *hcd) return rc; } -static int uhci_pci_suspend(struct usb_hcd *hcd) +static int uhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) { struct uhci_hcd *uhci = hcd_to_uhci(hcd); + struct pci_dev *pdev = to_pci_dev(uhci_dev(uhci)); int rc = 0; dev_dbg(uhci_dev(uhci), "%s\n", __func__); spin_lock_irq(&uhci->lock); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) + if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) goto done_okay; /* Already suspended or dead */ if (uhci->rh_state > UHCI_RH_SUSPENDED) { @@ -803,11 +814,15 @@ static int uhci_pci_suspend(struct usb_hcd *hcd) /* All PCI host controllers are required to disable IRQ generation * at the source, so we must turn off PIRQ. */ - pci_write_config_word(to_pci_dev(uhci_dev(uhci)), USBLEGSUP, 0); - mb(); - hcd->poll_rh = 0; - - /* FIXME: Enable non-PME# remote wakeup? */ + pci_write_config_word(pdev, USBLEGSUP, 0); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + + /* Enable platform-specific non-PME# wakeup */ + if (do_wakeup) { + if (pdev->vendor == PCI_VENDOR_ID_INTEL) + pci_write_config_byte(pdev, USBRES_INTEL, + USBPORT1EN | USBPORT2EN); + } done_okay: clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); @@ -826,7 +841,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) * even if the controller was dead. */ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - mb(); spin_lock_irq(&uhci->lock); @@ -834,8 +848,6 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) if (hibernated) uhci_hc_died(uhci); - /* FIXME: Disable non-PME# remote wakeup? */ - /* The firmware or a boot kernel may have changed the controller * settings during a system wakeup. Check it and reconfigure * to avoid problems. @@ -845,22 +857,20 @@ static int uhci_pci_resume(struct usb_hcd *hcd, bool hibernated) /* If the controller was dead before, it's back alive now */ configure_hc(uhci); - if (uhci->rh_state == UHCI_RH_RESET) { - - /* The controller had to be reset */ + /* Tell the core if the controller had to be reset */ + if (uhci->rh_state == UHCI_RH_RESET) usb_root_hub_lost_power(hcd->self.root_hub); - suspend_rh(uhci, UHCI_RH_SUSPENDED); - } spin_unlock_irq(&uhci->lock); /* If interrupts don't work and remote wakeup is enabled then * the suspended root hub needs to be polled. */ - if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) { - hcd->poll_rh = 1; - usb_hcd_poll_rh_status(hcd); - } + if (!uhci->RD_enable && hcd->self.root_hub->do_remote_wakeup) + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + + /* Does the root hub have a port wakeup pending? */ + usb_hcd_poll_rh_status(hcd); return 0; } #endif diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 26bd1b2bcbfc..49bf2790f9c2 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -67,12 +67,17 @@ #define USBPORTSC_RES3 0x4000 /* reserved, write zeroes */ #define USBPORTSC_RES4 0x8000 /* reserved, write zeroes */ -/* Legacy support register */ +/* PCI legacy support register */ #define USBLEGSUP 0xc0 #define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ +/* PCI Intel-specific resume-enable register */ +#define USBRES_INTEL 0xc4 +#define USBPORT1EN 0x01 +#define USBPORT2EN 0x02 + #define UHCI_PTR_BITS cpu_to_le32(0x000F) #define UHCI_PTR_TERM cpu_to_le32(0x0001) #define UHCI_PTR_QH cpu_to_le32(0x0002) diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 8270055848ca..6d59c0f77f25 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -190,7 +190,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) spin_lock_irqsave(&uhci->lock, flags); uhci_scan_schedule(uhci); - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) + if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) goto done; uhci_check_ports(uhci); @@ -200,7 +200,7 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) case UHCI_RH_SUSPENDING: case UHCI_RH_SUSPENDED: /* if port change, ask to be resumed */ - if (status) + if (status || uhci->resuming_ports) usb_hcd_resume_root_hub(hcd); break; @@ -246,7 +246,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wPortChange, wPortStatus; unsigned long flags; - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags) || uhci->dead) + if (!HCD_HW_ACCESSIBLE(hcd) || uhci->dead) return -ETIMEDOUT; spin_lock_irqsave(&uhci->lock, flags); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index acd582c02802..d3ade4018487 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -565,7 +565,7 @@ static void uhci_unlink_qh(struct uhci_hcd *uhci, struct uhci_qh *qh) qh->unlink_frame = uhci->frame_number; /* Force an interrupt so we know when the QH is fully unlinked */ - if (list_empty(&uhci->skel_unlink_qh->node)) + if (list_empty(&uhci->skel_unlink_qh->node) || uhci->is_stopped) uhci_set_next_interrupt(uhci); /* Move the QH from its old list to the end of the unlinking list */ @@ -1667,7 +1667,7 @@ static int uhci_advance_check(struct uhci_hcd *uhci, struct uhci_qh *qh) qh->advance_jiffies = jiffies; goto done; } - ret = 0; + ret = uhci->is_stopped; } /* The queue hasn't advanced; check for timeout */ diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index e0d3401285c8..72b6892fda67 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -68,7 +68,7 @@ static int whc_start(struct usb_hcd *usb_hcd) whc_write_wusbcmd(whc, WUSBCMD_RUN, WUSBCMD_RUN); usb_hcd->uses_new_polling = 1; - usb_hcd->poll_rh = 1; + set_bit(HCD_FLAG_POLL_RH, &usb_hcd->flags); usb_hcd->state = HC_STATE_RUNNING; out: diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index ab5a14fbfeeb..dc0ab8382f5d 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -475,7 +475,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u || (prev_end & (WHCI_PAGE_SIZE-1)) || (dma_addr & (WHCI_PAGE_SIZE-1)) || std->len + WHCI_PAGE_SIZE > QTD_MAX_XFER_SIZE) { - if (std->len % qset->max_packet != 0) + if (std && std->len % qset->max_packet != 0) return -EINVAL; std = qset_new_std(whc, qset, urb, mem_flags); if (std == NULL) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8cc824bbc4ee..a20bf609eefc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1587,7 +1587,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) unsigned int num_tests; int i, ret; - num_tests = sizeof(simple_test_vector) / sizeof(simple_test_vector[0]); + num_tests = ARRAY_SIZE(simple_test_vector); for (i = 0; i < num_tests; i++) { ret = xhci_test_trb_in_td(xhci, xhci->event_ring->first_seg, @@ -1600,7 +1600,7 @@ static int xhci_check_trb_in_td_math(struct xhci_hcd *xhci, gfp_t mem_flags) return ret; } - num_tests = sizeof(complex_test_vector) / sizeof(complex_test_vector[0]); + num_tests = ARRAY_SIZE(complex_test_vector); for (i = 0; i < num_tests; i++) { ret = xhci_test_trb_in_td(xhci, complex_test_vector[i].input_seg, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3998f72cd0c4..5e73386b3899 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -427,7 +427,6 @@ int xhci_run(struct usb_hcd *hcd) void (*doorbell)(struct xhci_hcd *) = NULL; hcd->uses_new_polling = 1; - hcd->poll_rh = 0; xhci_dbg(xhci, "xhci_run\n"); #if 0 /* FIXME: MSI not setup yet */ @@ -495,7 +494,6 @@ int xhci_run(struct usb_hcd *hcd) return -ENODEV; } - xhci_dbg(xhci, "// @%p = 0x%x\n", &xhci->op_regs->command, temp); if (doorbell) (*doorbell)(xhci); if (xhci->quirks & XHCI_NEC_HOST) @@ -734,7 +732,7 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) ret = -EINVAL; goto exit; } - if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + if (!HCD_HW_ACCESSIBLE(hcd)) { if (!in_interrupt()) xhci_dbg(xhci, "urb submitted during PCI suspend\n"); ret = -ESHUTDOWN; diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 16dffe99d9f1..0cfbd789ddf2 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1548,6 +1548,7 @@ fail: * off just killing the userspace task and waiting for it to exit. */ +/* No BKL needed */ static int usbtest_ioctl (struct usb_interface *intf, unsigned int code, void *buf) { @@ -2170,7 +2171,7 @@ static struct usb_driver usbtest_driver = { .name = "usbtest", .id_table = id_table, .probe = usbtest_probe, - .ioctl = usbtest_ioctl, + .unlocked_ioctl = usbtest_ioctl, .disconnect = usbtest_disconnect, .suspend = usbtest_suspend, .resume = usbtest_resume, diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 61c76b13f0f1..1be0b9f93366 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -646,17 +646,14 @@ static int mon_bin_open(struct inode *inode, struct file *file) size_t size; int rc; - lock_kernel(); mutex_lock(&mon_lock); if ((mbus = mon_bus_lookup(iminor(inode))) == NULL) { mutex_unlock(&mon_lock); - unlock_kernel(); return -ENODEV; } if (mbus != &mon_bus0 && mbus->u_bus == NULL) { printk(KERN_ERR TAG ": consistency error on open\n"); mutex_unlock(&mon_lock); - unlock_kernel(); return -ENODEV; } @@ -689,7 +686,6 @@ static int mon_bin_open(struct inode *inode, struct file *file) file->private_data = rp; mutex_unlock(&mon_lock); - unlock_kernel(); return 0; err_allocbuff: @@ -698,7 +694,6 @@ err_allocvec: kfree(rp); err_alloc: mutex_unlock(&mon_lock); - unlock_kernel(); return rc; } @@ -954,7 +949,7 @@ static int mon_bin_queued(struct mon_reader_bin *rp) /* */ -static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct mon_reader_bin *rp = file->private_data; // struct mon_bus* mbus = rp->r.m_bus; @@ -1094,19 +1089,6 @@ static int mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } -static long mon_bin_unlocked_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - int ret; - - lock_kernel(); - ret = mon_bin_ioctl(file, cmd, arg); - unlock_kernel(); - - return ret; -} - - #ifdef CONFIG_COMPAT static long mon_bin_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) @@ -1250,7 +1232,7 @@ static const struct file_operations mon_fops_binary = { .read = mon_bin_read, /* .write = mon_text_write, */ .poll = mon_bin_poll, - .unlocked_ioctl = mon_bin_unlocked_ioctl, + .unlocked_ioctl = mon_bin_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = mon_bin_compat_ioctl, #endif diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3b795c56221f..540c766c4f86 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -704,7 +704,6 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, #ifdef CONFIG_USB_MUSB_HDRC_HCD if (int_usb & MUSB_INTR_CONNECT) { struct usb_hcd *hcd = musb_to_hcd(musb); - void __iomem *mbase = musb->mregs; handled = IRQ_HANDLED; musb->is_active = 1; @@ -717,9 +716,9 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, if (is_peripheral_active(musb)) { /* REVISIT HNP; just force disconnect */ } - musb_writew(mbase, MUSB_INTRTXE, musb->epmask); - musb_writew(mbase, MUSB_INTRRXE, musb->epmask & 0xfffe); - musb_writeb(mbase, MUSB_INTRUSBE, 0xf7); + musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask); + musb_writew(musb->mregs, MUSB_INTRRXE, musb->epmask & 0xfffe); + musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7); #endif musb->port1_status &= ~(USB_PORT_STAT_LOW_SPEED |USB_PORT_STAT_HIGH_SPEED diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index bba76af0c0c6..c79a5e30d437 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -92,29 +92,29 @@ static const struct musb_register_map musb_regmap[] = { { "LS_EOF1", 0x7E, 8 }, { "SOFT_RST", 0x7F, 8 }, { "DMA_CNTLch0", 0x204, 16 }, - { "DMA_ADDRch0", 0x208, 16 }, - { "DMA_COUNTch0", 0x20C, 16 }, + { "DMA_ADDRch0", 0x208, 32 }, + { "DMA_COUNTch0", 0x20C, 32 }, { "DMA_CNTLch1", 0x214, 16 }, - { "DMA_ADDRch1", 0x218, 16 }, - { "DMA_COUNTch1", 0x21C, 16 }, + { "DMA_ADDRch1", 0x218, 32 }, + { "DMA_COUNTch1", 0x21C, 32 }, { "DMA_CNTLch2", 0x224, 16 }, - { "DMA_ADDRch2", 0x228, 16 }, - { "DMA_COUNTch2", 0x22C, 16 }, + { "DMA_ADDRch2", 0x228, 32 }, + { "DMA_COUNTch2", 0x22C, 32 }, { "DMA_CNTLch3", 0x234, 16 }, - { "DMA_ADDRch3", 0x238, 16 }, - { "DMA_COUNTch3", 0x23C, 16 }, + { "DMA_ADDRch3", 0x238, 32 }, + { "DMA_COUNTch3", 0x23C, 32 }, { "DMA_CNTLch4", 0x244, 16 }, - { "DMA_ADDRch4", 0x248, 16 }, - { "DMA_COUNTch4", 0x24C, 16 }, + { "DMA_ADDRch4", 0x248, 32 }, + { "DMA_COUNTch4", 0x24C, 32 }, { "DMA_CNTLch5", 0x254, 16 }, - { "DMA_ADDRch5", 0x258, 16 }, - { "DMA_COUNTch5", 0x25C, 16 }, + { "DMA_ADDRch5", 0x258, 32 }, + { "DMA_COUNTch5", 0x25C, 32 }, { "DMA_CNTLch6", 0x264, 16 }, - { "DMA_ADDRch6", 0x268, 16 }, - { "DMA_COUNTch6", 0x26C, 16 }, + { "DMA_ADDRch6", 0x268, 32 }, + { "DMA_COUNTch6", 0x26C, 32 }, { "DMA_CNTLch7", 0x274, 16 }, - { "DMA_ADDRch7", 0x278, 16 }, - { "DMA_COUNTch7", 0x27C, 16 }, + { "DMA_ADDRch7", 0x278, 32 }, + { "DMA_COUNTch7", 0x27C, 32 }, { } /* Terminating Entry */ }; diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 92e85e027cfb..43233c397b6e 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -244,7 +244,7 @@ int musb_hub_control( spin_lock_irqsave(&musb->lock, flags); - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) { + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) { spin_unlock_irqrestore(&musb->lock, flags); return -ESHUTDOWN; } diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index dc66e4376d49..6dc107f25245 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -173,10 +173,7 @@ static int dma_channel_program(struct dma_channel *channel, musb_channel->max_packet_sz = packet_sz; channel->status = MUSB_DMA_STATUS_BUSY; - if ((mode == 1) && (len >= packet_sz)) - configure_channel(channel, packet_sz, 1, dma_addr, len); - else - configure_channel(channel, packet_sz, 0, dma_addr, len); + configure_channel(channel, packet_sz, mode, dma_addr, len); return true; } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e06d65e36bf7..2111a241dd03 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -32,8 +32,6 @@ #include <linux/clk.h> #include <linux/io.h> -#include <plat/mux.h> - #include "musb_core.h" #include "omap2430.h" @@ -194,10 +192,6 @@ int __init musb_platform_init(struct musb *musb, void *board_data) u32 l; struct omap_musb_board_data *data = board_data; -#if defined(CONFIG_ARCH_OMAP2430) - omap_cfg_reg(AE5_2430_USB0HS_STP); -#endif - /* We require some kind of external transceiver, hooked * up through ULPI. TWL4030-family PMICs include one, * which needs a driver, drivers aren't always needed. diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 05c077f8f9ac..3c48e77a0aa2 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -29,19 +29,6 @@ static void tusb_source_power(struct musb *musb, int is_on); #define TUSB_REV_MAJOR(reg_val) ((reg_val >> 4) & 0xf) #define TUSB_REV_MINOR(reg_val) (reg_val & 0xf) -#ifdef CONFIG_PM -/* REVISIT: These should be only needed if somebody implements off idle */ -void musb_platform_save_context(struct musb *musb, - struct musb_context_registers *musb_context) -{ -} - -void musb_platform_restore_context(struct musb *musb, - struct musb_context_registers *musb_context) -{ -} -#endif - /* * Checks the revision. We need to use the DMA register as 3.0 does not * have correct versions for TUSB_PRCM_REV or TUSB_INT_CTRL_REV. diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 0fca2659206f..03696b91bd6d 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -1321,7 +1321,7 @@ static int download_fw(struct edgeport_serial *serial) kfree(header); kfree(rom_desc); kfree(ti_manuf_desc); - return status; + return -EINVAL; } kfree(vheader); diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 28913fa95fb7..4735931b4c7b 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -534,7 +534,6 @@ static struct usb_device_id ipaq_id_table [] = { { USB_DEVICE(0x413C, 0x4009) }, /* Dell Axim USB Sync */ { USB_DEVICE(0x4505, 0x0010) }, /* Smartphone */ { USB_DEVICE(0x5E04, 0xCE00) }, /* SAGEM Wireless Assistant */ - { USB_DEVICE(0x0BB4, 0x00CF) }, /* HTC smartphone modems */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 74551cb2e8ee..efc72113216b 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -1,6 +1,8 @@ /* * Infinity Unlimited USB Phoenix driver * + * Copyright (C) 2010 James Courtier-Dutton (James@superbug.co.uk) + * Copyright (C) 2007 Alain Degreffe (eczema@ecze.com) * * Original code taken from iuutool (Copyright (C) 2006 Juan Carlos Borrás) @@ -40,7 +42,7 @@ static int debug; /* * Version Information */ -#define DRIVER_VERSION "v0.11" +#define DRIVER_VERSION "v0.12" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" static const struct usb_device_id id_table[] = { @@ -81,6 +83,9 @@ struct iuu_private { u8 *dbgbuf; /* debug buffer */ u8 len; int vcc; /* vcc (either 3 or 5 V) */ + u32 baud; + u32 boost; + u32 clk; }; @@ -157,13 +162,14 @@ static int iuu_tiocmset(struct tty_struct *tty, struct file *file, port->number, set, clear); spin_lock_irqsave(&priv->lock, flags); - if (set & TIOCM_RTS) - priv->tiostatus = TIOCM_RTS; - if (!(set & TIOCM_RTS) && priv->tiostatus == TIOCM_RTS) { + if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) { dbg("%s TIOCMSET RESET called !!!", __func__); priv->reset = 1; } + if (set & TIOCM_RTS) + priv->tiostatus = TIOCM_RTS; + spin_unlock_irqrestore(&priv->lock, flags); return 0; } @@ -851,20 +857,24 @@ static int iuu_uart_off(struct usb_serial_port *port) return status; } -static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, +static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, u32 *actual, u8 parity) { int status; + u32 baud; u8 *dataout; u8 DataCount = 0; u8 T1Frekvens = 0; u8 T1reload = 0; unsigned int T1FrekvensHZ = 0; + dbg("%s - enter baud_base=%d", __func__, baud_base); dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); if (!dataout) return -ENOMEM; + /*baud = (((priv->clk / 35) * baud_base) / 100000); */ + baud = baud_base; if (baud < 1200 || baud > 230400) { kfree(dataout); @@ -948,15 +958,20 @@ static void iuu_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { const u32 supported_mask = CMSPAR|PARENB|PARODD; - + struct iuu_private *priv = usb_get_serial_port_data(port); unsigned int cflag = tty->termios->c_cflag; int status; u32 actual; u32 parity; int csize = CS7; - int baud = 9600; /* Fixed for the moment */ + int baud; u32 newval = cflag & supported_mask; + /* Just use the ospeed. ispeed should be the same. */ + baud = tty->termios->c_ospeed; + + dbg("%s - enter c_ospeed or baud=%d", __func__, baud); + /* compute the parity parameter */ parity = 0; if (cflag & CMSPAR) { /* Using mark space */ @@ -976,15 +991,15 @@ static void iuu_set_termios(struct tty_struct *tty, /* set it */ status = iuu_uart_baud(port, - (clockmode == 2) ? 16457 : 9600 * boost / 100, + baud * priv->boost / 100, &actual, parity); /* set the termios value to the real one, so the user now what has * changed. We support few fields so its easies to copy the old hw * settings back over and then adjust them */ - if (old_termios) - tty_termios_copy_hw(tty->termios, old_termios); + if (old_termios) + tty_termios_copy_hw(tty->termios, old_termios); if (status != 0) /* Set failed - return old bits */ return; /* Re-encode speed, parity and csize */ @@ -1018,6 +1033,7 @@ static void iuu_close(struct usb_serial_port *port) static void iuu_init_termios(struct tty_struct *tty) { + dbg("%s - enter", __func__); *(tty->termios) = tty_std_termios; tty->termios->c_cflag = CLOCAL | CREAD | CS8 | B9600 | TIOCM_CTS | CSTOPB | PARENB; @@ -1033,10 +1049,16 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) struct usb_serial *serial = port->serial; u8 *buf; int result; + int baud; u32 actual; struct iuu_private *priv = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); + baud = tty->termios->c_ospeed; + tty->termios->c_ispeed = baud; + /* Re-encode speed */ + tty_encode_baud_rate(tty, baud, baud); + + dbg("%s - port %d, baud %d", __func__, port->number, baud); usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -1071,23 +1093,29 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) iuu_uart_on(port); if (boost < 100) boost = 100; + priv->boost = boost; + priv->baud = baud; switch (clockmode) { case 2: /* 3.680 Mhz */ + priv->clk = IUU_CLK_3680000; iuu_clk(port, IUU_CLK_3680000 * boost / 100); result = - iuu_uart_baud(port, 9600 * boost / 100, &actual, + iuu_uart_baud(port, baud * boost / 100, &actual, IUU_PARITY_EVEN); break; case 3: /* 6.00 Mhz */ iuu_clk(port, IUU_CLK_6000000 * boost / 100); + priv->clk = IUU_CLK_6000000; + /* Ratio of 6000000 to 3500000 for baud 9600 */ result = iuu_uart_baud(port, 16457 * boost / 100, &actual, IUU_PARITY_EVEN); break; default: /* 3.579 Mhz */ iuu_clk(port, IUU_CLK_3579000 * boost / 100); + priv->clk = IUU_CLK_3579000; result = - iuu_uart_baud(port, 9600 * boost / 100, &actual, + iuu_uart_baud(port, baud * boost / 100, &actual, IUU_PARITY_EVEN); } diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5cd30e4345c6..a8c54b2116a6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -264,9 +264,6 @@ static void option_instat_callback(struct urb *urb); #define BANDRICH_PRODUCT_1011 0x1011 #define BANDRICH_PRODUCT_1012 0x1012 -#define AMOI_VENDOR_ID 0x1614 -#define AMOI_PRODUCT_9508 0x0800 - #define QUALCOMM_VENDOR_ID 0x05C6 #define CMOTECH_VENDOR_ID 0x16d8 @@ -483,7 +480,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, { USB_DEVICE(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC) }, - { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_9508) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, /* Novatel Merlin V640/XV620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, /* Novatel Merlin V620/S620 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, /* Novatel Merlin EX720/V740/X720 */ diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 941c2d409f85..443468e9d66e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -653,6 +653,7 @@ exit: return id; } +/* Caller must hold table_lock */ static struct usb_serial_driver *search_serial_device( struct usb_interface *iface) { @@ -718,17 +719,23 @@ int usb_serial_probe(struct usb_interface *interface, int num_ports = 0; int max_endpoints; - lock_kernel(); /* guard against unloading a serial driver module */ + mutex_lock(&table_lock); type = search_serial_device(interface); if (!type) { - unlock_kernel(); + mutex_unlock(&table_lock); dbg("none matched"); return -ENODEV; } + if (!try_module_get(type->driver.owner)) { + mutex_unlock(&table_lock); + dev_err(&interface->dev, "module get failed, exiting\n"); + return -EIO; + } + mutex_unlock(&table_lock); + serial = create_serial(dev, interface, type); if (!serial) { - unlock_kernel(); dev_err(&interface->dev, "%s - out of memory\n", __func__); return -ENOMEM; } @@ -737,20 +744,11 @@ int usb_serial_probe(struct usb_interface *interface, if (type->probe) { const struct usb_device_id *id; - if (!try_module_get(type->driver.owner)) { - unlock_kernel(); - dev_err(&interface->dev, - "module get failed, exiting\n"); - kfree(serial); - return -EIO; - } - id = get_iface_id(type, interface); retval = type->probe(serial, id); module_put(type->driver.owner); if (retval) { - unlock_kernel(); dbg("sub driver rejected device"); kfree(serial); return retval; @@ -822,7 +820,6 @@ int usb_serial_probe(struct usb_interface *interface, * properly during a later invocation of usb_serial_probe */ if (num_bulk_in == 0 || num_bulk_out == 0) { - unlock_kernel(); dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); kfree(serial); return -ENODEV; @@ -835,7 +832,6 @@ int usb_serial_probe(struct usb_interface *interface, if (type == &usb_serial_generic_device) { num_ports = num_bulk_out; if (num_ports == 0) { - unlock_kernel(); dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); kfree(serial); @@ -847,7 +843,6 @@ int usb_serial_probe(struct usb_interface *interface, /* if this device type has a calc_num_ports function, call it */ if (type->calc_num_ports) { if (!try_module_get(type->driver.owner)) { - unlock_kernel(); dev_err(&interface->dev, "module get failed, exiting\n"); kfree(serial); @@ -878,7 +873,6 @@ int usb_serial_probe(struct usb_interface *interface, max_endpoints = max(max_endpoints, num_interrupt_out); max_endpoints = max(max_endpoints, (int)serial->num_ports); serial->num_port_pointers = max_endpoints; - unlock_kernel(); dbg("%s - setting up %d port structures for this device", __func__, max_endpoints); @@ -1349,6 +1343,7 @@ int usb_serial_register(struct usb_serial_driver *driver) driver->description = driver->driver.name; /* Add this device to our list of devices */ + mutex_lock(&table_lock); list_add(&driver->driver_list, &usb_serial_driver_list); retval = usb_serial_bus_register(driver); @@ -1360,6 +1355,7 @@ int usb_serial_register(struct usb_serial_driver *driver) printk(KERN_INFO "USB Serial support registered for %s\n", driver->description); + mutex_unlock(&table_lock); return retval; } EXPORT_SYMBOL_GPL(usb_serial_register); @@ -1370,8 +1366,10 @@ void usb_serial_deregister(struct usb_serial_driver *device) /* must be called with BKL held */ printk(KERN_INFO "USB Serial deregistering driver %s\n", device->description); + mutex_lock(&table_lock); list_del(&device->driver_list); usb_serial_bus_deregister(device); + mutex_unlock(&table_lock); } EXPORT_SYMBOL_GPL(usb_serial_deregister); diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index e9cbc1467f76..6b9982cd5423 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -1456,8 +1456,7 @@ static int isd200_init_info(struct us_data *us) int retStatus = ISD200_GOOD; struct isd200_info *info; - info = (struct isd200_info *) - kzalloc(sizeof(struct isd200_info), GFP_KERNEL); + info = kzalloc(sizeof(struct isd200_info), GFP_KERNEL); if (!info) retStatus = ISD200_ERROR; else { |