USB fixes for 3.4-rc5
Here are a number of small USB fixes for 3.4-rc5. Nothing major, as before, some USB gadget fixes. There's a crash fix for a number of ASUS laptops on resume that had been reported by a number of different people. We think the fix might also pertain to other machines, as this was a BIOS bug, and they seem to travel to different models and manufacturers quite easily. Other than that, some other reported problems fixed as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iEYEABECAAYFAk+dZ7kACgkQMUfUDdst+ylxwACdFS4V69bnBi2nw9spEYClh+FB SToAoLUFsDiTDexIMIMWZkCyq+bqVLG+ =Pzvi -----END PGP SIGNATURE----- Merge tag 'usb-3.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg Kroah-Hartman: "Here are a number of small USB fixes for 3.4-rc5. Nothing major, as before, some USB gadget fixes. There's a crash fix for a number of ASUS laptops on resume that had been reported by a number of different people. We think the fix might also pertain to other machines, as this was a BIOS bug, and they seem to travel to different models and manufacturers quite easily. Other than that, some other reported problems fixed as well." * tag 'usb-3.4-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: usb: gadget: udc-core: fix incompatibility with dummy-hcd usb: gadget: udc-core: fix wrong call order USB: cdc-wdm: fix race leading leading to memory corruption USB: EHCI: fix crash during suspend on ASUS computers usb gadget: uvc: uvc_request_data::length field must be signed usb: gadget: dummy: do not call pullup() on udc_stop() usb: musb: davinci.c: add missing unregister usb: musb: drop __deprecated flag USB: gadget: storage gadgets send wrong error code for unknown commands usb: otg: gpio_vbus: Add otg transceiver events and notifiers
This commit is contained in:
commit
8d7d1adcd7
|
@ -157,8 +157,9 @@ static void wdm_out_callback(struct urb *urb)
|
|||
spin_lock(&desc->iuspin);
|
||||
desc->werr = urb->status;
|
||||
spin_unlock(&desc->iuspin);
|
||||
clear_bit(WDM_IN_USE, &desc->flags);
|
||||
kfree(desc->outbuf);
|
||||
desc->outbuf = NULL;
|
||||
clear_bit(WDM_IN_USE, &desc->flags);
|
||||
wake_up(&desc->wait);
|
||||
}
|
||||
|
||||
|
@ -338,7 +339,7 @@ static ssize_t wdm_write
|
|||
if (we < 0)
|
||||
return -EIO;
|
||||
|
||||
desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
|
||||
buf = kmalloc(count, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
rv = -ENOMEM;
|
||||
goto outnl;
|
||||
|
@ -406,10 +407,12 @@ static ssize_t wdm_write
|
|||
req->wIndex = desc->inum;
|
||||
req->wLength = cpu_to_le16(count);
|
||||
set_bit(WDM_IN_USE, &desc->flags);
|
||||
desc->outbuf = buf;
|
||||
|
||||
rv = usb_submit_urb(desc->command, GFP_KERNEL);
|
||||
if (rv < 0) {
|
||||
kfree(buf);
|
||||
desc->outbuf = NULL;
|
||||
clear_bit(WDM_IN_USE, &desc->flags);
|
||||
dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
|
||||
} else {
|
||||
|
|
|
@ -493,6 +493,15 @@ static int hcd_pci_suspend_noirq(struct device *dev)
|
|||
|
||||
pci_save_state(pci_dev);
|
||||
|
||||
/*
|
||||
* Some systems crash if an EHCI controller is in D3 during
|
||||
* a sleep transition. We have to leave such controllers in D0.
|
||||
*/
|
||||
if (hcd->broken_pci_sleep) {
|
||||
dev_dbg(dev, "Staying in PCI D0\n");
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* If the root hub is dead rather than suspended, disallow remote
|
||||
* wakeup. usb_hc_died() should ensure that both hosts are marked as
|
||||
* dying, so we only need to check the primary roothub.
|
||||
|
|
|
@ -927,7 +927,6 @@ static int dummy_udc_stop(struct usb_gadget *g,
|
|||
|
||||
dum->driver = NULL;
|
||||
|
||||
dummy_pullup(&dum->gadget, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -2189,7 +2189,7 @@ unknown_cmnd:
|
|||
common->data_size_from_cmnd = 0;
|
||||
sprintf(unknown, "Unknown x%02x", common->cmnd[0]);
|
||||
reply = check_command(common, common->cmnd_size,
|
||||
DATA_DIR_UNKNOWN, 0xff, 0, unknown);
|
||||
DATA_DIR_UNKNOWN, ~0, 0, unknown);
|
||||
if (reply == 0) {
|
||||
common->curlun->sense_data = SS_INVALID_COMMAND;
|
||||
reply = -EINVAL;
|
||||
|
|
|
@ -2579,7 +2579,7 @@ static int do_scsi_command(struct fsg_dev *fsg)
|
|||
fsg->data_size_from_cmnd = 0;
|
||||
sprintf(unknown, "Unknown x%02x", fsg->cmnd[0]);
|
||||
if ((reply = check_command(fsg, fsg->cmnd_size,
|
||||
DATA_DIR_UNKNOWN, 0xff, 0, unknown)) == 0) {
|
||||
DATA_DIR_UNKNOWN, ~0, 0, unknown)) == 0) {
|
||||
fsg->curlun->sense_data = SS_INVALID_COMMAND;
|
||||
reply = -EINVAL;
|
||||
}
|
||||
|
|
|
@ -263,8 +263,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
|
|||
|
||||
if (udc_is_newstyle(udc)) {
|
||||
udc->driver->disconnect(udc->gadget);
|
||||
udc->driver->unbind(udc->gadget);
|
||||
usb_gadget_disconnect(udc->gadget);
|
||||
udc->driver->unbind(udc->gadget);
|
||||
usb_gadget_udc_stop(udc->gadget, udc->driver);
|
||||
} else {
|
||||
usb_gadget_stop(udc->gadget, udc->driver);
|
||||
|
@ -415,9 +415,9 @@ static ssize_t usb_udc_softconn_store(struct device *dev,
|
|||
usb_gadget_udc_start(udc->gadget, udc->driver);
|
||||
usb_gadget_connect(udc->gadget);
|
||||
} else if (sysfs_streq(buf, "disconnect")) {
|
||||
usb_gadget_disconnect(udc->gadget);
|
||||
if (udc_is_newstyle(udc))
|
||||
usb_gadget_udc_stop(udc->gadget, udc->driver);
|
||||
usb_gadget_disconnect(udc->gadget);
|
||||
} else {
|
||||
dev_err(dev, "unsupported command '%s'\n", buf);
|
||||
return -EINVAL;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
struct uvc_request_data
|
||||
{
|
||||
unsigned int length;
|
||||
__s32 length;
|
||||
__u8 data[60];
|
||||
};
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ uvc_send_response(struct uvc_device *uvc, struct uvc_request_data *data)
|
|||
if (data->length < 0)
|
||||
return usb_ep_set_halt(cdev->gadget->ep0);
|
||||
|
||||
req->length = min(uvc->event_length, data->length);
|
||||
req->length = min_t(unsigned int, uvc->event_length, data->length);
|
||||
req->zero = data->length < uvc->event_length;
|
||||
req->dma = DMA_ADDR_INVALID;
|
||||
|
||||
|
|
|
@ -144,6 +144,14 @@ static int ehci_pci_setup(struct usb_hcd *hcd)
|
|||
hcd->has_tt = 1;
|
||||
tdi_reset(ehci);
|
||||
}
|
||||
if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) {
|
||||
/* EHCI #1 or #2 on 6 Series/C200 Series chipset */
|
||||
if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) {
|
||||
ehci_info(ehci, "broken D3 during system sleep on ASUS\n");
|
||||
hcd->broken_pci_sleep = 1;
|
||||
device_set_wakeup_capable(&pdev->dev, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PCI_VENDOR_ID_TDI:
|
||||
if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
|
||||
|
|
|
@ -386,7 +386,7 @@ static int davinci_musb_init(struct musb *musb)
|
|||
usb_nop_xceiv_register();
|
||||
musb->xceiv = usb_get_transceiver();
|
||||
if (!musb->xceiv)
|
||||
return -ENODEV;
|
||||
goto unregister;
|
||||
|
||||
musb->mregs += DAVINCI_BASE_OFFSET;
|
||||
|
||||
|
@ -444,6 +444,7 @@ static int davinci_musb_init(struct musb *musb)
|
|||
|
||||
fail:
|
||||
usb_put_transceiver(musb->xceiv);
|
||||
unregister:
|
||||
usb_nop_xceiv_unregister();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
|
|
@ -449,7 +449,7 @@ struct musb {
|
|||
* We added this flag to forcefully disable double
|
||||
* buffering until we get it working.
|
||||
*/
|
||||
unsigned double_buffer_not_ok:1 __deprecated;
|
||||
unsigned double_buffer_not_ok:1;
|
||||
|
||||
struct musb_hdrc_config *config;
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ static void gpio_vbus_work(struct work_struct *work)
|
|||
struct gpio_vbus_data *gpio_vbus =
|
||||
container_of(work, struct gpio_vbus_data, work);
|
||||
struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data;
|
||||
int gpio;
|
||||
int gpio, status;
|
||||
|
||||
if (!gpio_vbus->phy.otg->gadget)
|
||||
return;
|
||||
|
@ -108,7 +108,9 @@ static void gpio_vbus_work(struct work_struct *work)
|
|||
*/
|
||||
gpio = pdata->gpio_pullup;
|
||||
if (is_vbus_powered(pdata)) {
|
||||
status = USB_EVENT_VBUS;
|
||||
gpio_vbus->phy.state = OTG_STATE_B_PERIPHERAL;
|
||||
gpio_vbus->phy.last_event = status;
|
||||
usb_gadget_vbus_connect(gpio_vbus->phy.otg->gadget);
|
||||
|
||||
/* drawing a "unit load" is *always* OK, except for OTG */
|
||||
|
@ -117,6 +119,9 @@ static void gpio_vbus_work(struct work_struct *work)
|
|||
/* optionally enable D+ pullup */
|
||||
if (gpio_is_valid(gpio))
|
||||
gpio_set_value(gpio, !pdata->gpio_pullup_inverted);
|
||||
|
||||
atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
|
||||
status, gpio_vbus->phy.otg->gadget);
|
||||
} else {
|
||||
/* optionally disable D+ pullup */
|
||||
if (gpio_is_valid(gpio))
|
||||
|
@ -125,7 +130,12 @@ static void gpio_vbus_work(struct work_struct *work)
|
|||
set_vbus_draw(gpio_vbus, 0);
|
||||
|
||||
usb_gadget_vbus_disconnect(gpio_vbus->phy.otg->gadget);
|
||||
status = USB_EVENT_NONE;
|
||||
gpio_vbus->phy.state = OTG_STATE_B_IDLE;
|
||||
gpio_vbus->phy.last_event = status;
|
||||
|
||||
atomic_notifier_call_chain(&gpio_vbus->phy.notifier,
|
||||
status, gpio_vbus->phy.otg->gadget);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,6 +297,9 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
|
|||
irq, err);
|
||||
goto err_irq;
|
||||
}
|
||||
|
||||
ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier);
|
||||
|
||||
INIT_WORK(&gpio_vbus->work, gpio_vbus_work);
|
||||
|
||||
gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw");
|
||||
|
|
|
@ -126,6 +126,8 @@ struct usb_hcd {
|
|||
unsigned wireless:1; /* Wireless USB HCD */
|
||||
unsigned authorized_default:1;
|
||||
unsigned has_tt:1; /* Integrated TT in root hub */
|
||||
unsigned broken_pci_sleep:1; /* Don't put the
|
||||
controller in PCI-D3 for system sleep */
|
||||
|
||||
unsigned int irq; /* irq allocated */
|
||||
void __iomem *regs; /* device memory/io */
|
||||
|
|
Loading…
Reference in a new issue