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: (232 commits) USB: Add USB-ID for Multiplex RC serial adapter to cp210x.c xhci: Clean up 32-bit build warnings. USB: update documentation for usbmon usb: usb-storage doesn't support dynamic id currently, the patch disables the feature to fix an oops drivers/usb/class/cdc-acm.c: clear dangling pointer drivers/usb/dwc3/dwc3-pci.c: introduce missing kfree drivers/usb/host/isp1760-if.c: introduce missing kfree usb: option: add ZD Incorporated HSPA modem usb: ch9: fix up MaxStreams helper USB: usb-skeleton.c: cleanup open_count USB: usb-skeleton.c: fix open/disconnect race xhci: Properly handle COMP_2ND_BW_ERR USB: remove dead code from suspend/resume path USB: add quirk for another camera drivers: usb: wusbcore: Fix dependency for USB_WUSB xhci: Better debugging for critical host errors. xhci: Be less verbose during URB cancellation. xhci: Remove debugging about ring structure allocation. xhci: Remove debugging about toggling cycle bits. xhci: Remove debugging for individual transfers. ...
This commit is contained in:
@@ -119,6 +119,31 @@ Description:
|
||||
Write a 1 to force the device to disconnect
|
||||
(equivalent to unplugging a wired USB device).
|
||||
|
||||
What: /sys/bus/usb/drivers/.../new_id
|
||||
Date: October 2011
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
Writing a device ID to this file will attempt to
|
||||
dynamically add a new device ID to a USB device driver.
|
||||
This may allow the driver to support more hardware than
|
||||
was included in the driver's static device ID support
|
||||
table at compile time. The format for the device ID is:
|
||||
idVendor idProduct bInterfaceClass.
|
||||
The vendor ID and device ID fields are required, the
|
||||
interface class is optional.
|
||||
Upon successfully adding an ID, the driver will probe
|
||||
for the device and attempt to bind to it. For example:
|
||||
# echo "8086 10f5" > /sys/bus/usb/drivers/foo/new_id
|
||||
|
||||
What: /sys/bus/usb-serial/drivers/.../new_id
|
||||
Date: October 2011
|
||||
Contact: linux-usb@vger.kernel.org
|
||||
Description:
|
||||
For serial USB drivers, this attribute appears under the
|
||||
extra bus folder "usb-serial" in sysfs; apart from that
|
||||
difference, all descriptions from the entry
|
||||
"/sys/bus/usb/drivers/.../new_id" apply.
|
||||
|
||||
What: /sys/bus/usb/drivers/.../remove_id
|
||||
Date: November 2009
|
||||
Contact: CHENG Renquan <rqcheng@smu.edu.sg>
|
||||
|
||||
@@ -523,6 +523,20 @@ Why: In 3.0, we can now autodetect internal 3G device and already have
|
||||
information log when acer-wmi initial.
|
||||
Who: Lee, Chun-Yi <jlee@novell.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: /sys/devices/platform/_UDC_/udc/_UDC_/is_dualspeed file and
|
||||
is_dualspeed line in /sys/devices/platform/ci13xxx_*/udc/device file.
|
||||
When: 3.8
|
||||
Why: The is_dualspeed file is superseded by maximum_speed in the same
|
||||
directory and is_dualspeed line in device file is superseded by
|
||||
max_speed line in the same file.
|
||||
|
||||
The maximum_speed/max_speed specifies maximum speed supported by UDC.
|
||||
To check if dualspeeed is supported, check if the value is >= 3.
|
||||
Various possible speeds are defined in <linux/usb/ch9.h>.
|
||||
Who: Michal Nazarewicz <mina86@mina86.com>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: The XFS nodelaylog mount option
|
||||
|
||||
@@ -2637,6 +2637,10 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
||||
[USB] Start with the old device initialization
|
||||
scheme (default 0 = off).
|
||||
|
||||
usbcore.usbfs_memory_mb=
|
||||
[USB] Memory limit (in MB) for buffers allocated by
|
||||
usbfs (default = 16, 0 = max = 2047).
|
||||
|
||||
usbcore.use_both_schemes=
|
||||
[USB] Try the other device initialization scheme
|
||||
if the first one fails (default 1 = enabled).
|
||||
|
||||
@@ -47,10 +47,11 @@ This allows to filter away annoying devices that talk continuously.
|
||||
|
||||
2. Find which bus connects to the desired device
|
||||
|
||||
Run "cat /proc/bus/usb/devices", and find the T-line which corresponds to
|
||||
the device. Usually you do it by looking for the vendor string. If you have
|
||||
many similar devices, unplug one and compare two /proc/bus/usb/devices outputs.
|
||||
The T-line will have a bus number. Example:
|
||||
Run "cat /sys/kernel/debug/usb/devices", and find the T-line which corresponds
|
||||
to the device. Usually you do it by looking for the vendor string. If you have
|
||||
many similar devices, unplug one and compare the two
|
||||
/sys/kernel/debug/usb/devices outputs. The T-line will have a bus number.
|
||||
Example:
|
||||
|
||||
T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=12 MxCh= 0
|
||||
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
|
||||
@@ -58,7 +59,10 @@ P: Vendor=0557 ProdID=2004 Rev= 1.00
|
||||
S: Manufacturer=ATEN
|
||||
S: Product=UC100KM V2.00
|
||||
|
||||
Bus=03 means it's bus 3.
|
||||
"Bus=03" means it's bus 3. Alternatively, you can look at the output from
|
||||
"lsusb" and get the bus number from the appropriate line. Example:
|
||||
|
||||
Bus 003 Device 002: ID 0557:2004 ATEN UC100KM V2.00
|
||||
|
||||
3. Start 'cat'
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ static struct device *mmc_device;
|
||||
#define TUSB6010_GPIO_ENABLE 0
|
||||
#define TUSB6010_DMACHAN 0x3f
|
||||
|
||||
#ifdef CONFIG_USB_MUSB_TUSB6010
|
||||
#if defined(CONFIG_USB_MUSB_TUSB6010) || defined(CONFIG_USB_MUSB_TUSB6010_MODULE)
|
||||
/*
|
||||
* Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and
|
||||
* 1.5 V voltage regulators of PM companion chip. Companion chip will then
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <plat/nand.h>
|
||||
#include <plat/sdhci.h>
|
||||
#include <plat/udc.h>
|
||||
#include <linux/platform_data/s3c-hsudc.h>
|
||||
|
||||
#include <plat/regs-fb-v4.h>
|
||||
#include <plat/fb.h>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/platform_data/s3c-hsudc.h>
|
||||
|
||||
#include <asm/irq.h>
|
||||
#include <asm/pmu.h>
|
||||
|
||||
@@ -37,20 +37,7 @@ struct s3c2410_udc_mach_info {
|
||||
|
||||
extern void __init s3c24xx_udc_set_platdata(struct s3c2410_udc_mach_info *);
|
||||
|
||||
/**
|
||||
* s3c24xx_hsudc_platdata - Platform data for USB High-Speed gadget controller.
|
||||
* @epnum: Number of endpoints to be instantiated by the controller driver.
|
||||
* @gpio_init: Platform specific USB related GPIO initialization.
|
||||
* @gpio_uninit: Platform specific USB releted GPIO uninitialzation.
|
||||
*
|
||||
* Representation of platform data for the S3C24XX USB 2.0 High Speed gadget
|
||||
* controllers.
|
||||
*/
|
||||
struct s3c24xx_hsudc_platdata {
|
||||
unsigned int epnum;
|
||||
void (*gpio_init)(void);
|
||||
void (*gpio_uninit)(void);
|
||||
};
|
||||
struct s3c24xx_hsudc_platdata;
|
||||
|
||||
extern void __init s3c24xx_hsudc_set_platdata(struct s3c24xx_hsudc_platdata *pd);
|
||||
|
||||
|
||||
+6
-4
@@ -212,11 +212,13 @@ kvp_respond_to_host(char *key, char *value, int error)
|
||||
* The windows host expects the key/value pair to be encoded
|
||||
* in utf16.
|
||||
*/
|
||||
keylen = utf8s_to_utf16s(key_name, strlen(key_name),
|
||||
(wchar_t *)kvp_data->data.key);
|
||||
keylen = utf8s_to_utf16s(key_name, strlen(key_name), UTF16_HOST_ENDIAN,
|
||||
(wchar_t *) kvp_data->data.key,
|
||||
HV_KVP_EXCHANGE_MAX_KEY_SIZE / 2);
|
||||
kvp_data->data.key_size = 2*(keylen + 1); /* utf16 encoding */
|
||||
valuelen = utf8s_to_utf16s(value, strlen(value),
|
||||
(wchar_t *)kvp_data->data.value);
|
||||
valuelen = utf8s_to_utf16s(value, strlen(value), UTF16_HOST_ENDIAN,
|
||||
(wchar_t *) kvp_data->data.value,
|
||||
HV_KVP_EXCHANGE_MAX_VALUE_SIZE / 2);
|
||||
kvp_data->data.value_size = 2*(valuelen + 1); /* utf16 encoding */
|
||||
|
||||
kvp_data->data.value_type = REG_SZ; /* all our values are strings */
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
obj-$(CONFIG_USB) += core/
|
||||
|
||||
obj-$(CONFIG_USB_OTG_UTILS) += otg/
|
||||
|
||||
obj-$(CONFIG_USB_DWC3) += dwc3/
|
||||
|
||||
obj-$(CONFIG_USB_MON) += mon/
|
||||
@@ -51,7 +53,6 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
|
||||
|
||||
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
|
||||
|
||||
@@ -225,21 +225,10 @@ static struct platform_driver c67x00_driver = {
|
||||
.name = "c67x00",
|
||||
},
|
||||
};
|
||||
MODULE_ALIAS("platform:c67x00");
|
||||
|
||||
static int __init c67x00_init(void)
|
||||
{
|
||||
return platform_driver_register(&c67x00_driver);
|
||||
}
|
||||
|
||||
static void __exit c67x00_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&c67x00_driver);
|
||||
}
|
||||
|
||||
module_init(c67x00_init);
|
||||
module_exit(c67x00_exit);
|
||||
module_platform_driver(c67x00_driver);
|
||||
|
||||
MODULE_AUTHOR("Peter Korsgaard, Jan Veldeman, Grant Likely");
|
||||
MODULE_DESCRIPTION("Cypress C67X00 USB Controller Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:c67x00");
|
||||
|
||||
@@ -271,7 +271,6 @@ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg)
|
||||
if (int_status & SOFEOP_FLG(sie->sie_num)) {
|
||||
c67x00_ll_usb_clear_status(sie, SOF_EOP_IRQ_FLG);
|
||||
c67x00_sched_kick(c67x00);
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+194
-148
File diff suppressed because it is too large
Load Diff
@@ -101,6 +101,7 @@ struct acm {
|
||||
int transmitting;
|
||||
spinlock_t write_lock;
|
||||
struct mutex mutex;
|
||||
bool disconnected;
|
||||
struct usb_cdc_line_coding line; /* bits, stop, parity */
|
||||
struct work_struct work; /* work queue entry for line discipline waking up */
|
||||
unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
|
||||
|
||||
+125
-64
@@ -86,6 +86,7 @@ struct async {
|
||||
void __user *userbuffer;
|
||||
void __user *userurb;
|
||||
struct urb *urb;
|
||||
unsigned int mem_usage;
|
||||
int status;
|
||||
u32 secid;
|
||||
u8 bulk_addr;
|
||||
@@ -108,8 +109,44 @@ enum snoop_when {
|
||||
|
||||
#define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0)
|
||||
|
||||
#define MAX_USBFS_BUFFER_SIZE 16384
|
||||
/* Limit on the total amount of memory we can allocate for transfers */
|
||||
static unsigned usbfs_memory_mb = 16;
|
||||
module_param(usbfs_memory_mb, uint, 0644);
|
||||
MODULE_PARM_DESC(usbfs_memory_mb,
|
||||
"maximum MB allowed for usbfs buffers (0 = no limit)");
|
||||
|
||||
/* Hard limit, necessary to avoid aithmetic overflow */
|
||||
#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000)
|
||||
|
||||
static atomic_t usbfs_memory_usage; /* Total memory currently allocated */
|
||||
|
||||
/* Check whether it's okay to allocate more memory for a transfer */
|
||||
static int usbfs_increase_memory_usage(unsigned amount)
|
||||
{
|
||||
unsigned lim;
|
||||
|
||||
/*
|
||||
* Convert usbfs_memory_mb to bytes, avoiding overflows.
|
||||
* 0 means use the hard limit (effectively unlimited).
|
||||
*/
|
||||
lim = ACCESS_ONCE(usbfs_memory_mb);
|
||||
if (lim == 0 || lim > (USBFS_XFER_MAX >> 20))
|
||||
lim = USBFS_XFER_MAX;
|
||||
else
|
||||
lim <<= 20;
|
||||
|
||||
atomic_add(amount, &usbfs_memory_usage);
|
||||
if (atomic_read(&usbfs_memory_usage) <= lim)
|
||||
return 0;
|
||||
atomic_sub(amount, &usbfs_memory_usage);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Memory for a transfer is being deallocated */
|
||||
static void usbfs_decrease_memory_usage(unsigned amount)
|
||||
{
|
||||
atomic_sub(amount, &usbfs_memory_usage);
|
||||
}
|
||||
|
||||
static int connected(struct dev_state *ps)
|
||||
{
|
||||
@@ -249,10 +286,12 @@ static struct async *alloc_async(unsigned int numisoframes)
|
||||
static void free_async(struct async *as)
|
||||
{
|
||||
put_pid(as->pid);
|
||||
put_cred(as->cred);
|
||||
if (as->cred)
|
||||
put_cred(as->cred);
|
||||
kfree(as->urb->transfer_buffer);
|
||||
kfree(as->urb->setup_packet);
|
||||
usb_free_urb(as->urb);
|
||||
usbfs_decrease_memory_usage(as->mem_usage);
|
||||
kfree(as);
|
||||
}
|
||||
|
||||
@@ -792,9 +831,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
wLength = ctrl.wLength; /* To suppress 64k PAGE_SIZE warning */
|
||||
if (wLength > PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
ret = usbfs_increase_memory_usage(PAGE_SIZE + sizeof(struct urb) +
|
||||
sizeof(struct usb_ctrlrequest));
|
||||
if (ret)
|
||||
return ret;
|
||||
tbuf = (unsigned char *)__get_free_page(GFP_KERNEL);
|
||||
if (!tbuf)
|
||||
return -ENOMEM;
|
||||
if (!tbuf) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
tmo = ctrl.timeout;
|
||||
snoop(&dev->dev, "control urb: bRequestType=%02x "
|
||||
"bRequest=%02x wValue=%04x "
|
||||
@@ -806,8 +851,8 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
if (ctrl.bRequestType & 0x80) {
|
||||
if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data,
|
||||
ctrl.wLength)) {
|
||||
free_page((unsigned long)tbuf);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
pipe = usb_rcvctrlpipe(dev, 0);
|
||||
snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT, NULL, 0);
|
||||
@@ -821,15 +866,15 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
tbuf, max(i, 0));
|
||||
if ((i > 0) && ctrl.wLength) {
|
||||
if (copy_to_user(ctrl.data, tbuf, i)) {
|
||||
free_page((unsigned long)tbuf);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ctrl.wLength) {
|
||||
if (copy_from_user(tbuf, ctrl.data, ctrl.wLength)) {
|
||||
free_page((unsigned long)tbuf);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
pipe = usb_sndctrlpipe(dev, 0);
|
||||
@@ -843,14 +888,18 @@ static int proc_control(struct dev_state *ps, void __user *arg)
|
||||
usb_lock_device(dev);
|
||||
snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE, NULL, 0);
|
||||
}
|
||||
free_page((unsigned long)tbuf);
|
||||
if (i < 0 && i != -EPIPE) {
|
||||
dev_printk(KERN_DEBUG, &dev->dev, "usbfs: USBDEVFS_CONTROL "
|
||||
"failed cmd %s rqt %u rq %u len %u ret %d\n",
|
||||
current->comm, ctrl.bRequestType, ctrl.bRequest,
|
||||
ctrl.wLength, i);
|
||||
}
|
||||
return i;
|
||||
ret = i;
|
||||
done:
|
||||
free_page((unsigned long) tbuf);
|
||||
usbfs_decrease_memory_usage(PAGE_SIZE + sizeof(struct urb) +
|
||||
sizeof(struct usb_ctrlrequest));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
@@ -877,15 +926,20 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
if (!usb_maxpacket(dev, pipe, !(bulk.ep & USB_DIR_IN)))
|
||||
return -EINVAL;
|
||||
len1 = bulk.len;
|
||||
if (len1 > MAX_USBFS_BUFFER_SIZE)
|
||||
if (len1 >= USBFS_XFER_MAX)
|
||||
return -EINVAL;
|
||||
if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
|
||||
if (ret)
|
||||
return ret;
|
||||
if (!(tbuf = kmalloc(len1, GFP_KERNEL))) {
|
||||
ret = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
tmo = bulk.timeout;
|
||||
if (bulk.ep & 0x80) {
|
||||
if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
|
||||
kfree(tbuf);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto done;
|
||||
}
|
||||
snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, NULL, 0);
|
||||
|
||||
@@ -896,15 +950,15 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
|
||||
if (!i && len2) {
|
||||
if (copy_to_user(bulk.data, tbuf, len2)) {
|
||||
kfree(tbuf);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (len1) {
|
||||
if (copy_from_user(tbuf, bulk.data, len1)) {
|
||||
kfree(tbuf);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT, tbuf, len1);
|
||||
@@ -914,10 +968,11 @@ static int proc_bulk(struct dev_state *ps, void __user *arg)
|
||||
usb_lock_device(dev);
|
||||
snoop_urb(dev, NULL, pipe, len2, i, COMPLETE, NULL, 0);
|
||||
}
|
||||
ret = (i < 0 ? i : len2);
|
||||
done:
|
||||
kfree(tbuf);
|
||||
if (i < 0)
|
||||
return i;
|
||||
return len2;
|
||||
usbfs_decrease_memory_usage(len1 + sizeof(struct urb));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int proc_resetep(struct dev_state *ps, void __user *arg)
|
||||
@@ -1062,7 +1117,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
{
|
||||
struct usbdevfs_iso_packet_desc *isopkt = NULL;
|
||||
struct usb_host_endpoint *ep;
|
||||
struct async *as;
|
||||
struct async *as = NULL;
|
||||
struct usb_ctrlrequest *dr = NULL;
|
||||
unsigned int u, totlen, isofrmlen;
|
||||
int ret, ifnum = -1;
|
||||
@@ -1095,32 +1150,30 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
}
|
||||
if (!ep)
|
||||
return -ENOENT;
|
||||
|
||||
u = 0;
|
||||
switch(uurb->type) {
|
||||
case USBDEVFS_URB_TYPE_CONTROL:
|
||||
if (!usb_endpoint_xfer_control(&ep->desc))
|
||||
return -EINVAL;
|
||||
/* min 8 byte setup packet,
|
||||
* max 8 byte setup plus an arbitrary data stage */
|
||||
if (uurb->buffer_length < 8 ||
|
||||
uurb->buffer_length > (8 + MAX_USBFS_BUFFER_SIZE))
|
||||
/* min 8 byte setup packet */
|
||||
if (uurb->buffer_length < 8)
|
||||
return -EINVAL;
|
||||
dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
|
||||
if (!dr)
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(dr, uurb->buffer, 8)) {
|
||||
kfree(dr);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
|
||||
kfree(dr);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
ret = check_ctrlrecip(ps, dr->bRequestType, dr->bRequest,
|
||||
le16_to_cpup(&dr->wIndex));
|
||||
if (ret) {
|
||||
kfree(dr);
|
||||
return ret;
|
||||
}
|
||||
if (ret)
|
||||
goto error;
|
||||
uurb->number_of_packets = 0;
|
||||
uurb->buffer_length = le16_to_cpup(&dr->wLength);
|
||||
uurb->buffer += 8;
|
||||
@@ -1138,6 +1191,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
__le16_to_cpup(&dr->wValue),
|
||||
__le16_to_cpup(&dr->wIndex),
|
||||
__le16_to_cpup(&dr->wLength));
|
||||
u = sizeof(struct usb_ctrlrequest);
|
||||
break;
|
||||
|
||||
case USBDEVFS_URB_TYPE_BULK:
|
||||
@@ -1151,8 +1205,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
goto interrupt_urb;
|
||||
}
|
||||
uurb->number_of_packets = 0;
|
||||
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case USBDEVFS_URB_TYPE_INTERRUPT:
|
||||
@@ -1160,8 +1212,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
return -EINVAL;
|
||||
interrupt_urb:
|
||||
uurb->number_of_packets = 0;
|
||||
if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
|
||||
return -EINVAL;
|
||||
break;
|
||||
|
||||
case USBDEVFS_URB_TYPE_ISO:
|
||||
@@ -1176,50 +1226,53 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
|
||||
return -ENOMEM;
|
||||
if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
|
||||
kfree(isopkt);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
for (totlen = u = 0; u < uurb->number_of_packets; u++) {
|
||||
/* arbitrary limit,
|
||||
* sufficient for USB 2.0 high-bandwidth iso */
|
||||
if (isopkt[u].length > 8192) {
|
||||
kfree(isopkt);
|
||||
return -EINVAL;
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
totlen += isopkt[u].length;
|
||||
}
|
||||
/* 3072 * 64 microframes */
|
||||
if (totlen > 196608) {
|
||||
kfree(isopkt);
|
||||
return -EINVAL;
|
||||
}
|
||||
u *= sizeof(struct usb_iso_packet_descriptor);
|
||||
uurb->buffer_length = totlen;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (uurb->buffer_length >= USBFS_XFER_MAX) {
|
||||
ret = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
if (uurb->buffer_length > 0 &&
|
||||
!access_ok(is_in ? VERIFY_WRITE : VERIFY_READ,
|
||||
uurb->buffer, uurb->buffer_length)) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
as = alloc_async(uurb->number_of_packets);
|
||||
if (!as) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
u += sizeof(struct async) + sizeof(struct urb) + uurb->buffer_length;
|
||||
ret = usbfs_increase_memory_usage(u);
|
||||
if (ret)
|
||||
goto error;
|
||||
as->mem_usage = u;
|
||||
|
||||
if (uurb->buffer_length > 0) {
|
||||
as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
|
||||
GFP_KERNEL);
|
||||
if (!as->urb->transfer_buffer) {
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
free_async(as);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
/* Isochronous input data may end up being discontiguous
|
||||
* if some of the packets are short. Clear the buffer so
|
||||
@@ -1253,6 +1306,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
|
||||
as->urb->transfer_buffer_length = uurb->buffer_length;
|
||||
as->urb->setup_packet = (unsigned char *)dr;
|
||||
dr = NULL;
|
||||
as->urb->start_frame = uurb->start_frame;
|
||||
as->urb->number_of_packets = uurb->number_of_packets;
|
||||
if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
|
||||
@@ -1268,6 +1322,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
totlen += isopkt[u].length;
|
||||
}
|
||||
kfree(isopkt);
|
||||
isopkt = NULL;
|
||||
as->ps = ps;
|
||||
as->userurb = arg;
|
||||
if (is_in && uurb->buffer_length > 0)
|
||||
@@ -1282,8 +1337,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
if (!is_in && uurb->buffer_length > 0) {
|
||||
if (copy_from_user(as->urb->transfer_buffer, uurb->buffer,
|
||||
uurb->buffer_length)) {
|
||||
free_async(as);
|
||||
return -EFAULT;
|
||||
ret = -EFAULT;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
snoop_urb(ps->dev, as->userurb, as->urb->pipe,
|
||||
@@ -1329,10 +1384,16 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
|
||||
snoop_urb(ps->dev, as->userurb, as->urb->pipe,
|
||||
0, ret, COMPLETE, NULL, 0);
|
||||
async_removepending(as);
|
||||
free_async(as);
|
||||
return ret;
|
||||
goto error;
|
||||
}
|
||||
return 0;
|
||||
|
||||
error:
|
||||
kfree(isopkt);
|
||||
kfree(dr);
|
||||
if (as)
|
||||
free_async(as);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int proc_submiturb(struct dev_state *ps, void __user *arg)
|
||||
|
||||
+14
-22
@@ -45,10 +45,12 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
struct usb_dynid *dynid;
|
||||
u32 idVendor = 0;
|
||||
u32 idProduct = 0;
|
||||
unsigned int bInterfaceClass = 0;
|
||||
int fields = 0;
|
||||
int retval = 0;
|
||||
|
||||
fields = sscanf(buf, "%x %x", &idVendor, &idProduct);
|
||||
fields = sscanf(buf, "%x %x %x", &idVendor, &idProduct,
|
||||
&bInterfaceClass);
|
||||
if (fields < 2)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -60,6 +62,10 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
|
||||
dynid->id.idVendor = idVendor;
|
||||
dynid->id.idProduct = idProduct;
|
||||
dynid->id.match_flags = USB_DEVICE_ID_MATCH_DEVICE;
|
||||
if (fields == 3) {
|
||||
dynid->id.bInterfaceClass = (u8)bInterfaceClass;
|
||||
dynid->id.match_flags |= USB_DEVICE_ID_MATCH_INT_CLASS;
|
||||
}
|
||||
|
||||
spin_lock(&dynids->lock);
|
||||
list_add_tail(&dynid->node, &dynids->list);
|
||||
@@ -1073,17 +1079,10 @@ static int usb_suspend_interface(struct usb_device *udev,
|
||||
goto done;
|
||||
driver = to_usb_driver(intf->dev.driver);
|
||||
|
||||
if (driver->suspend) {
|
||||
status = driver->suspend(intf, msg);
|
||||
if (status && !PMSG_IS_AUTO(msg))
|
||||
dev_err(&intf->dev, "%s error %d\n",
|
||||
"suspend", status);
|
||||
} else {
|
||||
/* Later we will unbind the driver and reprobe */
|
||||
intf->needs_binding = 1;
|
||||
dev_warn(&intf->dev, "no %s for driver %s?\n",
|
||||
"suspend", driver->name);
|
||||
}
|
||||
/* at this time we know the driver supports suspend */
|
||||
status = driver->suspend(intf, msg);
|
||||
if (status && !PMSG_IS_AUTO(msg))
|
||||
dev_err(&intf->dev, "suspend error %d\n", status);
|
||||
|
||||
done:
|
||||
dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status);
|
||||
@@ -1132,16 +1131,9 @@ static int usb_resume_interface(struct usb_device *udev,
|
||||
"reset_resume", driver->name);
|
||||
}
|
||||
} else {
|
||||
if (driver->resume) {
|
||||
status = driver->resume(intf);
|
||||
if (status)
|
||||
dev_err(&intf->dev, "%s error %d\n",
|
||||
"resume", status);
|
||||
} else {
|
||||
intf->needs_binding = 1;
|
||||
dev_warn(&intf->dev, "no %s for driver %s?\n",
|
||||
"resume", driver->name);
|
||||
}
|
||||
status = driver->resume(intf);
|
||||
if (status)
|
||||
dev_err(&intf->dev, "resume error %d\n", status);
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
@@ -453,10 +453,6 @@ static int resume_common(struct device *dev, int event)
|
||||
|
||||
pci_set_master(pci_dev);
|
||||
|
||||
clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
|
||||
if (hcd->shared_hcd)
|
||||
clear_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
|
||||
|
||||
if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
|
||||
if (event != PM_EVENT_AUTO_RESUME)
|
||||
wait_for_companions(pci_dev, hcd);
|
||||
|
||||
+6
-25
@@ -658,7 +658,7 @@ error:
|
||||
len > offsetof(struct usb_device_descriptor,
|
||||
bDeviceProtocol))
|
||||
((struct usb_device_descriptor *) ubuf)->
|
||||
bDeviceProtocol = 1;
|
||||
bDeviceProtocol = USB_HUB_PR_HS_SINGLE_TT;
|
||||
}
|
||||
|
||||
/* any errors get returned through the urb completion */
|
||||
@@ -1168,20 +1168,6 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,
|
||||
if (urb->unlinked)
|
||||
return -EBUSY;
|
||||
urb->unlinked = status;
|
||||
|
||||
/* IRQ setup can easily be broken so that USB controllers
|
||||
* never get completion IRQs ... maybe even the ones we need to
|
||||
* finish unlinking the initial failed usb_set_address()
|
||||
* or device descriptor fetch.
|
||||
*/
|
||||
if (!HCD_SAW_IRQ(hcd) && !is_root_hub(urb->dev)) {
|
||||
dev_warn(hcd->self.controller, "Unlink after no-IRQ? "
|
||||
"Controller is probably using the wrong IRQ.\n");
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
|
||||
if (hcd->shared_hcd)
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(usb_hcd_check_unlink_urb);
|
||||
@@ -1412,11 +1398,10 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
|
||||
ret = -EAGAIN;
|
||||
else
|
||||
urb->transfer_flags |= URB_DMA_MAP_SG;
|
||||
if (n != urb->num_sgs) {
|
||||
urb->num_sgs = n;
|
||||
urb->num_mapped_sgs = n;
|
||||
if (n != urb->num_sgs)
|
||||
urb->transfer_flags |=
|
||||
URB_DMA_SG_COMBINED;
|
||||
}
|
||||
} else if (urb->sg) {
|
||||
struct scatterlist *sg = urb->sg;
|
||||
urb->transfer_dma = dma_map_page(
|
||||
@@ -2148,16 +2133,12 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
|
||||
*/
|
||||
local_irq_save(flags);
|
||||
|
||||
if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) {
|
||||
if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
|
||||
rc = IRQ_NONE;
|
||||
} else if (hcd->driver->irq(hcd) == IRQ_NONE) {
|
||||
else if (hcd->driver->irq(hcd) == IRQ_NONE)
|
||||
rc = IRQ_NONE;
|
||||
} else {
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
|
||||
if (hcd->shared_hcd)
|
||||
set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
|
||||
else
|
||||
rc = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
return rc;
|
||||
|
||||
+44
-45
@@ -84,7 +84,7 @@ struct usb_hub {
|
||||
|
||||
static inline int hub_is_superspeed(struct usb_device *hdev)
|
||||
{
|
||||
return (hdev->descriptor.bDeviceProtocol == 3);
|
||||
return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS);
|
||||
}
|
||||
|
||||
/* Protect struct usb_device->state and ->children members
|
||||
@@ -1041,58 +1041,58 @@ static int hub_configure(struct usb_hub *hub,
|
||||
dev_dbg(hub_dev, "standalone hub\n");
|
||||
|
||||
switch (wHubCharacteristics & HUB_CHAR_LPSM) {
|
||||
case 0x00:
|
||||
dev_dbg(hub_dev, "ganged power switching\n");
|
||||
break;
|
||||
case 0x01:
|
||||
dev_dbg(hub_dev, "individual port power switching\n");
|
||||
break;
|
||||
case 0x02:
|
||||
case 0x03:
|
||||
dev_dbg(hub_dev, "no power switching (usb 1.0)\n");
|
||||
break;
|
||||
case HUB_CHAR_COMMON_LPSM:
|
||||
dev_dbg(hub_dev, "ganged power switching\n");
|
||||
break;
|
||||
case HUB_CHAR_INDV_PORT_LPSM:
|
||||
dev_dbg(hub_dev, "individual port power switching\n");
|
||||
break;
|
||||
case HUB_CHAR_NO_LPSM:
|
||||
case HUB_CHAR_LPSM:
|
||||
dev_dbg(hub_dev, "no power switching (usb 1.0)\n");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (wHubCharacteristics & HUB_CHAR_OCPM) {
|
||||
case 0x00:
|
||||
dev_dbg(hub_dev, "global over-current protection\n");
|
||||
break;
|
||||
case 0x08:
|
||||
dev_dbg(hub_dev, "individual port over-current protection\n");
|
||||
break;
|
||||
case 0x10:
|
||||
case 0x18:
|
||||
dev_dbg(hub_dev, "no over-current protection\n");
|
||||
break;
|
||||
case HUB_CHAR_COMMON_OCPM:
|
||||
dev_dbg(hub_dev, "global over-current protection\n");
|
||||
break;
|
||||
case HUB_CHAR_INDV_PORT_OCPM:
|
||||
dev_dbg(hub_dev, "individual port over-current protection\n");
|
||||
break;
|
||||
case HUB_CHAR_NO_OCPM:
|
||||
case HUB_CHAR_OCPM:
|
||||
dev_dbg(hub_dev, "no over-current protection\n");
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_init (&hub->tt.lock);
|
||||
INIT_LIST_HEAD (&hub->tt.clear_list);
|
||||
INIT_WORK(&hub->tt.clear_work, hub_tt_work);
|
||||
switch (hdev->descriptor.bDeviceProtocol) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
dev_dbg(hub_dev, "Single TT\n");
|
||||
hub->tt.hub = hdev;
|
||||
break;
|
||||
case 2:
|
||||
ret = usb_set_interface(hdev, 0, 1);
|
||||
if (ret == 0) {
|
||||
dev_dbg(hub_dev, "TT per port\n");
|
||||
hub->tt.multi = 1;
|
||||
} else
|
||||
dev_err(hub_dev, "Using single TT (err %d)\n",
|
||||
ret);
|
||||
hub->tt.hub = hdev;
|
||||
break;
|
||||
case 3:
|
||||
/* USB 3.0 hubs don't have a TT */
|
||||
break;
|
||||
default:
|
||||
dev_dbg(hub_dev, "Unrecognized hub protocol %d\n",
|
||||
hdev->descriptor.bDeviceProtocol);
|
||||
break;
|
||||
case USB_HUB_PR_FS:
|
||||
break;
|
||||
case USB_HUB_PR_HS_SINGLE_TT:
|
||||
dev_dbg(hub_dev, "Single TT\n");
|
||||
hub->tt.hub = hdev;
|
||||
break;
|
||||
case USB_HUB_PR_HS_MULTI_TT:
|
||||
ret = usb_set_interface(hdev, 0, 1);
|
||||
if (ret == 0) {
|
||||
dev_dbg(hub_dev, "TT per port\n");
|
||||
hub->tt.multi = 1;
|
||||
} else
|
||||
dev_err(hub_dev, "Using single TT (err %d)\n",
|
||||
ret);
|
||||
hub->tt.hub = hdev;
|
||||
break;
|
||||
case USB_HUB_PR_SS:
|
||||
/* USB 3.0 hubs don't have a TT */
|
||||
break;
|
||||
default:
|
||||
dev_dbg(hub_dev, "Unrecognized hub protocol %d\n",
|
||||
hdev->descriptor.bDeviceProtocol);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Note 8 FS bit times == (8 bits / 12000000 bps) ~= 666ns */
|
||||
@@ -1360,7 +1360,6 @@ descriptor_error:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* No BKL needed */
|
||||
static int
|
||||
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
|
||||
{
|
||||
|
||||
@@ -117,9 +117,12 @@ static const struct usb_device_id usb_quirk_list[] = {
|
||||
{ USB_DEVICE(0x06a3, 0x0006), .driver_info =
|
||||
USB_QUIRK_CONFIG_INTF_STRINGS },
|
||||
|
||||
/* Guillemot Webcam Hercules Dualpix Exchange*/
|
||||
/* Guillemot Webcam Hercules Dualpix Exchange (2nd ID) */
|
||||
{ USB_DEVICE(0x06f8, 0x0804), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* Guillemot Webcam Hercules Dualpix Exchange*/
|
||||
{ USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
/* M-Systems Flash Disk Pioneers */
|
||||
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user