diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-03-14 10:05:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-03-14 10:05:59 -0700 |
commit | 3032f8c504d2b15d58e4c96060a96b47e215573c (patch) | |
tree | bd059f56005014a1deb10dea44fce4d6e5684f1a | |
parent | 6560ca4a0f7b1faacf0480ed0bdb8cd6b6cd2cc8 (diff) | |
parent | 94e46a4f2d5eb14059e42f313c098d4854847376 (diff) | |
download | linux-3032f8c504d2b15d58e4c96060a96b47e215573c.tar.bz2 |
Merge tag 'usb-4.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB fixes from Greg KH:
"Here are a small clump of USB fixes for 4.16-rc6.
Nothing major, just a number of fixes in lots of different drivers, as
well as a PHY driver fix that snuck into this tree. Full details are
in the shortlog.
All of these have been in linux-next with no reported issues"
* tag 'usb-4.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (22 commits)
usb: musb: Fix external abort in musb_remove on omap2430
phy: qcom-ufs: add MODULE_LICENSE tag
usb: typec: tcpm: fusb302: Do not log an error on -EPROBE_DEFER
USB: OHCI: Fix NULL dereference in HCDs using HCD_LOCAL_MEM
usbip: vudc: fix null pointer dereference on udc->lock
xhci: Fix front USB ports on ASUS PRIME B350M-A
usb: host: xhci-plat: revert "usb: host: xhci-plat: enable clk in resume timing"
usb: usbmon: Read text within supplied buffer size
usb: host: xhci-rcar: add support for r8a77965
USB: storage: Add JMicron bridge 152d:2567 to unusual_devs.h
usb: xhci: dbc: Fix lockdep warning
xhci: fix endpoint context tracer output
Revert "typec: tcpm: Only request matching pdos"
usb: musb: call pm_runtime_{get,put}_sync before reading vbus registers
usb: quirks: add control message delay for 1b1c:1b20
uas: fix comparison for error code
usb: gadget: udc: renesas_usb3: add binging for r8a77965
usb: renesas_usbhs: add binding for r8a77965
usb: dwc2: fix STM32F7 USB OTG HS compatible
dt-bindings: usb: fix the STM32F7 DWC2 OTG HS core binding
...
26 files changed, 211 insertions, 218 deletions
diff --git a/Documentation/devicetree/bindings/usb/dwc2.txt b/Documentation/devicetree/bindings/usb/dwc2.txt index e64d903bcbe8..46da5f184460 100644 --- a/Documentation/devicetree/bindings/usb/dwc2.txt +++ b/Documentation/devicetree/bindings/usb/dwc2.txt @@ -19,7 +19,7 @@ Required properties: configured in FS mode; - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs configured in HS mode; - - "st,stm32f7xx-hsotg": The DWC2 USB HS controller instance in STM32F7xx SoCs + - "st,stm32f7-hsotg": The DWC2 USB HS controller instance in STM32F7 SoCs configured in HS mode; - reg : Should contain 1 register range (address and length) - interrupts : Should contain 1 interrupt diff --git a/Documentation/devicetree/bindings/usb/renesas_usb3.txt b/Documentation/devicetree/bindings/usb/renesas_usb3.txt index 87a45e2f9b7f..2c071bb5801e 100644 --- a/Documentation/devicetree/bindings/usb/renesas_usb3.txt +++ b/Documentation/devicetree/bindings/usb/renesas_usb3.txt @@ -4,6 +4,7 @@ Required properties: - compatible: Must contain one of the following: - "renesas,r8a7795-usb3-peri" - "renesas,r8a7796-usb3-peri" + - "renesas,r8a77965-usb3-peri" - "renesas,rcar-gen3-usb3-peri" for a generic R-Car Gen3 compatible device diff --git a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt index d060172f1529..43960faf5a88 100644 --- a/Documentation/devicetree/bindings/usb/renesas_usbhs.txt +++ b/Documentation/devicetree/bindings/usb/renesas_usbhs.txt @@ -12,6 +12,7 @@ Required properties: - "renesas,usbhs-r8a7794" for r8a7794 (R-Car E2) compatible device - "renesas,usbhs-r8a7795" for r8a7795 (R-Car H3) compatible device - "renesas,usbhs-r8a7796" for r8a7796 (R-Car M3-W) compatible device + - "renesas,usbhs-r8a77965" for r8a77965 (R-Car M3-N) compatible device - "renesas,usbhs-r8a77995" for r8a77995 (R-Car D3) compatible device - "renesas,usbhs-r7s72100" for r7s72100 (RZ/A1) compatible device - "renesas,rcar-gen2-usbhs" for R-Car Gen2 or RZ/G1 compatible devices diff --git a/Documentation/devicetree/bindings/usb/usb-xhci.txt b/Documentation/devicetree/bindings/usb/usb-xhci.txt index e2ea59bbca93..1651483a7048 100644 --- a/Documentation/devicetree/bindings/usb/usb-xhci.txt +++ b/Documentation/devicetree/bindings/usb/usb-xhci.txt @@ -13,6 +13,7 @@ Required properties: - "renesas,xhci-r8a7793" for r8a7793 SoC - "renesas,xhci-r8a7795" for r8a7795 SoC - "renesas,xhci-r8a7796" for r8a7796 SoC + - "renesas,xhci-r8a77965" for r8a77965 SoC - "renesas,rcar-gen2-xhci" for a generic R-Car Gen2 or RZ/G1 compatible device - "renesas,rcar-gen3-xhci" for a generic R-Car Gen3 compatible device diff --git a/drivers/phy/qualcomm/phy-qcom-ufs.c b/drivers/phy/qualcomm/phy-qcom-ufs.c index c5ff4525edef..c5493ea51282 100644 --- a/drivers/phy/qualcomm/phy-qcom-ufs.c +++ b/drivers/phy/qualcomm/phy-qcom-ufs.c @@ -675,3 +675,8 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy) return 0; } EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off); + +MODULE_AUTHOR("Yaniv Gardi <ygardi@codeaurora.org>"); +MODULE_AUTHOR("Vivek Gautam <vivek.gautam@codeaurora.org>"); +MODULE_DESCRIPTION("Universal Flash Storage (UFS) QCOM PHY"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index c64cf6c4a83d..0c11d40a12bc 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -151,6 +151,10 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); + /* Linger a bit, prior to the next control message. */ + if (dev->quirks & USB_QUIRK_DELAY_CTRL_MSG) + msleep(200); + kfree(dr); return ret; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f4a548471f0f..54b019e267c5 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -230,7 +230,8 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, /* Corsair Strafe RGB */ - { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, + { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT | + USB_QUIRK_DELAY_CTRL_MSG }, /* Corsair K70 LUX */ { USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT }, diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c index 03fd20f0b496..c4a47496d2fb 100644 --- a/drivers/usb/dwc2/params.c +++ b/drivers/usb/dwc2/params.c @@ -137,7 +137,7 @@ static void dwc2_set_stm32f4x9_fsotg_params(struct dwc2_hsotg *hsotg) p->activate_stm_fs_transceiver = true; } -static void dwc2_set_stm32f7xx_hsotg_params(struct dwc2_hsotg *hsotg) +static void dwc2_set_stm32f7_hsotg_params(struct dwc2_hsotg *hsotg) { struct dwc2_core_params *p = &hsotg->params; @@ -164,8 +164,8 @@ const struct of_device_id dwc2_of_match_table[] = { { .compatible = "st,stm32f4x9-fsotg", .data = dwc2_set_stm32f4x9_fsotg_params }, { .compatible = "st,stm32f4x9-hsotg" }, - { .compatible = "st,stm32f7xx-hsotg", - .data = dwc2_set_stm32f7xx_hsotg_params }, + { .compatible = "st,stm32f7-hsotg", + .data = dwc2_set_stm32f7_hsotg_params }, {}, }; MODULE_DEVICE_TABLE(of, dwc2_of_match_table); diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index f1d838a4acd6..e94bf91cc58a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -175,7 +175,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode) dwc->desired_dr_role = mode; spin_unlock_irqrestore(&dwc->lock, flags); - queue_work(system_power_efficient_wq, &dwc->drd_work); + queue_work(system_freezable_wq, &dwc->drd_work); } u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index c2592d883f67..d2428a9e8900 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -1538,7 +1538,6 @@ ffs_fs_kill_sb(struct super_block *sb) if (sb->s_fs_info) { ffs_release_dev(sb->s_fs_info); ffs_data_closed(sb->s_fs_info); - ffs_data_put(sb->s_fs_info); } } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 84f88fa411cd..d088c340e4d0 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -447,7 +447,8 @@ static int ohci_init (struct ohci_hcd *ohci) struct usb_hcd *hcd = ohci_to_hcd(ohci); /* Accept arbitrarily long scatter-gather lists */ - hcd->self.sg_tablesize = ~0; + if (!(hcd->driver->flags & HCD_LOCAL_MEM)) + hcd->self.sg_tablesize = ~0; if (distrust_firmware) ohci->flags |= OHCI_QUIRK_HUB_POWER; diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c index a1ab8acf39ba..c359bae7b754 100644 --- a/drivers/usb/host/xhci-dbgcap.c +++ b/drivers/usb/host/xhci-dbgcap.c @@ -328,13 +328,14 @@ dbc_ep_do_queue(struct dbc_ep *dep, struct dbc_request *req) int dbc_ep_queue(struct dbc_ep *dep, struct dbc_request *req, gfp_t gfp_flags) { + unsigned long flags; struct xhci_dbc *dbc = dep->dbc; int ret = -ESHUTDOWN; - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); if (dbc->state == DS_CONFIGURED) ret = dbc_ep_do_queue(dep, req); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); mod_delayed_work(system_wq, &dbc->event_work, 0); @@ -521,15 +522,16 @@ static void xhci_do_dbc_stop(struct xhci_hcd *xhci) static int xhci_dbc_start(struct xhci_hcd *xhci) { int ret; + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; WARN_ON(!dbc); pm_runtime_get_sync(xhci_to_hcd(xhci)->self.controller); - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); ret = xhci_do_dbc_start(xhci); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); if (ret) { pm_runtime_put(xhci_to_hcd(xhci)->self.controller); @@ -541,6 +543,7 @@ static int xhci_dbc_start(struct xhci_hcd *xhci) static void xhci_dbc_stop(struct xhci_hcd *xhci) { + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; struct dbc_port *port = &dbc->port; @@ -551,9 +554,9 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci) if (port->registered) xhci_dbc_tty_unregister_device(xhci); - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); xhci_do_dbc_stop(xhci); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller); } @@ -779,14 +782,15 @@ static void xhci_dbc_handle_events(struct work_struct *work) int ret; enum evtreturn evtr; struct xhci_dbc *dbc; + unsigned long flags; struct xhci_hcd *xhci; dbc = container_of(to_delayed_work(work), struct xhci_dbc, event_work); xhci = dbc->xhci; - spin_lock(&dbc->lock); + spin_lock_irqsave(&dbc->lock, flags); evtr = xhci_dbc_do_handle_events(dbc); - spin_unlock(&dbc->lock); + spin_unlock_irqrestore(&dbc->lock, flags); switch (evtr) { case EVT_GSER: diff --git a/drivers/usb/host/xhci-dbgtty.c b/drivers/usb/host/xhci-dbgtty.c index 8d47b6fbf973..75f0b92694ba 100644 --- a/drivers/usb/host/xhci-dbgtty.c +++ b/drivers/usb/host/xhci-dbgtty.c @@ -92,21 +92,23 @@ static void dbc_start_rx(struct dbc_port *port) static void dbc_read_complete(struct xhci_hcd *xhci, struct dbc_request *req) { + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; struct dbc_port *port = &dbc->port; - spin_lock(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); list_add_tail(&req->list_pool, &port->read_queue); tasklet_schedule(&port->push); - spin_unlock(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); } static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) { + unsigned long flags; struct xhci_dbc *dbc = xhci->dbc; struct dbc_port *port = &dbc->port; - spin_lock(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); list_add(&req->list_pool, &port->write_pool); switch (req->status) { case 0: @@ -119,7 +121,7 @@ static void dbc_write_complete(struct xhci_hcd *xhci, struct dbc_request *req) req->status); break; } - spin_unlock(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); } static void xhci_dbc_free_req(struct dbc_ep *dep, struct dbc_request *req) @@ -327,12 +329,13 @@ static void dbc_rx_push(unsigned long _port) { struct dbc_request *req; struct tty_struct *tty; + unsigned long flags; bool do_push = false; bool disconnect = false; struct dbc_port *port = (void *)_port; struct list_head *queue = &port->read_queue; - spin_lock_irq(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); tty = port->port.tty; while (!list_empty(queue)) { req = list_first_entry(queue, struct dbc_request, list_pool); @@ -392,16 +395,17 @@ static void dbc_rx_push(unsigned long _port) if (!disconnect) dbc_start_rx(port); - spin_unlock_irq(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); } static int dbc_port_activate(struct tty_port *_port, struct tty_struct *tty) { + unsigned long flags; struct dbc_port *port = container_of(_port, struct dbc_port, port); - spin_lock_irq(&port->port_lock); + spin_lock_irqsave(&port->port_lock, flags); dbc_start_rx(port); - spin_unlock_irq(&port->port_lock); + spin_unlock_irqrestore(&port->port_lock, flags); return 0; } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5262fa571a5d..d9f831b67e57 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -126,6 +126,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info()) xhci->quirks |= XHCI_AMD_PLL_FIX; + if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x43bb) + xhci->quirks |= XHCI_SUSPEND_DELAY; + if (pdev->vendor == PCI_VENDOR_ID_AMD) xhci->quirks |= XHCI_TRUST_TX_LENGTH; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 6f038306c14d..6652e2d5bd2e 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -360,7 +360,6 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); - int ret; /* * xhci_suspend() needs `do_wakeup` to know whether host is allowed @@ -370,12 +369,7 @@ static int __maybe_unused xhci_plat_suspend(struct device *dev) * reconsider this when xhci_plat_suspend enlarges its scope, e.g., * also applies to runtime suspend. */ - ret = xhci_suspend(xhci, device_may_wakeup(dev)); - - if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) - clk_disable_unprepare(xhci->clk); - - return ret; + return xhci_suspend(xhci, device_may_wakeup(dev)); } static int __maybe_unused xhci_plat_resume(struct device *dev) @@ -384,9 +378,6 @@ static int __maybe_unused xhci_plat_resume(struct device *dev) struct xhci_hcd *xhci = hcd_to_xhci(hcd); int ret; - if (!device_may_wakeup(dev) && !IS_ERR(xhci->clk)) - clk_prepare_enable(xhci->clk); - ret = xhci_priv_resume_quirk(hcd); if (ret) return ret; diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index f0b559660007..f33ffc2bc4ed 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -83,6 +83,10 @@ static const struct soc_device_attribute rcar_quirks_match[] = { .soc_id = "r8a7796", .data = (void *)RCAR_XHCI_FIRMWARE_V3, }, + { + .soc_id = "r8a77965", + .data = (void *)RCAR_XHCI_FIRMWARE_V3, + }, { /* sentinel */ }, }; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 25d4b748a56f..5d37700ae4b0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -877,6 +877,9 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags); del_timer_sync(&xhci->shared_hcd->rh_timer); + if (xhci->quirks & XHCI_SUSPEND_DELAY) + usleep_range(1000, 1500); + spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e4d7d3d06a75..866e141d4972 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -718,11 +718,12 @@ struct xhci_ep_ctx { /* bits 10:14 are Max Primary Streams */ /* bit 15 is Linear Stream Array */ /* Interval - period between requests to an endpoint - 125u increments. */ -#define EP_INTERVAL(p) (((p) & 0xff) << 16) -#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) -#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) -#define EP_MAXPSTREAMS_MASK (0x1f << 10) -#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) +#define EP_INTERVAL(p) (((p) & 0xff) << 16) +#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) +#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) +#define EP_MAXPSTREAMS_MASK (0x1f << 10) +#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) +#define CTX_TO_EP_MAXPSTREAMS(p) (((p) & EP_MAXPSTREAMS_MASK) >> 10) /* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ #define EP_HAS_LSA (1 << 15) /* hosts with LEC=1 use bits 31:24 as ESIT high bits. */ @@ -1825,6 +1826,7 @@ struct xhci_hcd { #define XHCI_U2_DISABLE_WAKE (1 << 27) #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) #define XHCI_HW_LPM_DISABLE (1 << 29) +#define XHCI_SUSPEND_DELAY (1 << 30) unsigned int num_active_eps; unsigned int limit_active_eps; @@ -2549,21 +2551,22 @@ static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq, u8 burst; u8 cerr; u8 mult; - u8 lsa; - u8 hid; + + bool lsa; + bool hid; esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 | CTX_TO_MAX_ESIT_PAYLOAD(tx_info); ep_state = info & EP_STATE_MASK; - max_pstr = info & EP_MAXPSTREAMS_MASK; + max_pstr = CTX_TO_EP_MAXPSTREAMS(info); interval = CTX_TO_EP_INTERVAL(info); mult = CTX_TO_EP_MULT(info) + 1; - lsa = info & EP_HAS_LSA; + lsa = !!(info & EP_HAS_LSA); cerr = (info2 & (3 << 1)) >> 1; ep_type = CTX_TO_EP_TYPE(info2); - hid = info2 & (1 << 7); + hid = !!(info2 & (1 << 7)); burst = CTX_TO_MAX_BURST(info2); maxp = MAX_PACKET_DECODED(info2); diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c index f5e1bb5e5217..984f7e12a6a5 100644 --- a/drivers/usb/mon/mon_text.c +++ b/drivers/usb/mon/mon_text.c @@ -85,6 +85,8 @@ struct mon_reader_text { wait_queue_head_t wait; int printf_size; + size_t printf_offset; + size_t printf_togo; char *printf_buf; struct mutex printf_lock; @@ -376,75 +378,103 @@ err_alloc: return rc; } -/* - * For simplicity, we read one record in one system call and throw out - * what does not fit. This means that the following does not work: - * dd if=/dbg/usbmon/0t bs=10 - * Also, we do not allow seeks and do not bother advancing the offset. - */ +static ssize_t mon_text_copy_to_user(struct mon_reader_text *rp, + char __user * const buf, const size_t nbytes) +{ + const size_t togo = min(nbytes, rp->printf_togo); + + if (copy_to_user(buf, &rp->printf_buf[rp->printf_offset], togo)) + return -EFAULT; + rp->printf_togo -= togo; + rp->printf_offset += togo; + return togo; +} + +/* ppos is not advanced since the llseek operation is not permitted. */ static ssize_t mon_text_read_t(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) + size_t nbytes, loff_t *ppos) { struct mon_reader_text *rp = file->private_data; struct mon_event_text *ep; struct mon_text_ptr ptr; + ssize_t ret; - ep = mon_text_read_wait(rp, file); - if (IS_ERR(ep)) - return PTR_ERR(ep); mutex_lock(&rp->printf_lock); - ptr.cnt = 0; - ptr.pbuf = rp->printf_buf; - ptr.limit = rp->printf_size; - - mon_text_read_head_t(rp, &ptr, ep); - mon_text_read_statset(rp, &ptr, ep); - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, - " %d", ep->length); - mon_text_read_data(rp, &ptr, ep); - - if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) - ptr.cnt = -EFAULT; + + if (rp->printf_togo == 0) { + + ep = mon_text_read_wait(rp, file); + if (IS_ERR(ep)) { + mutex_unlock(&rp->printf_lock); + return PTR_ERR(ep); + } + ptr.cnt = 0; + ptr.pbuf = rp->printf_buf; + ptr.limit = rp->printf_size; + + mon_text_read_head_t(rp, &ptr, ep); + mon_text_read_statset(rp, &ptr, ep); + ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, + " %d", ep->length); + mon_text_read_data(rp, &ptr, ep); + + rp->printf_togo = ptr.cnt; + rp->printf_offset = 0; + + kmem_cache_free(rp->e_slab, ep); + } + + ret = mon_text_copy_to_user(rp, buf, nbytes); mutex_unlock(&rp->printf_lock); - kmem_cache_free(rp->e_slab, ep); - return ptr.cnt; + return ret; } +/* ppos is not advanced since the llseek operation is not permitted. */ static ssize_t mon_text_read_u(struct file *file, char __user *buf, - size_t nbytes, loff_t *ppos) + size_t nbytes, loff_t *ppos) { struct mon_reader_text *rp = file->private_data; struct mon_event_text *ep; struct mon_text_ptr ptr; + ssize_t ret; - ep = mon_text_read_wait(rp, file); - if (IS_ERR(ep)) - return PTR_ERR(ep); mutex_lock(&rp->printf_lock); - ptr.cnt = 0; - ptr.pbuf = rp->printf_buf; - ptr.limit = rp->printf_size; - mon_text_read_head_u(rp, &ptr, ep); - if (ep->type == 'E') { - mon_text_read_statset(rp, &ptr, ep); - } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { - mon_text_read_isostat(rp, &ptr, ep); - mon_text_read_isodesc(rp, &ptr, ep); - } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { - mon_text_read_intstat(rp, &ptr, ep); - } else { - mon_text_read_statset(rp, &ptr, ep); + if (rp->printf_togo == 0) { + + ep = mon_text_read_wait(rp, file); + if (IS_ERR(ep)) { + mutex_unlock(&rp->printf_lock); + return PTR_ERR(ep); + } + ptr.cnt = 0; + ptr.pbuf = rp->printf_buf; + ptr.limit = rp->printf_size; + + mon_text_read_head_u(rp, &ptr, ep); + if (ep->type == 'E') { + mon_text_read_statset(rp, &ptr, ep); + } else if (ep->xfertype == USB_ENDPOINT_XFER_ISOC) { + mon_text_read_isostat(rp, &ptr, ep); + mon_text_read_isodesc(rp, &ptr, ep); + } else if (ep->xfertype == USB_ENDPOINT_XFER_INT) { + mon_text_read_intstat(rp, &ptr, ep); + } else { + mon_text_read_statset(rp, &ptr, ep); + } + ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, + " %d", ep->length); + mon_text_read_data(rp, &ptr, ep); + + rp->printf_togo = ptr.cnt; + rp->printf_offset = 0; + + kmem_cache_free(rp->e_slab, ep); } - ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt, - " %d", ep->length); - mon_text_read_data(rp, &ptr, ep); - if (copy_to_user(buf, rp->printf_buf, ptr.cnt)) - ptr.cnt = -EFAULT; + ret = mon_text_copy_to_user(rp, buf, nbytes); mutex_unlock(&rp->printf_lock); - kmem_cache_free(rp->e_slab, ep); - return ptr.cnt; + return ret; } static struct mon_event_text *mon_text_read_wait(struct mon_reader_text *rp, diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index eef4ad578b31..4d723077be2b 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1756,6 +1756,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf) int vbus; u8 devctl; + pm_runtime_get_sync(dev); spin_lock_irqsave(&musb->lock, flags); val = musb->a_wait_bcon; vbus = musb_platform_get_vbus_status(musb); @@ -1769,6 +1770,7 @@ vbus_show(struct device *dev, struct device_attribute *attr, char *buf) vbus = 0; } spin_unlock_irqrestore(&musb->lock, flags); + pm_runtime_put_sync(dev); return sprintf(buf, "Vbus %s, timeout %lu msec\n", vbus ? "on" : "off", val); @@ -2471,11 +2473,11 @@ static int musb_remove(struct platform_device *pdev) musb_disable_interrupts(musb); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); spin_unlock_irqrestore(&musb->lock, flags); + musb_platform_exit(musb); pm_runtime_dont_use_autosuspend(musb->controller); pm_runtime_put_sync(musb->controller); pm_runtime_disable(musb->controller); - musb_platform_exit(musb); musb_phy_callback = NULL; if (musb->dma_controller) musb_dma_controller_destroy(musb->dma_controller); diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 3b1b9695177a..6034c39b67d1 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -1076,7 +1076,7 @@ static int uas_post_reset(struct usb_interface *intf) return 0; err = uas_configure_endpoints(devinfo); - if (err && err != ENODEV) + if (err && err != -ENODEV) shost_printk(KERN_ERR, shost, "%s: alloc streams error %d after reset", __func__, err); diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 264af199aec8..747d3a9596d9 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2118,6 +2118,13 @@ UNUSUAL_DEV( 0x152d, 0x2566, 0x0114, 0x0114, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_BROKEN_FUA ), +/* Reported by Teijo Kinnunen <teijo.kinnunen@code-q.fi> */ +UNUSUAL_DEV( 0x152d, 0x2567, 0x0117, 0x0117, + "JMicron", + "USB to ATA/ATAPI Bridge", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BROKEN_FUA ), + /* Reported-by George Cherian <george.cherian@cavium.com> */ UNUSUAL_DEV(0x152d, 0x9561, 0x0000, 0x9999, "JMicron", diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 9ce4756adad6..dcd8ef085b30 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -1857,7 +1857,8 @@ static int fusb302_probe(struct i2c_client *client, chip->tcpm_port = tcpm_register_port(&client->dev, &chip->tcpc_dev); if (IS_ERR(chip->tcpm_port)) { ret = PTR_ERR(chip->tcpm_port); - dev_err(dev, "cannot register tcpm port, ret=%d", ret); + if (ret != -EPROBE_DEFER) + dev_err(dev, "cannot register tcpm port, ret=%d", ret); goto destroy_workqueue; } diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index f4d563ee7690..8b637a4b474b 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -252,9 +252,6 @@ struct tcpm_port { unsigned int nr_src_pdo; u32 snk_pdo[PDO_MAX_OBJECTS]; unsigned int nr_snk_pdo; - unsigned int nr_fixed; /* number of fixed sink PDOs */ - unsigned int nr_var; /* number of variable sink PDOs */ - unsigned int nr_batt; /* number of battery sink PDOs */ u32 snk_vdo[VDO_MAX_OBJECTS]; unsigned int nr_snk_vdo; @@ -1770,90 +1767,39 @@ static int tcpm_pd_check_request(struct tcpm_port *port) return 0; } -#define min_power(x, y) min(pdo_max_power(x), pdo_max_power(y)) -#define min_current(x, y) min(pdo_max_current(x), pdo_max_current(y)) - -static int tcpm_pd_select_pdo(struct tcpm_port *port, int *sink_pdo, - int *src_pdo) +static int tcpm_pd_select_pdo(struct tcpm_port *port) { - unsigned int i, j, max_mw = 0, max_mv = 0, mw = 0, mv = 0, ma = 0; + unsigned int i, max_mw = 0, max_mv = 0; int ret = -EINVAL; /* - * Select the source PDO providing the most power which has a - * matchig sink cap. + * Select the source PDO providing the most power while staying within + * the board's voltage limits. Prefer PDO providing exp */ for (i = 0; i < port->nr_source_caps; i++) { u32 pdo = port->source_caps[i]; enum pd_pdo_type type = pdo_type(pdo); + unsigned int mv, ma, mw; - if (type == PDO_TYPE_FIXED) { - for (j = 0; j < port->nr_fixed; j++) { - if (pdo_fixed_voltage(pdo) == - pdo_fixed_voltage(port->snk_pdo[j])) { - ma = min_current(pdo, port->snk_pdo[j]); - mv = pdo_fixed_voltage(pdo); - mw = ma * mv / 1000; - if (mw > max_mw || - (mw == max_mw && mv > max_mv)) { - ret = 0; - *src_pdo = i; - *sink_pdo = j; - max_mw = mw; - max_mv = mv; - } - /* There could only be one fixed pdo - * at a specific voltage level. - * So breaking here. - */ - break; - } - } - } else if (type == PDO_TYPE_BATT) { - for (j = port->nr_fixed; - j < port->nr_fixed + - port->nr_batt; - j++) { - if (pdo_min_voltage(pdo) >= - pdo_min_voltage(port->snk_pdo[j]) && - pdo_max_voltage(pdo) <= - pdo_max_voltage(port->snk_pdo[j])) { - mw = min_power(pdo, port->snk_pdo[j]); - mv = pdo_min_voltage(pdo); - if (mw > max_mw || - (mw == max_mw && mv > max_mv)) { - ret = 0; - *src_pdo = i; - *sink_pdo = j; - max_mw = mw; - max_mv = mv; - } - } - } - } else if (type == PDO_TYPE_VAR) { - for (j = port->nr_fixed + - port->nr_batt; - j < port->nr_fixed + - port->nr_batt + - port->nr_var; - j++) { - if (pdo_min_voltage(pdo) >= - pdo_min_voltage(port->snk_pdo[j]) && - pdo_max_voltage(pdo) <= - pdo_max_voltage(port->snk_pdo[j])) { - ma = min_current(pdo, port->snk_pdo[j]); - mv = pdo_min_voltage(pdo); - mw = ma * mv / 1000; - if (mw > max_mw || - (mw == max_mw && mv > max_mv)) { - ret = 0; - *src_pdo = i; - *sink_pdo = j; - max_mw = mw; - max_mv = mv; - } - } - } + if (type == PDO_TYPE_FIXED) + mv = pdo_fixed_voltage(pdo); + else + mv = pdo_min_voltage(pdo); + + if (type == PDO_TYPE_BATT) { + mw = pdo_max_power(pdo); + } else { + ma = min(pdo_max_current(pdo), + port->max_snk_ma); + mw = ma * mv / 1000; + } + + /* Perfer higher voltages if available */ + if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && + mv <= port->max_snk_mv) { + ret = i; + max_mw = mw; + max_mv = mv; } } @@ -1865,14 +1811,13 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) unsigned int mv, ma, mw, flags; unsigned int max_ma, max_mw; enum pd_pdo_type type; - int src_pdo_index, snk_pdo_index; - u32 pdo, matching_snk_pdo; + int index; + u32 pdo; - if (tcpm_pd_select_pdo(port, &snk_pdo_index, &src_pdo_index) < 0) + index = tcpm_pd_select_pdo(port); + if (index < 0) return -EINVAL; - - pdo = port->source_caps[src_pdo_index]; - matching_snk_pdo = port->snk_pdo[snk_pdo_index]; + pdo = port->source_caps[index]; type = pdo_type(pdo); if (type == PDO_TYPE_FIXED) @@ -1880,28 +1825,26 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) else mv = pdo_min_voltage(pdo); - /* Select maximum available current within the sink pdo's limit */ + /* Select maximum available current within the board's power limit */ if (type == PDO_TYPE_BATT) { - mw = min_power(pdo, matching_snk_pdo); - ma = 1000 * mw / mv; + mw = pdo_max_power(pdo); + ma = 1000 * min(mw, port->max_snk_mw) / mv; } else { - ma = min_current(pdo, matching_snk_pdo); - mw = ma * mv / 1000; + ma = min(pdo_max_current(pdo), + 1000 * port->max_snk_mw / mv); } + ma = min(ma, port->max_snk_ma); flags = RDO_USB_COMM | RDO_NO_SUSPEND; /* Set mismatch bit if offered power is less than operating power */ + mw = ma * mv / 1000; max_ma = ma; max_mw = mw; if (mw < port->operating_snk_mw) { flags |= RDO_CAP_MISMATCH; - if (type == PDO_TYPE_BATT && - (pdo_max_power(matching_snk_pdo) > pdo_max_power(pdo))) - max_mw = pdo_max_power(matching_snk_pdo); - else if (pdo_max_current(matching_snk_pdo) > - pdo_max_current(pdo)) - max_ma = pdo_max_current(matching_snk_pdo); + max_mw = port->operating_snk_mw; + max_ma = max_mw * 1000 / mv; } tcpm_log(port, "cc=%d cc1=%d cc2=%d vbus=%d vconn=%s polarity=%d", @@ -1910,16 +1853,16 @@ static int tcpm_pd_build_request(struct tcpm_port *port, u32 *rdo) port->polarity); if (type == PDO_TYPE_BATT) { - *rdo = RDO_BATT(src_pdo_index + 1, mw, max_mw, flags); + *rdo = RDO_BATT(index + 1, mw, max_mw, flags); tcpm_log(port, "Requesting PDO %d: %u mV, %u mW%s", - src_pdo_index, mv, mw, + index, mv, mw, flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); } else { - *rdo = RDO_FIXED(src_pdo_index + 1, ma, max_ma, flags); + *rdo = RDO_FIXED(index + 1, ma, max_ma, flags); tcpm_log(port, "Requesting PDO %d: %u mV, %u mA%s", - src_pdo_index, mv, ma, + index, mv, ma, flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); } @@ -3650,19 +3593,6 @@ int tcpm_update_sink_capabilities(struct tcpm_port *port, const u32 *pdo, } EXPORT_SYMBOL_GPL(tcpm_update_sink_capabilities); -static int nr_type_pdos(const u32 *pdo, unsigned int nr_pdo, - enum pd_pdo_type type) -{ - int count = 0; - int i; - - for (i = 0; i < nr_pdo; i++) { - if (pdo_type(pdo[i]) == type) - count++; - } - return count; -} - struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) { struct tcpm_port *port; @@ -3708,15 +3638,6 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) tcpc->config->nr_src_pdo); port->nr_snk_pdo = tcpm_copy_pdos(port->snk_pdo, tcpc->config->snk_pdo, tcpc->config->nr_snk_pdo); - port->nr_fixed = nr_type_pdos(port->snk_pdo, - port->nr_snk_pdo, - PDO_TYPE_FIXED); - port->nr_var = nr_type_pdos(port->snk_pdo, - port->nr_snk_pdo, - PDO_TYPE_VAR); - port->nr_batt = nr_type_pdos(port->snk_pdo, - port->nr_snk_pdo, - PDO_TYPE_BATT); port->nr_snk_vdo = tcpm_copy_vdos(port->snk_vdo, tcpc->config->snk_vdo, tcpc->config->nr_snk_vdo); diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index d86f72bbbb91..6dcd3ff655c3 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -105,10 +105,14 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a if (rv != 0) return -EINVAL; + if (!udc) { + dev_err(dev, "no device"); + return -ENODEV; + } spin_lock_irqsave(&udc->lock, flags); /* Don't export what we don't have */ - if (!udc || !udc->driver || !udc->pullup) { - dev_err(dev, "no device or gadget not bound"); + if (!udc->driver || !udc->pullup) { + dev_err(dev, "gadget not bound"); ret = -ENODEV; goto unlock; } diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index f1fcec2fd5f8..b7a99ce56bc9 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -63,4 +63,7 @@ */ #define USB_QUIRK_DISCONNECT_SUSPEND BIT(12) +/* Device needs a pause after every control message. */ +#define USB_QUIRK_DELAY_CTRL_MSG BIT(13) + #endif /* __LINUX_USB_QUIRKS_H */ |