Re: question on possible deadlock with devices with multiple interfaces
On Fri, 2015-01-16 at 10:33 -0500, Alan Stern wrote: Yes, that could happen. It seems unlikely but it is possible. Thanks. I am pushing out a fix. Regards Oliver -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Control message failures kill entire XHCI stack
On 19.01.2015 22:02, Devin Heitmueller wrote: Hi Mathias, Thanks for getting back to me. There are a couple of xhci bugs triggered by dvb devices: https://bugzilla.kernel.org/show_bug.cgi?id=75521 https://bugzilla.kernel.org/show_bug.cgi?id=65021 The first one (75521) I believe is mostly fixed by patches in 3.18 and early 3.19-rc, so work on a 3.19-rc kernel to eliminate those issues. Yeah, I'm already running 3.19-rc1 so I should be in good shape for the first issue (and I've never seen any errors that resemble those in the bug report). The second bug (65021) looks more like your case, it queues two stop_endpoints commands almost simultaneously, which end up never completing, -timeout and tear down xhci. That bug has a debug patch for command ring status, you could try it out to check if the command queue is running among other details. The second bug definitely looks like what I'm seeing. I'll try your tree and report back my findings. Ah, let me rebase that tree on top of a more current kernel first. A verbose xhci dmesg log log using: echo -n 'module xhci_hcd =p' /sys/kernel/debug/dynamic_debug/control could give some insight to what's happening Just to be clear, the log I provided in my original email actually was with xhci_hcd +p, but I'm assuming you mean to provide that log output after loading up your for-usb-next-test tree. Right, yes logs with the debug patches, and starting earlier to see what happened before xHCI to stopped responding. I'm happy to ship you a device if you want to reproduce the issue locally. On my 2014 Macbook Pro all I have to do is plug in the device and run the tvtime application that ships with most distros, and it fails 100% of the time within 5 seconds (you don't actually need a DVB or analog TV source connected to hit the bug). Just email me your shipping info off-list if you're interested. I got one device from sundtek. They said they could reproduce the first bug easily, but I couldn't. If the debug output doesn't give any clues then I could be interested in one. -Mathias -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/3] usb: dwc3: add ULPI interface support
Registers ULPI interface with the ULPI bus if HSPHY type is ULPI. Signed-off-by: Heikki Krogerus heikki.kroge...@linux.intel.com Cc: Felipe Balbi ba...@ti.com --- drivers/usb/dwc3/Kconfig | 7 drivers/usb/dwc3/Makefile | 4 ++ drivers/usb/dwc3/core.c | 9 +++- drivers/usb/dwc3/core.h | 22 ++ drivers/usb/dwc3/ulpi.c | 102 ++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/dwc3/ulpi.c diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 58b5b2c..6d0c5e6 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -11,6 +11,13 @@ config USB_DWC3 if USB_DWC3 +config USB_DWC3_ULPI + bool Provide ULPI PHY Interface + depends on ULPI_PHY=y || ULPI_PHY=USB_DWC3 + help + Select this if you have ULPI type PHY attached to your DWC3 + controller. + choice bool DWC3 Mode Selection default USB_DWC3_DUAL_ROLE if (USB USB_GADGET) diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index bb34fbc..2fc44e0 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -16,6 +16,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += gadget.o ep0.o endif +ifneq ($(CONFIG_USB_DWC3_ULPI),) + dwc3-y += ulpi.o +endif + ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o endif diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 25ddc39..5219bc7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -876,12 +876,17 @@ static int dwc3_probe(struct platform_device *pdev) dwc-hird_threshold = hird_threshold | (dwc-is_utmi_l1_suspend 4); + platform_set_drvdata(pdev, dwc); + + ret = dwc3_ulpi_init(dwc); + if (ret) + return ret; + ret = dwc3_core_get_phy(dwc); if (ret) return ret; spin_lock_init(dwc-lock); - platform_set_drvdata(pdev, dwc); if (!dev-dma_mask) { dev-dma_mask = dev-parent-dma_mask; @@ -965,6 +970,7 @@ err1: err0: dwc3_free_event_buffers(dwc); + dwc3_ulpi_exit(dwc); return ret; } @@ -984,6 +990,7 @@ static int dwc3_remove(struct platform_device *pdev) phy_power_off(dwc-usb3_generic_phy); dwc3_core_exit(dwc); + dwc3_ulpi_exit(dwc); pm_runtime_put_sync(pdev-dev); pm_runtime_disable(pdev-dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0842aa8..f6881a6 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -32,6 +32,7 @@ #include linux/usb/otg.h #include linux/phy/phy.h +#include linux/phy/ulpi/interface.h #define DWC3_MSG_MAX 500 @@ -174,6 +175,14 @@ #define DWC3_GUSB2PHYCFG_PHYSOFTRST(1 31) #define DWC3_GUSB2PHYCFG_SUSPHY(1 6) +/* Global USB2 PHY Vendor Control Register */ +#define DWC3_GUSB2PHYACC_NEWREGREQ (1 25) +#define DWC3_GUSB2PHYACC_BUSY (1 23) +#define DWC3_GUSB2PHYACC_WRITE (1 22) +#define DWC3_GUSB2PHYACC_ADDR(n) (n 16) +#define DWC3_GUSB2PHYACC_EXTEND_ADDR(n)(n 8) +#define DWC3_GUSB2PHYACC_DATA(n) (n 0xff) + /* Global USB3 PIPE Control Register */ #define DWC3_GUSB3PIPECTL_PHYSOFTRST (1 31) #define DWC3_GUSB3PIPECTL_U2SSINP3OK (1 29) @@ -590,6 +599,7 @@ struct dwc3_hwparams { #define DWC3_NUM_INT(n)(((n) (0x3f 15)) 15) /* HWPARAMS3 */ +#define DWC3_ULPI_HSPHY(1 3) #define DWC3_NUM_IN_EPS_MASK (0x1f 18) #define DWC3_NUM_EPS_MASK (0x3f 12) #define DWC3_NUM_EPS(p)(((p)-hwparams3 \ @@ -739,6 +749,8 @@ struct dwc3 { struct phy *usb2_generic_phy; struct phy *usb3_generic_phy; + struct ulpi *ulpi; + void __iomem*regs; size_t regs_size; @@ -1035,4 +1047,14 @@ static inline int dwc3_gadget_resume(struct dwc3 *dwc) } #endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ +#if IS_ENABLED(CONFIG_USB_DWC3_ULPI) +int dwc3_ulpi_init(struct dwc3 *dwc); +void dwc3_ulpi_exit(struct dwc3 *dwc); +#else +static inline int dwc3_ulpi_init(struct dwc3 *dwc) +{ return 0; } +static inline void dwc3_ulpi_exit(struct dwc3 *dwc) +{ } +#endif + #endif /* __DRIVERS_USB_DWC3_CORE_H */ diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c new file mode 100644 index 000..ee3ebbe --- /dev/null +++ b/drivers/usb/dwc3/ulpi.c @@ -0,0 +1,102 @@ +/** + * ulpi.c - DesignWare USB3 Controller's ULPI PHY interface + * + * Copyright (C) 2015 Intel Corporation + * + * Author: Heikki Krogerus heikki.kroge...@linux.intel.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public
Re: [PATCH 5/5] ARM: omap2plus_defconfig: Enable PCF857X and EXTCON_GPIO_USB
On 19/01/15 21:38, Tony Lindgren wrote: * Tony Lindgren t...@atomide.com [150119 10:52]: * Roger Quadros rog...@ti.com [150119 09:55]: Both are needed for USB cable type detection on dra7-evm. Signed-off-by: Roger Quadros rog...@ti.com --- arch/arm/configs/omap2plus_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig index c2c3a85..bc23b90 100644 --- a/arch/arm/configs/omap2plus_defconfig +++ b/arch/arm/configs/omap2plus_defconfig @@ -203,6 +203,7 @@ CONFIG_SPI_OMAP24XX=y CONFIG_PINCTRL_SINGLE=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_PCF857X=y CONFIG_GPIO_TWL4030=y CONFIG_W1=y CONFIG_BATTERY_BQ27x00=m Looks like I have this too but as a loadable module :) So I'll keep that one. @@ -326,6 +327,7 @@ CONFIG_DMADEVICES=y CONFIG_TI_EDMA=y CONFIG_DMA_OMAP=y CONFIG_EXTCON=y +CONFIG_EXTCON_GPIO_USB=y CONFIG_EXTCON_PALMAS=y CONFIG_PWM=y CONFIG_PWM_TIECAP=y I'll apply this part into omap-for-v3.20/defconfig but make it into =m instead of =y. Oh but this depends on the driver being added, so not applying. Can you please repost a patch adding CONFIG_EXTCON_GPIO_USB=m once the driver is merged? Yes, I'll do that. cheers, -roger -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv3 1/2] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state
Le 20/01/2015 12:02, Sylvain Rochet a écrit : Hello, On Mon, Jan 19, 2015 at 12:55:47PM -0600, Felipe Balbi wrote: On Mon, Jan 19, 2015 at 03:09:44PM +0100, Nicolas Ferre wrote: Le 18/01/2015 18:24, Sylvain Rochet a écrit : If vbus gpio is high at init, we should set vbus_prev to true accordingly to the current vbus state. Without that, we skip the first vbus interrupt because the saved vbus state is not consistent. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Indeed: Acked-by: Nicolas Ferre nicolas.fe...@atmel.com We can also add the following tags: Fixes: 914a3f3b3754 (USB: add atmel_usba_udc driver) Cc: sta...@vger.kernel.org # 2.6.x-ish Please resend with the proper stable format. Also, this 2.6.x-ish should be 2.6.24+, git describe helps a lot figuring these out. Unfortunately I failed to understand what I should do. The Also keyword means for me that there are two differents things to fix: 1. proper stable format 2. 2.6.x-ish → 2.6.24+ 2. does not imply fixing 1., isn'it ? Well, I think it does. My understanding is that fixing '2' is the solution. I read SubmittingPatches thoroughly and I can't find a reference to stable format. Sylvain Bye, -- Nicolas Ferre -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 01/11] hso: remove useless header file timer.h
No timer related function is used in this driver. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index babda7d..cb0bcc1 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -58,7 +58,6 @@ #include linux/module.h #include linux/ethtool.h #include linux/usb.h -#include linux/timer.h #include linux/tty.h #include linux/tty_driver.h #include linux/tty_flip.h -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 04/11] hso: fix memory leak in hso_create_rfkill()
When the rfkill interface was created, a buffer containing the name of the rfkill node was allocated. This buffer was never freed when the device disappears. To fix the problem, we put the name given to rfkill_alloc() in the hso_net structure. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 470ef9e..a49ac2e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -153,6 +153,7 @@ struct hso_net { struct hso_device *parent; struct net_device *net; struct rfkill *rfkill; + char name[8]; struct usb_endpoint_descriptor *in_endp; struct usb_endpoint_descriptor *out_endp; @@ -2467,27 +2468,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev, { struct hso_net *hso_net = dev2net(hso_dev); struct device *dev = hso_net-net-dev; - char *rfkn; - rfkn = kzalloc(20, GFP_KERNEL); - if (!rfkn) - dev_err(dev, %s - Out of memory\n, __func__); - - snprintf(rfkn, 20, hso-%d, + snprintf(hso_net-name, sizeof(hso_net-name), hso-%d, interface-altsetting-desc.bInterfaceNumber); - hso_net-rfkill = rfkill_alloc(rfkn, + hso_net-rfkill = rfkill_alloc(hso_net-name, interface_to_usbdev(interface)-dev, RFKILL_TYPE_WWAN, hso_rfkill_ops, hso_dev); if (!hso_net-rfkill) { dev_err(dev, %s - Out of memory\n, __func__); - kfree(rfkn); return; } if (rfkill_register(hso_net-rfkill) 0) { rfkill_destroy(hso_net-rfkill); - kfree(rfkn); hso_net-rfkill = NULL; dev_err(dev, %s - Failed to register rfkill\n, __func__); return; -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 03/11] hso: fix memory leak when device disconnects
In the disconnect path, tx_buffer should freed like tx_data to avoid a memory leak when the device disconnects. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 3a6c630..470ef9e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2253,6 +2253,7 @@ static void hso_serial_common_free(struct hso_serial *serial) /* unlink and free TX URB */ usb_free_urb(serial-tx_urb); + kfree(serial-tx_buffer); kfree(serial-tx_data); tty_port_destroy(serial-port); } -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 05/11] hso: fix small indentation error
Simply remove the useless extra tab. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index a49ac2e..2f2343d 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2206,8 +2206,8 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) for (i = 0; i serial-num_rx_urbs; i++) { if (serial-rx_urb[i]) { - usb_kill_urb(serial-rx_urb[i]); - serial-rx_urb_filled[i] = 0; + usb_kill_urb(serial-rx_urb[i]); + serial-rx_urb_filled[i] = 0; } } serial-curr_rx_urb_idx = 0; -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 10/11] hso: add missing cancel_work_sync in disconnect()
For hso serial devices, two cancel_work_sync were missing in the disconnect method. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index c916ab5..c14fc80 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -3107,6 +3107,8 @@ static void hso_free_interface(struct usb_interface *interface) mutex_lock(serial-parent-mutex); serial-parent-usb_gone = 1; mutex_unlock(serial-parent-mutex); + cancel_work_sync(serial_table[i]-async_put_intf); + cancel_work_sync(serial_table[i]-async_get_intf); hso_serial_tty_unregister(serial); kref_put(serial_table[i]-ref, hso_serial_ref_free); set_serial_by_index(i, NULL); -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 02/11] hso: fix crash when device disappears while serial port is open
When the device disappear, the function hso_disconnect() is called to perform cleanup. In the cleanup function, hso_free_interface() calls tty_port_tty_hangup() in view of scheduling a work to hang up the tty if needed. If the port was not open then hso_serial_ref_free() is called directly to cleanup everything. Otherwise, hso_serial_ref_free() is called when the last fd associated to the port is closed. For each open port, tty_release() will call the close method, hso_serial_close(), which drops the last kref and call hso_serial_ref_free() which unregisters, destroys the tty port and finally frees the structure in which the tty_port structure is included. Later, in tty_release(), more precisely when release_tty() is called, the tty_port previously freed is accessed to cancel the tty buf workqueue and it leads to a crash. In view of avoiding this crash, we add a cleanup method that is called at the end of the hangup process and we drop the last kref in this function when all the ports have been closed, when tty_port is no more needed and when it is safe to free the structure containing the tty_port structure. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 17 + 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index cb0bcc1..3a6c630 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1270,7 +1270,6 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) goto err_out; D1(Opening %d, serial-minor); - kref_get(serial-parent-ref); /* setup */ tty-driver_data = serial; @@ -1289,7 +1288,8 @@ static int hso_serial_open(struct tty_struct *tty, struct file *filp) if (result) { hso_stop_serial_device(serial-parent); serial-port.count--; - kref_put(serial-parent-ref, hso_serial_ref_free); + } else { + kref_get(serial-parent-ref); } } else { D1(Port was already open); @@ -1339,8 +1339,6 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) usb_autopm_put_interface(serial-parent-interface); mutex_unlock(serial-parent-mutex); - - kref_put(serial-parent-ref, hso_serial_ref_free); } /* close the requested serial port */ @@ -1391,6 +1389,16 @@ static int hso_serial_write_room(struct tty_struct *tty) return room; } +static void hso_serial_cleanup(struct tty_struct *tty) +{ + struct hso_serial *serial = tty-driver_data; + + if (!serial) + return; + + kref_put(serial-parent-ref, hso_serial_ref_free); +} + /* setup the term */ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) { @@ -3215,6 +3223,7 @@ static const struct tty_operations hso_serial_ops = { .close = hso_serial_close, .write = hso_serial_write, .write_room = hso_serial_write_room, + .cleanup = hso_serial_cleanup, .ioctl = hso_serial_ioctl, .set_termios = hso_serial_set_termios, .chars_in_buffer = hso_serial_chars_in_buffer, -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv3 1/2] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state
Hello, On Mon, Jan 19, 2015 at 12:55:47PM -0600, Felipe Balbi wrote: On Mon, Jan 19, 2015 at 03:09:44PM +0100, Nicolas Ferre wrote: Le 18/01/2015 18:24, Sylvain Rochet a écrit : If vbus gpio is high at init, we should set vbus_prev to true accordingly to the current vbus state. Without that, we skip the first vbus interrupt because the saved vbus state is not consistent. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Indeed: Acked-by: Nicolas Ferre nicolas.fe...@atmel.com We can also add the following tags: Fixes: 914a3f3b3754 (USB: add atmel_usba_udc driver) Cc: sta...@vger.kernel.org # 2.6.x-ish Please resend with the proper stable format. Also, this 2.6.x-ish should be 2.6.24+, git describe helps a lot figuring these out. Unfortunately I failed to understand what I should do. The Also keyword means for me that there are two differents things to fix: 1. proper stable format 2. 2.6.x-ish → 2.6.24+ 2. does not imply fixing 1., isn'it ? I read SubmittingPatches thoroughly and I can't find a reference to stable format. Sylvain -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 09/11] hso: update serial_table in usb disconnect method
The serial_table is used to map the minor number of the usb serial device to its associated context. The table is updated in the probe method and in hso_serial_ref_free() which is called either from the tty cleanup method or from the usb disconnect method. This patch ensures that the serial_table is updated in the disconnect method and no more from the cleanup method to avoid the following potential race condition. - hso_disconnect() is called for usb interface x. Because the serial port was open and because the cleanup method of the tty_port hasn't been called yet, hso_serial_ref_free() is not run. - hso_probe() is called and fails for a new hso serial usb interface y. The function hso_free_interface() is called and iterates over the element of serial_table to find the device associated to the usb interface context. If the usb interface context of usb interface y has been created at the same place as for usb interface x, then the cleanup functions are called for usb interfaces x and y and hso_serial_ref_free() is called for both interfaces. - release_tty() is called for serial port linked to usb interface x and possibly crash because the tty_port structure contained in the hso_device structure has been freed. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 5b157ad..c916ab5 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2597,7 +2597,6 @@ static void hso_free_serial_device(struct hso_device *hso_dev) if (!serial) return; - set_serial_by_index(serial-minor, NULL); hso_serial_common_free(serial); @@ -3110,6 +3109,7 @@ static void hso_free_interface(struct usb_interface *interface) mutex_unlock(serial-parent-mutex); hso_serial_tty_unregister(serial); kref_put(serial_table[i]-ref, hso_serial_ref_free); + set_serial_by_index(i, NULL); } } -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 11/11] usb: core: fix a race with usb_queue_reset_device()
When usb_queue_reset() is called it schedules a work in view of resetting the usb interface. When the reset work is running, it can be scheduled again (e.g. by the usb disconnect method of the driver). Consider that the reset work is queued again while the reset work is running and that this work leads to a forced unbinding of the usb interface (e.g. because a driver is bound to the interface and has no pre/post_reset methods - see usb_reset_device()). In such condition, usb_unbind_interface() gets called and this function calls usb_cancel_queued_reset() which does nothing because the flag reset_running is set to 1. The second reset work that has been scheduled is therefore not cancelled. Later, the usb_reset_device() tries to rebind the interface. If it fails, then the usb interface context which contain the reset work struct is freed and it most likely crash when the second reset work tries to be run. The following flow shows the problem: * usb_queue_reset_device() * __usb_queue_reset_device() - If the reset work is queued after here, then reset_running = 1 it will never be cancelled. usb_reset_device() usb_forced_unbind_intf() usb_driver_release_interface() usb_unbind_interface() driver-disconnect() usb_queue_reset_device() - second reset usb_cancel_queued_reset() - does nothing because the flag reset_running is set usb_unbind_and_rebind_marked_interfaces() usb_rebind_intf() device_attach() driver-probe() - fails (no more drivers hold a reference to the usb interface) reset_running = 0 * hub_event() usb_disconnect() usb_disable_device() kobject_release() device_release() usb_release_interface() kfree(intf) - usb interface context is released while we still have a pending reset work that should be run To avoid this problem, we use a delayed work so that if the reset work is currently run, we can avoid further call to __usb_queue_reset_device() work by using cancel_delayed_work(). Unfortunately it increases the size of the usb_interface structure... Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/usb/core/driver.c | 4 +++- drivers/usb/core/hub.c | 4 ++-- drivers/usb/core/message.c | 4 ++-- include/linux/usb.h| 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9bffd26..c93f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -287,7 +287,9 @@ static int usb_unbind_device(struct device *dev) static void usb_cancel_queued_reset(struct usb_interface *iface) { if (iface-reset_running == 0) - cancel_work_sync(iface-reset_ws); + cancel_delayed_work_sync(iface-reset_ws); + else + cancel_delayed_work(iface-reset_ws); } /* called from driver core with dev locked */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b649fef..52fba97 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5604,13 +5604,13 @@ EXPORT_SYMBOL_GPL(usb_reset_device); * NOTE: We don't do any reference count tracking because it is not * needed. The lifecycle of the work_struct is tied to the * usb_interface. Before destroying the interface we cancel the - * work_struct, so the fact that work_struct is queued and or + * delayed_work, so the fact that delayed_work is queued and or * running means the interface (and thus, the device) exist and * are referenced. */ void usb_queue_reset_device(struct usb_interface *iface) { - schedule_work(iface-reset_ws); + schedule_delayed_work(iface-reset_ws, 0); } EXPORT_SYMBOL_GPL(usb_queue_reset_device); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index f7b7713..d9f3f68 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1650,7 +1650,7 @@ static void __usb_queue_reset_device(struct work_struct *ws) { int rc; struct usb_interface *iface = - container_of(ws, struct usb_interface, reset_ws); + container_of(ws, struct usb_interface, reset_ws.work); struct usb_device *udev = interface_to_usbdev(iface); rc = usb_lock_device_for_reset(udev, iface); @@ -1847,7 +1847,7 @@ free_interfaces: intf-dev.type = usb_if_device_type; intf-dev.groups = usb_interface_groups; intf-dev.dma_mask = dev-dev.dma_mask; - INIT_WORK(intf-reset_ws, __usb_queue_reset_device); + INIT_DELAYED_WORK(intf-reset_ws, __usb_queue_reset_device); intf-minor = -1; device_initialize(intf-dev);
[PATCH 08/11] hso: move tty_unregister outside hso_serial_common_free()
The function hso_serial_common_free() is called either by the cleanup method of the tty or by the usb disconnect method. In the former case, the usb_disconnect() has been already called and the sysfs group associated to the device has been removed. By calling tty_unregister directly from the usb_disconnect() method, we avoid a warning due to the removal of the sysfs group of the usb device. Example of warning: [ cut here ] WARNING: CPU: 0 PID: 778 at fs/sysfs/group.c:225 sysfs_remove_group+0x50/0x94() sysfs group c0645a88 not found for kobject 'ttyHS5' Modules linked in: CPU: 0 PID: 778 Comm: kworker/0:3 Tainted: GW 3.18.0+ #105 Workqueue: events release_one_tty [c000dfe4] (unwind_backtrace) from [c000c014] (show_stack+0x14/0x1c) [c000c014] (show_stack) from [c0016bac] (warn_slowpath_common+0x5c/0x7c) [c0016bac] (warn_slowpath_common) from [c0016c60] (warn_slowpath_fmt+0x30/0x40) [c0016c60] (warn_slowpath_fmt) from [c00ddd14] (sysfs_remove_group+0x50/0x94) [c00ddd14] (sysfs_remove_group) from [c0221e44] (device_del+0x30/0x190) [c0221e44] (device_del) from [c0221fb0] (device_unregister+0xc/0x18) [c0221fb0] (device_unregister) from [c0221fec] (device_destroy+0x30/0x3c) [c0221fec] (device_destroy) from [c01fe1dc] (tty_unregister_device+0x2c/0x5c) [c01fe1dc] (tty_unregister_device) from [c029a428] (hso_serial_common_free+0x2c/0x88) [c029a428] (hso_serial_common_free) from [c029a4c0] (hso_serial_ref_free+0x3c/0xb8) [c029a4c0] (hso_serial_ref_free) from [c01ff430] (release_one_tty+0x30/0x84) [c01ff430] (release_one_tty) from [c00271d4] (process_one_work+0x21c/0x3c8) [c00271d4] (process_one_work) from [c0027758] (worker_thread+0x3d8/0x560) [c0027758] (worker_thread) from [c002be4c] (kthread+0xc0/0xcc) [c002be4c] (kthread) from [c0009630] (ret_from_fork+0x14/0x24) ---[ end trace cb88537fdc8fa208 ]--- Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 12 +--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 55074da..5b157ad 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2234,14 +2234,17 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) return 0; } -static void hso_serial_common_free(struct hso_serial *serial) +static void hso_serial_tty_unregister(struct hso_serial *serial) { - int i; - if (serial-parent-dev) device_remove_file(serial-parent-dev, dev_attr_hsotype); tty_unregister_device(tty_drv, serial-minor); +} + +static void hso_serial_common_free(struct hso_serial *serial) +{ + int i; for (i = 0; i serial-num_rx_urbs; i++) { /* unlink and free RX URB */ @@ -2323,6 +2326,7 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, return 0; exit: + hso_serial_tty_unregister(serial); hso_serial_common_free(serial); return -1; } @@ -2683,6 +2687,7 @@ static struct hso_device *hso_create_bulk_serial_device( return hso_dev; exit2: + hso_serial_tty_unregister(serial); hso_serial_common_free(serial); exit: hso_free_tiomget(serial); @@ -3103,6 +3108,7 @@ static void hso_free_interface(struct usb_interface *interface) mutex_lock(serial-parent-mutex); serial-parent-usb_gone = 1; mutex_unlock(serial-parent-mutex); + hso_serial_tty_unregister(serial); kref_put(serial_table[i]-ref, hso_serial_ref_free); } } -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 07/11] hso: replace reset_device work by usb_queue_reset_device()
There is no need for a dedicated reset work in the hso driver since there is already a reset work foreseen in usb_interface that does the same. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 25 + 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 484e423..55074da 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -274,7 +274,6 @@ struct hso_device { u8 usb_gone; struct work_struct async_get_intf; struct work_struct async_put_intf; - struct work_struct reset_device; struct usb_device *usb; struct usb_interface *interface; @@ -340,7 +339,6 @@ static void async_put_intf(struct work_struct *data); static int hso_put_activity(struct hso_device *hso_dev); static int hso_get_activity(struct hso_device *hso_dev); static void tiocmget_intr_callback(struct urb *urb); -static void reset_device(struct work_struct *data); /*/ /* Helping functions */ /*/ @@ -696,7 +694,7 @@ static void handle_usb_error(int status, const char *function, case -ETIMEDOUT: explanation = protocol error; if (hso_dev) - schedule_work(hso_dev-reset_device); + usb_queue_reset_device(hso_dev-interface); break; default: explanation = unknown status; @@ -2347,7 +2345,6 @@ static struct hso_device *hso_create_device(struct usb_interface *intf, INIT_WORK(hso_dev-async_get_intf, async_get_intf); INIT_WORK(hso_dev-async_put_intf, async_put_intf); - INIT_WORK(hso_dev-reset_device, reset_device); return hso_dev; } @@ -3086,26 +3083,6 @@ out: return result; } -static void reset_device(struct work_struct *data) -{ - struct hso_device *hso_dev = - container_of(data, struct hso_device, reset_device); - struct usb_device *usb = hso_dev-usb; - int result; - - if (hso_dev-usb_gone) { - D1(No reset during disconnect\n); - } else { - result = usb_lock_device_for_reset(usb, hso_dev-interface); - if (result 0) - D1(unable to lock device for reset: %d\n, result); - else { - usb_reset_device(usb); - usb_unlock_device(usb); - } - } -} - static void hso_serial_ref_free(struct kref *ref) { struct hso_device *hso_dev = container_of(ref, struct hso_device, ref); -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv6 0/6] USB: host: Atmel OHCI and EHCI drivers improvements
Le 19/01/2015 12:06, Sylvain Rochet a écrit : USB: host: Atmel OHCI and EHCI drivers improvements Suspend/resume support for EHCI. struct dev_pm_ops for OHCI. Removed global variables from both. Fixed OHCI wake up support for STANDBY(wake-up enabled) and MEM(wake-up disabled) sleep targets. Changes since v5: * Don't overwrite device wakeup flag with device_init_wakeup(), now using a private wakeup bool instead. Changes since v4: * Re-add at91_suspend_entering_slow_clock() to OHCI, we can't naively remove this one, this device needs to be continuously clocked to provide wake up support. The removal of at91_suspend_entering_slow_clock() actually lighted up an issue on wake up support, which is now fixed. Changes since v3: * Using struct dev_pm_ops instead of static struct platform_driver resume and suspend bindings for both EHCI and OHCI * Fixed inconsistency in patch subjects, _ intead of - for file names * Patch cleaning with the help of checkpatch.pl, fixed lines over 80 characters Changes since v2: * Added patchs from an other submission, because this series depended on this one * EHCI: Move global variables to private struct * OHCI: Move global variables to private struct * Using ohci-priv and ehci-priv instead of hcd-hcd_priv, which were not the right way to do that Changes since v1: * Don't use at91_suspend_entering_slow_clock() on EHCI, we are trying to get read of this of this function * Removed at91_suspend_entering_slow_clock() from OHCI Sylvain Rochet (6): USB: host: ehci-atmel: Add suspend/resume support USB: host: ohci-at91: Use struct dev_pm_ops instead of struct platform_driver USB: host: ehci-atmel: Move global variables to private struct USB: host: ohci-at91: Move global variables to private struct USB: host: ohci-at91: usb_hcd_at91_probe(), remove useless stack initialisation USB: host: ohci-at91: Fix wake-up support drivers/usb/host/ehci-atmel.c | 102 +- drivers/usb/host/ohci-at91.c | 126 ++ 2 files changed, 154 insertions(+), 74 deletions(-) As already mentioned for the v5, I'm okay with the whole series: Acked-by: Nicolas Ferre nicolas.fe...@atmel.com So Sylvain, as said by Alan, I think you can now collect all the Acked-by tags (Alex had also sent some if I recall well) and re-send a clean v7 series to Greg KH. BTW, for rewriting this series' logs, I suggest you to use: git filter-branch -f --msg-filter ... ;-) Bye, -- Nicolas Ferre -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv6 0/6] USB: host: Atmel OHCI and EHCI drivers improvements
On Mon, 19 Jan 2015 12:06:01 +0100 Sylvain Rochet sylvain.roc...@finsecur.com wrote: USB: host: Atmel OHCI and EHCI drivers improvements Suspend/resume support for EHCI. struct dev_pm_ops for OHCI. Removed global variables from both. Fixed OHCI wake up support for STANDBY(wake-up enabled) and MEM(wake-up disabled) sleep targets. To the whole series: Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Changes since v5: * Don't overwrite device wakeup flag with device_init_wakeup(), now using a private wakeup bool instead. Changes since v4: * Re-add at91_suspend_entering_slow_clock() to OHCI, we can't naively remove this one, this device needs to be continuously clocked to provide wake up support. The removal of at91_suspend_entering_slow_clock() actually lighted up an issue on wake up support, which is now fixed. Changes since v3: * Using struct dev_pm_ops instead of static struct platform_driver resume and suspend bindings for both EHCI and OHCI * Fixed inconsistency in patch subjects, _ intead of - for file names * Patch cleaning with the help of checkpatch.pl, fixed lines over 80 characters Changes since v2: * Added patchs from an other submission, because this series depended on this one * EHCI: Move global variables to private struct * OHCI: Move global variables to private struct * Using ohci-priv and ehci-priv instead of hcd-hcd_priv, which were not the right way to do that Changes since v1: * Don't use at91_suspend_entering_slow_clock() on EHCI, we are trying to get read of this of this function * Removed at91_suspend_entering_slow_clock() from OHCI Sylvain Rochet (6): USB: host: ehci-atmel: Add suspend/resume support USB: host: ohci-at91: Use struct dev_pm_ops instead of struct platform_driver USB: host: ehci-atmel: Move global variables to private struct USB: host: ohci-at91: Move global variables to private struct USB: host: ohci-at91: usb_hcd_at91_probe(), remove useless stack initialisation USB: host: ohci-at91: Fix wake-up support drivers/usb/host/ehci-atmel.c | 102 +- drivers/usb/host/ohci-at91.c | 126 ++ 2 files changed, 154 insertions(+), 74 deletions(-) -- Boris Brezillon, Free Electrons Embedded Linux and Kernel engineering http://free-electrons.com -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/4] toshiba_acpi: Add support for USB Sleep functions
On Sun, 2015-01-18 at 18:30 -0700, Azael Avalos wrote: The following patches add support to several USB Sleep functions found on newer Toshiba laptops, allowing to use the USB ports while the laptop is asleep or turned off. Hi, this is most interesting. But the interface is terrible. If possible we would like to have a generic interface for this, which should not depend on the specific platform in use and would have to be per bus or even per port (for example the ports on a Thunderbolt dock would not work with your module). Do you think we could provide a hook from generic code into platform code to detect the capability for power control? Regards Oliver -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 06/11] hso: rename hso_dev into serial in hso_free_interface()
In other functions of the driver, variables of type struct hso_serial are denoted by serial and variables of type struct hso_device are denoted by hso_dev. This patch makes the hso_free_interface() consistent with these notations. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 2f2343d..484e423 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -3115,17 +3115,17 @@ static void hso_serial_ref_free(struct kref *ref) static void hso_free_interface(struct usb_interface *interface) { - struct hso_serial *hso_dev; + struct hso_serial *serial; int i; for (i = 0; i HSO_SERIAL_TTY_MINORS; i++) { if (serial_table[i] (serial_table[i]-interface == interface)) { - hso_dev = dev2ser(serial_table[i]); - tty_port_tty_hangup(hso_dev-port, false); - mutex_lock(hso_dev-parent-mutex); - hso_dev-parent-usb_gone = 1; - mutex_unlock(hso_dev-parent-mutex); + serial = dev2ser(serial_table[i]); + tty_port_tty_hangup(serial-port, false); + mutex_lock(serial-parent-mutex); + serial-parent-usb_gone = 1; + mutex_unlock(serial-parent-mutex); kref_put(serial_table[i]-ref, hso_serial_ref_free); } } -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 2/2] mfd: dln2: add suspend/resume functionality
On Mon, 19 Jan 2015, Octavian Purdila wrote: Without suspend/resume functionality in the USB driver the USB core will disconnect and reconnect the DLN2 port and because the GPIO framework does not yet support removal of an in-use controller a suspend/resume operation will result in a crash. This patch provides suspend and resume functions for the DLN2 driver so that the above scenario is avoided, if the host controller does not drop VBUS during suspend, since in this case the device state is preserved. We chose not implemented reset_resume so that if the host controller does drop VBUS the resume path will go through above the disconnect/reconnect process since it is probably better to fix the GPIO framework disconnect issue then to save and restore the device state for every driver. Signed-off-by: Octavian Purdila octavian.purd...@intel.com Reviewed-by: Johan Hovold jo...@kernel.org With Johan's Ack, I'm fairly sure I can just apply this without an in depth review from me. After a quick glance; applied, thanks. --- drivers/mfd/dln2.c | 20 1 file changed, 20 insertions(+) diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 8311820..1be9bd1 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -791,6 +791,24 @@ out_free: return ret; } +static int dln2_suspend(struct usb_interface *iface, pm_message_t message) +{ + struct dln2_dev *dln2 = usb_get_intfdata(iface); + + dln2_stop(dln2); + + return 0; +} + +static int dln2_resume(struct usb_interface *iface) +{ + struct dln2_dev *dln2 = usb_get_intfdata(iface); + + dln2-disconnect = false; + + return dln2_start_rx_urbs(dln2, GFP_NOIO); +} + static const struct usb_device_id dln2_table[] = { { USB_DEVICE(0xa257, 0x2013) }, { } @@ -803,6 +821,8 @@ static struct usb_driver dln2_driver = { .probe = dln2_probe, .disconnect = dln2_disconnect, .id_table = dln2_table, + .suspend = dln2_suspend, + .resume = dln2_resume, }; module_usb_driver(dln2_driver); -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 1/2] mfd: dln2: add start/stop RX URBs helpers
On Mon, 19 Jan 2015, Octavian Purdila wrote: This is in preparation for adding suspend / resume support. Signed-off-by: Octavian Purdila octavian.purd...@intel.com Reviewed-by: Johan Hovold jo...@kernel.org --- drivers/mfd/dln2.c | 51 +-- 1 file changed, 41 insertions(+), 10 deletions(-) With Johan's Ack, I'm fairly sure I can just apply this without an in depth review from me. After a quick glance; applied, thanks. diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 6d49685..8311820 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -587,12 +587,19 @@ static void dln2_free_rx_urbs(struct dln2_dev *dln2) int i; for (i = 0; i DLN2_MAX_URBS; i++) { - usb_kill_urb(dln2-rx_urb[i]); usb_free_urb(dln2-rx_urb[i]); kfree(dln2-rx_buf[i]); } } +static void dln2_stop_rx_urbs(struct dln2_dev *dln2) +{ + int i; + + for (i = 0; i DLN2_MAX_URBS; i++) + usb_kill_urb(dln2-rx_urb[i]); +} + static void dln2_free(struct dln2_dev *dln2) { dln2_free_rx_urbs(dln2); @@ -604,9 +611,7 @@ static int dln2_setup_rx_urbs(struct dln2_dev *dln2, struct usb_host_interface *hostif) { int i; - int ret; const int rx_max_size = DLN2_RX_BUF_SIZE; - struct device *dev = dln2-interface-dev; for (i = 0; i DLN2_MAX_URBS; i++) { dln2-rx_buf[i] = kmalloc(rx_max_size, GFP_KERNEL); @@ -620,8 +625,19 @@ static int dln2_setup_rx_urbs(struct dln2_dev *dln2, usb_fill_bulk_urb(dln2-rx_urb[i], dln2-usb_dev, usb_rcvbulkpipe(dln2-usb_dev, dln2-ep_in), dln2-rx_buf[i], rx_max_size, dln2_rx, dln2); + } + + return 0; +} - ret = usb_submit_urb(dln2-rx_urb[i], GFP_KERNEL); +static int dln2_start_rx_urbs(struct dln2_dev *dln2, gfp_t gfp) +{ + struct device *dev = dln2-interface-dev; + int ret; + int i; + + for (i = 0; i DLN2_MAX_URBS; i++) { + ret = usb_submit_urb(dln2-rx_urb[i], gfp); if (ret 0) { dev_err(dev, failed to submit RX URB: %d\n, ret); return ret; @@ -665,9 +681,8 @@ static const struct mfd_cell dln2_devs[] = { }, }; -static void dln2_disconnect(struct usb_interface *interface) +static void dln2_stop(struct dln2_dev *dln2) { - struct dln2_dev *dln2 = usb_get_intfdata(interface); int i, j; /* don't allow starting new transfers */ @@ -696,6 +711,15 @@ static void dln2_disconnect(struct usb_interface *interface) /* wait for transfers to end */ wait_event(dln2-disconnect_wq, !dln2-active_transfers); + dln2_stop_rx_urbs(dln2); +} + +static void dln2_disconnect(struct usb_interface *interface) +{ + struct dln2_dev *dln2 = usb_get_intfdata(interface); + + dln2_stop(dln2); + mfd_remove_devices(interface-dev); dln2_free(dln2); @@ -738,23 +762,30 @@ static int dln2_probe(struct usb_interface *interface, ret = dln2_setup_rx_urbs(dln2, hostif); if (ret) - goto out_cleanup; + goto out_free; + + ret = dln2_start_rx_urbs(dln2, GFP_KERNEL); + if (ret) + goto out_stop_rx; ret = dln2_hw_init(dln2); if (ret 0) { dev_err(dev, failed to initialize hardware\n); - goto out_cleanup; + goto out_stop_rx; } ret = mfd_add_hotplug_devices(dev, dln2_devs, ARRAY_SIZE(dln2_devs)); if (ret != 0) { dev_err(dev, failed to add mfd devices to core\n); - goto out_cleanup; + goto out_stop_rx; } return 0; -out_cleanup: +out_stop_rx: + dln2_stop_rx_urbs(dln2); + +out_free: dln2_free(dln2); return ret; -- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 00/11] hso: fix some problems with reset/disconnect path
These patches attempt to fix some problems I observed when the hso device is disconnected or when a usb reset is queued by the hso driver Several patches of this serie are fixing crashes or memleaks in hso. The last patch of this serie fix a race condition occurring when multiple usb resets are queued on an usb interface. This serie of patches is based on v3.18. Olivier Sobrie (11): hso: remove useless header file timer.h hso: fix crash when device disappears while serial port is open hso: fix memory leak when device disconnects hso: fix memory leak in hso_create_rfkill() hso: fix small indentation error hso: rename hso_dev into serial in hso_free_interface() hso: replace reset_device work by usb_queue_reset_device() hso: move tty_unregister outside hso_serial_common_free() hso: update serial_table in usb disconnect method hso: add missing cancel_work_sync in disconnect() usb: core: fix a race with usb_queue_reset_device() drivers/net/usb/hso.c | 88 -- drivers/usb/core/driver.c | 4 ++- drivers/usb/core/hub.c | 4 +-- drivers/usb/core/message.c | 4 +-- include/linux/usb.h| 2 +- 5 files changed, 46 insertions(+), 56 deletions(-) -- 2.2.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCHv2 3/4] usb: gadget: uvc: use explicit type instead of void *
Hi Andrzej, On Tuesday 20 January 2015 08:56:47 Andrzej Pietrasiewicz wrote: W dniu 19.01.2015 o 22:30, Laurent Pinchart pisze: On Monday 19 January 2015 23:27:28 Laurent Pinchart wrote: On Monday 19 January 2015 13:52:57 Andrzej Pietrasiewicz wrote: The first parameter of __uvcg_iter_strm_cls() is always used in the context of struct uvcg_streaming_header, so change the function prototype accordingly. Signed-off-by: Andrzej Pietrasiewicz andrze...@samsung.com Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com I spoke too fast. Shouldn't the first argument of the callback function be a struct uvcg_streaming_header * as well ? Both __uvcg_count_strm() and __uvcg_fill_strm() use their 1st parameter in different contexts, depending whether they are called at the streaming header, format or frame level. That is why originally the 1st parameter of __uvcg_iter_strm_cls() was a void * - to emphasize the fact that what is propagated to the callbacks as the 1st parameter is not always the same type of thing. Right. Let's keep it as-is then. For the whole series, Acked-by: Laurent Pinchart laurent.pinch...@ideasonboard.com -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Maximum bitrate for CDC ECM
I am trying to use g_ether with a USB 3 gadget (PLX 3380). During testing I noticed that the transfer speed is much lower than expected at 42MB/s vs a 95Mb/s for a gigabit connection between the same machines. The same gadget is capable of transferring 170MB/s via USB 3 when reading from a g_mass_storage provided virtual drive. Perusing the code of f_ecm.c I noticed that the maximum theoretical bitrate for USB 3 gadgets is calculated as 13 * 1024 * 8 * 1000 * 8 = 851,968,000 (roughly 850Mbit/s) and for USB 2 gadgets as 13 * 512 * 8 * 1000 * 8 = 425,984,000 (roughly 425 Mbit/s). I was wondering what that calculation is based on? The 1024/512 seem to be the IN/OUT buffer size being used. Technically USB3 allows for a native bitrate (after 8/10b coding) of 4Gbit/s. Regards, Paul. On 18 Jan 2015, at 16:49, Paul Jones p.jo...@teclyn.com wrote: Ricardo, I think I figured out the problem: my 3380 was running in legacy adapter mode. I am now capable of connecting both g_mass_storage and g_ether without any kernel panics after ensuring the 3380 is in enhanced adapter mode. My only concern is the speed from my Mac to Linux: - g_ether: scp transfer 42Mb/s - g_mass_storage: dd bs=64k 116Mb/s (backed by SSD storage) For comparison, a direct gigabit connection allows between 90 and 95Mb/s using scp between the machines. Local writes on the linux side using dd is around 480Mb/s (on the same SSD storage). Any ideas on how to achieve a higher performance? Regards, Paul. -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv7 6/6] USB: host: ohci-at91: Fix wake-up support
This device needs to be continuously clocked to provide wake up support, previously, if STANDBY target were chosen the device were enable_irq_wake()-prepared and clock still active and if MEM target were chosen the device were also enable_irq_wake()-prepared but not clocked anymore, which is wrong. Now, if STANDBY target is chosen the device is still clocked with wake up support enabled, which were the previous default and if MEM target is chosen the device is declocked with wake up support disabled. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/usb/host/ohci-at91.c | 27 +++ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 970a776..1fc5610 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -42,6 +42,7 @@ struct ohci_at91_priv { struct clk *uclk; struct clk *hclk; bool clocked; + bool wakeup;/* Saved wake-up state for resume */ }; /* interface and function clocks; sometimes also an AHB clock */ @@ -61,6 +62,8 @@ extern int usb_disabled(void); static void at91_start_clock(struct ohci_at91_priv *ohci_at91) { + if (ohci_at91-clocked) + return; if (IS_ENABLED(CONFIG_COMMON_CLK)) { clk_set_rate(ohci_at91-uclk, 4800); clk_prepare_enable(ohci_at91-uclk); @@ -73,6 +76,8 @@ static void at91_start_clock(struct ohci_at91_priv *ohci_at91) static void at91_stop_clock(struct ohci_at91_priv *ohci_at91) { + if (!ohci_at91-clocked) + return; clk_disable_unprepare(ohci_at91-fclk); clk_disable_unprepare(ohci_at91-iclk); clk_disable_unprepare(ohci_at91-hclk); @@ -614,15 +619,22 @@ ohci_hcd_at91_drv_suspend(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd); - booldo_wakeup = device_may_wakeup(dev); int ret; - if (do_wakeup) + /* +* Disable wakeup if we are going to sleep with slow clock mode +* enabled. +*/ + ohci_at91-wakeup = device_may_wakeup(dev) +!at91_suspend_entering_slow_clock(); + + if (ohci_at91-wakeup) enable_irq_wake(hcd-irq); - ret = ohci_suspend(hcd, do_wakeup); + ret = ohci_suspend(hcd, ohci_at91-wakeup); if (ret) { - disable_irq_wake(hcd-irq); + if (ohci_at91-wakeup) + disable_irq_wake(hcd-irq); return ret; } /* @@ -632,7 +644,7 @@ ohci_hcd_at91_drv_suspend(struct device *dev) * * REVISIT: some boards will be able to turn VBUS off... */ - if (at91_suspend_entering_slow_clock()) { + if (!ohci_at91-wakeup) { ohci-hc_control = ohci_readl(ohci, ohci-regs-control); ohci-hc_control = OHCI_CTRL_RWC; ohci_writel(ohci, ohci-hc_control, ohci-regs-control); @@ -651,11 +663,10 @@ static int ohci_hcd_at91_drv_resume(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd); - if (device_may_wakeup(dev)) + if (ohci_at91-wakeup) disable_irq_wake(hcd-irq); - if (!ohci_at91-clocked) - at91_start_clock(ohci_at91); + at91_start_clock(ohci_at91); ohci_resume(hcd, false); return 0; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv7 4/6] USB: host: ohci-at91: Move global variables to private struct
This patch move AT91 OHCI global variables (clocks ptr and clocked boolean) to private struct ohci_at91_priv, stored in ohci-priv. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/usb/host/ohci-at91.c | 84 +++- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 65e7836..c810917 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -33,7 +33,16 @@ for ((index) = 0; (index) AT91_MAX_USBH_PORTS; (index)++) /* interface, function and usb clocks; sometimes also an AHB clock */ -static struct clk *iclk, *fclk, *uclk, *hclk; +#define hcd_to_ohci_at91_priv(h) \ + ((struct ohci_at91_priv *)hcd_to_ohci(h)-priv) + +struct ohci_at91_priv { + struct clk *iclk; + struct clk *fclk; + struct clk *uclk; + struct clk *hclk; + bool clocked; +}; /* interface and function clocks; sometimes also an AHB clock */ #define DRIVER_DESC OHCI Atmel driver @@ -41,45 +50,49 @@ static struct clk *iclk, *fclk, *uclk, *hclk; static const char hcd_name[] = ohci-atmel; static struct hc_driver __read_mostly ohci_at91_hc_driver; -static int clocked; + +static const struct ohci_driver_overrides ohci_at91_drv_overrides __initconst = { + .extra_priv_size = sizeof(struct ohci_at91_priv), +}; extern int usb_disabled(void); /*-*/ -static void at91_start_clock(void) +static void at91_start_clock(struct ohci_at91_priv *ohci_at91) { if (IS_ENABLED(CONFIG_COMMON_CLK)) { - clk_set_rate(uclk, 4800); - clk_prepare_enable(uclk); + clk_set_rate(ohci_at91-uclk, 4800); + clk_prepare_enable(ohci_at91-uclk); } - clk_prepare_enable(hclk); - clk_prepare_enable(iclk); - clk_prepare_enable(fclk); - clocked = 1; + clk_prepare_enable(ohci_at91-hclk); + clk_prepare_enable(ohci_at91-iclk); + clk_prepare_enable(ohci_at91-fclk); + ohci_at91-clocked = true; } -static void at91_stop_clock(void) +static void at91_stop_clock(struct ohci_at91_priv *ohci_at91) { - clk_disable_unprepare(fclk); - clk_disable_unprepare(iclk); - clk_disable_unprepare(hclk); + clk_disable_unprepare(ohci_at91-fclk); + clk_disable_unprepare(ohci_at91-iclk); + clk_disable_unprepare(ohci_at91-hclk); if (IS_ENABLED(CONFIG_COMMON_CLK)) - clk_disable_unprepare(uclk); - clocked = 0; + clk_disable_unprepare(ohci_at91-uclk); + ohci_at91-clocked = false; } static void at91_start_hc(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd-regs; + struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd); dev_dbg(pdev-dev, start\n); /* * Start the USB clocks. */ - at91_start_clock(); + at91_start_clock(ohci_at91); /* * The USB host controller must remain in reset. @@ -91,6 +104,7 @@ static void at91_stop_hc(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_regs __iomem *regs = hcd-regs; + struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd); dev_dbg(pdev-dev, stop\n); @@ -102,7 +116,7 @@ static void at91_stop_hc(struct platform_device *pdev) /* * Stop the USB clocks. */ - at91_stop_clock(); + at91_stop_clock(ohci_at91); } @@ -129,6 +143,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, struct ohci_hcd *ohci; int retval; struct usb_hcd *hcd = NULL; + struct ohci_at91_priv *ohci_at91; struct device *dev = pdev-dev; struct resource *res; int irq; @@ -142,6 +157,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, hcd = usb_create_hcd(driver, dev, at91); if (!hcd) return -ENOMEM; + ohci_at91 = hcd_to_ohci_at91_priv(hcd); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd-regs = devm_ioremap_resource(dev, res); @@ -152,29 +168,29 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, hcd-rsrc_start = res-start; hcd-rsrc_len = resource_size(res); - iclk = devm_clk_get(dev, ohci_clk); - if (IS_ERR(iclk)) { + ohci_at91-iclk = devm_clk_get(dev, ohci_clk); + if (IS_ERR(ohci_at91-iclk)) { dev_err(dev, failed to get ohci_clk\n); - retval = PTR_ERR(iclk); + retval = PTR_ERR(ohci_at91-iclk); goto
[PATCHv7 0/6] USB: host: Atmel OHCI and EHCI drivers improvements
USB: host: Atmel OHCI and EHCI drivers improvements Suspend/resume support for EHCI. struct dev_pm_ops for OHCI. Removed global variables from both. Fixed OHCI wake up support for STANDBY(wake-up enabled) and MEM(wake-up disabled) sleep targets. Changes since v6: * Collected Acked-by tags Changes since v5: * Don't overwrite device wakeup flag with device_init_wakeup(), now using a private wakeup bool instead. Changes since v4: * Re-add at91_suspend_entering_slow_clock() to OHCI, we can't naively remove this one, this device needs to be continuously clocked to provide wake up support. The removal of at91_suspend_entering_slow_clock() actually lighted up an issue on wake up support, which is now fixed. Changes since v3: * Using struct dev_pm_ops instead of static struct platform_driver resume and suspend bindings for both EHCI and OHCI * Fixed inconsistency in patch subjects, _ intead of - for file names * Patch cleaning with the help of checkpatch.pl, fixed lines over 80 characters Changes since v2: * Added patchs from an other submission, because this series depended on this one * EHCI: Move global variables to private struct * OHCI: Move global variables to private struct * Using ohci-priv and ehci-priv instead of hcd-hcd_priv, which were not the right way to do that Changes since v1: * Don't use at91_suspend_entering_slow_clock() on EHCI, we are trying to get read of this of this function * Removed at91_suspend_entering_slow_clock() from OHCI Sylvain Rochet (6): USB: host: ehci-atmel: Add suspend/resume support USB: host: ohci-at91: Use struct dev_pm_ops instead of struct platform_driver USB: host: ehci-atmel: Move global variables to private struct USB: host: ohci-at91: Move global variables to private struct USB: host: ohci-at91: usb_hcd_at91_probe(), remove useless stack initialisation USB: host: ohci-at91: Fix wake-up support drivers/usb/host/ehci-atmel.c | 102 +- drivers/usb/host/ohci-at91.c | 126 ++ 2 files changed, 154 insertions(+), 74 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv7 1/6] USB: host: ehci-atmel: Add suspend/resume support
This patch add suspend/resume support for Atmel EHCI, mostly about disabling and unpreparing clocks so USB PLL is stopped before entering sleep state. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Nicolas Ferre nicolas.fe...@atmel.com Acked-by: Alexandre Belloni alexandre.bell...@free-electrons.com --- drivers/usb/host/ehci-atmel.c | 31 +++ 1 file changed, 31 insertions(+) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 56a8850..5a15e3d 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -37,6 +37,8 @@ static int clocked; static void atmel_start_clock(void) { + if (clocked) + return; if (IS_ENABLED(CONFIG_COMMON_CLK)) { clk_set_rate(uclk, 4800); clk_prepare_enable(uclk); @@ -48,6 +50,8 @@ static void atmel_start_clock(void) static void atmel_stop_clock(void) { + if (!clocked) + return; clk_disable_unprepare(fclk); clk_disable_unprepare(iclk); if (IS_ENABLED(CONFIG_COMMON_CLK)) @@ -174,6 +178,29 @@ static int ehci_atmel_drv_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_PM +static int ehci_atmel_drv_suspend(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + int ret; + + ret = ehci_suspend(hcd, false); + if (ret) + return ret; + + atmel_stop_clock(); + return 0; +} + +static int ehci_atmel_drv_resume(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + + atmel_start_clock(); + return ehci_resume(hcd, false); +} +#endif + #ifdef CONFIG_OF static const struct of_device_id atmel_ehci_dt_ids[] = { { .compatible = atmel,at91sam9g45-ehci }, @@ -183,12 +210,16 @@ static const struct of_device_id atmel_ehci_dt_ids[] = { MODULE_DEVICE_TABLE(of, atmel_ehci_dt_ids); #endif +static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend, + ehci_atmel_drv_resume); + static struct platform_driver ehci_atmel_driver = { .probe = ehci_atmel_drv_probe, .remove = ehci_atmel_drv_remove, .shutdown = usb_hcd_platform_shutdown, .driver = { .name = atmel-ehci, + .pm = ehci_atmel_pm_ops, .of_match_table = of_match_ptr(atmel_ehci_dt_ids), }, }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv7 5/6] USB: host: ohci-at91: usb_hcd_at91_probe(), remove useless stack initialisation
struct usb_hcd *hcd = NULL; ... hcd = usb_create_hcd(driver, dev, at91); This patch remove *hcd useless initialisation Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/usb/host/ohci-at91.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index c810917..970a776 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -142,7 +142,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, struct at91_usbh_data *board; struct ohci_hcd *ohci; int retval; - struct usb_hcd *hcd = NULL; + struct usb_hcd *hcd; struct ohci_at91_priv *ohci_at91; struct device *dev = pdev-dev; struct resource *res; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv7 2/6] USB: host: ohci-at91: Use struct dev_pm_ops instead of struct platform_driver
This patch replace struct platform_driver.{resume,suspend} PM bindings to a new struct dev_pm_ops. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/usb/host/ohci-at91.c | 21 ++--- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index dc9e4e6..65e7836 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -593,11 +593,11 @@ static int ohci_hcd_at91_drv_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int -ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) +ohci_hcd_at91_drv_suspend(struct device *dev) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct usb_hcd *hcd = dev_get_drvdata(dev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); - booldo_wakeup = device_may_wakeup(pdev-dev); + booldo_wakeup = device_may_wakeup(dev); int ret; if (do_wakeup) @@ -629,11 +629,11 @@ ohci_hcd_at91_drv_suspend(struct platform_device *pdev, pm_message_t mesg) return ret; } -static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) +static int ohci_hcd_at91_drv_resume(struct device *dev) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct usb_hcd *hcd = dev_get_drvdata(dev); - if (device_may_wakeup(pdev-dev)) + if (device_may_wakeup(dev)) disable_irq_wake(hcd-irq); if (!clocked) @@ -642,19 +642,18 @@ static int ohci_hcd_at91_drv_resume(struct platform_device *pdev) ohci_resume(hcd, false); return 0; } -#else -#define ohci_hcd_at91_drv_suspend NULL -#define ohci_hcd_at91_drv_resume NULL #endif +static SIMPLE_DEV_PM_OPS(ohci_hcd_at91_pm_ops, ohci_hcd_at91_drv_suspend, + ohci_hcd_at91_drv_resume); + static struct platform_driver ohci_hcd_at91_driver = { .probe = ohci_hcd_at91_drv_probe, .remove = ohci_hcd_at91_drv_remove, .shutdown = usb_hcd_platform_shutdown, - .suspend= ohci_hcd_at91_drv_suspend, - .resume = ohci_hcd_at91_drv_resume, .driver = { .name = at91_ohci, + .pm = ohci_hcd_at91_pm_ops, .of_match_table = of_match_ptr(at91_ohci_dt_ids), }, }; -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv7 3/6] USB: host: ehci-atmel: Move global variables to private struct
This patch move Atmel EHCI global variables (clocks ptr and clocked boolean) to private struct atmel_ehci_priv, stored in ehci-priv. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Boris Brezillon boris.brezil...@free-electrons.com Acked-by: Alan Stern st...@rowland.harvard.edu Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/usb/host/ehci-atmel.c | 79 +++ 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index 5a15e3d..663f790 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -27,48 +27,66 @@ #define DRIVER_DESC EHCI Atmel driver static const char hcd_name[] = ehci-atmel; -static struct hc_driver __read_mostly ehci_atmel_hc_driver; /* interface and function clocks */ -static struct clk *iclk, *fclk, *uclk; -static int clocked; +#define hcd_to_atmel_ehci_priv(h) \ + ((struct atmel_ehci_priv *)hcd_to_ehci(h)-priv) + +struct atmel_ehci_priv { + struct clk *iclk; + struct clk *fclk; + struct clk *uclk; + bool clocked; +}; + +static struct hc_driver __read_mostly ehci_atmel_hc_driver; + +static const struct ehci_driver_overrides ehci_atmel_drv_overrides __initconst = { + .extra_priv_size = sizeof(struct atmel_ehci_priv), +}; /*-*/ -static void atmel_start_clock(void) +static void atmel_start_clock(struct atmel_ehci_priv *atmel_ehci) { - if (clocked) + if (atmel_ehci-clocked) return; if (IS_ENABLED(CONFIG_COMMON_CLK)) { - clk_set_rate(uclk, 4800); - clk_prepare_enable(uclk); + clk_set_rate(atmel_ehci-uclk, 4800); + clk_prepare_enable(atmel_ehci-uclk); } - clk_prepare_enable(iclk); - clk_prepare_enable(fclk); - clocked = 1; + clk_prepare_enable(atmel_ehci-iclk); + clk_prepare_enable(atmel_ehci-fclk); + atmel_ehci-clocked = true; } -static void atmel_stop_clock(void) +static void atmel_stop_clock(struct atmel_ehci_priv *atmel_ehci) { - if (!clocked) + if (!atmel_ehci-clocked) return; - clk_disable_unprepare(fclk); - clk_disable_unprepare(iclk); + clk_disable_unprepare(atmel_ehci-fclk); + clk_disable_unprepare(atmel_ehci-iclk); if (IS_ENABLED(CONFIG_COMMON_CLK)) - clk_disable_unprepare(uclk); - clocked = 0; + clk_disable_unprepare(atmel_ehci-uclk); + atmel_ehci-clocked = false; } static void atmel_start_ehci(struct platform_device *pdev) { + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd); + dev_dbg(pdev-dev, start\n); - atmel_start_clock(); + atmel_start_clock(atmel_ehci); } static void atmel_stop_ehci(struct platform_device *pdev) { + struct usb_hcd *hcd = platform_get_drvdata(pdev); + struct atmel_ehci_priv *atmel_ehci = hcd_to_atmel_ehci_priv(hcd); + dev_dbg(pdev-dev, stop\n); - atmel_stop_clock(); + atmel_stop_clock(atmel_ehci); } /*-*/ @@ -79,6 +97,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) const struct hc_driver *driver = ehci_atmel_hc_driver; struct resource *res; struct ehci_hcd *ehci; + struct atmel_ehci_priv *atmel_ehci; int irq; int retval; @@ -109,6 +128,7 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) retval = -ENOMEM; goto fail_create_hcd; } + atmel_ehci = hcd_to_atmel_ehci_priv(hcd); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hcd-regs = devm_ioremap_resource(pdev-dev, res); @@ -120,23 +140,23 @@ static int ehci_atmel_drv_probe(struct platform_device *pdev) hcd-rsrc_start = res-start; hcd-rsrc_len = resource_size(res); - iclk = devm_clk_get(pdev-dev, ehci_clk); - if (IS_ERR(iclk)) { + atmel_ehci-iclk = devm_clk_get(pdev-dev, ehci_clk); + if (IS_ERR(atmel_ehci-iclk)) { dev_err(pdev-dev, Error getting interface clock\n); retval = -ENOENT; goto fail_request_resource; } - fclk = devm_clk_get(pdev-dev, uhpck); - if (IS_ERR(fclk)) { + atmel_ehci-fclk = devm_clk_get(pdev-dev, uhpck); + if (IS_ERR(atmel_ehci-fclk)) { dev_err(pdev-dev, Error getting function clock\n); retval = -ENOENT; goto fail_request_resource; } if (IS_ENABLED(CONFIG_COMMON_CLK)) { - uclk = devm_clk_get(pdev-dev, usb_clk); - if (IS_ERR(uclk)) { + atmel_ehci-uclk = devm_clk_get(pdev-dev,
Re: [PATCH 11/11] usb: core: fix a race with usb_queue_reset_device()
On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote: When usb_queue_reset() is called it schedules a work in view of resetting the usb interface. When the reset work is running, it can be scheduled again (e.g. by the usb disconnect method of the driver). Consider that the reset work is queued again while the reset work is running and that this work leads to a forced unbinding of the usb interface (e.g. because a driver is bound to the interface and has no pre/post_reset methods - see usb_reset_device()). In such condition, usb_unbind_interface() gets called and this function calls usb_cancel_queued_reset() which does nothing because the flag reset_running is set to 1. The second reset work that has been scheduled is therefore not cancelled. Later, the usb_reset_device() tries to rebind the interface. If it fails, then the usb interface context which contain the reset work struct is freed and it most likely crash when the second reset work tries to be run. The following flow shows the problem: * usb_queue_reset_device() * __usb_queue_reset_device() - If the reset work is queued after here, then reset_running = 1 it will never be cancelled. usb_reset_device() usb_forced_unbind_intf() usb_driver_release_interface() usb_unbind_interface() driver-disconnect() usb_queue_reset_device() - second reset That is the sledgehammer approach. Wouldn't it be better to guarantee that usb_queue_reset_device() be a nop when reset_running==1 ? usb_cancel_queued_reset() - does nothing because the flag reset_running is set usb_unbind_and_rebind_marked_interfaces() usb_rebind_intf() device_attach() driver-probe() - fails (no more drivers hold a reference to the usb interface) reset_running = 0 * hub_event() usb_disconnect() usb_disable_device() kobject_release() device_release() usb_release_interface() kfree(intf) - usb interface context is released while we still have a pending reset work that should be run To avoid this problem, we use a delayed work so that if the reset work is currently run, we can avoid further call to __usb_queue_reset_device() work by using cancel_delayed_work(). Unfortunately it increases the size of the usb_interface structure... Regards Oliver -- Oliver Neukum oneu...@suse.de -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 001/001] usbhid: Fix initialisation and force effect modifications for the Microsoft Sidewinder Force Feedback Pro 2 joystick
Hi, Jim, in addition to what Alan said, here are some comments that I would like to be fixed in the v2. On Sun, Jan 18, 2015 at 11:07 AM, Jim Keir jimk...@oracledbadirect.com wrote: From: Jim Keir jimk...@yahoo.co.uk Signed-off-by: Jim Keir jimk...@yahoo.co.uk The Signed-off-by line is generally at the end of the commit message. This way, if someone else adds new changes to the patch, we can trace which modifications belongs to which. Currently the SWFF2 driver fails during initialisation, making the force capability of the joystick unusable. Further, there is a long-standing bug in the same driver where commands to update force parameters are addressed to the last-created force effect instead of the specified one, making it impossible to modify effects after their creation. Three bugs are addressed: 1) The FF2 driver (usbhid/hid-pidff.c) sends commands to the stick during ff_init. However, this is called inside a block where driver_input_lock is locked, so the results of these initial commands are discarded. This one is the killer, without this nothing else works. ff_init issues commands using hid_hw_request. This eventually goes to hid_input_report, which returns -EBUSY because driver_input_lock is locked. The change is to delay the ff_init call in hid-core.c until after this lock has been released. 2) The usbhid driver ignores an endpoint stall when sending control commands, causing the first few commands of the hid-pidff.c initialisation to get lost. usbhid/hid-core.c has been modified by copying lines into hid_ctrl from the hid_irq_in function in the same file. 3) The FF2 driver (usbhid/hid-pidff.c) does not set the effect ID when uploading an effect. The result is that the initial upload works but subsequent uploads to modify effect parameters are all directed at the last-created effect. Fully agree that you should split the commit in 3 if there are 3 issues (and to the rest Alan said also, but this is the most important I think). The targeted effect ID must be passed back to the device when effect parameters are changed. This is done at the start of pidff_set_condition_report, pidff_set_periodic_report etc. based on the value of pidff-block_load[PID_EFFECT_BLOCK_INDEX].value[0]. However, this value is only ever set during pidff_request_effect_upload. The result is stored in pidff-pid_id[effect-id] at the end of pid_upload_effect, for later use. However, if an effect is modified and re-sent then this identifier is not being copied back from pidff-pid_id[effect-id] before sending the command to the device. The fix is to do this at the start of pidff_upload_effect. This patch taken against kernel 3.13.0 --- diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 905e40a..a608ee6 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1546,9 +1546,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) On my local tree, hid_connect is at 1562. Is your patch based on the for-next branch of the HID tree? https://git.kernel.org/cgit/linux/kernel/git/jikos/hid.git return -ENODEV; } -if ((hdev-claimed HID_CLAIMED_INPUT) -(connect_mask HID_CONNECT_FF) hdev-ff_init) -hdev-ff_init(hdev); +/* Removed ff_init() call from here. It does device I/O but this + * is blocked because driver_input_lock is currently locked. */ Please don't. If the feedback driver needs to have access to the IO earlier, it needs to call hid_device_io_start() (and eventually hid_device_io_stop() if some other initialization are required). len = 0; if (hdev-claimed HID_CLAIMED_INPUT) @@ -2029,6 +2028,13 @@ static int hid_device_probe(struct device *dev) unlock: if (!hdev-io_started) up(hdev-driver_input_lock); + +if ((hdev-claimed HID_CLAIMED_INPUT) hdev-ff_init) { +/* Late init of PID force-feedback drivers moved to after + * unlock of driver_input_lock */ +hdev-ff_init(hdev); +} + Same comment as above. unlock_driver_lock: up(hdev-driver_lock); return ret; diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 029965e..5d34dd7 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -505,7 +505,12 @@ static void hid_ctrl(struct urb *urb) case -EPROTO:/* protocol error or unplug */ case -ECONNRESET:/* unlink */ case -ENOENT: +break; case -EPIPE:/* report not available */ +usbhid_mark_busy(usbhid); +clear_bit(HID_IN_RUNNING, usbhid-iofl); +set_bit(HID_CLEAR_HALT, usbhid-iofl); +schedule_work(usbhid-reset_work); break; default:/* error */ hid_warn(urb-dev, ctrl urb status %d received\n, status); diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 10b6167..3f8ea63 100644 ---
Re: [PATCH 11/11] usb: core: fix a race with usb_queue_reset_device()
Hi Oliver, On Tue, Jan 20, 2015 at 02:48:37PM +0100, Oliver Neukum wrote: On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote: When usb_queue_reset() is called it schedules a work in view of resetting the usb interface. When the reset work is running, it can be scheduled again (e.g. by the usb disconnect method of the driver). Consider that the reset work is queued again while the reset work is running and that this work leads to a forced unbinding of the usb interface (e.g. because a driver is bound to the interface and has no pre/post_reset methods - see usb_reset_device()). In such condition, usb_unbind_interface() gets called and this function calls usb_cancel_queued_reset() which does nothing because the flag reset_running is set to 1. The second reset work that has been scheduled is therefore not cancelled. Later, the usb_reset_device() tries to rebind the interface. If it fails, then the usb interface context which contain the reset work struct is freed and it most likely crash when the second reset work tries to be run. The following flow shows the problem: * usb_queue_reset_device() * __usb_queue_reset_device() - If the reset work is queued after here, then reset_running = 1 it will never be cancelled. usb_reset_device() usb_forced_unbind_intf() usb_driver_release_interface() usb_unbind_interface() driver-disconnect() usb_queue_reset_device() - second reset That is the sledgehammer approach. Wouldn't it be better to guarantee that usb_queue_reset_device() be a nop when reset_running==1 ? If I'm right, we have to prevent that usb_queue_reset_device() shedules the work a second time before the variable reset_running is set. An other task can requeue a reset while the work __usb_queue_reset_device() is busy but when the flag reset_running hasn't been set yet. I see different other approaches to solve the problem: * Setting a flag in the usb_queue_reset_device() when a reset has been scheduled and resetting this flag when the reset is done. This implies a locking mechanism around the flag. * Avoid that the hso driver queues multiple resets by using a flag. It also requires locking. It comes more or less to the same solution as the previous one but the patch is done in the hso driver. * using get_device() and put_device() to avoid that the usb interface structure get freed before the second reset is run. I mean: void usb_queue_reset_device(struct usb_interface *iface) { get_device() if (!schedule_work(iface-reset_ws)) put_device() } static void __usb_queue_reset_device(struct work_struct *ws) { ... put_device() } But this solution does not avoid the second reset... If you have other better ideas, let me know. Correct me if I'm wrong. Thank you, Olivier usb_cancel_queued_reset() - does nothing because the flag reset_running is set usb_unbind_and_rebind_marked_interfaces() usb_rebind_intf() device_attach() driver-probe() - fails (no more drivers hold a reference to the usb interface) reset_running = 0 * hub_event() usb_disconnect() usb_disable_device() kobject_release() device_release() usb_release_interface() kfree(intf) - usb interface context is released while we still have a pending reset work that should be run To avoid this problem, we use a delayed work so that if the reset work is currently run, we can avoid further call to __usb_queue_reset_device() work by using cancel_delayed_work(). Unfortunately it increases the size of the usb_interface structure... Regards Oliver -- Oliver Neukum oneu...@suse.de -- Olivier -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/11] hso: fix memory leak in hso_create_rfkill()
On Tue, Jan 20, 2015 at 02:13:17PM +0100, Oliver Neukum wrote: On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote: When the rfkill interface was created, a buffer containing the name of the rfkill node was allocated. This buffer was never freed when the device disappears. To fix the problem, we put the name given to rfkill_alloc() in the hso_net structure. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 470ef9e..a49ac2e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -153,6 +153,7 @@ struct hso_net { struct hso_device *parent; struct net_device *net; struct rfkill *rfkill; + char name[8]; struct usb_endpoint_descriptor *in_endp; struct usb_endpoint_descriptor *out_endp; @@ -2467,27 +2468,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev, { struct hso_net *hso_net = dev2net(hso_dev); struct device *dev = hso_net-net-dev; - char *rfkn; - rfkn = kzalloc(20, GFP_KERNEL); - if (!rfkn) - dev_err(dev, %s - Out of memory\n, __func__); - - snprintf(rfkn, 20, hso-%d, + snprintf(hso_net-name, sizeof(hso_net-name), hso-%d, interface-altsetting-desc.bInterfaceNumber); That number is not unique. Indeed it will be identical for all devices. Indeed. That should be corrected too. Thank you, Olivier -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: XHCI, brain-dead scanner, and microframe rounding
Mathias Nyman mathias.nyman@... writes: Many changes were done in 3.18 and 3.19-rc release regarding to how we handle halted and stopped endpoints, Can you test if that fixes your issues? preferably with a 3.19-rc kernel Here's the result of 3.19-rc4: 2015-01-20T15:26:41.242455+01:00 xrated kernel: [ 37.979496] usb 6-10.3.1: new high-speed USB device number 11 using xhci_hcd 2015-01-20T15:26:41.329458+01:00 xrated kernel: [ 38.066734] usb 6-10.3.1: New USB device found, idVendor=04b8, idProduct=0119 2015-01-20T15:26:41.329477+01:00 xrated kernel: [ 38.066742] usb 6-10.3.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 2015-01-20T15:26:41.329480+01:00 xrated kernel: [ 38.066746] usb 6-10.3.1: Product: EPSON Scanner 2015-01-20T15:26:41.329481+01:00 xrated kernel: [ 38.066749] usb 6-10.3.1: Manufacturer: EPSON 2015-01-20T15:26:41.329483+01:00 xrated kernel: [ 38.067029] usb 6-10.3.1: ep 0x81 - rounding interval to 128 microframes, ep desc says 255 microframes 2015-01-20T15:26:41.329484+01:00 xrated kernel: [ 38.067035] usb 6-10.3.1: ep 0x2 - rounding interval to 128 microframes, ep desc says 255 microframes Plugging the scanner to a USB2 port works flawlessly. Pete -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: XHCI, brain-dead scanner, and microframe rounding
Mathias Nyman mathias.nyman@... writes: Many changes were done in 3.18 and 3.19-rc release regarding to how we handle halted and stopped endpoints, Can you test if that fixes your issues? preferably with a 3.19-rc kernel Here's the result of 3.19-rc4: 2015-01-20T15:26:41.242455+01:00 xrated kernel: [ 37.979496] usb 6-10.3.1: new high-speed USB device number 11 using xhci_hcd 2015-01-20T15:26:41.329458+01:00 xrated kernel: [ 38.066734] usb 6-10.3.1: New USB device found, idVendor=04b8, idProduct=0119 2015-01-20T15:26:41.329477+01:00 xrated kernel: [ 38.066742] usb 6-10.3.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 2015-01-20T15:26:41.329480+01:00 xrated kernel: [ 38.066746] usb 6-10.3.1: Product: EPSON Scanner 2015-01-20T15:26:41.329481+01:00 xrated kernel: [ 38.066749] usb 6-10.3.1: Manufacturer: EPSON 2015-01-20T15:26:41.329483+01:00 xrated kernel: [ 38.067029] usb 6-10.3.1: ep 0x81 - rounding interval to 128 microframes, ep desc says 255 microframes 2015-01-20T15:26:41.329484+01:00 xrated kernel: [ 38.067035] usb 6-10.3.1: ep 0x2 - rounding interval to 128 microframes, ep desc says 255 microframes Plugging the scanner to a USB2 port works flawlessly. Pete -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html I have the same experience steve -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: XHCI, senseless logging
Mathias Nyman mathias.nyman@... writes: Many changes were done in 3.18 and 3.19-rc release regarding to how we handle halted and stopped endpoints, Can you test if that fixes your issues? preferably with a 3.19-rc kernel BTW: something regressed between 3.16.7 and 3.18.2 My logs get spammed with loads of: 2015-01-20T15:08:33.798826+01:00 xrated kernel: [77311.951840] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? 2015-01-20T15:08:34.064094+01:00 xrated kernel: [77312.217023] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? 2015-01-20T15:08:34.453604+01:00 xrated kernel: [77312.606415] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? 2015-01-20T15:08:34.703090+01:00 xrated kernel: [77312.855803] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? 2015-01-20T15:08:36.794267+01:00 xrated kernel: [77314.946318] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? # lsusb Bus 002 Device 002: ID 8087:8001 Intel Corp. Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub Bus 001 Device 002: ID 8087:8009 Intel Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Bus 007 Device 010: ID 0bda:0307 Realtek Semiconductor Corp. Bus 007 Device 007: ID 0451:8041 Texas Instruments, Inc. Bus 007 Device 006: ID 0451:8041 Texas Instruments, Inc. Bus 007 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub Bus 006 Device 008: ID 0d46:3014 Kobil Systems GmbH Bus 006 Device 005: ID 0a12:0001 Cambridge Silicon Radio, Ltd Bluetooth Dongle (HCI mode) Bus 006 Device 003: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB Bus 006 Device 002: ID 046d:08cc Logitech, Inc. Mic (PTZ) Bus 006 Device 009: ID 046a:0001 Cherry GmbH My3000 Keyboard Bus 006 Device 006: ID 1a81:1701 Holtek Semiconductor, Inc. Bus 006 Device 018: ID 0451:8043 Texas Instruments, Inc. Bus 006 Device 017: ID 0451:8043 Texas Instruments, Inc. Bus 006 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub I guess, this relates to the Kobil Smart Card reader, that is handled by pcscd. 1510 lines just for today: # grep 'WARN Event TRB for slot 8 ep 2' /var/log/messages | wc -l 1510 # grep 'WARN Event TRB for slot 8 ep 2' /var/log/messages | head -1 2015-01-20T09:34:26.287387+01:00 xrated kernel: [57275.923658] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? # grep 'WARN Event TRB for slot 8 ep 2' /var/log/messages | tail -1 2015-01-20T15:08:43.718097+01:00 xrated kernel: [77321.867860] xhci_hcd :00:14.0: WARN Event TRB for slot 8 ep 2 with no TDs queued? Will reboot to 3.19-rc4 now. Pete -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 00/11] scsi: fix module reference mismatch for scsi host
2015-01-19 23:22 GMT+09:00 Tejun Heo t...@kernel.org: On Mon, Jan 19, 2015 at 12:05:58AM +0900, Akinobu Mita wrote: While accessing a scsi_device, the use count of the underlying LLDD module is incremented. The module reference is retrieved through .module field of struct scsi_host_template. This mapping between scsi_device and underlying LLDD module works well except some drivers which consist with the core driver and the actual LLDDs and scsi_host_template is defined in the core driver. In these cases, the actual LLDDs can be unloaded even if the scsi_device is being accessed. This patch series fixes the module reference mismatch problem for ufs, usb-storage, esp_scsi, ahci_platform, and pata_platform drivers by moving owner module reference field from struct scsi_host_template to struct Scsi_Host and allowing the LLDDs to set their correct module reference. Hmmm, can't we just move sht definitions to actual LLDDs? libata can do that easily. sht, as its name implies, is the template for creating the scsi_hosts of a given type. We're now just moving module ownership from sht definition site to whatever callsite the actual instance is being created which can also be wrapped in a separate layer requiring explicit propagation. Why not just propagate sht's directly? What's the difference? The reason I didn't move sht from the core driver to the LLDDs for fixing ufs and ums-* in the first place is to avoid exporting many symbols for callbacks in sht. But I realized that we can do it without that many exported symbols by creating a single function that returns a kmemdup()ed sht with a few change including -module. So there are three options we can take for fixing this problem. I would like to know the opinions which one should be taken. (1) Add owner module field to Scsi_Host for allowing LLDDs to adjust it after scsi host allocation. This approach is used by v1,2,3 of this patch series and the scsi midlayer change is minimum. (2) Move owner module field from scsi_host_template to Scsi_Host. The owner module reference is retrieved from the callsite of scsi_host_alloc() by passing THIS_MODULE to the extra argument. The scsi midlayer change is small, but we need the same macro trick for each scsi_host_alloc() wrapper and these changes are relatively large (required by libata, libiscsi, libfc, cxgbi, 53c700, legacy). This approach is used by v4 of this patch series. (3) Allocate scsi host template for each module. No scsi midlayer change is required. Instead of sharing a single scsi host template defined in the core, create a single function that returns a kmemdup()ed sht with a few change including -module so that the sub modules can use it as their sht. -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/11] hso: fix memory leak in hso_create_rfkill()
On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote: When the rfkill interface was created, a buffer containing the name of the rfkill node was allocated. This buffer was never freed when the device disappears. To fix the problem, we put the name given to rfkill_alloc() in the hso_net structure. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 470ef9e..a49ac2e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -153,6 +153,7 @@ struct hso_net { struct hso_device *parent; struct net_device *net; struct rfkill *rfkill; + char name[8]; struct usb_endpoint_descriptor *in_endp; struct usb_endpoint_descriptor *out_endp; @@ -2467,27 +2468,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev, { struct hso_net *hso_net = dev2net(hso_dev); struct device *dev = hso_net-net-dev; - char *rfkn; - rfkn = kzalloc(20, GFP_KERNEL); - if (!rfkn) - dev_err(dev, %s - Out of memory\n, __func__); - - snprintf(rfkn, 20, hso-%d, + snprintf(hso_net-name, sizeof(hso_net-name), hso-%d, interface-altsetting-desc.bInterfaceNumber); That number is not unique. Indeed it will be identical for all devices. Regards Oliver -- Oliver Neukum oneu...@suse.de -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] usb: hid: Do not bind to Microchip Pick16F1454
The Microchip Pick16F1454 is exported as a HID device and is used by for example the Yepkit YKUSH three-port switchable USB hub. However, it is not an actual HID-device. On the Yepkit, it is used to power up/down the ports on the hub. The HID driver should ignore this device. Signed-off-by: Kristian Evensen kristian.even...@gmail.com --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8b63879..77afffc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2328,6 +2328,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICK16F1454) }, { HID_USB_DEVICE(USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR, USB_DEVICE_ID_N_S_HARMONY) }, { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100) }, { HID_USB_DEVICE(USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 20) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9243359..8df4744 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -638,6 +638,7 @@ #define USB_DEVICE_ID_PICKIT2 0x0033 #define USB_DEVICE_ID_PICOLCD 0xc002 #define USB_DEVICE_ID_PICOLCD_BOOTLOADER 0xf002 +#define USB_DEVICE_ID_PICK16F1454 0x0042 #define USB_VENDOR_ID_MICROSOFT0x045e #define USB_DEVICE_ID_SIDEWINDER_GV0x003b -- 2.1.0 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: Suspected (out of tree) HCI issue
On Sun, 18 Jan 2015, Vincent Pelletier wrote: Hello, (please keep me cc'ed, I'm not subscribed) On Thu, 27 Nov 2014 13:00:28 -0500 (EST), Alan Stern st...@rowland.harvard.edu wrote: If your hardware resembles, say, the DWC2 hardware then maybe the DWC2 driver (drivers/usb/dwc2/) can be made to work with it. I've worked on this and have a functional USB port using dwc2. Attached is the largest patch involved, and likely the only one touching dwc2 (the rest is board-specific and not polished enough yet). Could I get feedback on it ? I didn't test this exact patch, as OpenWRT is on 3.14.28 and this patch is against linux-stable current master (eaa27f34e91a14cdceed26ed6c6793ec1d186115 linux 3.19-rc4). Going further: The hardware I'm testing this on has 2 ports, each on a different HCI core of the same device (it seems they share some registers). As far as I can see, dwc2 actually handles a single core, and one port is indeed not functional. Is there some work in progress on this topic ? Or any idea on how it should be done ? You ought to CC: the maintainer of the dwc2 driver, if you want to get any knowledgeable feedback. Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/3] usb: dwc3: add ULPI interface support
Hi, On Tue, Jan 20, 2015 at 11:18:21AM +0200, Heikki Krogerus wrote: Registers ULPI interface with the ULPI bus if HSPHY type is ULPI. Signed-off-by: Heikki Krogerus heikki.kroge...@linux.intel.com Cc: Felipe Balbi ba...@ti.com you're doing quite a bit in a single patch... --- drivers/usb/dwc3/Kconfig | 7 drivers/usb/dwc3/Makefile | 4 ++ drivers/usb/dwc3/core.c | 9 +++- drivers/usb/dwc3/core.h | 22 ++ drivers/usb/dwc3/ulpi.c | 102 ++ 5 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/dwc3/ulpi.c diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 58b5b2c..6d0c5e6 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -11,6 +11,13 @@ config USB_DWC3 if USB_DWC3 +config USB_DWC3_ULPI + bool Provide ULPI PHY Interface + depends on ULPI_PHY=y || ULPI_PHY=USB_DWC3 + help + Select this if you have ULPI type PHY attached to your DWC3 + controller. + choice bool DWC3 Mode Selection default USB_DWC3_DUAL_ROLE if (USB USB_GADGET) diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index bb34fbc..2fc44e0 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -16,6 +16,10 @@ ifneq ($(filter y,$(CONFIG_USB_DWC3_GADGET) $(CONFIG_USB_DWC3_DUAL_ROLE)),) dwc3-y += gadget.o ep0.o endif +ifneq ($(CONFIG_USB_DWC3_ULPI),) + dwc3-y += ulpi.o +endif + ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o endif diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 25ddc39..5219bc7 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -876,12 +876,17 @@ static int dwc3_probe(struct platform_device *pdev) dwc-hird_threshold = hird_threshold | (dwc-is_utmi_l1_suspend 4); + platform_set_drvdata(pdev, dwc); + + ret = dwc3_ulpi_init(dwc); + if (ret) + return ret; + ret = dwc3_core_get_phy(dwc); if (ret) return ret; spin_lock_init(dwc-lock); - platform_set_drvdata(pdev, dwc); why do you need to move this ? Looks like this should be a cleanup and split into a single patch. it also appears that you need another patch moving dwc3_cache_hwparams() before all of these other calls, so you can use it from dwc3_ulpi_init(). @@ -965,6 +970,7 @@ err1: err0: dwc3_free_event_buffers(dwc); + dwc3_ulpi_exit(dwc); return ret; } @@ -984,6 +990,7 @@ static int dwc3_remove(struct platform_device *pdev) phy_power_off(dwc-usb3_generic_phy); dwc3_core_exit(dwc); + dwc3_ulpi_exit(dwc); pm_runtime_put_sync(pdev-dev); pm_runtime_disable(pdev-dev); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 0842aa8..f6881a6 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -32,6 +32,7 @@ #include linux/usb/otg.h #include linux/phy/phy.h +#include linux/phy/ulpi/interface.h #define DWC3_MSG_MAX 500 @@ -174,6 +175,14 @@ #define DWC3_GUSB2PHYCFG_PHYSOFTRST (1 31) #define DWC3_GUSB2PHYCFG_SUSPHY (1 6) +/* Global USB2 PHY Vendor Control Register */ +#define DWC3_GUSB2PHYACC_NEWREGREQ (1 25) +#define DWC3_GUSB2PHYACC_BUSY(1 23) +#define DWC3_GUSB2PHYACC_WRITE (1 22) +#define DWC3_GUSB2PHYACC_ADDR(n) (n 16) +#define DWC3_GUSB2PHYACC_EXTEND_ADDR(n) (n 8) +#define DWC3_GUSB2PHYACC_DATA(n) (n 0xff) separate patch @@ -590,6 +599,7 @@ struct dwc3_hwparams { #define DWC3_NUM_INT(n) (((n) (0x3f 15)) 15) /* HWPARAMS3 */ +#define DWC3_ULPI_HSPHY (1 3) you also need a patch which defines this bit of HWPARAMS3. This is also the wrong definition. Which core revision do you have ? I can see that bit 3 is part of a 2 bit field called: DWC_USB3_HSPHY_INTERFACE moreover, there are systems which have both ULPI and UTMI enabled and you can't really know which one the PHY is using. This needs a bit more thought. #define DWC3_NUM_IN_EPS_MASK (0x1f 18) #define DWC3_NUM_EPS_MASK(0x3f 12) #define DWC3_NUM_EPS(p) (((p)-hwparams3 \ @@ -739,6 +749,8 @@ struct dwc3 { struct phy *usb2_generic_phy; struct phy *usb3_generic_phy; + struct ulpi *ulpi; + void __iomem*regs; size_t regs_size; @@ -1035,4 +1047,14 @@ static inline int dwc3_gadget_resume(struct dwc3 *dwc) } #endif /* !IS_ENABLED(CONFIG_USB_DWC3_HOST) */ +#if IS_ENABLED(CONFIG_USB_DWC3_ULPI) +int dwc3_ulpi_init(struct dwc3 *dwc); +void dwc3_ulpi_exit(struct dwc3 *dwc); +#else +static inline int dwc3_ulpi_init(struct dwc3 *dwc) +{ return 0; }
Re: [PATCH 11/11] usb: core: fix a race with usb_queue_reset_device()
On Tue, 20 Jan 2015, Olivier Sobrie wrote: When usb_queue_reset() is called it schedules a work in view of resetting the usb interface. When the reset work is running, it can be scheduled again (e.g. by the usb disconnect method of the driver). Consider that the reset work is queued again while the reset work is running and that this work leads to a forced unbinding of the usb interface (e.g. because a driver is bound to the interface and has no pre/post_reset methods - see usb_reset_device()). In such condition, usb_unbind_interface() gets called and this function calls usb_cancel_queued_reset() which does nothing because the flag reset_running is set to 1. The second reset work that has been scheduled is therefore not cancelled. Later, the usb_reset_device() tries to rebind the interface. If it fails, then the usb interface context which contain the reset work struct is freed and it most likely crash when the second reset work tries to be run. There was an earlier patch posted for testing (no results yet) affecting this same region of code: http://marc.info/?l=linux-usbm=142064533924019w=2 It should fix the problem described here, because (among other things) it adds usb_get/put_intf calls to the delayed-reset routines. Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v4 00/11] scsi: fix module reference mismatch for scsi host
Hello, Akinobu. On Tue, Jan 20, 2015 at 11:57:37PM +0900, Akinobu Mita wrote: The reason I didn't move sht from the core driver to the LLDDs for fixing ufs and ums-* in the first place is to avoid exporting many symbols for callbacks in sht. But I realized that we can do it without that many exported symbols by creating a single function that returns a kmemdup()ed sht with a few change including -module. Hmmm, libata already exports most of the necessary symbols. libahci or platform drivers might have to export more but that shouldn't be much. For libata, pushing sht's to the leaf drivers would make far more sense as sht's already get inherited and modified along the hierarchy. Thanks. -- tejun -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: ohci: sporadic crash/lockup in ohci-hcd io_watchdog_func()
On Mon, 19 Jan 2015, Heiko Przybyl wrote: On Monday 19 January 2015 11:17:59 Alan Stern wrote: On Mon, 19 Jan 2015, Heiko Przybyl wrote: It seems to be related to keyboard input (at least it happens when using the keyboard), without relation to system load. Can happen within a day after boot or after several days of hibernated uptime. Unfortunately, I haven't found a way to reliably reproduce the issue, yet. [..] My (pretty wild) guess is, that the corruption happens through a race in the interrupt handler ohci_irq(), which calls ohci_work(), which calls finish_urb(), which states: * PRECONDITION: ohci lock held, irqs blocked But ohci_irq() seems to only spin_[un]lock(), not spin_[un]lock_irq[save| restore](). All other functions that call ohci_work() do at least spin_[un]lock_irq. So irqs could still be enabled and possibly the event triggered twice, thus the double list add? That's easy enough to test. All you have to do is change the spin_lock/unlock statements to their irq_save/restore variants. Well, thought about that as well, but I'm not sure when to take it as fixed and when to take it as issue-just-didn't-happen-yet, because of the not-so- deterministic occurrence of the error. But I can try it out anyway, just wanted to have some feedback before trying. By the way, failing to disable interrupts when acquiring a spinlock generally does not lead to data corruption -- it leads to deadlocks. So I doubt this is the cause of your problem. If you really want to, you could add a WARN_ON(!irqs_disabled()); line to ohci_irq(). If that's not the explanation then we'll have to dig deeper. I can still work on a saved vmcore dump of a crash. Btw. using crash(1) and its command `bt -E`shows two kernel mode exceptions. Though, I can't figure out where the first one originates from CPU 3 IRQ STACK: KERNEL-MODE EXCEPTION FRAME AT: 88022ecc3638 [exception RIP: _raw_spin_unlock_irqrestore+9] RIP: 814774b9 RSP: 88022ecc36e8 RFLAGS: 0202 RAX: 88022ecc36a8 RBX: 88022ecc36b0 RCX: 81290279 RDX: 2dff RSI: RDI: 88022ecc3788 RBP: 88022ecc36e8 R8: 0080 R9: 0023 R10: 813e6407 R11: ea000863ad80 R12: 88022ecc3658 R13: 81478b2a R14: 88022ecc36e8 R15: 0001 ORIG_RAX: 81471cfd CS: 0010 SS: 0018 0x814774b9 +9: decl %gs:0xa860 No idea. It might be a good idea for you to try something a little more invasive. How about writing a routine to check the entire ohci-eds_in_use list for validity (each forward pointer is matched by the corresponding backward pointer), and calling this routine at each place where the list gets modified, before the modification happens? You could also make sure that an entry being added to the list isn't on the list already, and whenever an entry is deleted from the list either it really is on the list or else its list pointers point to themselves. Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 11/11] usb: core: fix a race with usb_queue_reset_device()
On Tue, Jan 20, 2015 at 10:26:30AM -0500, Alan Stern wrote: On Tue, 20 Jan 2015, Olivier Sobrie wrote: When usb_queue_reset() is called it schedules a work in view of resetting the usb interface. When the reset work is running, it can be scheduled again (e.g. by the usb disconnect method of the driver). Consider that the reset work is queued again while the reset work is running and that this work leads to a forced unbinding of the usb interface (e.g. because a driver is bound to the interface and has no pre/post_reset methods - see usb_reset_device()). In such condition, usb_unbind_interface() gets called and this function calls usb_cancel_queued_reset() which does nothing because the flag reset_running is set to 1. The second reset work that has been scheduled is therefore not cancelled. Later, the usb_reset_device() tries to rebind the interface. If it fails, then the usb interface context which contain the reset work struct is freed and it most likely crash when the second reset work tries to be run. There was an earlier patch posted for testing (no results yet) affecting this same region of code: http://marc.info/?l=linux-usbm=142064533924019w=2 It should fix the problem described here, because (among other things) it adds usb_get/put_intf calls to the delayed-reset routines. Ok sorry I didn't see that patch. It looks indeed that it should solve my problem. I'll give it a try tomorrow. Thank you, -- Olivier -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: USB autosuspend causing trouble with bluetooth
On Tue, 2015-01-20 at 18:58 +0400, Kirill Elagin wrote: On Tue, Jan 20, 2015 at 5:06 PM, Oliver Neukum oneu...@suse.de wrote: On Tue, 2015-01-20 at 16:18 +0400, Kirill Elagin wrote: I use a Logitech wireless keyboard (with a Unifying receiver) and it keeps working fine even with `auto`. That is, everything is OK if the receiver is plugged before `power/control` is switched to `auto`. Wait. There is no power/control file for the receiver before you plug it in. We are having a very big misunderstanding here. Sorry for not being clear. I was referring to `power/control` of the USB-device itself except for the cases when I was talking about hot-plugging issues — in those cases I was referring to the `power/control` of the root hub. Please check whether you are not accidentally touching the ports linux-0dmf:/sys/bus/usb/devices/usb1/1-0:1.0/usb1-port1 At paths like this you find control files for ports, not the root hub as a device. In this particular case I was talking about the `power/control` of the root hub. OK, so autosuspend does work if you enable it for the device but not the hub? `laptop-mode-tools` by default writes `auto` to `power/control` of _all_ the USB devices, root hubs included (even when on AC). Is it really expected that kernel might completely power off the physical USB port? Sounds weird. It can. It is a recent feature if ACPI supports that on a machine. Here is an even more strange thing. First I set all the USB power management to the defaults (that is, `auto` for all the usb devices including root hubs). Again, the keyboard keeps working and as soon as I unplug the receiver kernel says the device was disconnected. Now if I plug the receiver back nothing happens. _But_ if I plug a flash drive in the save physical port it gets detected. So, I tried a number of other usb devices and it totally looks like USB2.0 ones are properly hot-plugged while USB1.1 devices are not. Does this sound to you like a bug in my laptop's hardware? Could be, but could also be software. Please double check where exactly an on is needed. Regards Oliver -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 04/11] hso: fix memory leak in hso_create_rfkill()
On Tue, 2015-01-20 at 14:13 +0100, Oliver Neukum wrote: On Tue, 2015-01-20 at 13:29 +0100, Olivier Sobrie wrote: When the rfkill interface was created, a buffer containing the name of the rfkill node was allocated. This buffer was never freed when the device disappears. To fix the problem, we put the name given to rfkill_alloc() in the hso_net structure. Signed-off-by: Olivier Sobrie oliv...@sobrie.be --- drivers/net/usb/hso.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 470ef9e..a49ac2e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -153,6 +153,7 @@ struct hso_net { struct hso_device *parent; struct net_device *net; struct rfkill *rfkill; + char name[8]; struct usb_endpoint_descriptor *in_endp; struct usb_endpoint_descriptor *out_endp; @@ -2467,27 +2468,20 @@ static void hso_create_rfkill(struct hso_device *hso_dev, { struct hso_net *hso_net = dev2net(hso_dev); struct device *dev = hso_net-net-dev; - char *rfkn; - rfkn = kzalloc(20, GFP_KERNEL); - if (!rfkn) - dev_err(dev, %s - Out of memory\n, __func__); - - snprintf(rfkn, 20, hso-%d, + snprintf(hso_net-name, sizeof(hso_net-name), hso-%d, interface-altsetting-desc.bInterfaceNumber); That number is not unique. Indeed it will be identical for all devices. I would say just do static u32 rfkill_counter = 0 and + snprintf(hso_net-name, sizeof(hso_net-name), hso-%d, +rfkill_counter++); We can't just use the netdev's name because that may have conflicts. eg, the netdev will get hso0 when plugged in (and thus rfkill would get hso-0) but then udev will rename that to something like wwp0s26f7u2i8. Then the second HSO you plug in will get the name 'hso0', and so the second rfkill would get 'hso-0', but that's already taken by the first rfkill... Which is why I just suggest a counter. Dan -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/5] extcon: gpio-usb: Introduce gpio usb extcon driver
On Mon, Jan 19, 2015 at 07:52:18PM +0200, Roger Quadros wrote: This driver observes the USB ID pin connected over a GPIO and updates the USB cable extcon states accordingly. The existing GPIO extcon driver is not suitable for this purpose as it needs to be taught to understand USB cable states and it can't handle more than one cable per instance. For the USB case we need to handle 2 cable states. 1) USB (attach/detach) 2) USB-Host (attach/detach) This driver can be easily updated in the future to handle VBUS events in case it happens to be available on GPIO for any platform. Signed-off-by: Roger Quadros rog...@ti.com Reviewed-by: Felipe Balbi ba...@ti.com Acked-by: Felipe Balbi ba...@ti.com --- .../devicetree/bindings/extcon/extcon-usb.txt | 20 ++ drivers/extcon/Kconfig | 7 + drivers/extcon/Makefile| 1 + drivers/extcon/extcon-gpio-usb.c | 225 + 4 files changed, 253 insertions(+) create mode 100644 Documentation/devicetree/bindings/extcon/extcon-usb.txt create mode 100644 drivers/extcon/extcon-gpio-usb.c diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb.txt b/Documentation/devicetree/bindings/extcon/extcon-usb.txt new file mode 100644 index 000..171c5a4 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-usb.txt @@ -0,0 +1,20 @@ +USB Extcon device + +This is a virtual device used to generate USB cable states from the USB ID pin +connected to a GPIO pin. + +Required properties: +- compatible: Should be linux,extcon-usb +- id-gpio: gpio for USB ID pin. See gpio binding. + +Example: + extcon_usb1 { + compatible = linux,extcon-usb; + id-gpio = gpio6 1 GPIO_ACTIVE_HIGH; + } + + usb@1 { + ... + extcon = extcon_usb1; + ... + }; diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 6a1f7de..8106a83 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -35,6 +35,13 @@ config EXTCON_GPIO Say Y here to enable GPIO based extcon support. Note that GPIO extcon supports single state per extcon instance. +config EXTCON_GPIO_USB + tristate USB GPIO extcon support + depends on GPIOLIB + help + Say Y here to enable GPIO based USB cable detection extcon support. + Used typically if GPIO is used for USB ID pin detection. + config EXTCON_MAX14577 tristate MAX14577/77836 EXTCON Support depends on MFD_MAX14577 diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 0370b42..bae594b 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)+= extcon-max8997.o obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o +obj-$(CONFIG_EXTCON_GPIO_USB)+= extcon-gpio-usb.o diff --git a/drivers/extcon/extcon-gpio-usb.c b/drivers/extcon/extcon-gpio-usb.c new file mode 100644 index 000..aeb2298 --- /dev/null +++ b/drivers/extcon/extcon-gpio-usb.c @@ -0,0 +1,225 @@ +/** + * drivers/extcon/extcon_gpio_usb.c - USB GPIO extcon driver + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com + * + * Author: Roger Quadros rog...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include linux/extcon.h +#include linux/extcon/extcon-gpio.h +#include linux/gpio.h +#include linux/init.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/kernel.h +#include linux/module.h +#include linux/of_gpio.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/workqueue.h + +#define USB_GPIO_DEBOUNCE_MS 20 /* ms */ + +struct usb_extcon_info { + struct device *dev; + struct extcon_dev *edev; + + struct gpio_desc *id_gpiod; + int id_irq; + + unsigned long debounce_jiffies; + struct delayed_work wq_detcable; +}; + +/* List of detectable cables */ +enum { + EXTCON_CABLE_USB = 0, + EXTCON_CABLE_USB_HOST, + + EXTCON_CABLE_END, +}; + +static const char *usb_extcon_cable[] = { + [EXTCON_CABLE_USB] = USB, + [EXTCON_CABLE_USB_HOST] = USB-Host, + NULL, +}; + +static void usb_extcon_detect_cable(struct work_struct *work) +{ + int id; + struct usb_extcon_info *info; + const char **cable_names; + + info =
Re: [PATCH 4/5] ARM: dts: dra72-evm: Add extcon nodes for USB
On Mon, Jan 19, 2015 at 07:52:21PM +0200, Roger Quadros wrote: On this EVM, the USB cable state has to be determined via the ID pin tied to a GPIO line. We use the gpio-usb-extcon driver to read the ID pin and the extcon framework to forward the USB cable state information to the USB driver so the controller can be configured in the right mode (host/peripheral). Gets USB peripheral mode to work on this EVM. Signed-off-by: Roger Quadros rog...@ti.com Reviewed-by: Felipe Balbi ba...@ti.com Acked-by: Felipe Balbi ba...@ti.com --- arch/arm/boot/dts/dra72-evm.dts | 31 +++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/boot/dts/dra72-evm.dts b/arch/arm/boot/dts/dra72-evm.dts index 89085d0..d93a98f 100644 --- a/arch/arm/boot/dts/dra72-evm.dts +++ b/arch/arm/boot/dts/dra72-evm.dts @@ -8,6 +8,7 @@ /dts-v1/; #include dra72x.dtsi +#include dt-bindings/gpio/gpio.h / { model = TI DRA722; @@ -24,6 +25,16 @@ regulator-min-microvolt = 330; regulator-max-microvolt = 330; }; + + extcon_usb1: extcon_usb1 { + compatible = linux,extcon-usb; + id-gpio = pcf_gpio_21 1 GPIO_ACTIVE_HIGH; + }; + + extcon_usb2: extcon_usb2 { + compatible = linux,extcon-usb; + id-gpio = pcf_gpio_21 2 GPIO_ACTIVE_HIGH; + }; }; dra7_pmx_core { @@ -243,6 +254,18 @@ ti,palmas-long-press-seconds = 6; }; }; + + pcf_gpio_21: gpio@21 { + compatible = ti,pcf8575; + reg = 0x21; + lines-initial-states = 0x1408; + gpio-controller; + #gpio-cells = 2; + interrupt-parent = gpio6; + interrupts = 11 IRQ_TYPE_EDGE_FALLING; + interrupt-controller; + #interrupt-cells = 2; + }; }; uart1 { @@ -345,6 +368,14 @@ phy-supply = ldo4_reg; }; +omap_dwc3_1 { + extcon = extcon_usb1; +}; + +omap_dwc3_2 { + extcon = extcon_usb2; +}; + usb1 { dr_mode = peripheral; pinctrl-names = default; -- 2.1.0 -- balbi signature.asc Description: Digital signature
Re: [PATCH 2/5] usb: extcon: Fix USB-Host cable name
On Mon, Jan 19, 2015 at 07:52:19PM +0200, Roger Quadros wrote: The recommended name for USB-Host cable state is USB-Host and not USB-HOST as per drivers/extcon/extcon-class.c extcon_cable_name. Change all instances of USB-HOST to USB-Host. Signed-off-by: Roger Quadros rog...@ti.com I checked that these are not documented and there are no DTS using USB-HOST, so it's fine to change Reviewed-by: Felipe Balbi ba...@ti.com Acked-by: Felipe Balbi ba...@ti.com --- drivers/extcon/extcon-palmas.c | 18 +- drivers/usb/dwc3/dwc3-omap.c | 6 +++--- drivers/usb/phy/phy-omap-otg.c | 4 ++-- drivers/usb/phy/phy-tahvo.c| 8 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c index 11c6757..6d002c3 100644 --- a/drivers/extcon/extcon-palmas.c +++ b/drivers/extcon/extcon-palmas.c @@ -31,7 +31,7 @@ static const char *palmas_extcon_cable[] = { [0] = USB, - [1] = USB-HOST, + [1] = USB-Host, NULL, }; @@ -93,26 +93,26 @@ static irqreturn_t palmas_id_irq_handler(int irq, void *_palmas_usb) PALMAS_USB_ID_INT_LATCH_CLR, PALMAS_USB_ID_INT_EN_HI_CLR_ID_GND); palmas_usb-linkstat = PALMAS_USB_STATE_ID; - extcon_set_cable_state(palmas_usb-edev, USB-HOST, true); - dev_info(palmas_usb-dev, USB-HOST cable is attached\n); + extcon_set_cable_state(palmas_usb-edev, USB-Host, true); + dev_info(palmas_usb-dev, USB-Host cable is attached\n); } else if ((set PALMAS_USB_ID_INT_SRC_ID_FLOAT) (id_src PALMAS_USB_ID_INT_SRC_ID_FLOAT)) { palmas_write(palmas_usb-palmas, PALMAS_USB_OTG_BASE, PALMAS_USB_ID_INT_LATCH_CLR, PALMAS_USB_ID_INT_EN_HI_CLR_ID_FLOAT); palmas_usb-linkstat = PALMAS_USB_STATE_DISCONNECT; - extcon_set_cable_state(palmas_usb-edev, USB-HOST, false); - dev_info(palmas_usb-dev, USB-HOST cable is detached\n); + extcon_set_cable_state(palmas_usb-edev, USB-Host, false); + dev_info(palmas_usb-dev, USB-Host cable is detached\n); } else if ((palmas_usb-linkstat == PALMAS_USB_STATE_ID) (!(set PALMAS_USB_ID_INT_SRC_ID_GND))) { palmas_usb-linkstat = PALMAS_USB_STATE_DISCONNECT; - extcon_set_cable_state(palmas_usb-edev, USB-HOST, false); - dev_info(palmas_usb-dev, USB-HOST cable is detached\n); + extcon_set_cable_state(palmas_usb-edev, USB-Host, false); + dev_info(palmas_usb-dev, USB-Host cable is detached\n); } else if ((palmas_usb-linkstat == PALMAS_USB_STATE_DISCONNECT) (id_src PALMAS_USB_ID_INT_SRC_ID_GND)) { palmas_usb-linkstat = PALMAS_USB_STATE_ID; - extcon_set_cable_state(palmas_usb-edev, USB-HOST, true); - dev_info(palmas_usb-dev, USB-HOST cable is attached\n); + extcon_set_cable_state(palmas_usb-edev, USB-Host, true); + dev_info(palmas_usb-dev, USB-Host cable is attached\n); } return IRQ_HANDLED; diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 172d64e..6713ad9 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -445,14 +445,14 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap) omap-id_nb.notifier_call = dwc3_omap_id_notifier; ret = extcon_register_interest(omap-extcon_id_dev, -edev-name, USB-HOST, +edev-name, USB-Host, omap-id_nb); if (ret 0) - dev_vdbg(omap-dev, failed to register notifier for USB-HOST\n); + dev_vdbg(omap-dev, failed to register notifier for USB-Host\n); if (extcon_get_cable_state(edev, USB) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID); - if (extcon_get_cable_state(edev, USB-HOST) == true) + if (extcon_get_cable_state(edev, USB-Host) == true) dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND); } diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c index 56ee760..53cba3f 100644 --- a/drivers/usb/phy/phy-omap-otg.c +++ b/drivers/usb/phy/phy-omap-otg.c @@ -119,7 +119,7 @@ static int omap_otg_probe(struct platform_device *pdev) otg_dev-vbus_nb.notifier_call = omap_otg_vbus_notifier; ret = extcon_register_interest(otg_dev-id_dev, config-extcon, -USB-HOST, otg_dev-id_nb); +USB-Host, otg_dev-id_nb); if (ret)
Re: [PATCH v4 00/11] scsi: fix module reference mismatch for scsi host
On Tue, 20 Jan 2015, Akinobu Mita wrote: 2015-01-19 23:22 GMT+09:00 Tejun Heo t...@kernel.org: On Mon, Jan 19, 2015 at 12:05:58AM +0900, Akinobu Mita wrote: While accessing a scsi_device, the use count of the underlying LLDD module is incremented. The module reference is retrieved through .module field of struct scsi_host_template. This mapping between scsi_device and underlying LLDD module works well except some drivers which consist with the core driver and the actual LLDDs and scsi_host_template is defined in the core driver. In these cases, the actual LLDDs can be unloaded even if the scsi_device is being accessed. This patch series fixes the module reference mismatch problem for ufs, usb-storage, esp_scsi, ahci_platform, and pata_platform drivers by moving owner module reference field from struct scsi_host_template to struct Scsi_Host and allowing the LLDDs to set their correct module reference. Hmmm, can't we just move sht definitions to actual LLDDs? libata can do that easily. sht, as its name implies, is the template for creating the scsi_hosts of a given type. We're now just moving module ownership from sht definition site to whatever callsite the actual instance is being created which can also be wrapped in a separate layer requiring explicit propagation. Why not just propagate sht's directly? What's the difference? The reason I didn't move sht from the core driver to the LLDDs for fixing ufs and ums-* in the first place is to avoid exporting many symbols for callbacks in sht. But I realized that we can do it without that many exported symbols by creating a single function that returns a kmemdup()ed sht with a few change including -module. So there are three options we can take for fixing this problem. I would like to know the opinions which one should be taken. (1) Add owner module field to Scsi_Host for allowing LLDDs to adjust it after scsi host allocation. This approach is used by v1,2,3 of this patch series and the scsi midlayer change is minimum. (2) Move owner module field from scsi_host_template to Scsi_Host. The owner module reference is retrieved from the callsite of scsi_host_alloc() by passing THIS_MODULE to the extra argument. The scsi midlayer change is small, but we need the same macro trick for each scsi_host_alloc() wrapper and these changes are relatively large (required by libata, libiscsi, libfc, cxgbi, 53c700, legacy). This approach is used by v4 of this patch series. (3) Allocate scsi host template for each module. No scsi midlayer change is required. Instead of sharing a single scsi host template defined in the core, create a single function that returns a kmemdup()ed sht with a few change including -module so that the sub modules can use it as their sht. (3) means duplicating a reasonably large data structure in order to alter just one field. It also means changing all the subdrivers to make them call the new function. (1) is the simplest. Since the use of subdrivers in general tends to be a special case (most SCSI drivers don't do it), I prefer to keep the code optimized for it. In other words, I prefer option (1). If people think (2) is better, it can always be layered on top of (1). Alan Stern -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 3/4] mfd: dln2: add support for ACPI
I need an ACPI Ack on this. This patch adds support to load a custom ACPI table that describes devices connected via the DLN2 USB to I2C/SPI/GPIO bridge. The ACPI table can be loaded either externally (from QEMU or with CONFIG_ACPI_CUSTOM_DSDT) or it can be loaded as firmware file with the name dln2.aml. The driver looks for an ACPI device entry with _HID set to DLN2 and makes it the ACPI companion for DLN2 USB sub-drivers. Signed-off-by: Octavian Purdila octavian.purd...@intel.com --- Documentation/acpi/dln2-acpi.txt | 62 ++ drivers/mfd/dln2.c | 134 +++ 2 files changed, 196 insertions(+) create mode 100644 Documentation/acpi/dln2-acpi.txt diff --git a/Documentation/acpi/dln2-acpi.txt b/Documentation/acpi/dln2-acpi.txt new file mode 100644 index 000..d76605f --- /dev/null +++ b/Documentation/acpi/dln2-acpi.txt @@ -0,0 +1,62 @@ +Diolan DLN2 custom APCI table + +The Diolan DLN2 is an USB to I2C/SPI/GPIO bridge and as such it can be used to +connect to various I2C or SPI devices. Because these busses lack an enumeration +protocol, the driver obtains various information about the device (such as I2C +address and GPIO pins) from either ACPI or device tree. + +To allow enumerating devices and their properties via ACPI, the Diolan +driver looks for an ACPI tree with the root _HID set to DLN2. If +it finds such an ACPI object it will set the ACPI companion to the +DLN2 MFD driver and from their it will be propagated to all its +sub-devices (I2C, GPIO, SPI). + +The user can either load the custom DSDT table with three methods: + +1. Via QEMU (see -acpitable) + +2. Via the CONFIG_ACPI_CUSTOM_DSDT kernel config option (see +Documentation/acpi/dsdt-override.txt) + +3. By placing the custom DSDT in the firmware paths in a file name +dln2.aml. + +Here is an example ACPI table that enumerates a BMC150 accelerometer +and defines its I2C address and GPIO pin used as an interrupt source: + +DefinitionBlock (ssdt.aml, SSDT, 1, INTEL , CpuDptf, 0x0003) +{ + Device (DLN0) + { + Name (_ADR, Zero) + Name (_HID, DLN2000) + + Device (STAC) + { + Name (_ADR, Zero) + Name (_HID, BMC150A) + Name (_CID, INTACCL) + Name (_UID, One) + + Method (_CRS, 0, Serialized) + { + Name (RBUF, ResourceTemplate () + { + I2cSerialBus (0x0010, ControllerInitiated, 0x00061A80, + AddressingMode7Bit, \\DLN0, + 0x00, ResourceConsumer, ,) + + GpioInt (Level, ActiveHigh, Exclusive, PullDown, 0x, + \\DLN0, 0x00, ResourceConsumer, , ) + { // Pin list + 0 + } + }) + Return (RBUF) +} + } + } +} + +The resources defined in the devices under the DLN0 are those +supported by the I2C, GPIO and SPI sub-systems. diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index f9c4a0b..93f6d1d 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -23,6 +23,8 @@ #include linux/mfd/core.h #include linux/mfd/dln2.h #include linux/rculist.h +#include linux/acpi.h +#include linux/firmware.h struct dln2_header { __le16 size; @@ -714,6 +716,134 @@ static void dln2_stop(struct dln2_dev *dln2) dln2_stop_rx_urbs(dln2); } + +#if IS_ENABLED(CONFIG_ACPI) + +static struct dln2_acpi_info { + const struct firmware *fw; + acpi_owner_id table_id; + struct acpi_device *dev; + int users; +} dln2_acpi_info; + +static DEFINE_MUTEX(dln2_acpi_lock); + +static acpi_status dln2_find_acpi_handle(acpi_handle handle, u32 level, + void *ctxt, void **retv) +{ + acpi_handle *dln2_handle = (acpi_handle *)retv; + + *dln2_handle = handle; + + return AE_CTRL_TERMINATE; +} + +static void dln2_probe_acpi(struct dln2_dev *dln2) +{ + struct device *dev = dln2-interface-dev; + struct dln2_acpi_info *ai = dln2_acpi_info; + acpi_handle h = NULL; + int ret; + bool fw_loaded = false; + + mutex_lock(dln2_acpi_lock); + + if (ai-dev) + goto out_success; + + /* + * Look for the DLN2000 HID in case the ACPI table was loaded + * externally (e.g. from qemu). + */ + acpi_get_devices(DLN2, dln2_find_acpi_handle, NULL, h); + if (!h) { + /* Try to load the
Re: [PATCH 3/3] phy: ulpi: add driver for TI TUSB1210
Hi, On Tue, Jan 20, 2015 at 11:18:22AM +0200, Heikki Krogerus wrote: TUSB1210 ULPI PHY has vendor specific register for eye diagram tuning. On some platforms the system firmware has set optimized value to it. In order to not loose the optimized value, the driver stores it during probe and restores it every time the PHY is powered back on. Signed-off-by: Heikki Krogerus heikki.kroge...@linux.intel.com --- drivers/phy/ulpi/Kconfig| 11 drivers/phy/ulpi/Makefile | 2 + drivers/phy/ulpi/tusb1210.c | 131 3 files changed, 144 insertions(+) create mode 100644 drivers/phy/ulpi/tusb1210.c diff --git a/drivers/phy/ulpi/Kconfig b/drivers/phy/ulpi/Kconfig index 8007df2..7cd6f82 100644 --- a/drivers/phy/ulpi/Kconfig +++ b/drivers/phy/ulpi/Kconfig @@ -7,3 +7,14 @@ config ULPI_PHY Say yes if you have ULPI PHY attached to your USB controller. If unsure, say N. + +if ULPI_PHY + +config ULPI_TUSB1210 + tristate TI TUSB1210 USB PHY module + depends on POWER_SUPPLY + select USB_PHY + help + Support for TI TUSB1210 USB ULPI PHY. + +endif diff --git a/drivers/phy/ulpi/Makefile b/drivers/phy/ulpi/Makefile index 59e61cb..7ee6679 100644 --- a/drivers/phy/ulpi/Makefile +++ b/drivers/phy/ulpi/Makefile @@ -1,2 +1,4 @@ ulpiphy-y:= ulpi.o obj-$(CONFIG_ULPI_PHY) += ulpiphy.o + +obj-$(CONFIG_ULPI_TUSB1210) += tusb1210.o diff --git a/drivers/phy/ulpi/tusb1210.c b/drivers/phy/ulpi/tusb1210.c new file mode 100644 index 000..ac77f98 --- /dev/null +++ b/drivers/phy/ulpi/tusb1210.c do you really need this extra ulpi directory ? I wonder if phy-tusb1210.c as a name would be enough. @@ -0,0 +1,131 @@ +/** + * tusb1210.c - TUSB1210 USB ULPI PHY driver + * + * Copyright (C) 2015 Intel Corporation + * + * Author: Heikki Krogerus heikki.kroge...@linux.intel.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include linux/module.h +#include linux/phy/ulpi/driver.h +#include linux/phy/ulpi/regs.h +#include linux/gpio/consumer.h + +#include ulpi_phy.h + +struct tusb1210 { + struct ulpi *ulpi; + struct phy *phy; + struct gpio_desc *gpio_reset; + struct gpio_desc *gpio_cs; + u8 ctx[1]; +}; + +static int tusb1210_power_on(struct phy *phy) +{ + struct tusb1210 *tusb = phy_get_drvdata(phy); + + gpiod_set_value_cansleep(tusb-gpio_reset, 1); + gpiod_set_value_cansleep(tusb-gpio_cs, 1); + + /* Restore eye optimisation value */ + ulpi_write(tusb-ulpi, ULPI_EXT_VENDOR_SPECIFIC, tusb-ctx[0]); + + return 0; +} + +static int tusb1210_power_off(struct phy *phy) +{ + struct tusb1210 *tusb = phy_get_drvdata(phy); + + gpiod_set_value_cansleep(tusb-gpio_reset, 0); + gpiod_set_value_cansleep(tusb-gpio_cs, 0); + + return 0; +} + +static struct phy_ops phy_ops = { + .power_on = tusb1210_power_on, + .power_off = tusb1210_power_off, + .init = tusb1210_power_on, + .exit = tusb1210_power_off, + .owner = THIS_MODULE, +}; + +static int tusb1210_probe(struct ulpi *ulpi) +{ + struct gpio_desc *gpio; + struct tusb1210 *tusb; + int ret; + + tusb = devm_kzalloc(ulpi-dev, sizeof(*tusb), GFP_KERNEL); + if (!tusb) + return -ENOMEM; + + gpio = devm_gpiod_get(ulpi-dev, reset); + if (!IS_ERR(gpio)) { + ret = gpiod_direction_output(gpio, 0); + if (ret) + return ret; + tusb-gpio_reset = gpio; + } + + gpio = devm_gpiod_get(ulpi-dev, cs); + if (!IS_ERR(gpio)) { + ret = gpiod_direction_output(gpio, 0); + if (ret) + return ret; + tusb-gpio_cs = gpio; + } + + /* Store initial eye diagram optimisation value */ + ret = ulpi_read(ulpi, ULPI_EXT_VENDOR_SPECIFIC); do they *all* use this register for eye diagram optimization or is this something that Intel decided to do ? (sorry, don't know much about tusb1210 other than it sucks like hell :-) + if (ret 0) + return ret; + + tusb-ctx[0] = ret; + + tusb-phy = ulpi_phy_create(ulpi, phy_ops); + if (IS_ERR(tusb-phy)) + return PTR_ERR(tusb-phy); + + tusb-ulpi = ulpi; + + phy_set_drvdata(tusb-phy, tusb); + dev_set_drvdata(ulpi-dev, tusb); + return 0; +} + +static void tusb1210_remove(struct ulpi *ulpi) +{ + struct tusb1210 *tusb = dev_get_drvdata(ulpi-dev); completely unrelated to $subject, but we might want to have a ulpi_{set,get}_drvdata() at some point. In fact, we might decide to add an entire ULPI bus, eventually, though I'm still considering if there's any benefit to that. + +
Re: [PATCH 3/5] ARM: dts: dra7-evm: Add extcon nodes for USB
On Mon, Jan 19, 2015 at 07:52:20PM +0200, Roger Quadros wrote: On this EVM, the USB cable state has to be determined via the ID pin tied to a GPIO line. We use the gpio-usb-extcon driver to read the ID pin and the extcon framework to forward the USB cable state information to the USB driver so the controller can be configured in the right mode (host/peripheral). Gets USB peripheral mode to work on this EVM. Signed-off-by: Roger Quadros rog...@ti.com Reviewed-by: Felipe Balbi ba...@ti.com Acked-by: Felipe Balbi ba...@ti.com --- arch/arm/boot/dts/dra7-evm.dts | 31 +++ 1 file changed, 31 insertions(+) diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts index 10b725c..47d9a06 100644 --- a/arch/arm/boot/dts/dra7-evm.dts +++ b/arch/arm/boot/dts/dra7-evm.dts @@ -26,6 +26,16 @@ regulator-max-microvolt = 330; }; + extcon_usb1: extcon_usb1 { + compatible = linux,extcon-usb; + id-gpio = pcf_gpio_21 1 GPIO_ACTIVE_HIGH; + }; + + extcon_usb2: extcon_usb2 { + compatible = linux,extcon-usb; + id-gpio = pcf_gpio_21 2 GPIO_ACTIVE_HIGH; + }; + vtt_fixed: fixedregulator-vtt { compatible = regulator-fixed; regulator-name = vtt_fixed; @@ -391,6 +401,19 @@ }; }; }; + + pcf_gpio_21: gpio@21 { + compatible = ti,pcf8575; + reg = 0x21; + lines-initial-states = 0x1408; + gpio-controller; + #gpio-cells = 2; + interrupt-parent = gpio6; + interrupts = 11 IRQ_TYPE_EDGE_FALLING; + interrupt-controller; + #interrupt-cells = 2; + }; + }; i2c2 { @@ -520,6 +543,14 @@ }; }; +omap_dwc3_1 { + extcon = extcon_usb1; +}; + +omap_dwc3_2 { + extcon = extcon_usb2; +}; + usb1 { dr_mode = peripheral; pinctrl-names = default; -- 2.1.0 -- balbi signature.asc Description: Digital signature
Re: [PATCH 0/5] extcon: usb: Introduce USB GPIO extcon driver. Fix DRA7 USB.
On Mon, Jan 19, 2015 at 07:52:17PM +0200, Roger Quadros wrote: Hi, On DRA7 EVMs the USB ID pin is connected to a GPIO line. The USB drivers (dwc3 + dwc3-omap) depend on extcon framework to get the USB cable state (USB or USB-Host) to put the controller in the right mode. There were earlier attempts [1] to get this working by trying to patch up the existing GPIO extcon driver. This series attemts to take a different approach by introducing a new USB specific extcon driver to handle the USB ID GPIO pin and interpret a right USB cable state. The reasoning to introduce this new driver is: 1) The existing GPIO extcon driver doesn't understand USB cable states and it can't handle more than one cable per instance. For the USB case we need to handle at least 2 cable states. a) USB (attach/detach) b) USB-Host (attach/detach) and could possible include more states like c) Fast-charger (attach/detach) d) Slow-charger (attach/detach) 2) This USB specific driver can be easily updated in the future to handle VBUS events, or charger detect events, in case it happens to be available on GPIO for any platform. 3) The DT implementation is very easy. You just need one extcon node per USB instead of one extcon node per cable state as in case of [1]. 4) The cable state string doesn't need to be encoded in the device tree as in case of [1]. 5) With only ID event available, you can simulate a USB-peripheral attach when USB-Host is detacted instead of hacking the USB driver to do the same. Tested on DRA7-evm and DRA72-evm. while at that, you might want to patch X15 too. -- balbi signature.asc Description: Digital signature
Re: ohci: sporadic crash/lockup in ohci-hcd io_watchdog_func()
On Tuesday 20 January 2015 10:49:29 Alan Stern wrote: On Mon, 19 Jan 2015, Heiko Przybyl wrote: On Monday 19 January 2015 11:17:59 Alan Stern wrote: That's easy enough to test. All you have to do is change the spin_lock/unlock statements to their irq_save/restore variants. Well, thought about that as well, but I'm not sure when to take it as fixed and when to take it as issue-just-didn't-happen-yet, because of the not-so- deterministic occurrence of the error. But I can try it out anyway, just wanted to have some feedback before trying. By the way, failing to disable interrupts when acquiring a spinlock generally does not lead to data corruption -- it leads to deadlocks. So I doubt this is the cause of your problem. If you really want to, you could add a WARN_ON(!irqs_disabled()); line to ohci_irq(). You're right. After thinking/reading a bit more about the topic, not disabled IRQs would cause deadlocks, because there's already one thread in the critical section. No idea. It might be a good idea for you to try something a little more invasive. How about writing a routine to check the entire ohci-eds_in_use list for validity (each forward pointer is matched by the corresponding backward pointer), and calling this routine at each place where the list gets modified, before the modification happens? You could also make sure that an entry being added to the list isn't on the list already, and whenever an entry is deleted from the list either it really is on the list or else its list pointers point to themselves. I'm not 100% sure, but then it's probably a race between urb enqueuing (duplicates?) and the watchdog orphan cleanup. The crash log already shows the double list add in ohci_urb_enqueue ohci-hcd.c:238: list_add(ed-in_use_list, ohci-eds_in_use); This is probably due to the ed returned by ed_get() being reused before the watchdog ran, thus the same in_use_list re-added to ohci.eds_in_use. Entries seem to get removed in finish_unlinks() ohci-q.c:1090: list_del(ed-in_use_list); with list_del() poisoning the next/prev pointers of the removed entry. Now with the watchdog starting cleanup it iterates over the ohci.eds_in_use list that still has the second very same entry of in_use_list we double-added (but now with 0xdead... pointers) and we fault on ohci-hcd.c:761: if (ed-pending_td) { I hope that makes any sense? I'll hook up the list checking tomorrow. Though I haven't hit the (double-add) problem again, since the bug report. Seems pretty specific the whole thing. Alan Stern Heiko -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 00/20] Add UDC support to the isp1760 driver
On Tue, Jan 20, 2015 at 09:29:04PM +0200, Laurent Pinchart wrote: Hi Felipe, On Friday 09 January 2015 11:34:25 Felipe Balbi wrote: On Fri, Jan 09, 2015 at 11:30:31AM -0600, Felipe Balbi wrote: This patch set adds UDC support to the isp1760 driver, to be used with the ISP1761 dual-role USB controller. The first 17 patches rework the isp1760 driver to prepare it for UDC support. In particular they removes the direct HCD dependencies from the glue code (01/20 to 04/20), creates core initialization code shared by the HCD and UDC (15/20) and move common initialization code to the core (16/20 to 17/20). Patch 18/20 adds UDC support, and patches 19/20 and 20/20 move the driver to drivers/usb/isp1760/ and make HCD support optional. The ISP1761 has three USB ports, with port 1 configurable in host or peripheral mode with OTG support, and ports 2 and 3 supporting host mode only. OTG support is not implemented yet, port 1 can thus be configured in host or peripheral mode only. The UDC driver has been successfully tested with the g_zero and g_mass_storage gadgets. Global changes compared to v2: - Rebase on top of Felipe's testing/next branch - Drop patches that have been merged already - Add patch 19/20 and 20/20 Global changes compared to v1: - Replace GPIO request move by patch 01/22 - Split PORT1 configuration to separate patch - Drop the shutdown implementation patch - Add patches 02/22, 04/22, 05/22, 13/22, 14/22 See individual patches for patch-specific changes. with this set I started getting: In file included from drivers/usb/isp1760/isp1760-core.h:22:0, from drivers/usb/isp1760/isp1760-core.c:24: drivers/usb/isp1760/isp1760-udc.h:65:5: warning: CONFIG_USB_ISP1761_UDC is not defined [-Wundef] drivers/usb/isp1760/isp1760-udc.h:90:5: warning: CONFIG_USB_ISP1761_UDC is not defined [-Wundef] I have now dropped this series from my testing/next btw, I've dropped the entire series, even the ones which were applied before. Please rebase and make sure each patch builds fine without warnings or build errors. Sorry about that. I forgot to update drivers/usb/host/Makefile, and the build breakage went unnoticed as the isp1760 object files were still available in that directory. I'm fixing the issue and I'll resubmit the patches shortly. cool, thanks -- balbi signature.asc Description: Digital signature
[PATCH v4 02/26] usb: isp1760: Remove isp1760 glue structure
The structure is allocated for the sole purpose of holding a pointer to the HCD and being stored in platform device driver data. Store the HCD pointer directly instead. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-if.c | 46 ++- 1 file changed, 15 insertions(+), 31 deletions(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 7e8e7f6..b5bcb99 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -31,13 +31,9 @@ #endif #if defined(CONFIG_OF) defined(CONFIG_OF_IRQ) -struct isp1760 { - struct usb_hcd *hcd; -}; - static int of_isp1760_probe(struct platform_device *dev) { - struct isp1760 *drvdata; + struct usb_hcd *hcd; struct device_node *dp = dev-dev.of_node; struct resource *res; struct resource memory; @@ -47,23 +43,15 @@ static int of_isp1760_probe(struct platform_device *dev) unsigned int devflags = 0; u32 bus_width = 0; - drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); - if (!drvdata) - return -ENOMEM; - ret = of_address_to_resource(dp, 0, memory); - if (ret) { - ret = -ENXIO; - goto free_data; - } + if (ret) + return -ENXIO; res_len = resource_size(memory); res = request_mem_region(memory.start, res_len, dev_name(dev-dev)); - if (!res) { - ret = -EBUSY; - goto free_data; - } + if (!res) + return -EBUSY; virq = irq_of_parse_and_map(dp, 0); if (!virq) { @@ -91,34 +79,30 @@ static int of_isp1760_probe(struct platform_device *dev) if (of_get_property(dp, dreq-polarity, NULL) != NULL) devflags |= ISP1760_FLAG_DREQ_POL_HIGH; - drvdata-hcd = isp1760_register(memory.start, res_len, virq, - IRQF_SHARED, dev-dev, - dev_name(dev-dev), devflags); - if (IS_ERR(drvdata-hcd)) { - ret = PTR_ERR(drvdata-hcd); + hcd = isp1760_register(memory.start, res_len, virq, IRQF_SHARED, + dev-dev, dev_name(dev-dev), devflags); + if (IS_ERR(hcd)) { + ret = PTR_ERR(hcd); goto release_reg; } - platform_set_drvdata(dev, drvdata); + platform_set_drvdata(dev, hcd); return ret; release_reg: release_mem_region(memory.start, res_len); -free_data: - kfree(drvdata); return ret; } static int of_isp1760_remove(struct platform_device *dev) { - struct isp1760 *drvdata = platform_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(dev); - usb_remove_hcd(drvdata-hcd); - iounmap(drvdata-hcd-regs); - release_mem_region(drvdata-hcd-rsrc_start, drvdata-hcd-rsrc_len); - usb_put_hcd(drvdata-hcd); + usb_remove_hcd(hcd); + iounmap(hcd-regs); + release_mem_region(hcd-rsrc_start, hcd-rsrc_len); + usb_put_hcd(hcd); - kfree(drvdata); return 0; } -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 05/26] usb: isp1760: Merge platform and OF glue codes
Both handle platform devices, merge them. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/host/isp1760-if.c | 190 -- 1 file changed, 55 insertions(+), 135 deletions(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 730caa1..3db98da 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -12,121 +12,18 @@ #include linux/usb.h #include linux/io.h #include linux/module.h +#include linux/of.h #include linux/platform_device.h +#include linux/slab.h #include linux/usb/isp1760.h #include linux/usb/hcd.h #include isp1760-hcd.h -#if defined(CONFIG_OF) defined(CONFIG_OF_IRQ) -#include linux/slab.h -#include linux/of.h -#include linux/of_platform.h -#include linux/of_address.h -#include linux/of_irq.h -#endif - #ifdef CONFIG_PCI #include linux/pci.h #endif -#if defined(CONFIG_OF) defined(CONFIG_OF_IRQ) -static int of_isp1760_probe(struct platform_device *dev) -{ - struct usb_hcd *hcd; - struct device_node *dp = dev-dev.of_node; - struct resource *res; - struct resource memory; - int virq; - resource_size_t res_len; - int ret; - unsigned int devflags = 0; - u32 bus_width = 0; - - ret = of_address_to_resource(dp, 0, memory); - if (ret) - return -ENXIO; - - res_len = resource_size(memory); - - res = request_mem_region(memory.start, res_len, dev_name(dev-dev)); - if (!res) - return -EBUSY; - - virq = irq_of_parse_and_map(dp, 0); - if (!virq) { - ret = -ENODEV; - goto release_reg; - } - - if (of_device_is_compatible(dp, nxp,usb-isp1761)) - devflags |= ISP1760_FLAG_ISP1761; - - /* Some systems wire up only 16 of the 32 data lines */ - of_property_read_u32(dp, bus-width, bus_width); - if (bus_width == 16) - devflags |= ISP1760_FLAG_BUS_WIDTH_16; - - if (of_get_property(dp, port1-otg, NULL) != NULL) - devflags |= ISP1760_FLAG_OTG_EN; - - if (of_get_property(dp, analog-oc, NULL) != NULL) - devflags |= ISP1760_FLAG_ANALOG_OC; - - if (of_get_property(dp, dack-polarity, NULL) != NULL) - devflags |= ISP1760_FLAG_DACK_POL_HIGH; - - if (of_get_property(dp, dreq-polarity, NULL) != NULL) - devflags |= ISP1760_FLAG_DREQ_POL_HIGH; - - hcd = isp1760_register(memory.start, res_len, virq, IRQF_SHARED, - dev-dev, dev_name(dev-dev), devflags); - if (IS_ERR(hcd)) { - ret = PTR_ERR(hcd); - goto release_reg; - } - - platform_set_drvdata(dev, hcd); - return ret; - -release_reg: - release_mem_region(memory.start, res_len); - return ret; -} - -static int of_isp1760_remove(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - usb_remove_hcd(hcd); - iounmap(hcd-regs); - release_mem_region(hcd-rsrc_start, hcd-rsrc_len); - usb_put_hcd(hcd); - - return 0; -} - -static const struct of_device_id of_isp1760_match[] = { - { - .compatible = nxp,usb-isp1760, - }, - { - .compatible = nxp,usb-isp1761, - }, - { }, -}; -MODULE_DEVICE_TABLE(of, of_isp1760_match); - -static struct platform_driver isp1760_of_driver = { - .driver = { - .name = nxp-isp1760, - .of_match_table = of_isp1760_match, - }, - .probe = of_isp1760_probe, - .remove = of_isp1760_remove, -}; -#endif - #ifdef CONFIG_PCI static int isp1761_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) @@ -304,26 +201,23 @@ static struct pci_driver isp1761_pci_driver = { static int isp1760_plat_probe(struct platform_device *pdev) { - int ret = 0; - struct usb_hcd *hcd; + unsigned long irqflags = IRQF_SHARED; + unsigned int devflags = 0; struct resource *mem_res; struct resource *irq_res; resource_size_t mem_size; - struct isp1760_platform_data *priv = dev_get_platdata(pdev-dev); - unsigned int devflags = 0; - unsigned long irqflags = IRQF_SHARED; + struct usb_hcd *hcd; + int ret; mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem_res) { pr_warning(isp1760: Memory resource not available\n); - ret = -ENODEV; - goto out; + return -ENODEV; } mem_size = resource_size(mem_res); if (!request_mem_region(mem_res-start, mem_size, isp1760)) { pr_warning(isp1760: Cannot reserve the memory resource\n); - ret = -EBUSY; - goto out; + return -EBUSY; } irq_res = platform_get_resource(pdev,
[PATCH v4 01/26] usb: isp1760: Use the gpio descriptor API
Switching to the managed gpio descriptor API simplifies both error and cleanup code paths (by removing the need to free the gpio) and runtime code (by removing manual handling of the active low flag). It also permits handling the reset gpio entirely from within the HCD code, sharing it between the different glue layers. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 24 drivers/usb/host/isp1760-hcd.h | 2 -- drivers/usb/host/isp1760-if.c | 39 +++ 3 files changed, 19 insertions(+), 46 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 395649f..e4a9424 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -11,6 +11,7 @@ * (c) 2011 Arvid Brodin arvid.bro...@enea.com * */ +#include linux/gpio/consumer.h #include linux/module.h #include linux/kernel.h #include linux/slab.h @@ -24,7 +25,6 @@ #include linux/timer.h #include asm/unaligned.h #include asm/cacheflush.h -#include linux/gpio.h #include isp1760-hcd.h @@ -57,7 +57,7 @@ struct isp1760_hcd { unsigned long next_statechange; unsigned intdevflags; - int rst_gpio; + struct gpio_desc*rst_gpio; }; static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) @@ -444,15 +444,10 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) u32 scratch, hwmode; /* low-level chip reset */ - if (gpio_is_valid(priv-rst_gpio)) { - unsigned int rst_lvl; - - rst_lvl = (priv-devflags - ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0; - - gpio_set_value(priv-rst_gpio, rst_lvl); + if (priv-rst_gpio) { + gpiod_set_value_cansleep(priv-rst_gpio, 1); mdelay(50); - gpio_set_value(priv-rst_gpio, !rst_lvl); + gpiod_set_value_cansleep(priv-rst_gpio, 0); } /* Setup HW Mode Control: This assumes a level active-low interrupt */ @@ -2215,7 +2210,6 @@ void deinit_kmem_cache(void) struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, unsigned long irqflags, -int rst_gpio, struct device *dev, const char *busname, unsigned int devflags) { @@ -2235,7 +2229,13 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, priv = hcd_to_priv(hcd); priv-devflags = devflags; - priv-rst_gpio = rst_gpio; + + priv-rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); + if (IS_ERR(priv-rst_gpio)) { + ret = PTR_ERR(priv-rst_gpio); + goto err_put; + } + init_memory(priv); hcd-regs = ioremap(res_start, res_len); if (!hcd-regs) { diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 33dc79c..fda0f2d 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -4,7 +4,6 @@ /* exports for if */ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, unsigned long irqflags, -int rst_gpio, struct device *dev, const char *busname, unsigned int devflags); int init_kmem_once(void); @@ -127,7 +126,6 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, #define ISP1760_FLAG_ISP1761 0x0040 /* Chip is ISP1761 */ #define ISP1760_FLAG_INTR_POL_HIGH 0x0080 /* Interrupt polarity active high */ #define ISP1760_FLAG_INTR_EDGE_TRIG0x0100 /* Interrupt edge triggered */ -#define ISP1760_FLAG_RESET_ACTIVE_HIGH 0x8000 /* RESET GPIO active high */ /* chip memory management */ struct memory_chunk { diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 09254a4..7e8e7f6 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -24,7 +24,6 @@ #include linux/of_platform.h #include linux/of_address.h #include linux/of_irq.h -#include linux/of_gpio.h #endif #ifdef CONFIG_PCI @@ -34,7 +33,6 @@ #if defined(CONFIG_OF) defined(CONFIG_OF_IRQ) struct isp1760 { struct usb_hcd *hcd; - int rst_gpio; }; static int of_isp1760_probe(struct platform_device *dev) @@ -47,7 +45,6 @@ static int of_isp1760_probe(struct platform_device *dev) resource_size_t res_len; int ret; unsigned int devflags = 0; - enum of_gpio_flags gpio_flags; u32 bus_width = 0; drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); @@ -94,36 +91,17 @@ static int of_isp1760_probe(struct
[PATCH v4 00/26] Add UDC support to the isp1760 driver
Hello, This patch set adds UDC support to the isp1760 driver, to be used with the ISP1761 dual-role USB controller. The first 21 patches rework the isp1760 driver to prepare it for UDC support. In particular they removes the direct HCD dependencies from the glue code (01/26 to 08/26), creates core initialization code shared by the HCD and UDC (18/26) and move common initialization code to the core (19/26 to 21/26). Patch 22/26 adds UDC support, patch 23/26 moves the driver to drivers/usb/isp1760/, and patches 24/26 to 26/26 make HCD support optional. The ISP1761 has three USB ports, with port 1 configurable in host or peripheral mode with OTG support, and ports 2 and 3 supporting host mode only. OTG support is not implemented yet, port 1 can thus be configured in host or peripheral mode only. The UDC driver has been successfully tested with the g_zero and g_mass_storage gadgets. Felipe, I've tested compilation with all possible options of CONFIG_USB, CONFIG_USB_STORAGE, CONFIG_USB_ISP1760 and CONFIG_USB_ISP1760_*_ROLE. Changes compared to v3: - Fix compilation breakage due to isp1760 leftovers in drivers/usb/host/Makefile - Add patches 01/26 to 04/16 that have been dropped from the USB gadget master branch - Add patches 25/26 and 26/26 Global changes compared to v2: - Rebase on top of Felipe's testing/next branch - Drop patches that have been merged already - Add patch 19/20 and 20/20 Global changes compared to v1: - Replace GPIO request move by patch 01/22 - Split PORT1 configuration to separate patch - Drop the shutdown implementation patch - Add patches 02/22, 04/22, 05/22, 13/22, 14/22 See individual patches for details. Laurent Pinchart (26): usb: isp1760: Use the gpio descriptor API usb: isp1760: Remove isp1760 glue structure usb: isp1760: Retrieve pdev memory resource from hcd at remove time usb: isp1760: Unmap I/O registers at platform device removal usb: isp1760: Merge platform and OF glue codes usb: isp1760: Move removal cleanup code to isp1760-hcd.c usb: isp1760: Manage device driver data in common code usb: isp1760: Don't expose hcd to glue code from isp1760_register usb: isp1760: Fix indentation in probe error path usb: isp1760: Prefix init_kmem_once and deinit_kmem_cache with isp1760_ usb: isp1760: Remove busname argument to isp1760_register usb: isp1760: Pass resource pointer to isp1760_register usb: isp1760: Use the managed devm_ioremap_resource() API usb: isp1760: Refactor PCI initialization code usb: isp1760: Decouple usb_hdc and isp1760_priv usb: isp1760: Prefix driver data structures with isp1760_ usb: isp1760: Reorganize header files usb: isp1760: Move core code to isp1760-core.c usb: isp1760: Set IRQF_SHARED flag in core code usb: isp1760: Initialize the bus interface in core code usb: isp1760: Move PORT1 configuration to core code usb: isp1760: Add device controller support usb: isp1760: Move driver from drivers/usb/host/ to drivers/usb/isp1760/ usb: isp1760: Make HCD support optional usb: isp1760: Remove duplicate usb_disabled() check usb: isp1760: Fix USB disabled check drivers/usb/Kconfig|2 + drivers/usb/Makefile |2 +- drivers/usb/host/Kconfig | 14 - drivers/usb/host/Makefile |3 - drivers/usb/host/isp1760-hcd.c | 2268 drivers/usb/host/isp1760-hcd.h | 208 drivers/usb/host/isp1760-if.c | 477 drivers/usb/isp1760/Kconfig| 59 + drivers/usb/isp1760/Makefile |5 + drivers/usb/isp1760/isp1760-core.c | 177 +++ drivers/usb/isp1760/isp1760-core.h | 68 ++ drivers/usb/isp1760/isp1760-hcd.c | 2234 +++ drivers/usb/isp1760/isp1760-hcd.h | 102 ++ drivers/usb/isp1760/isp1760-if.c | 309 + drivers/usb/isp1760/isp1760-regs.h | 230 drivers/usb/isp1760/isp1760-udc.c | 1498 drivers/usb/isp1760/isp1760-udc.h | 106 ++ 17 files changed, 4791 insertions(+), 2971 deletions(-) delete mode 100644 drivers/usb/host/isp1760-hcd.c delete mode 100644 drivers/usb/host/isp1760-hcd.h delete mode 100644 drivers/usb/host/isp1760-if.c create mode 100644 drivers/usb/isp1760/Kconfig create mode 100644 drivers/usb/isp1760/Makefile create mode 100644 drivers/usb/isp1760/isp1760-core.c create mode 100644 drivers/usb/isp1760/isp1760-core.h create mode 100644 drivers/usb/isp1760/isp1760-hcd.c create mode 100644 drivers/usb/isp1760/isp1760-hcd.h create mode 100644 drivers/usb/isp1760/isp1760-if.c create mode 100644 drivers/usb/isp1760/isp1760-regs.h create mode 100644 drivers/usb/isp1760/isp1760-udc.c create mode 100644 drivers/usb/isp1760/isp1760-udc.h -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv4 0/3] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal
If USB PLL is not necessary for other USB drivers (e.g. OHCI and EHCI) reduce power consumption by switching off the USB PLL if no USB Host is currently connected to this USB Device. Changes since v3: * Added stable tag for the first patch * As suggested, removed the unused check for udc-driver is not NULL in Vbus IRQ by requesting IRQ after udc-driver is set and by releasing IRQ before udc-driver is cleared * Rebased the core patch of this series against the just explained changes Changes since v2: * Use spin_lock_irqsave/unlock_irqrestore instead of spin_lock/unlock in threaded interrupt because we are not in irq context anymore * Removed useless and probably harmful IRQF_NO_SUSPEND from devm_request_threaded_irq() flags Changes since v1: * Using a threaded irq and mutex instead of spinclock as suggested * Moved a silently fixed bug in a separate patch (1/2) Sylvain Rochet (3): USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state USB: gadget: atmel_usba_udc: Enable Vbus signal IRQ in UDC start instead of UDC probe USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal drivers/usb/gadget/udc/atmel_usba_udc.c | 130 +--- drivers/usb/gadget/udc/atmel_usba_udc.h | 4 + 2 files changed, 89 insertions(+), 45 deletions(-) -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCHv4 2/3] USB: gadget: atmel_usba_udc: Enable Vbus signal IRQ in UDC start instead of UDC probe
Vbus IRQ handler needs a started UDC driver to work because it uses udc-driver, which is set by the UDC start handler. The previous way chosen was to return from interrupt if udc-driver is NULL using a spinlock. This patch now request the Vbus signal IRQ in UDC start instead of UDC probe and release the IRQ in UDC stop before udc-driver is set back to NULL. This way we don't need the check about udc-driver in interruption handler, therefore we don't need the spinlock as well anymore. This was chosen against using set_irq_flags() to request a not auto enabled IRQ (IRQF_NOAUTOEN flag) because set_irq_flags() can't change just one flag, therefore it must be called with all flags, without respecting what the AIC previously did. Naively copying IRQ flags currently set by the AIC looked like error-prone if defaults flags change at some point in the future. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Suggested-by: Boris Brezillon boris.brezil...@free-electrons.com --- drivers/usb/gadget/udc/atmel_usba_udc.c | 64 - 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index e207d75..546da63 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -1729,10 +1729,6 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) spin_lock(udc-lock); - /* May happen if Vbus pin toggles during probe() */ - if (!udc-driver) - goto out; - vbus = vbus_is_present(udc); if (vbus != udc-vbus_prev) { if (vbus) { @@ -1753,7 +1749,6 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) udc-vbus_prev = vbus; } -out: spin_unlock(udc-lock); return IRQ_HANDLED; @@ -1767,23 +1762,27 @@ static int atmel_usba_start(struct usb_gadget *gadget, unsigned long flags; spin_lock_irqsave(udc-lock, flags); - udc-devstatus = 1 USB_DEVICE_SELF_POWERED; udc-driver = driver; spin_unlock_irqrestore(udc-lock, flags); ret = clk_prepare_enable(udc-pclk); if (ret) - return ret; + goto err_pclk; ret = clk_prepare_enable(udc-hclk); - if (ret) { - clk_disable_unprepare(udc-pclk); - return ret; - } + if (ret) + goto err_hclk; udc-vbus_prev = 0; - if (gpio_is_valid(udc-vbus_pin)) - enable_irq(gpio_to_irq(udc-vbus_pin)); + if (gpio_is_valid(udc-vbus_pin)) { + ret = request_irq(gpio_to_irq(udc-vbus_pin), + usba_vbus_irq, 0, + atmel_usba_udc, udc); + if (ret) { + udc-vbus_pin = -ENODEV; + goto err; + } + } /* If Vbus is present, enable the controller and wait for reset */ spin_lock_irqsave(udc-lock, flags); @@ -1797,6 +1796,17 @@ static int atmel_usba_start(struct usb_gadget *gadget, spin_unlock_irqrestore(udc-lock, flags); return 0; + +err: + clk_disable_unprepare(udc-hclk); +err_hclk: + clk_disable_unprepare(udc-pclk); +err_pclk: + spin_lock_irqsave(udc-lock, flags); + udc-devstatus = ~(1 USB_DEVICE_SELF_POWERED); + udc-driver = NULL; + spin_unlock_irqrestore(udc-lock, flags); + return ret; } static int atmel_usba_stop(struct usb_gadget *gadget) @@ -1805,7 +1815,7 @@ static int atmel_usba_stop(struct usb_gadget *gadget) unsigned long flags; if (gpio_is_valid(udc-vbus_pin)) - disable_irq(gpio_to_irq(udc-vbus_pin)); + free_irq(gpio_to_irq(udc-vbus_pin), udc); spin_lock_irqsave(udc-lock, flags); udc-gadget.speed = USB_SPEED_UNKNOWN; @@ -2047,24 +2057,14 @@ static int usba_udc_probe(struct platform_device *pdev) } udc-irq = irq; - if (gpio_is_valid(udc-vbus_pin)) { - if (!devm_gpio_request(pdev-dev, udc-vbus_pin, atmel_usba_udc)) { - ret = devm_request_irq(pdev-dev, - gpio_to_irq(udc-vbus_pin), - usba_vbus_irq, 0, - atmel_usba_udc, udc); - if (ret) { - udc-vbus_pin = -ENODEV; - dev_warn(udc-pdev-dev, -failed to request vbus irq; -assuming always on\n); - } else { - disable_irq(gpio_to_irq(udc-vbus_pin)); - } - } else { - /* gpio_request fail so use -EINVAL for gpio_is_valid */ - udc-vbus_pin = -EINVAL; - } +
[PATCHv4 3/3] USB: gadget: atmel_usba_udc: Start clocks on rising edge of the Vbus signal, stop clocks on falling edge of the Vbus signal
If USB PLL is not necessary for other USB drivers (e.g. OHCI and EHCI) it will reduce power consumption by switching off the USB PLL if no USB Host is currently connected to this USB Device. We are using Vbus GPIO signal to detect Host presence. If Vbus signal is not available then the device stays continuously clocked. Note this driver does not support suspend/resume yet, it may stay clocked if USB Host is still connected when suspending. For what I need, forbidding suspend from userland if we are still attached to an USB host is fine, but we might as well add suspend/resume to this driver in the future. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com --- drivers/usb/gadget/udc/atmel_usba_udc.c | 86 - drivers/usb/gadget/udc/atmel_usba_udc.h | 4 ++ 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 546da63..e05b16c 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -315,6 +315,37 @@ static inline void usba_cleanup_debugfs(struct usba_udc *udc) } #endif +static int start_clock(struct usba_udc *udc) +{ + int ret; + + if (udc-clocked) + return 0; + + ret = clk_prepare_enable(udc-pclk); + if (ret) + return ret; + ret = clk_prepare_enable(udc-hclk); + if (ret) { + clk_disable_unprepare(udc-pclk); + return ret; + } + + udc-clocked = true; + return 0; +} + +static void stop_clock(struct usba_udc *udc) +{ + if (!udc-clocked) + return; + + clk_disable_unprepare(udc-hclk); + clk_disable_unprepare(udc-pclk); + + udc-clocked = false; +} + static int vbus_is_present(struct usba_udc *udc) { if (gpio_is_valid(udc-vbus_pin)) @@ -1719,37 +1750,48 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) return IRQ_HANDLED; } -static irqreturn_t usba_vbus_irq(int irq, void *devid) +static irqreturn_t usba_vbus_irq_thread(int irq, void *devid) { struct usba_udc *udc = devid; int vbus; + int ret; + unsigned long flags; /* debounce */ udelay(10); - spin_lock(udc-lock); + mutex_lock(udc-vbus_mutex); vbus = vbus_is_present(udc); if (vbus != udc-vbus_prev) { if (vbus) { + ret = start_clock(udc); + if (ret) + goto out; + + spin_lock_irqsave(udc-lock, flags); toggle_bias(1); usba_writel(udc, CTRL, USBA_ENABLE_MASK); usba_writel(udc, INT_ENB, USBA_END_OF_RESET); + spin_unlock_irqrestore(udc-lock, flags); } else { + spin_lock_irqsave(udc-lock, flags); udc-gadget.speed = USB_SPEED_UNKNOWN; reset_all_endpoints(udc); toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); - if (udc-driver-disconnect) { - spin_unlock(udc-lock); + spin_unlock_irqrestore(udc-lock, flags); + + stop_clock(udc); + + if (udc-driver-disconnect) udc-driver-disconnect(udc-gadget); - spin_lock(udc-lock); - } } udc-vbus_prev = vbus; } - spin_unlock(udc-lock); +out: + mutex_unlock(udc-vbus_mutex); return IRQ_HANDLED; } @@ -1766,17 +1808,12 @@ static int atmel_usba_start(struct usb_gadget *gadget, udc-driver = driver; spin_unlock_irqrestore(udc-lock, flags); - ret = clk_prepare_enable(udc-pclk); - if (ret) - goto err_pclk; - ret = clk_prepare_enable(udc-hclk); - if (ret) - goto err_hclk; + mutex_lock(udc-vbus_mutex); udc-vbus_prev = 0; if (gpio_is_valid(udc-vbus_pin)) { - ret = request_irq(gpio_to_irq(udc-vbus_pin), - usba_vbus_irq, 0, + ret = request_threaded_irq(gpio_to_irq(udc-vbus_pin), NULL, + usba_vbus_irq_thread, IRQF_ONESHOT, atmel_usba_udc, udc); if (ret) { udc-vbus_pin = -ENODEV; @@ -1785,23 +1822,24 @@ static int atmel_usba_start(struct usb_gadget *gadget, } /* If Vbus is present, enable the controller and wait for reset */ - spin_lock_irqsave(udc-lock, flags); if (vbus_is_present(udc) udc-vbus_prev == 0) { + ret = start_clock(udc); + if (ret) +
[PATCHv4 1/3] USB: gadget: atmel_usba_udc: Fixed vbus_prev initial state
If vbus gpio is high at init, we should set vbus_prev to true accordingly to the current vbus state. Without that, we skip the first vbus interrupt because the saved vbus state is not consistent. Signed-off-by: Sylvain Rochet sylvain.roc...@finsecur.com Acked-by: Nicolas Ferre nicolas.fe...@atmel.com Fixes: 914a3f3b3754 (USB: add atmel_usba_udc driver) Cc: sta...@vger.kernel.org #2.6.24+ --- drivers/usb/gadget/udc/atmel_usba_udc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index ce88237..e207d75 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -1791,6 +1791,8 @@ static int atmel_usba_start(struct usb_gadget *gadget, toggle_bias(1); usba_writel(udc, CTRL, USBA_ENABLE_MASK); usba_writel(udc, INT_ENB, USBA_END_OF_RESET); + + udc-vbus_prev = 1; } spin_unlock_irqrestore(udc-lock, flags); -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 16/26] usb: isp1760: Prefix driver data structures with isp1760_
The slotinfo and memory_chunk structures are specific to the driver and defined in a header file. Prefix them with isp1760_ to avoid namespace clashes. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 15 --- drivers/usb/host/isp1760-hcd.h | 4 ++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 55c0add..99f56c6 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -44,11 +44,11 @@ struct isp1760_hcd { u32 hcs_params; spinlock_t lock; - struct slotinfo atl_slots[32]; + struct isp1760_slotinfo atl_slots[32]; int atl_done_map; - struct slotinfo int_slots[32]; + struct isp1760_slotinfo int_slots[32]; int int_done_map; - struct memory_chunk memory_pool[BLOCKS]; + struct isp1760_memory_chunk memory_pool[BLOCKS]; struct list_headqh_list[QH_END]; /* periodic schedule support */ @@ -743,8 +743,9 @@ static void qtd_free(struct isp1760_qtd *qtd) } static void start_bus_transfer(struct usb_hcd *hcd, u32 ptd_offset, int slot, - struct slotinfo *slots, struct isp1760_qtd *qtd, - struct isp1760_qh *qh, struct ptd *ptd) + struct isp1760_slotinfo *slots, + struct isp1760_qtd *qtd, struct isp1760_qh *qh, + struct ptd *ptd) { struct isp1760_hcd *priv = hcd_to_priv(hcd); int skip_map; @@ -857,7 +858,7 @@ static void enqueue_qtds(struct usb_hcd *hcd, struct isp1760_qh *qh) { struct isp1760_hcd *priv = hcd_to_priv(hcd); int ptd_offset; - struct slotinfo *slots; + struct isp1760_slotinfo *slots; int curr_slot, free_slot; int n; struct ptd ptd; @@ -1097,7 +1098,7 @@ static void handle_done_ptds(struct usb_hcd *hcd) struct isp1760_qh *qh; int slot; int state; - struct slotinfo *slots; + struct isp1760_slotinfo *slots; u32 ptd_offset; struct isp1760_qtd *qtd; int modified; diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 7fc510f..3056bcd 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -103,7 +103,7 @@ struct ptd { #define ATL_PTD_OFFSET 0x0c00 #define PAYLOAD_OFFSET 0x1000 -struct slotinfo { +struct isp1760_slotinfo { struct isp1760_qh *qh; struct isp1760_qtd *qtd; unsigned long timestamp; @@ -125,7 +125,7 @@ struct slotinfo { #define ISP1760_FLAG_INTR_EDGE_TRIG0x0100 /* Interrupt edge triggered */ /* chip memory management */ -struct memory_chunk { +struct isp1760_memory_chunk { unsigned int start; unsigned int size; unsigned int free; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 11/26] usb: isp1760: Remove busname argument to isp1760_register
The argument is unused, remove it. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 2 +- drivers/usb/host/isp1760-hcd.h | 2 +- drivers/usb/host/isp1760-if.c | 6 ++ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 0ae1719..9ba3023 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2213,7 +2213,7 @@ void isp1760_deinit_kmem_cache(void) int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, unsigned long irqflags, struct device *dev, -const char *busname, unsigned int devflags) +unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index f97c9d6..cc65602 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -4,7 +4,7 @@ /* exports for if */ int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, unsigned long irqflags, struct device *dev, -const char *busname, unsigned int devflags); +unsigned int devflags); void isp1760_unregister(struct device *dev); int isp1760_init_kmem_once(void); diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index e268b20..ce572cc 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -134,8 +134,7 @@ static int isp1761_pci_probe(struct pci_dev *dev, dev-dev.dma_mask = NULL; ret_status = isp1760_register(pci_mem_phy0, memlength, dev-irq, - IRQF_SHARED, dev-dev, - dev_name(dev-dev), devflags); + IRQF_SHARED, dev-dev, devflags); if (ret_status 0) goto cleanup3; @@ -259,8 +258,7 @@ static int isp1760_plat_probe(struct platform_device *pdev) } ret = isp1760_register(mem_res-start, mem_size, irq_res-start, - irqflags, pdev-dev, dev_name(pdev-dev), - devflags); + irqflags, pdev-dev, devflags); if (ret 0) goto cleanup; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 17/26] usb: isp1760: Reorganize header files
The isp1760-rhcd.h header contains PTD constants and structures only useful for the HCD implementation. It also contains register definitions that will be needed by common code when implementing support for the ISP1761 device controller, but doesn't contain the isp1760_hcd structure definition that will also be used by common code. Move definitions to the right location and create an isp1760-regs.h to store register definitions. No change other than moving definitions and modifying indentation is performed. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 130 +-- drivers/usb/host/isp1760-hcd.h | 230 +++- drivers/usb/host/isp1760-if.c | 1 + drivers/usb/host/isp1760-regs.h | 120 + 4 files changed, 256 insertions(+), 225 deletions(-) create mode 100644 drivers/usb/host/isp1760-regs.h diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 99f56c6..50434cc 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -27,41 +27,12 @@ #include asm/cacheflush.h #include isp1760-hcd.h +#include isp1760-regs.h static struct kmem_cache *qtd_cachep; static struct kmem_cache *qh_cachep; static struct kmem_cache *urb_listitem_cachep; -enum queue_head_types { - QH_CONTROL, - QH_BULK, - QH_INTERRUPT, - QH_END -}; - -struct isp1760_hcd { - struct usb_hcd *hcd; - - u32 hcs_params; - spinlock_t lock; - struct isp1760_slotinfo atl_slots[32]; - int atl_done_map; - struct isp1760_slotinfo int_slots[32]; - int int_done_map; - struct isp1760_memory_chunk memory_pool[BLOCKS]; - struct list_headqh_list[QH_END]; - - /* periodic schedule support */ -#defineDEFAULT_I_TDPS 1024 - unsignedperiodic_size; - unsignedi_thresh; - unsigned long reset_done; - unsigned long next_statechange; - unsigned intdevflags; - - struct gpio_desc*rst_gpio; -}; - typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, struct isp1760_qtd *qtd); @@ -70,32 +41,79 @@ static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) return *(struct isp1760_hcd **)hcd-hcd_priv; } -/* Section 2.2 Host Controller Capability Registers */ -#define HC_LENGTH(p) (((p)00)0x00ff) /* bits 7:0 */ -#define HC_VERSION(p) (((p)16)0x) /* bits 31:16 */ -#define HCS_INDICATOR(p) ((p)(1 16)) /* true: has port indicators */ -#define HCS_PPC(p) ((p)(1 4)) /* true: port power control */ -#define HCS_N_PORTS(p) (((p)0)0xf) /* bits 3:0, ports on HC */ -#define HCC_ISOC_CACHE(p) ((p)(1 7)) /* true: can cache isoc frame */ -#define HCC_ISOC_THRES(p) (((p)4)0x7) /* bits 6:4, uframes cached */ - -/* Section 2.3 Host Controller Operational Registers */ -#define CMD_LRESET (17) /* partial reset (no ports, etc) */ -#define CMD_RESET (11) /* reset HC not bus */ -#define CMD_RUN(10) /* start/stop HC */ -#define STS_PCD(12) /* port change detect */ -#define FLAG_CF(10) /* true: we'll support high speed */ - -#define PORT_OWNER (113) /* true: companion hc owns this port */ -#define PORT_POWER (112) /* true: has power (see PPC) */ -#define PORT_USB11(x) (((x) (3 10)) == (1 10)) /* USB 1.1 device */ -#define PORT_RESET (18) /* reset port */ -#define PORT_SUSPEND (17) /* suspend port */ -#define PORT_RESUME(16) /* resume it */ -#define PORT_PE(12) /* port enable */ -#define PORT_CSC (11) /* connect status change */ -#define PORT_CONNECT (10) /* device connected */ -#define PORT_RWC_BITS (PORT_CSC) +/* urb state*/ +#define DELETE_URB (0x0008) +#define NO_TRANSFER_ACTIVE (0x) + +/* Philips Proprietary Transfer Descriptor (PTD) */ +typedef __u32 __bitwise __dw; +struct ptd { + __dw dw0; + __dw dw1; + __dw dw2; + __dw dw3; + __dw dw4; + __dw dw5; + __dw dw6; + __dw dw7; +}; +#define PTD_OFFSET 0x0400 +#define ISO_PTD_OFFSET 0x0400 +#define INT_PTD_OFFSET 0x0800 +#define ATL_PTD_OFFSET 0x0c00 +#define PAYLOAD_OFFSET 0x1000 + + +/* ATL */ +/* DW0 */ +#define DW0_VALID_BIT 1 +#define FROM_DW0_VALID(x) ((x) 0x01) +#define TO_DW0_LENGTH(x) (((u32) x) 3) +#define TO_DW0_MAXPACKET(x)(((u32) x) 18) +#define TO_DW0_MULTI(x)(((u32) x) 29) +#define
[PATCH v4 22/26] usb: isp1760: Add device controller support
The ISP1761 is a dual-mode host and device controller backward compatible on the host side with the ISP1760. Add support for the device controller. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- Changes since v2: - Update .udc_stop API Changes since v1: - Reject SET_ADDRESS in states other than default and addressed - Unregister the HCD if initialization fails due to the UDC - Remove unnecessary sleep during initialization - Use the usb_gadget_udc_reset API - Add VBUS disconnection timer - Clean up comments - Clean up ep0_status usage usb: isp1760-udc: Reset stall flag when enabling the endpoint usb: isp1760-udc: Move lock from __isp1760_udc_set_stall to the callers usb: isp1760-udc: Move uninitialized endpoint check to isp1760_udc_set_halt usb: isp1760-udc: Refuse to halt IN endpoints with queued transfers usb: isp1760-udc: Reset EP0 state to SETUP when halting the endpoint usb: isp1760-udc: Differentiate protocol and functional stall usb: isp1760-udc: Release the UDC lock before completing request usb: isp1760-udc: Move to the status stage after completing the request usb: isp1760-udc: Stop the UDC when unregistering the gadget usb: isp1760-udc: Properly delegate non-standard control requests to gadget usb: isp1760-udc: Handle gadget device registration errors usb: isp1760-udc: Reject invalid SET_CONFIGURATION requests usb: isp1760-udc: Update device state in SET_CONFIGURATION usb: isp1760-udc: Fix oops at gadget registration when UDC probe failed usb: isp1760-udc: Print scratch register value when scratch test fails usb: isp1760-udc: Call the right operation in USB resume handler usb: isp1760-udc: Update to the latest UDC API usb: isp1760-udc: Fix locking in isp1760_udc_request_complete() usb: isp1760-udc: Remove fifo_status operation usb: isp1760-udc: Implement the flush_fifo operation usb: isp1760-udc: Improve request dequeue operation debug message usb: isp1760-udc: Implement wedge support --- drivers/usb/gadget/udc/Kconfig |7 + drivers/usb/host/Makefile |1 + drivers/usb/host/isp1760-core.c | 50 +- drivers/usb/host/isp1760-core.h |4 + drivers/usb/host/isp1760-regs.h | 110 +++ drivers/usb/host/isp1760-udc.c | 1495 +++ drivers/usb/host/isp1760-udc.h | 106 +++ 7 files changed, 1768 insertions(+), 5 deletions(-) create mode 100644 drivers/usb/host/isp1760-udc.c create mode 100644 drivers/usb/host/isp1760-udc.h diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index b8e213e..c9152e2 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -109,6 +109,13 @@ config USB_GR_UDC Select this to support Aeroflex Gaisler GRUSBDC cores from the GRLIB VHDL IP core library. +config USB_ISP1761_UDC + boolean NXP ISP1761 USB Device Controller + depends on USB_ISP1760_HCD + help + The NXP ISP1761 is a dual-role high-speed USB host and device + controller. + config USB_OMAP tristate OMAP USB Device Controller depends on ARCH_OMAP1 diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 4dea9b1..67d3f18 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -6,6 +6,7 @@ CFLAGS_xhci-trace.o := -I$(src) isp1760-y := isp1760-core.o isp1760-hcd.o isp1760-if.o +isp1760-$(CONFIG_USB_ISP1761_UDC) += isp1760-udc.o fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c index 1cba3e0..727e90a 100644 --- a/drivers/usb/host/isp1760-core.c +++ b/drivers/usb/host/isp1760-core.c @@ -24,9 +24,11 @@ #include isp1760-core.h #include isp1760-hcd.h #include isp1760-regs.h +#include isp1760-udc.h static void isp1760_init_core(struct isp1760_device *isp) { + u32 otgctrl; u32 hwmode; /* Low-level chip reset */ @@ -60,6 +62,17 @@ static void isp1760_init_core(struct isp1760_device *isp) hwmode |= HW_INTR_EDGE_TRIG; /* +* The ISP1761 has a dedicated DC IRQ line but supports sharing the HC +* IRQ line for both the host and device controllers. Hardcode IRQ +* sharing for now and disable the DC interrupts globally to avoid +* spurious interrupts during HCD registration. +*/ + if (isp-devflags ISP1760_FLAG_ISP1761) { + isp1760_write32(isp-regs, DC_MODE, 0); + hwmode |= HW_COMN_IRQ; + } + + /* * We have to set this first in case we're in 16-bit mode. * Write it twice to ensure correct upper bits if switching * to 16-bit mode. @@ -68,18 +81,33 @@ static void isp1760_init_core(struct isp1760_device *isp) isp1760_write32(isp-regs, HC_HW_MODE_CTRL, hwmode); /* -* PORT 1 Control register of the ISP1760 is the OTG control register on -* ISP1761. Since there is no OTG or
[PATCH v4 19/26] usb: isp1760: Set IRQF_SHARED flag in core code
The IRQF_SHARED flag needs to be set regardless of the bus type. Don't require glue code to set it manually. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-core.c | 4 ++-- drivers/usb/host/isp1760-if.c | 9 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c index d38efa0..35278a8 100644 --- a/drivers/usb/host/isp1760-core.c +++ b/drivers/usb/host/isp1760-core.c @@ -43,8 +43,8 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, if (IS_ERR(isp-regs)) return PTR_ERR(isp-regs); - ret = isp1760_hcd_register(isp-hcd, isp-regs, mem, irq, irqflags, - dev, devflags); + ret = isp1760_hcd_register(isp-hcd, isp-regs, mem, irq, + irqflags | IRQF_SHARED, dev, devflags); if (ret 0) return ret; diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index f2a3990..c2a94c9 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -142,8 +142,8 @@ static int isp1761_pci_probe(struct pci_dev *dev, pci_set_master(dev); dev-dev.dma_mask = NULL; - ret = isp1760_register(dev-resource[3], dev-irq, IRQF_SHARED, - dev-dev, devflags); + ret = isp1760_register(dev-resource[3], dev-irq, 0, dev-dev, + devflags); if (ret 0) goto error; @@ -190,7 +190,7 @@ static struct pci_driver isp1761_pci_driver = { static int isp1760_plat_probe(struct platform_device *pdev) { - unsigned long irqflags = IRQF_SHARED; + unsigned long irqflags; unsigned int devflags = 0; struct resource *mem_res; struct resource *irq_res; @@ -203,8 +203,7 @@ static int isp1760_plat_probe(struct platform_device *pdev) pr_warning(isp1760: IRQ resource not available\n); return -ENODEV; } - - irqflags |= irq_res-flags IRQF_TRIGGER_MASK; + irqflags = irq_res-flags IRQF_TRIGGER_MASK; if (IS_ENABLED(CONFIG_OF) pdev-dev.of_node) { struct device_node *dp = pdev-dev.of_node; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 15/26] usb: isp1760: Decouple usb_hdc and isp1760_priv
Allocate the driver private data structure manually instead of using the usb_hcd private space. This will allow skipping hcd registration for the isp1761 when used in device mode only. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- Changes since v1: - Use the devm_kzalloc managed allocator --- drivers/usb/host/isp1760-hcd.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 2e38efe..55c0add 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -40,6 +40,8 @@ enum queue_head_types { }; struct isp1760_hcd { + struct usb_hcd *hcd; + u32 hcs_params; spinlock_t lock; struct slotinfo atl_slots[32]; @@ -65,7 +67,7 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) { - return (struct isp1760_hcd *) (hcd-hcd_priv); + return *(struct isp1760_hcd **)hcd-hcd_priv; } /* Section 2.2 Host Controller Capability Registers */ @@ -2161,7 +2163,7 @@ static void isp1760_clear_tt_buffer_complete(struct usb_hcd *hcd, static const struct hc_driver isp1760_hc_driver = { .description= isp1760-hcd, .product_desc = NXP ISP1760 USB Host Controller, - .hcd_priv_size = sizeof(struct isp1760_hcd), + .hcd_priv_size = sizeof(struct isp1760_hcd *), .irq= isp1760_irq, .flags = HCD_MEMORY | HCD_USB2, .reset = isp1760_hc_setup, @@ -2214,13 +2216,17 @@ void isp1760_deinit_kmem_cache(void) int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, struct device *dev, unsigned int devflags) { - struct usb_hcd *hcd; + struct usb_hcd *hcd = NULL; struct isp1760_hcd *priv; int ret; if (usb_disabled()) return -ENODEV; + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + /* prevent usb-core allocating DMA pages */ dev-dma_mask = NULL; @@ -2228,7 +2234,9 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, if (!hcd) return -ENOMEM; - priv = hcd_to_priv(hcd); + priv-hcd = hcd; + *(struct isp1760_hcd **)hcd-hcd_priv = priv; + priv-devflags = devflags; priv-rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); @@ -2253,7 +2261,7 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, goto error; device_wakeup_enable(hcd-self.controller); - dev_set_drvdata(dev, hcd); + dev_set_drvdata(dev, priv); return 0; @@ -2264,7 +2272,8 @@ error: void isp1760_unregister(struct device *dev) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct isp1760_hcd *priv = dev_get_drvdata(dev); + struct usb_hcd *hcd = priv-hcd; usb_remove_hcd(hcd); usb_put_hcd(hcd); -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 13/26] usb: isp1760: Use the managed devm_ioremap_resource() API
This simplifies error and remove code paths. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/host/isp1760-hcd.c | 20 +++- drivers/usb/host/isp1760-if.c | 37 + 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index e99dafa..2e38efe 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2234,14 +2234,14 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, priv-rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); if (IS_ERR(priv-rst_gpio)) { ret = PTR_ERR(priv-rst_gpio); - goto err_put; + goto error; } init_memory(priv); - hcd-regs = ioremap(mem-start, resource_size(mem)); - if (!hcd-regs) { - ret = -EIO; - goto err_put; + hcd-regs = devm_ioremap_resource(dev, mem); + if (IS_ERR(hcd-regs)) { + ret = PTR_ERR(hcd-regs); + goto error; } hcd-irq = irq; @@ -2250,19 +2250,15 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, ret = usb_add_hcd(hcd, irq, irqflags); if (ret) - goto err_unmap; + goto error; device_wakeup_enable(hcd-self.controller); dev_set_drvdata(dev, hcd); return 0; -err_unmap: - iounmap(hcd-regs); - -err_put: +error: usb_put_hcd(hcd); - return ret; } @@ -2271,8 +2267,6 @@ void isp1760_unregister(struct device *dev) struct usb_hcd *hcd = dev_get_drvdata(dev); usb_remove_hcd(hcd); - iounmap(hcd-regs); - release_mem_region(hcd-rsrc_start, hcd-rsrc_len); usb_put_hcd(hcd); } diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 3a9b4f6..dbb287c 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -85,8 +85,9 @@ static int isp1761_pci_probe(struct pci_dev *dev, chip_addr = ioremap_nocache(pci_mem_phy0,memlength); if (!chip_addr) { printk(KERN_ERR Error ioremap failed\n); + release_mem_region(pci_mem_phy0, memlength); ret_status = -ENOMEM; - goto cleanup3; + goto cleanup2; } /* bad pci latencies can contribute to overruns */ @@ -114,6 +115,7 @@ static int isp1761_pci_probe(struct pci_dev *dev, } iounmap(chip_addr); + release_mem_region(pci_mem_phy0, memlength); /* Host Controller presence is detected by writing to scratch register * and reading back and checking the contents are same or not @@ -121,7 +123,7 @@ static int isp1761_pci_probe(struct pci_dev *dev, if (reg_data != 0xFACE) { dev_err(dev-dev, scratch register mismatch %x\n, reg_data); ret_status = -ENOMEM; - goto cleanup3; + goto cleanup2; } pci_set_master(dev); @@ -132,20 +134,14 @@ static int isp1761_pci_probe(struct pci_dev *dev, reg_data |= 0x900; writel(reg_data, iobase + PLX_INT_CSR_REG); - dev-dev.dma_mask = NULL; - ret_status = isp1760_register(dev-resource[3], dev-irq, IRQF_SHARED, - dev-dev, devflags); - if (ret_status 0) - goto cleanup3; - /* done with PLX IO access */ iounmap(iobase); release_mem_region(nxp_pci_io_base, iolength); - return 0; + dev-dev.dma_mask = NULL; + return isp1760_register(dev-resource[3], dev-irq, IRQF_SHARED, + dev-dev, devflags); -cleanup3: - release_mem_region(pci_mem_phy0, memlength); cleanup2: iounmap(iobase); cleanup1: @@ -193,25 +189,14 @@ static int isp1760_plat_probe(struct platform_device *pdev) unsigned int devflags = 0; struct resource *mem_res; struct resource *irq_res; - resource_size_t mem_size; int ret; mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem_res) { - pr_warning(isp1760: Memory resource not available\n); - return -ENODEV; - } - mem_size = resource_size(mem_res); - if (!request_mem_region(mem_res-start, mem_size, isp1760)) { - pr_warning(isp1760: Cannot reserve the memory resource\n); - return -EBUSY; - } irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!irq_res) { pr_warning(isp1760: IRQ resource not available\n); - ret = -ENODEV; - goto cleanup; + return -ENODEV; } irqflags |= irq_res-flags IRQF_TRIGGER_MASK; @@ -260,14 +245,10 @@ static int isp1760_plat_probe(struct platform_device *pdev)
[PATCH v4 25/26] usb: isp1760: Remove duplicate usb_disabled() check
Both isp1760_register() and isp1761_pci_probe() check whether USB is disabled by calling usb_disabled(), and bail out with an error if it is. One check is enough, remove the PCI-specific check. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/isp1760/isp1760-if.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c index c2a94c9..264be4d 100644 --- a/drivers/usb/isp1760/isp1760-if.c +++ b/drivers/usb/isp1760/isp1760-if.c @@ -126,9 +126,6 @@ static int isp1761_pci_probe(struct pci_dev *dev, unsigned int devflags = 0; int ret; - if (usb_disabled()) - return -ENODEV; - if (!dev-irq) return -ENODEV; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 07/26] usb: isp1760: Manage device driver data in common code
Don't duplicate *_set_drvdata calls in glue code. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 2 ++ drivers/usb/host/isp1760-if.c | 3 --- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 7498727..19fbd69 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2252,6 +2252,8 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, goto err_unmap; device_wakeup_enable(hcd-self.controller); + dev_set_drvdata(dev, hcd); + return hcd; err_unmap: diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index b96c62f..64eaf5d 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -146,7 +146,6 @@ static int isp1761_pci_probe(struct pci_dev *dev, iounmap(iobase); release_mem_region(nxp_pci_io_base, iolength); - pci_set_drvdata(dev, hcd); return 0; cleanup3: @@ -272,8 +271,6 @@ static int isp1760_plat_probe(struct platform_device *pdev) goto cleanup; } - platform_set_drvdata(pdev, hcd); - pr_info(ISP1760 USB device initialised\n); return 0; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 08/26] usb: isp1760: Don't expose hcd to glue code from isp1760_register
The glue code probe functions don't need to access the hcd structure anymore. Modify isp1760_register to return an integer error code instead of the hcd pointer. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 18 ++ drivers/usb/host/isp1760-hcd.h | 10 +++--- drivers/usb/host/isp1760-if.c | 19 ++- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 19fbd69..4d6e50b 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -60,6 +60,9 @@ struct isp1760_hcd { struct gpio_desc*rst_gpio; }; +typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, + struct isp1760_qtd *qtd); + static inline struct isp1760_hcd *hcd_to_priv(struct usb_hcd *hcd) { return (struct isp1760_hcd *) (hcd-hcd_priv); @@ -2208,24 +2211,23 @@ void deinit_kmem_cache(void) kmem_cache_destroy(urb_listitem_cachep); } -struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, -int irq, unsigned long irqflags, -struct device *dev, const char *busname, -unsigned int devflags) +int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, +unsigned long irqflags, struct device *dev, +const char *busname, unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; int ret; if (usb_disabled()) - return ERR_PTR(-ENODEV); + return -ENODEV; /* prevent usb-core allocating DMA pages */ dev-dma_mask = NULL; hcd = usb_create_hcd(isp1760_hc_driver, dev, dev_name(dev)); if (!hcd) - return ERR_PTR(-ENOMEM); + return -ENOMEM; priv = hcd_to_priv(hcd); priv-devflags = devflags; @@ -2254,7 +2256,7 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, dev_set_drvdata(dev, hcd); - return hcd; + return 0; err_unmap: iounmap(hcd-regs); @@ -2262,7 +2264,7 @@ err_unmap: err_put: usb_put_hcd(hcd); -return ERR_PTR(ret); +return ret; } void isp1760_unregister(struct device *dev) diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index ea13a58..372d2e5 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -2,10 +2,9 @@ #define _ISP1760_HCD_H_ /* exports for if */ -struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, -int irq, unsigned long irqflags, -struct device *dev, const char *busname, -unsigned int devflags); +int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, +unsigned long irqflags, struct device *dev, +const char *busname, unsigned int devflags); void isp1760_unregister(struct device *dev); int init_kmem_once(void); @@ -112,9 +111,6 @@ struct slotinfo { }; -typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, - struct isp1760_qtd *qtd); - /* * Device flags that can vary from board to board. All of these * indicate the most atypical case, so that a devflags of 0 is diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 64eaf5d..03243b0 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -31,7 +31,6 @@ static int isp1761_pci_probe(struct pci_dev *dev, u8 latency, limit; __u32 reg_data; int retry_count; - struct usb_hcd *hcd; unsigned int devflags = 0; int ret_status = 0; @@ -134,13 +133,11 @@ static int isp1761_pci_probe(struct pci_dev *dev, writel(reg_data, iobase + PLX_INT_CSR_REG); dev-dev.dma_mask = NULL; - hcd = isp1760_register(pci_mem_phy0, memlength, dev-irq, - IRQF_SHARED, dev-dev, dev_name(dev-dev), - devflags); - if (IS_ERR(hcd)) { - ret_status = -ENODEV; + ret_status = isp1760_register(pci_mem_phy0, memlength, dev-irq, + IRQF_SHARED, dev-dev, + dev_name(dev-dev), devflags); + if (ret_status 0) goto cleanup3; - } /* done with PLX IO access */ iounmap(iobase); @@ -198,7 +195,6 @@ static int isp1760_plat_probe(struct platform_device *pdev) struct resource *mem_res; struct resource *irq_res; resource_size_t mem_size; - struct usb_hcd *hcd; int ret; mem_res
[PATCH v4 24/26] usb: isp1760: Make HCD support optional
Enable compilation of the isp1760 driver in pure host mode, pure device mode, or dual-role mode. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/isp1760/Kconfig | 47 ++- drivers/usb/isp1760/Makefile | 3 ++- drivers/usb/isp1760/isp1760-hcd.h | 25 + drivers/usb/isp1760/isp1760-udc.h | 4 ++-- 4 files changed, 71 insertions(+), 8 deletions(-) diff --git a/drivers/usb/isp1760/Kconfig b/drivers/usb/isp1760/Kconfig index c09ab8f..c94b7d9 100644 --- a/drivers/usb/isp1760/Kconfig +++ b/drivers/usb/isp1760/Kconfig @@ -1,6 +1,6 @@ config USB_ISP1760 tristate NXP ISP 1760/1761 support - depends on USB + depends on USB || USB_GADGET help Say Y or M here if your system as an ISP1760 USB host controller or an ISP1761 USB dual-role controller. @@ -14,9 +14,46 @@ config USB_ISP1760 To compile this driver as a module, choose M here: the module will be called isp1760. +config USB_ISP1760_HCD + bool + config USB_ISP1761_UDC - boolean NXP ISP1761 USB Device Controller - depends on USB_ISP1760 USB_GADGET + bool + +if USB_ISP1760 + +choice + bool ISP1760 Mode Selection + default USB_ISP1760_DUAL_ROLE if (USB USB_GADGET) + default USB_ISP1760_HOST_ROLE if (USB !USB_GADGET) + default USB_ISP1760_GADGET_ROLE if (!USB USB_GADGET) + +config USB_ISP1760_HOST_ROLE + bool Host only mode + depends on USB=y || USB=USB_ISP1760 + select USB_ISP1760_HCD + help + Select this if you want to use the ISP1760 in host mode only. The + gadget function will be disabled. + +config USB_ISP1760_GADGET_ROLE + bool Gadget only mode + depends on USB_GADGET=y || USB_GADGET=USB_ISP1760 + select USB_ISP1761_UDC + help + Select this if you want to use the ISP1760 in peripheral mode only. + The host function will be disabled. + +config USB_ISP1760_DUAL_ROLE + bool Dual Role mode + depends on USB=y || USB=USB_ISP1760 + depends on USB_GADGET=y || USB_GADGET=USB_ISP1760 + select USB_ISP1760_HCD + select USB_ISP1761_UDC help - The NXP ISP1761 is a dual-role high-speed USB host and device - controller. + Select this if you want to use the ISP1760 in both host and + peripheral modes. + +endchoice + +endif diff --git a/drivers/usb/isp1760/Makefile b/drivers/usb/isp1760/Makefile index 698ccb0..2b74107 100644 --- a/drivers/usb/isp1760/Makefile +++ b/drivers/usb/isp1760/Makefile @@ -1,4 +1,5 @@ -isp1760-y := isp1760-core.o isp1760-hcd.o isp1760-if.o +isp1760-y := isp1760-core.o isp1760-if.o +isp1760-$(CONFIG_USB_ISP1760_HCD) += isp1760-hcd.o isp1760-$(CONFIG_USB_ISP1761_UDC) += isp1760-udc.o obj-$(CONFIG_USB_ISP1760) += isp1760.o diff --git a/drivers/usb/isp1760/isp1760-hcd.h b/drivers/usb/isp1760/isp1760-hcd.h index df7ea36..0c1c98d 100644 --- a/drivers/usb/isp1760/isp1760-hcd.h +++ b/drivers/usb/isp1760/isp1760-hcd.h @@ -47,6 +47,7 @@ enum isp1760_queue_head_types { }; struct isp1760_hcd { +#ifdef CONFIG_USB_ISP1760_HCD struct usb_hcd *hcd; u32 hcs_params; @@ -64,8 +65,10 @@ struct isp1760_hcd { unsignedi_thresh; unsigned long reset_done; unsigned long next_statechange; +#endif }; +#ifdef CONFIG_USB_ISP1760_HCD int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, struct resource *mem, int irq, unsigned long irqflags, struct device *dev); @@ -73,5 +76,27 @@ void isp1760_hcd_unregister(struct isp1760_hcd *priv); int isp1760_init_kmem_once(void); void isp1760_deinit_kmem_cache(void); +#else +static inline int isp1760_hcd_register(struct isp1760_hcd *priv, + void __iomem *regs, struct resource *mem, + int irq, unsigned long irqflags, + struct device *dev) +{ + return 0; +} + +static inline void isp1760_hcd_unregister(struct isp1760_hcd *priv) +{ +} + +static inline int isp1760_init_kmem_once(void) +{ + return 0; +} + +static inline void isp1760_deinit_kmem_cache(void) +{ +} +#endif #endif /* _ISP1760_HCD_H_ */ diff --git a/drivers/usb/isp1760/isp1760-udc.h b/drivers/usb/isp1760/isp1760-udc.h index 4af6ba6..26899ed 100644 --- a/drivers/usb/isp1760/isp1760-udc.h +++ b/drivers/usb/isp1760/isp1760-udc.h @@ -62,7 +62,7 @@ struct isp1760_ep { * connected: Tracks gadget driver bus connection state */ struct isp1760_udc { -#if CONFIG_USB_ISP1761_UDC +#ifdef CONFIG_USB_ISP1761_UDC struct isp1760_device *isp; int irq; @@ -87,7 +87,7 @@ struct isp1760_udc { #endif }; -#if CONFIG_USB_ISP1761_UDC +#ifdef CONFIG_USB_ISP1761_UDC int isp1760_udc_register(struct isp1760_device *isp,
[PATCH v4 09/26] usb: isp1760: Fix indentation in probe error path
Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 4d6e50b..aa894a1 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2259,12 +2259,12 @@ int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, return 0; err_unmap: -iounmap(hcd-regs); + iounmap(hcd-regs); err_put: -usb_put_hcd(hcd); + usb_put_hcd(hcd); -return ret; + return ret; } void isp1760_unregister(struct device *dev) -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 20/26] usb: isp1760: Initialize the bus interface in core code
Although the corresponding register is part of the HCD register space, processor bus initialization is not specific to the HCD. To prepare for device controller support, move bus interface initialization to core code. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-core.c | 62 -- drivers/usb/host/isp1760-core.h | 31 +++ drivers/usb/host/isp1760-hcd.c | 67 - drivers/usb/host/isp1760-hcd.h | 20 +--- 4 files changed, 105 insertions(+), 75 deletions(-) diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c index 35278a8..e840a1d 100644 --- a/drivers/usb/host/isp1760-core.c +++ b/drivers/usb/host/isp1760-core.c @@ -13,7 +13,8 @@ * version 2 as published by the Free Software Foundation. */ -#include linux/gpio.h +#include linux/delay.h +#include linux/gpio/consumer.h #include linux/io.h #include linux/kernel.h #include linux/module.h @@ -22,6 +23,54 @@ #include isp1760-core.h #include isp1760-hcd.h +#include isp1760-regs.h + +static void isp1760_init_core(struct isp1760_device *isp) +{ + u32 hwmode; + + /* Low-level chip reset */ + if (isp-rst_gpio) { + gpiod_set_value_cansleep(isp-rst_gpio, 1); + mdelay(50); + gpiod_set_value_cansleep(isp-rst_gpio, 0); + } + + /* +* Reset the host controller, including the CPU interface +* configuration. +*/ + isp1760_write32(isp-regs, HC_RESET_REG, SW_RESET_RESET_ALL); + msleep(100); + + /* Setup HW Mode Control: This assumes a level active-low interrupt */ + hwmode = HW_DATA_BUS_32BIT; + + if (isp-devflags ISP1760_FLAG_BUS_WIDTH_16) + hwmode = ~HW_DATA_BUS_32BIT; + if (isp-devflags ISP1760_FLAG_ANALOG_OC) + hwmode |= HW_ANA_DIGI_OC; + if (isp-devflags ISP1760_FLAG_DACK_POL_HIGH) + hwmode |= HW_DACK_POL_HIGH; + if (isp-devflags ISP1760_FLAG_DREQ_POL_HIGH) + hwmode |= HW_DREQ_POL_HIGH; + if (isp-devflags ISP1760_FLAG_INTR_POL_HIGH) + hwmode |= HW_INTR_HIGH_ACT; + if (isp-devflags ISP1760_FLAG_INTR_EDGE_TRIG) + hwmode |= HW_INTR_EDGE_TRIG; + + /* +* We have to set this first in case we're in 16-bit mode. +* Write it twice to ensure correct upper bits if switching +* to 16-bit mode. +*/ + isp1760_write32(isp-regs, HC_HW_MODE_CTRL, hwmode); + isp1760_write32(isp-regs, HC_HW_MODE_CTRL, hwmode); + + dev_info(isp-dev, bus width: %u, oc: %s\n, +isp-devflags ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32, +isp-devflags ISP1760_FLAG_ANALOG_OC ? analog : digital); +} int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, struct device *dev, unsigned int devflags) @@ -39,12 +88,21 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, if (!isp) return -ENOMEM; + isp-dev = dev; + isp-devflags = devflags; + + isp-rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); + if (IS_ERR(isp-rst_gpio)) + return PTR_ERR(isp-rst_gpio); + isp-regs = devm_ioremap_resource(dev, mem); if (IS_ERR(isp-regs)) return PTR_ERR(isp-regs); + isp1760_init_core(isp); + ret = isp1760_hcd_register(isp-hcd, isp-regs, mem, irq, - irqflags | IRQF_SHARED, dev, devflags); + irqflags | IRQF_SHARED, dev); if (ret 0) return ret; diff --git a/drivers/usb/host/isp1760-core.h b/drivers/usb/host/isp1760-core.h index 0caeb11..cd4a0f3 100644 --- a/drivers/usb/host/isp1760-core.h +++ b/drivers/usb/host/isp1760-core.h @@ -20,8 +20,29 @@ #include isp1760-hcd.h +struct device; +struct gpio_desc; + +/* + * Device flags that can vary from board to board. All of these + * indicate the most atypical case, so that a devflags of 0 is + * a sane default configuration. + */ +#define ISP1760_FLAG_BUS_WIDTH_16 0x0002 /* 16-bit data bus width */ +#define ISP1760_FLAG_OTG_EN0x0004 /* Port 1 supports OTG */ +#define ISP1760_FLAG_ANALOG_OC 0x0008 /* Analog overcurrent */ +#define ISP1760_FLAG_DACK_POL_HIGH 0x0010 /* DACK active high */ +#define ISP1760_FLAG_DREQ_POL_HIGH 0x0020 /* DREQ active high */ +#define ISP1760_FLAG_ISP1761 0x0040 /* Chip is ISP1761 */ +#define ISP1760_FLAG_INTR_POL_HIGH 0x0080 /* Interrupt polarity active high */ +#define ISP1760_FLAG_INTR_EDGE_TRIG0x0100 /* Interrupt edge triggered */ + struct isp1760_device { + struct device *dev; + void __iomem *regs; + unsigned int devflags; +
[PATCH v4 21/26] usb: isp1760: Move PORT1 configuration to core code
Configuring the mode of operation of port 1 doesn't belong to the HCD code, as it's related to the soon to come UDC support. Move the configuration to core code. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/host/isp1760-core.c | 8 drivers/usb/host/isp1760-hcd.c | 9 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c index e840a1d..1cba3e0 100644 --- a/drivers/usb/host/isp1760-core.c +++ b/drivers/usb/host/isp1760-core.c @@ -67,6 +67,14 @@ static void isp1760_init_core(struct isp1760_device *isp) isp1760_write32(isp-regs, HC_HW_MODE_CTRL, hwmode); isp1760_write32(isp-regs, HC_HW_MODE_CTRL, hwmode); + /* +* PORT 1 Control register of the ISP1760 is the OTG control register on +* ISP1761. Since there is no OTG or device controller support in this +* driver, we use port 1 as a normal USB host port on both chips. +*/ + isp1760_write32(isp-regs, HC_PORT1_CTRL, PORT1_POWER | PORT1_INIT2); + usleep_range(1, 11000); + dev_info(isp-dev, bus width: %u, oc: %s\n, isp-devflags ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32, isp-devflags ISP1760_FLAG_ANALOG_OC ? analog : digital); diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 5309d73..568446c 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -503,15 +503,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) reg_write32(hcd-regs, HC_INTERRUPT_ENABLE, INTERRUPT_ENABLE_MASK); - /* -* PORT 1 Control register of the ISP1760 is the OTG control -* register on ISP1761. Since there is no OTG or device controller -* support in this driver, we use port 1 as a normal USB host port on -* both chips. -*/ - reg_write32(hcd-regs, HC_PORT1_CTRL, PORT1_POWER | PORT1_INIT2); - mdelay(10); - priv-hcs_params = reg_read32(hcd-regs, HC_HCSPARAMS); return priv_init(hcd); -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 03/26] usb: isp1760: Retrieve pdev memory resource from hcd at remove time
The platform driver remove function needs to release the memory resource requested at probe time. Instead of retrieving the resource from the platform device, retrieve it from the usb_hcd. This mimics the behaviour of the PCI and OF glues, and will make it easier to share code between all three glue layers. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-if.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index b5bcb99..025edf2 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -373,15 +373,11 @@ out: static int isp1760_plat_remove(struct platform_device *pdev) { - struct resource *mem_res; - resource_size_t mem_size; struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mem_size = resource_size(mem_res); - release_mem_region(mem_res-start, mem_size); + release_mem_region(hcd-rsrc_start, hcd-rsrc_len); usb_put_hcd(hcd); -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 18/26] usb: isp1760: Move core code to isp1760-core.c
Move core device initialization to a central location in order to share it with the device mode implementation. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/host/Makefile | 2 +- drivers/usb/host/isp1760-core.c | 65 + drivers/usb/host/isp1760-core.h | 33 + drivers/usb/host/isp1760-hcd.c | 42 +++--- drivers/usb/host/isp1760-hcd.h | 8 ++--- drivers/usb/host/isp1760-if.c | 2 +- 6 files changed, 114 insertions(+), 38 deletions(-) create mode 100644 drivers/usb/host/isp1760-core.c create mode 100644 drivers/usb/host/isp1760-core.h diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index d6216a4..4dea9b1 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -5,7 +5,7 @@ # tell define_trace.h where to find the xhci trace header CFLAGS_xhci-trace.o := -I$(src) -isp1760-y := isp1760-hcd.o isp1760-if.o +isp1760-y := isp1760-core.o isp1760-hcd.o isp1760-if.o fhci-y := fhci-hcd.o fhci-hub.o fhci-q.o fhci-y += fhci-mem.o fhci-tds.o fhci-sched.o diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c new file mode 100644 index 000..d38efa0 --- /dev/null +++ b/drivers/usb/host/isp1760-core.c @@ -0,0 +1,65 @@ +/* + * Driver for the NXP ISP1760 chip + * + * Copyright 2014 Laurent Pinchart + * Copyright 2007 Sebastian Siewior + * + * Contacts: + * Sebastian Siewior bige...@linutronix.de + * Laurent Pinchart laurent.pinch...@ideasonboard.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#include linux/gpio.h +#include linux/io.h +#include linux/kernel.h +#include linux/module.h +#include linux/slab.h +#include linux/usb.h + +#include isp1760-core.h +#include isp1760-hcd.h + +int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, +struct device *dev, unsigned int devflags) +{ + struct isp1760_device *isp; + int ret; + + if (usb_disabled()) + return -ENODEV; + + /* prevent usb-core allocating DMA pages */ + dev-dma_mask = NULL; + + isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL); + if (!isp) + return -ENOMEM; + + isp-regs = devm_ioremap_resource(dev, mem); + if (IS_ERR(isp-regs)) + return PTR_ERR(isp-regs); + + ret = isp1760_hcd_register(isp-hcd, isp-regs, mem, irq, irqflags, + dev, devflags); + if (ret 0) + return ret; + + dev_set_drvdata(dev, isp); + + return 0; +} + +void isp1760_unregister(struct device *dev) +{ + struct isp1760_device *isp = dev_get_drvdata(dev); + + isp1760_hcd_unregister(isp-hcd); +} + +MODULE_DESCRIPTION(Driver for the ISP1760 USB-controller from NXP); +MODULE_AUTHOR(Sebastian Siewior bige...@linuxtronix.de); +MODULE_LICENSE(GPL v2); diff --git a/drivers/usb/host/isp1760-core.h b/drivers/usb/host/isp1760-core.h new file mode 100644 index 000..0caeb11 --- /dev/null +++ b/drivers/usb/host/isp1760-core.h @@ -0,0 +1,33 @@ +/* + * Driver for the NXP ISP1760 chip + * + * Copyright 2014 Laurent Pinchart + * Copyright 2007 Sebastian Siewior + * + * Contacts: + * Sebastian Siewior bige...@linutronix.de + * Laurent Pinchart laurent.pinch...@ideasonboard.com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ + +#ifndef _ISP1760_CORE_H_ +#define _ISP1760_CORE_H_ + +#include linux/ioport.h + +#include isp1760-hcd.h + +struct isp1760_device { + void __iomem *regs; + + struct isp1760_hcd hcd; +}; + +int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, +struct device *dev, unsigned int devflags); +void isp1760_unregister(struct device *dev); + +#endif diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 50434cc..0cf620b 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2232,30 +2232,20 @@ void isp1760_deinit_kmem_cache(void) kmem_cache_destroy(urb_listitem_cachep); } -int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, -struct device *dev, unsigned int devflags) +int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, +struct resource *mem, int irq, unsigned long irqflags, +struct device *dev, unsigned int devflags) { - struct usb_hcd *hcd = NULL; - struct isp1760_hcd *priv; + struct usb_hcd *hcd; int ret; - if (usb_disabled()) - return -ENODEV; - - priv = devm_kzalloc(dev,
[PATCH v4 06/26] usb: isp1760: Move removal cleanup code to isp1760-hcd.c
The removal cleanup code is duplicated between the different bus glues. Move it to a central location. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- Changes since v1: - Call release_mem_region() after iounmap() --- drivers/usb/host/isp1760-hcd.c | 10 ++ drivers/usb/host/isp1760-hcd.h | 2 ++ drivers/usb/host/isp1760-if.c | 16 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index e4a9424..7498727 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2263,6 +2263,16 @@ err_put: return ERR_PTR(ret); } +void isp1760_unregister(struct device *dev) +{ + struct usb_hcd *hcd = dev_get_drvdata(dev); + + usb_remove_hcd(hcd); + iounmap(hcd-regs); + release_mem_region(hcd-rsrc_start, hcd-rsrc_len); + usb_put_hcd(hcd); +} + MODULE_DESCRIPTION(Driver for the ISP1760 USB-controller from NXP); MODULE_AUTHOR(Sebastian Siewior bige...@linuxtronix.de); MODULE_LICENSE(GPL v2); diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index fda0f2d..ea13a58 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -6,6 +6,8 @@ struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, unsigned long irqflags, struct device *dev, const char *busname, unsigned int devflags); +void isp1760_unregister(struct device *dev); + int init_kmem_once(void); void deinit_kmem_cache(void); diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 3db98da..b96c62f 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -160,14 +160,7 @@ cleanup1: static void isp1761_pci_remove(struct pci_dev *dev) { - struct usb_hcd *hcd; - - hcd = pci_get_drvdata(dev); - - usb_remove_hcd(hcd); - iounmap(hcd-regs); - release_mem_region(hcd-rsrc_start, hcd-rsrc_len); - usb_put_hcd(hcd); + isp1760_unregister(dev-dev); pci_disable_device(dev); } @@ -291,12 +284,7 @@ cleanup: static int isp1760_plat_remove(struct platform_device *pdev) { - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_remove_hcd(hcd); - iounmap(hcd-regs); - release_mem_region(hcd-rsrc_start, hcd-rsrc_len); - usb_put_hcd(hcd); + isp1760_unregister(pdev-dev); return 0; } -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 14/26] usb: isp1760: Refactor PCI initialization code
Move the initialization code out of the PCI probe function to a new function in order to simplify and fix error handling. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/host/isp1760-if.c | 134 ++ 1 file changed, 69 insertions(+), 65 deletions(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index dbb287c..7c03320 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -25,69 +25,34 @@ #endif #ifdef CONFIG_PCI -static int isp1761_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int isp1761_pci_init(struct pci_dev *dev) { + resource_size_t mem_start; + resource_size_t mem_length; + u8 __iomem *iobase; u8 latency, limit; - __u32 reg_data; int retry_count; - unsigned int devflags = 0; - int ret_status = 0; - - resource_size_t pci_mem_phy0; - resource_size_t memlength; + u32 reg_data; - u8 __iomem *chip_addr; - u8 __iomem *iobase; - resource_size_t nxp_pci_io_base; - resource_size_t iolength; - - if (usb_disabled()) - return -ENODEV; - - if (pci_enable_device(dev) 0) - return -ENODEV; - - if (!dev-irq) - return -ENODEV; - - /* Grab the PLX PCI mem maped port start address we need */ - nxp_pci_io_base = pci_resource_start(dev, 0); - iolength = pci_resource_len(dev, 0); - - if (!request_mem_region(nxp_pci_io_base, iolength, ISP1761 IO MEM)) { - printk(KERN_ERR request region #1\n); - return -EBUSY; - } - - iobase = ioremap_nocache(nxp_pci_io_base, iolength); - if (!iobase) { - printk(KERN_ERR ioremap #1\n); - ret_status = -ENOMEM; - goto cleanup1; - } /* Grab the PLX PCI shared memory of the ISP 1761 we need */ - pci_mem_phy0 = pci_resource_start(dev, 3); - memlength = pci_resource_len(dev, 3); - if (memlength 0x) { + mem_start = pci_resource_start(dev, 3); + mem_length = pci_resource_len(dev, 3); + if (mem_length 0x) { printk(KERN_ERR memory length for this resource is wrong\n); - ret_status = -ENOMEM; - goto cleanup2; + return -ENOMEM; } - if (!request_mem_region(pci_mem_phy0, memlength, ISP-PCI)) { + if (!request_mem_region(mem_start, mem_length, ISP-PCI)) { printk(KERN_ERR host controller already in use\n); - ret_status = -EBUSY; - goto cleanup2; + return -EBUSY; } /* map available memory */ - chip_addr = ioremap_nocache(pci_mem_phy0,memlength); - if (!chip_addr) { + iobase = ioremap_nocache(mem_start, mem_length); + if (!iobase) { printk(KERN_ERR Error ioremap failed\n); - release_mem_region(pci_mem_phy0, memlength); - ret_status = -ENOMEM; - goto cleanup2; + release_mem_region(mem_start, mem_length); + return -ENOMEM; } /* bad pci latencies can contribute to overruns */ @@ -108,25 +73,38 @@ static int isp1761_pci_probe(struct pci_dev *dev, /*by default host is in 16bit mode, so * io operations at this stage must be 16 bit * */ - writel(0xface, chip_addr + HC_SCRATCH_REG); + writel(0xface, iobase + HC_SCRATCH_REG); udelay(100); - reg_data = readl(chip_addr + HC_SCRATCH_REG) 0x; + reg_data = readl(iobase + HC_SCRATCH_REG) 0x; retry_count--; } - iounmap(chip_addr); - release_mem_region(pci_mem_phy0, memlength); + iounmap(iobase); + release_mem_region(mem_start, mem_length); /* Host Controller presence is detected by writing to scratch register * and reading back and checking the contents are same or not */ if (reg_data != 0xFACE) { dev_err(dev-dev, scratch register mismatch %x\n, reg_data); - ret_status = -ENOMEM; - goto cleanup2; + return -ENOMEM; } - pci_set_master(dev); + /* Grab the PLX PCI mem maped port start address we need */ + mem_start = pci_resource_start(dev, 0); + mem_length = pci_resource_len(dev, 0); + + if (!request_mem_region(mem_start, mem_length, ISP1761 IO MEM)) { + printk(KERN_ERR request region #1\n); + return -EBUSY; + } + + iobase = ioremap_nocache(mem_start, mem_length); + if (!iobase) { + printk(KERN_ERR ioremap #1\n); + release_mem_region(mem_start, mem_length); + return -ENOMEM; + }
[PATCH v4 26/26] usb: isp1760: Fix USB disabled check
The isp1760 driver registration function returns an error if USB is disabled. This made sense when the driver only supported host controllers, but now that it supports peripheral controllers host support isn't mandatory anymore. Fix this by returning an error only when both the HCD and UDC functions are disabled, either through the kernel configuration or at runtime. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com --- drivers/usb/isp1760/isp1760-core.c | 24 +++- drivers/usb/isp1760/isp1760-hcd.c | 3 +++ drivers/usb/isp1760/isp1760-udc.c | 3 +++ 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/usb/isp1760/isp1760-core.c b/drivers/usb/isp1760/isp1760-core.c index 727e90a..b982755 100644 --- a/drivers/usb/isp1760/isp1760-core.c +++ b/drivers/usb/isp1760/isp1760-core.c @@ -112,9 +112,15 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, struct device *dev, unsigned int devflags) { struct isp1760_device *isp; + bool udc_disabled = !(devflags ISP1760_FLAG_ISP1761); int ret; - if (usb_disabled()) + /* +* If neither the HCD not the UDC is enabled return an error, as no +* device would be registered. +*/ + if ((!IS_ENABLED(CONFIG_USB_ISP1760_HCD) || usb_disabled()) + (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled)) return -ENODEV; /* prevent usb-core allocating DMA pages */ @@ -137,12 +143,14 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, isp1760_init_core(isp); - ret = isp1760_hcd_register(isp-hcd, isp-regs, mem, irq, - irqflags | IRQF_SHARED, dev); - if (ret 0) - return ret; + if (IS_ENABLED(CONFIG_USB_ISP1760_HCD) !usb_disabled()) { + ret = isp1760_hcd_register(isp-hcd, isp-regs, mem, irq, + irqflags | IRQF_SHARED, dev); + if (ret 0) + return ret; + } - if (devflags ISP1760_FLAG_ISP1761) { + if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) !udc_disabled) { ret = isp1760_udc_register(isp, irq, irqflags | IRQF_SHARED | IRQF_DISABLED); if (ret 0) { @@ -160,9 +168,7 @@ void isp1760_unregister(struct device *dev) { struct isp1760_device *isp = dev_get_drvdata(dev); - if (isp-devflags ISP1760_FLAG_ISP1761) - isp1760_udc_unregister(isp); - + isp1760_udc_unregister(isp); isp1760_hcd_unregister(isp-hcd); } diff --git a/drivers/usb/isp1760/isp1760-hcd.c b/drivers/usb/isp1760/isp1760-hcd.c index 568446c..996b2c1 100644 --- a/drivers/usb/isp1760/isp1760-hcd.c +++ b/drivers/usb/isp1760/isp1760-hcd.c @@ -2226,6 +2226,9 @@ error: void isp1760_hcd_unregister(struct isp1760_hcd *priv) { + if (!priv-hcd) + return; + usb_remove_hcd(priv-hcd); usb_put_hcd(priv-hcd); } diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c index 6bfda30..9612d79 100644 --- a/drivers/usb/isp1760/isp1760-udc.c +++ b/drivers/usb/isp1760/isp1760-udc.c @@ -1488,6 +1488,9 @@ void isp1760_udc_unregister(struct isp1760_device *isp) { struct isp1760_udc *udc = isp-udc; + if (!udc-isp) + return; + usb_del_gadget_udc(udc-gadget); free_irq(udc-irq, udc); -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 04/26] usb: isp1760: Unmap I/O registers at platform device removal
The I/O registers are mapped in the HCD code but must be unmapped by glue code. The OF and PCI glue code unmap them correctly but the platform glue code is missing an iounmap() call. Fix it. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Signed-off-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-if.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 025edf2..730caa1 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -376,9 +376,8 @@ static int isp1760_plat_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - + iounmap(hcd-regs); release_mem_region(hcd-rsrc_start, hcd-rsrc_len); - usb_put_hcd(hcd); return 0; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 12/26] usb: isp1760: Pass resource pointer to isp1760_register
The function takes quite a few arguments, passing the resource pointer instead of the start address and length simplifies it a bit. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 11 +-- drivers/usb/host/isp1760-hcd.h | 5 ++--- drivers/usb/host/isp1760-if.c | 8 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 9ba3023..e99dafa 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2211,9 +2211,8 @@ void isp1760_deinit_kmem_cache(void) kmem_cache_destroy(urb_listitem_cachep); } -int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, -unsigned long irqflags, struct device *dev, -unsigned int devflags) +int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, +struct device *dev, unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; @@ -2239,15 +2238,15 @@ int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, } init_memory(priv); - hcd-regs = ioremap(res_start, res_len); + hcd-regs = ioremap(mem-start, resource_size(mem)); if (!hcd-regs) { ret = -EIO; goto err_put; } hcd-irq = irq; - hcd-rsrc_start = res_start; - hcd-rsrc_len = res_len; + hcd-rsrc_start = mem-start; + hcd-rsrc_len = resource_size(mem); ret = usb_add_hcd(hcd, irq, irqflags); if (ret) diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index cc65602..7fc510f 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -2,9 +2,8 @@ #define _ISP1760_HCD_H_ /* exports for if */ -int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, -unsigned long irqflags, struct device *dev, -unsigned int devflags); +int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, +struct device *dev, unsigned int devflags); void isp1760_unregister(struct device *dev); int isp1760_init_kmem_once(void); diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index ce572cc..3a9b4f6 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -133,8 +133,8 @@ static int isp1761_pci_probe(struct pci_dev *dev, writel(reg_data, iobase + PLX_INT_CSR_REG); dev-dev.dma_mask = NULL; - ret_status = isp1760_register(pci_mem_phy0, memlength, dev-irq, - IRQF_SHARED, dev-dev, devflags); + ret_status = isp1760_register(dev-resource[3], dev-irq, IRQF_SHARED, + dev-dev, devflags); if (ret_status 0) goto cleanup3; @@ -257,8 +257,8 @@ static int isp1760_plat_probe(struct platform_device *pdev) devflags |= ISP1760_FLAG_DREQ_POL_HIGH; } - ret = isp1760_register(mem_res-start, mem_size, irq_res-start, - irqflags, pdev-dev, devflags); + ret = isp1760_register(mem_res, irq_res-start, irqflags, pdev-dev, + devflags); if (ret 0) goto cleanup; -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4 10/26] usb: isp1760: Prefix init_kmem_once and deinit_kmem_cache with isp1760_
The two functions are specific to the driver but have very generic names, subject to collisions. Rename them. Signed-off-by: Laurent Pinchart laurent.pinch...@ideasonboard.com Reviewed-by: Felipe Balbi ba...@ti.com --- drivers/usb/host/isp1760-hcd.c | 4 ++-- drivers/usb/host/isp1760-hcd.h | 4 ++-- drivers/usb/host/isp1760-if.c | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index aa894a1..0ae1719 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2177,7 +2177,7 @@ static const struct hc_driver isp1760_hc_driver = { .clear_tt_buffer_complete = isp1760_clear_tt_buffer_complete, }; -int __init init_kmem_once(void) +int __init isp1760_init_kmem_once(void) { urb_listitem_cachep = kmem_cache_create(isp1760_urb_listitem, sizeof(struct urb_listitem), 0, SLAB_TEMPORARY | @@ -2204,7 +2204,7 @@ int __init init_kmem_once(void) return 0; } -void deinit_kmem_cache(void) +void isp1760_deinit_kmem_cache(void) { kmem_cache_destroy(qtd_cachep); kmem_cache_destroy(qh_cachep); diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index 372d2e5..f97c9d6 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -7,8 +7,8 @@ int isp1760_register(phys_addr_t res_start, resource_size_t res_len, int irq, const char *busname, unsigned int devflags); void isp1760_unregister(struct device *dev); -int init_kmem_once(void); -void deinit_kmem_cache(void); +int isp1760_init_kmem_once(void); +void isp1760_deinit_kmem_cache(void); /* EHCI capability registers */ #define HC_CAPLENGTH 0x00 diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 03243b0..e268b20 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -301,7 +301,7 @@ static int __init isp1760_init(void) { int ret, any_ret = -ENODEV; - init_kmem_once(); + isp1760_init_kmem_once(); ret = platform_driver_register(isp1760_plat_driver); if (!ret) @@ -313,7 +313,7 @@ static int __init isp1760_init(void) #endif if (any_ret) - deinit_kmem_cache(); + isp1760_deinit_kmem_cache(); return any_ret; } module_init(isp1760_init); @@ -324,6 +324,6 @@ static void __exit isp1760_exit(void) #ifdef CONFIG_PCI pci_unregister_driver(isp1761_pci_driver); #endif - deinit_kmem_cache(); + isp1760_deinit_kmem_cache(); } module_exit(isp1760_exit); -- 2.0.5 -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/5] extcon: gpio-usb: Introduce gpio usb extcon driver
Hi Roger, On 01/20/2015 02:52 AM, Roger Quadros wrote: This driver observes the USB ID pin connected over a GPIO and updates the USB cable extcon states accordingly. The existing GPIO extcon driver is not suitable for this purpose as it needs to be taught to understand USB cable states and it can't handle more than one cable per instance. For the USB case we need to handle 2 cable states. 1) USB (attach/detach) 2) USB-Host (attach/detach) This driver can be easily updated in the future to handle VBUS events in case it happens to be available on GPIO for any platform. Signed-off-by: Roger Quadros rog...@ti.com --- .../devicetree/bindings/extcon/extcon-usb.txt | 20 ++ drivers/extcon/Kconfig | 7 + drivers/extcon/Makefile| 1 + drivers/extcon/extcon-gpio-usb.c | 225 + 4 files changed, 253 insertions(+) create mode 100644 Documentation/devicetree/bindings/extcon/extcon-usb.txt create mode 100644 drivers/extcon/extcon-gpio-usb.c diff --git a/Documentation/devicetree/bindings/extcon/extcon-usb.txt b/Documentation/devicetree/bindings/extcon/extcon-usb.txt new file mode 100644 index 000..171c5a4 --- /dev/null +++ b/Documentation/devicetree/bindings/extcon/extcon-usb.txt Need to rename from extcon-usb.txt to extcon-gpio-usb.txt. @@ -0,0 +1,20 @@ +USB Extcon device + +This is a virtual device used to generate USB cable states from the USB ID pin +connected to a GPIO pin. + +Required properties: +- compatible: Should be linux,extcon-usb I think you better use linux,extcon-gpio-usb because the point of this driver use the gpio for usb cable. +- id-gpio: gpio for USB ID pin. See gpio binding. + +Example: + extcon_usb1 { + compatible = linux,extcon-usb; ditto. + id-gpio = gpio6 1 GPIO_ACTIVE_HIGH; + } + + usb@1 { + ... + extcon = extcon_usb1; + ... + }; diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 6a1f7de..8106a83 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -35,6 +35,13 @@ config EXTCON_GPIO Say Y here to enable GPIO based extcon support. Note that GPIO extcon supports single state per extcon instance. +config EXTCON_GPIO_USB + tristate USB GPIO extcon support + depends on GPIOLIB + help + Say Y here to enable GPIO based USB cable detection extcon support. + Used typically if GPIO is used for USB ID pin detection. + config EXTCON_MAX14577 tristate MAX14577/77836 EXTCON Support depends on MFD_MAX14577 diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 0370b42..bae594b 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -12,3 +12,4 @@ obj-$(CONFIG_EXTCON_MAX8997)+= extcon-max8997.o obj-$(CONFIG_EXTCON_PALMAS) += extcon-palmas.o obj-$(CONFIG_EXTCON_RT8973A) += extcon-rt8973a.o obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o +obj-$(CONFIG_EXTCON_GPIO_USB)+= extcon-gpio-usb.o Need to re-order it alphabetically. diff --git a/drivers/extcon/extcon-gpio-usb.c b/drivers/extcon/extcon-gpio-usb.c new file mode 100644 index 000..aeb2298 --- /dev/null +++ b/drivers/extcon/extcon-gpio-usb.c @@ -0,0 +1,225 @@ +/** + * drivers/extcon/extcon_gpio_usb.c - USB GPIO extcon driver + * + * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com + * Remove un-necessary blank line. + * Author: Roger Quadros rog...@ti.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include linux/extcon.h +#include linux/extcon/extcon-gpio.h Is it necessary? I think it is your mistake? +#include linux/gpio.h Don't need it because 'of_gpio.h' includes already 'gpio.h'. +#include linux/init.h +#include linux/interrupt.h +#include linux/irq.h +#include linux/kernel.h +#include linux/module.h +#include linux/of_gpio.h +#include linux/platform_device.h +#include linux/slab.h +#include linux/workqueue.h + +#define USB_GPIO_DEBOUNCE_MS 20 /* ms */ + +struct usb_extcon_info { + struct device *dev; + struct extcon_dev *edev; + + struct gpio_desc *id_gpiod; + int id_irq; + + unsigned long debounce_jiffies; + struct delayed_work wq_detcable; +}; + +/* List of detectable cables */ +enum { + EXTCON_CABLE_USB = 0, + EXTCON_CABLE_USB_HOST, + + EXTCON_CABLE_END, +}; + +static const char *usb_extcon_cable[] = { +
Re: USB autosuspend causing trouble with bluetooth
On Tue, 2015-01-20 at 23:25 +0400, Kirill Elagin wrote: Hm, I'm pretty sure I never touched anything with `port` in its name, all the ports are set to `auto` (that's what laptop-mode-tools does). Here we go. Right now I think I see three possibly unrelated issues: Issue #1. BT trackpad not working properly when connected to the builtin bluetooth adapter. -- The adapter is attached to a USB1.1 hub: # lsusb -t ... /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M |__ Port 2: Dev 2, If 0, Class=Wireless, Driver=btusb, 12M |__ Port 2: Dev 2, If 1, Class=Wireless, Driver=btusb, 12M |__ Port 2: Dev 2, If 2, Class=Vendor Specific Class, Driver=, 12M |__ Port 2: Dev 2, If 3, Class=Application Specific Interface, Driver=, 12M ... # cat usb3/power/control auto # cat usb3/3-*/usb3-port*/power/control auto auto Try setting this to on. # cat usb3/3-2/power/control on Here auto should work. Please try. [..] Issue #2. No hotplug with USB1.1: -- To see this I pick one physical port. When I plug a USB1.1 device it appears on bus 4 port 2; a USB2.0 device appears on bus 1 port 4. # cat usb4/power/control auto # cat usb4/4-*/usb4-port*/power/control auto auto Please set this to on # cat usb1/power/control auto # cat usb1/1-*/usb1-port*/power/control Please set this to on [..] Issue #3. No hot-plug-out for USB1.1. I think that the first two issues are fixed by keeping all the USB1.1 hubs and the builtin BT always `on`, but I just wanted to know whether those are hardware or software bugs. I suspect this is caused by outdated laptop-mode-tools. Basically setting the port controls (as opposed to hub and device controls) to auto tells the kernel that it may disable hotplugging to save energy. Hotunplug for devices that need remote wakeup will still work. Likewise if you disable autosuspend of the attached devices. Regards Oliver -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 0/3] ARM: mvebu: Enable XHCI on the Armada 385 AP
Hi Andrew, On Mon, Jan 19, 2015 at 10:35:07PM +0100, Andrew Lunn wrote: On Mon, Jan 19, 2015 at 02:01:11PM +0100, Maxime Ripard wrote: Hi all, This serie enables the Armada 385 AP XHCI controller. Since the controller uses a GPIO-controlled VBUS, we used the phy-generic driver, and made the needed additions to the xhci-plat driver to retrieve a USB phy. Unfortunately, some glitches were also found along the way, mostly because of the probe deferring that was introduced by this phy retrieval. Since the introduction of the Armada 38x support in 3.16, the driver was attempting to write into registers while the clock wasn't enabled yet. This was working because the bootloader left it enabled, but in the case of a deferred probing, the clock would have been disabled by the error path of our driver, and this would fail. This should go in 3.19, and any stable kernel for 3.16+. The two patches remaining are regular patches, and are aimed at 3.20. The last patch depend on my previous serie to introduce support for the the A385 AP board. Hi Maxime I assume you want me to take 3/3? Any other route is not simple, since this file only exists in mvebu/dt and maybe a staging branch of arm-soc. What route do you think the other patches will take? There should be no merge dependency, but merging the third patch alone will probably result on a boot breakage. I don't think it really matters though, since this is a new board, so I guess it can go through the USB-PHY tree. Maxime -- Maxime Ripard, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com signature.asc Description: Digital signature
Re: [PATCH v2 0/3] ARM: mvebu: Enable XHCI on the Armada 385 AP
On Tue, Jan 20, 2015 at 09:30:28PM +0100, Maxime Ripard wrote: Hi Andrew, On Mon, Jan 19, 2015 at 10:35:07PM +0100, Andrew Lunn wrote: On Mon, Jan 19, 2015 at 02:01:11PM +0100, Maxime Ripard wrote: Hi all, This serie enables the Armada 385 AP XHCI controller. Since the controller uses a GPIO-controlled VBUS, we used the phy-generic driver, and made the needed additions to the xhci-plat driver to retrieve a USB phy. Unfortunately, some glitches were also found along the way, mostly because of the probe deferring that was introduced by this phy retrieval. Since the introduction of the Armada 38x support in 3.16, the driver was attempting to write into registers while the clock wasn't enabled yet. This was working because the bootloader left it enabled, but in the case of a deferred probing, the clock would have been disabled by the error path of our driver, and this would fail. This should go in 3.19, and any stable kernel for 3.16+. The two patches remaining are regular patches, and are aimed at 3.20. The last patch depend on my previous serie to introduce support for the the A385 AP board. Hi Maxime I assume you want me to take 3/3? Any other route is not simple, since this file only exists in mvebu/dt and maybe a staging branch of arm-soc. What route do you think the other patches will take? There should be no merge dependency, but merging the third patch alone will probably result on a boot breakage. I don't think it really matters though, since this is a new board, so I guess it can go through the USB-PHY tree. Hi Maxime Humm, maybe i'm wrong, but i think arch/arm/boot/dts/armada-385-db-ap.dts only exists in the mvebu tree? At least, i don't see it here: https://git.kernel.org/cgit/linux/kernel/git/balbi/usb.git/tree/arch/arm/boot/dts?h=next Andrew -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: USB autosuspend causing trouble with bluetooth
On Tue, Jan 20, 2015 at 8:41 PM, Oliver Neukum oneu...@suse.de wrote: On Tue, 2015-01-20 at 18:58 +0400, Kirill Elagin wrote: On Tue, Jan 20, 2015 at 5:06 PM, Oliver Neukum oneu...@suse.de wrote: On Tue, 2015-01-20 at 16:18 +0400, Kirill Elagin wrote: I use a Logitech wireless keyboard (with a Unifying receiver) and it keeps working fine even with `auto`. That is, everything is OK if the receiver is plugged before `power/control` is switched to `auto`. Wait. There is no power/control file for the receiver before you plug it in. We are having a very big misunderstanding here. Sorry for not being clear. I was referring to `power/control` of the USB-device itself except for the cases when I was talking about hot-plugging issues — in those cases I was referring to the `power/control` of the root hub. Please check whether you are not accidentally touching the ports linux-0dmf:/sys/bus/usb/devices/usb1/1-0:1.0/usb1-port1 At paths like this you find control files for ports, not the root hub as a device. In this particular case I was talking about the `power/control` of the root hub. OK, so autosuspend does work if you enable it for the device but not the hub? Hm, I'm pretty sure I never touched anything with `port` in its name, all the ports are set to `auto` (that's what laptop-mode-tools does). Right now I think I see three possibly unrelated issues: Issue #1. BT trackpad not working properly when connected to the builtin bluetooth adapter. -- The adapter is attached to a USB1.1 hub: # lsusb -t ... /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=uhci_hcd/2p, 12M |__ Port 2: Dev 2, If 0, Class=Wireless, Driver=btusb, 12M |__ Port 2: Dev 2, If 1, Class=Wireless, Driver=btusb, 12M |__ Port 2: Dev 2, If 2, Class=Vendor Specific Class, Driver=, 12M |__ Port 2: Dev 2, If 3, Class=Application Specific Interface, Driver=, 12M ... # cat usb3/power/control auto # cat usb3/3-*/usb3-port*/power/control auto auto # cat usb3/3-2/power/control on The trackpad is working fine right now. Whenever I do # echo auto usb3/3-2/power/control and leave it alone for 5 seconds `btmon` stops showing any activity. As soon as I do # echo on usb3/3-2/power/control the trackpad is alive again. As I mentioned this doesn’t happen when the trackpad is connected to a USB BT dongle (also USB1.1, but a different bus number). Issue #2. No hotplug with USB1.1: -- To see this I pick one physical port. When I plug a USB1.1 device it appears on bus 4 port 2; a USB2.0 device appears on bus 1 port 4. # cat usb4/power/control auto # cat usb4/4-*/usb4-port*/power/control auto auto # cat usb1/power/control auto # cat usb1/1-*/usb1-port*/power/control auto auto auto auto # journalctl -b -k -f -n 0 [1] 8390 -- Logs begin at Fri 2015-01-02 03:13:31 MSK. -- (plug USB2.0 flash drive in) Jan 20 21:55:09 kirNote kernel: usb 4-2: USB disconnect, device number 6 Jan 20 22:00:19 kirNote kernel: usb 1-4: new high-speed USB device number 15 using ehci-pci Jan 20 22:00:19 kirNote kernel: usb 1-4: New USB device found, idVendor=0951, idProduct=1623 Jan 20 22:00:19 kirNote kernel: usb 1-4: New USB device strings: Mfr=1, Product=2, SerialNumber=3 ... (plug flash drive out) Jan 20 22:00:35 kirNote kernel: usb 1-4: USB disconnect, device number 15 (plug USB1.1 BT dongle) (nothing happens) # echo on usb4/power/control Jan 20 22:01:09 kirNote kernel: usb 4-2: new full-speed USB device number 7 using uhci_hcd Jan 20 22:01:09 kirNote kernel: usb 4-2: New USB device found, idVendor=0a12, idProduct=0001 Jan 20 22:01:09 kirNote kernel: usb 4-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0 (plug dongle out) Jan 20 22:01:26 kirNote kernel: usb 4-2: USB disconnect, device number 7 Issue #3. No hot-plug-out for USB1.1. This issue is somewhat harder to describe as it depends on the combination of power/control of the hub and device. And there are three possible outcomes: device disconnect properly detected (both `on`), not detected at all (both `auto`), error about a port being disabled by hub (EMI?) in some other cases. I'm not really sure about this one and I'll get back about it later after some more experiments. I think that the first two issues are fixed by keeping all the USB1.1 hubs and the builtin BT always `on`, but I just wanted to know whether those are hardware or software bugs. Thanks for helping me investigate this! -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 00/20] Add UDC support to the isp1760 driver
Hi Felipe, On Friday 09 January 2015 11:34:25 Felipe Balbi wrote: On Fri, Jan 09, 2015 at 11:30:31AM -0600, Felipe Balbi wrote: This patch set adds UDC support to the isp1760 driver, to be used with the ISP1761 dual-role USB controller. The first 17 patches rework the isp1760 driver to prepare it for UDC support. In particular they removes the direct HCD dependencies from the glue code (01/20 to 04/20), creates core initialization code shared by the HCD and UDC (15/20) and move common initialization code to the core (16/20 to 17/20). Patch 18/20 adds UDC support, and patches 19/20 and 20/20 move the driver to drivers/usb/isp1760/ and make HCD support optional. The ISP1761 has three USB ports, with port 1 configurable in host or peripheral mode with OTG support, and ports 2 and 3 supporting host mode only. OTG support is not implemented yet, port 1 can thus be configured in host or peripheral mode only. The UDC driver has been successfully tested with the g_zero and g_mass_storage gadgets. Global changes compared to v2: - Rebase on top of Felipe's testing/next branch - Drop patches that have been merged already - Add patch 19/20 and 20/20 Global changes compared to v1: - Replace GPIO request move by patch 01/22 - Split PORT1 configuration to separate patch - Drop the shutdown implementation patch - Add patches 02/22, 04/22, 05/22, 13/22, 14/22 See individual patches for patch-specific changes. with this set I started getting: In file included from drivers/usb/isp1760/isp1760-core.h:22:0, from drivers/usb/isp1760/isp1760-core.c:24: drivers/usb/isp1760/isp1760-udc.h:65:5: warning: CONFIG_USB_ISP1761_UDC is not defined [-Wundef] drivers/usb/isp1760/isp1760-udc.h:90:5: warning: CONFIG_USB_ISP1761_UDC is not defined [-Wundef] I have now dropped this series from my testing/next btw, I've dropped the entire series, even the ones which were applied before. Please rebase and make sure each patch builds fine without warnings or build errors. Sorry about that. I forgot to update drivers/usb/host/Makefile, and the build breakage went unnoticed as the isp1760 object files were still available in that directory. I'm fixing the issue and I'll resubmit the patches shortly. -- Regards, Laurent Pinchart -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] usb: hid: Do not bind to Microchip Pick16F1454
On Tue, 20 Jan 2015, Kristian Evensen wrote: The Microchip Pick16F1454 is exported as a HID device and is used by for example the Yepkit YKUSH three-port switchable USB hub. However, it is not an actual HID-device. On the Yepkit, it is used to power up/down the ports on the hub. The HID driver should ignore this device. Signed-off-by: Kristian Evensen kristian.even...@gmail.com Applied, thanks. -- Jiri Kosina SUSE Labs -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html