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:
+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 },
|
||||
|
||||
|
||||
@@ -132,20 +132,6 @@ static inline int is_usb_device_driver(struct device_driver *drv)
|
||||
for_devices;
|
||||
}
|
||||
|
||||
/* translate USB error codes to codes user space understands */
|
||||
static inline int usb_translate_errors(int error_code)
|
||||
{
|
||||
switch (error_code) {
|
||||
case 0:
|
||||
case -ENOMEM:
|
||||
case -ENODEV:
|
||||
return error_code;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* for labeling diagnostics */
|
||||
extern const char *usbcore_name;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user