diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-29 16:21:01 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-04-29 16:21:01 -0700 |
| commit | 6a262e12cd91119840767d1724f50b96d013551b (patch) | |
| tree | 9ada8a9eea32d8548d1491b98cd0e18f48c344e6 | |
| parent | c87f20e270b8b799d5e7fa2941117b4e0d6b1ab7 (diff) | |
| download | patches-6a262e12cd91119840767d1724f50b96d013551b.tar.gz | |
usb fun
21 files changed, 5403 insertions, 77 deletions
@@ -152,6 +152,9 @@ tty/serial-uartlite-move-from-byte-accesses-to-word-accesses.patch ################################### # USB stuff for after 2.6.34 is out ################################### +usb/usb-make-hcd.h-public-drivers-dependency.patch +usb/usb-make-hub.h-public-drivers-dependency.patch +usb/usb-split-hub.h-into-ch11.h-and-merge-in-hcd.h.patch usb/usb-sisusbvga-remove-the-bkl-from-ioctl.patch usb/usb-cdc-acm-make-bitfields-unsigned.patch usb/usb-remove-large-struct-from-the-stack-in-usb-storage-isd200-driver.patch @@ -241,6 +244,18 @@ usb/short-new-graph-for-usb-serial.txt.patch usb/usb-rename-usb_buffer_alloc-and-usb_buffer_free-users.patch usb/usb-staging-fix-up-usb_buffer_alloc-calls-in-the-staging-tree.patch + +usb/usb-usbserial-mos7720-add-support-for-parallel-port-on-moschip-7715.patch +usb/usb-usbserial-mos7720-cleanup-consolidation-replace-send_mos_cmd-with-read-write-_mos_reg.patch +usb/usb-cdc-ncm-constants-and-structures-added.patch +usb/usb-ncm-added-ncm.h-with-auxiliary-definitions.patch +usb/usb-core-config.c-usb_get_configuration-simplified.patch +usb/usb-clean-up-some-host-controller-sparse-warnings.patch +usb/usb-composite-framework-add-suspended-sysfs-entry.patch +usb/usb-mass-storage-gadget-handle-eject-request.patch + + +# this goes in last. usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch ####################################### @@ -251,4 +266,3 @@ usb/usb-remove-unused-usb_buffer_alloc-and-usb_buffer_free-macros.patch # new stuff is in the staging-next git tree on git.kernel.org - diff --git a/usb/devices-fix-coding-styles.patch b/usb/devices-fix-coding-styles.patch index 195090f8104c6a..a7adf40af73ad1 100644 --- a/usb/devices-fix-coding-styles.patch +++ b/usb/devices-fix-coding-styles.patch @@ -28,15 +28,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> * (C) Copyright 1999 Deti Fliegl (new USB architecture) * * This program is free software; you can redistribute it and/or modify -@@ -56,7 +57,7 @@ - #include <linux/smp_lock.h> +@@ -57,7 +58,7 @@ #include <linux/usbdevice_fs.h> + #include <linux/usb/hcd.h> #include <linux/mutex.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include "usb.h" - #include "hcd.h" + @@ -138,8 +139,8 @@ struct class_info { char *class_name; }; diff --git a/usb/usb-add-a-new-quirk-usb_quirk_honor_bnuminterfaces.patch b/usb/usb-add-a-new-quirk-usb_quirk_honor_bnuminterfaces.patch index a9133f2235e6f7..440af4ebfeed71 100644 --- a/usb/usb-add-a-new-quirk-usb_quirk_honor_bnuminterfaces.patch +++ b/usb/usb-add-a-new-quirk-usb_quirk_honor_bnuminterfaces.patch @@ -29,14 +29,15 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c -@@ -1,5 +1,6 @@ +@@ -1,6 +1,7 @@ #include <linux/usb.h> #include <linux/usb/ch9.h> + #include <linux/usb/hcd.h> +#include <linux/usb/quirks.h> #include <linux/module.h> #include <linux/init.h> #include <linux/slab.h> -@@ -478,9 +479,10 @@ skip_to_next_interface_descriptor: +@@ -479,9 +480,10 @@ skip_to_next_interface_descriptor: return buffer - buffer0 + i; } @@ -48,7 +49,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> unsigned char *buffer0 = buffer; int cfgno; int nintf, nintf_orig; -@@ -549,6 +551,16 @@ static int usb_parse_configuration(struc +@@ -550,6 +552,16 @@ static int usb_parse_configuration(struc } inum = d->bInterfaceNumber; @@ -65,7 +66,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (inum >= nintf_orig) dev_warn(ddev, "config %d has an invalid " "interface number: %d but max is %d\n", -@@ -800,7 +812,7 @@ int usb_get_configuration(struct usb_dev +@@ -801,7 +813,7 @@ int usb_get_configuration(struct usb_dev dev->rawdescriptors[cfgno] = bigbuffer; diff --git a/usb/usb-cdc-ncm-constants-and-structures-added.patch b/usb/usb-cdc-ncm-constants-and-structures-added.patch new file mode 100644 index 00000000000000..70973fb2cd9d64 --- /dev/null +++ b/usb/usb-cdc-ncm-constants-and-structures-added.patch @@ -0,0 +1,144 @@ +From yauheni.kaliuta@nokia.com Thu Apr 29 16:02:05 2010 +From: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Date: Fri, 16 Apr 2010 16:13:34 +0300 +Subject: usb: cdc: ncm constants and structures added +To: linux-usb@vger.kernel.org +Message-ID: <1271423621-26361-2-git-send-email-yauheni.kaliuta@nokia.com> + + +Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/cdc.h | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 94 insertions(+) + +--- a/include/linux/usb/cdc.h ++++ b/include/linux/usb/cdc.h +@@ -18,6 +18,7 @@ + #define USB_CDC_SUBCLASS_MDLM 0x0a + #define USB_CDC_SUBCLASS_OBEX 0x0b + #define USB_CDC_SUBCLASS_EEM 0x0c ++#define USB_CDC_SUBCLASS_NCM 0x0d + + #define USB_CDC_PROTO_NONE 0 + +@@ -49,6 +50,7 @@ + #define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ + #define USB_CDC_DMM_TYPE 0x14 + #define USB_CDC_OBEX_TYPE 0x15 ++#define USB_CDC_NCM_TYPE 0x1a + + /* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ + struct usb_cdc_header_desc { +@@ -174,6 +176,15 @@ struct usb_cdc_obex_desc { + __le16 bcdVersion; + } __attribute__ ((packed)); + ++/* "NCM Control Model Functional Descriptor" */ ++struct usb_cdc_ncm_desc { ++ __u8 bLength; ++ __u8 bDescriptorType; ++ __u8 bDescriptorSubType; ++ ++ __le16 bcdNcmVersion; ++ __u8 bmNetworkCapabilities; ++} __attribute__ ((packed)); + /*-------------------------------------------------------------------------*/ + + /* +@@ -197,6 +208,17 @@ struct usb_cdc_obex_desc { + #define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 + #define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 + #define USB_CDC_GET_ETHERNET_STATISTIC 0x44 ++#define USB_CDC_GET_NTB_PARAMETERS 0x80 ++#define USB_CDC_GET_NET_ADDRESS 0x81 ++#define USB_CDC_SET_NET_ADDRESS 0x82 ++#define USB_CDC_GET_NTB_FORMAT 0x83 ++#define USB_CDC_SET_NTB_FORMAT 0x84 ++#define USB_CDC_GET_NTB_INPUT_SIZE 0x85 ++#define USB_CDC_SET_NTB_INPUT_SIZE 0x86 ++#define USB_CDC_GET_MAX_DATAGRAM_SIZE 0x87 ++#define USB_CDC_SET_MAX_DATAGRAM_SIZE 0x88 ++#define USB_CDC_GET_CRC_MODE 0x89 ++#define USB_CDC_SET_CRC_MODE 0x8a + + /* Line Coding Structure from CDC spec 6.2.13 */ + struct usb_cdc_line_coding { +@@ -247,4 +269,76 @@ struct usb_cdc_notification { + __le16 wLength; + } __attribute__ ((packed)); + ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * Class Specific structures and constants ++ * ++ * CDC NCM parameter structure, CDC NCM subclass 6.2.1 ++ * ++ */ ++ ++struct usb_cdc_ncm_ntb_parameter { ++ __le16 wLength; ++ __le16 bmNtbFormatSupported; ++ __le32 dwNtbInMaxSize; ++ __le16 wNdpInDivisor; ++ __le16 wNdpInPayloadRemainder; ++ __le16 wNdpInAlignment; ++ __le16 wPadding1; ++ __le32 dwNtbOutMaxSize; ++ __le16 wNdpOutDivisor; ++ __le16 wNdpOutPayloadRemainder; ++ __le16 wNdpOutAlignment; ++ __le16 wPadding2; ++} __attribute__ ((packed)); ++ ++/* ++ * CDC NCM transfer headers, CDC NCM subclass 3.2 ++ */ ++ ++#define NCM_NTH16_SIGN 0x484D434E /* NCMH */ ++#define NCM_NTH32_SIGN 0x686D636E /* ncmh */ ++ ++struct usb_cdc_ncm_nth16 { ++ __le32 dwSignature; ++ __le16 wHeaderLength; ++ __le16 wSequence; ++ __le16 wBlockLength; ++ __le16 wFpIndex; ++} __attribute__ ((packed)); ++ ++struct usb_cdc_ncm_nth32 { ++ __le32 dwSignature; ++ __le16 wHeaderLength; ++ __le16 wSequence; ++ __le32 dwBlockLength; ++ __le32 dwFpIndex; ++} __attribute__ ((packed)); ++ ++/* ++ * CDC NCM datagram pointers, CDC NCM subclass 3.3 ++ */ ++ ++#define NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */ ++#define NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */ ++#define NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ ++#define NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ ++ ++struct usb_cdc_ncm_ndp16 { ++ __le32 dwSignature; ++ __le16 wLength; ++ __le16 wNextFpIndex; ++ __u8 data[0]; ++} __attribute__ ((packed)); ++ ++struct usb_cdc_ncm_ndp32 { ++ __le32 dwSignature; ++ __le16 wLength; ++ __le16 wReserved6; ++ __le32 dwNextFpIndex; ++ __le32 dwReserved12; ++ __u8 data[0]; ++} __attribute__ ((packed)); ++ + #endif /* __LINUX_USB_CDC_H */ diff --git a/usb/usb-clean-up-some-host-controller-sparse-warnings.patch b/usb/usb-clean-up-some-host-controller-sparse-warnings.patch new file mode 100644 index 00000000000000..488b5310a930a3 --- /dev/null +++ b/usb/usb-clean-up-some-host-controller-sparse-warnings.patch @@ -0,0 +1,204 @@ +From randy.dunlap@oracle.com Thu Apr 29 16:06:16 2010 +From: Randy Dunlap <randy.dunlap@oracle.com> +Date: Mon, 19 Apr 2010 08:53:50 -0700 +Subject: USB: clean up some host controller sparse warnings +Cc: gregkh@suse.de, Lothar Wassmann <LW@KARO-electronics.de>, Sarah Sharp <sarah.a.sharp@linux.intel.com> +Message-ID: <20100419085350.94470004.randy.dunlap@oracle.com> + + +From: Randy Dunlap <randy.dunlap@oracle.com> + +Fix usb sparse warnings: + +drivers/usb/host/isp1362-hcd.c:2220:50: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:43:24: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:49:24: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:161:24: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:198:16: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:319:31: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:1231:33: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-pci.c:177:23: warning: non-ANSI function declaration of function 'xhci_register_pci' +drivers/usb/host/xhci-pci.c:182:26: warning: non-ANSI function declaration of function 'xhci_unregister_pci' +drivers/usb/host/xhci-ring.c:342:32: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-ring.c:525:34: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-ring.c:1009:32: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-ring.c:1031:32: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-ring.c:1041:16: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-ring.c:1096:30: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-ring.c:1100:27: warning: Using plain integer as NULL pointer +drivers/usb/host/xhci-mem.c:224:27: warning: symbol 'xhci_alloc_container_ctx' was not declared. Should it be static? +drivers/usb/host/xhci-mem.c:242:6: warning: symbol 'xhci_free_container_ctx' was not declared. Should it be static? + +Signed-off-by: Randy Dunlap <randy.dunlap@oracle.com> +Cc: Lothar Wassmann <LW@KARO-electronics.de> +Signed-off By: Sarah Sharp <sarah.a.sharp@linux.intel.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/host/isp1362-hcd.c | 2 +- + drivers/usb/host/xhci-mem.c | 16 ++++++++-------- + drivers/usb/host/xhci-pci.c | 4 ++-- + drivers/usb/host/xhci-ring.c | 14 +++++++------- + 4 files changed, 18 insertions(+), 18 deletions(-) + +--- a/drivers/usb/host/isp1362-hcd.c ++++ b/drivers/usb/host/isp1362-hcd.c +@@ -2217,7 +2217,7 @@ static void create_debug_file(struct isp + static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) + { + if (isp1362_hcd->pde) +- remove_proc_entry(proc_filename, 0); ++ remove_proc_entry(proc_filename, NULL); + } + + #endif +--- a/drivers/usb/host/xhci-mem.c ++++ b/drivers/usb/host/xhci-mem.c +@@ -41,13 +41,13 @@ static struct xhci_segment *xhci_segment + + seg = kzalloc(sizeof *seg, flags); + if (!seg) +- return 0; ++ return NULL; + xhci_dbg(xhci, "Allocating priv segment structure at %p\n", seg); + + seg->trbs = dma_pool_alloc(xhci->segment_pool, flags, &dma); + if (!seg->trbs) { + kfree(seg); +- return 0; ++ return NULL; + } + xhci_dbg(xhci, "// Allocating segment at %p (virtual) 0x%llx (DMA)\n", + seg->trbs, (unsigned long long)dma); +@@ -159,7 +159,7 @@ static struct xhci_ring *xhci_ring_alloc + ring = kzalloc(sizeof *(ring), flags); + xhci_dbg(xhci, "Allocating ring at %p\n", ring); + if (!ring) +- return 0; ++ return NULL; + + INIT_LIST_HEAD(&ring->td_list); + if (num_segs == 0) +@@ -196,7 +196,7 @@ static struct xhci_ring *xhci_ring_alloc + + fail: + xhci_ring_free(xhci, ring); +- return 0; ++ return NULL; + } + + void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci, +@@ -247,7 +247,7 @@ static void xhci_reinit_cached_ring(stru + + #define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) + +-struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, ++static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, + int type, gfp_t flags) + { + struct xhci_container_ctx *ctx = kzalloc(sizeof(*ctx), flags); +@@ -265,7 +265,7 @@ struct xhci_container_ctx *xhci_alloc_co + return ctx; + } + +-void xhci_free_container_ctx(struct xhci_hcd *xhci, ++static void xhci_free_container_ctx(struct xhci_hcd *xhci, + struct xhci_container_ctx *ctx) + { + if (!ctx) +@@ -764,7 +764,7 @@ void xhci_free_virt_device(struct xhci_h + xhci_free_container_ctx(xhci, dev->out_ctx); + + kfree(xhci->devs[slot_id]); +- xhci->devs[slot_id] = 0; ++ xhci->devs[slot_id] = NULL; + } + + int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, +@@ -1779,7 +1779,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, + */ + init_completion(&xhci->addr_dev); + for (i = 0; i < MAX_HC_SLOTS; ++i) +- xhci->devs[i] = 0; ++ xhci->devs[i] = NULL; + + if (scratchpad_alloc(xhci, flags)) + goto fail; +--- a/drivers/usb/host/xhci-pci.c ++++ b/drivers/usb/host/xhci-pci.c +@@ -177,12 +177,12 @@ static struct pci_driver xhci_pci_driver + .shutdown = usb_hcd_pci_shutdown, + }; + +-int xhci_register_pci() ++int xhci_register_pci(void) + { + return pci_register_driver(&xhci_pci_driver); + } + +-void xhci_unregister_pci() ++void xhci_unregister_pci(void) + { + pci_unregister_driver(&xhci_pci_driver); + } +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -371,7 +371,7 @@ static struct xhci_segment *find_trb_seg + cur_seg = cur_seg->next; + if (cur_seg == start_seg) + /* Looped over the entire list. Oops! */ +- return 0; ++ return NULL; + } + return cur_seg; + } +@@ -565,7 +565,7 @@ static void handle_stopped_endpoint(stru + struct xhci_ring *ep_ring; + struct xhci_virt_ep *ep; + struct list_head *entry; +- struct xhci_td *cur_td = 0; ++ struct xhci_td *cur_td = NULL; + struct xhci_td *last_unlinked_td; + + struct xhci_dequeue_state deq_state; +@@ -1096,7 +1096,7 @@ struct xhci_segment *trb_in_td(struct xh + + do { + if (start_dma == 0) +- return 0; ++ return NULL; + /* We may get an event for a Link TRB in the middle of a TD */ + end_seg_dma = xhci_trb_virt_to_dma(cur_seg, + &cur_seg->trbs[TRBS_PER_SEGMENT - 1]); +@@ -1118,7 +1118,7 @@ struct xhci_segment *trb_in_td(struct xh + suspect_dma <= end_trb_dma)) + return cur_seg; + } +- return 0; ++ return NULL; + } else { + /* Might still be somewhere in this segment */ + if (suspect_dma >= start_dma && suspect_dma <= end_seg_dma) +@@ -1128,7 +1128,7 @@ struct xhci_segment *trb_in_td(struct xh + start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]); + } while (cur_seg != start_seg); + +- return 0; ++ return NULL; + } + + static void xhci_cleanup_halted_endpoint(struct xhci_hcd *xhci, +@@ -1199,11 +1199,11 @@ static int handle_tx_event(struct xhci_h + struct xhci_ring *ep_ring; + unsigned int slot_id; + int ep_index; +- struct xhci_td *td = 0; ++ struct xhci_td *td = NULL; + dma_addr_t event_dma; + struct xhci_segment *event_seg; + union xhci_trb *event_trb; +- struct urb *urb = 0; ++ struct urb *urb = NULL; + int status = -EINPROGRESS; + struct xhci_ep_ctx *ep_ctx; + u32 trb_comp_code; diff --git a/usb/usb-composite-framework-add-suspended-sysfs-entry.patch b/usb/usb-composite-framework-add-suspended-sysfs-entry.patch new file mode 100644 index 00000000000000..68eff031b40872 --- /dev/null +++ b/usb/usb-composite-framework-add-suspended-sysfs-entry.patch @@ -0,0 +1,117 @@ +From fabien.chouteau@gmail.com Thu Apr 29 16:07:20 2010 +From: Fabien Chouteau <fabien.chouteau@barco.com> +Date: Fri, 23 Apr 2010 14:21:26 +0200 +Subject: USB: Composite framework: Add suspended sysfs entry +To: linux-usb@vger.kernel.org +Cc: Fabien Chouteau <fabien.chouteau@barco.com>, Randy Dunlap <rdunlap@xenotime.net>, David Brownell <dbrownell@users.sourceforge.net>, Greg Kroah-Hartman <gregkh@suse.de>, Andrew Morton <akpm@linux-foundation.org>, Laurent Pinchart <laurent.pinchart@ideasonboard.com>, Michal Nazarewicz <m.nazarewicz@samsung.com>, Roel Kluin <roel.kluin@gmail.com>, Tejun Heo <tj@kernel.org>, Christoph Lameter <cl@linux-foundation.org>, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org +Message-ID: <1272025288-32555-1-git-send-email-fabien.chouteau@gmail.com> + + +From: Fabien Chouteau <fabien.chouteau@barco.com> + +This patch adds a sysfs entry (/sys/devices/platform/_UDC_/gadget/suspended) to +show the suspend state of an USB composite gadget. + +Signed-off-by: Fabien Chouteau <fabien.chouteau@barco.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget | 9 ++++ + drivers/usb/gadget/composite.c | 21 ++++++++++ + include/linux/usb/composite.h | 1 + include/linux/usb/gadget.h | 4 + + 4 files changed, 35 insertions(+) + +--- /dev/null ++++ b/Documentation/ABI/testing/sysfs-devices-platform-_UDC_-gadget +@@ -0,0 +1,9 @@ ++What: /sys/devices/platform/_UDC_/gadget/suspended ++Date: April 2010 ++Contact: Fabien Chouteau <fabien.chouteau@barco.com> ++Description: ++ Show the suspend state of an USB composite gadget. ++ 1 -> suspended ++ 0 -> resumed ++ ++ (_UDC_ is the name of the USB Device Controller driver) +--- a/drivers/usb/gadget/composite.c ++++ b/drivers/usb/gadget/composite.c +@@ -898,6 +898,18 @@ static void composite_disconnect(struct + + /*-------------------------------------------------------------------------*/ + ++static ssize_t composite_show_suspended(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct usb_gadget *gadget = dev_to_usb_gadget(dev); ++ struct usb_composite_dev *cdev = get_gadget_data(gadget); ++ ++ return sprintf(buf, "%d\n", cdev->suspended); ++} ++ ++static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL); ++ + static void /* __init_or_exit */ + composite_unbind(struct usb_gadget *gadget) + { +@@ -944,6 +956,7 @@ composite_unbind(struct usb_gadget *gadg + } + kfree(cdev); + set_gadget_data(gadget, NULL); ++ device_remove_file(&gadget->dev, &dev_attr_suspended); + composite = NULL; + } + +@@ -1036,6 +1049,10 @@ static int __init composite_bind(struct + string_override(composite->strings, + cdev->desc.iSerialNumber, iSerialNumber); + ++ status = device_create_file(&gadget->dev, &dev_attr_suspended); ++ if (status) ++ goto fail; ++ + INFO(cdev, "%s ready\n", composite->name); + return 0; + +@@ -1064,6 +1081,8 @@ composite_suspend(struct usb_gadget *gad + } + if (composite->suspend) + composite->suspend(cdev); ++ ++ cdev->suspended = 1; + } + + static void +@@ -1084,6 +1103,8 @@ composite_resume(struct usb_gadget *gadg + f->resume(f); + } + } ++ ++ cdev->suspended = 0; + } + + /*-------------------------------------------------------------------------*/ +--- a/include/linux/usb/composite.h ++++ b/include/linux/usb/composite.h +@@ -326,6 +326,7 @@ struct usb_composite_dev { + + /* private: */ + /* internals */ ++ unsigned int suspended:1; + struct usb_device_descriptor desc; + struct list_head configs; + struct usb_composite_driver *driver; +--- a/include/linux/usb/gadget.h ++++ b/include/linux/usb/gadget.h +@@ -494,6 +494,10 @@ static inline void set_gadget_data(struc + { dev_set_drvdata(&gadget->dev, data); } + static inline void *get_gadget_data(struct usb_gadget *gadget) + { return dev_get_drvdata(&gadget->dev); } ++static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev) ++{ ++ return container_of(dev, struct usb_gadget, dev); ++} + + /* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */ + #define gadget_for_each_ep(tmp,gadget) \ diff --git a/usb/usb-core-config.c-usb_get_configuration-simplified.patch b/usb/usb-core-config.c-usb_get_configuration-simplified.patch new file mode 100644 index 00000000000000..9359a5ebf715f0 --- /dev/null +++ b/usb/usb-core-config.c-usb_get_configuration-simplified.patch @@ -0,0 +1,60 @@ +From mina86@mina86.com Thu Apr 29 16:05:40 2010 +From: Michal Nazarewicz <mina86@mina86.com> +Date: Sat, 17 Apr 2010 17:12:58 +0200 +Subject: USB: core: config.c: usb_get_configuration() simplified +To: Alan Stern <stern@rowland.harvard.edu> +Cc: linux-usb@vger.kernel.org, <Linux-kernel@vger.kernel.org>, Greg Kroah-Hartman <gregkh@suse.de> +Message-ID: <87sk6uaz9h.fsf@erwin.mina86.com> + + +usb_gat_configuratio() used two pointers to point to the same +memory. Code simplified, by removing one of them. + +Signed-off-by: Michal Nazarewicz <mina86@mina86.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/config.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -735,7 +735,6 @@ int usb_get_configuration(struct usb_dev + int ncfg = dev->descriptor.bNumConfigurations; + int result = 0; + unsigned int cfgno, length; +- unsigned char *buffer; + unsigned char *bigbuffer; + struct usb_config_descriptor *desc; + +@@ -764,17 +763,16 @@ int usb_get_configuration(struct usb_dev + if (!dev->rawdescriptors) + goto err2; + +- buffer = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); +- if (!buffer) ++ desc = kmalloc(USB_DT_CONFIG_SIZE, GFP_KERNEL); ++ if (!desc) + goto err2; +- desc = (struct usb_config_descriptor *)buffer; + + result = 0; + for (; cfgno < ncfg; cfgno++) { + /* We grab just the first descriptor so we know how long + * the whole configuration is */ + result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, +- buffer, USB_DT_CONFIG_SIZE); ++ desc, USB_DT_CONFIG_SIZE); + if (result < 0) { + dev_err(ddev, "unable to read config index %d " + "descriptor/%s: %d\n", cfgno, "start", result); +@@ -823,7 +821,7 @@ int usb_get_configuration(struct usb_dev + result = 0; + + err: +- kfree(buffer); ++ kfree(desc); + out_not_authorized: + dev->descriptor.bNumConfigurations = cfgno; + err2: diff --git a/usb/usb-don-t-enable-remote-wakeup-by-default.patch b/usb/usb-don-t-enable-remote-wakeup-by-default.patch index 0eef17f4964813..3e9effc0951c10 100644 --- a/usb/usb-don-t-enable-remote-wakeup-by-default.patch +++ b/usb/usb-don-t-enable-remote-wakeup-by-default.patch @@ -26,7 +26,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -1784,7 +1784,6 @@ int usb_new_device(struct usb_device *ud +@@ -1783,7 +1783,6 @@ int usb_new_device(struct usb_device *ud * sysfs power/wakeup controls wakeup enabled/disabled */ device_init_wakeup(&udev->dev, 0); diff --git a/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch b/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch index 1bd7002f0875ba..2d08d07470a369 100644 --- a/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch +++ b/usb/usb-fix-usbmon-and-dma-mapping-for-scatter-gather-urbs.patch @@ -51,7 +51,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c -@@ -1260,6 +1260,51 @@ static void hcd_free_coherent(struct usb +@@ -1259,6 +1259,51 @@ static void hcd_free_coherent(struct usb *dma_handle = 0; } @@ -103,7 +103,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) { -@@ -1271,8 +1316,6 @@ static int map_urb_for_dma(struct usb_hc +@@ -1270,8 +1315,6 @@ static int map_urb_for_dma(struct usb_hc * unless it uses pio or talks to another transport, * or uses the provided scatter gather list for bulk. */ @@ -112,7 +112,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (usb_endpoint_xfer_control(&urb->ep->desc) && !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP)) { -@@ -1285,6 +1328,7 @@ static int map_urb_for_dma(struct usb_hc +@@ -1284,6 +1327,7 @@ static int map_urb_for_dma(struct usb_hc if (dma_mapping_error(hcd->self.controller, urb->setup_dma)) return -EAGAIN; @@ -120,7 +120,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } else if (hcd->driver->flags & HCD_LOCAL_MEM) ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, -@@ -1292,20 +1336,57 @@ static int map_urb_for_dma(struct usb_hc +@@ -1291,20 +1335,57 @@ static int map_urb_for_dma(struct usb_hc (void **)&urb->setup_packet, sizeof(struct usb_ctrlrequest), DMA_TO_DEVICE); @@ -186,7 +186,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } else if (hcd->driver->flags & HCD_LOCAL_MEM) { ret = hcd_alloc_coherent( urb->dev->bus, mem_flags, -@@ -1313,55 +1394,16 @@ static int map_urb_for_dma(struct usb_hc +@@ -1312,55 +1393,16 @@ static int map_urb_for_dma(struct usb_hc &urb->transfer_buffer, urb->transfer_buffer_length, dir); @@ -247,7 +247,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /*-------------------------------------------------------------------------*/ /* may be called in any context with a valid urb->dev usecount -@@ -1390,21 +1432,20 @@ int usb_hcd_submit_urb (struct urb *urb, +@@ -1389,21 +1431,20 @@ int usb_hcd_submit_urb (struct urb *urb, * URBs must be submitted in process context with interrupts * enabled. */ diff --git a/usb/usb-improve-runtime-remote-wakeup-settings.patch b/usb/usb-improve-runtime-remote-wakeup-settings.patch index d716bd5357879c..61b4ac53f24b5f 100644 --- a/usb/usb-improve-runtime-remote-wakeup-settings.patch +++ b/usb/usb-improve-runtime-remote-wakeup-settings.patch @@ -22,7 +22,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c -@@ -1485,9 +1485,6 @@ int usb_autoresume_device(struct usb_dev +@@ -1486,9 +1486,6 @@ int usb_autoresume_device(struct usb_dev * 0, a delayed autosuspend request for @intf's device is attempted. The * attempt may fail (see autosuspend_check()). * @@ -32,7 +32,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> * This routine can run only in process context. */ void usb_autopm_put_interface(struct usb_interface *intf) -@@ -1672,14 +1669,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interfa +@@ -1673,14 +1670,14 @@ EXPORT_SYMBOL_GPL(usb_autopm_get_interfa /* Internal routine to check whether we may autosuspend a device. */ static int autosuspend_check(struct usb_device *udev) { @@ -49,7 +49,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> if (udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; -@@ -1693,12 +1690,7 @@ static int autosuspend_check(struct usb_ +@@ -1694,12 +1691,7 @@ static int autosuspend_check(struct usb_ continue; if (atomic_read(&intf->dev.power.usage_count) > 0) return -EBUSY; @@ -63,7 +63,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* Don't allow autosuspend if the device will need * a reset-resume and any of its interface drivers -@@ -1714,6 +1706,11 @@ static int autosuspend_check(struct usb_ +@@ -1715,6 +1707,11 @@ static int autosuspend_check(struct usb_ } } } diff --git a/usb/usb-make-hcd.h-public-drivers-dependency.patch b/usb/usb-make-hcd.h-public-drivers-dependency.patch new file mode 100644 index 00000000000000..f6a640422331ef --- /dev/null +++ b/usb/usb-make-hcd.h-public-drivers-dependency.patch @@ -0,0 +1,1838 @@ +From Eric.Lescouet@virtuallogix.com Thu Apr 29 16:09:14 2010 +From: Eric Lescouet <Eric.Lescouet@virtuallogix.com> +Date: Sat, 24 Apr 2010 23:21:52 +0200 +Subject: USB: make hcd.h public (drivers dependency) +To: Greg KH <greg@kroah.com> +Cc: Alan Stern <stern@rowland.harvard.edu> +Message-ID: <1272144112.2307.4.camel@localhost> + + +The usbcore headers: hcd.h and hub.h are shared between usbcore, +HCDs and a couple of other drivers (e.g. USBIP modules). +So, it makes sense to move them into a more public location and +to cleanup dependency of those modules on kernel internal headers. +This patch moves hcd.h from drivers/usb/core into include/linux/usb/ + +Signed-of-by: Eric Lescouet <eric@lescouet.org> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/staging/usbip/stub_rx.c | 2 + drivers/staging/usbip/vhci.h | 2 + drivers/usb/c67x00/c67x00-hcd.h | 2 + drivers/usb/core/buffer.c | 2 + drivers/usb/core/config.c | 3 + drivers/usb/core/devices.c | 2 + drivers/usb/core/devio.c | 3 + drivers/usb/core/driver.c | 3 + drivers/usb/core/generic.c | 2 + drivers/usb/core/hcd-pci.c | 2 + drivers/usb/core/hcd.c | 3 + drivers/usb/core/hcd.h | 578 ---------------------------------------- + drivers/usb/core/hub.c | 3 + drivers/usb/core/inode.c | 2 + drivers/usb/core/message.c | 2 + drivers/usb/core/urb.c | 2 + drivers/usb/core/usb.c | 2 + drivers/usb/gadget/dummy_hcd.c | 4 + drivers/usb/host/ehci-hcd.c | 3 + drivers/usb/host/fhci-dbg.c | 2 + drivers/usb/host/fhci-hcd.c | 2 + drivers/usb/host/fhci-hub.c | 2 + drivers/usb/host/fhci-mem.c | 2 + drivers/usb/host/fhci-q.c | 2 + drivers/usb/host/fhci-sched.c | 2 + drivers/usb/host/fhci-tds.c | 2 + drivers/usb/host/fhci.h | 2 + drivers/usb/host/imx21-hcd.c | 2 + drivers/usb/host/isp116x-hcd.c | 2 + drivers/usb/host/isp1362-hcd.c | 2 + drivers/usb/host/isp1760-hcd.c | 2 + drivers/usb/host/isp1760-if.c | 2 + drivers/usb/host/ohci-hcd.c | 2 + drivers/usb/host/oxu210hp-hcd.c | 3 + drivers/usb/host/r8a66597-hcd.c | 2 + drivers/usb/host/sl811-hcd.c | 2 + drivers/usb/host/u132-hcd.c | 2 + drivers/usb/host/uhci-hcd.c | 2 + drivers/usb/host/xhci.h | 2 + drivers/usb/misc/ftdi-elan.c | 2 + drivers/usb/mon/mon_main.c | 3 + drivers/usb/musb/musb_core.h | 2 + drivers/usb/wusbcore/wusbhc.h | 4 + include/linux/usb/hcd.h | 578 ++++++++++++++++++++++++++++++++++++++++ + 44 files changed, 623 insertions(+), 629 deletions(-) + +--- a/drivers/staging/usbip/stub_rx.c ++++ b/drivers/staging/usbip/stub_rx.c +@@ -21,7 +21,7 @@ + + #include "usbip_common.h" + #include "stub.h" +-#include "../../usb/core/hcd.h" ++#include <linux/usb/hcd.h> + + + static int is_clear_halt_cmd(struct urb *urb) +--- a/drivers/staging/usbip/vhci.h ++++ b/drivers/staging/usbip/vhci.h +@@ -18,7 +18,7 @@ + */ + + #include <linux/platform_device.h> +-#include "../../usb/core/hcd.h" ++#include <linux/usb/hcd.h> + + + struct vhci_device { +--- a/drivers/usb/c67x00/c67x00-hcd.h ++++ b/drivers/usb/c67x00/c67x00-hcd.h +@@ -28,7 +28,7 @@ + #include <linux/spinlock.h> + #include <linux/list.h> + #include <linux/usb.h> +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + #include "c67x00.h" + + /* +--- a/drivers/usb/core/buffer.c ++++ b/drivers/usb/core/buffer.c +@@ -14,7 +14,7 @@ + #include <linux/dma-mapping.h> + #include <linux/dmapool.h> + #include <linux/usb.h> +-#include "hcd.h" ++#include <linux/usb/hcd.h> + + + /* +--- a/drivers/usb/core/config.c ++++ b/drivers/usb/core/config.c +@@ -1,12 +1,13 @@ + #include <linux/usb.h> + #include <linux/usb/ch9.h> ++#include <linux/usb/hcd.h> + #include <linux/module.h> + #include <linux/init.h> + #include <linux/slab.h> + #include <linux/device.h> + #include <asm/byteorder.h> + #include "usb.h" +-#include "hcd.h" ++ + + #define USB_MAXALTSETTING 128 /* Hard limit */ + #define USB_MAXENDPOINTS 30 /* Hard limit */ +--- a/drivers/usb/core/devices.c ++++ b/drivers/usb/core/devices.c +@@ -55,11 +55,11 @@ + #include <linux/usb.h> + #include <linux/smp_lock.h> + #include <linux/usbdevice_fs.h> ++#include <linux/usb/hcd.h> + #include <linux/mutex.h> + #include <asm/uaccess.h> + + #include "usb.h" +-#include "hcd.h" + + /* Define ALLOW_SERIAL_NUMBER if you want to see the serial number of devices */ + #define ALLOW_SERIAL_NUMBER +--- a/drivers/usb/core/devio.c ++++ b/drivers/usb/core/devio.c +@@ -43,6 +43,7 @@ + #include <linux/module.h> + #include <linux/usb.h> + #include <linux/usbdevice_fs.h> ++#include <linux/usb/hcd.h> /* for usbcore internals */ + #include <linux/cdev.h> + #include <linux/notifier.h> + #include <linux/security.h> +@@ -50,9 +51,7 @@ + #include <asm/byteorder.h> + #include <linux/moduleparam.h> + +-#include "hcd.h" /* for usbcore internals */ + #include "usb.h" +-#include "hub.h" + + #define USB_MAXBUS 64 + #define USB_DEVICE_MAX USB_MAXBUS * 128 +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -26,8 +26,9 @@ + #include <linux/slab.h> + #include <linux/usb.h> + #include <linux/usb/quirks.h> ++#include <linux/usb/hcd.h> + #include <linux/pm_runtime.h> +-#include "hcd.h" ++ + #include "usb.h" + + +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -18,8 +18,8 @@ + */ + + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include "usb.h" +-#include "hcd.h" + + static inline const char *plural(int n) + { +--- a/drivers/usb/core/hcd-pci.c ++++ b/drivers/usb/core/hcd-pci.c +@@ -21,6 +21,7 @@ + #include <linux/pci.h> + #include <linux/pm_runtime.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + + #include <asm/io.h> + #include <asm/irq.h> +@@ -33,7 +34,6 @@ + #endif + + #include "usb.h" +-#include "hcd.h" + + + /* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ +--- a/drivers/usb/core/hcd.c ++++ b/drivers/usb/core/hcd.c +@@ -42,10 +42,9 @@ + #include <linux/pm_runtime.h> + + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + + #include "usb.h" +-#include "hcd.h" +-#include "hub.h" + + + /*-------------------------------------------------------------------------*/ +--- a/drivers/usb/core/hcd.h ++++ /dev/null +@@ -1,578 +0,0 @@ +-/* +- * Copyright (c) 2001-2002 by David Brownell +- * +- * This program is free software; you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by the +- * Free Software Foundation; either version 2 of the License, or (at your +- * option) any later version. +- * +- * 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. +- */ +- +-#ifndef __USB_CORE_HCD_H +-#define __USB_CORE_HCD_H +- +-#ifdef __KERNEL__ +- +-#include <linux/rwsem.h> +- +-#define MAX_TOPO_LEVEL 6 +- +-/* This file contains declarations of usbcore internals that are mostly +- * used or exposed by Host Controller Drivers. +- */ +- +-/* +- * USB Packet IDs (PIDs) +- */ +-#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */ +-#define USB_PID_OUT 0xe1 +-#define USB_PID_ACK 0xd2 +-#define USB_PID_DATA0 0xc3 +-#define USB_PID_PING 0xb4 /* USB 2.0 */ +-#define USB_PID_SOF 0xa5 +-#define USB_PID_NYET 0x96 /* USB 2.0 */ +-#define USB_PID_DATA2 0x87 /* USB 2.0 */ +-#define USB_PID_SPLIT 0x78 /* USB 2.0 */ +-#define USB_PID_IN 0x69 +-#define USB_PID_NAK 0x5a +-#define USB_PID_DATA1 0x4b +-#define USB_PID_PREAMBLE 0x3c /* Token mode */ +-#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ +-#define USB_PID_SETUP 0x2d +-#define USB_PID_STALL 0x1e +-#define USB_PID_MDATA 0x0f /* USB 2.0 */ +- +-/*-------------------------------------------------------------------------*/ +- +-/* +- * USB Host Controller Driver (usb_hcd) framework +- * +- * Since "struct usb_bus" is so thin, you can't share much code in it. +- * This framework is a layer over that, and should be more sharable. +- * +- * @authorized_default: Specifies if new devices are authorized to +- * connect by default or they require explicit +- * user space authorization; this bit is settable +- * through /sys/class/usb_host/X/authorized_default. +- * For the rest is RO, so we don't lock to r/w it. +- */ +- +-/*-------------------------------------------------------------------------*/ +- +-struct usb_hcd { +- +- /* +- * housekeeping +- */ +- struct usb_bus self; /* hcd is-a bus */ +- struct kref kref; /* reference counter */ +- +- const char *product_desc; /* product/vendor string */ +- char irq_descr[24]; /* driver + bus # */ +- +- struct timer_list rh_timer; /* drives root-hub polling */ +- struct urb *status_urb; /* the current status urb */ +-#ifdef CONFIG_USB_SUSPEND +- struct work_struct wakeup_work; /* for remote wakeup */ +-#endif +- +- /* +- * hardware info/state +- */ +- const struct hc_driver *driver; /* hw-specific hooks */ +- +- /* Flags that need to be manipulated atomically */ +- unsigned long flags; +-#define HCD_FLAG_HW_ACCESSIBLE 0x00000001 +-#define HCD_FLAG_SAW_IRQ 0x00000002 +- +- unsigned rh_registered:1;/* is root hub registered? */ +- +- /* The next flag is a stopgap, to be removed when all the HCDs +- * support the new root-hub polling mechanism. */ +- unsigned uses_new_polling:1; +- unsigned poll_rh:1; /* poll for rh status? */ +- unsigned poll_pending:1; /* status has changed? */ +- unsigned wireless:1; /* Wireless USB HCD */ +- unsigned authorized_default:1; +- unsigned has_tt:1; /* Integrated TT in root hub */ +- +- int irq; /* irq allocated */ +- void __iomem *regs; /* device memory/io */ +- u64 rsrc_start; /* memory/io resource start */ +- u64 rsrc_len; /* memory/io resource length */ +- unsigned power_budget; /* in mA, 0 = no limit */ +- +- /* bandwidth_mutex should be taken before adding or removing +- * any new bus bandwidth constraints: +- * 1. Before adding a configuration for a new device. +- * 2. Before removing the configuration to put the device into +- * the addressed state. +- * 3. Before selecting a different configuration. +- * 4. Before selecting an alternate interface setting. +- * +- * bandwidth_mutex should be dropped after a successful control message +- * to the device, or resetting the bandwidth after a failed attempt. +- */ +- struct mutex bandwidth_mutex; +- +- +-#define HCD_BUFFER_POOLS 4 +- struct dma_pool *pool [HCD_BUFFER_POOLS]; +- +- int state; +-# define __ACTIVE 0x01 +-# define __SUSPEND 0x04 +-# define __TRANSIENT 0x80 +- +-# define HC_STATE_HALT 0 +-# define HC_STATE_RUNNING (__ACTIVE) +-# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) +-# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT) +-# define HC_STATE_SUSPENDED (__SUSPEND) +- +-#define HC_IS_RUNNING(state) ((state) & __ACTIVE) +-#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) +- +- /* more shared queuing code would be good; it should support +- * smarter scheduling, handle transaction translators, etc; +- * input size of periodic table to an interrupt scheduler. +- * (ohci 32, uhci 1024, ehci 256/512/1024). +- */ +- +- /* The HC driver's private data is stored at the end of +- * this structure. +- */ +- unsigned long hcd_priv[0] +- __attribute__ ((aligned(sizeof(unsigned long)))); +-}; +- +-/* 2.4 does this a bit differently ... */ +-static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd) +-{ +- return &hcd->self; +-} +- +-static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus) +-{ +- return container_of(bus, struct usb_hcd, self); +-} +- +-struct hcd_timeout { /* timeouts we allocate */ +- struct list_head timeout_list; +- struct timer_list timer; +-}; +- +-/*-------------------------------------------------------------------------*/ +- +- +-struct hc_driver { +- const char *description; /* "ehci-hcd" etc */ +- const char *product_desc; /* product/vendor string */ +- size_t hcd_priv_size; /* size of private data */ +- +- /* irq handler */ +- irqreturn_t (*irq) (struct usb_hcd *hcd); +- +- int flags; +-#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ +-#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */ +-#define HCD_USB11 0x0010 /* USB 1.1 */ +-#define HCD_USB2 0x0020 /* USB 2.0 */ +-#define HCD_USB3 0x0040 /* USB 3.0 */ +-#define HCD_MASK 0x0070 +- +- /* called to init HCD and root hub */ +- int (*reset) (struct usb_hcd *hcd); +- int (*start) (struct usb_hcd *hcd); +- +- /* NOTE: these suspend/resume calls relate to the HC as +- * a whole, not just the root hub; they're for PCI bus glue. +- */ +- /* called after suspending the hub, before entering D3 etc */ +- int (*pci_suspend)(struct usb_hcd *hcd); +- +- /* called after entering D0 (etc), before resuming the hub */ +- int (*pci_resume)(struct usb_hcd *hcd, bool hibernated); +- +- /* cleanly make HCD stop writing memory and doing I/O */ +- void (*stop) (struct usb_hcd *hcd); +- +- /* shutdown HCD */ +- void (*shutdown) (struct usb_hcd *hcd); +- +- /* return current frame number */ +- int (*get_frame_number) (struct usb_hcd *hcd); +- +- /* manage i/o requests, device state */ +- int (*urb_enqueue)(struct usb_hcd *hcd, +- struct urb *urb, gfp_t mem_flags); +- int (*urb_dequeue)(struct usb_hcd *hcd, +- struct urb *urb, int status); +- +- /* hw synch, freeing endpoint resources that urb_dequeue can't */ +- void (*endpoint_disable)(struct usb_hcd *hcd, +- struct usb_host_endpoint *ep); +- +- /* (optional) reset any endpoint state such as sequence number +- and current window */ +- void (*endpoint_reset)(struct usb_hcd *hcd, +- struct usb_host_endpoint *ep); +- +- /* root hub support */ +- int (*hub_status_data) (struct usb_hcd *hcd, char *buf); +- int (*hub_control) (struct usb_hcd *hcd, +- u16 typeReq, u16 wValue, u16 wIndex, +- char *buf, u16 wLength); +- int (*bus_suspend)(struct usb_hcd *); +- int (*bus_resume)(struct usb_hcd *); +- int (*start_port_reset)(struct usb_hcd *, unsigned port_num); +- +- /* force handover of high-speed port to full-speed companion */ +- void (*relinquish_port)(struct usb_hcd *, int); +- /* has a port been handed over to a companion? */ +- int (*port_handed_over)(struct usb_hcd *, int); +- +- /* CLEAR_TT_BUFFER completion callback */ +- void (*clear_tt_buffer_complete)(struct usb_hcd *, +- struct usb_host_endpoint *); +- +- /* xHCI specific functions */ +- /* Called by usb_alloc_dev to alloc HC device structures */ +- int (*alloc_dev)(struct usb_hcd *, struct usb_device *); +- /* Called by usb_disconnect to free HC device structures */ +- void (*free_dev)(struct usb_hcd *, struct usb_device *); +- +- /* Bandwidth computation functions */ +- /* Note that add_endpoint() can only be called once per endpoint before +- * check_bandwidth() or reset_bandwidth() must be called. +- * drop_endpoint() can only be called once per endpoint also. +- * A call to xhci_drop_endpoint() followed by a call to xhci_add_endpoint() will +- * add the endpoint to the schedule with possibly new parameters denoted by a +- * different endpoint descriptor in usb_host_endpoint. +- * A call to xhci_add_endpoint() followed by a call to xhci_drop_endpoint() is +- * not allowed. +- */ +- /* Allocate endpoint resources and add them to a new schedule */ +- int (*add_endpoint)(struct usb_hcd *, struct usb_device *, struct usb_host_endpoint *); +- /* Drop an endpoint from a new schedule */ +- int (*drop_endpoint)(struct usb_hcd *, struct usb_device *, struct usb_host_endpoint *); +- /* Check that a new hardware configuration, set using +- * endpoint_enable and endpoint_disable, does not exceed bus +- * bandwidth. This must be called before any set configuration +- * or set interface requests are sent to the device. +- */ +- int (*check_bandwidth)(struct usb_hcd *, struct usb_device *); +- /* Reset the device schedule to the last known good schedule, +- * which was set from a previous successful call to +- * check_bandwidth(). This reverts any add_endpoint() and +- * drop_endpoint() calls since that last successful call. +- * Used for when a check_bandwidth() call fails due to resource +- * or bandwidth constraints. +- */ +- void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); +- /* Returns the hardware-chosen device address */ +- int (*address_device)(struct usb_hcd *, struct usb_device *udev); +- /* Notifies the HCD after a hub descriptor is fetched. +- * Will block. +- */ +- int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev, +- struct usb_tt *tt, gfp_t mem_flags); +- int (*reset_device)(struct usb_hcd *, struct usb_device *); +-}; +- +-extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); +-extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, +- int status); +-extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb); +- +-extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags); +-extern int usb_hcd_unlink_urb(struct urb *urb, int status); +-extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, +- int status); +-extern void usb_hcd_flush_endpoint(struct usb_device *udev, +- struct usb_host_endpoint *ep); +-extern void usb_hcd_disable_endpoint(struct usb_device *udev, +- struct usb_host_endpoint *ep); +-extern void usb_hcd_reset_endpoint(struct usb_device *udev, +- struct usb_host_endpoint *ep); +-extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); +-extern int usb_hcd_alloc_bandwidth(struct usb_device *udev, +- struct usb_host_config *new_config, +- struct usb_host_interface *old_alt, +- struct usb_host_interface *new_alt); +-extern int usb_hcd_get_frame_number(struct usb_device *udev); +- +-extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, +- struct device *dev, const char *bus_name); +-extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd); +-extern void usb_put_hcd(struct usb_hcd *hcd); +-extern int usb_add_hcd(struct usb_hcd *hcd, +- unsigned int irqnum, unsigned long irqflags); +-extern void usb_remove_hcd(struct usb_hcd *hcd); +- +-struct platform_device; +-extern void usb_hcd_platform_shutdown(struct platform_device *dev); +- +-#ifdef CONFIG_PCI +-struct pci_dev; +-struct pci_device_id; +-extern int usb_hcd_pci_probe(struct pci_dev *dev, +- const struct pci_device_id *id); +-extern void usb_hcd_pci_remove(struct pci_dev *dev); +-extern void usb_hcd_pci_shutdown(struct pci_dev *dev); +- +-#ifdef CONFIG_PM_SLEEP +-extern const struct dev_pm_ops usb_hcd_pci_pm_ops; +-#endif +-#endif /* CONFIG_PCI */ +- +-/* pci-ish (pdev null is ok) buffer alloc/mapping support */ +-int hcd_buffer_create(struct usb_hcd *hcd); +-void hcd_buffer_destroy(struct usb_hcd *hcd); +- +-void *hcd_buffer_alloc(struct usb_bus *bus, size_t size, +- gfp_t mem_flags, dma_addr_t *dma); +-void hcd_buffer_free(struct usb_bus *bus, size_t size, +- void *addr, dma_addr_t dma); +- +-/* generic bus glue, needed for host controllers that don't use PCI */ +-extern irqreturn_t usb_hcd_irq(int irq, void *__hcd); +- +-extern void usb_hc_died(struct usb_hcd *hcd); +-extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); +- +-/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ +-#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) +-#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep))) +-#define usb_settoggle(dev, ep, out, bit) \ +- ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \ +- ((bit) << (ep))) +- +-/* -------------------------------------------------------------------------- */ +- +-/* Enumeration is only for the hub driver, or HCD virtual root hubs */ +-extern struct usb_device *usb_alloc_dev(struct usb_device *parent, +- struct usb_bus *, unsigned port); +-extern int usb_new_device(struct usb_device *dev); +-extern void usb_disconnect(struct usb_device **); +- +-extern int usb_get_configuration(struct usb_device *dev); +-extern void usb_destroy_configuration(struct usb_device *dev); +- +-/*-------------------------------------------------------------------------*/ +- +-/* +- * HCD Root Hub support +- */ +- +-#include "hub.h" +- +-/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ +-#define DeviceRequest \ +- ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) +-#define DeviceOutRequest \ +- ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) +- +-#define InterfaceRequest \ +- ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) +- +-#define EndpointRequest \ +- ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) +-#define EndpointOutRequest \ +- ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) +- +-/* class requests from the USB 2.0 hub spec, table 11-15 */ +-/* GetBusState and SetHubDescriptor are optional, omitted */ +-#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) +-#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) +-#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) +-#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) +-#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) +-#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) +-#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) +- +- +-/*-------------------------------------------------------------------------*/ +- +-/* +- * Generic bandwidth allocation constants/support +- */ +-#define FRAME_TIME_USECS 1000L +-#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ +- /* Trying not to use worst-case bit-stuffing +- * of (7/6 * 8 * bytecount) = 9.33 * bytecount */ +- /* bytecount = data payload byte count */ +- +-#define NS_TO_US(ns) ((ns + 500L) / 1000L) +- /* convert & round nanoseconds to microseconds */ +- +- +-/* +- * Full/low speed bandwidth allocation constants/support. +- */ +-#define BW_HOST_DELAY 1000L /* nanoseconds */ +-#define BW_HUB_LS_SETUP 333L /* nanoseconds */ +- /* 4 full-speed bit times (est.) */ +- +-#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ +-#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) +-#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) +- +-/* +- * Ceiling [nano/micro]seconds (typical) for that many bytes at high speed +- * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed +- * to preallocate bandwidth) +- */ +-#define USB2_HOST_DELAY 5 /* nsec, guess */ +-#define HS_NSECS(bytes) (((55 * 8 * 2083) \ +- + (2083UL * (3 + BitTime(bytes))))/1000 \ +- + USB2_HOST_DELAY) +-#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \ +- + (2083UL * (3 + BitTime(bytes))))/1000 \ +- + USB2_HOST_DELAY) +-#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes)) +-#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes)) +- +-extern long usb_calc_bus_time(int speed, int is_input, +- int isoc, int bytecount); +- +-/*-------------------------------------------------------------------------*/ +- +-extern void usb_set_device_state(struct usb_device *udev, +- enum usb_device_state new_state); +- +-/*-------------------------------------------------------------------------*/ +- +-/* exported only within usbcore */ +- +-extern struct list_head usb_bus_list; +-extern struct mutex usb_bus_list_lock; +-extern wait_queue_head_t usb_kill_urb_queue; +- +-extern int usb_find_interface_driver(struct usb_device *dev, +- struct usb_interface *interface); +- +-#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) +- +-#ifdef CONFIG_PM +-extern void usb_root_hub_lost_power(struct usb_device *rhdev); +-extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg); +-extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg); +-#endif /* CONFIG_PM */ +- +-#ifdef CONFIG_USB_SUSPEND +-extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); +-#else +-static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) +-{ +- return; +-} +-#endif /* CONFIG_USB_SUSPEND */ +- +- +-/* +- * USB device fs stuff +- */ +- +-#ifdef CONFIG_USB_DEVICEFS +- +-/* +- * these are expected to be called from the USB core/hub thread +- * with the kernel lock held +- */ +-extern void usbfs_update_special(void); +-extern int usbfs_init(void); +-extern void usbfs_cleanup(void); +- +-#else /* CONFIG_USB_DEVICEFS */ +- +-static inline void usbfs_update_special(void) {} +-static inline int usbfs_init(void) { return 0; } +-static inline void usbfs_cleanup(void) { } +- +-#endif /* CONFIG_USB_DEVICEFS */ +- +-/*-------------------------------------------------------------------------*/ +- +-#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) +- +-struct usb_mon_operations { +- void (*urb_submit)(struct usb_bus *bus, struct urb *urb); +- void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err); +- void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status); +- /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */ +-}; +- +-extern struct usb_mon_operations *mon_ops; +- +-static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) +-{ +- if (bus->monitored) +- (*mon_ops->urb_submit)(bus, urb); +-} +- +-static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, +- int error) +-{ +- if (bus->monitored) +- (*mon_ops->urb_submit_error)(bus, urb, error); +-} +- +-static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, +- int status) +-{ +- if (bus->monitored) +- (*mon_ops->urb_complete)(bus, urb, status); +-} +- +-int usb_mon_register(struct usb_mon_operations *ops); +-void usb_mon_deregister(void); +- +-#else +- +-static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {} +-static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, +- int error) {} +-static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, +- int status) {} +- +-#endif /* CONFIG_USB_MON || CONFIG_USB_MON_MODULE */ +- +-/*-------------------------------------------------------------------------*/ +- +-/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ +-/* bleech -- resurfaced in 2.4.11 or 2.4.12 */ +-#define bitmap DeviceRemovable +- +- +-/*-------------------------------------------------------------------------*/ +- +-/* random stuff */ +- +-#define RUN_CONTEXT (in_irq() ? "in_irq" \ +- : (in_interrupt() ? "in_interrupt" : "can sleep")) +- +- +-/* This rwsem is for use only by the hub driver and ehci-hcd. +- * Nobody else should touch it. +- */ +-extern struct rw_semaphore ehci_cf_port_reset_rwsem; +- +-/* Keep track of which host controller drivers are loaded */ +-#define USB_UHCI_LOADED 0 +-#define USB_OHCI_LOADED 1 +-#define USB_EHCI_LOADED 2 +-extern unsigned long usb_hcds_loaded; +- +-#endif /* __KERNEL__ */ +- +-#endif /* __USB_CORE_HCD_H */ +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -19,6 +19,7 @@ + #include <linux/ioctl.h> + #include <linux/usb.h> + #include <linux/usbdevice_fs.h> ++#include <linux/usb/hcd.h> + #include <linux/kthread.h> + #include <linux/mutex.h> + #include <linux/freezer.h> +@@ -28,8 +29,6 @@ + #include <asm/byteorder.h> + + #include "usb.h" +-#include "hcd.h" +-#include "hub.h" + + /* if we are in debug mode, always announce new devices */ + #ifdef DEBUG +--- a/drivers/usb/core/inode.c ++++ b/drivers/usb/core/inode.c +@@ -40,9 +40,9 @@ + #include <linux/notifier.h> + #include <linux/seq_file.h> + #include <linux/smp_lock.h> ++#include <linux/usb/hcd.h> + #include <asm/byteorder.h> + #include "usb.h" +-#include "hcd.h" + + #define USBFS_DEFAULT_DEVMODE (S_IWUSR | S_IRUGO) + #define USBFS_DEFAULT_BUSMODE (S_IXUGO | S_IRUGO) +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -14,9 +14,9 @@ + #include <linux/device.h> + #include <linux/scatterlist.h> + #include <linux/usb/quirks.h> ++#include <linux/usb/hcd.h> /* for usbcore internals */ + #include <asm/byteorder.h> + +-#include "hcd.h" /* for usbcore internals */ + #include "usb.h" + + static void cancel_async_set_config(struct usb_device *udev); +--- a/drivers/usb/core/urb.c ++++ b/drivers/usb/core/urb.c +@@ -6,7 +6,7 @@ + #include <linux/log2.h> + #include <linux/usb.h> + #include <linux/wait.h> +-#include "hcd.h" ++#include <linux/usb/hcd.h> + + #define to_urb(d) container_of(d, struct urb, kref) + +--- a/drivers/usb/core/usb.c ++++ b/drivers/usb/core/usb.c +@@ -32,6 +32,7 @@ + #include <linux/spinlock.h> + #include <linux/errno.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/mutex.h> + #include <linux/workqueue.h> + #include <linux/debugfs.h> +@@ -41,7 +42,6 @@ + #include <linux/mm.h> + #include <linux/dma-mapping.h> + +-#include "hcd.h" + #include "usb.h" + + +--- a/drivers/usb/gadget/dummy_hcd.c ++++ b/drivers/usb/gadget/dummy_hcd.c +@@ -47,6 +47,7 @@ + #include <linux/platform_device.h> + #include <linux/usb.h> + #include <linux/usb/gadget.h> ++#include <linux/usb/hcd.h> + + #include <asm/byteorder.h> + #include <asm/io.h> +@@ -55,9 +56,6 @@ + #include <asm/unaligned.h> + + +-#include "../core/hcd.h" +- +- + #define DRIVER_DESC "USB Host+Gadget Emulator" + #define DRIVER_VERSION "02 May 2005" + +--- a/drivers/usb/host/ehci-hcd.c ++++ b/drivers/usb/host/ehci-hcd.c +@@ -31,13 +31,12 @@ + #include <linux/list.h> + #include <linux/interrupt.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/moduleparam.h> + #include <linux/dma-mapping.h> + #include <linux/debugfs.h> + #include <linux/slab.h> + +-#include "../core/hcd.h" +- + #include <asm/byteorder.h> + #include <asm/io.h> + #include <asm/irq.h> +--- a/drivers/usb/host/fhci-dbg.c ++++ b/drivers/usb/host/fhci-dbg.c +@@ -20,7 +20,7 @@ + #include <linux/debugfs.h> + #include <linux/seq_file.h> + #include <linux/usb.h> +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + #include "fhci.h" + + void fhci_dbg_isr(struct fhci_hcd *fhci, int usb_er) +--- a/drivers/usb/host/fhci-hcd.c ++++ b/drivers/usb/host/fhci-hcd.c +@@ -25,12 +25,12 @@ + #include <linux/interrupt.h> + #include <linux/io.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/of_platform.h> + #include <linux/of_gpio.h> + #include <linux/slab.h> + #include <asm/qe.h> + #include <asm/fsl_gtm.h> +-#include "../core/hcd.h" + #include "fhci.h" + + void fhci_start_sof_timer(struct fhci_hcd *fhci) +--- a/drivers/usb/host/fhci-hub.c ++++ b/drivers/usb/host/fhci-hub.c +@@ -22,9 +22,9 @@ + #include <linux/errno.h> + #include <linux/io.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/gpio.h> + #include <asm/qe.h> +-#include "../core/hcd.h" + #include "fhci.h" + + /* virtual root hub specific descriptor */ +--- a/drivers/usb/host/fhci-mem.c ++++ b/drivers/usb/host/fhci-mem.c +@@ -21,7 +21,7 @@ + #include <linux/slab.h> + #include <linux/list.h> + #include <linux/usb.h> +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + #include "fhci.h" + + static void init_td(struct td *td) +--- a/drivers/usb/host/fhci-q.c ++++ b/drivers/usb/host/fhci-q.c +@@ -22,7 +22,7 @@ + #include <linux/slab.h> + #include <linux/list.h> + #include <linux/usb.h> +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + #include "fhci.h" + + /* maps the hardware error code to the USB error code */ +--- a/drivers/usb/host/fhci-sched.c ++++ b/drivers/usb/host/fhci-sched.c +@@ -24,9 +24,9 @@ + #include <linux/interrupt.h> + #include <linux/io.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <asm/qe.h> + #include <asm/fsl_gtm.h> +-#include "../core/hcd.h" + #include "fhci.h" + + static void recycle_frame(struct fhci_usb *usb, struct packet *pkt) +--- a/drivers/usb/host/fhci-tds.c ++++ b/drivers/usb/host/fhci-tds.c +@@ -22,7 +22,7 @@ + #include <linux/list.h> + #include <linux/io.h> + #include <linux/usb.h> +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + #include "fhci.h" + + #define DUMMY_BD_BUFFER 0xdeadbeef +--- a/drivers/usb/host/fhci.h ++++ b/drivers/usb/host/fhci.h +@@ -25,8 +25,8 @@ + #include <linux/kfifo.h> + #include <linux/io.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <asm/qe.h> +-#include "../core/hcd.h" + + #define USB_CLOCK 48000000 + +--- a/drivers/usb/host/imx21-hcd.c ++++ b/drivers/usb/host/imx21-hcd.c +@@ -56,8 +56,8 @@ + #include <linux/platform_device.h> + #include <linux/slab.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + +-#include "../core/hcd.h" + #include "imx21-hcd.h" + + #ifdef DEBUG +--- a/drivers/usb/host/isp116x-hcd.c ++++ b/drivers/usb/host/isp116x-hcd.c +@@ -65,6 +65,7 @@ + #include <linux/slab.h> + #include <linux/usb.h> + #include <linux/usb/isp116x.h> ++#include <linux/usb/hcd.h> + #include <linux/platform_device.h> + + #include <asm/io.h> +@@ -72,7 +73,6 @@ + #include <asm/system.h> + #include <asm/byteorder.h> + +-#include "../core/hcd.h" + #include "isp116x.h" + + #define DRIVER_VERSION "03 Nov 2005" +--- a/drivers/usb/host/isp1362-hcd.c ++++ b/drivers/usb/host/isp1362-hcd.c +@@ -77,6 +77,7 @@ + #include <linux/interrupt.h> + #include <linux/usb.h> + #include <linux/usb/isp1362.h> ++#include <linux/usb/hcd.h> + #include <linux/platform_device.h> + #include <linux/pm.h> + #include <linux/io.h> +@@ -95,7 +96,6 @@ module_param(dbg_level, int, 0); + #define STUB_DEBUG_FILE + #endif + +-#include "../core/hcd.h" + #include "../core/usb.h" + #include "isp1362.h" + +--- a/drivers/usb/host/isp1760-hcd.c ++++ b/drivers/usb/host/isp1760-hcd.c +@@ -14,6 +14,7 @@ + #include <linux/slab.h> + #include <linux/list.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/debugfs.h> + #include <linux/uaccess.h> + #include <linux/io.h> +@@ -21,7 +22,6 @@ + #include <asm/unaligned.h> + #include <asm/cacheflush.h> + +-#include "../core/hcd.h" + #include "isp1760-hcd.h" + + static struct kmem_cache *qtd_cachep; +--- a/drivers/usb/host/isp1760-if.c ++++ b/drivers/usb/host/isp1760-if.c +@@ -13,8 +13,8 @@ + #include <linux/io.h> + #include <linux/platform_device.h> + #include <linux/usb/isp1760.h> ++#include <linux/usb/hcd.h> + +-#include "../core/hcd.h" + #include "isp1760-hcd.h" + + #ifdef CONFIG_PPC_OF +--- a/drivers/usb/host/ohci-hcd.c ++++ b/drivers/usb/host/ohci-hcd.c +@@ -32,6 +32,7 @@ + #include <linux/list.h> + #include <linux/usb.h> + #include <linux/usb/otg.h> ++#include <linux/usb/hcd.h> + #include <linux/dma-mapping.h> + #include <linux/dmapool.h> + #include <linux/workqueue.h> +@@ -43,7 +44,6 @@ + #include <asm/unaligned.h> + #include <asm/byteorder.h> + +-#include "../core/hcd.h" + + #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" + #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" +--- a/drivers/usb/host/oxu210hp-hcd.c ++++ b/drivers/usb/host/oxu210hp-hcd.c +@@ -34,12 +34,11 @@ + #include <linux/list.h> + #include <linux/interrupt.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/moduleparam.h> + #include <linux/dma-mapping.h> + #include <linux/io.h> + +-#include "../core/hcd.h" +- + #include <asm/irq.h> + #include <asm/system.h> + #include <asm/unaligned.h> +--- a/drivers/usb/host/r8a66597-hcd.c ++++ b/drivers/usb/host/r8a66597-hcd.c +@@ -33,6 +33,7 @@ + #include <linux/list.h> + #include <linux/interrupt.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/platform_device.h> + #include <linux/io.h> + #include <linux/mm.h> +@@ -40,7 +41,6 @@ + #include <linux/slab.h> + #include <asm/cacheflush.h> + +-#include "../core/hcd.h" + #include "r8a66597.h" + + MODULE_DESCRIPTION("R8A66597 USB Host Controller Driver"); +--- a/drivers/usb/host/sl811-hcd.c ++++ b/drivers/usb/host/sl811-hcd.c +@@ -45,6 +45,7 @@ + #include <linux/interrupt.h> + #include <linux/usb.h> + #include <linux/usb/sl811.h> ++#include <linux/usb/hcd.h> + #include <linux/platform_device.h> + + #include <asm/io.h> +@@ -53,7 +54,6 @@ + #include <asm/byteorder.h> + #include <asm/unaligned.h> + +-#include "../core/hcd.h" + #include "sl811.h" + + +--- a/drivers/usb/host/u132-hcd.c ++++ b/drivers/usb/host/u132-hcd.c +@@ -49,6 +49,7 @@ + #include <linux/list.h> + #include <linux/interrupt.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/workqueue.h> + #include <linux/platform_device.h> + #include <linux/mutex.h> +@@ -56,7 +57,6 @@ + #include <asm/irq.h> + #include <asm/system.h> + #include <asm/byteorder.h> +-#include "../core/hcd.h" + + /* FIXME ohci.h is ONLY for internal use by the OHCI driver. + * If you're going to try stuff like this, you need to split +--- a/drivers/usb/host/uhci-hcd.c ++++ b/drivers/usb/host/uhci-hcd.c +@@ -38,6 +38,7 @@ + #include <linux/dmapool.h> + #include <linux/dma-mapping.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/bitops.h> + #include <linux/dmi.h> + +@@ -46,7 +47,6 @@ + #include <asm/irq.h> + #include <asm/system.h> + +-#include "../core/hcd.h" + #include "uhci-hcd.h" + #include "pci-quirks.h" + +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -26,8 +26,8 @@ + #include <linux/usb.h> + #include <linux/timer.h> + #include <linux/kernel.h> ++#include <linux/usb/hcd.h> + +-#include "../core/hcd.h" + /* Code sharing between pci-quirks and xhci hcd */ + #include "xhci-ext-caps.h" + +--- a/drivers/usb/misc/ftdi-elan.c ++++ b/drivers/usb/misc/ftdi-elan.c +@@ -73,7 +73,7 @@ static struct list_head ftdi_static_list + */ + #include "usb_u132.h" + #include <asm/io.h> +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + + /* FIXME ohci.h is ONLY for internal use by the OHCI driver. + * If you're going to try stuff like this, you need to split +--- a/drivers/usb/mon/mon_main.c ++++ b/drivers/usb/mon/mon_main.c +@@ -9,12 +9,13 @@ + #include <linux/kernel.h> + #include <linux/module.h> + #include <linux/usb.h> ++#include <linux/usb/hcd.h> + #include <linux/slab.h> + #include <linux/notifier.h> + #include <linux/mutex.h> + + #include "usb_mon.h" +-#include "../core/hcd.h" ++ + + static void mon_stop(struct mon_bus *mbus); + static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus); +--- a/drivers/usb/musb/musb_core.h ++++ b/drivers/usb/musb/musb_core.h +@@ -69,7 +69,7 @@ struct musb_ep; + #include "musb_regs.h" + + #include "musb_gadget.h" +-#include "../core/hcd.h" ++#include <linux/usb/hcd.h> + #include "musb_host.h" + + +--- a/drivers/usb/wusbcore/wusbhc.h ++++ b/drivers/usb/wusbcore/wusbhc.h +@@ -58,9 +58,7 @@ + #include <linux/mutex.h> + #include <linux/kref.h> + #include <linux/workqueue.h> +-/* FIXME: Yes, I know: BAD--it's not my fault the USB HC iface is not +- * public */ +-#include <linux/../../drivers/usb/core/hcd.h> ++#include <linux/usb/hcd.h> + #include <linux/uwb.h> + #include <linux/usb/wusb.h> + +--- /dev/null ++++ b/include/linux/usb/hcd.h +@@ -0,0 +1,578 @@ ++/* ++ * Copyright (c) 2001-2002 by David Brownell ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License as published by the ++ * Free Software Foundation; either version 2 of the License, or (at your ++ * option) any later version. ++ * ++ * 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. ++ */ ++ ++#ifndef __USB_CORE_HCD_H ++#define __USB_CORE_HCD_H ++ ++#ifdef __KERNEL__ ++ ++#include <linux/rwsem.h> ++ ++#define MAX_TOPO_LEVEL 6 ++ ++/* This file contains declarations of usbcore internals that are mostly ++ * used or exposed by Host Controller Drivers. ++ */ ++ ++/* ++ * USB Packet IDs (PIDs) ++ */ ++#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */ ++#define USB_PID_OUT 0xe1 ++#define USB_PID_ACK 0xd2 ++#define USB_PID_DATA0 0xc3 ++#define USB_PID_PING 0xb4 /* USB 2.0 */ ++#define USB_PID_SOF 0xa5 ++#define USB_PID_NYET 0x96 /* USB 2.0 */ ++#define USB_PID_DATA2 0x87 /* USB 2.0 */ ++#define USB_PID_SPLIT 0x78 /* USB 2.0 */ ++#define USB_PID_IN 0x69 ++#define USB_PID_NAK 0x5a ++#define USB_PID_DATA1 0x4b ++#define USB_PID_PREAMBLE 0x3c /* Token mode */ ++#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ ++#define USB_PID_SETUP 0x2d ++#define USB_PID_STALL 0x1e ++#define USB_PID_MDATA 0x0f /* USB 2.0 */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * USB Host Controller Driver (usb_hcd) framework ++ * ++ * Since "struct usb_bus" is so thin, you can't share much code in it. ++ * This framework is a layer over that, and should be more sharable. ++ * ++ * @authorized_default: Specifies if new devices are authorized to ++ * connect by default or they require explicit ++ * user space authorization; this bit is settable ++ * through /sys/class/usb_host/X/authorized_default. ++ * For the rest is RO, so we don't lock to r/w it. ++ */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++struct usb_hcd { ++ ++ /* ++ * housekeeping ++ */ ++ struct usb_bus self; /* hcd is-a bus */ ++ struct kref kref; /* reference counter */ ++ ++ const char *product_desc; /* product/vendor string */ ++ char irq_descr[24]; /* driver + bus # */ ++ ++ struct timer_list rh_timer; /* drives root-hub polling */ ++ struct urb *status_urb; /* the current status urb */ ++#ifdef CONFIG_USB_SUSPEND ++ struct work_struct wakeup_work; /* for remote wakeup */ ++#endif ++ ++ /* ++ * hardware info/state ++ */ ++ const struct hc_driver *driver; /* hw-specific hooks */ ++ ++ /* Flags that need to be manipulated atomically */ ++ unsigned long flags; ++#define HCD_FLAG_HW_ACCESSIBLE 0x00000001 ++#define HCD_FLAG_SAW_IRQ 0x00000002 ++ ++ unsigned rh_registered:1;/* is root hub registered? */ ++ ++ /* The next flag is a stopgap, to be removed when all the HCDs ++ * support the new root-hub polling mechanism. */ ++ unsigned uses_new_polling:1; ++ unsigned poll_rh:1; /* poll for rh status? */ ++ unsigned poll_pending:1; /* status has changed? */ ++ unsigned wireless:1; /* Wireless USB HCD */ ++ unsigned authorized_default:1; ++ unsigned has_tt:1; /* Integrated TT in root hub */ ++ ++ int irq; /* irq allocated */ ++ void __iomem *regs; /* device memory/io */ ++ u64 rsrc_start; /* memory/io resource start */ ++ u64 rsrc_len; /* memory/io resource length */ ++ unsigned power_budget; /* in mA, 0 = no limit */ ++ ++ /* bandwidth_mutex should be taken before adding or removing ++ * any new bus bandwidth constraints: ++ * 1. Before adding a configuration for a new device. ++ * 2. Before removing the configuration to put the device into ++ * the addressed state. ++ * 3. Before selecting a different configuration. ++ * 4. Before selecting an alternate interface setting. ++ * ++ * bandwidth_mutex should be dropped after a successful control message ++ * to the device, or resetting the bandwidth after a failed attempt. ++ */ ++ struct mutex bandwidth_mutex; ++ ++ ++#define HCD_BUFFER_POOLS 4 ++ struct dma_pool *pool [HCD_BUFFER_POOLS]; ++ ++ int state; ++# define __ACTIVE 0x01 ++# define __SUSPEND 0x04 ++# define __TRANSIENT 0x80 ++ ++# define HC_STATE_HALT 0 ++# define HC_STATE_RUNNING (__ACTIVE) ++# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) ++# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT) ++# define HC_STATE_SUSPENDED (__SUSPEND) ++ ++#define HC_IS_RUNNING(state) ((state) & __ACTIVE) ++#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) ++ ++ /* more shared queuing code would be good; it should support ++ * smarter scheduling, handle transaction translators, etc; ++ * input size of periodic table to an interrupt scheduler. ++ * (ohci 32, uhci 1024, ehci 256/512/1024). ++ */ ++ ++ /* The HC driver's private data is stored at the end of ++ * this structure. ++ */ ++ unsigned long hcd_priv[0] ++ __attribute__ ((aligned(sizeof(unsigned long)))); ++}; ++ ++/* 2.4 does this a bit differently ... */ ++static inline struct usb_bus *hcd_to_bus(struct usb_hcd *hcd) ++{ ++ return &hcd->self; ++} ++ ++static inline struct usb_hcd *bus_to_hcd(struct usb_bus *bus) ++{ ++ return container_of(bus, struct usb_hcd, self); ++} ++ ++struct hcd_timeout { /* timeouts we allocate */ ++ struct list_head timeout_list; ++ struct timer_list timer; ++}; ++ ++/*-------------------------------------------------------------------------*/ ++ ++ ++struct hc_driver { ++ const char *description; /* "ehci-hcd" etc */ ++ const char *product_desc; /* product/vendor string */ ++ size_t hcd_priv_size; /* size of private data */ ++ ++ /* irq handler */ ++ irqreturn_t (*irq) (struct usb_hcd *hcd); ++ ++ int flags; ++#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ ++#define HCD_LOCAL_MEM 0x0002 /* HC needs local memory */ ++#define HCD_USB11 0x0010 /* USB 1.1 */ ++#define HCD_USB2 0x0020 /* USB 2.0 */ ++#define HCD_USB3 0x0040 /* USB 3.0 */ ++#define HCD_MASK 0x0070 ++ ++ /* called to init HCD and root hub */ ++ int (*reset) (struct usb_hcd *hcd); ++ int (*start) (struct usb_hcd *hcd); ++ ++ /* NOTE: these suspend/resume calls relate to the HC as ++ * a whole, not just the root hub; they're for PCI bus glue. ++ */ ++ /* called after suspending the hub, before entering D3 etc */ ++ int (*pci_suspend)(struct usb_hcd *hcd); ++ ++ /* called after entering D0 (etc), before resuming the hub */ ++ int (*pci_resume)(struct usb_hcd *hcd, bool hibernated); ++ ++ /* cleanly make HCD stop writing memory and doing I/O */ ++ void (*stop) (struct usb_hcd *hcd); ++ ++ /* shutdown HCD */ ++ void (*shutdown) (struct usb_hcd *hcd); ++ ++ /* return current frame number */ ++ int (*get_frame_number) (struct usb_hcd *hcd); ++ ++ /* manage i/o requests, device state */ ++ int (*urb_enqueue)(struct usb_hcd *hcd, ++ struct urb *urb, gfp_t mem_flags); ++ int (*urb_dequeue)(struct usb_hcd *hcd, ++ struct urb *urb, int status); ++ ++ /* hw synch, freeing endpoint resources that urb_dequeue can't */ ++ void (*endpoint_disable)(struct usb_hcd *hcd, ++ struct usb_host_endpoint *ep); ++ ++ /* (optional) reset any endpoint state such as sequence number ++ and current window */ ++ void (*endpoint_reset)(struct usb_hcd *hcd, ++ struct usb_host_endpoint *ep); ++ ++ /* root hub support */ ++ int (*hub_status_data) (struct usb_hcd *hcd, char *buf); ++ int (*hub_control) (struct usb_hcd *hcd, ++ u16 typeReq, u16 wValue, u16 wIndex, ++ char *buf, u16 wLength); ++ int (*bus_suspend)(struct usb_hcd *); ++ int (*bus_resume)(struct usb_hcd *); ++ int (*start_port_reset)(struct usb_hcd *, unsigned port_num); ++ ++ /* force handover of high-speed port to full-speed companion */ ++ void (*relinquish_port)(struct usb_hcd *, int); ++ /* has a port been handed over to a companion? */ ++ int (*port_handed_over)(struct usb_hcd *, int); ++ ++ /* CLEAR_TT_BUFFER completion callback */ ++ void (*clear_tt_buffer_complete)(struct usb_hcd *, ++ struct usb_host_endpoint *); ++ ++ /* xHCI specific functions */ ++ /* Called by usb_alloc_dev to alloc HC device structures */ ++ int (*alloc_dev)(struct usb_hcd *, struct usb_device *); ++ /* Called by usb_disconnect to free HC device structures */ ++ void (*free_dev)(struct usb_hcd *, struct usb_device *); ++ ++ /* Bandwidth computation functions */ ++ /* Note that add_endpoint() can only be called once per endpoint before ++ * check_bandwidth() or reset_bandwidth() must be called. ++ * drop_endpoint() can only be called once per endpoint also. ++ * A call to xhci_drop_endpoint() followed by a call to xhci_add_endpoint() will ++ * add the endpoint to the schedule with possibly new parameters denoted by a ++ * different endpoint descriptor in usb_host_endpoint. ++ * A call to xhci_add_endpoint() followed by a call to xhci_drop_endpoint() is ++ * not allowed. ++ */ ++ /* Allocate endpoint resources and add them to a new schedule */ ++ int (*add_endpoint)(struct usb_hcd *, struct usb_device *, struct usb_host_endpoint *); ++ /* Drop an endpoint from a new schedule */ ++ int (*drop_endpoint)(struct usb_hcd *, struct usb_device *, struct usb_host_endpoint *); ++ /* Check that a new hardware configuration, set using ++ * endpoint_enable and endpoint_disable, does not exceed bus ++ * bandwidth. This must be called before any set configuration ++ * or set interface requests are sent to the device. ++ */ ++ int (*check_bandwidth)(struct usb_hcd *, struct usb_device *); ++ /* Reset the device schedule to the last known good schedule, ++ * which was set from a previous successful call to ++ * check_bandwidth(). This reverts any add_endpoint() and ++ * drop_endpoint() calls since that last successful call. ++ * Used for when a check_bandwidth() call fails due to resource ++ * or bandwidth constraints. ++ */ ++ void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); ++ /* Returns the hardware-chosen device address */ ++ int (*address_device)(struct usb_hcd *, struct usb_device *udev); ++ /* Notifies the HCD after a hub descriptor is fetched. ++ * Will block. ++ */ ++ int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev, ++ struct usb_tt *tt, gfp_t mem_flags); ++ int (*reset_device)(struct usb_hcd *, struct usb_device *); ++}; ++ ++extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); ++extern int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb, ++ int status); ++extern void usb_hcd_unlink_urb_from_ep(struct usb_hcd *hcd, struct urb *urb); ++ ++extern int usb_hcd_submit_urb(struct urb *urb, gfp_t mem_flags); ++extern int usb_hcd_unlink_urb(struct urb *urb, int status); ++extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb, ++ int status); ++extern void usb_hcd_flush_endpoint(struct usb_device *udev, ++ struct usb_host_endpoint *ep); ++extern void usb_hcd_disable_endpoint(struct usb_device *udev, ++ struct usb_host_endpoint *ep); ++extern void usb_hcd_reset_endpoint(struct usb_device *udev, ++ struct usb_host_endpoint *ep); ++extern void usb_hcd_synchronize_unlinks(struct usb_device *udev); ++extern int usb_hcd_alloc_bandwidth(struct usb_device *udev, ++ struct usb_host_config *new_config, ++ struct usb_host_interface *old_alt, ++ struct usb_host_interface *new_alt); ++extern int usb_hcd_get_frame_number(struct usb_device *udev); ++ ++extern struct usb_hcd *usb_create_hcd(const struct hc_driver *driver, ++ struct device *dev, const char *bus_name); ++extern struct usb_hcd *usb_get_hcd(struct usb_hcd *hcd); ++extern void usb_put_hcd(struct usb_hcd *hcd); ++extern int usb_add_hcd(struct usb_hcd *hcd, ++ unsigned int irqnum, unsigned long irqflags); ++extern void usb_remove_hcd(struct usb_hcd *hcd); ++ ++struct platform_device; ++extern void usb_hcd_platform_shutdown(struct platform_device *dev); ++ ++#ifdef CONFIG_PCI ++struct pci_dev; ++struct pci_device_id; ++extern int usb_hcd_pci_probe(struct pci_dev *dev, ++ const struct pci_device_id *id); ++extern void usb_hcd_pci_remove(struct pci_dev *dev); ++extern void usb_hcd_pci_shutdown(struct pci_dev *dev); ++ ++#ifdef CONFIG_PM_SLEEP ++extern const struct dev_pm_ops usb_hcd_pci_pm_ops; ++#endif ++#endif /* CONFIG_PCI */ ++ ++/* pci-ish (pdev null is ok) buffer alloc/mapping support */ ++int hcd_buffer_create(struct usb_hcd *hcd); ++void hcd_buffer_destroy(struct usb_hcd *hcd); ++ ++void *hcd_buffer_alloc(struct usb_bus *bus, size_t size, ++ gfp_t mem_flags, dma_addr_t *dma); ++void hcd_buffer_free(struct usb_bus *bus, size_t size, ++ void *addr, dma_addr_t dma); ++ ++/* generic bus glue, needed for host controllers that don't use PCI */ ++extern irqreturn_t usb_hcd_irq(int irq, void *__hcd); ++ ++extern void usb_hc_died(struct usb_hcd *hcd); ++extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); ++ ++/* The D0/D1 toggle bits ... USE WITH CAUTION (they're almost hcd-internal) */ ++#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> (ep)) & 1) ++#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << (ep))) ++#define usb_settoggle(dev, ep, out, bit) \ ++ ((dev)->toggle[out] = ((dev)->toggle[out] & ~(1 << (ep))) | \ ++ ((bit) << (ep))) ++ ++/* -------------------------------------------------------------------------- */ ++ ++/* Enumeration is only for the hub driver, or HCD virtual root hubs */ ++extern struct usb_device *usb_alloc_dev(struct usb_device *parent, ++ struct usb_bus *, unsigned port); ++extern int usb_new_device(struct usb_device *dev); ++extern void usb_disconnect(struct usb_device **); ++ ++extern int usb_get_configuration(struct usb_device *dev); ++extern void usb_destroy_configuration(struct usb_device *dev); ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * HCD Root Hub support ++ */ ++ ++#include <linux/../../drivers/usb/core/hub.h> ++ ++/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ ++#define DeviceRequest \ ++ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) ++#define DeviceOutRequest \ ++ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) ++ ++#define InterfaceRequest \ ++ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) ++ ++#define EndpointRequest \ ++ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) ++#define EndpointOutRequest \ ++ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) ++ ++/* class requests from the USB 2.0 hub spec, table 11-15 */ ++/* GetBusState and SetHubDescriptor are optional, omitted */ ++#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) ++#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) ++#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) ++#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) ++#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) ++#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) ++#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* ++ * Generic bandwidth allocation constants/support ++ */ ++#define FRAME_TIME_USECS 1000L ++#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ ++ /* Trying not to use worst-case bit-stuffing ++ * of (7/6 * 8 * bytecount) = 9.33 * bytecount */ ++ /* bytecount = data payload byte count */ ++ ++#define NS_TO_US(ns) ((ns + 500L) / 1000L) ++ /* convert & round nanoseconds to microseconds */ ++ ++ ++/* ++ * Full/low speed bandwidth allocation constants/support. ++ */ ++#define BW_HOST_DELAY 1000L /* nanoseconds */ ++#define BW_HUB_LS_SETUP 333L /* nanoseconds */ ++ /* 4 full-speed bit times (est.) */ ++ ++#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ ++#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) ++#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) ++ ++/* ++ * Ceiling [nano/micro]seconds (typical) for that many bytes at high speed ++ * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed ++ * to preallocate bandwidth) ++ */ ++#define USB2_HOST_DELAY 5 /* nsec, guess */ ++#define HS_NSECS(bytes) (((55 * 8 * 2083) \ ++ + (2083UL * (3 + BitTime(bytes))))/1000 \ ++ + USB2_HOST_DELAY) ++#define HS_NSECS_ISO(bytes) (((38 * 8 * 2083) \ ++ + (2083UL * (3 + BitTime(bytes))))/1000 \ ++ + USB2_HOST_DELAY) ++#define HS_USECS(bytes) NS_TO_US (HS_NSECS(bytes)) ++#define HS_USECS_ISO(bytes) NS_TO_US (HS_NSECS_ISO(bytes)) ++ ++extern long usb_calc_bus_time(int speed, int is_input, ++ int isoc, int bytecount); ++ ++/*-------------------------------------------------------------------------*/ ++ ++extern void usb_set_device_state(struct usb_device *udev, ++ enum usb_device_state new_state); ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* exported only within usbcore */ ++ ++extern struct list_head usb_bus_list; ++extern struct mutex usb_bus_list_lock; ++extern wait_queue_head_t usb_kill_urb_queue; ++ ++extern int usb_find_interface_driver(struct usb_device *dev, ++ struct usb_interface *interface); ++ ++#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) ++ ++#ifdef CONFIG_PM ++extern void usb_root_hub_lost_power(struct usb_device *rhdev); ++extern int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg); ++extern int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg); ++#endif /* CONFIG_PM */ ++ ++#ifdef CONFIG_USB_SUSPEND ++extern void usb_hcd_resume_root_hub(struct usb_hcd *hcd); ++#else ++static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd) ++{ ++ return; ++} ++#endif /* CONFIG_USB_SUSPEND */ ++ ++ ++/* ++ * USB device fs stuff ++ */ ++ ++#ifdef CONFIG_USB_DEVICEFS ++ ++/* ++ * these are expected to be called from the USB core/hub thread ++ * with the kernel lock held ++ */ ++extern void usbfs_update_special(void); ++extern int usbfs_init(void); ++extern void usbfs_cleanup(void); ++ ++#else /* CONFIG_USB_DEVICEFS */ ++ ++static inline void usbfs_update_special(void) {} ++static inline int usbfs_init(void) { return 0; } ++static inline void usbfs_cleanup(void) { } ++ ++#endif /* CONFIG_USB_DEVICEFS */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) ++ ++struct usb_mon_operations { ++ void (*urb_submit)(struct usb_bus *bus, struct urb *urb); ++ void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err); ++ void (*urb_complete)(struct usb_bus *bus, struct urb *urb, int status); ++ /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */ ++}; ++ ++extern struct usb_mon_operations *mon_ops; ++ ++static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) ++{ ++ if (bus->monitored) ++ (*mon_ops->urb_submit)(bus, urb); ++} ++ ++static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, ++ int error) ++{ ++ if (bus->monitored) ++ (*mon_ops->urb_submit_error)(bus, urb, error); ++} ++ ++static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, ++ int status) ++{ ++ if (bus->monitored) ++ (*mon_ops->urb_complete)(bus, urb, status); ++} ++ ++int usb_mon_register(struct usb_mon_operations *ops); ++void usb_mon_deregister(void); ++ ++#else ++ ++static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {} ++static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, ++ int error) {} ++static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb, ++ int status) {} ++ ++#endif /* CONFIG_USB_MON || CONFIG_USB_MON_MODULE */ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ ++/* bleech -- resurfaced in 2.4.11 or 2.4.12 */ ++#define bitmap DeviceRemovable ++ ++ ++/*-------------------------------------------------------------------------*/ ++ ++/* random stuff */ ++ ++#define RUN_CONTEXT (in_irq() ? "in_irq" \ ++ : (in_interrupt() ? "in_interrupt" : "can sleep")) ++ ++ ++/* This rwsem is for use only by the hub driver and ehci-hcd. ++ * Nobody else should touch it. ++ */ ++extern struct rw_semaphore ehci_cf_port_reset_rwsem; ++ ++/* Keep track of which host controller drivers are loaded */ ++#define USB_UHCI_LOADED 0 ++#define USB_OHCI_LOADED 1 ++#define USB_EHCI_LOADED 2 ++extern unsigned long usb_hcds_loaded; ++ ++#endif /* __KERNEL__ */ ++ ++#endif /* __USB_CORE_HCD_H */ diff --git a/usb/usb-make-hub.h-public-drivers-dependency.patch b/usb/usb-make-hub.h-public-drivers-dependency.patch new file mode 100644 index 00000000000000..c6eaa9cd37a4f6 --- /dev/null +++ b/usb/usb-make-hub.h-public-drivers-dependency.patch @@ -0,0 +1,451 @@ +From Eric.Lescouet@virtuallogix.com Thu Apr 29 16:13:33 2010 +From: Eric Lescouet <Eric.Lescouet@virtuallogix.com> +Date: Sat, 24 Apr 2010 23:34:27 +0200 +Subject: USB: make hub.h public (drivers dependency) +To: Greg KH <greg@kroah.com> +Message-ID: <1272144867.2517.1.camel@localhost> + + +The usbcore headers: hcd.h and hub.h are shared between usbcore, +HCDs and a couple of other drivers (e.g. USBIP modules). +So, it makes sense to move them into a more public location and +to cleanup dependency of those modules on kernel internal headers. +This patch moves hub.h from drivers/usb/core into include/linux/usb/ + +Signed-of-by: Eric Lescouet <eric@lescouet.org> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/core/hub.h | 205 ------------------------------------------------ + include/linux/usb/hcd.h | 2 + include/linux/usb/hub.h | 205 ++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 206 insertions(+), 206 deletions(-) + +--- a/drivers/usb/core/hub.h ++++ /dev/null +@@ -1,205 +0,0 @@ +-#ifndef __LINUX_HUB_H +-#define __LINUX_HUB_H +- +-/* +- * Hub protocol and driver data structures. +- * +- * Some of these are known to the "virtual root hub" code +- * in host controller drivers. +- */ +- +-#include <linux/list.h> +-#include <linux/workqueue.h> +-#include <linux/compiler.h> /* likely()/unlikely() */ +- +-/* +- * Hub request types +- */ +- +-#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) +-#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) +- +-/* +- * Hub class requests +- * See USB 2.0 spec Table 11-16 +- */ +-#define HUB_CLEAR_TT_BUFFER 8 +-#define HUB_RESET_TT 9 +-#define HUB_GET_TT_STATE 10 +-#define HUB_STOP_TT 11 +- +-/* +- * Hub Class feature numbers +- * See USB 2.0 spec Table 11-17 +- */ +-#define C_HUB_LOCAL_POWER 0 +-#define C_HUB_OVER_CURRENT 1 +- +-/* +- * Port feature numbers +- * See USB 2.0 spec Table 11-17 +- */ +-#define USB_PORT_FEAT_CONNECTION 0 +-#define USB_PORT_FEAT_ENABLE 1 +-#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */ +-#define USB_PORT_FEAT_OVER_CURRENT 3 +-#define USB_PORT_FEAT_RESET 4 +-#define USB_PORT_FEAT_L1 5 /* L1 suspend */ +-#define USB_PORT_FEAT_POWER 8 +-#define USB_PORT_FEAT_LOWSPEED 9 +-/* This value was never in Table 11-17 */ +-#define USB_PORT_FEAT_HIGHSPEED 10 +-/* This value is also fake */ +-#define USB_PORT_FEAT_SUPERSPEED 11 +-#define USB_PORT_FEAT_C_CONNECTION 16 +-#define USB_PORT_FEAT_C_ENABLE 17 +-#define USB_PORT_FEAT_C_SUSPEND 18 +-#define USB_PORT_FEAT_C_OVER_CURRENT 19 +-#define USB_PORT_FEAT_C_RESET 20 +-#define USB_PORT_FEAT_TEST 21 +-#define USB_PORT_FEAT_INDICATOR 22 +-#define USB_PORT_FEAT_C_PORT_L1 23 +- +-/* +- * Hub Status and Hub Change results +- * See USB 2.0 spec Table 11-19 and Table 11-20 +- */ +-struct usb_port_status { +- __le16 wPortStatus; +- __le16 wPortChange; +-} __attribute__ ((packed)); +- +-/* +- * wPortStatus bit field +- * See USB 2.0 spec Table 11-21 +- */ +-#define USB_PORT_STAT_CONNECTION 0x0001 +-#define USB_PORT_STAT_ENABLE 0x0002 +-#define USB_PORT_STAT_SUSPEND 0x0004 +-#define USB_PORT_STAT_OVERCURRENT 0x0008 +-#define USB_PORT_STAT_RESET 0x0010 +-#define USB_PORT_STAT_L1 0x0020 +-/* bits 6 to 7 are reserved */ +-#define USB_PORT_STAT_POWER 0x0100 +-#define USB_PORT_STAT_LOW_SPEED 0x0200 +-#define USB_PORT_STAT_HIGH_SPEED 0x0400 +-#define USB_PORT_STAT_TEST 0x0800 +-#define USB_PORT_STAT_INDICATOR 0x1000 +-/* bits 13 to 15 are reserved */ +- +-/* +- * wPortChange bit field +- * See USB 2.0 spec Table 11-22 +- * Bits 0 to 4 shown, bits 5 to 15 are reserved +- */ +-#define USB_PORT_STAT_C_CONNECTION 0x0001 +-#define USB_PORT_STAT_C_ENABLE 0x0002 +-#define USB_PORT_STAT_C_SUSPEND 0x0004 +-#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +-#define USB_PORT_STAT_C_RESET 0x0010 +-#define USB_PORT_STAT_C_L1 0x0020 +- +-/* +- * wHubCharacteristics (masks) +- * See USB 2.0 spec Table 11-13, offset 3 +- */ +-#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ +-#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ +-#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ +-#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ +-#define HUB_CHAR_PORTIND 0x0080 /* D7 */ +- +-struct usb_hub_status { +- __le16 wHubStatus; +- __le16 wHubChange; +-} __attribute__ ((packed)); +- +-/* +- * Hub Status & Hub Change bit masks +- * See USB 2.0 spec Table 11-19 and Table 11-20 +- * Bits 0 and 1 for wHubStatus and wHubChange +- * Bits 2 to 15 are reserved for both +- */ +-#define HUB_STATUS_LOCAL_POWER 0x0001 +-#define HUB_STATUS_OVERCURRENT 0x0002 +-#define HUB_CHANGE_LOCAL_POWER 0x0001 +-#define HUB_CHANGE_OVERCURRENT 0x0002 +- +- +-/* +- * Hub descriptor +- * See USB 2.0 spec Table 11-13 +- */ +- +-#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +-#define USB_DT_HUB_NONVAR_SIZE 7 +- +-struct usb_hub_descriptor { +- __u8 bDescLength; +- __u8 bDescriptorType; +- __u8 bNbrPorts; +- __le16 wHubCharacteristics; +- __u8 bPwrOn2PwrGood; +- __u8 bHubContrCurrent; +- /* add 1 bit for hub status change; round to bytes */ +- __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; +- __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; +-} __attribute__ ((packed)); +- +- +-/* port indicator status selectors, tables 11-7 and 11-25 */ +-#define HUB_LED_AUTO 0 +-#define HUB_LED_AMBER 1 +-#define HUB_LED_GREEN 2 +-#define HUB_LED_OFF 3 +- +-enum hub_led_mode { +- INDICATOR_AUTO = 0, +- INDICATOR_CYCLE, +- /* software blinks for attention: software, hardware, reserved */ +- INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF, +- INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF, +- INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF +-} __attribute__ ((packed)); +- +-struct usb_device; +- +-/* Transaction Translator Think Times, in bits */ +-#define HUB_TTTT_8_BITS 0x00 +-#define HUB_TTTT_16_BITS 0x20 +-#define HUB_TTTT_24_BITS 0x40 +-#define HUB_TTTT_32_BITS 0x60 +- +-/* +- * As of USB 2.0, full/low speed devices are segregated into trees. +- * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). +- * The other type grows from high speed hubs when they connect to +- * full/low speed devices using "Transaction Translators" (TTs). +- * +- * TTs should only be known to the hub driver, and high speed bus +- * drivers (only EHCI for now). They affect periodic scheduling and +- * sometimes control/bulk error recovery. +- */ +-struct usb_tt { +- struct usb_device *hub; /* upstream highspeed hub */ +- int multi; /* true means one TT per port */ +- unsigned think_time; /* think time in ns */ +- +- /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ +- spinlock_t lock; +- struct list_head clear_list; /* of usb_tt_clear */ +- struct work_struct clear_work; +-}; +- +-struct usb_tt_clear { +- struct list_head clear_list; +- unsigned tt; +- u16 devinfo; +- struct usb_hcd *hcd; +- struct usb_host_endpoint *ep; +-}; +- +-extern int usb_hub_clear_tt_buffer(struct urb *urb); +-extern void usb_ep0_reinit(struct usb_device *); +- +-#endif /* __LINUX_HUB_H */ +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -374,7 +374,7 @@ extern void usb_destroy_configuration(st + * HCD Root Hub support + */ + +-#include <linux/../../drivers/usb/core/hub.h> ++#include <linux/usb/hub.h> + + /* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ + #define DeviceRequest \ +--- /dev/null ++++ b/include/linux/usb/hub.h +@@ -0,0 +1,205 @@ ++#ifndef __LINUX_HUB_H ++#define __LINUX_HUB_H ++ ++/* ++ * Hub protocol and driver data structures. ++ * ++ * Some of these are known to the "virtual root hub" code ++ * in host controller drivers. ++ */ ++ ++#include <linux/list.h> ++#include <linux/workqueue.h> ++#include <linux/compiler.h> /* likely()/unlikely() */ ++ ++/* ++ * Hub request types ++ */ ++ ++#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) ++#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) ++ ++/* ++ * Hub class requests ++ * See USB 2.0 spec Table 11-16 ++ */ ++#define HUB_CLEAR_TT_BUFFER 8 ++#define HUB_RESET_TT 9 ++#define HUB_GET_TT_STATE 10 ++#define HUB_STOP_TT 11 ++ ++/* ++ * Hub Class feature numbers ++ * See USB 2.0 spec Table 11-17 ++ */ ++#define C_HUB_LOCAL_POWER 0 ++#define C_HUB_OVER_CURRENT 1 ++ ++/* ++ * Port feature numbers ++ * See USB 2.0 spec Table 11-17 ++ */ ++#define USB_PORT_FEAT_CONNECTION 0 ++#define USB_PORT_FEAT_ENABLE 1 ++#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */ ++#define USB_PORT_FEAT_OVER_CURRENT 3 ++#define USB_PORT_FEAT_RESET 4 ++#define USB_PORT_FEAT_L1 5 /* L1 suspend */ ++#define USB_PORT_FEAT_POWER 8 ++#define USB_PORT_FEAT_LOWSPEED 9 ++/* This value was never in Table 11-17 */ ++#define USB_PORT_FEAT_HIGHSPEED 10 ++/* This value is also fake */ ++#define USB_PORT_FEAT_SUPERSPEED 11 ++#define USB_PORT_FEAT_C_CONNECTION 16 ++#define USB_PORT_FEAT_C_ENABLE 17 ++#define USB_PORT_FEAT_C_SUSPEND 18 ++#define USB_PORT_FEAT_C_OVER_CURRENT 19 ++#define USB_PORT_FEAT_C_RESET 20 ++#define USB_PORT_FEAT_TEST 21 ++#define USB_PORT_FEAT_INDICATOR 22 ++#define USB_PORT_FEAT_C_PORT_L1 23 ++ ++/* ++ * Hub Status and Hub Change results ++ * See USB 2.0 spec Table 11-19 and Table 11-20 ++ */ ++struct usb_port_status { ++ __le16 wPortStatus; ++ __le16 wPortChange; ++} __attribute__ ((packed)); ++ ++/* ++ * wPortStatus bit field ++ * See USB 2.0 spec Table 11-21 ++ */ ++#define USB_PORT_STAT_CONNECTION 0x0001 ++#define USB_PORT_STAT_ENABLE 0x0002 ++#define USB_PORT_STAT_SUSPEND 0x0004 ++#define USB_PORT_STAT_OVERCURRENT 0x0008 ++#define USB_PORT_STAT_RESET 0x0010 ++#define USB_PORT_STAT_L1 0x0020 ++/* bits 6 to 7 are reserved */ ++#define USB_PORT_STAT_POWER 0x0100 ++#define USB_PORT_STAT_LOW_SPEED 0x0200 ++#define USB_PORT_STAT_HIGH_SPEED 0x0400 ++#define USB_PORT_STAT_TEST 0x0800 ++#define USB_PORT_STAT_INDICATOR 0x1000 ++/* bits 13 to 15 are reserved */ ++ ++/* ++ * wPortChange bit field ++ * See USB 2.0 spec Table 11-22 ++ * Bits 0 to 4 shown, bits 5 to 15 are reserved ++ */ ++#define USB_PORT_STAT_C_CONNECTION 0x0001 ++#define USB_PORT_STAT_C_ENABLE 0x0002 ++#define USB_PORT_STAT_C_SUSPEND 0x0004 ++#define USB_PORT_STAT_C_OVERCURRENT 0x0008 ++#define USB_PORT_STAT_C_RESET 0x0010 ++#define USB_PORT_STAT_C_L1 0x0020 ++ ++/* ++ * wHubCharacteristics (masks) ++ * See USB 2.0 spec Table 11-13, offset 3 ++ */ ++#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ ++#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ ++#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ ++#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ ++#define HUB_CHAR_PORTIND 0x0080 /* D7 */ ++ ++struct usb_hub_status { ++ __le16 wHubStatus; ++ __le16 wHubChange; ++} __attribute__ ((packed)); ++ ++/* ++ * Hub Status & Hub Change bit masks ++ * See USB 2.0 spec Table 11-19 and Table 11-20 ++ * Bits 0 and 1 for wHubStatus and wHubChange ++ * Bits 2 to 15 are reserved for both ++ */ ++#define HUB_STATUS_LOCAL_POWER 0x0001 ++#define HUB_STATUS_OVERCURRENT 0x0002 ++#define HUB_CHANGE_LOCAL_POWER 0x0001 ++#define HUB_CHANGE_OVERCURRENT 0x0002 ++ ++ ++/* ++ * Hub descriptor ++ * See USB 2.0 spec Table 11-13 ++ */ ++ ++#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) ++#define USB_DT_HUB_NONVAR_SIZE 7 ++ ++struct usb_hub_descriptor { ++ __u8 bDescLength; ++ __u8 bDescriptorType; ++ __u8 bNbrPorts; ++ __le16 wHubCharacteristics; ++ __u8 bPwrOn2PwrGood; ++ __u8 bHubContrCurrent; ++ /* add 1 bit for hub status change; round to bytes */ ++ __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; ++ __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; ++} __attribute__ ((packed)); ++ ++ ++/* port indicator status selectors, tables 11-7 and 11-25 */ ++#define HUB_LED_AUTO 0 ++#define HUB_LED_AMBER 1 ++#define HUB_LED_GREEN 2 ++#define HUB_LED_OFF 3 ++ ++enum hub_led_mode { ++ INDICATOR_AUTO = 0, ++ INDICATOR_CYCLE, ++ /* software blinks for attention: software, hardware, reserved */ ++ INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF, ++ INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF, ++ INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF ++} __attribute__ ((packed)); ++ ++struct usb_device; ++ ++/* Transaction Translator Think Times, in bits */ ++#define HUB_TTTT_8_BITS 0x00 ++#define HUB_TTTT_16_BITS 0x20 ++#define HUB_TTTT_24_BITS 0x40 ++#define HUB_TTTT_32_BITS 0x60 ++ ++/* ++ * As of USB 2.0, full/low speed devices are segregated into trees. ++ * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). ++ * The other type grows from high speed hubs when they connect to ++ * full/low speed devices using "Transaction Translators" (TTs). ++ * ++ * TTs should only be known to the hub driver, and high speed bus ++ * drivers (only EHCI for now). They affect periodic scheduling and ++ * sometimes control/bulk error recovery. ++ */ ++struct usb_tt { ++ struct usb_device *hub; /* upstream highspeed hub */ ++ int multi; /* true means one TT per port */ ++ unsigned think_time; /* think time in ns */ ++ ++ /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ ++ spinlock_t lock; ++ struct list_head clear_list; /* of usb_tt_clear */ ++ struct work_struct clear_work; ++}; ++ ++struct usb_tt_clear { ++ struct list_head clear_list; ++ unsigned tt; ++ u16 devinfo; ++ struct usb_hcd *hcd; ++ struct usb_host_endpoint *ep; ++}; ++ ++extern int usb_hub_clear_tt_buffer(struct urb *urb); ++extern void usb_ep0_reinit(struct usb_device *); ++ ++#endif /* __LINUX_HUB_H */ diff --git a/usb/usb-mass-storage-gadget-handle-eject-request.patch b/usb/usb-mass-storage-gadget-handle-eject-request.patch new file mode 100644 index 00000000000000..974673319494f2 --- /dev/null +++ b/usb/usb-mass-storage-gadget-handle-eject-request.patch @@ -0,0 +1,88 @@ +From fabien.chouteau@gmail.com Thu Apr 29 16:07:55 2010 +From: Fabien Chouteau <fabien.chouteau@barco.com> +Date: Mon, 26 Apr 2010 12:34:54 +0200 +Subject: USB: Mass storage gadget: Handle eject request +To: linux-usb@vger.kernel.org +Cc: Fabien Chouteau <fabien.chouteau@barco.com>, David Brownell <dbrownell@users.sourceforge.net>, Greg Kroah-Hartman <gregkh@suse.de>, Michal Nazarewicz <m.nazarewicz@samsung.com>, Peter Korsgaard <jacmet@sunsite.dk>, linux-kernel@vger.kernel.org +Message-ID: <1272278094-25433-1-git-send-email-fabien.chouteau@gmail.com> + + +From: Fabien Chouteau <fabien.chouteau@barco.com> + +This patch adds handling of the "Start/Stop Unit" SCSI request +to simulate media ejection. + +Signed-off-by: Fabien Chouteau <fabien.chouteau@barco.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/gadget/f_mass_storage.c | 48 +++++++++++++++++++++++++++++++++--- + 1 file changed, 45 insertions(+), 3 deletions(-) + +--- a/drivers/usb/gadget/f_mass_storage.c ++++ b/drivers/usb/gadget/f_mass_storage.c +@@ -163,6 +163,10 @@ + * ro setting are not allowed when the medium is loaded or if CD-ROM + * emulation is being used. + * ++ * When a LUN receive an "eject" SCSI request (Start/Stop Unit), ++ * if the LUN is removable, the backing file is released to simulate ++ * ejection. ++ * + * + * This function is heavily based on "File-backed Storage Gadget" by + * Alan Stern which in turn is heavily based on "Gadget Zero" by David +@@ -1384,12 +1388,50 @@ static int do_mode_sense(struct fsg_comm + + static int do_start_stop(struct fsg_common *common) + { +- if (!common->curlun) { ++ struct fsg_lun *curlun = common->curlun; ++ int loej, start; ++ ++ if (!curlun) { + return -EINVAL; +- } else if (!common->curlun->removable) { +- common->curlun->sense_data = SS_INVALID_COMMAND; ++ } 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 */ ++ 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 { ++ ++ /* Our emulation doesn't support mounting; the medium is ++ * available for use as soon as it is loaded. */ ++ if (!fsg_lun_is_open(curlun)) { ++ curlun->sense_data = SS_MEDIUM_NOT_PRESENT; ++ return -EINVAL; ++ } ++ } + return 0; + } + diff --git a/usb/usb-ncm-added-ncm.h-with-auxiliary-definitions.patch b/usb/usb-ncm-added-ncm.h-with-auxiliary-definitions.patch new file mode 100644 index 00000000000000..28f179c7e2885b --- /dev/null +++ b/usb/usb-ncm-added-ncm.h-with-auxiliary-definitions.patch @@ -0,0 +1,132 @@ +From yauheni.kaliuta@nokia.com Thu Apr 29 16:04:25 2010 +From: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Date: Fri, 16 Apr 2010 16:13:35 +0300 +Subject: USB: ncm: added ncm.h with auxiliary definitions +To: linux-usb@vger.kernel.org +Message-ID: <1271423621-26361-3-git-send-email-yauheni.kaliuta@nokia.com> + + +Signed-off-by: Yauheni Kaliuta <yauheni.kaliuta@nokia.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/ncm.h | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 114 insertions(+) + +--- /dev/null ++++ b/include/linux/usb/ncm.h +@@ -0,0 +1,114 @@ ++/* ++ * USB CDC NCM auxiliary definitions ++ */ ++ ++#ifndef __LINUX_USB_NCM_H ++#define __LINUX_USB_NCM_H ++ ++#include <linux/types.h> ++#include <linux/usb/cdc.h> ++#include <asm/unaligned.h> ++ ++#define NCM_NTB_MIN_IN_SIZE 2048 ++#define NCM_NTB_MIN_OUT_SIZE 2048 ++ ++#define NCM_CONTROL_TIMEOUT (5 * 1000) ++ ++/* bmNetworkCapabilities */ ++ ++#define NCM_NCAP_ETH_FILTER (1 << 0) ++#define NCM_NCAP_NET_ADDRESS (1 << 1) ++#define NCM_NCAP_ENCAP_COMM (1 << 2) ++#define NCM_NCAP_MAX_DGRAM (1 << 3) ++#define NCM_NCAP_CRC_MODE (1 << 4) ++ ++/* ++ * Here are options for NCM Datagram Pointer table (NDP) parser. ++ * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3), ++ * in NDP16 offsets and sizes fields are 1 16bit word wide, ++ * in NDP32 -- 2 16bit words wide. Also signatures are different. ++ * To make the parser code the same, put the differences in the structure, ++ * and switch pointers to the structures when the format is changed. ++ */ ++ ++struct ndp_parser_opts { ++ u32 nth_sign; ++ u32 ndp_sign; ++ unsigned nth_size; ++ unsigned ndp_size; ++ unsigned ndplen_align; ++ /* sizes in u16 units */ ++ unsigned dgram_item_len; /* index or length */ ++ unsigned block_length; ++ unsigned fp_index; ++ unsigned reserved1; ++ unsigned reserved2; ++ unsigned next_fp_index; ++}; ++ ++#define INIT_NDP16_OPTS { \ ++ .nth_sign = NCM_NTH16_SIGN, \ ++ .ndp_sign = NCM_NDP16_NOCRC_SIGN, \ ++ .nth_size = sizeof(struct usb_cdc_ncm_nth16), \ ++ .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \ ++ .ndplen_align = 4, \ ++ .dgram_item_len = 1, \ ++ .block_length = 1, \ ++ .fp_index = 1, \ ++ .reserved1 = 0, \ ++ .reserved2 = 0, \ ++ .next_fp_index = 1, \ ++ } ++ ++ ++#define INIT_NDP32_OPTS { \ ++ .nth_sign = NCM_NTH32_SIGN, \ ++ .ndp_sign = NCM_NDP32_NOCRC_SIGN, \ ++ .nth_size = sizeof(struct usb_cdc_ncm_nth32), \ ++ .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \ ++ .ndplen_align = 8, \ ++ .dgram_item_len = 2, \ ++ .block_length = 2, \ ++ .fp_index = 2, \ ++ .reserved1 = 1, \ ++ .reserved2 = 2, \ ++ .next_fp_index = 2, \ ++ } ++ ++static inline void put_ncm(__le16 **p, unsigned size, unsigned val) ++{ ++ switch (size) { ++ case 1: ++ put_unaligned_le16((u16)val, *p); ++ break; ++ case 2: ++ put_unaligned_le32((u32)val, *p); ++ ++ break; ++ default: ++ BUG(); ++ } ++ ++ *p += size; ++} ++ ++static inline unsigned get_ncm(__le16 **p, unsigned size) ++{ ++ unsigned tmp; ++ ++ switch (size) { ++ case 1: ++ tmp = get_unaligned_le16(*p); ++ break; ++ case 2: ++ tmp = get_unaligned_le32(*p); ++ break; ++ default: ++ BUG(); ++ } ++ ++ *p += size; ++ return tmp; ++} ++ ++#endif /* __LINUX_USB_NCM_H */ diff --git a/usb/usb-remove-bogus-usb_port_feat_-_speed-symbols.patch b/usb/usb-remove-bogus-usb_port_feat_-_speed-symbols.patch index c4a64cd5019cec..168280116808d6 100644 --- a/usb/usb-remove-bogus-usb_port_feat_-_speed-symbols.patch +++ b/usb/usb-remove-bogus-usb_port_feat_-_speed-symbols.patch @@ -7,7 +7,7 @@ Cc: Sarah Sharp <sarah.a.sharp@linux.intel.com>, Andiry Xu <andiry.xu@amd.com>, Message-ID: <Pine.LNX.4.44L0.1003041130360.1657-100000@iolanthe.rowland.org> This patch (as1348) removes the bogus -USB_PORT_FEAT_{HIGHSPEED,SUPERSPEED} symbols from hub.h. No such +USB_PORT_FEAT_{HIGHSPEED,SUPERSPEED} symbols from ch11.h. No such features are defined by the USB spec. (There is a PORT_LOWSPEED feature, but the spec doesn't mention it except to say that host software should never use it.) The speed indicators are port @@ -22,18 +22,18 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- drivers/usb/core/hub.c | 8 ++++---- - drivers/usb/core/hub.h | 7 ++----- drivers/usb/host/ehci.h | 8 ++++---- drivers/usb/host/isp1760-hcd.c | 2 +- drivers/usb/host/oxu210hp-hcd.c | 4 ++-- drivers/usb/host/r8a66597-hcd.c | 7 +++---- drivers/usb/host/sl811-hcd.c | 6 +++--- drivers/usb/host/xhci-hub.c | 8 ++++---- + include/linux/usb/ch11.h | 7 ++----- 8 files changed, 23 insertions(+), 27 deletions(-) --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -154,11 +154,11 @@ static int usb_reset_and_verify_device(s +@@ -153,11 +153,11 @@ static int usb_reset_and_verify_device(s static inline char *portspeed(int portstatus) { @@ -48,7 +48,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> return "5.0 Gb/s"; else return "12 Mb/s"; -@@ -3076,7 +3076,7 @@ static void hub_port_connect_change(stru +@@ -3075,7 +3075,7 @@ static void hub_port_connect_change(stru if (!(hcd->driver->flags & HCD_USB3)) udev->speed = USB_SPEED_UNKNOWN; else if ((hdev->parent == NULL) && @@ -57,29 +57,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> udev->speed = USB_SPEED_SUPER; else udev->speed = USB_SPEED_UNKNOWN; ---- a/drivers/usb/core/hub.h -+++ b/drivers/usb/core/hub.h -@@ -46,11 +46,7 @@ - #define USB_PORT_FEAT_RESET 4 - #define USB_PORT_FEAT_L1 5 /* L1 suspend */ - #define USB_PORT_FEAT_POWER 8 --#define USB_PORT_FEAT_LOWSPEED 9 --/* This value was never in Table 11-17 */ --#define USB_PORT_FEAT_HIGHSPEED 10 --/* This value is also fake */ --#define USB_PORT_FEAT_SUPERSPEED 11 -+#define USB_PORT_FEAT_LOWSPEED 9 /* Should never be used */ - #define USB_PORT_FEAT_C_CONNECTION 16 - #define USB_PORT_FEAT_C_ENABLE 17 - #define USB_PORT_FEAT_C_SUSPEND 18 -@@ -86,6 +82,7 @@ struct usb_port_status { - #define USB_PORT_STAT_TEST 0x0800 - #define USB_PORT_STAT_INDICATOR 0x1000 - /* bits 13 to 15 are reserved */ -+#define USB_PORT_STAT_SUPER_SPEED 0x8000 /* Linux-internal */ - - /* - * wPortChange bit field --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -556,20 +556,20 @@ ehci_port_speed(struct ehci_hcd *ehci, u @@ -120,7 +97,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> { --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c -@@ -3154,10 +3154,10 @@ static inline unsigned int oxu_port_spee +@@ -3153,10 +3153,10 @@ static inline unsigned int oxu_port_spee case 0: return 0; case 1: @@ -202,3 +179,26 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> */ return 0; } +--- a/include/linux/usb/ch11.h ++++ b/include/linux/usb/ch11.h +@@ -47,11 +47,7 @@ + #define USB_PORT_FEAT_RESET 4 + #define USB_PORT_FEAT_L1 5 /* L1 suspend */ + #define USB_PORT_FEAT_POWER 8 +-#define USB_PORT_FEAT_LOWSPEED 9 +-/* This value was never in Table 11-17 */ +-#define USB_PORT_FEAT_HIGHSPEED 10 +-/* This value is also fake */ +-#define USB_PORT_FEAT_SUPERSPEED 11 ++#define USB_PORT_FEAT_LOWSPEED 9 /* Should never be used */ + #define USB_PORT_FEAT_C_CONNECTION 16 + #define USB_PORT_FEAT_C_ENABLE 17 + #define USB_PORT_FEAT_C_SUSPEND 18 +@@ -87,6 +83,7 @@ struct usb_port_status { + #define USB_PORT_STAT_TEST 0x0800 + #define USB_PORT_STAT_INDICATOR 0x1000 + /* bits 13 to 15 are reserved */ ++#define USB_PORT_STAT_SUPER_SPEED 0x8000 /* Linux-internal */ + + /* + * wPortChange bit field diff --git a/usb/usb-split-hub.h-into-ch11.h-and-merge-in-hcd.h.patch b/usb/usb-split-hub.h-into-ch11.h-and-merge-in-hcd.h.patch new file mode 100644 index 00000000000000..548e2f144fa60e --- /dev/null +++ b/usb/usb-split-hub.h-into-ch11.h-and-merge-in-hcd.h.patch @@ -0,0 +1,452 @@ +From Eric.Lescouet@virtuallogix.com Thu Apr 29 16:14:09 2010 +From: Eric Lescouet <Eric.Lescouet@virtuallogix.com> +Date: Sat, 24 Apr 2010 23:38:17 +0200 +Subject: USB: split hub.h into ch11.h and merge-in hcd.h +To: Greg KH <greg@kroah.com> +Message-ID: <1272145097.2517.5.camel@localhost> + + +Base on inputs from Alan Stern, split the hub.h header into: +- new ch11.h header (most of it) containing constants and + structures from chapter 11 of the USB 2.0 spec. +- a small remaining part being merged into hcd.h. + +Signed-of-by: Eric Lescouet <eric@lescouet.org> +Cc: Alan Stern <stern@rowland.harvard.edu> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + include/linux/usb/ch11.h | 172 +++++++++++++++++++++++++++++++++++++++ + include/linux/usb/hcd.h | 37 ++++++++ + include/linux/usb/hub.h | 205 ----------------------------------------------- + 3 files changed, 208 insertions(+), 206 deletions(-) + +--- /dev/null ++++ b/include/linux/usb/ch11.h +@@ -0,0 +1,172 @@ ++/* ++ * This file holds Hub protocol constants and data structures that are ++ * defined in chapter 11 (Hub Specification) of the USB 2.0 specification. ++ * ++ * It is used/shared between the USB core, the HCDs and couple of other USB ++ * drivers. ++ */ ++ ++#ifndef __LINUX_HUB_H ++#define __LINUX_HUB_H ++ ++#include <linux/list.h> ++#include <linux/workqueue.h> ++#include <linux/compiler.h> /* likely()/unlikely() */ ++ ++/* ++ * Hub request types ++ */ ++ ++#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) ++#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) ++ ++/* ++ * Hub class requests ++ * See USB 2.0 spec Table 11-16 ++ */ ++#define HUB_CLEAR_TT_BUFFER 8 ++#define HUB_RESET_TT 9 ++#define HUB_GET_TT_STATE 10 ++#define HUB_STOP_TT 11 ++ ++/* ++ * Hub Class feature numbers ++ * See USB 2.0 spec Table 11-17 ++ */ ++#define C_HUB_LOCAL_POWER 0 ++#define C_HUB_OVER_CURRENT 1 ++ ++/* ++ * Port feature numbers ++ * See USB 2.0 spec Table 11-17 ++ */ ++#define USB_PORT_FEAT_CONNECTION 0 ++#define USB_PORT_FEAT_ENABLE 1 ++#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */ ++#define USB_PORT_FEAT_OVER_CURRENT 3 ++#define USB_PORT_FEAT_RESET 4 ++#define USB_PORT_FEAT_L1 5 /* L1 suspend */ ++#define USB_PORT_FEAT_POWER 8 ++#define USB_PORT_FEAT_LOWSPEED 9 ++/* This value was never in Table 11-17 */ ++#define USB_PORT_FEAT_HIGHSPEED 10 ++/* This value is also fake */ ++#define USB_PORT_FEAT_SUPERSPEED 11 ++#define USB_PORT_FEAT_C_CONNECTION 16 ++#define USB_PORT_FEAT_C_ENABLE 17 ++#define USB_PORT_FEAT_C_SUSPEND 18 ++#define USB_PORT_FEAT_C_OVER_CURRENT 19 ++#define USB_PORT_FEAT_C_RESET 20 ++#define USB_PORT_FEAT_TEST 21 ++#define USB_PORT_FEAT_INDICATOR 22 ++#define USB_PORT_FEAT_C_PORT_L1 23 ++ ++/* ++ * Hub Status and Hub Change results ++ * See USB 2.0 spec Table 11-19 and Table 11-20 ++ */ ++struct usb_port_status { ++ __le16 wPortStatus; ++ __le16 wPortChange; ++} __attribute__ ((packed)); ++ ++/* ++ * wPortStatus bit field ++ * See USB 2.0 spec Table 11-21 ++ */ ++#define USB_PORT_STAT_CONNECTION 0x0001 ++#define USB_PORT_STAT_ENABLE 0x0002 ++#define USB_PORT_STAT_SUSPEND 0x0004 ++#define USB_PORT_STAT_OVERCURRENT 0x0008 ++#define USB_PORT_STAT_RESET 0x0010 ++#define USB_PORT_STAT_L1 0x0020 ++/* bits 6 to 7 are reserved */ ++#define USB_PORT_STAT_POWER 0x0100 ++#define USB_PORT_STAT_LOW_SPEED 0x0200 ++#define USB_PORT_STAT_HIGH_SPEED 0x0400 ++#define USB_PORT_STAT_TEST 0x0800 ++#define USB_PORT_STAT_INDICATOR 0x1000 ++/* bits 13 to 15 are reserved */ ++ ++/* ++ * wPortChange bit field ++ * See USB 2.0 spec Table 11-22 ++ * Bits 0 to 4 shown, bits 5 to 15 are reserved ++ */ ++#define USB_PORT_STAT_C_CONNECTION 0x0001 ++#define USB_PORT_STAT_C_ENABLE 0x0002 ++#define USB_PORT_STAT_C_SUSPEND 0x0004 ++#define USB_PORT_STAT_C_OVERCURRENT 0x0008 ++#define USB_PORT_STAT_C_RESET 0x0010 ++#define USB_PORT_STAT_C_L1 0x0020 ++ ++/* ++ * wHubCharacteristics (masks) ++ * See USB 2.0 spec Table 11-13, offset 3 ++ */ ++#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ ++#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ ++#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ ++#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ ++#define HUB_CHAR_PORTIND 0x0080 /* D7 */ ++ ++struct usb_hub_status { ++ __le16 wHubStatus; ++ __le16 wHubChange; ++} __attribute__ ((packed)); ++ ++/* ++ * Hub Status & Hub Change bit masks ++ * See USB 2.0 spec Table 11-19 and Table 11-20 ++ * Bits 0 and 1 for wHubStatus and wHubChange ++ * Bits 2 to 15 are reserved for both ++ */ ++#define HUB_STATUS_LOCAL_POWER 0x0001 ++#define HUB_STATUS_OVERCURRENT 0x0002 ++#define HUB_CHANGE_LOCAL_POWER 0x0001 ++#define HUB_CHANGE_OVERCURRENT 0x0002 ++ ++ ++/* ++ * Hub descriptor ++ * See USB 2.0 spec Table 11-13 ++ */ ++ ++#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) ++#define USB_DT_HUB_NONVAR_SIZE 7 ++ ++struct usb_hub_descriptor { ++ __u8 bDescLength; ++ __u8 bDescriptorType; ++ __u8 bNbrPorts; ++ __le16 wHubCharacteristics; ++ __u8 bPwrOn2PwrGood; ++ __u8 bHubContrCurrent; ++ /* add 1 bit for hub status change; round to bytes */ ++ __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; ++ __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; ++} __attribute__ ((packed)); ++ ++ ++/* port indicator status selectors, tables 11-7 and 11-25 */ ++#define HUB_LED_AUTO 0 ++#define HUB_LED_AMBER 1 ++#define HUB_LED_GREEN 2 ++#define HUB_LED_OFF 3 ++ ++enum hub_led_mode { ++ INDICATOR_AUTO = 0, ++ INDICATOR_CYCLE, ++ /* software blinks for attention: software, hardware, reserved */ ++ INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF, ++ INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF, ++ INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF ++} __attribute__ ((packed)); ++ ++/* Transaction Translator Think Times, in bits */ ++#define HUB_TTTT_8_BITS 0x00 ++#define HUB_TTTT_16_BITS 0x20 ++#define HUB_TTTT_24_BITS 0x40 ++#define HUB_TTTT_32_BITS 0x60 ++ ++#endif /* __LINUX_HUB_H */ +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -374,7 +374,42 @@ extern void usb_destroy_configuration(st + * HCD Root Hub support + */ + +-#include <linux/usb/hub.h> ++#include <linux/usb/ch11.h> ++ ++/* ++ * As of USB 2.0, full/low speed devices are segregated into trees. ++ * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). ++ * The other type grows from high speed hubs when they connect to ++ * full/low speed devices using "Transaction Translators" (TTs). ++ * ++ * TTs should only be known to the hub driver, and high speed bus ++ * drivers (only EHCI for now). They affect periodic scheduling and ++ * sometimes control/bulk error recovery. ++ */ ++ ++struct usb_device; ++ ++struct usb_tt { ++ struct usb_device *hub; /* upstream highspeed hub */ ++ int multi; /* true means one TT per port */ ++ unsigned think_time; /* think time in ns */ ++ ++ /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ ++ spinlock_t lock; ++ struct list_head clear_list; /* of usb_tt_clear */ ++ struct work_struct clear_work; ++}; ++ ++struct usb_tt_clear { ++ struct list_head clear_list; ++ unsigned tt; ++ u16 devinfo; ++ struct usb_hcd *hcd; ++ struct usb_host_endpoint *ep; ++}; ++ ++extern int usb_hub_clear_tt_buffer(struct urb *urb); ++extern void usb_ep0_reinit(struct usb_device *); + + /* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ + #define DeviceRequest \ +--- a/include/linux/usb/hub.h ++++ /dev/null +@@ -1,205 +0,0 @@ +-#ifndef __LINUX_HUB_H +-#define __LINUX_HUB_H +- +-/* +- * Hub protocol and driver data structures. +- * +- * Some of these are known to the "virtual root hub" code +- * in host controller drivers. +- */ +- +-#include <linux/list.h> +-#include <linux/workqueue.h> +-#include <linux/compiler.h> /* likely()/unlikely() */ +- +-/* +- * Hub request types +- */ +- +-#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) +-#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) +- +-/* +- * Hub class requests +- * See USB 2.0 spec Table 11-16 +- */ +-#define HUB_CLEAR_TT_BUFFER 8 +-#define HUB_RESET_TT 9 +-#define HUB_GET_TT_STATE 10 +-#define HUB_STOP_TT 11 +- +-/* +- * Hub Class feature numbers +- * See USB 2.0 spec Table 11-17 +- */ +-#define C_HUB_LOCAL_POWER 0 +-#define C_HUB_OVER_CURRENT 1 +- +-/* +- * Port feature numbers +- * See USB 2.0 spec Table 11-17 +- */ +-#define USB_PORT_FEAT_CONNECTION 0 +-#define USB_PORT_FEAT_ENABLE 1 +-#define USB_PORT_FEAT_SUSPEND 2 /* L2 suspend */ +-#define USB_PORT_FEAT_OVER_CURRENT 3 +-#define USB_PORT_FEAT_RESET 4 +-#define USB_PORT_FEAT_L1 5 /* L1 suspend */ +-#define USB_PORT_FEAT_POWER 8 +-#define USB_PORT_FEAT_LOWSPEED 9 +-/* This value was never in Table 11-17 */ +-#define USB_PORT_FEAT_HIGHSPEED 10 +-/* This value is also fake */ +-#define USB_PORT_FEAT_SUPERSPEED 11 +-#define USB_PORT_FEAT_C_CONNECTION 16 +-#define USB_PORT_FEAT_C_ENABLE 17 +-#define USB_PORT_FEAT_C_SUSPEND 18 +-#define USB_PORT_FEAT_C_OVER_CURRENT 19 +-#define USB_PORT_FEAT_C_RESET 20 +-#define USB_PORT_FEAT_TEST 21 +-#define USB_PORT_FEAT_INDICATOR 22 +-#define USB_PORT_FEAT_C_PORT_L1 23 +- +-/* +- * Hub Status and Hub Change results +- * See USB 2.0 spec Table 11-19 and Table 11-20 +- */ +-struct usb_port_status { +- __le16 wPortStatus; +- __le16 wPortChange; +-} __attribute__ ((packed)); +- +-/* +- * wPortStatus bit field +- * See USB 2.0 spec Table 11-21 +- */ +-#define USB_PORT_STAT_CONNECTION 0x0001 +-#define USB_PORT_STAT_ENABLE 0x0002 +-#define USB_PORT_STAT_SUSPEND 0x0004 +-#define USB_PORT_STAT_OVERCURRENT 0x0008 +-#define USB_PORT_STAT_RESET 0x0010 +-#define USB_PORT_STAT_L1 0x0020 +-/* bits 6 to 7 are reserved */ +-#define USB_PORT_STAT_POWER 0x0100 +-#define USB_PORT_STAT_LOW_SPEED 0x0200 +-#define USB_PORT_STAT_HIGH_SPEED 0x0400 +-#define USB_PORT_STAT_TEST 0x0800 +-#define USB_PORT_STAT_INDICATOR 0x1000 +-/* bits 13 to 15 are reserved */ +- +-/* +- * wPortChange bit field +- * See USB 2.0 spec Table 11-22 +- * Bits 0 to 4 shown, bits 5 to 15 are reserved +- */ +-#define USB_PORT_STAT_C_CONNECTION 0x0001 +-#define USB_PORT_STAT_C_ENABLE 0x0002 +-#define USB_PORT_STAT_C_SUSPEND 0x0004 +-#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +-#define USB_PORT_STAT_C_RESET 0x0010 +-#define USB_PORT_STAT_C_L1 0x0020 +- +-/* +- * wHubCharacteristics (masks) +- * See USB 2.0 spec Table 11-13, offset 3 +- */ +-#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ +-#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ +-#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ +-#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ +-#define HUB_CHAR_PORTIND 0x0080 /* D7 */ +- +-struct usb_hub_status { +- __le16 wHubStatus; +- __le16 wHubChange; +-} __attribute__ ((packed)); +- +-/* +- * Hub Status & Hub Change bit masks +- * See USB 2.0 spec Table 11-19 and Table 11-20 +- * Bits 0 and 1 for wHubStatus and wHubChange +- * Bits 2 to 15 are reserved for both +- */ +-#define HUB_STATUS_LOCAL_POWER 0x0001 +-#define HUB_STATUS_OVERCURRENT 0x0002 +-#define HUB_CHANGE_LOCAL_POWER 0x0001 +-#define HUB_CHANGE_OVERCURRENT 0x0002 +- +- +-/* +- * Hub descriptor +- * See USB 2.0 spec Table 11-13 +- */ +- +-#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) +-#define USB_DT_HUB_NONVAR_SIZE 7 +- +-struct usb_hub_descriptor { +- __u8 bDescLength; +- __u8 bDescriptorType; +- __u8 bNbrPorts; +- __le16 wHubCharacteristics; +- __u8 bPwrOn2PwrGood; +- __u8 bHubContrCurrent; +- /* add 1 bit for hub status change; round to bytes */ +- __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; +- __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; +-} __attribute__ ((packed)); +- +- +-/* port indicator status selectors, tables 11-7 and 11-25 */ +-#define HUB_LED_AUTO 0 +-#define HUB_LED_AMBER 1 +-#define HUB_LED_GREEN 2 +-#define HUB_LED_OFF 3 +- +-enum hub_led_mode { +- INDICATOR_AUTO = 0, +- INDICATOR_CYCLE, +- /* software blinks for attention: software, hardware, reserved */ +- INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF, +- INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF, +- INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF +-} __attribute__ ((packed)); +- +-struct usb_device; +- +-/* Transaction Translator Think Times, in bits */ +-#define HUB_TTTT_8_BITS 0x00 +-#define HUB_TTTT_16_BITS 0x20 +-#define HUB_TTTT_24_BITS 0x40 +-#define HUB_TTTT_32_BITS 0x60 +- +-/* +- * As of USB 2.0, full/low speed devices are segregated into trees. +- * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). +- * The other type grows from high speed hubs when they connect to +- * full/low speed devices using "Transaction Translators" (TTs). +- * +- * TTs should only be known to the hub driver, and high speed bus +- * drivers (only EHCI for now). They affect periodic scheduling and +- * sometimes control/bulk error recovery. +- */ +-struct usb_tt { +- struct usb_device *hub; /* upstream highspeed hub */ +- int multi; /* true means one TT per port */ +- unsigned think_time; /* think time in ns */ +- +- /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ +- spinlock_t lock; +- struct list_head clear_list; /* of usb_tt_clear */ +- struct work_struct clear_work; +-}; +- +-struct usb_tt_clear { +- struct list_head clear_list; +- unsigned tt; +- u16 devinfo; +- struct usb_hcd *hcd; +- struct usb_host_endpoint *ep; +-}; +- +-extern int usb_hub_clear_tt_buffer(struct urb *urb); +-extern void usb_ep0_reinit(struct usb_device *); +- +-#endif /* __LINUX_HUB_H */ diff --git a/usb/usb-straighten-out-port-feature-vs.-port-status-usage.patch b/usb/usb-straighten-out-port-feature-vs.-port-status-usage.patch index b0cdd3b0a7aa51..d90dab095201da 100644 --- a/usb/usb-straighten-out-port-feature-vs.-port-status-usage.patch +++ b/usb/usb-straighten-out-port-feature-vs.-port-status-usage.patch @@ -33,7 +33,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c -@@ -3038,7 +3038,7 @@ static void hub_port_connect_change(stru +@@ -3037,7 +3037,7 @@ static void hub_port_connect_change(stru /* maybe switch power back on (e.g. root hub was reset) */ if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 @@ -194,7 +194,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> break; --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c -@@ -3202,7 +3202,7 @@ static int oxu_hub_control(struct usb_hc +@@ -3201,7 +3201,7 @@ static int oxu_hub_control(struct usb_hc * Even if OWNER is set, so the port is owned by the * companion controller, khubd needs to be able to clear * the port-change status bits (especially @@ -203,7 +203,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> */ switch (wValue) { -@@ -3264,11 +3264,11 @@ static int oxu_hub_control(struct usb_hc +@@ -3263,11 +3263,11 @@ static int oxu_hub_control(struct usb_hc /* wPortChange bits */ if (temp & PORT_CSC) @@ -218,7 +218,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* whoever resumes must GetPortStatus to complete it!! */ if (temp & PORT_RESUME) { -@@ -3286,7 +3286,7 @@ static int oxu_hub_control(struct usb_hc +@@ -3285,7 +3285,7 @@ static int oxu_hub_control(struct usb_hc /* resume completed? */ else if (time_after_eq(jiffies, oxu->reset_done[wIndex])) { @@ -227,7 +227,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> oxu->reset_done[wIndex] = 0; /* stop resume signaling */ -@@ -3309,7 +3309,7 @@ static int oxu_hub_control(struct usb_hc +@@ -3308,7 +3308,7 @@ static int oxu_hub_control(struct usb_hc if ((temp & PORT_RESET) && time_after_eq(jiffies, oxu->reset_done[wIndex])) { @@ -236,7 +236,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> oxu->reset_done[wIndex] = 0; /* force reset to complete */ -@@ -3348,20 +3348,20 @@ static int oxu_hub_control(struct usb_hc +@@ -3347,20 +3347,20 @@ static int oxu_hub_control(struct usb_hc */ if (temp & PORT_CONNECT) { diff --git a/usb/usb-support-for-allocating-usb-3.0-streams.patch b/usb/usb-support-for-allocating-usb-3.0-streams.patch index 24ffbd0f1eb7f1..ef97e06605f2f6 100644 --- a/usb/usb-support-for-allocating-usb-3.0-streams.patch +++ b/usb/usb-support-for-allocating-usb-3.0-streams.patch @@ -33,9 +33,9 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- Documentation/usb/bulk-streams.txt | 78 +++++++++++++++++++++++++++++++++++++ drivers/usb/core/hcd.c | 69 ++++++++++++++++++++++++++++++++ - drivers/usb/core/hcd.h | 10 ++++ drivers/usb/host/xhci-pci.c | 2 include/linux/usb.h | 10 ++++ + include/linux/usb/hcd.h | 10 ++++ 5 files changed, 169 insertions(+) --- /dev/null @@ -121,7 +121,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +ensure that drivers that don't support streams will be able to use the endpoint. --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c -@@ -1815,6 +1815,75 @@ void usb_hcd_reset_endpoint(struct usb_d +@@ -1814,6 +1814,75 @@ void usb_hcd_reset_endpoint(struct usb_d } } @@ -197,25 +197,6 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* Protect against drivers that try to unlink URBs after the device * is gone, by waiting until all unlinks for @udev are finished. * Since we don't currently track URBs by device, simply wait until ---- a/drivers/usb/core/hcd.h -+++ b/drivers/usb/core/hcd.h -@@ -250,6 +250,16 @@ struct hc_driver { - int (*alloc_dev)(struct usb_hcd *, struct usb_device *); - /* Called by usb_disconnect to free HC device structures */ - void (*free_dev)(struct usb_hcd *, struct usb_device *); -+ /* Change a group of bulk endpoints to support multiple stream IDs */ -+ int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev, -+ struct usb_host_endpoint **eps, unsigned int num_eps, -+ unsigned int num_streams, gfp_t mem_flags); -+ /* Reverts a group of bulk endpoints back to not using stream IDs. -+ * Can fail if we run out of memory. -+ */ -+ int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev, -+ struct usb_host_endpoint **eps, unsigned int num_eps, -+ gfp_t mem_flags); - - /* Bandwidth computation functions */ - /* Note that add_endpoint() can only be called once per endpoint before --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -132,6 +132,8 @@ static const struct hc_driver xhci_pci_h @@ -246,3 +227,22 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> /* used these for multi-interface device registration */ extern int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv); +--- a/include/linux/usb/hcd.h ++++ b/include/linux/usb/hcd.h +@@ -250,6 +250,16 @@ struct hc_driver { + int (*alloc_dev)(struct usb_hcd *, struct usb_device *); + /* Called by usb_disconnect to free HC device structures */ + void (*free_dev)(struct usb_hcd *, struct usb_device *); ++ /* Change a group of bulk endpoints to support multiple stream IDs */ ++ int (*alloc_streams)(struct usb_hcd *hcd, struct usb_device *udev, ++ struct usb_host_endpoint **eps, unsigned int num_eps, ++ unsigned int num_streams, gfp_t mem_flags); ++ /* Reverts a group of bulk endpoints back to not using stream IDs. ++ * Can fail if we run out of memory. ++ */ ++ int (*free_streams)(struct usb_hcd *hcd, struct usb_device *udev, ++ struct usb_host_endpoint **eps, unsigned int num_eps, ++ gfp_t mem_flags); + + /* Bandwidth computation functions */ + /* Note that add_endpoint() can only be called once per endpoint before diff --git a/usb/usb-usbserial-mos7720-add-support-for-parallel-port-on-moschip-7715.patch b/usb/usb-usbserial-mos7720-add-support-for-parallel-port-on-moschip-7715.patch new file mode 100644 index 00000000000000..e9a1319281b9be --- /dev/null +++ b/usb/usb-usbserial-mos7720-add-support-for-parallel-port-on-moschip-7715.patch @@ -0,0 +1,1078 @@ +From mikedunn@newsguy.com Thu Apr 29 16:00:24 2010 +From: mikedunn@newsguy.com +Date: Thu, 15 Apr 2010 17:01:33 -0400 +Subject: USB: usbserial: mos7720: add support for parallel port on moschip 7715 +To: linux-usb@vger.kernel.org +Cc: linux-parport@lists.infradead.org, Mike Dunn <mikedunn@newsguy.com> +Message-ID: <1271365293-3664-1-git-send-email-mikedunn@newsguy.com> + + +From: Mike Dunn <mikedunn@newsguy.com> + +Add support for the parallel port on the moschip MCS7715 device. The port +registers itself with the parport subsystem as a low-level driver. A separate +entry to the kernel configuration is added beneath that for the mos7720, to +avoid the need to link with the parport subsystem code for users who don't have +or don't want the parallel port. Only compatibility mode is currently supported +(no ECP/EPP). Tested with both moschip devices (7720 and 7715) on UP and SMP +hosts, including regression testing of serial port, concurrent operation of +serial and parallel ports, and various connect / disconnect scenarios. + +Signed-off-by: Mike Dunn <mikedunn@newsguy.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + Documentation/usb/usb-serial.txt | 16 + drivers/usb/serial/Kconfig | 11 + drivers/usb/serial/mos7720.c | 806 ++++++++++++++++++++++++++++++++++----- + 3 files changed, 747 insertions(+), 86 deletions(-) + +--- a/Documentation/usb/usb-serial.txt ++++ b/Documentation/usb/usb-serial.txt +@@ -440,6 +440,22 @@ Winchiphead CH341 Driver + For any questions or problems with this driver, please contact + frank@kingswood-consulting.co.uk. + ++Moschip MCS7720, MCS7715 driver ++ ++ These chips are present in devices sold by various manufacturers, such as Syba ++ and Cables Unlimited. There may be others. The 7720 provides two serial ++ ports, and the 7715 provides one serial and one standard PC parallel port. ++ Support for the 7715's parallel port is enabled by a separate option, which ++ will not appear unless parallel port support is first enabled at the top-level ++ of the Device Drivers config menu. Currently only compatibility mode is ++ supported on the parallel port (no ECP/EPP). ++ ++ TODO: ++ - Implement ECP/EPP modes for the parallel port. ++ - Baud rates higher than 115200 are currently broken. ++ - Devices with a single serial port based on the Moschip MCS7703 may work ++ with this driver with a simple addition to the usb_device_id table. I ++ don't have one of these devices, so I can't say for sure. + + Generic Serial driver + +--- a/drivers/usb/serial/Kconfig ++++ b/drivers/usb/serial/Kconfig +@@ -425,6 +425,17 @@ config USB_SERIAL_MOS7720 + To compile this driver as a module, choose M here: the + module will be called mos7720. + ++if USB_SERIAL_MOS7720 ++config USB_SERIAL_MOS7715_PARPORT ++ bool "Support for parallel port on the Moschip 7715" ++ select PARPORT_NOT_PC ++ depends on PARPORT ++ ---help--- ++ Say Y if you have a Moschip 7715 device and would like to use ++ the parallel port it provides. The port will register with ++ the parport subsystem as a low-level driver. ++endif ++ + config USB_SERIAL_MOS7840 + tristate "USB Moschip 7840/7820 USB Serial Driver" + ---help--- +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -34,12 +34,12 @@ + #include <linux/usb.h> + #include <linux/usb/serial.h> + #include <linux/uaccess.h> +- ++#include <linux/parport.h> + + /* + * Version Information + */ +-#define DRIVER_VERSION "1.0.0.4F" ++#define DRIVER_VERSION "2.0" + #define DRIVER_AUTHOR "Aspire Communications pvt Ltd." + #define DRIVER_DESC "Moschip USB Serial Driver" + +@@ -63,7 +63,7 @@ + #define NUM_URBS 16 /* URB Count */ + #define URB_TRANSFER_BUFFER_SIZE 32 /* URB Size */ + +-/* This structure holds all of the local port information */ ++/* This structure holds all of the local serial port information */ + struct moschip_port { + __u8 shadowLCR; /* last LCR value received */ + __u8 shadowMCR; /* last MCR value received */ +@@ -74,11 +74,6 @@ struct moschip_port { + struct urb *write_urb_pool[NUM_URBS]; + }; + +-/* This structure holds all of the individual serial device information */ +-struct moschip_serial { +- int interrupt_started; +-}; +- + static int debug; + + static struct usb_serial_driver moschip7720_2port_driver; +@@ -94,6 +89,649 @@ static const struct usb_device_id moschi + }; + MODULE_DEVICE_TABLE(usb, moschip_port_id_table); + ++#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT ++ ++/* initial values for parport regs */ ++#define DCR_INIT_VAL 0x0c /* SLCTIN, nINIT */ ++#define ECR_INIT_VAL 0x00 /* SPP mode */ ++ ++struct urbtracker { ++ struct mos7715_parport *mos_parport; ++ struct list_head urblist_entry; ++ struct kref ref_count; ++ struct urb *urb; ++}; ++ ++enum mos7715_pp_modes { ++ SPP = 0<<5, ++ PS2 = 1<<5, /* moschip calls this 'NIBBLE' mode */ ++ PPF = 2<<5, /* moschip calls this 'CB-FIFO mode */ ++}; ++ ++struct mos7715_parport { ++ struct parport *pp; /* back to containing struct */ ++ struct kref ref_count; /* to instance of this struct */ ++ struct list_head deferred_urbs; /* list deferred async urbs */ ++ struct list_head active_urbs; /* list async urbs in flight */ ++ spinlock_t listlock; /* protects list access */ ++ bool msg_pending; /* usb sync call pending */ ++ struct completion syncmsg_compl; /* usb sync call completed */ ++ struct tasklet_struct urb_tasklet; /* for sending deferred urbs */ ++ struct usb_serial *serial; /* back to containing struct */ ++ __u8 shadowECR; /* parallel port regs... */ ++ __u8 shadowDCR; ++ atomic_t shadowDSR; /* updated in int-in callback */ ++}; ++ ++/* lock guards against dereferencing NULL ptr in parport ops callbacks */ ++static DEFINE_SPINLOCK(release_lock); ++ ++enum mos_regs { ++ THR, /* serial port regs */ ++ RHR, ++ IER, ++ FCR, ++ ISR, ++ LCR, ++ MCR, ++ LSR, ++ MSR, ++ SPR, ++ DLL, ++ DLM, ++ DPR, /* parallel port regs */ ++ DSR, ++ DCR, ++ ECR, ++ SP1_REG, /* device control regs */ ++ SP2_REG, /* serial port 2 (7720 only) */ ++ PP_REG, ++ SP_CONTROL_REG, ++}; ++ ++/* ++ * Return the correct value for the Windex field of the setup packet ++ * for a control endpoint message. See the 7715 datasheet. ++ */ ++static inline __u16 get_reg_index(enum mos_regs reg) ++{ ++ static const __u16 mos7715_index_lookup_table[] = { ++ 0x00, /* THR */ ++ 0x00, /* RHR */ ++ 0x01, /* IER */ ++ 0x02, /* FCR */ ++ 0x02, /* ISR */ ++ 0x03, /* LCR */ ++ 0x04, /* MCR */ ++ 0x05, /* LSR */ ++ 0x06, /* MSR */ ++ 0x07, /* SPR */ ++ 0x00, /* DLL */ ++ 0x01, /* DLM */ ++ 0x00, /* DPR */ ++ 0x01, /* DSR */ ++ 0x02, /* DCR */ ++ 0x0a, /* ECR */ ++ 0x01, /* SP1_REG */ ++ 0x02, /* SP2_REG (7720 only) */ ++ 0x04, /* PP_REG (7715 only) */ ++ 0x08, /* SP_CONTROL_REG */ ++ }; ++ return mos7715_index_lookup_table[reg]; ++} ++ ++/* ++ * Return the correct value for the upper byte of the Wvalue field of ++ * the setup packet for a control endpoint message. ++ */ ++static inline __u16 get_reg_value(enum mos_regs reg) ++{ ++ if (reg >= SP1_REG) /* control reg */ ++ return 0x0000; ++ else /* parallel port reg (7715 only) */ ++ return 0x0100; ++} ++ ++/* ++ * Write data byte to the specified device register. The data is embedded in ++ * the value field of the setup packet. ++ */ ++static int write_parport_reg(struct mos7715_parport *mos_parport, ++ enum mos_regs reg, __u8 data) ++{ ++ struct usb_serial *serial = mos_parport->serial; ++ struct usb_device *usbdev = serial->dev; ++ unsigned int pipe = usb_sndctrlpipe(usbdev, 0); ++ __u8 request = (__u8)0x0e; ++ __u8 requesttype = (__u8)0x40; ++ __u16 value = get_reg_value(reg) + data; ++ __u16 index = get_reg_index(reg); ++ __u16 size = 0; ++ int status; ++ status = usb_control_msg(usbdev, pipe, request, requesttype, value, ++ index, NULL, size, MOS_WDR_TIMEOUT); ++ if (status < 0) ++ dev_err(&usbdev->dev, ++ "mos7720: usb_control_msg() failed: %d", status); ++ return status; ++} ++ ++/* ++ * Read data byte from the specified device register. The data returned by the ++ * device is embedded in the value field of the setup packet. ++ */ ++static int read_parport_reg(struct mos7715_parport *mos_parport, ++ enum mos_regs reg, __u8 *data) ++{ ++ struct usb_device *usbdev = mos_parport->serial->dev; ++ unsigned int pipe = usb_rcvctrlpipe(usbdev, 0); ++ __u8 request = (__u8)0x0d; ++ __u8 requesttype = (__u8)0xc0; ++ __u16 value = get_reg_value(reg); ++ __u16 index = get_reg_index(reg); ++ __u16 size = 1; ++ int status = usb_control_msg(usbdev, pipe, request, requesttype, value, ++ index, data, size, MOS_WDR_TIMEOUT); ++ if (status < 0) ++ dev_err(&usbdev->dev, ++ "mos7720: usb_control_msg() failed: %d", status); ++ return status; ++} ++ ++static inline int mos7715_change_mode(struct mos7715_parport *mos_parport, ++ enum mos7715_pp_modes mode) ++{ ++ mos_parport->shadowECR = mode; ++ write_parport_reg(mos_parport, ECR, mos_parport->shadowECR); ++ return 0; ++} ++ ++static void destroy_mos_parport(struct kref *kref) ++{ ++ struct mos7715_parport *mos_parport = ++ container_of(kref, struct mos7715_parport, ref_count); ++ ++ dbg("%s called", __func__); ++ kfree(mos_parport); ++} ++ ++static void destroy_urbtracker(struct kref *kref) ++{ ++ struct urbtracker *urbtrack = ++ container_of(kref, struct urbtracker, ref_count); ++ struct mos7715_parport *mos_parport = urbtrack->mos_parport; ++ dbg("%s called", __func__); ++ usb_free_urb(urbtrack->urb); ++ kfree(urbtrack); ++ kref_put(&mos_parport->ref_count, destroy_mos_parport); ++} ++ ++/* ++ * This runs as a tasklet when sending an urb in a non-blocking parallel ++ * port callback had to be deferred because the disconnect mutex could not be ++ * obtained at the time. ++ */ ++static void send_deferred_urbs(unsigned long _mos_parport) ++{ ++ int ret_val; ++ unsigned long flags; ++ struct mos7715_parport *mos_parport = (void *)_mos_parport; ++ struct urbtracker *urbtrack; ++ struct list_head *cursor, *next; ++ ++ dbg("%s called", __func__); ++ ++ /* if release function ran, game over */ ++ if (unlikely(mos_parport->serial == NULL)) ++ return; ++ ++ /* try again to get the mutex */ ++ if (!mutex_trylock(&mos_parport->serial->disc_mutex)) { ++ dbg("%s: rescheduling tasklet", __func__); ++ tasklet_schedule(&mos_parport->urb_tasklet); ++ return; ++ } ++ ++ /* if device disconnected, game over */ ++ if (unlikely(mos_parport->serial->disconnected)) { ++ mutex_unlock(&mos_parport->serial->disc_mutex); ++ return; ++ } ++ ++ spin_lock_irqsave(&mos_parport->listlock, flags); ++ if (list_empty(&mos_parport->deferred_urbs)) { ++ spin_unlock_irqrestore(&mos_parport->listlock, flags); ++ mutex_unlock(&mos_parport->serial->disc_mutex); ++ dbg("%s: deferred_urbs list empty", __func__); ++ return; ++ } ++ ++ /* move contents of deferred_urbs list to active_urbs list and submit */ ++ list_for_each_safe(cursor, next, &mos_parport->deferred_urbs) ++ list_move_tail(cursor, &mos_parport->active_urbs); ++ list_for_each_entry(urbtrack, &mos_parport->active_urbs, ++ urblist_entry) { ++ ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC); ++ dbg("%s: urb submitted", __func__); ++ if (ret_val) { ++ dev_err(&mos_parport->serial->dev->dev, ++ "usb_submit_urb() failed: %d", ret_val); ++ list_del(&urbtrack->urblist_entry); ++ kref_put(&urbtrack->ref_count, destroy_urbtracker); ++ } ++ } ++ spin_unlock_irqrestore(&mos_parport->listlock, flags); ++ mutex_unlock(&mos_parport->serial->disc_mutex); ++} ++ ++/* callback for parallel port control urbs submitted asynchronously */ ++static void async_complete(struct urb *urb) ++{ ++ struct urbtracker *urbtrack = urb->context; ++ int status = urb->status; ++ dbg("%s called", __func__); ++ if (unlikely(status)) ++ dbg("%s - nonzero urb status received: %d", __func__, status); ++ ++ /* remove the urbtracker from the active_urbs list */ ++ spin_lock(&urbtrack->mos_parport->listlock); ++ list_del(&urbtrack->urblist_entry); ++ spin_unlock(&urbtrack->mos_parport->listlock); ++ kref_put(&urbtrack->ref_count, destroy_urbtracker); ++} ++ ++static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, ++ enum mos_regs reg, __u8 data) ++{ ++ struct urbtracker *urbtrack; ++ int ret_val; ++ unsigned long flags; ++ struct usb_ctrlrequest setup; ++ struct usb_serial *serial = mos_parport->serial; ++ struct usb_device *usbdev = serial->dev; ++ dbg("%s called", __func__); ++ ++ /* create and initialize the control urb and containing urbtracker */ ++ urbtrack = kmalloc(sizeof(struct urbtracker), GFP_ATOMIC); ++ if (urbtrack == NULL) { ++ dev_err(&usbdev->dev, "out of memory"); ++ return -ENOMEM; ++ } ++ kref_get(&mos_parport->ref_count); ++ urbtrack->mos_parport = mos_parport; ++ urbtrack->urb = usb_alloc_urb(0, GFP_ATOMIC); ++ if (urbtrack->urb == NULL) { ++ dev_err(&usbdev->dev, "out of urbs"); ++ kfree(urbtrack); ++ return -ENOMEM; ++ } ++ setup.bRequestType = (__u8)0x40; ++ setup.bRequest = (__u8)0x0e; ++ setup.wValue = get_reg_value(reg); ++ setup.wIndex = get_reg_index(reg); ++ setup.wLength = 0; ++ usb_fill_control_urb(urbtrack->urb, usbdev, ++ usb_sndctrlpipe(usbdev, 0), ++ (unsigned char *)&setup, ++ NULL, 0, async_complete, urbtrack); ++ kref_init(&urbtrack->ref_count); ++ INIT_LIST_HEAD(&urbtrack->urblist_entry); ++ ++ /* ++ * get the disconnect mutex, or add tracker to the deferred_urbs list ++ * and schedule a tasklet to try again later ++ */ ++ if (!mutex_trylock(&serial->disc_mutex)) { ++ spin_lock_irqsave(&mos_parport->listlock, flags); ++ list_add_tail(&urbtrack->urblist_entry, ++ &mos_parport->deferred_urbs); ++ spin_unlock_irqrestore(&mos_parport->listlock, flags); ++ tasklet_schedule(&mos_parport->urb_tasklet); ++ dbg("tasklet scheduled"); ++ return 0; ++ } ++ ++ /* bail if device disconnected */ ++ if (serial->disconnected) { ++ kref_put(&urbtrack->ref_count, destroy_urbtracker); ++ mutex_unlock(&serial->disc_mutex); ++ return -ENODEV; ++ } ++ ++ /* add the tracker to the active_urbs list and submit */ ++ spin_lock_irqsave(&mos_parport->listlock, flags); ++ list_add_tail(&urbtrack->urblist_entry, &mos_parport->active_urbs); ++ spin_unlock_irqrestore(&mos_parport->listlock, flags); ++ ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC); ++ mutex_unlock(&serial->disc_mutex); ++ if (ret_val) { ++ dev_err(&usbdev->dev, ++ "%s: submit_urb() failed: %d", __func__, ret_val); ++ spin_lock_irqsave(&mos_parport->listlock, flags); ++ list_del(&urbtrack->urblist_entry); ++ spin_unlock_irqrestore(&mos_parport->listlock, flags); ++ kref_put(&urbtrack->ref_count, destroy_urbtracker); ++ return ret_val; ++ } ++ return 0; ++} ++ ++/* ++ * This is the the common top part of all parallel port callback operations that ++ * send synchronous messages to the device. This implements convoluted locking ++ * that avoids two scenarios: (1) a port operation is called after usbserial ++ * has called our release function, at which point struct mos7715_parport has ++ * been destroyed, and (2) the device has been disconnected, but usbserial has ++ * not called the release function yet because someone has a serial port open. ++ * The shared release_lock prevents the first, and the mutex and disconnected ++ * flag maintained by usbserial covers the second. We also use the msg_pending ++ * flag to ensure that all synchronous usb messgage calls have completed before ++ * our release function can return. ++ */ ++static int parport_prologue(struct parport *pp) ++{ ++ struct mos7715_parport *mos_parport; ++ ++ spin_lock(&release_lock); ++ mos_parport = pp->private_data; ++ if (unlikely(mos_parport == NULL)) { ++ /* release fn called, port struct destroyed */ ++ spin_unlock(&release_lock); ++ return -1; ++ } ++ mos_parport->msg_pending = true; /* synch usb call pending */ ++ INIT_COMPLETION(mos_parport->syncmsg_compl); ++ spin_unlock(&release_lock); ++ ++ mutex_lock(&mos_parport->serial->disc_mutex); ++ if (mos_parport->serial->disconnected) { ++ /* device disconnected */ ++ mutex_unlock(&mos_parport->serial->disc_mutex); ++ mos_parport->msg_pending = false; ++ complete(&mos_parport->syncmsg_compl); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++/* ++ * This is the the common bottom part of all parallel port functions that send ++ * synchronous messages to the device. ++ */ ++static inline void parport_epilogue(struct parport *pp) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ mutex_unlock(&mos_parport->serial->disc_mutex); ++ mos_parport->msg_pending = false; ++ complete(&mos_parport->syncmsg_compl); ++} ++ ++static void parport_mos7715_write_data(struct parport *pp, unsigned char d) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ dbg("%s called: %2.2x", __func__, d); ++ if (parport_prologue(pp) < 0) ++ return; ++ mos7715_change_mode(mos_parport, SPP); ++ write_parport_reg(mos_parport, DPR, (__u8)d); ++ parport_epilogue(pp); ++} ++ ++static unsigned char parport_mos7715_read_data(struct parport *pp) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ unsigned char d; ++ dbg("%s called", __func__); ++ if (parport_prologue(pp) < 0) ++ return 0; ++ read_parport_reg(mos_parport, DPR, &d); ++ parport_epilogue(pp); ++ return d; ++} ++ ++static void parport_mos7715_write_control(struct parport *pp, unsigned char d) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ __u8 data; ++ dbg("%s called: %2.2x", __func__, d); ++ if (parport_prologue(pp) < 0) ++ return; ++ data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0); ++ write_parport_reg(mos_parport, DCR, data); ++ mos_parport->shadowDCR = data; ++ parport_epilogue(pp); ++} ++ ++static unsigned char parport_mos7715_read_control(struct parport *pp) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ __u8 dcr; ++ dbg("%s called", __func__); ++ spin_lock(&release_lock); ++ mos_parport = pp->private_data; ++ if (unlikely(mos_parport == NULL)) { ++ spin_unlock(&release_lock); ++ return 0; ++ } ++ dcr = mos_parport->shadowDCR & 0x0f; ++ spin_unlock(&release_lock); ++ return dcr; ++} ++ ++static unsigned char parport_mos7715_frob_control(struct parport *pp, ++ unsigned char mask, ++ unsigned char val) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ __u8 dcr; ++ dbg("%s called", __func__); ++ mask &= 0x0f; ++ val &= 0x0f; ++ if (parport_prologue(pp) < 0) ++ return 0; ++ mos_parport->shadowDCR = (mos_parport->shadowDCR & (~mask)) ^ val; ++ write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ dcr = mos_parport->shadowDCR & 0x0f; ++ parport_epilogue(pp); ++ return dcr; ++} ++ ++static unsigned char parport_mos7715_read_status(struct parport *pp) ++{ ++ unsigned char status; ++ struct mos7715_parport *mos_parport = pp->private_data; ++ dbg("%s called", __func__); ++ spin_lock(&release_lock); ++ mos_parport = pp->private_data; ++ if (unlikely(mos_parport == NULL)) { /* release called */ ++ spin_unlock(&release_lock); ++ return 0; ++ } ++ status = atomic_read(&mos_parport->shadowDSR) & 0xf8; ++ spin_unlock(&release_lock); ++ return status; ++} ++ ++static void parport_mos7715_enable_irq(struct parport *pp) ++{ ++ dbg("%s called", __func__); ++} ++static void parport_mos7715_disable_irq(struct parport *pp) ++{ ++ dbg("%s called", __func__); ++} ++ ++static void parport_mos7715_data_forward(struct parport *pp) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ dbg("%s called", __func__); ++ if (parport_prologue(pp) < 0) ++ return; ++ mos7715_change_mode(mos_parport, PS2); ++ mos_parport->shadowDCR &= ~0x20; ++ write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ parport_epilogue(pp); ++} ++ ++static void parport_mos7715_data_reverse(struct parport *pp) ++{ ++ struct mos7715_parport *mos_parport = pp->private_data; ++ dbg("%s called", __func__); ++ if (parport_prologue(pp) < 0) ++ return; ++ mos7715_change_mode(mos_parport, PS2); ++ mos_parport->shadowDCR |= 0x20; ++ write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ parport_epilogue(pp); ++} ++ ++static void parport_mos7715_init_state(struct pardevice *dev, ++ struct parport_state *s) ++{ ++ dbg("%s called", __func__); ++ s->u.pc.ctr = DCR_INIT_VAL; ++ s->u.pc.ecr = ECR_INIT_VAL; ++} ++ ++/* N.B. Parport core code requires that this function not block */ ++static void parport_mos7715_save_state(struct parport *pp, ++ struct parport_state *s) ++{ ++ struct mos7715_parport *mos_parport; ++ dbg("%s called", __func__); ++ spin_lock(&release_lock); ++ mos_parport = pp->private_data; ++ if (unlikely(mos_parport == NULL)) { /* release called */ ++ spin_unlock(&release_lock); ++ return; ++ } ++ s->u.pc.ctr = mos_parport->shadowDCR; ++ s->u.pc.ecr = mos_parport->shadowECR; ++ spin_unlock(&release_lock); ++} ++ ++/* N.B. Parport core code requires that this function not block */ ++static void parport_mos7715_restore_state(struct parport *pp, ++ struct parport_state *s) ++{ ++ struct mos7715_parport *mos_parport; ++ dbg("%s called", __func__); ++ spin_lock(&release_lock); ++ mos_parport = pp->private_data; ++ if (unlikely(mos_parport == NULL)) { /* release called */ ++ spin_unlock(&release_lock); ++ return; ++ } ++ write_parport_reg_nonblock(mos_parport, DCR, mos_parport->shadowDCR); ++ write_parport_reg_nonblock(mos_parport, ECR, mos_parport->shadowECR); ++ spin_unlock(&release_lock); ++} ++ ++static size_t parport_mos7715_write_compat(struct parport *pp, ++ const void *buffer, ++ size_t len, int flags) ++{ ++ int retval; ++ struct mos7715_parport *mos_parport = pp->private_data; ++ int actual_len; ++ dbg("%s called: %u chars", __func__, (unsigned int)len); ++ if (parport_prologue(pp) < 0) ++ return 0; ++ mos7715_change_mode(mos_parport, PPF); ++ retval = usb_bulk_msg(mos_parport->serial->dev, ++ usb_sndbulkpipe(mos_parport->serial->dev, 2), ++ (void *)buffer, len, &actual_len, ++ MOS_WDR_TIMEOUT); ++ parport_epilogue(pp); ++ if (retval) { ++ dev_err(&mos_parport->serial->dev->dev, ++ "mos7720: usb_bulk_msg() failed: %d", retval); ++ return 0; ++ } ++ return actual_len; ++} ++ ++static struct parport_operations parport_mos7715_ops = { ++ .owner = THIS_MODULE, ++ .write_data = parport_mos7715_write_data, ++ .read_data = parport_mos7715_read_data, ++ ++ .write_control = parport_mos7715_write_control, ++ .read_control = parport_mos7715_read_control, ++ .frob_control = parport_mos7715_frob_control, ++ ++ .read_status = parport_mos7715_read_status, ++ ++ .enable_irq = parport_mos7715_enable_irq, ++ .disable_irq = parport_mos7715_disable_irq, ++ ++ .data_forward = parport_mos7715_data_forward, ++ .data_reverse = parport_mos7715_data_reverse, ++ ++ .init_state = parport_mos7715_init_state, ++ .save_state = parport_mos7715_save_state, ++ .restore_state = parport_mos7715_restore_state, ++ ++ .compat_write_data = parport_mos7715_write_compat, ++ ++ .nibble_read_data = parport_ieee1284_read_nibble, ++ .byte_read_data = parport_ieee1284_read_byte, ++}; ++ ++/* ++ * Allocate and initialize parallel port control struct, initialize ++ * the parallel port hardware device, and register with the parport subsystem. ++ */ ++static int mos7715_parport_init(struct usb_serial *serial) ++{ ++ struct mos7715_parport *mos_parport; ++ ++ /* allocate and initialize parallel port control struct */ ++ mos_parport = kzalloc(sizeof(struct mos7715_parport), GFP_KERNEL); ++ if (mos_parport == NULL) { ++ dbg("mos7715_parport_init: kzalloc failed"); ++ return -ENOMEM; ++ } ++ mos_parport->msg_pending = false; ++ kref_init(&mos_parport->ref_count); ++ spin_lock_init(&mos_parport->listlock); ++ INIT_LIST_HEAD(&mos_parport->active_urbs); ++ INIT_LIST_HEAD(&mos_parport->deferred_urbs); ++ usb_set_serial_data(serial, mos_parport); /* hijack private pointer */ ++ mos_parport->serial = serial; ++ tasklet_init(&mos_parport->urb_tasklet, send_deferred_urbs, ++ (unsigned long) mos_parport); ++ init_completion(&mos_parport->syncmsg_compl); ++ ++ /* cycle parallel port reset bit */ ++ write_parport_reg(mos_parport, PP_REG, (__u8)0x80); ++ write_parport_reg(mos_parport, PP_REG, (__u8)0x00); ++ ++ /* initialize device registers */ ++ mos_parport->shadowDCR = DCR_INIT_VAL; ++ write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ mos_parport->shadowECR = ECR_INIT_VAL; ++ write_parport_reg(mos_parport, ECR, mos_parport->shadowECR); ++ ++ /* register with parport core */ ++ mos_parport->pp = parport_register_port(0, PARPORT_IRQ_NONE, ++ PARPORT_DMA_NONE, ++ &parport_mos7715_ops); ++ if (mos_parport->pp == NULL) { ++ dev_err(&serial->interface->dev, ++ "Could not register parport\n"); ++ kref_put(&mos_parport->ref_count, destroy_mos_parport); ++ return -EIO; ++ } ++ mos_parport->pp->private_data = mos_parport; ++ mos_parport->pp->modes = PARPORT_MODE_COMPAT | PARPORT_MODE_PCSPP; ++ mos_parport->pp->dev = &serial->interface->dev; ++ parport_announce_port(mos_parport->pp); ++ ++ return 0; ++} ++#endif /* CONFIG_USB_SERIAL_MOS7715_PARPORT */ + + /* + * mos7720_interrupt_callback +@@ -109,8 +747,6 @@ static void mos7720_interrupt_callback(s + __u8 sp1; + __u8 sp2; + +- dbg(" : Entering"); +- + switch (status) { + case 0: + /* success */ +@@ -118,6 +754,7 @@ static void mos7720_interrupt_callback(s + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: ++ case -ENODEV: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + status); +@@ -161,7 +798,7 @@ static void mos7720_interrupt_callback(s + dbg("Serial Port 1: Receiver time out"); + break; + case SERIAL_IIR_MS: +- dbg("Serial Port 1: Modem status change"); ++ /* dbg("Serial Port 1: Modem status change"); */ + break; + } + +@@ -174,7 +811,7 @@ static void mos7720_interrupt_callback(s + dbg("Serial Port 2: Receiver time out"); + break; + case SERIAL_IIR_MS: +- dbg("Serial Port 2: Modem status change"); ++ /* dbg("Serial Port 2: Modem status change"); */ + break; + } + } +@@ -208,6 +845,7 @@ static void mos7715_interrupt_callback(s + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: ++ case -ENODEV: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + status); +@@ -243,11 +881,21 @@ static void mos7715_interrupt_callback(s + dbg("Serial Port: Receiver time out"); + break; + case SERIAL_IIR_MS: +- dbg("Serial Port: Modem status change"); ++ /* dbg("Serial Port: Modem status change"); */ + break; + } + } + ++#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT ++ { /* update local copy of DSR reg */ ++ struct usb_serial_port *port = urb->context; ++ struct mos7715_parport *mos_parport = port->serial->private; ++ if (unlikely(mos_parport == NULL)) ++ return; ++ atomic_set(&mos_parport->shadowDSR, data[2]); ++ } ++#endif ++ + exit: + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) +@@ -267,7 +915,6 @@ static void mos7720_bulk_in_callback(str + int retval; + unsigned char *data ; + struct usb_serial_port *port; +- struct moschip_port *mos7720_port; + struct tty_struct *tty; + int status = urb->status; + +@@ -276,13 +923,7 @@ static void mos7720_bulk_in_callback(str + return; + } + +- mos7720_port = urb->context; +- if (!mos7720_port) { +- dbg("NULL mos7720_port pointer"); +- return ; +- } +- +- port = mos7720_port->port; ++ port = urb->context; + + dbg("Entering...%s", __func__); + +@@ -332,8 +973,6 @@ static void mos7720_bulk_out_data_callba + return ; + } + +- dbg("Entering ........."); +- + tty = tty_port_tty_get(&mos7720_port->port->port); + + if (tty && mos7720_port->open) +@@ -424,7 +1063,6 @@ static int mos7720_open(struct tty_struc + struct usb_serial *serial; + struct usb_serial_port *port0; + struct urb *urb; +- struct moschip_serial *mos7720_serial; + struct moschip_port *mos7720_port; + int response; + int port_number; +@@ -440,11 +1078,6 @@ static int mos7720_open(struct tty_struc + + port0 = serial->port[0]; + +- mos7720_serial = usb_get_serial_data(serial); +- +- if (mos7720_serial == NULL || port0 == NULL) +- return -ENODEV; +- + usb_clear_halt(serial->dev, port->write_urb->pipe); + usb_clear_halt(serial->dev, port->read_urb->pipe); + +@@ -549,43 +1182,6 @@ static int mos7720_open(struct tty_struc + data = 0x0c; + send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); + +- /* see if we've set up our endpoint info yet * +- * (can't set it up in mos7720_startup as the * +- * structures were not set up at that time.) */ +- if (!mos7720_serial->interrupt_started) { +- dbg("Interrupt buffer NULL !!!"); +- +- /* not set up yet, so do it now */ +- mos7720_serial->interrupt_started = 1; +- +- dbg("To Submit URB !!!"); +- +- /* set up our interrupt urb */ +- usb_fill_int_urb(port0->interrupt_in_urb, serial->dev, +- usb_rcvintpipe(serial->dev, +- port->interrupt_in_endpointAddress), +- port0->interrupt_in_buffer, +- port0->interrupt_in_urb->transfer_buffer_length, +- mos7720_interrupt_callback, mos7720_port, +- port0->interrupt_in_urb->interval); +- +- /* start interrupt read for this mos7720 this interrupt * +- * will continue as long as the mos7720 is connected */ +- dbg("Submit URB over !!!"); +- response = usb_submit_urb(port0->interrupt_in_urb, GFP_KERNEL); +- if (response) +- dev_err(&port->dev, +- "%s - Error %d submitting control urb\n", +- __func__, response); +- } +- +- /* set up our bulk in urb */ +- usb_fill_bulk_urb(port->read_urb, serial->dev, +- usb_rcvbulkpipe(serial->dev, +- port->bulk_in_endpointAddress), +- port->bulk_in_buffer, +- port->read_urb->transfer_buffer_length, +- mos7720_bulk_in_callback, mos7720_port); + response = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (response) + dev_err(&port->dev, "%s - Error %d submitting read urb\n", +@@ -897,6 +1493,7 @@ static void mos7720_unthrottle(struct tt + } + } + ++/* FIXME: this function does not work */ + static int set_higher_rates(struct moschip_port *mos7720_port, + unsigned int baud) + { +@@ -939,6 +1536,7 @@ static int set_higher_rates(struct mosch + * Set for higher rates * + ***********************************************/ + ++ /* writing baud rate verbatum into uart clock field clearly not right */ + data = baud * 0x10; + send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); + +@@ -1308,7 +1906,7 @@ static void mos7720_set_termios(struct t + return; + } + +- dbg("setting termios - ASPIRE"); ++ dbg("%s\n", "setting termios - ASPIRE"); + + cflag = tty->termios->c_cflag; + +@@ -1326,7 +1924,7 @@ static void mos7720_set_termios(struct t + change_port_settings(tty, mos7720_port, old_termios); + + if (!port->read_urb) { +- dbg("URB KILLED !!!!!"); ++ dbg("%s", "URB KILLED !!!!!"); + return; + } + +@@ -1590,12 +2188,12 @@ static int mos7720_ioctl(struct tty_stru + + static int mos7720_startup(struct usb_serial *serial) + { +- struct moschip_serial *mos7720_serial; + struct moschip_port *mos7720_port; + struct usb_device *dev; + int i; + char data; + u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); ++ int ret_val; + + dbg("%s: Entering ..........", __func__); + +@@ -1606,15 +2204,6 @@ static int mos7720_startup(struct usb_se + + dev = serial->dev; + +- /* create our private serial structure */ +- mos7720_serial = kzalloc(sizeof(struct moschip_serial), GFP_KERNEL); +- if (mos7720_serial == NULL) { +- dev_err(&dev->dev, "%s - Out of memory\n", __func__); +- return -ENOMEM; +- } +- +- usb_set_serial_data(serial, mos7720_serial); +- + /* + * The 7715 uses the first bulk in/out endpoint pair for the parallel + * port, and the second for the serial port. Because the usbserial core +@@ -1638,16 +2227,12 @@ static int mos7720_startup(struct usb_se + serial->port[1]->interrupt_in_buffer = NULL; + } + +- /* we set up the pointers to the endpoints in the mos7720_open * +- * function, as the structures aren't created yet. */ + +- /* set up port private structures */ ++ /* set up serial port private structures */ + for (i = 0; i < serial->num_ports; ++i) { + mos7720_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); + if (mos7720_port == NULL) { + dev_err(&dev->dev, "%s - Out of memory\n", __func__); +- usb_set_serial_data(serial, NULL); +- kfree(mos7720_serial); + return -ENOMEM; + } + +@@ -1669,6 +2254,20 @@ static int mos7720_startup(struct usb_se + usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); + ++ /* start the interrupt urb */ ++ ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); ++ if (ret_val) ++ dev_err(&dev->dev, ++ "%s - Error %d submitting control urb\n", ++ __func__, ret_val); ++ ++#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT ++ if (product == MOSCHIP_DEVICE_ID_7715) { ++ ret_val = mos7715_parport_init(serial); ++ if (ret_val < 0) ++ return ret_val; ++ } ++#endif + /* LSR For Port 1 */ + send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data); + dbg("LSR:%x", data); +@@ -1684,12 +2283,47 @@ static void mos7720_release(struct usb_s + { + int i; + ++#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT ++ /* close the parallel port */ ++ ++ if (le16_to_cpu(serial->dev->descriptor.idProduct) ++ == MOSCHIP_DEVICE_ID_7715) { ++ struct urbtracker *urbtrack; ++ unsigned long flags; ++ struct mos7715_parport *mos_parport = ++ usb_get_serial_data(serial); ++ ++ /* prevent NULL ptr dereference in port callbacks */ ++ spin_lock(&release_lock); ++ mos_parport->pp->private_data = NULL; ++ spin_unlock(&release_lock); ++ ++ /* wait for synchronous usb calls to return */ ++ if (mos_parport->msg_pending) ++ wait_for_completion_timeout(&mos_parport->syncmsg_compl, ++ MOS_WDR_TIMEOUT); ++ ++ parport_remove_port(mos_parport->pp); ++ usb_set_serial_data(serial, NULL); ++ mos_parport->serial = NULL; ++ ++ /* if tasklet currently scheduled, wait for it to complete */ ++ tasklet_kill(&mos_parport->urb_tasklet); ++ ++ /* unlink any urbs sent by the tasklet */ ++ spin_lock_irqsave(&mos_parport->listlock, flags); ++ list_for_each_entry(urbtrack, ++ &mos_parport->active_urbs, ++ urblist_entry) ++ usb_unlink_urb(urbtrack->urb); ++ spin_unlock_irqrestore(&mos_parport->listlock, flags); ++ ++ kref_put(&mos_parport->ref_count, destroy_mos_parport); ++ } ++#endif + /* free private structure allocated for serial port */ + for (i = 0; i < serial->num_ports; ++i) + kfree(usb_get_serial_port_data(serial->port[i])); +- +- /* free private structure allocated for serial device */ +- kfree(usb_get_serial_data(serial)); + } + + static struct usb_driver usb_driver = { diff --git a/usb/usb-usbserial-mos7720-cleanup-consolidation-replace-send_mos_cmd-with-read-write-_mos_reg.patch b/usb/usb-usbserial-mos7720-cleanup-consolidation-replace-send_mos_cmd-with-read-write-_mos_reg.patch new file mode 100644 index 00000000000000..6060d5457c7a57 --- /dev/null +++ b/usb/usb-usbserial-mos7720-cleanup-consolidation-replace-send_mos_cmd-with-read-write-_mos_reg.patch @@ -0,0 +1,747 @@ +From mikedunn@newsguy.com Thu Apr 29 16:01:05 2010 +From: mikedunn@newsguy.com +Date: Thu, 15 Apr 2010 17:02:09 -0400 +Subject: USB: usbserial: mos7720: cleanup, consolidation, replace send_mos_cmd with {read,write}_mos_reg +To: linux-usb@vger.kernel.org +Cc: linux-parport@lists.infradead.org, Mike Dunn <mikedunn@newsguy.com> +Message-ID: <1271365329-3696-1-git-send-email-mikedunn@newsguy.com> + + +From: Mike Dunn <mikedunn@newsguy.com> + +No functionality added or bugs fixed, just improved code consistency and +(hopefully) readability by replacing send_mos_cmd with the register read & write +functions that were used for parallel port registers. Also shortens overall +file length. + +Thoroughly tested, with emphasis on regression testing the serial port. + +Signed-off-by: Mike Dunn <mikedunn@newsguy.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/mos7720.c | 392 +++++++++++++------------------------------ + 1 file changed, 124 insertions(+), 268 deletions(-) + +--- a/drivers/usb/serial/mos7720.c ++++ b/drivers/usb/serial/mos7720.c +@@ -39,16 +39,13 @@ + /* + * Version Information + */ +-#define DRIVER_VERSION "2.0" ++#define DRIVER_VERSION "2.1" + #define DRIVER_AUTHOR "Aspire Communications pvt Ltd." + #define DRIVER_DESC "Moschip USB Serial Driver" + + /* default urb timeout */ + #define MOS_WDR_TIMEOUT (HZ * 5) + +-#define MOS_PORT1 0x0200 +-#define MOS_PORT2 0x0300 +-#define MOS_VENREG 0x0000 + #define MOS_MAX_PORT 0x02 + #define MOS_WRITE 0x0E + #define MOS_READ 0x0D +@@ -126,6 +123,10 @@ struct mos7715_parport { + /* lock guards against dereferencing NULL ptr in parport ops callbacks */ + static DEFINE_SPINLOCK(release_lock); + ++#endif /* CONFIG_USB_SERIAL_MOS7715_PARPORT */ ++ ++static const unsigned int dummy; /* for clarity in register access fns */ ++ + enum mos_regs { + THR, /* serial port regs */ + RHR, +@@ -184,32 +185,35 @@ static inline __u16 get_reg_index(enum m + * Return the correct value for the upper byte of the Wvalue field of + * the setup packet for a control endpoint message. + */ +-static inline __u16 get_reg_value(enum mos_regs reg) ++static inline __u16 get_reg_value(enum mos_regs reg, ++ unsigned int serial_portnum) + { + if (reg >= SP1_REG) /* control reg */ + return 0x0000; +- else /* parallel port reg (7715 only) */ ++ ++ else if (reg >= DPR) /* parallel port reg (7715 only) */ + return 0x0100; ++ ++ else /* serial port reg */ ++ return (serial_portnum + 2) << 8; + } + + /* + * Write data byte to the specified device register. The data is embedded in +- * the value field of the setup packet. ++ * the value field of the setup packet. serial_portnum is ignored for registers ++ * not specific to a particular serial port. + */ +-static int write_parport_reg(struct mos7715_parport *mos_parport, +- enum mos_regs reg, __u8 data) ++static int write_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, ++ enum mos_regs reg, __u8 data) + { +- struct usb_serial *serial = mos_parport->serial; + struct usb_device *usbdev = serial->dev; + unsigned int pipe = usb_sndctrlpipe(usbdev, 0); + __u8 request = (__u8)0x0e; + __u8 requesttype = (__u8)0x40; +- __u16 value = get_reg_value(reg) + data; + __u16 index = get_reg_index(reg); +- __u16 size = 0; +- int status; +- status = usb_control_msg(usbdev, pipe, request, requesttype, value, +- index, NULL, size, MOS_WDR_TIMEOUT); ++ __u16 value = get_reg_value(reg, serial_portnum) + data; ++ int status = usb_control_msg(usbdev, pipe, request, requesttype, value, ++ index, NULL, 0, MOS_WDR_TIMEOUT); + if (status < 0) + dev_err(&usbdev->dev, + "mos7720: usb_control_msg() failed: %d", status); +@@ -218,31 +222,33 @@ static int write_parport_reg(struct mos7 + + /* + * Read data byte from the specified device register. The data returned by the +- * device is embedded in the value field of the setup packet. ++ * device is embedded in the value field of the setup packet. serial_portnum is ++ * ignored for registers that are not specific to a particular serial port. + */ +-static int read_parport_reg(struct mos7715_parport *mos_parport, +- enum mos_regs reg, __u8 *data) ++static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, ++ enum mos_regs reg, __u8 *data) + { +- struct usb_device *usbdev = mos_parport->serial->dev; ++ struct usb_device *usbdev = serial->dev; + unsigned int pipe = usb_rcvctrlpipe(usbdev, 0); + __u8 request = (__u8)0x0d; + __u8 requesttype = (__u8)0xc0; +- __u16 value = get_reg_value(reg); + __u16 index = get_reg_index(reg); +- __u16 size = 1; ++ __u16 value = get_reg_value(reg, serial_portnum); + int status = usb_control_msg(usbdev, pipe, request, requesttype, value, +- index, data, size, MOS_WDR_TIMEOUT); ++ index, data, 1, MOS_WDR_TIMEOUT); + if (status < 0) + dev_err(&usbdev->dev, + "mos7720: usb_control_msg() failed: %d", status); + return status; + } + ++#ifdef CONFIG_USB_SERIAL_MOS7715_PARPORT ++ + static inline int mos7715_change_mode(struct mos7715_parport *mos_parport, + enum mos7715_pp_modes mode) + { + mos_parport->shadowECR = mode; +- write_parport_reg(mos_parport, ECR, mos_parport->shadowECR); ++ write_mos_reg(mos_parport->serial, dummy, ECR, mos_parport->shadowECR); + return 0; + } + +@@ -367,7 +373,7 @@ static int write_parport_reg_nonblock(st + } + setup.bRequestType = (__u8)0x40; + setup.bRequest = (__u8)0x0e; +- setup.wValue = get_reg_value(reg); ++ setup.wValue = get_reg_value(reg, dummy); + setup.wIndex = get_reg_index(reg); + setup.wLength = 0; + usb_fill_control_urb(urbtrack->urb, usbdev, +@@ -474,7 +480,7 @@ static void parport_mos7715_write_data(s + if (parport_prologue(pp) < 0) + return; + mos7715_change_mode(mos_parport, SPP); +- write_parport_reg(mos_parport, DPR, (__u8)d); ++ write_mos_reg(mos_parport->serial, dummy, DPR, (__u8)d); + parport_epilogue(pp); + } + +@@ -485,7 +491,7 @@ static unsigned char parport_mos7715_rea + dbg("%s called", __func__); + if (parport_prologue(pp) < 0) + return 0; +- read_parport_reg(mos_parport, DPR, &d); ++ read_mos_reg(mos_parport->serial, dummy, DPR, &d); + parport_epilogue(pp); + return d; + } +@@ -498,7 +504,7 @@ static void parport_mos7715_write_contro + if (parport_prologue(pp) < 0) + return; + data = ((__u8)d & 0x0f) | (mos_parport->shadowDCR & 0xf0); +- write_parport_reg(mos_parport, DCR, data); ++ write_mos_reg(mos_parport->serial, dummy, DCR, data); + mos_parport->shadowDCR = data; + parport_epilogue(pp); + } +@@ -531,7 +537,7 @@ static unsigned char parport_mos7715_fro + if (parport_prologue(pp) < 0) + return 0; + mos_parport->shadowDCR = (mos_parport->shadowDCR & (~mask)) ^ val; +- write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + dcr = mos_parport->shadowDCR & 0x0f; + parport_epilogue(pp); + return dcr; +@@ -570,7 +576,7 @@ static void parport_mos7715_data_forward + return; + mos7715_change_mode(mos_parport, PS2); + mos_parport->shadowDCR &= ~0x20; +- write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + parport_epilogue(pp); + } + +@@ -582,7 +588,7 @@ static void parport_mos7715_data_reverse + return; + mos7715_change_mode(mos_parport, PS2); + mos_parport->shadowDCR |= 0x20; +- write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + parport_epilogue(pp); + } + +@@ -705,14 +711,14 @@ static int mos7715_parport_init(struct u + init_completion(&mos_parport->syncmsg_compl); + + /* cycle parallel port reset bit */ +- write_parport_reg(mos_parport, PP_REG, (__u8)0x80); +- write_parport_reg(mos_parport, PP_REG, (__u8)0x00); ++ write_mos_reg(mos_parport->serial, dummy, PP_REG, (__u8)0x80); ++ write_mos_reg(mos_parport->serial, dummy, PP_REG, (__u8)0x00); + + /* initialize device registers */ + mos_parport->shadowDCR = DCR_INIT_VAL; +- write_parport_reg(mos_parport, DCR, mos_parport->shadowDCR); ++ write_mos_reg(mos_parport->serial, dummy, DCR, mos_parport->shadowDCR); + mos_parport->shadowECR = ECR_INIT_VAL; +- write_parport_reg(mos_parport, ECR, mos_parport->shadowECR); ++ write_mos_reg(mos_parport->serial, dummy, ECR, mos_parport->shadowECR); + + /* register with parport core */ + mos_parport->pp = parport_register_port(0, PARPORT_IRQ_NONE, +@@ -754,7 +760,6 @@ static void mos7720_interrupt_callback(s + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: +- case -ENODEV: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + status); +@@ -981,56 +986,6 @@ static void mos7720_bulk_out_data_callba + } + + /* +- * send_mos_cmd +- * this function will be used for sending command to device +- */ +-static int send_mos_cmd(struct usb_serial *serial, __u8 request, __u16 value, +- __u16 index, u8 *data) +-{ +- int status; +- u8 *buf; +- u16 product = le16_to_cpu(serial->dev->descriptor.idProduct); +- +- if (value < MOS_MAX_PORT) { +- if (product == MOSCHIP_DEVICE_ID_7715) +- value = 0x0200; /* identifies the 7715's serial port */ +- else +- value = value*0x100+0x200; +- } else { +- value = 0x0000; +- if ((product == MOSCHIP_DEVICE_ID_7715) && +- (index != 0x08)) { +- dbg("serial->product== MOSCHIP_DEVICE_ID_7715"); +- /* index = 0x01 ; */ +- } +- } +- +- if (request == MOS_WRITE) { +- value = value + *data; +- status = usb_control_msg(serial->dev, +- usb_sndctrlpipe(serial->dev, 0), MOS_WRITE, +- 0x40, value, index, NULL, 0, MOS_WDR_TIMEOUT); +- } else { +- buf = kmalloc(1, GFP_KERNEL); +- if (!buf) { +- status = -ENOMEM; +- goto out; +- } +- status = usb_control_msg(serial->dev, +- usb_rcvctrlpipe(serial->dev, 0), MOS_READ, +- 0xc0, value, index, buf, 1, MOS_WDR_TIMEOUT); +- *data = *buf; +- kfree(buf); +- } +-out: +- if (status < 0) +- dbg("Command Write failed Value %x index %x", value, index); +- +- return status; +-} +- +- +-/* + * mos77xx_probe + * this function installs the appropriate read interrupt endpoint callback + * depending on whether the device is a 7720 or 7715, thus avoiding costly +@@ -1066,7 +1021,7 @@ static int mos7720_open(struct tty_struc + struct moschip_port *mos7720_port; + int response; + int port_number; +- char data; ++ __u8 data; + int allocated_urbs = 0; + int j; + +@@ -1122,65 +1077,35 @@ static int mos7720_open(struct tty_struc + * 0x08 : SP1/2 Control Reg + */ + port_number = port->number - port->serial->minor; +- send_mos_cmd(port->serial, MOS_READ, port_number, UART_LSR, &data); ++ read_mos_reg(serial, port_number, LSR, &data); ++ + dbg("SS::%p LSR:%x", mos7720_port, data); + + dbg("Check:Sending Command .........."); + +- data = 0x02; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x01, &data); +- data = 0x02; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x02, &data); +- +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); +- +- data = 0xCF; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); +- data = 0x03; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); +- data = 0x0b; +- mos7720_port->shadowMCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); +- data = 0x0b; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); +- +- data = 0x00; +- send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); +- +-/* data = 0x00; +- send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, port_number + 1, &data); +- data = 0x03; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); +- data = 0x00; +- send_mos_cmd(port->serial, MOS_WRITE, MOS_MAX_PORT, +- port_number + 1, &data); +-*/ +- data = 0x00; +- send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); ++ write_mos_reg(serial, dummy, SP1_REG, 0x02); ++ write_mos_reg(serial, dummy, SP2_REG, 0x02); + +- data = data | (port->number - port->serial->minor + 1); +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); ++ write_mos_reg(serial, port_number, IER, 0x00); ++ write_mos_reg(serial, port_number, FCR, 0x00); + +- data = 0x83; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); +- data = 0x0c; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); +- data = 0x03; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); +- data = 0x0c; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); +- data = 0x0c; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); ++ write_mos_reg(serial, port_number, FCR, 0xcf); ++ mos7720_port->shadowLCR = 0x03; ++ write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); ++ mos7720_port->shadowMCR = 0x0b; ++ write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); ++ ++ write_mos_reg(serial, port_number, SP_CONTROL_REG, 0x00); ++ read_mos_reg(serial, dummy, SP_CONTROL_REG, &data); ++ data = data | (port->number - port->serial->minor + 1); ++ write_mos_reg(serial, dummy, SP_CONTROL_REG, data); ++ mos7720_port->shadowLCR = 0x83; ++ write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); ++ write_mos_reg(serial, port_number, THR, 0x0c); ++ write_mos_reg(serial, port_number, IER, 0x00); ++ mos7720_port->shadowLCR = 0x03; ++ write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); ++ write_mos_reg(serial, port_number, IER, 0x0c); + + response = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (response) +@@ -1236,7 +1161,6 @@ static void mos7720_close(struct usb_ser + { + struct usb_serial *serial; + struct moschip_port *mos7720_port; +- char data; + int j; + + dbg("mos7720_close:entering..."); +@@ -1269,13 +1193,10 @@ static void mos7720_close(struct usb_ser + /* these commands must not be issued if the device has + * been disconnected */ + if (!serial->disconnected) { +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, +- port->number - port->serial->minor, 0x04, &data); +- +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, +- port->number - port->serial->minor, 0x01, &data); ++ write_mos_reg(serial, port->number - port->serial->minor, ++ MCR, 0x00); ++ write_mos_reg(serial, port->number - port->serial->minor, ++ IER, 0x00); + } + mutex_unlock(&serial->disc_mutex); + mos7720_port->open = 0; +@@ -1304,8 +1225,8 @@ static void mos7720_break(struct tty_str + data = mos7720_port->shadowLCR & ~UART_LCR_SBC; + + mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, +- 0x03, &data); ++ write_mos_reg(serial, port->number - port->serial->minor, ++ LCR, mos7720_port->shadowLCR); + + return; + } +@@ -1450,9 +1371,8 @@ static void mos7720_throttle(struct tty_ + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + mos7720_port->shadowMCR &= ~UART_MCR_RTS; +- status = send_mos_cmd(port->serial, MOS_WRITE, +- port->number - port->serial->minor, +- UART_MCR, &mos7720_port->shadowMCR); ++ write_mos_reg(port->serial, port->number - port->serial->minor, ++ MCR, mos7720_port->shadowMCR); + if (status != 0) + return; + } +@@ -1485,9 +1405,8 @@ static void mos7720_unthrottle(struct tt + /* if we are implementing RTS/CTS, toggle that line */ + if (tty->termios->c_cflag & CRTSCTS) { + mos7720_port->shadowMCR |= UART_MCR_RTS; +- status = send_mos_cmd(port->serial, MOS_WRITE, +- port->number - port->serial->minor, +- UART_MCR, &mos7720_port->shadowMCR); ++ write_mos_reg(port->serial, port->number - port->serial->minor, ++ MCR, mos7720_port->shadowMCR); + if (status != 0) + return; + } +@@ -1497,11 +1416,10 @@ static void mos7720_unthrottle(struct tt + static int set_higher_rates(struct moschip_port *mos7720_port, + unsigned int baud) + { +- unsigned char data; + struct usb_serial_port *port; + struct usb_serial *serial; + int port_number; +- ++ enum mos_regs sp_reg; + if (mos7720_port == NULL) + return -EINVAL; + +@@ -1514,59 +1432,35 @@ static int set_higher_rates(struct mosch + dbg("Sending Setting Commands .........."); + port_number = port->number - port->serial->minor; + +- data = 0x000; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); +- data = 0x000; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x02, &data); +- data = 0x0CF; +- send_mos_cmd(serial, MOS_WRITE, port->number, 0x02, &data); +- data = 0x00b; +- mos7720_port->shadowMCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); +- data = 0x00b; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); +- +- data = 0x000; +- send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); +- data = 0x000; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); +- ++ write_mos_reg(serial, port_number, IER, 0x00); ++ write_mos_reg(serial, port_number, FCR, 0x00); ++ write_mos_reg(serial, port_number, FCR, 0xcf); ++ mos7720_port->shadowMCR = 0x0b; ++ write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); ++ write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x00); + + /*********************************************** + * Set for higher rates * + ***********************************************/ +- + /* writing baud rate verbatum into uart clock field clearly not right */ +- data = baud * 0x10; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, port_number + 1, &data); +- +- data = 0x003; +- send_mos_cmd(serial, MOS_READ, MOS_MAX_PORT, 0x08, &data); +- data = 0x003; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, 0x08, &data); +- +- data = 0x02b; +- mos7720_port->shadowMCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); +- data = 0x02b; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); ++ if (port_number == 0) ++ sp_reg = SP1_REG; ++ else ++ sp_reg = SP2_REG; ++ write_mos_reg(serial, dummy, sp_reg, baud * 0x10); ++ write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x03); ++ mos7720_port->shadowMCR = 0x2b; ++ write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + + /*********************************************** + * Set DLL/DLM + ***********************************************/ +- +- data = mos7720_port->shadowLCR | UART_LCR_DLAB; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); +- +- data = 0x001; /* DLL */ +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x00, &data); +- data = 0x000; /* DLM */ +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x01, &data); +- +- data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x03, &data); ++ mos7720_port->shadowLCR = mos7720_port->shadowLCR | UART_LCR_DLAB; ++ write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); ++ write_mos_reg(serial, port_number, DLL, 0x01); ++ write_mos_reg(serial, port_number, DLM, 0x00); ++ mos7720_port->shadowLCR = mos7720_port->shadowLCR & ~UART_LCR_DLAB; ++ write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); + + return 0; + } +@@ -1654,7 +1548,6 @@ static int send_cmd_write_baud_rate(stru + struct usb_serial *serial; + int divisor; + int status; +- unsigned char data; + unsigned char number; + + if (mos7720_port == NULL) +@@ -1676,21 +1569,16 @@ static int send_cmd_write_baud_rate(stru + } + + /* Enable access to divisor latch */ +- data = mos7720_port->shadowLCR | UART_LCR_DLAB; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, number, UART_LCR, &data); ++ mos7720_port->shadowLCR = mos7720_port->shadowLCR | UART_LCR_DLAB; ++ write_mos_reg(serial, number, LCR, mos7720_port->shadowLCR); + + /* Write the divisor */ +- data = ((unsigned char)(divisor & 0xff)); +- send_mos_cmd(serial, MOS_WRITE, number, 0x00, &data); +- +- data = ((unsigned char)((divisor & 0xff00) >> 8)); +- send_mos_cmd(serial, MOS_WRITE, number, 0x01, &data); ++ write_mos_reg(serial, number, DLL, (__u8)(divisor & 0xff)); ++ write_mos_reg(serial, number, DLM, (__u8)((divisor & 0xff00) >> 8)); + + /* Disable access to divisor latch */ +- data = mos7720_port->shadowLCR & ~UART_LCR_DLAB; +- mos7720_port->shadowLCR = data; +- send_mos_cmd(serial, MOS_WRITE, number, 0x03, &data); ++ mos7720_port->shadowLCR = mos7720_port->shadowLCR & ~UART_LCR_DLAB; ++ write_mos_reg(serial, number, LCR, mos7720_port->shadowLCR); + + return status; + } +@@ -1715,7 +1603,6 @@ static void change_port_settings(struct + __u8 lStop; + int status; + int port_number; +- char data; + + if (mos7720_port == NULL) + return ; +@@ -1794,30 +1681,19 @@ static void change_port_settings(struct + + /* Update the LCR with the correct value */ + mos7720_port->shadowLCR &= +- ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); ++ ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); + mos7720_port->shadowLCR |= (lData | lParity | lStop); + + + /* Disable Interrupts */ +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, port->number - port->serial->minor, +- UART_IER, &data); +- +- data = 0x00; +- send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); +- +- data = 0xcf; +- send_mos_cmd(serial, MOS_WRITE, port_number, UART_FCR, &data); ++ write_mos_reg(serial, port_number, IER, 0x00); ++ write_mos_reg(serial, port_number, FCR, 0x00); ++ write_mos_reg(serial, port_number, FCR, 0xcf); + + /* Send the updated LCR value to the mos7720 */ +- data = mos7720_port->shadowLCR; +- send_mos_cmd(serial, MOS_WRITE, port_number, UART_LCR, &data); +- +- data = 0x00b; +- mos7720_port->shadowMCR = data; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); +- data = 0x00b; +- send_mos_cmd(serial, MOS_WRITE, port_number, 0x04, &data); ++ write_mos_reg(serial, port_number, LCR, mos7720_port->shadowLCR); ++ mos7720_port->shadowMCR = 0x0b; ++ write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + + /* set up the MCR register and send it to the mos7720 */ + mos7720_port->shadowMCR = UART_MCR_OUT2; +@@ -1828,21 +1704,15 @@ static void change_port_settings(struct + mos7720_port->shadowMCR |= (UART_MCR_XONANY); + /* To set hardware flow control to the specified * + * serial port, in SP1/2_CONTROL_REG */ +- if (port->number) { +- data = 0x001; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, +- 0x08, &data); +- } else { +- data = 0x002; +- send_mos_cmd(serial, MOS_WRITE, MOS_MAX_PORT, +- 0x08, &data); +- } +- } else { ++ if (port->number) ++ write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x01); ++ else ++ write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x02); ++ ++ } else + mos7720_port->shadowMCR &= ~(UART_MCR_XONANY); +- } + +- data = mos7720_port->shadowMCR; +- send_mos_cmd(serial, MOS_WRITE, port_number, UART_MCR, &data); ++ write_mos_reg(serial, port_number, MCR, mos7720_port->shadowMCR); + + /* Determine divisor based on baud rate */ + baud = tty_get_baud_rate(tty); +@@ -1855,8 +1725,7 @@ static void change_port_settings(struct + if (baud >= 230400) { + set_higher_rates(mos7720_port, baud); + /* Enable Interrupts */ +- data = 0x0c; +- send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); ++ write_mos_reg(serial, port_number, IER, 0x0c); + return; + } + +@@ -1867,8 +1736,7 @@ static void change_port_settings(struct + if (cflag & CBAUD) + tty_encode_baud_rate(tty, baud, baud); + /* Enable Interrupts */ +- data = 0x0c; +- send_mos_cmd(serial, MOS_WRITE, port_number, UART_IER, &data); ++ write_mos_reg(serial, port_number, IER, 0x0c); + + if (port->read_urb->status != -EINPROGRESS) { + port->read_urb->dev = serial->dev; +@@ -1959,8 +1827,7 @@ static int get_lsr_info(struct tty_struc + + count = mos7720_chars_in_buffer(tty); + if (count == 0) { +- send_mos_cmd(port->serial, MOS_READ, port_number, +- UART_LSR, &data); ++ read_mos_reg(port->serial, port_number, LSR, &data); + if ((data & (UART_LSR_TEMT | UART_LSR_THRE)) + == (UART_LSR_TEMT | UART_LSR_THRE)) { + dbg("%s -- Empty", __func__); +@@ -1998,13 +1865,11 @@ static int mos7720_tiocmget(struct tty_s + } + + static int mos7720_tiocmset(struct tty_struct *tty, struct file *file, +- unsigned int set, unsigned int clear) ++ unsigned int set, unsigned int clear) + { + struct usb_serial_port *port = tty->driver_data; + struct moschip_port *mos7720_port = usb_get_serial_port_data(port); + unsigned int mcr ; +- unsigned char lmcr; +- + dbg("%s - port %d", __func__, port->number); + dbg("he was at tiocmget"); + +@@ -2025,10 +1890,8 @@ static int mos7720_tiocmset(struct tty_s + mcr &= ~UART_MCR_LOOP; + + mos7720_port->shadowMCR = mcr; +- lmcr = mos7720_port->shadowMCR; +- +- send_mos_cmd(port->serial, MOS_WRITE, +- port->number - port->serial->minor, UART_MCR, &lmcr); ++ write_mos_reg(port->serial, port->number - port->serial->minor, ++ MCR, mos7720_port->shadowMCR); + + return 0; + } +@@ -2038,7 +1901,6 @@ static int set_modem_info(struct moschip + { + unsigned int mcr ; + unsigned int arg; +- unsigned char data; + + struct usb_serial_port *port; + +@@ -2073,10 +1935,8 @@ static int set_modem_info(struct moschip + } + + mos7720_port->shadowMCR = mcr; +- +- data = mos7720_port->shadowMCR; +- send_mos_cmd(port->serial, MOS_WRITE, +- port->number - port->serial->minor, UART_MCR, &data); ++ write_mos_reg(port->serial, port->number - port->serial->minor, ++ MCR, mos7720_port->shadowMCR); + + return 0; + } +@@ -2269,11 +2129,7 @@ static int mos7720_startup(struct usb_se + } + #endif + /* LSR For Port 1 */ +- send_mos_cmd(serial, MOS_READ, 0x00, UART_LSR, &data); +- dbg("LSR:%x", data); +- +- /* LSR For Port 2 */ +- send_mos_cmd(serial, MOS_READ, 0x01, UART_LSR, &data); ++ read_mos_reg(serial, 0, LSR, &data); + dbg("LSR:%x", data); + + return 0; diff --git a/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch b/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch index 13593136a77ce6..d0647faccabade 100644 --- a/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch +++ b/usb/usb-use-pm-core-routines-to-enable-disable-autosuspend.patch @@ -22,7 +22,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c -@@ -1355,13 +1355,9 @@ int usb_resume(struct device *dev, pm_me +@@ -1356,13 +1356,9 @@ int usb_resume(struct device *dev, pm_me * * The caller must hold @udev's device lock. */ @@ -38,7 +38,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } EXPORT_SYMBOL_GPL(usb_enable_autosuspend); -@@ -1374,16 +1370,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend +@@ -1375,16 +1371,9 @@ EXPORT_SYMBOL_GPL(usb_enable_autosuspend * * The caller must hold @udev's device lock. */ @@ -57,7 +57,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> } EXPORT_SYMBOL_GPL(usb_disable_autosuspend); -@@ -1527,7 +1516,7 @@ void usb_autopm_put_interface_async(stru +@@ -1528,7 +1517,7 @@ void usb_autopm_put_interface_async(stru atomic_dec(&intf->pm_usage_cnt); pm_runtime_put_noidle(&intf->dev); |
