From f1bddbb3de60872acc2446eee97dbeb0a6d57acb Mon Sep 17 00:00:00 2001 From: Krzysztof Opasiak Date: Thu, 5 May 2016 10:46:05 +0200 Subject: usb: gadget: Fix binding to UDC via configfs interface By default user could store only valid UDC name in configfs UDC attr by doing: echo $UDC_NAME > UDC Commit (855ed04 "usb: gadget: udc-core: independent registration of gadgets and gadget drivers") broke this behavior and allowed to store any arbitrary string in UDC file and udc core was waiting for such controller to appear. echo "any arbitrary string here" > UDC This commit fix this by adding a flag which prevents configfs gadget from being added to list of pending drivers if UDC with given name has not been found. Signed-off-by: Krzysztof Opasiak Signed-off-by: Felipe Balbi --- include/linux/usb/gadget.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux/usb') diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 457651bf45b0..fefe8b06a63d 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -1034,6 +1034,8 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget) * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL, * this driver will be bound to any available UDC. * @pending: UDC core private data used for deferred probe of this driver. + * @match_existing_only: If udc is not found, return an error and don't add this + * gadget driver to list of pending driver * * Devices are disabled till a gadget driver successfully bind()s, which * means the driver will handle setup() requests needed to enumerate (and @@ -1097,6 +1099,7 @@ struct usb_gadget_driver { char *udc_name; struct list_head pending; + unsigned match_existing_only:1; }; -- cgit v1.2.3 From 12b7db2bf8b88938798c60416172b53225207b1f Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 31 May 2016 10:05:19 -0500 Subject: usb: musb: Return error value from musb_mailbox At least on n900 we have phy-twl4030-usb only generating cable interrupts, and then have a separate USB PHY. In order for musb to know the real cable status, we need to clear any cached state until musb is ready. Otherwise the cable status interrupts will get just ignored if the status does not change from the initial state. To do this, let's add a return value to musb_mailbox(), and reset cached linkstat to MUSB_UNKNOWN on error. Sorry to cause a bit of churn here, I should have added that already last time patching musb_mailbox(). Signed-off-by: Tony Lindgren Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman --- drivers/phy/phy-twl4030-usb.c | 14 ++++++++++---- drivers/usb/musb/musb_core.c | 7 ++++--- drivers/usb/musb/musb_core.h | 2 +- drivers/usb/musb/omap2430.c | 8 +++++--- drivers/usb/phy/phy-twl6030-usb.c | 12 +++++++++--- include/linux/usb/musb.h | 5 +++-- 6 files changed, 32 insertions(+), 16 deletions(-) (limited to 'include/linux/usb') diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 6b6af6cba454..d9b10a39a2cf 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -463,7 +463,8 @@ static int twl4030_phy_power_on(struct phy *phy) twl4030_usb_set_mode(twl, twl->usb_mode); if (twl->usb_mode == T2_USB_MODE_ULPI) twl4030_i2c_access(twl, 0); - schedule_delayed_work(&twl->id_workaround_work, 0); + twl->linkstat = MUSB_UNKNOWN; + schedule_delayed_work(&twl->id_workaround_work, HZ); return 0; } @@ -537,6 +538,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) struct twl4030_usb *twl = _twl; enum musb_vbus_id_status status; bool status_changed = false; + int err; status = twl4030_usb_linkstat(twl); @@ -567,7 +569,9 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_autosuspend(twl->dev); } - musb_mailbox(status); + err = musb_mailbox(status); + if (err) + twl->linkstat = MUSB_UNKNOWN; } /* don't schedule during sleep - irq works right then */ @@ -595,7 +599,8 @@ static int twl4030_phy_init(struct phy *phy) struct twl4030_usb *twl = phy_get_drvdata(phy); pm_runtime_get_sync(twl->dev); - schedule_delayed_work(&twl->id_workaround_work, 0); + twl->linkstat = MUSB_UNKNOWN; + schedule_delayed_work(&twl->id_workaround_work, HZ); pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_autosuspend(twl->dev); @@ -763,7 +768,8 @@ static int twl4030_usb_remove(struct platform_device *pdev) if (cable_present(twl->linkstat)) pm_runtime_put_noidle(twl->dev); pm_runtime_mark_last_busy(twl->dev); - pm_runtime_put_sync_suspend(twl->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_put_sync(twl->dev); pm_runtime_disable(twl->dev); /* autogate 60MHz ULPI clock, diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 23888d579e8b..6469eff4fc30 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1679,7 +1679,7 @@ EXPORT_SYMBOL_GPL(musb_dma_completion); #define use_dma 0 #endif -static void (*musb_phy_callback)(enum musb_vbus_id_status status); +static int (*musb_phy_callback)(enum musb_vbus_id_status status); /* * musb_mailbox - optional phy notifier function @@ -1688,11 +1688,12 @@ static void (*musb_phy_callback)(enum musb_vbus_id_status status); * Optionally gets called from the USB PHY. Note that the USB PHY must be * disabled at the point the phy_callback is registered or unregistered. */ -void musb_mailbox(enum musb_vbus_id_status status) +int musb_mailbox(enum musb_vbus_id_status status) { if (musb_phy_callback) - musb_phy_callback(status); + return musb_phy_callback(status); + return -ENODEV; }; EXPORT_SYMBOL_GPL(musb_mailbox); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 29473846b098..b55a776b03eb 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -215,7 +215,7 @@ struct musb_platform_ops { dma_addr_t *dma_addr, u32 *len); void (*pre_root_reset_end)(struct musb *musb); void (*post_root_reset_end)(struct musb *musb); - void (*phy_callback)(enum musb_vbus_id_status status); + int (*phy_callback)(enum musb_vbus_id_status status); }; /* diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index d312d42592d6..2c54f52ae386 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -180,22 +180,24 @@ static void omap2430_set_power(struct musb *musb, bool enabled, bool cable) } } -static void omap2430_musb_mailbox(enum musb_vbus_id_status status) +static int omap2430_musb_mailbox(enum musb_vbus_id_status status) { struct omap2430_glue *glue = _glue; if (!glue) { pr_err("%s: musb core is not yet initialized\n", __func__); - return; + return -EPROBE_DEFER; } glue->status = status; if (!glue_to_musb(glue)) { pr_err("%s: musb core is not yet ready\n", __func__); - return; + return -EPROBE_DEFER; } schedule_work(&glue->omap_musb_mailbox_work); + + return 0; } static void omap_musb_set_mailbox(struct omap2430_glue *glue) diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c index 24e2b3cf1867..c66a447c3dfe 100644 --- a/drivers/usb/phy/phy-twl6030-usb.c +++ b/drivers/usb/phy/phy-twl6030-usb.c @@ -227,12 +227,16 @@ static irqreturn_t twl6030_usb_irq(int irq, void *_twl) twl->asleep = 1; status = MUSB_VBUS_VALID; twl->linkstat = status; - musb_mailbox(status); + ret = musb_mailbox(status); + if (ret) + twl->linkstat = MUSB_UNKNOWN; } else { if (twl->linkstat != MUSB_UNKNOWN) { status = MUSB_VBUS_OFF; twl->linkstat = status; - musb_mailbox(status); + ret = musb_mailbox(status); + if (ret) + twl->linkstat = MUSB_UNKNOWN; if (twl->asleep) { regulator_disable(twl->usb3v3); twl->asleep = 0; @@ -264,7 +268,9 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_SET); status = MUSB_ID_GROUND; twl->linkstat = status; - musb_mailbox(status); + ret = musb_mailbox(status); + if (ret) + twl->linkstat = MUSB_UNKNOWN; } else { twl6030_writeb(twl, TWL_MODULE_USB, 0x10, USB_ID_INT_EN_HI_CLR); twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h index 0b3da40a525e..d315c8907869 100644 --- a/include/linux/usb/musb.h +++ b/include/linux/usb/musb.h @@ -142,10 +142,11 @@ enum musb_vbus_id_status { }; #if IS_ENABLED(CONFIG_USB_MUSB_HDRC) -void musb_mailbox(enum musb_vbus_id_status status); +int musb_mailbox(enum musb_vbus_id_status status); #else -static inline void musb_mailbox(enum musb_vbus_id_status status) +static inline int musb_mailbox(enum musb_vbus_id_status status) { + return 0; } #endif -- cgit v1.2.3 From 7e8b3dfef16375dbfeb1f36a83eb9f27117c51fd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 23 Jun 2016 14:54:37 -0400 Subject: USB: EHCI: declare hostpc register as zero-length array The HOSTPC extension registers found in some EHCI implementations form a variable-length array, with one element for each port. Therefore the hostpc field in struct ehci_regs should be declared as a zero-length array, not a single-element array. This fixes a problem reported by UBSAN. Signed-off-by: Alan Stern Reported-by: Wilfried Klaebe Tested-by: Wilfried Klaebe CC: Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/ehci_def.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux/usb') diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h index 966889a20ea3..e479033bd782 100644 --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -180,11 +180,11 @@ struct ehci_regs { * PORTSCx */ /* HOSTPC: offset 0x84 */ - u32 hostpc[1]; /* HOSTPC extension */ + u32 hostpc[0]; /* HOSTPC extension */ #define HOSTPC_PHCD (1<<22) /* Phy clock disable */ #define HOSTPC_PSPD (3<<25) /* Port speed detection */ - u32 reserved5[16]; + u32 reserved5[17]; /* USBMODE_EX: offset 0xc8 */ u32 usbmode_ex; /* USB Device mode extension */ -- cgit v1.2.3