You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (260 commits) usb: renesas_usbhs: fixup inconsistent return from usbhs_pkt_push() usb/isp1760: Allow to optionally trigger low-level chip reset via GPIOLIB. USB: gadget: midi: memory leak in f_midi_bind_config() USB: gadget: midi: fix range check in f_midi_out_open() QE/FHCI: fixed the CONTROL bug usb: renesas_usbhs: tidyup for smatch warnings USB: Fix USB Kconfig dependency problem on 85xx/QoirQ platforms EHCI: workaround for MosChip controller bug usb: gadget: file_storage: fix race on unloading USB: ftdi_sio.c: Use ftdi async_icount structure for TIOCMIWAIT, as in other drivers USB: ftdi_sio.c:Fill MSR fields of the ftdi async_icount structure USB: ftdi_sio.c: Fill LSR fields of the ftdi async_icount structure USB: ftdi_sio.c:Fill TX field of the ftdi async_icount structure USB: ftdi_sio.c: Fill the RX field of the ftdi async_icount structure USB: ftdi_sio.c: Basic icount infrastructure for ftdi_sio usb/isp1760: Let OF bindings depend on general CONFIG_OF instead of PPC_OF . USB: ftdi_sio: Support TI/Luminary Micro Stellaris BD-ICDI Board USB: Fix runtime wakeup on OHCI xHCI/USB: Make xHCI driver have a BOS descriptor. usb: gadget: add new usb gadget for ACM and mass storage ...
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
What: /sys/bus/pci/drivers/ehci_hcd/.../companion
|
||||
/sys/bus/usb/devices/usbN/../companion
|
||||
Date: January 2007
|
||||
KernelVersion: 2.6.21
|
||||
Contact: Alan Stern <stern@rowland.harvard.edu>
|
||||
Description:
|
||||
PCI-based EHCI USB controllers (i.e., high-speed USB-2.0
|
||||
controllers) are often implemented along with a set of
|
||||
"companion" full/low-speed USB-1.1 controllers. When a
|
||||
high-speed device is plugged in, the connection is routed
|
||||
to the EHCI controller; when a full- or low-speed device
|
||||
is plugged in, the connection is routed to the companion
|
||||
controller.
|
||||
|
||||
Sometimes you want to force a high-speed device to connect
|
||||
at full speed, which can be accomplished by forcing the
|
||||
connection to be routed to the companion controller.
|
||||
That's what this file does. Writing a port number to the
|
||||
file causes connections on that port to be routed to the
|
||||
companion controller, and writing the negative of a port
|
||||
number returns the port to normal operation.
|
||||
|
||||
For example: To force the high-speed device attached to
|
||||
port 4 on bus 2 to run at full speed:
|
||||
|
||||
echo 4 >/sys/bus/usb/devices/usb2/../companion
|
||||
|
||||
To return the port to high-speed operation:
|
||||
|
||||
echo -4 >/sys/bus/usb/devices/usb2/../companion
|
||||
|
||||
Reading the file gives the list of ports currently forced
|
||||
to the companion controller.
|
||||
|
||||
Note: Some EHCI controllers do not have companions; they
|
||||
may contain an internal "transaction translator" or they
|
||||
may be attached directly to a "rate-matching hub". This
|
||||
mechanism will not work with such controllers. Also, it
|
||||
cannot be used to force a port on a high-speed hub to
|
||||
connect at full speed.
|
||||
|
||||
Note: When this file was first added, it appeared in a
|
||||
different sysfs directory. The location given above is
|
||||
correct for 2.6.35 (and probably several earlier kernel
|
||||
versions as well).
|
||||
|
||||
@@ -142,3 +142,18 @@ Description:
|
||||
such devices.
|
||||
Users:
|
||||
usb_modeswitch
|
||||
|
||||
What: /sys/bus/usb/devices/.../power/usb2_hardware_lpm
|
||||
Date: September 2011
|
||||
Contact: Andiry Xu <andiry.xu@amd.com>
|
||||
Description:
|
||||
If CONFIG_USB_SUSPEND is set and a USB 2.0 lpm-capable device
|
||||
is plugged in to a xHCI host which support link PM, it will
|
||||
perform a LPM test; if the test is passed and host supports
|
||||
USB2 hardware LPM (xHCI 1.0 feature), USB2 hardware LPM will
|
||||
be enabled for the device and the USB device directory will
|
||||
contain a file named power/usb2_hardware_lpm. The file holds
|
||||
a string value (enable or disable) indicating whether or not
|
||||
USB2 hardware LPM is enabled for the device. Developer can
|
||||
write y/Y/1 or n/N/0 to the file to enable/disable the
|
||||
feature.
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
|
||||
TODO
|
||||
~~~~~~
|
||||
Please pick something while reading :)
|
||||
|
||||
- Convert interrupt handler to per-ep-thread-irq
|
||||
|
||||
As it turns out some DWC3-commands ~1ms to complete. Currently we spin
|
||||
until the command completes which is bad.
|
||||
|
||||
Implementation idea:
|
||||
- dwc core implements a demultiplexing irq chip for interrupts per
|
||||
endpoint. The interrupt numbers are allocated during probe and belong
|
||||
to the device. If MSI provides per-endpoint interrupt this dummy
|
||||
interrupt chip can be replaced with "real" interrupts.
|
||||
- interrupts are requested / allocated on usb_ep_enable() and removed on
|
||||
usb_ep_disable(). Worst case are 32 interrupts, the lower limit is two
|
||||
for ep0/1.
|
||||
- dwc3_send_gadget_ep_cmd() will sleep in wait_for_completion_timeout()
|
||||
until the command completes.
|
||||
- the interrupt handler is split into the following pieces:
|
||||
- primary handler of the device
|
||||
goes through every event and calls generic_handle_irq() for event
|
||||
it. On return from generic_handle_irq() in acknowledges the event
|
||||
counter so interrupt goes away (eventually).
|
||||
|
||||
- threaded handler of the device
|
||||
none
|
||||
|
||||
- primary handler of the EP-interrupt
|
||||
reads the event and tries to process it. Everything that requries
|
||||
sleeping is handed over to the Thread. The event is saved in an
|
||||
per-endpoint data-structure.
|
||||
We probably have to pay attention not to process events once we
|
||||
handed something to thread so we don't process event X prio Y
|
||||
where X > Y.
|
||||
|
||||
- threaded handler of the EP-interrupt
|
||||
handles the remaining EP work which might sleep such as waiting
|
||||
for command completion.
|
||||
|
||||
Latency:
|
||||
There should be no increase in latency since the interrupt-thread has a
|
||||
high priority and will be run before an average task in user land
|
||||
(except the user changed priorities).
|
||||
@@ -487,3 +487,29 @@ succeed, it may still remain active and thus cause the system to
|
||||
resume as soon as the system suspend is complete. Or the remote
|
||||
wakeup may fail and get lost. Which outcome occurs depends on timing
|
||||
and on the hardware and firmware design.
|
||||
|
||||
|
||||
xHCI hardware link PM
|
||||
---------------------
|
||||
|
||||
xHCI host controller provides hardware link power management to usb2.0
|
||||
(xHCI 1.0 feature) and usb3.0 devices which support link PM. By
|
||||
enabling hardware LPM, the host can automatically put the device into
|
||||
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
|
||||
which state device can enter and resume very quickly.
|
||||
|
||||
The user interface for controlling USB2 hardware LPM is located in the
|
||||
power/ subdirectory of each USB device's sysfs directory, that is, in
|
||||
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
|
||||
relevant attribute files is usb2_hardware_lpm.
|
||||
|
||||
power/usb2_hardware_lpm
|
||||
|
||||
When a USB2 device which support LPM is plugged to a
|
||||
xHCI host root hub which support software LPM, the
|
||||
host will run a software LPM test for it; if the device
|
||||
enters L1 state and resume successfully and the host
|
||||
supports USB2 hardware LPM, this file will show up and
|
||||
driver will enable hardware LPM for the device. You
|
||||
can write y/Y/1 or n/N/0 to the file to enable/disable
|
||||
USB2 hardware LPM manually. This is for test purpose mainly.
|
||||
|
||||
@@ -2136,6 +2136,14 @@ M: Matthew Garrett <mjg59@srcf.ucam.org>
|
||||
S: Maintained
|
||||
F: drivers/platform/x86/dell-wmi.c
|
||||
|
||||
DESIGNWARE USB3 DRD IP DRIVER
|
||||
M: Felipe Balbi <balbi@ti.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
L: linux-omap@vger.kernel.org
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
|
||||
S: Maintained
|
||||
F: drivers/usb/dwc3/
|
||||
|
||||
DEVICE NUMBER REGISTRY
|
||||
M: Torben Mathiasen <device@lanana.org>
|
||||
W: http://lanana.org/docs/device-list/index.html
|
||||
|
||||
@@ -35,6 +35,13 @@ extern struct pxa_device_desc pxa168_device_fb;
|
||||
extern struct pxa_device_desc pxa168_device_keypad;
|
||||
extern struct pxa_device_desc pxa168_device_eth;
|
||||
|
||||
struct pxa168_usb_pdata {
|
||||
/* If NULL, default phy init routine for PXA168 would be called */
|
||||
int (*phy_init)(void __iomem *usb_phy_reg_base);
|
||||
};
|
||||
/* pdata can be NULL */
|
||||
int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata);
|
||||
|
||||
static inline int pxa168_add_uart(int id)
|
||||
{
|
||||
struct pxa_device_desc *d = NULL;
|
||||
|
||||
@@ -25,6 +25,9 @@
|
||||
#include <mach/dma.h>
|
||||
#include <mach/devices.h>
|
||||
#include <mach/mfp.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <mach/pxa168.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "clock.h"
|
||||
@@ -83,6 +86,7 @@ static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
|
||||
static APMU_CLK(nand, NAND, 0x19b, 156000000);
|
||||
static APMU_CLK(lcd, LCD, 0x7f, 312000000);
|
||||
static APMU_CLK(eth, ETH, 0x09, 0);
|
||||
static APMU_CLK(usb, USB, 0x12, 0);
|
||||
|
||||
/* device and clock bindings */
|
||||
static struct clk_lookup pxa168_clkregs[] = {
|
||||
@@ -104,6 +108,7 @@ static struct clk_lookup pxa168_clkregs[] = {
|
||||
INIT_CLKREG(&clk_lcd, "pxa168-fb", NULL),
|
||||
INIT_CLKREG(&clk_keypad, "pxa27x-keypad", NULL),
|
||||
INIT_CLKREG(&clk_eth, "pxa168-eth", "MFUCLK"),
|
||||
INIT_CLKREG(&clk_usb, "pxa168-ehci", "PXA168-USBCLK"),
|
||||
};
|
||||
|
||||
static int __init pxa168_init(void)
|
||||
@@ -169,3 +174,44 @@ PXA168_DEVICE(ssp5, "pxa168-ssp", 4, SSP5, 0xd4021000, 0x40, 60, 61);
|
||||
PXA168_DEVICE(fb, "pxa168-fb", -1, LCD, 0xd420b000, 0x1c8);
|
||||
PXA168_DEVICE(keypad, "pxa27x-keypad", -1, KEYPAD, 0xd4012000, 0x4c);
|
||||
PXA168_DEVICE(eth, "pxa168-eth", -1, MFU, 0xc0800000, 0x0fff);
|
||||
|
||||
struct resource pxa168_usb_host_resources[] = {
|
||||
/* USB Host conroller register base */
|
||||
[0] = {
|
||||
.start = 0xd4209000,
|
||||
.end = 0xd4209000 + 0x200,
|
||||
.flags = IORESOURCE_MEM,
|
||||
.name = "pxa168-usb-host",
|
||||
},
|
||||
/* USB PHY register base */
|
||||
[1] = {
|
||||
.start = 0xd4206000,
|
||||
.end = 0xd4206000 + 0xff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
.name = "pxa168-usb-phy",
|
||||
},
|
||||
[2] = {
|
||||
.start = IRQ_PXA168_USB2,
|
||||
.end = IRQ_PXA168_USB2,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static u64 pxa168_usb_host_dmamask = DMA_BIT_MASK(32);
|
||||
struct platform_device pxa168_device_usb_host = {
|
||||
.name = "pxa168-ehci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &pxa168_usb_host_dmamask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
|
||||
.num_resources = ARRAY_SIZE(pxa168_usb_host_resources),
|
||||
.resource = pxa168_usb_host_resources,
|
||||
};
|
||||
|
||||
int __init pxa168_add_usb_host(struct pxa168_usb_pdata *pdata)
|
||||
{
|
||||
pxa168_device_usb_host.dev.platform_data = pdata;
|
||||
return platform_device_register(&pxa168_device_usb_host);
|
||||
}
|
||||
|
||||
@@ -242,14 +242,11 @@ obj-$(CONFIG_MACH_IGEP0020) += board-igep0020.o \
|
||||
obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK) += board-omap3touchbook.o \
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_OMAP_4430SDP) += board-4430sdp.o \
|
||||
hsmmc.o \
|
||||
omap_phy_internal.o
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \
|
||||
hsmmc.o \
|
||||
omap_phy_internal.o
|
||||
hsmmc.o
|
||||
|
||||
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o \
|
||||
omap_phy_internal.o \
|
||||
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o
|
||||
|
||||
obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o
|
||||
|
||||
@@ -260,6 +257,8 @@ obj-$(CONFIG_MACH_TI8168EVM) += board-ti8168evm.o
|
||||
usbfs-$(CONFIG_ARCH_OMAP_OTG) := usb-fs.o
|
||||
obj-y += $(usbfs-m) $(usbfs-y)
|
||||
obj-y += usb-musb.o
|
||||
obj-y += omap_phy_internal.o
|
||||
|
||||
obj-$(CONFIG_MACH_OMAP2_TUSB6010) += usb-tusb6010.o
|
||||
obj-y += usb-host.o
|
||||
|
||||
|
||||
@@ -810,6 +810,7 @@ static struct usbhs_private usbhs1_private = {
|
||||
},
|
||||
.driver_param = {
|
||||
.buswait_bwait = 4,
|
||||
.has_otg = 1,
|
||||
.pipe_type = usbhs1_pipe_cfg,
|
||||
.pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg),
|
||||
.d0_tx_id = SHDMA_SLAVE_USB1_TX,
|
||||
|
||||
+15
-1
@@ -12,6 +12,11 @@ menuconfig USB_SUPPORT
|
||||
|
||||
if USB_SUPPORT
|
||||
|
||||
config USB_COMMON
|
||||
tristate
|
||||
default y
|
||||
depends on USB || USB_GADGET
|
||||
|
||||
# Host-side USB depends on having a host controller
|
||||
# NOTE: dummy_hcd is always an option, but it's ignored here ...
|
||||
# NOTE: SL-811 option should be board-specific ...
|
||||
@@ -19,6 +24,7 @@ config USB_ARCH_HAS_HCD
|
||||
boolean
|
||||
default y if USB_ARCH_HAS_OHCI
|
||||
default y if USB_ARCH_HAS_EHCI
|
||||
default y if USB_ARCH_HAS_XHCI
|
||||
default y if PCMCIA && !M32R # sl811_cs
|
||||
default y if ARM # SL-811
|
||||
default y if BLACKFIN # SL-811
|
||||
@@ -54,7 +60,7 @@ config USB_ARCH_HAS_OHCI
|
||||
# some non-PCI hcds implement EHCI
|
||||
config USB_ARCH_HAS_EHCI
|
||||
boolean
|
||||
default y if PPC_83xx
|
||||
default y if FSL_SOC
|
||||
default y if PPC_MPC512x
|
||||
default y if SOC_AU1200
|
||||
default y if ARCH_IXP4XX
|
||||
@@ -69,6 +75,12 @@ config USB_ARCH_HAS_EHCI
|
||||
default y if ARCH_MSM
|
||||
default y if MICROBLAZE
|
||||
default y if SPARC_LEON
|
||||
default y if ARCH_MMP
|
||||
default PCI
|
||||
|
||||
# some non-PCI HCDs implement xHCI
|
||||
config USB_ARCH_HAS_XHCI
|
||||
boolean
|
||||
default PCI
|
||||
|
||||
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
|
||||
@@ -110,6 +122,8 @@ config USB
|
||||
|
||||
source "drivers/usb/core/Kconfig"
|
||||
|
||||
source "drivers/usb/dwc3/Kconfig"
|
||||
|
||||
source "drivers/usb/mon/Kconfig"
|
||||
|
||||
source "drivers/usb/wusbcore/Kconfig"
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
obj-$(CONFIG_USB) += core/
|
||||
|
||||
obj-$(CONFIG_USB_DWC3) += dwc3/
|
||||
|
||||
obj-$(CONFIG_USB_MON) += mon/
|
||||
|
||||
obj-$(CONFIG_PCI) += host/
|
||||
@@ -51,3 +53,5 @@ obj-$(CONFIG_USB_MUSB_HDRC) += musb/
|
||||
obj-$(CONFIG_USB_RENESAS_USBHS) += renesas_usbhs/
|
||||
obj-$(CONFIG_USB_OTG_UTILS) += otg/
|
||||
obj-$(CONFIG_USB_GADGET) += gadget/
|
||||
|
||||
obj-$(CONFIG_USB_COMMON) += usb-common.o
|
||||
|
||||
@@ -1058,11 +1058,11 @@ made_compressed_probe:
|
||||
goto alloc_fail;
|
||||
}
|
||||
|
||||
ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize);
|
||||
readsize = le16_to_cpu(epread->wMaxPacketSize) *
|
||||
ctrlsize = usb_endpoint_maxp(epctrl);
|
||||
readsize = usb_endpoint_maxp(epread) *
|
||||
(quirks == SINGLE_RX_URB ? 1 : 2);
|
||||
acm->combined_interfaces = combined_interfaces;
|
||||
acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20;
|
||||
acm->writesize = usb_endpoint_maxp(epwrite) * 20;
|
||||
acm->control = control_interface;
|
||||
acm->data = data_interface;
|
||||
acm->minor = minor;
|
||||
@@ -1534,6 +1534,9 @@ static const struct usb_device_id acm_ids[] = {
|
||||
{ NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */
|
||||
{ SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
|
||||
|
||||
/* Support for Owen devices */
|
||||
{ USB_DEVICE(0x03eb, 0x0030), }, /* Owen SI30 */
|
||||
|
||||
/* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
|
||||
|
||||
/* Support Lego NXT using pbLua firmware */
|
||||
|
||||
@@ -682,7 +682,7 @@ next_desc:
|
||||
if (!ep || !usb_endpoint_is_int_in(ep))
|
||||
goto err;
|
||||
|
||||
desc->wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
|
||||
desc->wMaxPacketSize = usb_endpoint_maxp(ep);
|
||||
desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
|
||||
|
||||
desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
|
||||
|
||||
@@ -186,8 +186,7 @@ static int usbtmc_ioctl_abort_bulk_in(struct usbtmc_device_data *data)
|
||||
for (n = 0; n < current_setting->desc.bNumEndpoints; n++)
|
||||
if (current_setting->endpoint[n].desc.bEndpointAddress ==
|
||||
data->bulk_in)
|
||||
max_size = le16_to_cpu(current_setting->endpoint[n].
|
||||
desc.wMaxPacketSize);
|
||||
max_size = usb_endpoint_maxp(¤t_setting->endpoint[n].desc);
|
||||
|
||||
if (max_size == 0) {
|
||||
dev_err(dev, "Couldn't get wMaxPacketSize\n");
|
||||
@@ -636,7 +635,7 @@ static int usbtmc_ioctl_clear(struct usbtmc_device_data *data)
|
||||
for (n = 0; n < current_setting->desc.bNumEndpoints; n++) {
|
||||
desc = ¤t_setting->endpoint[n].desc;
|
||||
if (desc->bEndpointAddress == data->bulk_in)
|
||||
max_size = le16_to_cpu(desc->wMaxPacketSize);
|
||||
max_size = usb_endpoint_maxp(desc);
|
||||
}
|
||||
|
||||
if (max_size == 0) {
|
||||
|
||||
+107
-4
@@ -124,9 +124,9 @@ static void usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno,
|
||||
|
||||
if (usb_endpoint_xfer_isoc(&ep->desc))
|
||||
max_tx = (desc->bMaxBurst + 1) * (desc->bmAttributes + 1) *
|
||||
le16_to_cpu(ep->desc.wMaxPacketSize);
|
||||
usb_endpoint_maxp(&ep->desc);
|
||||
else if (usb_endpoint_xfer_int(&ep->desc))
|
||||
max_tx = le16_to_cpu(ep->desc.wMaxPacketSize) *
|
||||
max_tx = usb_endpoint_maxp(&ep->desc) *
|
||||
(desc->bMaxBurst + 1);
|
||||
else
|
||||
max_tx = 999999;
|
||||
@@ -241,7 +241,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
||||
cfgno, inum, asnum, d->bEndpointAddress);
|
||||
endpoint->desc.bmAttributes = USB_ENDPOINT_XFER_INT;
|
||||
endpoint->desc.bInterval = 1;
|
||||
if (le16_to_cpu(endpoint->desc.wMaxPacketSize) > 8)
|
||||
if (usb_endpoint_maxp(&endpoint->desc) > 8)
|
||||
endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
|
||||
&& usb_endpoint_xfer_bulk(d)) {
|
||||
unsigned maxp;
|
||||
|
||||
maxp = le16_to_cpu(endpoint->desc.wMaxPacketSize) & 0x07ff;
|
||||
maxp = usb_endpoint_maxp(&endpoint->desc) & 0x07ff;
|
||||
if (maxp != 512)
|
||||
dev_warn(ddev, "config %d interface %d altsetting %d "
|
||||
"bulk endpoint 0x%X has invalid maxpacket %d\n",
|
||||
@@ -755,3 +755,106 @@ err2:
|
||||
dev_err(ddev, "out of memory\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
void usb_release_bos_descriptor(struct usb_device *dev)
|
||||
{
|
||||
if (dev->bos) {
|
||||
kfree(dev->bos->desc);
|
||||
kfree(dev->bos);
|
||||
dev->bos = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get BOS descriptor set */
|
||||
int usb_get_bos_descriptor(struct usb_device *dev)
|
||||
{
|
||||
struct device *ddev = &dev->dev;
|
||||
struct usb_bos_descriptor *bos;
|
||||
struct usb_dev_cap_header *cap;
|
||||
unsigned char *buffer;
|
||||
int length, total_len, num, i;
|
||||
int ret;
|
||||
|
||||
bos = kzalloc(sizeof(struct usb_bos_descriptor), GFP_KERNEL);
|
||||
if (!bos)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Get BOS descriptor */
|
||||
ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE);
|
||||
if (ret < USB_DT_BOS_SIZE) {
|
||||
dev_err(ddev, "unable to get BOS descriptor\n");
|
||||
if (ret >= 0)
|
||||
ret = -ENOMSG;
|
||||
kfree(bos);
|
||||
return ret;
|
||||
}
|
||||
|
||||
length = bos->bLength;
|
||||
total_len = le16_to_cpu(bos->wTotalLength);
|
||||
num = bos->bNumDeviceCaps;
|
||||
kfree(bos);
|
||||
if (total_len < length)
|
||||
return -EINVAL;
|
||||
|
||||
dev->bos = kzalloc(sizeof(struct usb_host_bos), GFP_KERNEL);
|
||||
if (!dev->bos)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Now let's get the whole BOS descriptor set */
|
||||
buffer = kzalloc(total_len, GFP_KERNEL);
|
||||
if (!buffer) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
dev->bos->desc = (struct usb_bos_descriptor *)buffer;
|
||||
|
||||
ret = usb_get_descriptor(dev, USB_DT_BOS, 0, buffer, total_len);
|
||||
if (ret < total_len) {
|
||||
dev_err(ddev, "unable to get BOS descriptor set\n");
|
||||
if (ret >= 0)
|
||||
ret = -ENOMSG;
|
||||
goto err;
|
||||
}
|
||||
total_len -= length;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
buffer += length;
|
||||
cap = (struct usb_dev_cap_header *)buffer;
|
||||
length = cap->bLength;
|
||||
|
||||
if (total_len < length)
|
||||
break;
|
||||
total_len -= length;
|
||||
|
||||
if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) {
|
||||
dev_warn(ddev, "descriptor type invalid, skip\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cap->bDevCapabilityType) {
|
||||
case USB_CAP_TYPE_WIRELESS_USB:
|
||||
/* Wireless USB cap descriptor is handled by wusb */
|
||||
break;
|
||||
case USB_CAP_TYPE_EXT:
|
||||
dev->bos->ext_cap =
|
||||
(struct usb_ext_cap_descriptor *)buffer;
|
||||
break;
|
||||
case USB_SS_CAP_TYPE:
|
||||
dev->bos->ss_cap =
|
||||
(struct usb_ss_cap_descriptor *)buffer;
|
||||
break;
|
||||
case CONTAINER_ID_TYPE:
|
||||
dev->bos->ss_id =
|
||||
(struct usb_ss_container_id_descriptor *)buffer;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
usb_release_bos_descriptor(dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
|
||||
dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
|
||||
|
||||
if (speed == USB_SPEED_HIGH) {
|
||||
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
|
||||
switch (usb_endpoint_maxp(desc) & (0x03 << 11)) {
|
||||
case 1 << 11:
|
||||
bandwidth = 2; break;
|
||||
case 2 << 11:
|
||||
@@ -240,7 +240,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
|
||||
|
||||
start += sprintf(start, format_endpt, desc->bEndpointAddress, dir,
|
||||
desc->bmAttributes, type,
|
||||
(le16_to_cpu(desc->wMaxPacketSize) & 0x07ff) *
|
||||
(usb_endpoint_maxp(desc) & 0x07ff) *
|
||||
bandwidth,
|
||||
interval, unit);
|
||||
return start;
|
||||
|
||||
+35
-22
@@ -46,6 +46,7 @@
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@@ -68,7 +69,7 @@ struct dev_state {
|
||||
wait_queue_head_t wait; /* wake up if a request completed */
|
||||
unsigned int discsignr;
|
||||
struct pid *disc_pid;
|
||||
uid_t disc_uid, disc_euid;
|
||||
const struct cred *cred;
|
||||
void __user *disccontext;
|
||||
unsigned long ifclaimed;
|
||||
u32 secid;
|
||||
@@ -79,7 +80,7 @@ struct async {
|
||||
struct list_head asynclist;
|
||||
struct dev_state *ps;
|
||||
struct pid *pid;
|
||||
uid_t uid, euid;
|
||||
const struct cred *cred;
|
||||
unsigned int signr;
|
||||
unsigned int ifnum;
|
||||
void __user *userbuffer;
|
||||
@@ -248,6 +249,7 @@ static struct async *alloc_async(unsigned int numisoframes)
|
||||
static void free_async(struct async *as)
|
||||
{
|
||||
put_pid(as->pid);
|
||||
put_cred(as->cred);
|
||||
kfree(as->urb->transfer_buffer);
|
||||
kfree(as->urb->setup_packet);
|
||||
usb_free_urb(as->urb);
|
||||
@@ -393,9 +395,8 @@ static void async_completed(struct urb *urb)
|
||||
struct dev_state *ps = as->ps;
|
||||
struct siginfo sinfo;
|
||||
struct pid *pid = NULL;
|
||||
uid_t uid = 0;
|
||||
uid_t euid = 0;
|
||||
u32 secid = 0;
|
||||
const struct cred *cred = NULL;
|
||||
int signr;
|
||||
|
||||
spin_lock(&ps->lock);
|
||||
@@ -407,9 +408,8 @@ static void async_completed(struct urb *urb)
|
||||
sinfo.si_errno = as->status;
|
||||
sinfo.si_code = SI_ASYNCIO;
|
||||
sinfo.si_addr = as->userurb;
|
||||
pid = as->pid;
|
||||
uid = as->uid;
|
||||
euid = as->euid;
|
||||
pid = get_pid(as->pid);
|
||||
cred = get_cred(as->cred);
|
||||
secid = as->secid;
|
||||
}
|
||||
snoop(&urb->dev->dev, "urb complete\n");
|
||||
@@ -422,9 +422,11 @@ static void async_completed(struct urb *urb)
|
||||
cancel_bulk_urbs(ps, as->bulk_addr);
|
||||
spin_unlock(&ps->lock);
|
||||
|
||||
if (signr)
|
||||
kill_pid_info_as_uid(sinfo.si_signo, &sinfo, pid, uid,
|
||||
euid, secid);
|
||||
if (signr) {
|
||||
kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred, secid);
|
||||
put_pid(pid);
|
||||
put_cred(cred);
|
||||
}
|
||||
|
||||
wake_up(&ps->wait);
|
||||
}
|
||||
@@ -607,9 +609,10 @@ static int findintfep(struct usb_device *dev, unsigned int ep)
|
||||
}
|
||||
|
||||
static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
|
||||
unsigned int index)
|
||||
unsigned int request, unsigned int index)
|
||||
{
|
||||
int ret = 0;
|
||||
struct usb_host_interface *alt_setting;
|
||||
|
||||
if (ps->dev->state != USB_STATE_UNAUTHENTICATED
|
||||
&& ps->dev->state != USB_STATE_ADDRESS
|
||||
@@ -618,6 +621,19 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype,
|
||||
if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* check for the special corner case 'get_device_id' in the printer
|
||||
* class specification, where wIndex is (interface << 8 | altsetting)
|
||||
* instead of just interface
|
||||
*/
|
||||
if (requesttype == 0xa1 && request == 0) {
|
||||
alt_setting = usb_find_alt_setting(ps->dev->actconfig,
|
||||
index >> 8, index & 0xff);
|
||||
if (alt_setting
|
||||
&& alt_setting->desc.bInterfaceClass == USB_CLASS_PRINTER)
|
||||
index >>= 8;
|
||||
}
|
||||
|
||||
index &= 0xff;
|
||||
switch (requesttype & USB_RECIP_MASK) {
|
||||
case USB_RECIP_ENDPOINT:
|
||||
@@ -656,7 +672,6 @@ static int usbdev_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct usb_device *dev = NULL;
|
||||
struct dev_state *ps;
|
||||
const struct cred *cred = current_cred();
|
||||
int ret;
|
||||
|
||||
ret = -ENOMEM;
|
||||
@@ -706,8 +721,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
|
||||
init_waitqueue_head(&ps->wait);
|
||||
ps->discsignr = 0;
|
||||
ps->disc_pid = get_pid(task_pid(current));
|
||||
ps->disc_uid = cred->uid;
|
||||
ps->disc_euid = cred->euid;
|
||||
ps->cred = get_current_cred();
|
||||
ps->disccontext = NULL;
|
||||
ps->ifclaimed = 0;
|
||||
security_task_getsecid(current, &ps->secid);
|
||||
@@ -749,6 +763,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
|
||||
usb_unlock_device(dev);
|
||||
usb_put_dev(dev);
|
||||
put_pid(ps->disc_pid);
|
||||
put_cred(ps->cred);
|
||||
|
||||
as = async_getcompleted(ps);
|
||||
while (as) {
|
||||
@@ -770,7 +785,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
|
||||
if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
|
||||
return -EFAULT;
|
||||
ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.wIndex);
|
||||
ret = check_ctrlrecip(ps, ctrl.bRequestType, ctrl.bRequest,
|
||||
ctrl.wIndex);
|
||||
if (ret)
|
||||
return ret;
|
||||
wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */
|
||||
@@ -1048,7 +1064,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
struct usb_host_endpoint *ep;
|
||||
struct async *as;
|
||||
struct usb_ctrlrequest *dr = NULL;
|
||||
const struct cred *cred = current_cred();
|
||||
unsigned int u, totlen, isofrmlen;
|
||||
int ret, ifnum = -1;
|
||||
int is_in;
|
||||
@@ -1100,7 +1115,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
kfree(dr);
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = check_ctrlrecip(ps, dr->bRequestType,
|
||||
ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,
|
||||
le16_to_cpup(&dr->wIndex));
|
||||
if (ret) {
|
||||
kfree(dr);
|
||||
@@ -1262,8 +1277,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
as->signr = uurb->signr;
|
||||
as->ifnum = ifnum;
|
||||
as->pid = get_pid(task_pid(current));
|
||||
as->uid = cred->uid;
|
||||
as->euid = cred->euid;
|
||||
as->cred = get_current_cred();
|
||||
security_task_getsecid(current, &as->secid);
|
||||
if (!is_in && uurb->buffer_length > 0) {
|
||||
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
|
||||
@@ -1981,9 +1995,8 @@ static void usbdev_remove(struct usb_device *udev)
|
||||
sinfo.si_errno = EPIPE;
|
||||
sinfo.si_code = SI_ASYNCIO;
|
||||
sinfo.si_addr = ps->disccontext;
|
||||
kill_pid_info_as_uid(ps->discsignr, &sinfo,
|
||||
ps->disc_pid, ps->disc_uid,
|
||||
ps->disc_euid, ps->secid);
|
||||
kill_pid_info_as_cred(ps->discsignr, &sinfo,
|
||||
ps->disc_pid, ps->cred, ps->secid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,7 +1583,7 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
|
||||
dev_vdbg(&intf->dev, "%s: cnt %d -> %d\n",
|
||||
__func__, atomic_read(&intf->dev.power.usage_count),
|
||||
status);
|
||||
if (status > 0)
|
||||
if (status > 0 || status == -EINPROGRESS)
|
||||
status = 0;
|
||||
return status;
|
||||
}
|
||||
@@ -1700,6 +1700,20 @@ int usb_runtime_idle(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
int ret = -EPERM;
|
||||
|
||||
if (hcd->driver->set_usb2_hw_lpm) {
|
||||
ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, enable);
|
||||
if (!ret)
|
||||
udev->usb2_hw_lpm_enabled = enable;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USB_SUSPEND */
|
||||
|
||||
struct bus_type usb_bus_type = {
|
||||
|
||||
@@ -56,7 +56,7 @@ static ssize_t show_ep_wMaxPacketSize(struct device *dev,
|
||||
{
|
||||
struct ep_device *ep = to_ep_device(dev);
|
||||
return sprintf(buf, "%04x\n",
|
||||
le16_to_cpu(ep->desc->wMaxPacketSize) & 0x07ff);
|
||||
usb_endpoint_maxp(ep->desc) & 0x07ff);
|
||||
}
|
||||
static DEVICE_ATTR(wMaxPacketSize, S_IRUGO, show_ep_wMaxPacketSize, NULL);
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
||||
pci_set_master(dev);
|
||||
|
||||
retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
|
||||
retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
|
||||
if (retval != 0)
|
||||
goto unmap_registers;
|
||||
set_hs_companion(dev, hcd);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user