[PATCH v2 1/7] extcon: usb-gpio: add device binding for platform device
This is needed to handle the GPIO connected USB ID pin found on Intel Baytrail devices. Signed-off-by: Lu Baolu Reviewed-by: Felipe Balbi Acked-by: Chanwoo Choi --- drivers/extcon/extcon-usb-gpio.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index 2b2fecf..af9c8b0 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c @@ -206,6 +206,12 @@ static const struct of_device_id usb_extcon_dt_match[] = { }; MODULE_DEVICE_TABLE(of, usb_extcon_dt_match); +static const struct platform_device_id usb_extcon_platform_ids[] = { + { .name = "extcon-usb-gpio", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(platform, usb_extcon_platform_ids); + static struct platform_driver usb_extcon_driver = { .probe = usb_extcon_probe, .remove = usb_extcon_remove, @@ -214,6 +220,7 @@ static struct platform_driver usb_extcon_driver = { .pm = &usb_extcon_pm_ops, .of_match_table = usb_extcon_dt_match, }, + .id_table = usb_extcon_platform_ids, }; module_platform_driver(usb_extcon_driver); -- 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 v2 4/7] usb: mux: add driver for Intel gpio controlled port mux
In some Intel platforms, a single usb port is shared between USB host and device controller. The shared port is under control of GPIO pins. This patch adds the support for USB GPIO controlled port mux. Signed-off-by: David Cohen Signed-off-by: Lu Baolu Reviewed-by: Heikki Krogerus Reviewed-by: Felipe Balbi Signed-off-by: Fengguang Wu --- MAINTAINERS | 1 + drivers/usb/mux/Kconfig | 9 +++ drivers/usb/mux/Makefile | 1 + drivers/usb/mux/intel-mux-gpio.c | 125 +++ 4 files changed, 136 insertions(+) create mode 100644 drivers/usb/mux/intel-mux-gpio.c diff --git a/MAINTAINERS b/MAINTAINERS index a93d26a..ab876eb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11406,6 +11406,7 @@ L: linux-usb@vger.kernel.org S: Supported F: drivers/usb/mux/intel-mux.c F: include/linux/usb/intel-mux.h +F: drivers/usb/mux/intel-mux-gpio.c USB PRINTER DRIVER (usblp) M: Pete Zaitcev diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig index 8fedc4f..060bf5c 100644 --- a/drivers/usb/mux/Kconfig +++ b/drivers/usb/mux/Kconfig @@ -6,4 +6,13 @@ config INTEL_USB_MUX select EXTCON def_bool n +config INTEL_MUX_GPIO + tristate "Intel dual role port mux controlled by GPIOs" + depends on GPIOLIB + depends on X86 && ACPI + select INTEL_USB_MUX + help + Say Y here to enable support for Intel dual role port mux + controlled by GPIOs. + endmenu diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile index 84f0ae8..66f765c 100644 --- a/drivers/usb/mux/Makefile +++ b/drivers/usb/mux/Makefile @@ -2,3 +2,4 @@ # Makefile for USB port mux drivers # obj-$(CONFIG_INTEL_USB_MUX)+= intel-mux.o +obj-$(CONFIG_INTEL_MUX_GPIO) += intel-mux-gpio.o diff --git a/drivers/usb/mux/intel-mux-gpio.c b/drivers/usb/mux/intel-mux-gpio.c new file mode 100644 index 000..adcb496 --- /dev/null +++ b/drivers/usb/mux/intel-mux-gpio.c @@ -0,0 +1,125 @@ +/* + * USB Dual Role Port Mux driver controlled by gpios + * + * Copyright (c) 2016, Intel Corporation. + * Author: David Cohen + * Author: Lu Baolu + * + * 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 +#include +#include +#include + +struct vuport { + struct intel_mux_dev umdev; + struct gpio_desc *gpio_vbus_en; + struct gpio_desc *gpio_usb_mux; +}; + +/* + * id == 0, HOST connected, USB port should be set to peripheral + * id == 1, HOST disconnected, USB port should be set to host + * + * Peripheral: set USB mux to peripheral and disable VBUS + * Host: set USB mux to host and enable VBUS + */ +static inline int vuport_set_port(struct intel_mux_dev *umdev, int id) +{ + struct vuport *vup = container_of(umdev, struct vuport, umdev); + + dev_dbg(umdev->dev, "USB PORT ID: %s\n", id ? "HOST" : "PERIPHERAL"); + + gpiod_set_value_cansleep(vup->gpio_usb_mux, !id); + gpiod_set_value_cansleep(vup->gpio_vbus_en, id); + + return 0; +} + +static int vuport_cable_set(struct intel_mux_dev *umdev) +{ + return vuport_set_port(umdev, 1); +} + +static int vuport_cable_unset(struct intel_mux_dev *umdev) +{ + return vuport_set_port(umdev, 0); +} + +static int vuport_probe(struct platform_device *pdev) +{ + struct intel_mux_dev *umdev; + struct device *dev = &pdev->dev; + struct vuport *vup; + + vup = devm_kzalloc(dev, sizeof(*vup), GFP_KERNEL); + if (!vup) + return -ENOMEM; + + /* retrieve vbus and mux gpios */ + vup->gpio_vbus_en = devm_gpiod_get_optional(dev, + "vbus_en", GPIOD_ASIS); + if (IS_ERR(vup->gpio_vbus_en)) + return PTR_ERR(vup->gpio_vbus_en); + + vup->gpio_usb_mux = devm_gpiod_get_optional(dev, + "usb_mux", GPIOD_ASIS); + if (IS_ERR(vup->gpio_usb_mux)) + return PTR_ERR(vup->gpio_usb_mux); + + /* populate the mux generic structure */ + umdev = &vup->umdev; + umdev->dev = dev; + umdev->cable_name = "USB-HOST"; + umdev->cable_set_cb = vuport_cable_set; + umdev->cable_unset_cb = vuport_cable_unset; + + return intel_usb_mux_register(umdev); +} + +static int vuport_remove(struct platform_device *pdev) +{ + return intel_usb_mux_unregister(&pdev->dev); +} + +#ifdef CONFIG_PM_SLEEP +/* + * In case a micro A cable was plugged in while device was sleeping, + * we missed the interrupt. We need to poll usb id gpio when waking the + * driver to detect the missed event. + * We use 'complete' callback to give time to all extcon listeners to
[PATCH v2 7/7] mfd: intel_vuport: Add Intel virtual USB port MFD Driver
Some Intel platforms have an USB port mux controlled by GPIOs. There's a single ACPI platform device that provides both USB ID extcon device and a USB port mux device. This MFD driver will split the 2 devices for their respective drivers. Signed-off-by: Lu Baolu Suggested-by: David Cohen Reviewed-by: Felipe Balbi Signed-off-by: Fengguang Wu --- MAINTAINERS| 1 + drivers/mfd/Kconfig| 8 + drivers/mfd/Makefile | 1 + drivers/mfd/intel-vuport.c | 78 ++ 4 files changed, 88 insertions(+) create mode 100644 drivers/mfd/intel-vuport.c diff --git a/MAINTAINERS b/MAINTAINERS index 399cefe..1671a4d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11408,6 +11408,7 @@ F: drivers/usb/mux/intel-mux.c F: include/linux/usb/intel-mux.h F: drivers/usb/mux/intel-mux-gpio.c F: drivers/usb/mux/intel-mux-drcfg.c +F: drivers/mfd/intel-vuport.c USB PRINTER DRIVER (usblp) M: Pete Zaitcev diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 9ca66de..8dd1bf3 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -1534,5 +1534,13 @@ config MFD_VEXPRESS_SYSREG System Registers are the platform configuration block on the ARM Ltd. Versatile Express board. +config MFD_INTEL_VUPORT + tristate "Intel virtual USB port controller" + select MFD_CORE + depends on X86 && ACPI + help + Say Y here to enable support for Intel dual role port mux + controlled by 3 GPIOs. + endmenu endif diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 0f230a6..0ccd107 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -198,3 +198,4 @@ intel-soc-pmic-objs := intel_soc_pmic_core.o intel_soc_pmic_crc.o intel-soc-pmic-$(CONFIG_INTEL_PMC_IPC) += intel_soc_pmic_bxtwc.o obj-$(CONFIG_INTEL_SOC_PMIC) += intel-soc-pmic.o obj-$(CONFIG_MFD_MT6397) += mt6397-core.o +obj-$(CONFIG_MFD_INTEL_VUPORT) += intel-vuport.o diff --git a/drivers/mfd/intel-vuport.c b/drivers/mfd/intel-vuport.c new file mode 100644 index 000..1371099 --- /dev/null +++ b/drivers/mfd/intel-vuport.c @@ -0,0 +1,78 @@ +/* + * MFD driver for Intel virtual USB port + * + * Copyright(c) 2016 Intel Corporation. + * Author: Lu Baolu + * + * 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 +#include +#include +#include + +/* ACPI GPIO Mappings */ +static const struct acpi_gpio_params id_gpio = { 0, 0, false }; +static const struct acpi_gpio_params vbus_gpio = { 1, 0, false }; +static const struct acpi_gpio_params mux_gpio = { 2, 0, false }; +static const struct acpi_gpio_mapping acpi_usb_gpios[] = { + { "id-gpios", &id_gpio, 1 }, + { "vbus_en-gpios", &vbus_gpio, 1 }, + { "usb_mux-gpios", &mux_gpio, 1 }, + { }, +}; + +static const struct mfd_cell intel_vuport_mfd_cells[] = { + { + .name = "extcon-usb-gpio", + }, + { + .name = "intel-mux-gpio", + }, +}; + +static int vuport_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret; + + ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_usb_gpios); + if (ret) + return ret; + + return mfd_add_devices(&pdev->dev, 0, intel_vuport_mfd_cells, + ARRAY_SIZE(intel_vuport_mfd_cells), NULL, 0, + NULL); +} + +static int vuport_remove(struct platform_device *pdev) +{ + mfd_remove_devices(&pdev->dev); + acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev)); + + return 0; +} + +static struct acpi_device_id vuport_acpi_match[] = { + { "INT3496" }, + { } +}; +MODULE_DEVICE_TABLE(acpi, vuport_acpi_match); + +static struct platform_driver vuport_driver = { + .driver = { + .name = "intel-vuport", + .acpi_match_table = ACPI_PTR(vuport_acpi_match), + }, + .probe = vuport_probe, + .remove = vuport_remove, +}; + +module_platform_driver(vuport_driver); + +MODULE_AUTHOR("Lu Baolu "); +MODULE_DESCRIPTION("Intel virtual USB port"); +MODULE_LICENSE("GPL v2"); -- 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 v2 5/7] usb: mux: add driver for Intel drcfg controlled port mux
Several Intel PCHs and SOCs have an internal mux that is used to share one USB port between device controller and host controller. The mux is handled through the Dual Role Configuration Register. Signed-off-by: Heikki Krogerus Signed-off-by: Lu Baolu Signed-off-by: Wu Hao Reviewed-by: Felipe Balbi --- MAINTAINERS | 1 + drivers/usb/mux/Kconfig | 7 ++ drivers/usb/mux/Makefile | 1 + drivers/usb/mux/intel-mux-drcfg.c | 161 ++ 4 files changed, 170 insertions(+) create mode 100644 drivers/usb/mux/intel-mux-drcfg.c diff --git a/MAINTAINERS b/MAINTAINERS index ab876eb..399cefe 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11407,6 +11407,7 @@ S: Supported F: drivers/usb/mux/intel-mux.c F: include/linux/usb/intel-mux.h F: drivers/usb/mux/intel-mux-gpio.c +F: drivers/usb/mux/intel-mux-drcfg.c USB PRINTER DRIVER (usblp) M: Pete Zaitcev diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig index 060bf5c..775d5da 100644 --- a/drivers/usb/mux/Kconfig +++ b/drivers/usb/mux/Kconfig @@ -15,4 +15,11 @@ config INTEL_MUX_GPIO Say Y here to enable support for Intel dual role port mux controlled by GPIOs. +config INTEL_MUX_DRCFG + tristate "Intel dual role port mux controlled by register" + depends on X86 + select INTEL_USB_MUX + help + Say Y here to enable support for Intel dual role port mux + controlled by the Dual Role Configuration Register. endmenu diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile index 66f765c..3179909 100644 --- a/drivers/usb/mux/Makefile +++ b/drivers/usb/mux/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_INTEL_USB_MUX)+= intel-mux.o obj-$(CONFIG_INTEL_MUX_GPIO) += intel-mux-gpio.o +obj-$(CONFIG_INTEL_MUX_DRCFG) += intel-mux-drcfg.o diff --git a/drivers/usb/mux/intel-mux-drcfg.c b/drivers/usb/mux/intel-mux-drcfg.c new file mode 100644 index 000..11db826 --- /dev/null +++ b/drivers/usb/mux/intel-mux-drcfg.c @@ -0,0 +1,161 @@ +/** + * intel-mux-drcfg.c - Driver for Intel USB mux via register + * + * Copyright (C) 2016 Intel Corporation + * Author: Heikki Krogerus + * Author: Lu Baolu + * + * 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 +#include +#include +#include +#include + +#define INTEL_MUX_CFG0 0x00 +#define INTEL_MUX_CFG1 0x04 +#define CFG0_SW_IDPIN BIT(20) +#define CFG0_SW_IDPIN_EN BIT(21) +#define CFG0_SW_VBUS_VALID BIT(24) +#define CFG1_SW_MODE BIT(29) +#define CFG1_POLL_TIMEOUT 1000 + +struct intel_usb_mux { + struct intel_mux_dev umdev; + void __iomem *regs; +}; + +static inline int intel_mux_drcfg_switch(struct intel_mux_dev *umdev, bool host) +{ + struct intel_usb_mux *mux; + unsigned long timeout; + u32 data; + + mux = container_of(umdev, struct intel_usb_mux, umdev); + + /* Check and set mux to SW controlled mode */ + data = readl(mux->regs + INTEL_MUX_CFG0); + if (!(data & CFG0_SW_IDPIN_EN)) { + data |= CFG0_SW_IDPIN_EN; + writel(data, mux->regs + INTEL_MUX_CFG0); + } + + /* +* Configure CFG0 to switch the mux and VBUS_VALID bit is +* required for device mode. +*/ + data = readl(mux->regs + INTEL_MUX_CFG0); + if (host) + data &= ~(CFG0_SW_IDPIN | CFG0_SW_VBUS_VALID); + else + data |= (CFG0_SW_IDPIN | CFG0_SW_VBUS_VALID); + writel(data, mux->regs + INTEL_MUX_CFG0); + + /* +* Polling CFG1 for safety, most case it takes about 600ms +* to finish mode switching, set TIMEOUT long enough. +*/ + timeout = jiffies + msecs_to_jiffies(CFG1_POLL_TIMEOUT); + + /* Polling on CFG1 register to confirm mode switch. */ + while (!time_after(jiffies, timeout)) { + data = readl(mux->regs + INTEL_MUX_CFG1); + if (!(host ^ (data & CFG1_SW_MODE))) + return 0; + /* interval for polling is set to about 5ms */ + usleep_range(5000, 5100); + } + + return -ETIMEDOUT; +} + +static int intel_mux_drcfg_cable_set(struct intel_mux_dev *umdev) +{ + dev_dbg(umdev->dev, "drcfg mux switch to HOST\n"); + + return intel_mux_drcfg_switch(umdev, true); +} + +static int intel_mux_drcfg_cable_unset(struct intel_mux_dev *umdev) +{ + dev_dbg(umdev->dev, "drcfg mux switch to DEVICE\n"); + + return intel_mux_drcfg_switch(umdev, false); +} + +static int intel_mux_drcfg_probe(struct platform_device *pdev) +{ + struct intel_usb_mux *mux; + struct intel_mux_dev *umdev; + struct
[PATCH v2 2/7] extcon: usb-gpio: add support for ACPI gpio interface
GPIO resource could be retrieved through APCI as well. Signed-off-by: Lu Baolu Reviewed-by: Felipe Balbi Acked-by: Chanwoo Choi --- drivers/extcon/extcon-usb-gpio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c index af9c8b0..472c431 100644 --- a/drivers/extcon/extcon-usb-gpio.c +++ b/drivers/extcon/extcon-usb-gpio.c @@ -26,6 +26,7 @@ #include #include #include +#include #define USB_GPIO_DEBOUNCE_MS 20 /* ms */ @@ -91,7 +92,7 @@ static int usb_extcon_probe(struct platform_device *pdev) struct usb_extcon_info *info; int ret; - if (!np) + if (!np && !ACPI_HANDLE(dev)) return -EINVAL; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); -- 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 v2 3/7] usb: mux: add common code for Intel dual role port mux
Several Intel PCHs and SOCs have an internal mux that is used to share one USB port between device controller and host controller. A usb port mux could be abstracted as the following elements: 1) mux state: HOST or PERIPHERAL; 2) an extcon cable which triggers the change of mux state between HOST and PERIPHERAL; 3) The required action to do the real port switch. This patch adds the common code to handle usb port mux. With this common code, the individual mux driver, which always is platform dependent, could focus on the real operation of mux switch. Signed-off-by: Lu Baolu Reviewed-by: Heikki Krogerus Reviewed-by: Felipe Balbi --- Documentation/ABI/testing/sysfs-bus-platform | 15 +++ MAINTAINERS | 7 ++ drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 1 + drivers/usb/mux/Kconfig | 9 ++ drivers/usb/mux/Makefile | 4 + drivers/usb/mux/intel-mux.c | 166 +++ include/linux/usb/intel-mux.h| 47 8 files changed, 251 insertions(+) create mode 100644 drivers/usb/mux/Kconfig create mode 100644 drivers/usb/mux/Makefile create mode 100644 drivers/usb/mux/intel-mux.c create mode 100644 include/linux/usb/intel-mux.h diff --git a/Documentation/ABI/testing/sysfs-bus-platform b/Documentation/ABI/testing/sysfs-bus-platform index 5172a61..a2261cb 100644 --- a/Documentation/ABI/testing/sysfs-bus-platform +++ b/Documentation/ABI/testing/sysfs-bus-platform @@ -18,3 +18,18 @@ Description: devices to opt-out of driver binding using a driver_override name such as "none". Only a single driver may be specified in the override, there is no support for parsing delimiters. + +What: /sys/bus/platform/devices/.../intel_mux +Date: Febuary 2016 +Contact: Lu Baolu +Description: + In some platforms, a single USB port is shared between a USB host + controller and a device controller. A USB mux driver is needed to + handle the port mux. intel_mux attribute shows and stores the mux + state. + For read: + 'peripheral' - mux switched to PERIPHERAL controller; + 'host' - mux switched to HOST controller. + For write: + 'peripheral' - mux will be switched to PERIPHERAL controller; + 'host' - mux will be switched to HOST controller. diff --git a/MAINTAINERS b/MAINTAINERS index c55b37e..a93d26a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11400,6 +11400,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git S: Maintained F: drivers/usb/phy/ +USB PORT MUX DRIVER +M: Lu Baolu +L: linux-usb@vger.kernel.org +S: Supported +F: drivers/usb/mux/intel-mux.c +F: include/linux/usb/intel-mux.h + USB PRINTER DRIVER (usblp) M: Pete Zaitcev L: linux-usb@vger.kernel.org diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 8ed451d..dbd6620 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -149,6 +149,8 @@ endif # USB source "drivers/usb/phy/Kconfig" +source "drivers/usb/mux/Kconfig" + source "drivers/usb/gadget/Kconfig" config USB_LED_TRIG diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index dca7856..9a92338 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_USB) += core/ obj-$(CONFIG_USB_SUPPORT) += phy/ +obj-$(CONFIG_USB_SUPPORT) += mux/ obj-$(CONFIG_USB_DWC3) += dwc3/ obj-$(CONFIG_USB_DWC2) += dwc2/ diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig new file mode 100644 index 000..8fedc4f --- /dev/null +++ b/drivers/usb/mux/Kconfig @@ -0,0 +1,9 @@ +# +# USB port mux driver configuration +# +menu "USB Port MUX drivers" +config INTEL_USB_MUX + select EXTCON + def_bool n + +endmenu diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile new file mode 100644 index 000..84f0ae8 --- /dev/null +++ b/drivers/usb/mux/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for USB port mux drivers +# +obj-$(CONFIG_INTEL_USB_MUX)+= intel-mux.o diff --git a/drivers/usb/mux/intel-mux.c b/drivers/usb/mux/intel-mux.c new file mode 100644 index 000..b243758 --- /dev/null +++ b/drivers/usb/mux/intel-mux.c @@ -0,0 +1,166 @@ +/** + * mux.c - USB Port Mux support + * + * Copyright (C) 2016 Intel Corporation + * + * Author: Lu Baolu + * + * 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 +#include +#include +#include + +struct intel_usb_mux { + struct i
[PATCH v2 6/7] usb: pci-quirks: add Intel USB drcfg mux device
In some Intel platforms, a single usb port is shared between USB host and device controllers. The shared port is under control of a switch which is defined in the Intel vendor defined extended capability for xHCI. This patch adds the support to detect and create the platform device for the port mux switch. Signed-off-by: Lu Baolu Reviewed-by: Felipe Balbi --- drivers/usb/host/pci-quirks.c| 47 ++-- drivers/usb/host/xhci-ext-caps.h | 2 ++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 35af362..6a737cf 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -16,10 +16,11 @@ #include #include #include +#include + #include "pci-quirks.h" #include "xhci-ext-caps.h" - #define UHCI_USBLEGSUP 0xc0/* legacy support */ #define UHCI_USBCMD0 /* command register */ #define UHCI_USBINTR 4 /* interrupt register */ @@ -78,6 +79,9 @@ #define USB_INTEL_USB3_PSSEN 0xD8 #define USB_INTEL_USB3PRM 0xDC +#define DEVICE_ID_INTEL_CHERRYVIEW_XHCI0x22b5 +#define DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 + /* * amd_chipset_gen values represent AMD different chipset generations */ @@ -956,6 +960,41 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) } EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); +static void create_intel_usb_mux_device(struct pci_dev *xhci_pdev, + void __iomem *base) +{ + struct platform_device *plat_dev; + struct property_set pset; + int ret; + + struct property_entry pentry[] = { + PROPERTY_ENTRY_U64("reg-start", + pci_resource_start(xhci_pdev, 0) + 0x80d8), + PROPERTY_ENTRY_U64("reg-size", 8), + { }, + }; + + if (!xhci_find_next_ext_cap(base, 0, XHCI_EXT_CAPS_INTEL_USB_MUX)) + return; + + plat_dev = platform_device_alloc("intel-mux-drcfg", + PLATFORM_DEVID_AUTO); + if (!plat_dev) + return; + + plat_dev->dev.parent = &xhci_pdev->dev; + pset.properties = pentry; + platform_device_add_properties(plat_dev, &pset); + + ret = platform_device_add(plat_dev); + if (ret) { + dev_warn(&xhci_pdev->dev, + "failed to create mux device with error %d", + ret); + platform_device_put(plat_dev); + } +} + /** * PCI Quirks for xHCI. * @@ -1022,8 +1061,12 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); hc_init: - if (pdev->vendor == PCI_VENDOR_ID_INTEL) + if (pdev->vendor == PCI_VENDOR_ID_INTEL) { usb_enable_intel_xhci_ports(pdev); + if (pdev->device == DEVICE_ID_INTEL_CHERRYVIEW_XHCI || + pdev->device == DEVICE_ID_INTEL_BROXTON_M_XHCI) + create_intel_usb_mux_device(pdev, base); + } op_reg_base = base + XHCI_HC_LENGTH(readl(base)); diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index e0244fb..e368ccb 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -51,6 +51,8 @@ #define XHCI_EXT_CAPS_ROUTE5 /* IDs 6-9 reserved */ #define XHCI_EXT_CAPS_DEBUG10 +/* Vendor defined 192-255 */ +#define XHCI_EXT_CAPS_INTEL_USB_MUX192 /* USB Legacy Support Capability - section 7.1.1 */ #define XHCI_HC_BIOS_OWNED (1 << 16) #define XHCI_HC_OS_OWNED (1 << 24) -- 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 v2 0/7] usb: add support for Intel dual role port mux
Intel SOC chips are featured with USB dual role. The host role is provided by Intel xHCI IP, and the gadget role is provided by IP from designware. Tablet platform designs always share a single port for both host and gadget controllers. There is a mux to switch the port to the right controller according to the cable type. OS needs to provide the callback to control the mux when a plug-in event raises. The method to control the mux is platform dependent. At least three types of implementation can be found across current devices. 1) GPIO pins; 2) a unit which can be controlled by memory mapped registers; 3) ACPI ASL code. This patch series adds supports for Intel dual role port mux. It includes: (1) A helper layer on top of extcon for individual mux driver. It listens to the USB-HOST extcon cable and call the switch call-back when the cable state changes. (2) Drivers for GPIO controlled port mux which could be found on Baytrail devices. A mfd driver is used to split the GPIOs into USB gpio extcon device and a USB mux device. Driver for USB gpio extcon device is already in upstream Linux. This patch series includes a driver for GPIO USB mux. (3) Drivers for USB port mux controlled through memory mapped registers and the logic to create the mux device. This type of dual role port mux could be found in Cherry Trail and Broxton devices. Lu Baolu (7): extcon: usb-gpio: add device binding for platform device extcon: usb-gpio: add support for ACPI gpio interface usb: mux: add common code for Intel dual role port mux usb: mux: add driver for Intel gpio controlled port mux usb: mux: add driver for Intel drcfg controlled port mux usb: pci-quirks: add Intel USB drcfg mux device mfd: intel_vuport: Add Intel virtual USB port MFD Driver Documentation/ABI/testing/sysfs-bus-platform | 15 +++ MAINTAINERS | 10 ++ drivers/extcon/extcon-usb-gpio.c | 10 +- drivers/mfd/Kconfig | 8 ++ drivers/mfd/Makefile | 1 + drivers/mfd/intel-vuport.c | 78 + drivers/usb/Kconfig | 2 + drivers/usb/Makefile | 1 + drivers/usb/host/pci-quirks.c| 47 +++- drivers/usb/host/xhci-ext-caps.h | 2 + drivers/usb/mux/Kconfig | 25 drivers/usb/mux/Makefile | 6 + drivers/usb/mux/intel-mux-drcfg.c| 161 ++ drivers/usb/mux/intel-mux-gpio.c | 125 drivers/usb/mux/intel-mux.c | 166 +++ include/linux/usb/intel-mux.h| 47 16 files changed, 701 insertions(+), 3 deletions(-) create mode 100644 drivers/mfd/intel-vuport.c create mode 100644 drivers/usb/mux/Kconfig create mode 100644 drivers/usb/mux/Makefile create mode 100644 drivers/usb/mux/intel-mux-drcfg.c create mode 100644 drivers/usb/mux/intel-mux-gpio.c create mode 100644 drivers/usb/mux/intel-mux.c create mode 100644 include/linux/usb/intel-mux.h Change log: v1->v2: - move mux driver from drivers/usb/misc to drivers/usb/mux; - replace debugfs with sysfs for user level mux control; - remove unnecessary register restore if mux registeration failed; - Add "Acked-by: Chanwoo Choi " to extcon changes; - Make the file names and exported function names more specific; - Remove the usb_mux_get_dev() interface; - Move "struct intel_usb_mux" from .h to .c file; - Fix various kbuild robot warnings. -- 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
Re: xhci_hcd : Not enough bandwidth on HS bus for newly activated TT.
Hi Kenneth Johansson, Did you still get the bandwidth error when testing it with longer time? Thanks, Baolu On 2015-03-03 10:06, Lu, Baolu wrote: cc'ed usb mailing list. On 2015-03-02 21:23, Kenneth Johansson wrote: I have been running 3.19 prereleases and now 3.19 and have not got the bandwidth problem with that kernel version. While it was quite hard to get before I think I have run int long enough to say that it no longer exist. so I guess I get it like 5 minutes after I send this ;) On 2015-03-02 03:37, Lu, Baolu wrote: Include Kenneth Johansson. On 2015-03-02 10:33, Lu, Baolu wrote: I tried to reproduce this issue on an Intel Ivybridge machine. But I failed. Kernel version: 4.0.0-rc1 (built against master branch of Greg's usb tree) USB fabric: $ sudo lsusb -t /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M |__ Port 5: Dev 3, If 0, Class=Video, Driver=, 480M |__ Port 5: Dev 3, If 1, Class=Video, Driver=, 480M |__ Port 6: Dev 4, If 0, Class=Wireless, Driver=, 12M |__ Port 6: Dev 4, If 1, Class=Wireless, Driver=, 12M /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M |__ Port 1: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 1: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 12M /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M |__ Port 2: Dev 10, If 0, Class=Hub, Driver=hub/4p, 480M |__ Port 1: Dev 11, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M |__ Port 1: Dev 11, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M |__ Port 2: Dev 12, If 0, Class=Hub, Driver=hub/3p, 12M |__ Port 1: Dev 13, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 1: Dev 13, If 1, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 3: Dev 14, If 0, Class=Vendor Specific Class, Driver=asix, 480M Test script: #!/bin/bash while [ 1 ] do echo "devices" > /sys/power/pm_test sleep 5 echo "freeze" > /sys/power/state sleep 15 done I kept this script running for more than 24 hours and didn't see the issue described below. Any hints or suggestions? Thanks, Baolu On 2014-11-10 14:40:13, Mathias Nyman wrote: On 10.11.2014 12:47, Kenneth Johansson wrote: So I have a problem that happens with 1-2 weeks interval in that the xhci driver confuses itself and thinks that the usb bus is overused or something. The thing is that this is an external usb 2 hub with 7 ports and all 7 is used for different devices. I do a suspend/resume once a day and thats it. its the same devices on the hub but the USB driver for some reason decides that it no longer can allow the devices on the bus. 1. is there any way to reset the entire usb stack without rebooting?? I run 3.16 ubuntu kernel and I think usb is built in I at least can see any module named xhci. 2. what can be done to solve this ?? there must be some type of resource leak here as a reboot solves the problem and I have exactly the same usb devices that I use. 3. I also notice that we max out at about 30 devices and I think usb should be able to handle 127. 4. I noticed on a different computer that a usb sound card (5.1) was also getting the bandwidth error if I attached it to a usb3 hub that had only that device, it works if I remove the hub. 5. overall usb3 looks to be a bit "unpredictable" and if you google for this type of errors the advice is to downgrade to usb2. that do sound like the wrong thing to do unless the xhci hardware is that broken. is it ? or is this the driver that needs fixing. - [65633.315419] usb 3-1.4.1: Product: USB Transfer Cable [65633.315422] usb 3-1.4.1: Manufacturer: Prolific Technology Inc. [65633.315607] xhci_hcd :00:14.0: Not enough bandwidth on HS bus for newly activated TT. [65633.315612] xhci_hcd :00:14.0: Not enough bandwidth [65633.315619] usb 3-1.4.1: can't set config #1, error -12 --- [65653.367865] xhci_hcd :00:14.0: Not enough bandwidth on HS bus for newly activated TT. [65653.367867] xhci_hcd :00:14.0: Not enough bandwidth [65653.367872] usb 3-1.2: can't set config #1, error -12 and so on. -- The xhci controller has a limit for max devices it can support, usually less than 127. 3.16 kernel and later should report "Max number of devices this xHCI host supports is %u.\n" when you reach the limit. I've got reports about bandwidth errors before, so far two different kinds, one is a context error which happends while allocating bandwith, and is not really a bandwidth issue. Then we also got real band
Re: xhci_hcd : Not enough bandwidth on HS bus for newly activated TT.
On 03/05/2015 09:17 PM, Kenneth Johansson wrote: On 2015-03-05 03:23, Lu, Baolu wrote: Hi Kenneth Johansson, Did you still get the bandwidth error when testing it with longer time? no I have not seen it on any 3.19 kernel I have used so far. But It could take a week to see it before so it's hard to say that I'm 100% sure it's gone. But so far it looks like its gone. Thanks for the information. Please let me know when you are 100% sure that it's gone. Thanks, Baolu On 2015-03-03 10:06, Lu, Baolu wrote: cc'ed usb mailing list. On 2015-03-02 21:23, Kenneth Johansson wrote: I have been running 3.19 prereleases and now 3.19 and have not got the bandwidth problem with that kernel version. While it was quite hard to get before I think I have run int long enough to say that it no longer exist. so I guess I get it like 5 minutes after I send this ;) On 2015-03-02 03:37, Lu, Baolu wrote: Include Kenneth Johansson. On 2015-03-02 10:33, Lu, Baolu wrote: I tried to reproduce this issue on an Intel Ivybridge machine. But I failed. Kernel version: 4.0.0-rc1 (built against master branch of Greg's usb tree) USB fabric: $ sudo lsusb -t /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/6p, 480M |__ Port 5: Dev 3, If 0, Class=Video, Driver=, 480M |__ Port 5: Dev 3, If 1, Class=Video, Driver=, 480M |__ Port 6: Dev 4, If 0, Class=Wireless, Driver=, 12M |__ Port 6: Dev 4, If 1, Class=Wireless, Driver=, 12M /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=ehci-pci/3p, 480M |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/4p, 480M |__ Port 1: Dev 3, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 1: Dev 3, If 1, Class=Human Interface Device, Driver=usbhid, 12M /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 5000M |__ Port 2: Dev 3, If 0, Class=Hub, Driver=hub/4p, 5000M /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 480M |__ Port 2: Dev 10, If 0, Class=Hub, Driver=hub/4p, 480M |__ Port 1: Dev 11, If 0, Class=Human Interface Device, Driver=usbhid, 1.5M |__ Port 1: Dev 11, If 1, Class=Human Interface Device, Driver=usbhid, 1.5M |__ Port 2: Dev 12, If 0, Class=Hub, Driver=hub/3p, 12M |__ Port 1: Dev 13, If 0, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 1: Dev 13, If 1, Class=Human Interface Device, Driver=usbhid, 12M |__ Port 3: Dev 14, If 0, Class=Vendor Specific Class, Driver=asix, 480M Test script: #!/bin/bash while [ 1 ] do echo "devices" > /sys/power/pm_test sleep 5 echo "freeze" > /sys/power/state sleep 15 done I kept this script running for more than 24 hours and didn't see the issue described below. Any hints or suggestions? Thanks, Baolu On 2014-11-10 14:40:13, Mathias Nyman wrote: On 10.11.2014 12:47, Kenneth Johansson wrote: So I have a problem that happens with 1-2 weeks interval in that the xhci driver confuses itself and thinks that the usb bus is overused or something. The thing is that this is an external usb 2 hub with 7 ports and all 7 is used for different devices. I do a suspend/resume once a day and thats it. its the same devices on the hub but the USB driver for some reason decides that it no longer can allow the devices on the bus. 1. is there any way to reset the entire usb stack without rebooting?? I run 3.16 ubuntu kernel and I think usb is built in I at least can see any module named xhci. 2. what can be done to solve this ?? there must be some type of resource leak here as a reboot solves the problem and I have exactly the same usb devices that I use. 3. I also notice that we max out at about 30 devices and I think usb should be able to handle 127. 4. I noticed on a different computer that a usb sound card (5.1) was also getting the bandwidth error if I attached it to a usb3 hub that had only that device, it works if I remove the hub. 5. overall usb3 looks to be a bit "unpredictable" and if you google for this type of errors the advice is to downgrade to usb2. that do sound like the wrong thing to do unless the xhci hardware is that broken. is it ? or is this the driver that needs fixing. - [65633.315419] usb 3-1.4.1: Product: USB Transfer Cable [65633.315422] usb 3-1.4.1: Manufacturer: Prolific Technology Inc. [65633.315607] xhci_hcd :00:14.0: Not enough bandwidth on HS bus for newly activated TT. [65633.315612] xhci_hcd :00:14.0: Not enough bandwidth [65633.315619] usb 3-1.4.1: can't set config #1, error -12 --- [65653.367865] xhci_hcd :00:14.0: Not enough bandwidth on HS bus for newly activated TT. [65653.367867] xhci_hcd :00:14.0: Not enough bandwidth [65653.367872] usb 3-1.2: can't set config #1, error -12 and so on. -- The xhci controller has a limit for
[PATCH 1/1] usb: xhci: handle Config Error Change (CEC) in xhci driver
Linux xHCI driver doesn't report and handle port cofig error change. If Port Configure Error for root hub port occurs, CEC bit in PORTSC would be set by xHC and remains 1. This happends when the root port fails to configure its link partner, e.g. the port fails to exchange port capabilities information using Port Capability LMPs. Then the Port Status Change Events will be blocked until all status change bits(CEC is one of the change bits) are cleared('0') (refer to xHCI spec 4.19.2). Otherwise, the port status change event for this root port will not be generated anymore, then root port would look like dead for user and can't be recovered until a Host Controller Reset(HCRST). This patch is to check CEC bit in PORTSC in xhci_get_port_status() and set a Config Error in the return status if CEC is set. This will cause a ClearPortFeature request, where CEC bit is cleared in xhci_clear_port_change_bit(). [Mathias Nyman contributed the idea. The commit log is based on patch posted at http://marc.info/?l=linux-kernel&m=142323612321434&w=2] Signed-off-by: Lu Baolu Cc: stable # v3.2+ --- drivers/usb/host/xhci-hub.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a7865c4..0827d7c 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -387,6 +387,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, status = PORT_PLC; port_change_bit = "link state"; break; + case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: + status = PORT_CEC; + port_change_bit = "config error"; + break; default: /* Should never happen */ return; @@ -588,6 +592,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_C_LINK_STATE << 16; if ((raw_port_status & PORT_WRC)) status |= USB_PORT_STAT_C_BH_RESET << 16; + if ((raw_port_status & PORT_CEC)) + status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; } if (hcd->speed != HCD_USB3) { @@ -1005,6 +1011,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_C_OVER_CURRENT: case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_PORT_LINK_STATE: + case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: xhci_clear_port_change_bit(xhci, wValue, wIndex, port_array[wIndex], temp); break; @@ -1069,7 +1076,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) */ status = bus_state->resuming_ports; - mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; + mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC; spin_lock_irqsave(&xhci->lock, flags); /* For each port, did anything change? If so, set that bit in buf. */ -- 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: [PATCH 1/1] usb: xhci: handle Config Error Change (CEC) in xhci driver
Hi Alan, Do you have any comments for this patch? Thanks, Baolu On 03/06/2015 04:12 PM, Lu Baolu wrote: Linux xHCI driver doesn't report and handle port cofig error change. If Port Configure Error for root hub port occurs, CEC bit in PORTSC would be set by xHC and remains 1. This happends when the root port fails to configure its link partner, e.g. the port fails to exchange port capabilities information using Port Capability LMPs. Then the Port Status Change Events will be blocked until all status change bits(CEC is one of the change bits) are cleared('0') (refer to xHCI spec 4.19.2). Otherwise, the port status change event for this root port will not be generated anymore, then root port would look like dead for user and can't be recovered until a Host Controller Reset(HCRST). This patch is to check CEC bit in PORTSC in xhci_get_port_status() and set a Config Error in the return status if CEC is set. This will cause a ClearPortFeature request, where CEC bit is cleared in xhci_clear_port_change_bit(). [Mathias Nyman contributed the idea. The commit log is based on patch posted at http://marc.info/?l=linux-kernel&m=142323612321434&w=2] Signed-off-by: Lu Baolu Cc: stable # v3.2+ --- drivers/usb/host/xhci-hub.c | 9 - 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a7865c4..0827d7c 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -387,6 +387,10 @@ static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue, status = PORT_PLC; port_change_bit = "link state"; break; + case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: + status = PORT_CEC; + port_change_bit = "config error"; + break; default: /* Should never happen */ return; @@ -588,6 +592,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_C_LINK_STATE << 16; if ((raw_port_status & PORT_WRC)) status |= USB_PORT_STAT_C_BH_RESET << 16; + if ((raw_port_status & PORT_CEC)) + status |= USB_PORT_STAT_C_CONFIG_ERROR << 16; } if (hcd->speed != HCD_USB3) { @@ -1005,6 +1011,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_C_OVER_CURRENT: case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_PORT_LINK_STATE: + case USB_PORT_FEAT_C_PORT_CONFIG_ERROR: xhci_clear_port_change_bit(xhci, wValue, wIndex, port_array[wIndex], temp); break; @@ -1069,7 +1076,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) */ status = bus_state->resuming_ports; - mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; + mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC; spin_lock_irqsave(&xhci->lock, flags); /* For each port, did anything change? If so, set that bit in buf. */ -- 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
Hi Devin, Do you mind to post output of "lspci -xv" on the machine where you saw this problem? We are facing the same problems in other cases. I could provide a patch for it later. Thanks, Baolu On 01/19/2015 04:55 AM, Devin Heitmueller wrote: Hello, I'm debugging some issues on a couple of different USB TV tuners which boil down to the following error: xhci_hcd :00:14.0: xHCI host not responding to stop endpoint command. This is followed by the XHCI driver disconnecting *all* USB devices from the controller. I've done a bit of debugging, and the root of the issue appears to be an intermittent control message timing out, and then the call to usb_kill_urb() that occurs inside of usb_control_msg() when the timeout expires is what causes the disconnect. Specifically, it would appear that xhci_urb_dequeue tries to stop the endpoint using xhci_queue_stop_endpoint(), the command gets queued but the IRQ never fires to perform the TRB_STOP_RING completion code. The function xhci_stop_endpoint_command_watchdog() fires after five seconds, which tears down the entire driver. Below is the dmesg output with the xhci_hcd debugging enabled. The dump_stack() call is something I added (i.e. it's not an OOPS) so I could see which code path was making the usb_kill_urb() call that was failing. Note that the caller is using usb_control_msg() with 1000ms timeout, and we can see from the timestamps that the timer expires which is what causes the call to usb_kill_urb(). I would imagine that explicitly killing URBs is a pretty uncommon task for control endpoint messages (compared to ISOC or BULK endpoints where it's done regularly). Is it possible a exception case has been missed? Independent of the usb_kill_urb() killing the entire stack, I still don't really understand yet why the control message failed in the first place. This is a well-exercised code path in the au0828 driver (related to I2C transfers) and I've never seen this when using the EHCI driver. My assumption is that either the HCD is getting sick which is causing both the control message to fail as well as putting it into an inconsistent state such that we never get the TRB_STOP_RING IRQ, or we've got two separate bugs - the control message failing for some "legitimate" reason (i.e. I screwed something up in my au0828 driver), followed by the usb_kill_urb() error simply not handling killing of URBs on a control endpoint (which causes the entire stack to go down). Thoughts/suggestions/recommendations are welcome. Thanks in advance, Devin Jan 18 14:04:05 devin-MacBookPro kernel: [ 9119.647249] au0828: au0828_writereg(0x0100, 0x00) Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.645091] xhci_hcd :00:14.0: Cancel URB 8802543c36c0, dev 1, ep 0x0, starting at offset 0x25c358940 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.645365] djh dequeue pending=0 ep_index=0 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.645632] CPU: 1 PID: 2782 Comm: tvtime Tainted: P OE 3.18.0-rc4djh+ #33 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.645921] Hardware name: Apple Inc. MacBookPro11,1/Mac-189A3D4F975D5FFC, BIOS MBP111.88Z.0138.B11.1408291433 08/29/2014 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.646236] 88025b9b 88023ea2f9d8 817445c1 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.646570] 8802543c36c0 88023ea2fa58 a0080b2e 00025c358940 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.646909] 88023ea2fa48 3ea2fa18 88023e8a22a0 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.647256] Call Trace: Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.647605] [] dump_stack+0x46/0x58 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.647981] [] xhci_urb_dequeue+0x28e/0x420 [xhci_hcd] Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.648357] [] unlink1+0x2d/0x130 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.648743] [] ? internal_add_timer+0xb0/0xb0 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.649133] [] ? get_device+0x17/0x30 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.649526] [] usb_hcd_unlink_urb+0x5d/0xf0 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.649928] [] usb_kill_urb+0x3a/0xa0 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.650334] [] ? wake_up_state+0x20/0x20 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.650746] [] usb_start_wait_urb+0xc8/0x150 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.651166] [] ? __kmalloc+0x55/0x190 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.651586] [] usb_control_msg+0xc5/0x110 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.652011] [] au0828_writereg+0x79/0xf0 [au0828] Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.652447] [] ? try_to_del_timer_sync+0x4f/0x70 Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.652894] [] au0828_analog_stream_disable+0x29/0x50 [au0828] Jan 18 14:04:06 devin-MacBookPro kernel: [ 9120.653354] [] vidioc_streamoff+0xd9/0x1c0 [au0828] Jan 18 14:04:06 devin-MacBookPro kernel: [
Re: Control message failures kill entire XHCI stack
2 Apple USB Ethernet Adapter iSerial 3 18E4ED bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 39 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 4 0 bmAttributes 0xa0 (Bus Powered) Remote Wakeup MaxPower 250mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber0 bAlternateSetting 0 bNumEndpoints 3 bInterfaceClass 255 Vendor Specific Class bInterfaceSubClass255 Vendor Specific Subclass bInterfaceProtocol 0 iInterface 7 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes3 Transfer TypeInterrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 11 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x03 EP 3 OUT bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0200 1x 512 bytes bInterval 0 Device Qualifier (for other device speed): bLength10 bDescriptorType 6 bcdUSB 2.00 bDeviceClass 255 Vendor Specific Class bDeviceSubClass 255 Vendor Specific Subclass bDeviceProtocol 0 bMaxPacketSize0 8 bNumConfigurations 1 Device Status: 0x (Bus Powered) Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub Device Descriptor: bLength18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass9 Hub bDeviceSubClass 0 Unused bDeviceProtocol 1 Single TT bMaxPacketSize064 idVendor 0x1d6b Linux Foundation idProduct 0x0002 2.0 root hub bcdDevice3.19 iManufacturer 3 Linux 3.19.0-rc5djh+ xhci-hcd iProduct2 xHCI Host Controller iSerial 1 :00:14.0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 25 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower0mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 9 Hub bInterfaceSubClass 0 Unused bInterfaceProtocol 0 Full speed (or root) hub iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes3 Transfer TypeInterrupt Synch Type None Usage Type Data wMaxPacketSize 0x0004 1x 4 bytes bInterval 12 Hub Descriptor: bLength 11 bDescriptorType 41 nNbrPorts 9 wHubCharacteristic 0x000a No power switching (usb 1.0) Per-port overcurrent protection TT think time 8 FS bits bPwrOn2PwrGood 10 * 2 milli seconds bHubContrCurrent 0 milli Ampere DeviceRemovable0x00 0x00 PortPwrCtrlMask0xff 0xff Hub Port Status: Port 1: .0503 highspeed power enable connect Port 2: .0100 power Port 3: .0103 power enable connect Port 4: .0100 power Port 5: .0103 power enable connect Port 6: .0100 power Port 7: .0100 power Port 8: .0100 power Port 9: .0100 power Device Status: 0x0001 Self Powered Devin On Tue, Mar 10, 2015 at 5:55 AM, Lu, Baolu wrote: Hi Devin, Do you mind to post output of "lspci -xv" on the machine where you saw this problem? We are facing the same problems in other cases. I could provide a patch for it later.
Re: [V4.0.0-rc3] Xhci Regression: ERROR Transfer event TRB DMA ptr not part of current TD
On 03/11/2015 02:49 AM, Alan Stern wrote: On Tue, 10 Mar 2015, Mathias Nyman wrote: Mathias: Your patch description says this: The endpoint might already processesed some TRBs on the endpiont ring before we soft reset the endpoint. Make sure we set the dequeue pointer to where we were befere soft reset However, if a driver tries to issue an endpoint reset while there are still some URBs queued, it is a bug. Host controller drivers shouldn't have to worry about this -- xhci_endpoint_reset() should simply return an error if the endpoint ring isn't empty. I suppose we should check for this in the USB core. I'll write a patch and CC: you. Alan Stern It's possible that there's something in usb core as well, but I think the following was what happened: 1. First a normal configure endpoint command is issued, it sets endpoint dequeue pointer to xxx400 = start of ring segment 2. two urbs get queued -> two TDs put on endpoint ring. 3. xhci executes those, ring is in running (idle) state. sw dequeue at xxx430, No TDs queued. Endpoint dequeue pointer is not written to the endpoint output context as the ring is still in running state (even if idle, not advancing with no TDs queued) it still shows xxx400 4. -> something happends, xhci_endpoint_reset() is called, we do a new configure endpoint to 'soft reset' the endpiont, but we copy the dequeue pointer from the old endpoint output context to the configure endpoint input context, which re-initializes the old dequeue xxx400 pointer to xhci hardware, and it starts executing the old TDs from the ring. Is it possible to return an error message up to client driver? The client driver then decides how to handle this kind of error. It, possibly, unlink all ongoing transfers and ask host driver to soft reset this endpoint. When xhci_endpoint_reset is called, there should be no ongoing transfers. Thanks, Baolu Obviously that's bad. But don't you have to stop the endpoint ring in order to configure it? When you stop the ring, doesn't the controller store the correct current value of the dequeue pointer somewhere? 5. xhci driver notices that we get events for old TRBs that do not belong to the TD the driver thinks we should be handling Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 1/1] usb: xhci: apply XHCI_AVOID_BEI quirk to Intel ValleyView and LynxPoint LP
When a device with an isochronous endpoint is plugged into the Intel xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under some Intel xHCI host controllers like ValleyView and Lynx Point LP, if the event ring is full of events from transfers with BEI set, a "Event Ring is Full" event will be posted to the last entry of the event ring, but no interrupt is generated. Host will cease all transfer and command executions and wait until software completes handling the pending events in event ring. That means xHC stops but event of "event ring is full" is not notified. As the result, the xHC looks like dead to user. The patch is to apply XHCI_AVOID_BEI to Intel VallyView and Lynx Point LP devices. And it should be backported to kernels as old as 3.0, that contains the commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port switching.") Signed-off-by: Lu Baolu Cc: sta...@vger.kernel.org --- drivers/usb/host/xhci-pci.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fd53c9e..5aa4893 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -40,6 +40,7 @@ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI0x22b5 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI0xa12f #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f +#definePCI_DEVICE_ID_INTEL_VALLEYVIEW_XHCI 0x0f35 static const char hcd_name[] = "xhci_hcd"; @@ -135,6 +136,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) { xhci->quirks |= XHCI_SPURIOUS_REBOOT; + xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI || @@ -142,6 +144,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) { xhci->quirks |= XHCI_PME_STUCK_QUIRK; } + if (pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_VALLEYVIEW_XHCI) + xhci->quirks |= XHCI_AVOID_BEI; if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_EJ168) { xhci->quirks |= XHCI_RESET_ON_RESUME; -- 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: [PATCH 1/1] usb: xhci: apply XHCI_AVOID_BEI quirk to Intel ValleyView and LynxPoint LP
On 03/12/2015 04:46 PM, Mathias Nyman wrote: On 12.03.2015 03:39, Lu Baolu wrote: When a device with an isochronous endpoint is plugged into the Intel xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under some Intel xHCI host controllers like ValleyView and Lynx Point LP, if the event ring is full of events from transfers with BEI set, a "Event Ring is Full" event will be posted to the last entry of the event ring, but no interrupt is generated. Host will cease all transfer and command executions and wait until software completes handling the pending events in event ring. That means xHC stops but event of "event ring is full" is not notified. As the result, the xHC looks like dead to user. The patch is to apply XHCI_AVOID_BEI to Intel VallyView and Lynx Point LP devices. And it should be backported to kernels as old as 3.0, that contains the commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port switching.") Maybe we should set the quirk for all Intel xHCI controllers. So far the list includes Pantherpoint, Lynxpoint and valleyview. I bet it concerns most Intel platforms. Yes, I agree with you. I will send out a new patch for this. -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 -- 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/1] usb: xhci: apply XHCI_AVOID_BEI quirk to Intel ValleyView and LynxPoint LP
On 03/12/2015 03:54 PM, Greg Kroah-Hartman wrote: On Thu, Mar 12, 2015 at 09:39:06AM +0800, Lu Baolu wrote: When a device with an isochronous endpoint is plugged into the Intel xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under some Intel xHCI host controllers like ValleyView and Lynx Point LP, if the event ring is full of events from transfers with BEI set, a "Event Ring is Full" event will be posted to the last entry of the event ring, but no interrupt is generated. Host will cease all transfer and command executions and wait until software completes handling the pending events in event ring. That means xHC stops but event of "event ring is full" is not notified. As the result, the xHC looks like dead to user. The patch is to apply XHCI_AVOID_BEI to Intel VallyView and Lynx Point LP devices. And it should be backported to kernels as old as 3.0, that contains the commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port switching.") Signed-off-by: Lu Baolu Cc: sta...@vger.kernel.org --- drivers/usb/host/xhci-pci.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fd53c9e..5aa4893 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -40,6 +40,7 @@ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f +#definePCI_DEVICE_ID_INTEL_VALLEYVIEW_XHCI 0x0f35 Minor nit, you added a tab where the rest of the file was using a space :( Yes, thanks for reminding. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 v2 1/1] usb: xhci: apply XHCI_AVOID_BEI quirk to all Intel xHCI controllers
When a device with an isochronous endpoint is plugged into the Intel xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under Intel xHCI host controllers, if the event ring is full of events from transfers with BEI set, an "Event Ring is Full" event will be posted to the last entry of the event ring, but no interrupt is generated. Host will cease all transfer and command executions and wait until software completes handling the pending events in the event ring. That means xHC stops, but event of "event ring is full" is not notified. As the result, the xHC looks like dead to user. This patch is to apply XHCI_AVOID_BEI quirk to Intel xHC devices. And it should be backported to kernels as old as 3.0, that contains the commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port switching."). Signed-off-by: Lu Baolu Cc: sta...@vger.kernel.org --- drivers/usb/host/xhci-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fd53c9e..2af32e2 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -115,6 +115,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; xhci->quirks |= XHCI_INTEL_HOST; + xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { @@ -130,7 +131,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) * PPT chipsets. */ xhci->quirks |= XHCI_SPURIOUS_REBOOT; - xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) { -- 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
[PATCH v3 1/1] usb: xhci: apply XHCI_AVOID_BEI quirk to all Intel xHCI controllers
When a device with an isochronous endpoint is plugged into the Intel xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under Intel xHCI host controllers, if the event ring is full of events from transfers with BEI set, an "Event Ring is Full" event will be posted to the last entry of the event ring, but no interrupt is generated. Host will cease all transfer and command executions and wait until software completes handling the pending events in the event ring. That means xHC stops, but event of "event ring is full" is not notified. As the result, the xHC looks like dead to user. This patch is to apply XHCI_AVOID_BEI quirk to Intel xHC devices. And it should be backported to kernels as old as 3.0, that contains the commit 69e848c2090a ("Intel xhci: Support EHCI/xHCI port switching."). Signed-off-by: Lu Baolu Tested-by: Alistair Grant Tested-by: Devin Heitmueller Cc: sta...@vger.kernel.org --- drivers/usb/host/xhci-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Change log: v2: apply to all Intel xHC devices as suggested by Mathias v3: add two Tested-by's diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index fd53c9e..2af32e2 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -115,6 +115,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; xhci->quirks |= XHCI_INTEL_HOST; + xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { @@ -130,7 +131,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) * PPT chipsets. */ xhci->quirks |= XHCI_SPURIOUS_REBOOT; - xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) { -- 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: [PATCHv2 01/12] usb: add bus type for USB ULPI
On 03/18/2015 08:40 PM, Heikki Krogerus wrote: + +/** + * ulpi_register_driver - unregister a driver with the ULPI bus Hi Heikki, "ulpi_register_driver" should be changed to "ulpi_unregister_driver". Thanks, Baolu + * @drv: driver to unregister + * + * Unregisters a driver with the ULPI bus. + */ +void ulpi_unregister_driver(struct ulpi_driver *drv) +{ + driver_unregister(&drv->driver); +} +EXPORT_SYMBOL_GPL(ulpi_unregister_driver); + -- 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
[RFC][PATCH 2/3] usb: xhci: implement hc_driver notify entry
This patch implements the notify entry defined in hc_driver for xHC driver. For HCD_MSG_DEV_SUSPEND message, it will issue stop endpoint command for each endpoint in the device. The Suspend(SP) bit in the command TRB will be set, which gives xHC a hint about the suspend. For HCD_MSG_DEV_RESUME, it will ring doorbells for all endpoints unconditionally. XHC may use these hints to optimize its operation on endpoint state cashes. Signed-off-by: Lu Baolu --- drivers/usb/host/xhci-hub.c | 2 +- drivers/usb/host/xhci.c | 28 drivers/usb/host/xhci.h | 3 +++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0827d7c..a83e82e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -266,7 +266,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, * to complete. * suspend will set to 1, if suspend bit need to set in command. */ -static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) +int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) { struct xhci_virt_device *virt_dev; struct xhci_command *cmd; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ec8ac16..1e4aa78 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4917,6 +4917,29 @@ error: } EXPORT_SYMBOL_GPL(xhci_gen_setup); +void xhci_notify(struct usb_hcd *hcd, struct usb_device *udev, + enum hcd_notification_type type, void *data) +{ + struct xhci_hcd *xhci; + + xhci = hcd_to_xhci(hcd); + if (!xhci || !xhci->devs[udev->slot_id]) + return; + + switch (type) { + case HCD_MSG_DEV_SUSPEND: + xhci_stop_device(xhci, udev->slot_id, 1); + break; + case HCD_MSG_DEV_RESUME: + xhci_ring_device(xhci, udev->slot_id); + break; + default: + xhci_dbg(xhci, "unknown notification message %d.\n", type); + break; + } + +} + static const struct hc_driver xhci_hc_driver = { .description = "xhci-hcd", .product_desc = "xHCI Host Controller", @@ -4976,6 +4999,11 @@ static const struct hc_driver xhci_hc_driver = { .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, .find_raw_port_number = xhci_find_raw_port_number, + + /* +* notification call back +*/ + .notify = xhci_notify, }; void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *)) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8e421b8..f71c643 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1867,10 +1867,13 @@ u32 xhci_port_state_to_neutral(u32 state); int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, u16 port); void xhci_ring_device(struct xhci_hcd *xhci, int slot_id); +int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend); /* xHCI contexts */ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); +void xhci_notify(struct usb_hcd *hcd, struct usb_device *udev, + enum hcd_notification_type type, void *data); #endif /* __LINUX_XHCI_HCD_H */ -- 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
[PATCH v2 2/3] usb: xhci: implement device_suspend/device_resume entries
This patch implements device_suspend/device_resume entries for xHC driver. device_suspend will be called when a USB device is about to suspend. It will issue a stop endpoint command for each endpoint in this device. The Suspend(SP) bit in the command TRB will set which will give xHC a hint about the suspend. device_resume will be called when a USB device is just resumed. It will ring doorbells of all endpoint unconditionally. XHC may use these suspend/resume hints to optimize its operation. Signed-off-by: Lu Baolu --- drivers/usb/host/xhci-hub.c | 2 +- drivers/usb/host/xhci.c | 40 drivers/usb/host/xhci.h | 5 + 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 0827d7c..a83e82e 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -266,7 +266,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, * to complete. * suspend will set to 1, if suspend bit need to set in command. */ -static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) +int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) { struct xhci_virt_device *virt_dev; struct xhci_command *cmd; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index ec8ac16..b639627 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4680,6 +4680,30 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, return ret; return 0; } + +void xhci_device_suspend(struct usb_hcd *hcd, + struct usb_device *udev, pm_message_t msg) +{ + struct xhci_hcd *xhci; + + xhci = hcd_to_xhci(hcd); + if (!xhci || !xhci->devs[udev->slot_id]) + return; + + xhci_stop_device(xhci, udev->slot_id, 1); +} + +void xhci_device_resume(struct usb_hcd *hcd, + struct usb_device *udev, pm_message_t msg) +{ + struct xhci_hcd *xhci; + + xhci = hcd_to_xhci(hcd); + if (!xhci || !xhci->devs[udev->slot_id]) + return; + + xhci_ring_device(xhci, udev->slot_id); +} #else /* CONFIG_PM */ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, @@ -4704,6 +4728,16 @@ int xhci_disable_usb3_lpm_timeout(struct usb_hcd *hcd, { return 0; } + +void xhci_device_suspend(struct usb_hcd *hcd, + struct usb_device *udev, pm_message_t msg) +{ +} + +void xhci_device_resume(struct usb_hcd *hcd, + struct usb_device *udev, pm_message_t msg) +{ +} #endif /* CONFIG_PM */ /*-*/ @@ -4976,6 +5010,12 @@ static const struct hc_driver xhci_hc_driver = { .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, .find_raw_port_number = xhci_find_raw_port_number, + + /* +* call back when devices suspend or resume +*/ + .device_suspend = xhci_device_suspend, + .device_resume =xhci_device_resume, }; void xhci_init_driver(struct hc_driver *drv, int (*setup_fn)(struct usb_hcd *)) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8e421b8..3d1f73b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1867,10 +1867,15 @@ u32 xhci_port_state_to_neutral(u32 state); int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, u16 port); void xhci_ring_device(struct xhci_hcd *xhci, int slot_id); +int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend); /* xHCI contexts */ struct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); struct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); struct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); +void xhci_device_suspend(struct usb_hcd *hcd, + struct usb_device *udev, pm_message_t msg); +void xhci_device_resume(struct usb_hcd *hcd, + struct usb_device *udev, pm_message_t msg); #endif /* __LINUX_XHCI_HCD_H */ -- 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
[PATCH 1/1] usb: ulpi: ulpi_init should be used in subsys_initcall
The intention of this change is to fix below kernel panic when USB_ULPI_BUS was configured as buildin. [0.746856] kernel BUG at drivers/base/driver.c:153! [0.752418] invalid opcode: [#1] PREEMPT SMP [0.757804] Modules linked in: [0.893985] Call Trace: [0.896729] [] ? ulpi_register_driver+0x21/0x30 [0.903654] [] tusb1210_driver_init+0x10/0x12 [0.910386] [] do_one_initcall+0xd8/0x200 [0.916729] [] kernel_init_freeable+0x196/0x21e [0.923655] [] ? rest_init+0x90/0x90 [0.929509] [] kernel_init+0xe/0xf0 [0.935266] [] ret_from_fork+0x42/0x70 [0.941315] [] ? rest_init+0x90/0x90 Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..01c0c04 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: [PATCH] usb: ulpi: don't register drivers if bus doesn't exist
On 05/21/2015 05:22 AM, David Cohen wrote: Hi, On Wed, May 20, 2015 at 03:33:26PM -0400, Sasha Levin wrote: ULPI registers it's bus at module_init so if the bus fails to register, the A minor comment: s/it's/its/ module will fail to load and all will be well in the world. However, if the ULPI code is built-in rather than a module, the bus initialization may fail but we'd still try to register drivers later onto a non-existant bus, which will panic the kernel. Fix that by checking that the bus was indeed initialized before trying to register drivers on top of it. Signed-off-by: Sasha Levin --- drivers/usb/common/ulpi.c |4 1 file changed, 4 insertions(+) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..0b0a5e7 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -132,6 +132,10 @@ int ulpi_register_driver(struct ulpi_driver *drv) if (!drv->probe) return -EINVAL; + /* Was the bus registered successfully? */ + if (!ulpi_bus.p) + return -ENODEV; + Good catch. Otherwise it may trigger BUG() on driver_register(). I wonder if it would be nice to have a macro for that checking :) Anyway, Reviewed-by: David Cohen Well, I was also encountering panic issue when running it on Intel Bay Trail tablets. In my case, it's due to the execution sequence. When ulpi bus is built-in, driver or device registered before ulpi bus registration. Thanks, Baolu drv->driver.bus = &ulpi_bus; return driver_register(&drv->driver); -- 1.7.10.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 -- 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/1] usb: ulpi: ulpi_init should be used in subsys_initcall
On 05/21/2015 03:33 PM, Heikki Krogerus wrote: On Thu, May 21, 2015 at 01:40:43PM +0800, Lu Baolu wrote: The intention of this change is to fix below kernel panic when USB_ULPI_BUS was configured as buildin. That is actually incorrect. Having the bus build-in does not cause this panic.. [0.746856] kernel BUG at drivers/base/driver.c:153! [0.752418] invalid opcode: [#1] PREEMPT SMP [0.757804] Modules linked in: [0.893985] Call Trace: [0.896729] [] ? ulpi_register_driver+0x21/0x30 [0.903654] [] tusb1210_driver_init+0x10/0x12 [0.910386] [] do_one_initcall+0xd8/0x200 [0.916729] [] kernel_init_freeable+0x196/0x21e [0.923655] [] ? rest_init+0x90/0x90 [0.929509] [] kernel_init+0xe/0xf0 [0.935266] [] ret_from_fork+0x42/0x70 [0.941315] [] ? rest_init+0x90/0x90 This happens if the PHY drivers are build-in. If the bus is build-in, but the drivers are modules, you are still fine. I ever tried the config of bus "=y" and driver "=n". It results in panic as well. The call trace looks like below. 1.058876] [] device_add+0x402/0x640 [1.064829] [] device_register+0x1e/0x30 [1.071072] [] ulpi_register_interface+0x14c/0x1f0 [1.078291] [] dwc3_ulpi_init+0x24/0x60 [1.084437] [] dwc3_probe+0x802/0x1650 [1.090487] [] platform_drv_probe+0x34/0xa0 [1.097022] [] driver_probe_device+0x209/0x4b0 [1.103850] [] ? driver_probe_device+0x4b0/0x4b0 [1.110871] [] __device_attach+0x3b/0x40 [1.117114] [] bus_for_each_drv+0x63/0xa0 [1.123454] [] device_attach+0x98/0xb0 [1.129503] [] bus_probe_device+0xa0/0xc0 [1.135843] [] device_add+0x46f/0x640 [1.141799] [] ? __insert_resource+0x60/0x150 [1.148530] [] platform_device_add+0xd0/0x2b0 [1.155260] [] dwc3_pci_probe+0xf6/0x2c0 [1.161505] [] pci_device_probe+0x8c/0xf0 [1.167846] [] driver_probe_device+0x209/0x4b0 [1.174673] [] __driver_attach+0x9b/0xa0 [1.180917] [] ? __device_attach+0x40/0x40 [1.187354] [] bus_for_each_dev+0x6b/0xb0 [1.193694] [] driver_attach+0x1e/0x20 [1.199742] [] bus_add_driver+0x180/0x250 [1.206086] [] ? ftrace_define_fields_dwc3_log_trb+0x126/0x126 [1.214474] [] driver_register+0x64/0xf0 [1.220718] [] __pci_register_driver+0x4b/0x50 [1.227546] [] dwc3_pci_driver_init+0x19/0x1b [1.234277] [] do_one_initcall+0xd8/0x200 [1.240619] [] kernel_init_freeable+0x196/0x21e [1.247545] [] ? rest_init+0x90/0x90 [1.253399] [] kernel_init+0xe/0xf0 [1.259156] [] ret_from_fork+0x42/0x70 [1.265205] [] ? rest_init+0x90/0x90 Maybe it would have been better to explain that this is addressing an issue with the execution sequence, and consider Sasha's patch as the actual fix for panic. Fair enough. I will resend the patch. Thanks guys, Thanks, Baolu -- 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 1/1] usb: ulpi: don't register drivers if bus doesn't exist
ULPI registers its bus at module_init, so if the bus fails to register, the module will fail to load and all will be well in the world. However, if the ULPI code is built-in rather than a module, the bus initialization may fail, but we'd still try to register drivers later onto a non-existent bus, which will panic the kernel. Fix that by checking that the bus was indeed initialized before trying to register drivers on top of it. Signed-off-by: Sasha Levin Signed-off-by: Heikki Krogerus Signed-off-by: Lu Baolu Reported-by: Zhuo Qiuxu Reviewed-by: David Cohen --- drivers/usb/common/ulpi.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..af52b46 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -132,6 +132,10 @@ int ulpi_register_driver(struct ulpi_driver *drv) if (!drv->probe) return -EINVAL; + /* Was the bus registered successfully? */ + if (unlikely(WARN_ON(!ulpi_bus.p))) + return -ENODEV; + drv->driver.bus = &ulpi_bus; return driver_register(&drv->driver); @@ -242,7 +246,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: [PATCH 1/1] usb: ulpi: don't register drivers if bus doesn't exist
Hi Heikki, Sasha and others, Please ignore this patch. I should not squash these two patches into one and sign it off behalf of other people. I apologize for this and I'm sorry if this lets you feel affronted. Thanks, Baolu On 05/21/2015 04:57 PM, Lu Baolu wrote: ULPI registers its bus at module_init, so if the bus fails to register, the module will fail to load and all will be well in the world. However, if the ULPI code is built-in rather than a module, the bus initialization may fail, but we'd still try to register drivers later onto a non-existent bus, which will panic the kernel. Fix that by checking that the bus was indeed initialized before trying to register drivers on top of it. Signed-off-by: Sasha Levin Signed-off-by: Heikki Krogerus Signed-off-by: Lu Baolu Reported-by: Zhuo Qiuxu Reviewed-by: David Cohen --- drivers/usb/common/ulpi.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..af52b46 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -132,6 +132,10 @@ int ulpi_register_driver(struct ulpi_driver *drv) if (!drv->probe) return -EINVAL; + /* Was the bus registered successfully? */ + if (unlikely(WARN_ON(!ulpi_bus.p))) + return -ENODEV; + drv->driver.bus = &ulpi_bus; return driver_register(&drv->driver); @@ -242,7 +246,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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 v2 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
Many drivers and modules depend on ULPI bus registeration to register ULPI interfaces and drivers. It's more appropriate to register ULPI bus in subsys_initcall instead of module_init. Kernel panic has been reported with some kind of kernel config. [0.746856] kernel BUG at drivers/base/driver.c:153! [0.752418] invalid opcode: [#1] PREEMPT SMP [0.757804] Modules linked in: [0.893985] Call Trace: [0.896729] [] ? ulpi_register_driver+0x21/0x30 [0.903654] [] tusb1210_driver_init+0x10/0x12 [0.910386] [] do_one_initcall+0xd8/0x200 [0.916729] [] kernel_init_freeable+0x196/0x21e [0.923655] [] ? rest_init+0x90/0x90 [0.929509] [] kernel_init+0xe/0xf0 [0.935266] [] ret_from_fork+0x42/0x70 [0.941315] [] ? rest_init+0x90/0x90 This patch fixes this kind of kernel panic by putting ulpi_init in subsys_initcall(). Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..01c0c04 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: [PATCH v2 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
On 05/22/2015 11:11 AM, David Cohen wrote: On Thu, May 21, 2015 at 08:09:54PM -0700, David Cohen wrote: Hi, On Fri, May 22, 2015 at 10:07:05AM +0800, Lu Baolu wrote: Many drivers and modules depend on ULPI bus registeration to register ULPI interfaces and drivers. It's more appropriate to register ULPI bus in subsys_initcall instead of module_init. Kernel panic has been reported with some kind of kernel config. Even though I agree subsys_initcall is better to register ulpi bus, it's still no excuse to have kernel panic. What about ULPI bus being compiled as module? No kernel panic if ULPI is built as a module. IMHO this is avoiding the proper kernel panic fix which should be failing gracefully (or defer probe) from tusb1210 driver. Maybe I need to express myself better :) IMHO we should not consider work done with this patch only. It's still incomplete. I am with you on that we should know the real problem. I could go ahead with further debugging. Do you have any suggestions about which direction should I go? Br, David Thank you, -Baolu -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
On 05/22/2015 02:46 PM, Lu, Baolu wrote: On 05/22/2015 11:11 AM, David Cohen wrote: On Thu, May 21, 2015 at 08:09:54PM -0700, David Cohen wrote: Hi, On Fri, May 22, 2015 at 10:07:05AM +0800, Lu Baolu wrote: Many drivers and modules depend on ULPI bus registeration to register ULPI interfaces and drivers. It's more appropriate to register ULPI bus in subsys_initcall instead of module_init. Kernel panic has been reported with some kind of kernel config. Even though I agree subsys_initcall is better to register ulpi bus, it's still no excuse to have kernel panic. What about ULPI bus being compiled as module? No kernel panic if ULPI is built as a module. IMHO this is avoiding the proper kernel panic fix which should be failing gracefully (or defer probe) from tusb1210 driver. Maybe I need to express myself better :) IMHO we should not consider work done with this patch only. It's still incomplete. I am with you on that we should know the real problem. I could go ahead with further debugging. Do you have any suggestions about which direction should I go? I forgot to mention that the panic was found in an Android environment. The kernel version is v4.1-rc3. Br, David Thank you, -Baolu -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 v3 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
Phy drivers and the ulpi interface providers depend on the registeration of the ulpi bus. Ulpi registers the bus in module_init(). This could result in a load order issue, i.e. ulpi phy drivers or the ulpi interface providers loading before the bus registeration. This patch fixes this load order issue by putting ulpi_init in subsys_initcall(). Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..01c0c04 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: [PATCH v3 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
On 05/23/2015 12:08 AM, David Cohen wrote: Hi, On Fri, May 22, 2015 at 07:29:15PM +0800, Lu Baolu wrote: Phy drivers and the ulpi interface providers depend on the registeration of the ulpi bus. Ulpi registers the bus in module_init(). This could result in a load order issue, i.e. It's still not an issue :( I'd say "unnecessary probe delays". I managed to boot a kernel built from the top of Felipe's remotes/origin/next branch under an Ubuntu environment on Intel's Bay Trail tablet. The same panic (as I found in the Android environment previously) shows up as well. And if I replace module_init() with sys_initcall(), the panic disappears. Thanks, -Baolu But of cource it's Felipe's call :) Description looks better now. BR, David ulpi phy drivers or the ulpi interface providers loading before the bus registeration. This patch fixes this load order issue by putting ulpi_init in subsys_initcall(). Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..01c0c04 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: [Bulk] seagate SRD00f2 expansion 4Tb desktop drive does not work on USB 3.0 Part 2 xhci-debug
On 05/23/2015 10:00 PM, Donald Harter wrote: May 23 08:52:05 pc_u kernel: [53875.075976] xhci_hcd :00:14.0: Port Status Change Event for port 3 May 23 08:52:05 pc_u kernel: [53875.075979] xhci_hcd :00:14.0: port resume event for port 3 May 23 08:52:05 pc_u kernel: [53875.075981] xhci_hcd :00:14.0: resume HS port 3 May 23 08:52:05 pc_u kernel: [53875.075983] xhci_hcd :00:14.0: handle_port_status: starting port polling. May 23 08:52:05 pc_u kernel: [53875.135221] xhci_hcd :00:14.0: Resume USB2 port 3 May 23 08:52:05 pc_u kernel: [53875.135230] xhci_hcd :00:14.0: Port Status Change Event for port 3 May 23 08:52:05 pc_u kernel: [53875.135240] xhci_hcd :00:14.0: get port status, actual port 2 status = 0xfe3 May 23 08:52:05 pc_u kernel: [53875.135241] xhci_hcd :00:14.0: Get port status returned 0x40503 May 23 08:52:05 pc_u kernel: [53875.135262] xhci_hcd :00:14.0: clear port suspend/resume change, actual port 2 status = 0xe03 May 23 08:52:05 pc_u kernel: [53875.151222] xhci_hcd :00:14.0: get port status, actual port 2 status = 0xe03 May 23 08:52:05 pc_u kernel: [53875.151224] xhci_hcd :00:14.0: Get port status returned 0x503 May 23 08:52:05 pc_u kernel: [53875.255453] xhci_hcd :00:14.0: // Ding dong! May 23 08:52:05 pc_u kernel: [53875.255496] xhci_hcd :00:14.0: Slot 15 output ctx = 0x4018f1000 (dma) May 23 08:52:05 pc_u kernel: [53875.255498] xhci_hcd :00:14.0: Slot 15 input ctx = 0x401e2a000 (dma) May 23 08:52:05 pc_u kernel: [53875.255499] xhci_hcd :00:14.0: Set slot id 15 dcbaa entry 8804028f2078 to 0x4018f1000 May 23 08:52:06 pc_u kernel: [53875.343311] usb 3-3.4: new high-speed USB device number 14 using xhci_hcd May 23 08:52:06 pc_u kernel: [53875.343314] xhci_hcd :00:14.0: Set root hub portnum to 3 May 23 08:52:06 pc_u kernel: [53875.343315] xhci_hcd :00:14.0: Set fake root hub portnum to 3 May 23 08:52:06 pc_u kernel: [53875.343315] xhci_hcd :00:14.0: udev->tt = (null) May 23 08:52:06 pc_u kernel: [53875.343316] xhci_hcd :00:14.0: udev->ttport = 0x0 May 23 08:52:06 pc_u kernel: [53875.343317] xhci_hcd :00:14.0: Slot ID 15 Input Context: It looks like USB device doesn't complete resuming while host controller tries to assign USB address to it. Do you mind trying below change? diff --git a/include/linux/usb.h b/include/linux/usb.h index 447fe29..660e2d7 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -229,7 +229,7 @@ void usb_put_intf(struct usb_interface *intf); * should cope with both LPJ calibration errors and devices not following every * detail of the USB Specification. */ -#define USB_RESUME_TIMEOUT 40 /* ms */ +#define USB_RESUME_TIMEOUT 100 /* ms */ /** * struct usb_interface_cache - long-term representation of a device interface Thanks, -Baolu -- 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: [Bulk] seagate SRD00f2 expansion 4Tb desktop drive does not work on USB 3.0 Part 2 xhci-debug SOLVED
es2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 0 Command pipe (0x01) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 0 MaxStreams 32 Status pipe (0x02) Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x0a EP 10 OUT bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 7 MaxStreams 32 Data-out pipe (0x04) Endpoint Descriptor: bLength 7 bDescriptorType 5 : bEndpointAddress 0x83 EP 3 IN bmAttributes2 Transfer TypeBulk Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 0 bMaxBurst 7 MaxStreams 32 Data-in pipe (0x03) Binary Object Store Descriptor: bLength 5 bDescriptorType15 wTotalLength 22 bNumDeviceCaps 2 USB 2.0 Extension Device Capability: bLength 7 bDescriptorType16 bDevCapabilityType 2 bmAttributes 0x0002 Link Power Management (LPM) Supported SuperSpeed USB Device Capability: bLength10 bDescriptorType16 bDevCapabilityType 3 bmAttributes 0x00 wSpeedsSupported 0x000e Device can operate at Full Speed (12Mbps) Device can operate at High Speed (480Mbps) Device can operate at SuperSpeed (5Gbps) bFunctionalitySupport 1 Lowest fully-functional device speed is Full Speed (12Mbps) bU1DevExitLat 10 micro seconds bU2DevExitLat 512 micro seconds Device Status: 0x0001 Self Powered On 05/25/2015 05:34 AM, Lu, Baolu wrote: On 05/23/2015 10:00 PM, Donald Harter wrote: May 23 08:52:05 pc_u kernel: [53875.075976] xhci_hcd :00:14.0: Port Status Change Event for port 3 May 23 08:52:05 pc_u kernel: [53875.075979] xhci_hcd :00:14.0: port resume event for port 3 May 23 08:52:05 pc_u kernel: [53875.075981] xhci_hcd :00:14.0: resume HS port 3 May 23 08:52:05 pc_u kernel: [53875.075983] xhci_hcd :00:14.0: handle_port_status: starting port polling. May 23 08:52:05 pc_u kernel: [53875.135221] xhci_hcd :00:14.0: Resume USB2 port 3 May 23 08:52:05 pc_u kernel: [53875.135230] xhci_hcd :00:14.0: Port Status Change Event for port 3 May 23 08:52:05 pc_u kernel: [53875.135240] xhci_hcd :00:14.0: get port status, actual port 2 status = 0xfe3 May 23 08:52:05 pc_u kernel: [53875.135241] xhci_hcd :00:14.0: Get port status returned 0x40503 May 23 08:52:05 pc_u kernel: [53875.135262] xhci_hcd :00:14.0: clear port suspend/resume change, actual port 2 status = 0xe03 May 23 08:52:05 pc_u kernel: [53875.151222] xhci_hcd :00:14.0: get port status, actual port 2 status = 0xe03 May 23 08:52:05 pc_u kernel: [53875.151224] xhci_hcd :00:14.0: Get port status returned 0x503 May 23 08:52:05 pc_u kernel: [53875.255453] xhci_hcd :00:14.0: // Ding dong! May 23 08:52:05 pc_u kernel: [53875.255496] xhci_hcd :00:14.0: Slot 15 output ctx = 0x4018f1000 (dma) May 23 08:52:05 pc_u kernel: [53875.255498] xhci_hcd :00:14.0: Slot 15 input ctx = 0x401e2a000 (dma) May 23 08:52:05 pc_u kernel: [53875.255499] xhci_hcd :00:14.0: Set slot id 15 dcbaa entry 8804028f2078 to 0x4018f1000 May 23 08:52:06 pc_u kernel: [53875.343311] usb 3-3.4: new high-speed USB device number 14 using xhci_hcd May 23 08:52:06 pc_u kernel: [53875.343314] xhci_hcd :00:14.0: Set root hub portnum to 3 May 23 08:52:06 pc_u kernel: [53875.343315] xhci_hcd :00:14.0: Set fake root hub portnum to 3 May 23 08:52:06 pc_u kernel: [53875.343315] xhci_hcd :00:14.0: udev->tt = (null) May 23 08:52:06 pc_u kernel: [53875.343316] xhci_hcd :00:14.0: udev->ttport = 0x0 May 23 08:52:06 pc_u kernel: [53875.343317] xhci_hcd :00:14.0: Slot ID 15 Input Context: It looks like USB device doesn't complete resuming while host controller tries to assign USB address to it. Do you mind trying below change? diff --git a/include/l
Re: [PATCH v3 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
On 05/26/2015 10:50 PM, Felipe Balbi wrote: Hi, On Mon, May 25, 2015 at 02:24:00PM +0800, Lu, Baolu wrote: On 05/23/2015 12:08 AM, David Cohen wrote: Hi, On Fri, May 22, 2015 at 07:29:15PM +0800, Lu Baolu wrote: Phy drivers and the ulpi interface providers depend on the registeration of the ulpi bus. Ulpi registers the bus in module_init(). This could result in a load order issue, i.e. It's still not an issue :( I'd say "unnecessary probe delays". I managed to boot a kernel built from the top of Felipe's remotes/origin/next branch under an Ubuntu environment on Intel's Bay Trail tablet. The same panic (as I found in the Android environment previously) shows up as well. And if I replace module_init() with sys_initcall(), the panic disappears. the problem is something else... Moving things around in the init levels is just a workaround for another issue. Seems like there's some missing EPROBE_DEFER somewhere. Yes, I agree. Heikki, I assume "missing EPROBE_DEFER issue" will be fixed by Sasha's patch. I will resend the patch with a new commit message. Thanks, Baolu -- 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 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
Phy drivers and the ulpi interface providers depend on the registration of the ulpi bus. Ulpi registers the bus in module_init(). This could cause unnecessary probe delays. Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu Acked-by: Heikki Krogerus --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..01c0c04 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: [PATCH v4 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
On 05/28/2015 12:53 AM, David Cohen wrote: Hi, On Tue, May 26, 2015 at 07:37:02PM -0700, Greg Kroah-Hartman wrote: On Wed, May 27, 2015 at 09:45:37AM +0800, Lu Baolu wrote: Phy drivers and the ulpi interface providers depend on the registration of the ulpi bus. Ulpi registers the bus in module_init(). This could cause unnecessary probe delays. What do you mean by "probe delays"? I believe he meant the bus users' probe delays. i.e. unnecessary -EPROBE_DEFER happening on ulpi_drivers in case they're registered before ulpi bus itself. Is that correct, Baolu? Yes. Br, David -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
On 06/04/2015 08:17 PM, Heikki Krogerus wrote: Hi Baolu, On Thu, May 28, 2015 at 08:50:12AM +0800, Lu, Baolu wrote: On 05/28/2015 12:53 AM, David Cohen wrote: Hi, On Tue, May 26, 2015 at 07:37:02PM -0700, Greg Kroah-Hartman wrote: On Wed, May 27, 2015 at 09:45:37AM +0800, Lu Baolu wrote: Phy drivers and the ulpi interface providers depend on the registration of the ulpi bus. Ulpi registers the bus in module_init(). This could cause unnecessary probe delays. What do you mean by "probe delays"? I believe he meant the bus users' probe delays. i.e. unnecessary -EPROBE_DEFER happening on ulpi_drivers in case they're registered before ulpi bus itself. Is that correct, Baolu? Yes. Could you prepare one more version of this patche with the change log included. Sure. I will resent it soon. Thanks, -- 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 v5 1/1] usb: ulpi: ulpi_init should be executed in subsys_initcall
Phy drivers and the ulpi interface providers depend on the registration of the ulpi bus. Ulpi registers the bus in module_init(). This could cause unnecessary bus users' probe delays. i.e. unnecessary -EPROBE_DEFER happening on ulpi_drivers in case they're registered before ulpi bus itself. Reported-by: Zhuo Qiuxu Signed-off-by: Lu Baolu Acked-by: Heikki Krogerus --- drivers/usb/common/ulpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) v0->v5 change log: Various changes in the commit description. diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c index 0e6f968..01c0c04 100644 --- a/drivers/usb/common/ulpi.c +++ b/drivers/usb/common/ulpi.c @@ -242,7 +242,7 @@ static int __init ulpi_init(void) { return bus_register(&ulpi_bus); } -module_init(ulpi_init); +subsys_initcall(ulpi_init); static void __exit ulpi_exit(void) { -- 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
Re: USB3 external HDD not recognized [regression]
On 06/06/2015 04:56 AM, Ralf Jung wrote: Hi, I got some untested and not yet reviewed usb3 resume race fixes from Zhuang Jin Can If you can try them out and see if they help it would be great. They are sitting in a topic branch called "xhci_usb3_pm_fixes" in my tree: (5 extra patches on top of current usb-linus) git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git xhci_usb3_pm_fixes This is my production and (main and only) work machine. If you tell me testing that branch is safe and won't mess up my file systems or hardware, I can give it a try. I tested that branch (HEAD commit 190f6b0b), and the issue is still the same. Directly after booting, if I plug in the disk, it doesn't work (with the "root hub lost power" error). Removing the cable, setting power/control to "on" for all PCI devices, then plugging it back in, the disk works fine. "root hub lost power" is not an error message. It shows when host controller needs to reset on a resume. Do you mind sending a dmesg data with usbcore and xhci_hcd dynamic debug enabled? Sorry if you have posted one. echo -n 'module xhci_hcd +p' > /sys/kernel/debug/dynamic_debug/control echo -n 'module usbcore +p' > /sys/kernel/debug/dynamic_debug/control Thanks, Baolu What was the model of the USB3 disk again? some Seagate Expansion Disk? I'll see If I can find one of those myself somehow lsusb says: Bus 003 Device 002: ID 0bc2:3312 Seagate RSS LLC The package says "Seagate Expansion 5TB". But I'm not sure these are all using the same controller; for example, I also have a "Seagate Expansion 3TB" that works fine. (I'm removing Wang, Yu from the recipients, as I keep getting bounces from that address.) Kind regards, Ralf -- 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 -- 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 1/1] usb: core: lpm: set lpm_capable for root hub device
Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu --- drivers/usb/core/hcd.c | 6 ++ drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 45a915c..48b208d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1032,6 +1032,12 @@ static int register_root_hub(struct usb_hcd *hcd) } } + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { + retval = usb_get_bos_descriptor(usb_dev); + if (!retval) + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } + retval = usb_new_device (usb_dev); if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3b71516..884d702 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26..d5668c4 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -82,6 +82,7 @@ extern int usb_runtime_suspend(struct device *dev); extern int usb_runtime_resume(struct device *dev); extern int usb_runtime_idle(struct device *dev); extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); +extern int usb_device_supports_lpm(struct usb_device *udev); #else -- 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
Re: [PATCH 1/1] usb: core: lpm: set lpm_capable for root hub device
On 06/12/2015 12:32 PM, Greg Kroah-Hartman wrote: On Fri, Jun 12, 2015 at 09:29:37AM +0800, Lu Baolu wrote: Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu --- drivers/usb/core/hcd.c | 6 ++ drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 45a915c..48b208d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1032,6 +1032,12 @@ static int register_root_hub(struct usb_hcd *hcd) } } + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { Why are you treating a binary coded value as a hex number to compare against? The value of the bcdUSB field is 0xJJMN for version JJ.M.N, where JJ – major version number, M – minor version number, N – sub-minor version number I saw several places in usb core where it is treated as a hex and check the version requirement like this. Do you want me to separate it into three numbers and check major/minor/sub-minor versions separately? Thanks, Baolu -- 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 -- 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/1] usb: core: lpm: set lpm_capable for root hub device
On 06/13/2015 01:43 AM, Alan Stern wrote: On Fri, 12 Jun 2015, Lu Baolu wrote: Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu --- drivers/usb/core/hcd.c | 6 ++ drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 45a915c..48b208d 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1032,6 +1032,12 @@ static int register_root_hub(struct usb_hcd *hcd) } } + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { + retval = usb_get_bos_descriptor(usb_dev); + if (!retval) + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } + This should be integrated with the code immediately above it, which also calls usb_get_bos_descriptor(). In fact, maybe you should simply change the existing code to check bcdUSB >= 0x0201 instead of speed == USB_SPEED_SUPER. I agree with you and will change it in v2 patch. retval = usb_new_device (usb_dev); if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3b71516..884d702 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26..d5668c4 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -82,6 +82,7 @@ extern int usb_runtime_suspend(struct device *dev); extern int usb_runtime_resume(struct device *dev); extern int usb_runtime_idle(struct device *dev); extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); +extern int usb_device_supports_lpm(struct usb_device *udev); #else This will break if you build it with CONFIG_PM disabled. Yes. Will fix it in v2 patch. Alan Stern Thank you, Baolu -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 v2 1/1] usb: core: lpm: set lpm_capable for root hub device
Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu --- drivers/usb/core/hcd.c | 7 +-- drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 6 ++ 3 files changed, 12 insertions(+), 3 deletions(-) v1->v2 change log: 1. two code blocks merged (Alan's feedback) 2. fix build error when CONFIG_PM is not set (Alan's feedback) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 45a915c..1c1385e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1022,9 +1022,12 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; } - if (usb_dev->speed == USB_SPEED_SUPER) { + + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(usb_dev); - if (retval < 0) { + if (!retval) { + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } else if (usb_dev->speed == USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3b71516..884d702 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26..d54a669 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -82,6 +82,7 @@ extern int usb_runtime_suspend(struct device *dev); extern int usb_runtime_resume(struct device *dev); extern int usb_runtime_idle(struct device *dev); extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); +extern int usb_device_supports_lpm(struct usb_device *udev); #else @@ -106,6 +107,11 @@ static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) return 0; } +static inline int usb_device_supports_lpm(struct usb_device *udev) +{ + return 0; +} + #endif extern struct bus_type usb_bus_type; -- 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
Re: [PATCH v2 1/1] usb: core: lpm: set lpm_capable for root hub device
On 06/13/2015 11:00 PM, Alan Stern wrote: On Sat, 13 Jun 2015, Lu Baolu wrote: Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu --- --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -82,6 +82,7 @@ extern int usb_runtime_suspend(struct device *dev); extern int usb_runtime_resume(struct device *dev); extern int usb_runtime_idle(struct device *dev); extern int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable); +extern int usb_device_supports_lpm(struct usb_device *udev); #else @@ -106,6 +107,11 @@ static inline int usb_set_usb2_hardware_lpm(struct usb_device *udev, int enable) return 0; } +static inline int usb_device_supports_lpm(struct usb_device *udev) +{ + return 0; +} + #endif extern struct bus_type usb_bus_type; In fact, usb_device_supports_lpm() is compiled even when CONFIG_PM isn't set. Maybe this should be changed. But if you don't want to change it now, you need to put the declaration outside the "#ifdef CONFIG_PM" region. As it is, your patch is still broken (did you try building it with CONFIG_PM unset?). I am sorry for this silly mistake. I will move it out of CONFIG_PM region. I tried building with CONFIG_PM unset. But it turns out that CONFIG_PM was auto selected by some other items. I will test my next version of patch with CONFIG_PM *really* unset before sending it out. Thanks, Baolu 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
[PATCH v3 1/1] usb: core: lpm: set lpm_capable for root hub device
Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu --- drivers/usb/core/hcd.c | 7 +-- drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) v1->v2 change log: 1. two code blocks merged 2. fix build error when CONFIG_PM is not set v2->v3 change log: 1. further fix of build error when CONFIG_PM is not set diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 45a915c..1c1385e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1022,9 +1022,12 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; } - if (usb_dev->speed == USB_SPEED_SUPER) { + + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(usb_dev); - if (retval < 0) { + if (!retval) { + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } else if (usb_dev->speed == USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3b71516..884d702 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26..457255a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -65,6 +65,7 @@ extern int usb_hub_init(void); extern void usb_hub_cleanup(void); extern int usb_major_init(void); extern void usb_major_cleanup(void); +extern int usb_device_supports_lpm(struct usb_device *udev); #ifdef CONFIG_PM -- 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 1/1] usb: core: lpm: set lpm_capable for root hub device
Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM.") removed the code to set lpm_capable for USB 3.0 super-speed root hub. The intention of that change was to avoid touching usb core internal field, a.k.a. lpm_capable, and let usb core to set it by checking U1 and U2 exit latency values in the descriptor. Usb core checks and sets lpm_capable in hub_port_init(). Unfortunately, root hub is a special usb device as it has no parent. Hub_port_init() will never be called for a root hub device. That means lpm_capable will by no means be set for the root hub. As the result, lpm isn't functional at all in Linux kernel. This patch add the code to check and set lpm_capable when registering a root hub device. It could be back-ported to kernels as old as v3.15, that contains the Commit 25cd2882e2fc ("usb/xhci: Change how we indicate a host supports Link PM."). Cc: sta...@vger.kernel.org # 3.15 Reported-by: Kevin Strasser Signed-off-by: Lu Baolu Acked-by: Alan Stern --- drivers/usb/core/hcd.c | 7 +-- drivers/usb/core/hub.c | 2 +- drivers/usb/core/usb.h | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) v1->v2 change log: 1. two code blocks merged 2. fix build error when CONFIG_PM is not set v2->v3 change log: 1. further fix of build error when CONFIG_PM is not set v3->v4 change log: 1. Add Alan's ACK diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 45a915c..1c1385e 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1022,9 +1022,12 @@ static int register_root_hub(struct usb_hcd *hcd) dev_name(&usb_dev->dev), retval); return (retval < 0) ? retval : -EMSGSIZE; } - if (usb_dev->speed == USB_SPEED_SUPER) { + + if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) { retval = usb_get_bos_descriptor(usb_dev); - if (retval < 0) { + if (!retval) { + usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); + } else if (usb_dev->speed == USB_SPEED_SUPER) { mutex_unlock(&usb_bus_list_lock); dev_dbg(parent_dev, "can't read %s bos descriptor %d\n", dev_name(&usb_dev->dev), retval); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3b71516..884d702 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -122,7 +122,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) return usb_get_intfdata(hdev->actconfig->interface[0]); } -static int usb_device_supports_lpm(struct usb_device *udev) +int usb_device_supports_lpm(struct usb_device *udev) { /* USB 2.1 (and greater) devices indicate LPM support through * their USB 2.0 Extended Capabilities BOS descriptor. diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 7eb1e26..457255a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -65,6 +65,7 @@ extern int usb_hub_init(void); extern void usb_hub_cleanup(void); extern int usb_major_init(void); extern void usb_major_cleanup(void); +extern int usb_device_supports_lpm(struct usb_device *udev); #ifdef CONFIG_PM -- 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
Re: Overly conservative xHCI bandwidth estimation
I could spend some time on this issue a week later. I'd like to check whether there is any bugs in the driver itself. Otherwise, blacklist this specific device for LPM. Thanks, Baolu On 10/21/2015 07:05 AM, Steinar H. Gunderson wrote: On Mon, Sep 28, 2015 at 02:32:13PM +0200, Steinar H. Gunderson wrote: Just so that it doesn't get lost: I've reported issues with this specific device and LPM not too long ago. It's entirely possible that the device somehow is broken, although it works in Windows 7/8/10 and OS X, from what I know, and at least Windows 10 uses USB3 LPM. Perhaps figuring out what's wrong with the ping timeouts would also fix this issue? I'm afraid I don't have any fancy USB analyzer equipment to debug with, though. In any case, I'll reiterate my request to turn off LPM for a specific device, no matter whose fault these specific issues are. :-) Is there anything else I can do to help fixing these issues? (U1/U2 timeouts causing disconnects, and xHCI bandwidth estimation being off.) I've been running with CONFIG_PM=n for a while now, but it is obviously not a good place to be for a laptop. /* Steinar */ -- 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 1/1] usb: xhci: fix checking ep busy for CFC
Function ep_ring_is_processing() checks the dequeue pointer in endpoint context to know whether an endpoint is busy with processing TRBs. This is not correct since dequeue pointer field in an endpoint context is only valid when the endpoint is in Halted or Stopped states. This buggy code causes audio noise when playing sound with USB headset connected to host controllers which support CFC (one of xhci 1.1 features). This patch should exist in stable kernel since v4.3. Reported-and-tested-by: YD Tseng Signed-off-by: Lu Baolu --- drivers/usb/host/xhci-ring.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa83625..2b50d45 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3903,7 +3903,6 @@ static int ep_ring_is_processing(struct xhci_hcd *xhci, struct xhci_ring *ep_ring; struct xhci_ep_ctx *ep_ctx; struct xhci_virt_ep *xep; - dma_addr_t hw_deq; xdev = xhci->devs[slot_id]; xep = &xhci->devs[slot_id]->eps[ep_index]; @@ -3913,9 +3912,7 @@ static int ep_ring_is_processing(struct xhci_hcd *xhci, if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING) return 0; - hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK; - return (hw_deq != - xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue)); + return !list_empty(&ep_ring->td_list); } /* -- 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 07/12] usb: xhci: dbc: handle dbc-configured exit
DbC might exit configured state in some cases (refer to 7.6.4.4 in xHCI spec 1.1). Software needs detect and clear this situation by clearing DCCTRL.DCR and wait until the DbC configured before read or write oprations. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index f51daa4..8a5a51f 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -1153,6 +1153,29 @@ static int xdbc_wait_until_bulk_done(struct xdbc_trb *trb, int loops) return -EIO; } +static int xdbc_wait_until_dbc_configured(void) +{ + int timeout = 0; + u32 reg; + + /* Port exits configured state */ + reg = readl(&xdbcp->xdbc_reg->control); + if (!(reg & CTRL_DRC)) + return 0; + + /* clear run change bit (RW1C) */ + writel(reg | CTRL_DRC, &xdbcp->xdbc_reg->control); + + do { + if (readl(&xdbcp->xdbc_reg->control) & CTRL_DCR) + return 0; + + xdbc_udelay(10); + } while (timeout++ < XDBC_LOOPS); + + return -ETIMEDOUT; +} + static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) { u64 addr; @@ -1167,6 +1190,11 @@ static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) return -EINVAL; } + if (xdbc_wait_until_dbc_configured()) { + xdbc_trace("%s: hardware not ready\n", __func__); + return -EPERM; + } + ring = (read ? &xdbcp->in_ring : &xdbcp->out_ring); trb = ring->enqueue; cycle = ring->cycle_state; -- 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 11/12] usb: serial: usb_debug: add support for dbc debug device
This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu --- drivers/usb/serial/usb_debug.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..d4903b0 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); /* This HW really does not support a serial break, so one will be * emulated when ever the break state is set to true. @@ -71,9 +82,21 @@ static struct usb_serial_driver debug_device = { .process_read_urb = usb_debug_process_read_urb, }; +static struct usb_serial_driver dbc_device = { + .driver = { + .owner =THIS_MODULE, + .name = "xhci_dbc", + }, + .id_table = dbc_id_table, + .num_ports =1, + .bulk_out_size =1024, + .break_ctl =usb_debug_break_ctl, + .process_read_urb = usb_debug_process_read_urb, +}; + static struct usb_serial_driver * const serial_drivers[] = { - &debug_device, NULL + &debug_device, &dbc_device, NULL }; -module_usb_serial_driver(serial_drivers, id_table); +module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_LICENSE("GPL"); -- 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 08/12] usb: xhci: dbc: handle endpoint stall
In case of endpoint stall, software is able to detect the situation by reading DCCTRL.HIT or DCCTRL.HOT bits. DbC follows the normal USB framework to handle endpoint stall. When software detects endpoint stall situation, it should wait until endpoint is recovered before read or write oprations. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 36 1 file changed, 36 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 8a5a51f..aaf655f 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -1176,6 +1176,37 @@ static int xdbc_wait_until_dbc_configured(void) return -ETIMEDOUT; } +static int xdbc_wait_until_epstall_cleared(bool read) +{ + int timeout = 0; + + if (read) { + do { + if (!(readl(&xdbcp->xdbc_reg->control) & CTRL_HIT)) { + xdbcp->in_ep_state = EP_RUNNING; + + return 0; + } + + xdbcp->in_ep_state = EP_HALTED; + xdbc_udelay(10); + } while (timeout++ < XDBC_LOOPS); + } else { + do { + if (!(readl(&xdbcp->xdbc_reg->control) & CTRL_HOT)) { + xdbcp->out_ep_state = EP_RUNNING; + + return 0; + } + + xdbcp->out_ep_state = EP_HALTED; + xdbc_udelay(10); + } while (timeout++ < XDBC_LOOPS); + } + + return -ETIMEDOUT; +} + static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) { u64 addr; @@ -1195,6 +1226,11 @@ static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) return -EPERM; } + if (xdbc_wait_until_epstall_cleared(read)) { + xdbc_trace("%s: endpoint not ready\n", __func__); + return -EPERM; + } + ring = (read ? &xdbcp->in_ring : &xdbcp->out_ring); trb = ring->enqueue; cycle = ring->cycle_state; -- 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 12/12] usb: doc: add document for xHCI DbC driver
Add Documentation/usb/xhci-dbc.txt. This document includes development status and usage guide for USB3 debug port. Signed-off-by: Lu Baolu --- Documentation/usb/xhci-dbc.txt | 325 + MAINTAINERS| 1 + drivers/usb/early/xhci-dbc.c | 3 + 3 files changed, 329 insertions(+) create mode 100644 Documentation/usb/xhci-dbc.txt diff --git a/Documentation/usb/xhci-dbc.txt b/Documentation/usb/xhci-dbc.txt new file mode 100644 index 000..94b75a9 --- /dev/null +++ b/Documentation/usb/xhci-dbc.txt @@ -0,0 +1,325 @@ +xHCI debug capability driver + + Lu Baolu + +Last-updated: September 2015 + + + Contents: + - + * What is xHCI DbC? + * Debug topologies + * Debug stacks + * Port Multiplexing + * Hardware initialization + * External reset + * Port reset + * Interrupt/DMA/Memory during early boot + * Endpoint STALL + * Debug device information + * How to use DbC early printk? + * Limitations + + What is xHCI DbC? + - + +The xHCI Debugging Capability defined in section 7.6 of xHCI spec 1.1 +provides an optional functionality that enables low-level system debug +over USB. It provides a means of connecting two systems where one system +is a Debug Host and the other a Debug Target (System Under Test). The +Debug Capability provides an interface that is completely independent +of the xHCI interface. A Debug Target enumerates as a USB debug device +to the Debug Host, allowing a Debug Host to access a Debug Target through +the standard USB software stack. + + Debug topologies + + +Multiple Debug Targets may be attached to a single Debug Host. Debug +Targets may be connected to any downstream facing port below a Debug +Host (i.e. anywhere in the fabric, root port or external hub puts). +A Debug Target may only connect to a Debug Host through a Root Hub port +of the target. That means connection of a Debug Target to a Debug Host +through the ports of an external hub is not supported. + +Below is a typical connection between Debug Host and Debug target. Two +Debug targets are connected to a single Debug host. + + + +| Debug Host | | Debug Target | +|| || +|xHC without DbC | | xHC with DbC | +|or DbC disabled | | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + || | + ||_| + |_ +| + ___| +| HUB | | Debug Target | +|| || +| Superspeed hub | | xHC with DbC | +|| | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + | | + |_| + + Debug stacks + + +Below is a software stack diagram of both Debug Host and Debug Target. + + +| Debug Host | | Debug Target | +|| || +| debug App| || +|| | system debug | +| usb_debug| | hooks | +|| || +|usbcore | || +|| |debug capability| +|xhci_hcd| | driver | +|| || +|xHC without DbC | | xHC with DbC | +|or DbC disabled | | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + | | + |_| + + + Port Multiplexing + - + +A debug port is always multiplexed with the first xHCI root hub port. +Whenever debug capability is supported and enabled, and the first root +hub port is detected to be connected to a downstream super-speed port +of a Debug Host, the root hub port is assigned to the debug capability +and operating
[PATCH 09/12] x86: early_printk: add USB3 debug port earlyprintk support
Add support for early printk by writing debug messages to the USB3 debug port. Users can use this type of early printk by specifying kernel parameter of "earlyprintk=xdbc". This gives users a chance of providing debug output. Signed-off-by: Lu Baolu --- Documentation/kernel-parameters.txt | 1 + arch/x86/kernel/early_printk.c | 5 + drivers/usb/early/xhci-dbc.c| 43 + include/linux/usb/xhci-dbc.h| 5 + 4 files changed, 54 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 22a4b68..b65b07f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1032,6 +1032,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] earlyprintk=pciserial,bus:device.function[,baudrate] + earlyprintk=xdbc[xhciController#] earlyprintk is useful when the kernel crashes before the normal console is initialized. It is not enabled by diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index eec40f5..5341a16 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -373,6 +374,10 @@ static int __init setup_early_printk(char *buf) if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4)) early_console_register(&early_dbgp_console, keep); #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!strncmp(buf, "xdbc", 4) && !early_xdbc_init(buf + 4)) + early_console_register(&early_xdbc_console, keep); +#endif #ifdef CONFIG_HVC_XEN if (!strncmp(buf, "xen", 3)) early_console_register(&xenboot_console, keep); diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index aaf655f..68a7139 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -10,6 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -1332,3 +1333,45 @@ int xdbc_bulk_write(const char *bytes, int size) return ret; } + +/* + * Start a bulk-in or bulk-out transfer, wait until transfer completion + * or error. Return the count of actually transferred bytes or error. + */ +static void early_xdbc_write(struct console *con, const char *str, u32 n) +{ + int chunk, ret; + static char buf[XDBC_MAX_PACKET]; + int use_cr = 0; + + if (!xdbcp->xdbc_reg) + return; + memset(buf, 0, XDBC_MAX_PACKET); + while (n > 0) { + for (chunk = 0; chunk < XDBC_MAX_PACKET && n > 0; +str++, chunk++, n--) { + if (!use_cr && *str == '\n') { + use_cr = 1; + buf[chunk] = '\r'; + str--; + n++; + continue; + } + if (use_cr) + use_cr = 0; + buf[chunk] = *str; + } + if (chunk > 0) { + ret = xdbc_bulk_write(buf, chunk); + if (ret < 0) + break; + } + } +} + +struct console early_xdbc_console = { + .name = "earlyxdbc", + .write =early_xdbc_write, + .flags =CON_PRINTBUFFER, + .index =-1, +}; diff --git a/include/linux/usb/xhci-dbc.h b/include/linux/usb/xhci-dbc.h index 289ba58..a556eb8 100644 --- a/include/linux/usb/xhci-dbc.h +++ b/include/linux/usb/xhci-dbc.h @@ -216,4 +216,9 @@ struct xdbc_state { #definexdbc_read64(regs) xhci_read_64(NULL, (regs)) #definexdbc_write64(val, regs) xhci_write_64(NULL, (val), (regs)) +#ifdef CONFIG_EARLY_PRINTK_XDBC +extern int early_xdbc_init(char *s); +extern struct console early_xdbc_console; +#endif /* CONFIG_EARLY_PRINTK_XDBC */ + #endif /* __LINUX_XHCI_DBC_H */ -- 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 10/12] usb: xhci: dbc: add handshake between debug target and host
After DbC setup, debug target needs to wait until tty driver and application (e.g. mincom) on debug taget start. Otherwise, out messages might be ignored. This patch adds a ping/pong mechanism between debug target and host. Debug target will be waiting there until user presses 'Y' or 'y' in the tty application. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 68a7139..b75c523 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -32,6 +32,9 @@ static struct xdbc_state xdbc_stat; static struct xdbc_state *xdbcp = &xdbc_stat; +static int early_xdbc_read(struct console *con, char *str, unsigned n); +static void early_xdbc_write(struct console *con, const char *str, u32 n); + #ifdef DBC_DEBUG #defineXDBC_DEBUG_BUF_SIZE (PAGE_SIZE * 32) #defineMSG_MAX_LINE128 @@ -873,8 +876,12 @@ int __init early_xdbc_init(char *s) { u32 bus = 0, dev = 0, func = 0; unsigned long dbgp_num = 0; + char *ping = "Press Y to continue...\n"; + char pong[64]; + size_t size; u32 offset; int ret; + int retry = 20; if (!early_pci_allowed()) return -EPERM; @@ -917,6 +924,21 @@ int __init early_xdbc_init(char *s) return ret; } + while (retry > 0) { + early_xdbc_write(NULL, ping, strlen(ping)); + size = early_xdbc_read(NULL, pong, 64); + if (size > 0) { + xdbc_trace("%s: pong message: %s\n", __func__, pong); + if (pong[0] == 'Y' || pong[0] == 'y') + break; + } else { + xdbc_trace("%s: pong message error %d\n", + __func__, size); + } + + retry--; + } + return 0; } @@ -1338,6 +1360,11 @@ int xdbc_bulk_write(const char *bytes, int size) * Start a bulk-in or bulk-out transfer, wait until transfer completion * or error. Return the count of actually transferred bytes or error. */ +static int early_xdbc_read(struct console *con, char *str, unsigned n) +{ + return xdbc_bulk_read(str, n, 0); +} + static void early_xdbc_write(struct console *con, const char *str, u32 n) { int chunk, ret; -- 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 06/12] usb: xhci: dbc: add bulk out and bulk in interfaces
This patch adds interfaces for bulk out and bulk in ops. These interfaces could be used to implement early printk bootconsole or hook to various system debuggers. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 373 +++ include/linux/usb/xhci-dbc.h | 30 2 files changed, 403 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index b36a527..f51daa4 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -219,11 +219,21 @@ static void xdbc_dbg_dump_data(char *str) xdbc_dbg_dump_string("String Descriptor:"); } +static void xdbc_dbg_dump_trb(struct xdbc_trb *trb, char *str) +{ + xdbc_trace("DBC trb: %s\n", str); + xdbc_trace("@%016llx %08x %08x %08x %08x\n", (u64)__pa(trb), + le32_to_cpu(trb->field[0]), + le32_to_cpu(trb->field[1]), + le32_to_cpu(trb->field[2]), + le32_to_cpu(trb->field[3])); +} #else static inline void xdbc_trace(const char *fmt, ...) { } static inline void xdbc_dump_debug_buffer(void) { } static inline void xdbc_dbg_dump_regs(char *str) { } static inline void xdbc_dbg_dump_data(char *str) { } +static inline void xdbc_dbg_dump_trb(struct xdbc_trb *trb, char *str) { } #endif /* DBC_DEBUG */ /* @@ -334,6 +344,7 @@ static void *xdbc_get_page(dma_addr_t *dma_addr, static char in_ring_page[PAGE_SIZE] __aligned(PAGE_SIZE); static char out_ring_page[PAGE_SIZE] __aligned(PAGE_SIZE); static char table_page[PAGE_SIZE] __aligned(PAGE_SIZE); + static char bulk_buf_page[PAGE_SIZE] __aligned(PAGE_SIZE); switch (type) { case XDBC_PAGE_EVENT: @@ -348,6 +359,9 @@ static void *xdbc_get_page(dma_addr_t *dma_addr, case XDBC_PAGE_TABLE: virt = (void *)table_page; break; + case XDBC_PAGE_BUFFER: + virt = (void *)bulk_buf_page; + break; default: return NULL; } @@ -707,6 +721,12 @@ static int xdbc_mem_init(void) dev_info = cpu_to_le32((XDBC_DEVICE_REV << 16) | XDBC_PRODUCT_ID); writel(dev_info, &xdbcp->xdbc_reg->devinfo2); + /* get and store the transfer buffer */ + xdbcp->out_buf = xdbc_get_page(&xdbcp->out_dma, + XDBC_PAGE_BUFFER); + xdbcp->in_buf = xdbcp->out_buf + XDBC_MAX_PACKET; + xdbcp->in_dma = xdbcp->out_dma + XDBC_MAX_PACKET; + return 0; } @@ -802,6 +822,9 @@ static int xdbc_start(void) xdbc_trace("root hub port number %d\n", DCST_DPN(status)); + xdbcp->in_ep_state = EP_RUNNING; + xdbcp->out_ep_state = EP_RUNNING; + xdbc_trace("DbC is running now, control 0x%08x\n", readl(&xdbcp->xdbc_reg->control)); @@ -895,3 +918,353 @@ int __init early_xdbc_init(char *s) return 0; } + +static void xdbc_queue_trb(struct xdbc_ring *ring, + u32 field1, u32 field2, u32 field3, u32 field4) +{ + struct xdbc_trb *trb, *link_trb; + + trb = ring->enqueue; + trb->field[0] = cpu_to_le32(field1); + trb->field[1] = cpu_to_le32(field2); + trb->field[2] = cpu_to_le32(field3); + trb->field[3] = cpu_to_le32(field4); + + xdbc_dbg_dump_trb(trb, "enqueue trb"); + + ++(ring->enqueue); + if (ring->enqueue >= &ring->segment->trbs[TRBS_PER_SEGMENT - 1]) { + link_trb = ring->enqueue; + if (ring->cycle_state) + link_trb->field[3] |= cpu_to_le32(TRB_CYCLE); + else + link_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); + + ring->enqueue = ring->segment->trbs; + ring->cycle_state ^= 1; + } +} + +static void xdbc_ring_doorbell(int target) +{ + writel(DOOR_BELL_TARGET(target), &xdbcp->xdbc_reg->doorbell); +} + +static void xdbc_handle_port_status(struct xdbc_trb *evt_trb) +{ + u32 port_reg; + + port_reg = readl(&xdbcp->xdbc_reg->portsc); + + if (port_reg & PORTSC_CSC) { + xdbc_trace("%s: connect status change event\n", __func__); + writel(port_reg | PORTSC_CSC, &xdbcp->xdbc_reg->portsc); + port_reg = readl(&xdbcp->xdbc_reg->portsc); + } + + if (port_reg & PORTSC_PRC) { + xdbc_trace("%s: port reset change event\n", __func__); + writel(port_reg | PORTSC_PRC, &xdbcp->xdbc_reg->portsc); + port_reg = readl(&xdbcp->xdbc_reg->portsc); + } + + if (port_reg & PORTSC_PLC) { + xdbc_trace("%s: port l
[PATCH 04/12] usb: xhci: dbc: add support for Intel xHCI dbc quirk
On Intel platform, if the debug target is connected with debug host, enabling DCE bit in command register leads to a hung bus state. In the hung state, the host system will not see a port connected status bit set. Hence debug target fails to be probed. The state could be resolved by performing a port reset to the debug port from the host xHCI. This patch introduces this work around. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 52 include/linux/usb/xhci-dbc.h | 2 ++ 2 files changed, 54 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 22a1de9..6b23f09 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -255,6 +255,8 @@ static void __iomem *xdbc_map_pci_mmio(u32 bus, xdbcp->bar = bar; xdbcp->xhci_base = base; xdbcp->xhci_length = sz64; + xdbcp->vendor = read_pci_config_16(bus, dev, func, PCI_VENDOR_ID); + xdbcp->device = read_pci_config_16(bus, dev, func, PCI_DEVICE_ID); if (length) *length = sz64; @@ -651,6 +653,52 @@ static int xdbc_mem_init(void) return 0; } +static void xdbc_reset_debug_port_callback(int cap_offset, void *data) +{ + u8 major; + u32 val, port_offset, port_count; + u32 cap_length; + void __iomem *ops_reg; + void __iomem *portsc; + int i; + + val = readl(xdbcp->xhci_base + cap_offset); + major = (u8) XHCI_EXT_PORT_MAJOR(val); + + /* only reset super-speed port */ + if (major != 0x3) + return; + + val = readl(xdbcp->xhci_base + cap_offset + 8); + port_offset = XHCI_EXT_PORT_OFF(val); + port_count = XHCI_EXT_PORT_COUNT(val); + xdbc_trace("Extcap Port offset %d count %d\n", + port_offset, port_count); + + cap_length = readl(xdbcp->xhci_base) & 0xff; + ops_reg = xdbcp->xhci_base + cap_length; + + port_offset--; + for (i = port_offset; i < (port_offset + port_count); i++) { + portsc = ops_reg + 0x400 + i * 0x10; + val = readl(portsc); + /* reset the port if CCS bit is cleared */ + if (!(val & 0x1)) + writel(val | (1 << 4), portsc); + } +} + +static void xdbc_reset_debug_port(void) +{ + xdbc_walk_excap(xdbcp->bus, + xdbcp->dev, + xdbcp->func, + XHCI_EXT_CAPS_PROTOCOL, + false, + xdbc_reset_debug_port_callback, + NULL); +} + /* * xdbc_start: start DbC * @@ -669,6 +717,10 @@ static int xdbc_start(void) return -ENODEV; } + /* reset port to avoid bus hang */ + if (xdbcp->vendor == PCI_VENDOR_ID_INTEL) + xdbc_reset_debug_port(); + /* wait for port connection */ if (handshake(&xdbcp->xdbc_reg->portsc, PORTSC_CCS, PORTSC_CCS, 500, 100) < 0) { diff --git a/include/linux/usb/xhci-dbc.h b/include/linux/usb/xhci-dbc.h index 153fb87..fc0ef9a 100644 --- a/include/linux/usb/xhci-dbc.h +++ b/include/linux/usb/xhci-dbc.h @@ -128,6 +128,8 @@ struct xdbc_state { u32 dev; u32 func; u8 bar; + u16 vendor; + u16 device; void __iomem*xhci_base; size_t xhci_length; #defineXDBC_PCI_MAX_BUSES 256 -- 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 03/12] usb: xhci: dbc: probe and setup xhci debug capability
xHCI debug capability (DbC) is an optional functionality provided by an xHCI host controller. Software learns this capability by walking through the extended capability list in mmio of the host. This patch introduces the code to probe and initialize the debug capability hardware during early boot. With hardware initialization done, the debug target (system under debug which has DbC enabled) will present a debug device through the debug port. The debug device is fully compliant with the USB framework and provides the equivalent of a very high performance (USB3) full-duplex serial link between the debug host and target. Signed-off-by: Lu Baolu --- MAINTAINERS | 7 + arch/x86/Kconfig.debug | 12 + drivers/usb/early/Makefile | 1 + drivers/usb/early/xhci-dbc.c | 787 +++ include/linux/usb/xhci-dbc.h | 187 ++ 5 files changed, 994 insertions(+) create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 include/linux/usb/xhci-dbc.h diff --git a/MAINTAINERS b/MAINTAINERS index 0425167..585a369 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11040,6 +11040,13 @@ S: Supported F: drivers/usb/host/xhci* F: drivers/usb/host/pci-quirks* +USB XHCI DEBUG PORT +M: Lu Baolu +L: linux-usb@vger.kernel.org +S: Supported +F: drivers/usb/early/xhci-dbc.c +F: include/linux/usb/xhci-dbc.h + USB ZD1201 DRIVER L: linux-wirel...@vger.kernel.org W: http://linux-lc100020.sourceforge.net diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index d8c0d32..8d95abd 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -65,6 +65,18 @@ config EARLY_PRINTK_EFI This is useful for kernel debugging when your machine crashes very early before the console code is initialized. +config EARLY_PRINTK_XDBC + bool "Early printk via xHCI debug port" + depends on EARLY_PRINTK && PCI + ---help--- + Write kernel log output directly into the xHCI debug port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config X86_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile index 24bbe51..2db5906 100644 --- a/drivers/usb/early/Makefile +++ b/drivers/usb/early/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o +obj-$(CONFIG_EARLY_PRINTK_XDBC) += xhci-dbc.o diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c new file mode 100644 index 000..22a1de9 --- /dev/null +++ b/drivers/usb/early/xhci-dbc.c @@ -0,0 +1,787 @@ +/** + * xhci-dbc.c - xHCI debug capability driver + * + * Copyright (C) 2015 Intel Corporation + * + * Author: Lu Baolu + * Some code shared with EHCI debug port and xHCI driver. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../host/xhci.h" + +#defineXDBC_PROTOCOL 1 /* GNU Remote Debug Command Set */ +#defineXDBC_VENDOR_ID 0x1d6b /* Linux Foundation 0x1d6b */ +#defineXDBC_PRODUCT_ID 0x0004 /* __le16 idProduct; device 0004 */ +#defineXDBC_DEVICE_REV 0x0010 /* 0.10 */ + +static struct xdbc_state xdbc_stat; +static struct xdbc_state *xdbcp = &xdbc_stat; + +#ifdef DBC_DEBUG +/* place holder */ +#definexdbc_trace printk +static void xdbc_dbg_dump_regs(char *str) +{ + if (!xdbcp->xdbc_reg) { + xdbc_trace("register not mapped\n"); + return; + } + + xdbc_trace("XDBC registers: %s\n", str); + xdbc_trace(" Capability: %08x\n", + readl(&xdbcp->xdbc_reg->capability)); + xdbc_trace(" Door bell: %08x\n", + readl(&xdbcp->xdbc_reg->doorbell)); + xdbc_trace(" Event Ring Segment Table Size: %08x\n", + readl(&xdbcp->xdbc_reg->ersts)); + xdbc_trace(" Event Ring Segment Table Base Address: %16llx\n", + xdbc_read64(&xdbcp->xdbc_reg->erstba)); + xdbc_trace(" Event Ring Dequeue Pointer: %16llx\n", + xdbc_read64(&xdbcp->xdbc_reg->erdp)); +
[PATCH 05/12] usb: xhci: dbc: add debug buffer
"printk" is not suitable for dbc debugging especially when console is in usage. This patch adds a debug buffer in dbc driver and puts the debug messages in this local buffer. The debug buffer could be dumped whenever the console is not in use. This part of code will not be visible unless DBC_DEBUG is defined. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 62 ++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 6b23f09..b36a527 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -32,8 +32,64 @@ static struct xdbc_state xdbc_stat; static struct xdbc_state *xdbcp = &xdbc_stat; #ifdef DBC_DEBUG -/* place holder */ -#definexdbc_trace printk +#defineXDBC_DEBUG_BUF_SIZE (PAGE_SIZE * 32) +#defineMSG_MAX_LINE128 +static char xdbc_debug_buf[XDBC_DEBUG_BUF_SIZE]; +static void xdbc_trace(const char *fmt, ...) +{ + int i, size; + va_list args; + static int pos; + char temp_buf[MSG_MAX_LINE]; + + if (pos >= XDBC_DEBUG_BUF_SIZE - 1) + return; + + memset(temp_buf, 0, MSG_MAX_LINE); + va_start(args, fmt); + vsnprintf(temp_buf, MSG_MAX_LINE - 1, fmt, args); + va_end(args); + + i = 0; + size = strlen(temp_buf); + while (i < size) { + xdbc_debug_buf[pos] = temp_buf[i]; + pos++; + i++; + + if (pos >= XDBC_DEBUG_BUF_SIZE - 1) + break; + } +} + +static void xdbc_dump_debug_buffer(void) +{ + int index = 0; + int count = 0; + char dump_buf[MSG_MAX_LINE]; + + xdbc_trace("The end of DbC trace buffer\n"); + pr_notice("DBC debug buffer:\n"); + memset(dump_buf, 0, MSG_MAX_LINE); + + while (index < XDBC_DEBUG_BUF_SIZE) { + if (!xdbc_debug_buf[index]) + break; + + if (xdbc_debug_buf[index] == '\n' || + count >= MSG_MAX_LINE - 1) { + pr_notice("DBC: @%08x %s\n", index, dump_buf); + memset(dump_buf, 0, MSG_MAX_LINE); + count = 0; + } else { + dump_buf[count] = xdbc_debug_buf[index]; + count++; + } + + index++; + } +} + static void xdbc_dbg_dump_regs(char *str) { if (!xdbcp->xdbc_reg) { @@ -165,6 +221,7 @@ static void xdbc_dbg_dump_data(char *str) #else static inline void xdbc_trace(const char *fmt, ...) { } +static inline void xdbc_dump_debug_buffer(void) { } static inline void xdbc_dbg_dump_regs(char *str) { } static inline void xdbc_dbg_dump_data(char *str) { } #endif /* DBC_DEBUG */ @@ -832,6 +889,7 @@ int __init early_xdbc_init(char *s) pr_notice("failed to setup xHCI DbC connection\n"); xdbcp->xhci_base = NULL; xdbcp->xdbc_reg = NULL; + xdbc_dump_debug_buffer(); return ret; } -- 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 01/12] usb: xhci: expose xhci extended capabilities via debugfs
The xHCI host exports xHCI-specific extended capabilities utilizing a method similar to PCI extended capabilities. In many cases, users want to know whether a specific extended capability is supported by a host. Unfortunately, currently there's no existing mechanisms in the kernel to do this. This patch exposes extended capabilities supported by the xHCI host via debugfs. Signed-off-by: Lu Baolu --- drivers/usb/host/xhci-dbg.c | 212 +++ drivers/usb/host/xhci-ext-caps.h | 9 +- drivers/usb/host/xhci.c | 27 - drivers/usb/host/xhci.h | 10 ++ 4 files changed, 256 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c index 74c42f7..d3dcfed 100644 --- a/drivers/usb/host/xhci-dbg.c +++ b/drivers/usb/host/xhci-dbg.c @@ -20,6 +20,11 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include +#include +#include +#include + #include "xhci.h" #define XHCI_INIT_VALUE 0x0 @@ -612,3 +617,210 @@ void xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), va_end(args); } EXPORT_SYMBOL_GPL(xhci_dbg_trace); + +#ifdef CONFIG_DEBUG_FS +struct debug_buffer { + ssize_t (*fill_func)(struct debug_buffer *); + struct usb_bus *bus; + struct mutex mutex; + size_t count; + char *output_buf; + size_t alloc_size; +}; + +static const char *get_extcap_desc(u32 cap_id) +{ + switch (cap_id) { + case XHCI_EXT_CAPS_LEGACY: + return "USB Legacy Support"; + case XHCI_EXT_CAPS_PROTOCOL: + return "Supported Protocol"; + case XHCI_EXT_CAPS_PM: + return "Extended Power Management"; + case XHCI_EXT_CAPS_VIRT: + return "I/O Virtualization (xHCI-IOV)"; + case XHCI_EXT_CAPS_ROUTE: + return "Message Interrupt"; + case XHCI_EXT_CAPS_LOCALMEM: + return "Local Memory"; + case XHCI_EXT_CAPS_DEBUG: + return "USB Debug Capability"; + default: + if (XHCI_EXT_CAPS_VENDOR(XHCI_EXT_CAPS_ID(cap_id))) + return "Vendor Defined"; + else + return "Unknown"; + } +} + +static ssize_t fill_extcap_buffer(struct debug_buffer *buf) +{ + __le32 __iomem *addr; + struct usb_hcd *hcd; + struct xhci_hcd *xhci; + u32 offset, cap_id; + char*next; + int size, temp; + unsigned long flags; + int time_to_leave; + + hcd = bus_to_hcd(buf->bus); + xhci = hcd_to_xhci(hcd); + next = buf->output_buf; + size = buf->alloc_size; + + spin_lock_irqsave(&xhci->lock, flags); + + addr = &xhci->cap_regs->hcc_params; + offset = XHCI_HCC_EXT_CAPS(readl(addr)); + if (!HCD_HW_ACCESSIBLE(hcd) || !offset) { + size = scnprintf(next, size, + "bus %s, device %s\n%s\nNo extended capabilities\n", + hcd->self.controller->bus->name, + dev_name(hcd->self.controller), + hcd->product_desc); + goto done; + } + + temp = scnprintf(next, size, "@addr(virt)\t\tCAP_ID\tDescription\n"); + size -= temp; + next += temp; + + addr = &xhci->cap_regs->hc_capbase + offset; + time_to_leave = XHCI_EXT_MAX_CAPID; + while (time_to_leave--) { + cap_id = readl(addr); + temp = scnprintf(next, size, "@%p\t%02x\t%s\n", + addr, XHCI_EXT_CAPS_ID(cap_id), + get_extcap_desc(XHCI_EXT_CAPS_ID(cap_id))); + size -= temp; + next += temp; + + offset = XHCI_EXT_CAPS_NEXT(cap_id); + if (!offset) + break; + addr += offset; + } + +done: + spin_unlock_irqrestore(&xhci->lock, flags); + + return buf->alloc_size - size; +} + +static struct debug_buffer *buffer_init(struct usb_bus *bus, + ssize_t (*fill_func)(struct debug_buffer *)) +{ + struct debug_buffer *buf; + + buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + if (!buf) + return NULL; + + buf->bus = bus; + buf->fill_func = fill_func; + mutex_init(&buf->mutex); + + return buf; +} + +static int fill_buffer(struct debug_buffer *buf) +{ + int ret; + + if (buf->output_buf) + return -EINVAL; + + buf->alloc_size = PAGE_SIZE; + buf->output_buf = vmalloc(buf->alloc_size); + + if (!buf->output_buf) +
[PATCH 00/12] usb: early: add support for early printk through USB3 debug port
This patch series adds support for early printk through USB3 debug port. USB3 debug port is described in xHCI specification as an optional extended capability. The first patch adds a file in debugfs, through which users can check whether the debug capability is supported by a specific host controller. Patch 2 to 10 add the driver for xHCI debug capability. It interfaces with the register set and provides the required ops (read/write/control) to upper layers. Early printk is one consumer of these ops. The hooks for early printk are introduced in patch 9. This design is similar to what we have done in drivers/usb/early/ehci-dbgp.c. Patch 11 is a minor change to usb_debug module. This change is required to bind usb_debug with the USB3 debug device. Patch 12 is the design document and user guide. Lu Baolu (12): usb: xhci: expose xhci extended capabilities via debugfs x86: fixmap: add permanent fixmap for xhci debug port usb: xhci: dbc: probe and setup xhci debug capability usb: xhci: dbc: add support for Intel xHCI dbc quirk usb: xhci: dbc: add debug buffer usb: xhci: dbc: add bulk out and bulk in interfaces usb: xhci: dbc: handle dbc-configured exit usb: xhci: dbc: handle endpoint stall x86: early_printk: add USB3 debug port earlyprintk support usb: xhci: dbc: add handshake between debug target and host usb: serial: usb_debug: add support for dbc debug device usb: doc: add document for xHCI DbC driver Documentation/kernel-parameters.txt |1 + Documentation/usb/xhci-dbc.txt | 325 MAINTAINERS |8 + arch/x86/Kconfig.debug | 12 + arch/x86/include/asm/fixmap.h |4 + arch/x86/kernel/early_printk.c |5 + drivers/usb/early/Makefile |1 + drivers/usb/early/xhci-dbc.c| 1407 +++ drivers/usb/host/xhci-dbg.c | 212 ++ drivers/usb/host/xhci-ext-caps.h|9 +- drivers/usb/host/xhci.c | 27 +- drivers/usb/host/xhci.h | 10 + drivers/usb/serial/usb_debug.c | 29 +- include/linux/usb/xhci-dbc.h| 224 ++ 14 files changed, 2269 insertions(+), 5 deletions(-) create mode 100644 Documentation/usb/xhci-dbc.txt create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 include/linux/usb/xhci-dbc.h -- 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 02/12] x86: fixmap: add permanent fixmap for xhci debug port
xHCI compatible USB3 host controller may provide debug capability which enables low-level system debug over USB. In order to probing this debug capability, Linux kernel needs to map and access the mmio of the host controller during early boot. This patch adds permenent fixmap pages in fixed_addresses table for xHCI mmio access. Signed-off-by: Lu Baolu --- arch/x86/include/asm/fixmap.h | 4 1 file changed, 4 insertions(+) diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index f80d700..fbf452f 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -82,6 +82,10 @@ enum fixed_addresses { #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT FIX_OHCI1394_BASE, #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + FIX_XDBC_BASE, + FIX_XDBC_END = FIX_XDBC_BASE + 15, +#endif #ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ #endif -- 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
Re: [PATCH 01/12] usb: xhci: expose xhci extended capabilities via debugfs
On 10/28/2015 05:27 PM, Oliver Neukum wrote: +static int fill_buffer(struct debug_buffer *buf) >+{ >+ int ret; >+ >+ if (buf->output_buf) >+ return -EINVAL; >+ >+ buf->alloc_size = PAGE_SIZE; >+ buf->output_buf = vmalloc(buf->alloc_size); That really makes no sense. If you allocate exactly PAGE_SIZE, you should allocate a page. Yes, I will change it in v2. Regards Oliver Thanks, Baolu -- 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 01/12] usb: xhci: expose xhci extended capabilities via debugfs
On 10/28/2015 08:40 PM, Greg Kroah-Hartman wrote: >+struct debug_buffer { >+ ssize_t (*fill_func)(struct debug_buffer *); >+ struct usb_bus *bus; >+ struct mutex mutex; >+ size_t count; >+ char *output_buf; >+ size_t alloc_size; >+}; >+ >+static const char *get_extcap_desc(u32 cap_id) >+{ >+ switch (cap_id) { >+ case XHCI_EXT_CAPS_LEGACY: >+ return "USB Legacy Support"; >+ case XHCI_EXT_CAPS_PROTOCOL: >+ return "Supported Protocol"; >+ case XHCI_EXT_CAPS_PM: >+ return "Extended Power Management"; >+ case XHCI_EXT_CAPS_VIRT: >+ return "I/O Virtualization (xHCI-IOV)"; >+ case XHCI_EXT_CAPS_ROUTE: >+ return "Message Interrupt"; >+ case XHCI_EXT_CAPS_LOCALMEM: >+ return "Local Memory"; >+ case XHCI_EXT_CAPS_DEBUG: >+ return "USB Debug Capability"; This is a lot more stuff than just debug port, it should be in sysfs as individual files, not one big one that you somehow have to parse in order to determine this information. I will move it into sysfs in v2. Thanks, Baolu -- 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/12] usb: serial: usb_debug: add support for dbc debug device
On 10/28/2015 05:10 PM, Johan Hovold wrote: On Wed, Oct 28, 2015 at 04:00:42PM +0800, Lu Baolu wrote: This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu --- drivers/usb/serial/usb_debug.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) +static struct usb_serial_driver dbc_device = { + .driver = { + .owner =THIS_MODULE, + .name = "xhci_dbc", + }, + .id_table = dbc_id_table, + .num_ports =1, + .bulk_out_size =1024, No need to set this unless you need a larger (or smaller for ehci) buffer than the endpoint size. I will remove it in v2. Thanks for pointing this out. Johan Thanks, Baolu -- 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/1] usb: xhci: fix checking ep busy for CFC
On 10/28/2015 09:27 PM, Mathias Nyman wrote: On 28.10.2015 03:36, Lu Baolu wrote: Function ep_ring_is_processing() checks the dequeue pointer in endpoint context to know whether an endpoint is busy with processing TRBs. This is not correct since dequeue pointer field in an endpoint context is only valid when the endpoint is in Halted or Stopped states. This buggy code causes audio noise when playing sound with USB headset connected to host controllers which support CFC (one of xhci 1.1 features). This patch should exist in stable kernel since v4.3. Reported-and-tested-by: YD Tseng Signed-off-by: Lu Baolu --- drivers/usb/host/xhci-ring.c | 5 + 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa83625..2b50d45 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3903,7 +3903,6 @@ static int ep_ring_is_processing(struct xhci_hcd *xhci, struct xhci_ring *ep_ring; struct xhci_ep_ctx *ep_ctx; struct xhci_virt_ep *xep; -dma_addr_t hw_deq; xdev = xhci->devs[slot_id]; xep = &xhci->devs[slot_id]->eps[ep_index]; @@ -3913,9 +3912,7 @@ static int ep_ring_is_processing(struct xhci_hcd *xhci, if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING) return 0; -hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK; -return (hw_deq != -xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue)); +return !list_empty(&ep_ring->td_list); } Would it make sense to remove the ep_ring_is_processing() function completely? It is only called in one place, and the main use is checking list_empty(&ep_ring->td_list). This could be checked directly in xhci_queue_isoc_tx_prepare() Fair enough. I will make this change and send out the v2. -Mathias Thanks, Baolu -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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/12] usb: serial: usb_debug: add support for dbc debug device
On 10/28/2015 08:33 PM, Greg Kroah-Hartman wrote: On Wed, Oct 28, 2015 at 04:00:42PM +0800, Lu Baolu wrote: This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu --- drivers/usb/serial/usb_debug.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..d4903b0 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); You shouldn't need a "combined" module device table anymore, the module core was changed a while ago to remove that restriction, you should be able to just multiple exports of MODULE_DEVICE_TABLE and everything should "just work" on the export side. Now it might not work on the usb core side, but that's a different issue... Thanks for pointing this out. I will re-factor this code in v2 patch. thanks, greg k-h -- 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 v2 1/1] usb: xhci: fix checking ep busy for CFC
Function ep_ring_is_processing() checks the dequeue pointer in endpoint context to know whether an endpoint is busy with processing TRBs. This is not correct since dequeue pointer field in an endpoint context is only valid when the endpoint is in Halted or Stopped states. This buggy code causes audio noise when playing sound with USB headset connected to host controllers which support CFC (one of xhci 1.1 features). This patch should exist in stable kernel since v4.3. Reported-and-tested-by: YD Tseng Signed-off-by: Lu Baolu --- v1->v2: Implement the logic in xhci_queue_isoc_tx_prepare() instead of a seperated function as suggested by Mathias. --- drivers/usb/host/xhci-ring.c | 32 ++-- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa83625..8edc286 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3896,28 +3896,6 @@ cleanup: return ret; } -static int ep_ring_is_processing(struct xhci_hcd *xhci, - int slot_id, unsigned int ep_index) -{ - struct xhci_virt_device *xdev; - struct xhci_ring *ep_ring; - struct xhci_ep_ctx *ep_ctx; - struct xhci_virt_ep *xep; - dma_addr_t hw_deq; - - xdev = xhci->devs[slot_id]; - xep = &xhci->devs[slot_id]->eps[ep_index]; - ep_ring = xep->ring; - ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); - - if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING) - return 0; - - hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK; - return (hw_deq != - xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue)); -} - /* * Check transfer ring to guarantee there is enough room for the urb. * Update ISO URB start_frame and interval. @@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, } /* Calculate the start frame and put it in urb->start_frame. */ - if (HCC_CFC(xhci->hcc_params) && - ep_ring_is_processing(xhci, slot_id, ep_index)) { - urb->start_frame = xep->next_frame_id; - goto skip_start_over; + if (HCC_CFC(xhci->hcc_params)) { + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) + == EP_STATE_RUNNING && + !list_empty(&ep_ring->td_list)) + urb->start_frame = xep->next_frame_id; + goto skip_start_over; } start_frame = readl(&xhci->run_regs->microframe_index); -- 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
Re: [PATCH v2 1/1] usb: xhci: fix checking ep busy for CFC
On 10/29/2015 08:51 PM, Sergei Shtylyov wrote: Hello. On 10/29/2015 5:46 AM, Lu Baolu wrote: Function ep_ring_is_processing() checks the dequeue pointer in endpoint context to know whether an endpoint is busy with processing TRBs. This is not correct since dequeue pointer field in an endpoint context is only valid when the endpoint is in Halted or Stopped states. This buggy code causes audio noise when playing sound with USB headset connected to host controllers which support CFC (one of xhci 1.1 features). This patch should exist in stable kernel since v4.3. Reported-and-tested-by: YD Tseng Signed-off-by: Lu Baolu --- v1->v2: Implement the logic in xhci_queue_isoc_tx_prepare() instead of a seperated function as suggested by Mathias. --- drivers/usb/host/xhci-ring.c | 32 ++-- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa83625..8edc286 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c [...] @@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, } /* Calculate the start frame and put it in urb->start_frame. */ -if (HCC_CFC(xhci->hcc_params) && -ep_ring_is_processing(xhci, slot_id, ep_index)) { -urb->start_frame = xep->next_frame_id; -goto skip_start_over; +if (HCC_CFC(xhci->hcc_params)) { +if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) +== EP_STATE_RUNNING && +!list_empty(&ep_ring->td_list)) +urb->start_frame = xep->next_frame_id; +goto skip_start_over; Forgot {}? Oh, I am sorry. I am wondering how it passed my test. I will send v3 patch soon any way. } start_frame = readl(&xhci->run_regs->microframe_index); MBR, Sergei -- 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 -- 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 v3 1/1] usb: xhci: fix checking ep busy for CFC
Function ep_ring_is_processing() checks the dequeue pointer in endpoint context to know whether an endpoint is busy with processing TRBs. This is not correct since dequeue pointer field in an endpoint context is only valid when the endpoint is in Halted or Stopped states. This buggy code causes audio noise when playing sound with USB headset connected to host controllers which support CFC (one of xhci 1.1 features). This patch should exist in stable kernel since v4.3. Reported-and-tested-by: YD Tseng Signed-off-by: Lu Baolu --- v1->v2: Implement the logic in xhci_queue_isoc_tx_prepare() instead of a seperated function as suggested by Mathias. v2->v3: Add the missing {} pair found by Sergei. Adjust line for code readability as suggested by Mathias. --- drivers/usb/host/xhci-ring.c | 32 ++-- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa83625..6c5e813 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3896,28 +3896,6 @@ cleanup: return ret; } -static int ep_ring_is_processing(struct xhci_hcd *xhci, - int slot_id, unsigned int ep_index) -{ - struct xhci_virt_device *xdev; - struct xhci_ring *ep_ring; - struct xhci_ep_ctx *ep_ctx; - struct xhci_virt_ep *xep; - dma_addr_t hw_deq; - - xdev = xhci->devs[slot_id]; - xep = &xhci->devs[slot_id]->eps[ep_index]; - ep_ring = xep->ring; - ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); - - if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING) - return 0; - - hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK; - return (hw_deq != - xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue)); -} - /* * Check transfer ring to guarantee there is enough room for the urb. * Update ISO URB start_frame and interval. @@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, } /* Calculate the start frame and put it in urb->start_frame. */ - if (HCC_CFC(xhci->hcc_params) && - ep_ring_is_processing(xhci, slot_id, ep_index)) { - urb->start_frame = xep->next_frame_id; - goto skip_start_over; + if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) { + if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == + EP_STATE_RUNNING) { + urb->start_frame = xep->next_frame_id; + goto skip_start_over; + } } start_frame = readl(&xhci->run_regs->microframe_index); -- 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
Re: [PATCH v2 1/1] usb: xhci: fix checking ep busy for CFC
On 10/29/2015 10:08 PM, Mathias Nyman wrote: On 29.10.2015 14:58, Lu, Baolu wrote: On 10/29/2015 08:51 PM, Sergei Shtylyov wrote: Hello. On 10/29/2015 5:46 AM, Lu Baolu wrote: Function ep_ring_is_processing() checks the dequeue pointer in endpoint context to know whether an endpoint is busy with processing TRBs. This is not correct since dequeue pointer field in an endpoint context is only valid when the endpoint is in Halted or Stopped states. This buggy code causes audio noise when playing sound with USB headset connected to host controllers which support CFC (one of xhci 1.1 features). This patch should exist in stable kernel since v4.3. Reported-and-tested-by: YD Tseng Signed-off-by: Lu Baolu --- v1->v2: Implement the logic in xhci_queue_isoc_tx_prepare() instead of a seperated function as suggested by Mathias. --- drivers/usb/host/xhci-ring.c | 32 ++-- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fa83625..8edc286 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c [...] @@ -3983,10 +3961,12 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, } /* Calculate the start frame and put it in urb->start_frame. */ -if (HCC_CFC(xhci->hcc_params) && -ep_ring_is_processing(xhci, slot_id, ep_index)) { -urb->start_frame = xep->next_frame_id; -goto skip_start_over; +if (HCC_CFC(xhci->hcc_params)) { +if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) +== EP_STATE_RUNNING && +!list_empty(&ep_ring->td_list)) +urb->start_frame = xep->next_frame_id; +goto skip_start_over; Forgot {}? Oh, I am sorry. I am wondering how it passed my test. I will send v3 patch soon any way. If you are anyway making a v3 then maybe one more change, just for readability, no (real) functional change: if (HCC_CFC(xhci->hcc_params) && !list_empty(&ep_ring->td_list)) { if (le32_to_cpu(ep_... Done. While thinking about code cleanup I also think we should use a local variable u32 ep_info = le32_to_cpu(ep_ctx->ep_info) as it's used several times in xhci_queue_isoc_tx_preapare(), causing a lot of line splitting. It should be ok as we are under the same spinlock so ep_ctx should not change. But that is not a fix sent to a rc and stable, I can make a separate cleanup patch for it later. -Mathias -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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/12] usb: serial: usb_debug: add support for dbc debug device
On 10/28/2015 08:33 PM, Greg Kroah-Hartman wrote: On Wed, Oct 28, 2015 at 04:00:42PM +0800, Lu Baolu wrote: This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu --- drivers/usb/serial/usb_debug.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..d4903b0 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); You shouldn't need a "combined" module device table anymore, the module core was changed a while ago to remove that restriction, you should be able to just multiple exports of MODULE_DEVICE_TABLE and everything should "just work" on the export side. Now it might not work on the usb core side, but that's a different issue... Before I dive into the serial driver code, can anybody tell me, if I remove the "combined" module device table, what should I specify the second parameter for module_usb_serial_driver()? The previous declaration is, module_usb_serial_driver(serial_drivers, id_table_combined); Thanks, Baolu thanks, greg k-h -- 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 01/12] usb: xhci: expose xhci extended capabilities via debugfs
On 10/28/2015 08:40 PM, Greg Kroah-Hartman wrote: +static const char *get_extcap_desc(u32 cap_id) >+{ >+ switch (cap_id) { >+ case XHCI_EXT_CAPS_LEGACY: >+ return "USB Legacy Support"; >+ case XHCI_EXT_CAPS_PROTOCOL: >+ return "Supported Protocol"; >+ case XHCI_EXT_CAPS_PM: >+ return "Extended Power Management"; >+ case XHCI_EXT_CAPS_VIRT: >+ return "I/O Virtualization (xHCI-IOV)"; >+ case XHCI_EXT_CAPS_ROUTE: >+ return "Message Interrupt"; >+ case XHCI_EXT_CAPS_LOCALMEM: >+ return "Local Memory"; >+ case XHCI_EXT_CAPS_DEBUG: >+ return "USB Debug Capability"; This is a lot more stuff than just debug port, it should be in sysfs as individual files, not one big one that you somehow have to parse in order to determine this information. Hi Greg, It's hard to put each extended capability into a individual sysfs file. The extended capabilities are optional. One extended capability might be supported in one hardware, but not in another. Also, there are many "vendor defined" capabilities (ID range 192-255). The vendor defined capabilities are not defined in xhci spec and they could be used by the hardware vendor for various purposes. The purpose of this patch is to let user know what kind of extended capabilities does a host controller supported. For example, on one of my develop machines, it prints, @addr(virt)CAP_IDDescription @c90001c8800002Supported Protocol @c90001c8802002Supported Protocol @c90001c88070c0Vendor Defined @c90001c8846c01USB Legacy Support @c90001c884f4c6Vendor Defined @c90001c88500c7Vendor Defined @c90001c88600c2Vendor Defined @c90001c887000aUSB Debug Capability @c90001c88740c3Vendor Defined @c90001c88800c4Vendor Defined @c90001c88900c5Vendor Defined With this output I know that "USB Debug Capability" is supported in my machine. Thanks, Baolu -- 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/12] usb: serial: usb_debug: add support for dbc debug device
On 10/30/2015 10:41 PM, Greg Kroah-Hartman wrote: On Fri, Oct 30, 2015 at 07:46:45PM +0800, Lu, Baolu wrote: On 10/28/2015 08:33 PM, Greg Kroah-Hartman wrote: On Wed, Oct 28, 2015 at 04:00:42PM +0800, Lu Baolu wrote: This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu --- drivers/usb/serial/usb_debug.c | 29 ++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..d4903b0 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); You shouldn't need a "combined" module device table anymore, the module core was changed a while ago to remove that restriction, you should be able to just multiple exports of MODULE_DEVICE_TABLE and everything should "just work" on the export side. Now it might not work on the usb core side, but that's a different issue... Before I dive into the serial driver code, can anybody tell me, if I remove the "combined" module device table, what should I specify the second parameter for module_usb_serial_driver()? The previous declaration is, module_usb_serial_driver(serial_drivers, id_table_combined); Yeah, that's the issue I was alluding to here, maybe this will not work just yet for USB serial drivers, sorry to lead you down the wrong path. Your original patch should be fine for now. Okay, I will keep that patch. thanks, greg k-h Thanks, Baolu -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/ -- 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 01/12] usb: xhci: expose xhci extended capabilities via debugfs
On 10/30/2015 10:45 PM, Greg Kroah-Hartman wrote: On Fri, Oct 30, 2015 at 08:09:17PM +0800, Lu, Baolu wrote: On 10/28/2015 08:40 PM, Greg Kroah-Hartman wrote: +static const char *get_extcap_desc(u32 cap_id) +{ + switch (cap_id) { + case XHCI_EXT_CAPS_LEGACY: + return "USB Legacy Support"; + case XHCI_EXT_CAPS_PROTOCOL: + return "Supported Protocol"; + case XHCI_EXT_CAPS_PM: + return "Extended Power Management"; + case XHCI_EXT_CAPS_VIRT: + return "I/O Virtualization (xHCI-IOV)"; + case XHCI_EXT_CAPS_ROUTE: + return "Message Interrupt"; + case XHCI_EXT_CAPS_LOCALMEM: + return "Local Memory"; + case XHCI_EXT_CAPS_DEBUG: + return "USB Debug Capability"; This is a lot more stuff than just debug port, it should be in sysfs as individual files, not one big one that you somehow have to parse in order to determine this information. Hi Greg, It's hard to put each extended capability into a individual sysfs file. Agreed. The extended capabilities are optional. One extended capability might be supported in one hardware, but not in another. Also, there are many "vendor defined" capabilities (ID range 192-255). The vendor defined capabilities are not defined in xhci spec and they could be used by the hardware vendor for various purposes. The purpose of this patch is to let user know what kind of extended capabilities does a host controller supported. For example, on one of my develop machines, it prints, @addr(virt)CAP_IDDescription @c90001c8800002Supported Protocol @c90001c8802002Supported Protocol @c90001c88070c0Vendor Defined @c90001c8846c01USB Legacy Support @c90001c884f4c6Vendor Defined @c90001c88500c7Vendor Defined @c90001c88600c2Vendor Defined @c90001c887000aUSB Debug Capability @c90001c88740c3Vendor Defined @c90001c88800c4Vendor Defined @c90001c88900c5Vendor Defined With this output I know that "USB Debug Capability" is supported in my machine. First off, why are you printing the address out? Userspace never needs to see that. Why not just iterate through the protocols and export the information as different files: protocol_XX and if the file is present or not describes if the hardware supports it or not. The issue with debugfs is that it is not enabled on all systems, and only can be read by the root user, so it is hard for people to find this information out if they want to do normal things with the hardware. I agree with you that we should do this thru sysfs, not debugfs. But, if this really is only a debug thing, then it can say a debugfs file, but realize that almost no one will be able to see it (and even then, don't export the kernel addresses of the hardware.) I realized that not all extended capabilities are valuable to users. As far as I can see, debug capability (hw implements USB3 debug port) is one that users should be interested at. Another one that could be valuable is USB 3.1 speed protocol (root ports that support USB 3.1 enhanced super speed). For this time being, I will only implement sysfs node for debug port. I will make a separated patch for USB 3.1 speed port after I have Mathias' opinion. thanks, greg k-h Thanks, Baolu -- 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 -- 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: Overly conservative xHCI bandwidth estimation
Thanks for the information. I will let you know if I have anything. Thanks, Baolu On 11/01/2015 04:20 AM, Steinar H. Gunderson wrote: On Wed, Oct 21, 2015 at 09:49:16AM +0800, Lu, Baolu wrote: I could spend some time on this issue a week later. I'd like to check whether there is any bugs in the driver itself. Otherwise, blacklist this specific device for LPM. I don't know if anything happened here, but if you need information for a blacklist, the two devices I've tested (which both have this issue) are: - 1edb:bd3b (Blackmagic Design Intensity Shuttle) - 1edb:bd4f (Blackmagic Design UltraStudio SDI) /* Steinar */ -- 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 v2 05/12] usb: xhci: dbc: add debug buffer
"printk" is not suitable for dbc debugging especially when console is in usage. This patch adds a debug buffer in dbc driver and puts the debug messages in this local buffer. The debug buffer could be dumped whenever the console is not in use. This part of code will not be visible unless DBC_DEBUG is defined. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 62 ++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 6b23f09..b36a527 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -32,8 +32,64 @@ static struct xdbc_state xdbc_stat; static struct xdbc_state *xdbcp = &xdbc_stat; #ifdef DBC_DEBUG -/* place holder */ -#definexdbc_trace printk +#defineXDBC_DEBUG_BUF_SIZE (PAGE_SIZE * 32) +#defineMSG_MAX_LINE128 +static char xdbc_debug_buf[XDBC_DEBUG_BUF_SIZE]; +static void xdbc_trace(const char *fmt, ...) +{ + int i, size; + va_list args; + static int pos; + char temp_buf[MSG_MAX_LINE]; + + if (pos >= XDBC_DEBUG_BUF_SIZE - 1) + return; + + memset(temp_buf, 0, MSG_MAX_LINE); + va_start(args, fmt); + vsnprintf(temp_buf, MSG_MAX_LINE - 1, fmt, args); + va_end(args); + + i = 0; + size = strlen(temp_buf); + while (i < size) { + xdbc_debug_buf[pos] = temp_buf[i]; + pos++; + i++; + + if (pos >= XDBC_DEBUG_BUF_SIZE - 1) + break; + } +} + +static void xdbc_dump_debug_buffer(void) +{ + int index = 0; + int count = 0; + char dump_buf[MSG_MAX_LINE]; + + xdbc_trace("The end of DbC trace buffer\n"); + pr_notice("DBC debug buffer:\n"); + memset(dump_buf, 0, MSG_MAX_LINE); + + while (index < XDBC_DEBUG_BUF_SIZE) { + if (!xdbc_debug_buf[index]) + break; + + if (xdbc_debug_buf[index] == '\n' || + count >= MSG_MAX_LINE - 1) { + pr_notice("DBC: @%08x %s\n", index, dump_buf); + memset(dump_buf, 0, MSG_MAX_LINE); + count = 0; + } else { + dump_buf[count] = xdbc_debug_buf[index]; + count++; + } + + index++; + } +} + static void xdbc_dbg_dump_regs(char *str) { if (!xdbcp->xdbc_reg) { @@ -165,6 +221,7 @@ static void xdbc_dbg_dump_data(char *str) #else static inline void xdbc_trace(const char *fmt, ...) { } +static inline void xdbc_dump_debug_buffer(void) { } static inline void xdbc_dbg_dump_regs(char *str) { } static inline void xdbc_dbg_dump_data(char *str) { } #endif /* DBC_DEBUG */ @@ -832,6 +889,7 @@ int __init early_xdbc_init(char *s) pr_notice("failed to setup xHCI DbC connection\n"); xdbcp->xhci_base = NULL; xdbcp->xdbc_reg = NULL; + xdbc_dump_debug_buffer(); return ret; } -- 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 v2 12/12] usb: doc: add document for xHCI DbC driver
Add Documentation/usb/xhci-dbc.txt. This document includes development status and user guide for USB3 debug port. Signed-off-by: Lu Baolu --- Documentation/usb/xhci-dbc.txt | 325 + MAINTAINERS| 1 + drivers/usb/early/xhci-dbc.c | 3 + 3 files changed, 329 insertions(+) create mode 100644 Documentation/usb/xhci-dbc.txt diff --git a/Documentation/usb/xhci-dbc.txt b/Documentation/usb/xhci-dbc.txt new file mode 100644 index 000..441b40c --- /dev/null +++ b/Documentation/usb/xhci-dbc.txt @@ -0,0 +1,325 @@ +xHCI debug capability driver + + Lu Baolu + +Last-updated: September 2015 + + + Contents: + - + * What is xHCI DbC? + * Debug topologies + * Debug stacks + * Port Multiplexing + * Hardware initialization + * External reset + * Port reset + * Interrupt/DMA/Memory during early boot + * Endpoint STALL + * Debug device information + * How to use DbC early printk? + * Limitations + + What is xHCI DbC? + - + +The xHCI Debugging Capability defined in section 7.6 of xHCI spec 1.1 +provides an optional functionality that enables low-level system debug +over USB. It provides a means of connecting two systems where one system +is a Debug Host and the other a Debug Target (System Under Test). The +Debug Capability provides an interface that is completely independent +of the xHCI interface. A Debug Target enumerates as a USB debug device +to the Debug Host, allowing a Debug Host to access a Debug Target through +the standard USB software stack. + + Debug topologies + + +Multiple Debug Targets may be attached to a single Debug Host. Debug +Targets may be connected to any downstream facing port below a Debug +Host (i.e. anywhere in the fabric, root port or external hub puts). +A Debug Target may only connect to a Debug Host through a Root Hub port +of the target. That means connection of a Debug Target to a Debug Host +through the ports of an external hub is not supported. + +Below is a typical connection between Debug Host and Debug target. Two +Debug targets are connected to a single Debug host. + + + +| Debug Host | | Debug Target | +|| || +|xHC without DbC | | xHC with DbC | +|or DbC disabled | | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + || | + ||_| + |_ +| + ___| +| HUB | | Debug Target | +|| || +| Superspeed hub | | xHC with DbC | +|| | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + | | + |_| + + Debug stacks + + +Below is a software stack diagram of both Debug Host and Debug Target. + + +| Debug Host | | Debug Target | +|| || +| debug App| || +|| | system debug | +| usb_debug| | hooks | +|| || +|usbcore | || +|| |debug capability| +|xhci_hcd| | driver | +|| || +|xHC without DbC | | xHC with DbC | +|or DbC disabled | | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + | | + |_| + + + Port Multiplexing + - + +A debug port is always multiplexed with the first xHCI root hub port. +Whenever debug capability is supported and enabled, and the first root +hub port is detected to be connected to a downstream super-speed port +of a Debug Host, the root hub port is assigned to the debug capability +and operating
[PATCH v2 04/12] usb: xhci: dbc: add support for Intel xHCI dbc quirk
On Intel platform, if the debug target is connected with debug host, enabling DCE bit in command register leads to a hung bus state. In the hung state, the host system will not see a port connected status bit set. Hence debug target fails to be probed. The state could be resolved by performing a port reset to the debug port from the host xHCI. This patch introduces this work around. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 52 include/linux/usb/xhci-dbc.h | 2 ++ 2 files changed, 54 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 22a1de9..6b23f09 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -255,6 +255,8 @@ static void __iomem *xdbc_map_pci_mmio(u32 bus, xdbcp->bar = bar; xdbcp->xhci_base = base; xdbcp->xhci_length = sz64; + xdbcp->vendor = read_pci_config_16(bus, dev, func, PCI_VENDOR_ID); + xdbcp->device = read_pci_config_16(bus, dev, func, PCI_DEVICE_ID); if (length) *length = sz64; @@ -651,6 +653,52 @@ static int xdbc_mem_init(void) return 0; } +static void xdbc_reset_debug_port_callback(int cap_offset, void *data) +{ + u8 major; + u32 val, port_offset, port_count; + u32 cap_length; + void __iomem *ops_reg; + void __iomem *portsc; + int i; + + val = readl(xdbcp->xhci_base + cap_offset); + major = (u8) XHCI_EXT_PORT_MAJOR(val); + + /* only reset super-speed port */ + if (major != 0x3) + return; + + val = readl(xdbcp->xhci_base + cap_offset + 8); + port_offset = XHCI_EXT_PORT_OFF(val); + port_count = XHCI_EXT_PORT_COUNT(val); + xdbc_trace("Extcap Port offset %d count %d\n", + port_offset, port_count); + + cap_length = readl(xdbcp->xhci_base) & 0xff; + ops_reg = xdbcp->xhci_base + cap_length; + + port_offset--; + for (i = port_offset; i < (port_offset + port_count); i++) { + portsc = ops_reg + 0x400 + i * 0x10; + val = readl(portsc); + /* reset the port if CCS bit is cleared */ + if (!(val & 0x1)) + writel(val | (1 << 4), portsc); + } +} + +static void xdbc_reset_debug_port(void) +{ + xdbc_walk_excap(xdbcp->bus, + xdbcp->dev, + xdbcp->func, + XHCI_EXT_CAPS_PROTOCOL, + false, + xdbc_reset_debug_port_callback, + NULL); +} + /* * xdbc_start: start DbC * @@ -669,6 +717,10 @@ static int xdbc_start(void) return -ENODEV; } + /* reset port to avoid bus hang */ + if (xdbcp->vendor == PCI_VENDOR_ID_INTEL) + xdbc_reset_debug_port(); + /* wait for port connection */ if (handshake(&xdbcp->xdbc_reg->portsc, PORTSC_CCS, PORTSC_CCS, 500, 100) < 0) { diff --git a/include/linux/usb/xhci-dbc.h b/include/linux/usb/xhci-dbc.h index 153fb87..fc0ef9a 100644 --- a/include/linux/usb/xhci-dbc.h +++ b/include/linux/usb/xhci-dbc.h @@ -128,6 +128,8 @@ struct xdbc_state { u32 dev; u32 func; u8 bar; + u16 vendor; + u16 device; void __iomem*xhci_base; size_t xhci_length; #defineXDBC_PCI_MAX_BUSES 256 -- 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 v2 09/12] x86: early_printk: add USB3 debug port earlyprintk support
Add support for early printk by writing debug messages to the USB3 debug port. Users can use this type of early printk by specifying kernel parameter of "earlyprintk=xdbc". This gives users a chance of providing debug output. Signed-off-by: Lu Baolu --- Documentation/kernel-parameters.txt | 1 + arch/x86/kernel/early_printk.c | 5 + drivers/usb/early/xhci-dbc.c| 43 + include/linux/usb/xhci-dbc.h| 5 + 4 files changed, 54 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 22a4b68..b65b07f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1032,6 +1032,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] earlyprintk=pciserial,bus:device.function[,baudrate] + earlyprintk=xdbc[xhciController#] earlyprintk is useful when the kernel crashes before the normal console is initialized. It is not enabled by diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index eec40f5..5341a16 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -373,6 +374,10 @@ static int __init setup_early_printk(char *buf) if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4)) early_console_register(&early_dbgp_console, keep); #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!strncmp(buf, "xdbc", 4) && !early_xdbc_init(buf + 4)) + early_console_register(&early_xdbc_console, keep); +#endif #ifdef CONFIG_HVC_XEN if (!strncmp(buf, "xen", 3)) early_console_register(&xenboot_console, keep); diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index aaf655f..68a7139 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -10,6 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -1332,3 +1333,45 @@ int xdbc_bulk_write(const char *bytes, int size) return ret; } + +/* + * Start a bulk-in or bulk-out transfer, wait until transfer completion + * or error. Return the count of actually transferred bytes or error. + */ +static void early_xdbc_write(struct console *con, const char *str, u32 n) +{ + int chunk, ret; + static char buf[XDBC_MAX_PACKET]; + int use_cr = 0; + + if (!xdbcp->xdbc_reg) + return; + memset(buf, 0, XDBC_MAX_PACKET); + while (n > 0) { + for (chunk = 0; chunk < XDBC_MAX_PACKET && n > 0; +str++, chunk++, n--) { + if (!use_cr && *str == '\n') { + use_cr = 1; + buf[chunk] = '\r'; + str--; + n++; + continue; + } + if (use_cr) + use_cr = 0; + buf[chunk] = *str; + } + if (chunk > 0) { + ret = xdbc_bulk_write(buf, chunk); + if (ret < 0) + break; + } + } +} + +struct console early_xdbc_console = { + .name = "earlyxdbc", + .write =early_xdbc_write, + .flags =CON_PRINTBUFFER, + .index =-1, +}; diff --git a/include/linux/usb/xhci-dbc.h b/include/linux/usb/xhci-dbc.h index 289ba58..a556eb8 100644 --- a/include/linux/usb/xhci-dbc.h +++ b/include/linux/usb/xhci-dbc.h @@ -216,4 +216,9 @@ struct xdbc_state { #definexdbc_read64(regs) xhci_read_64(NULL, (regs)) #definexdbc_write64(val, regs) xhci_write_64(NULL, (val), (regs)) +#ifdef CONFIG_EARLY_PRINTK_XDBC +extern int early_xdbc_init(char *s); +extern struct console early_xdbc_console; +#endif /* CONFIG_EARLY_PRINTK_XDBC */ + #endif /* __LINUX_XHCI_DBC_H */ -- 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 v2 00/12] usb: early: add support for early printk through USB3 debug port
This patch series adds support for early printk through USB3 debug port. USB3 debug port is described in xHCI specification as an optional extended capability. The first patch adds a file in sysfs, through which users can check whether the debug capability is supported by a specific host controller, and the hardware state. Patch 2 to 10 add the driver for xHCI debug capability. It interfaces with the register set and provides the required ops (read/write/control) to upper layers. Early printk is one consumer of these ops. The hooks for early printk are introduced in patch 9. This design is similar to what we have done in drivers/usb/early/ehci-dbgp.c. Patch 11 is a minor change to usb_debug module. This change is required to bind usb_debug with the USB3 debug device. Patch 12 is the design document and user guide. Change log: v1->v2: (1) Patch 1 re-implemented. "debugfs" has been replaced with sysfs. The scope reduced from all extended capabilities to debug port specific. (2) Patch 11 changed. Removed unnecessary .bulk_out_size setting. Lu Baolu (12): usb: xhci: add sysfs file for xHCI debug port x86: fixmap: add permanent fixmap for xhci debug port usb: xhci: dbc: probe and setup xhci debug capability usb: xhci: dbc: add support for Intel xHCI dbc quirk usb: xhci: dbc: add debug buffer usb: xhci: dbc: add bulk out and bulk in interfaces usb: xhci: dbc: handle dbc-configured exit usb: xhci: dbc: handle endpoint stall x86: early_printk: add USB3 debug port earlyprintk support usb: xhci: dbc: add handshake between debug target and host usb: serial: usb_debug: add support for dbc debug device usb: doc: add document for xHCI DbC driver .../ABI/testing/sysfs-bus-pci-drivers-xhci_hcd | 23 + Documentation/kernel-parameters.txt|1 + Documentation/usb/xhci-dbc.txt | 325 + MAINTAINERS|8 + arch/x86/Kconfig.debug | 12 + arch/x86/include/asm/fixmap.h |4 + arch/x86/kernel/early_printk.c |5 + drivers/usb/early/Makefile |1 + drivers/usb/early/xhci-dbc.c | 1407 drivers/usb/host/Makefile |2 +- drivers/usb/host/xhci-ext-caps.h | 14 +- drivers/usb/host/xhci-sysfs.c | 100 ++ drivers/usb/host/xhci.c|4 + drivers/usb/host/xhci.h|4 + drivers/usb/serial/usb_debug.c | 28 +- include/linux/usb/xhci-dbc.h | 224 16 files changed, 2157 insertions(+), 5 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd create mode 100644 Documentation/usb/xhci-dbc.txt create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 drivers/usb/host/xhci-sysfs.c create mode 100644 include/linux/usb/xhci-dbc.h -- 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 v2 06/12] usb: xhci: dbc: add bulk out and bulk in interfaces
This patch adds interfaces for bulk out and bulk in ops. These interfaces could be used to implement early printk bootconsole or hook to various system debuggers. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 373 +++ include/linux/usb/xhci-dbc.h | 30 2 files changed, 403 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index b36a527..f51daa4 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -219,11 +219,21 @@ static void xdbc_dbg_dump_data(char *str) xdbc_dbg_dump_string("String Descriptor:"); } +static void xdbc_dbg_dump_trb(struct xdbc_trb *trb, char *str) +{ + xdbc_trace("DBC trb: %s\n", str); + xdbc_trace("@%016llx %08x %08x %08x %08x\n", (u64)__pa(trb), + le32_to_cpu(trb->field[0]), + le32_to_cpu(trb->field[1]), + le32_to_cpu(trb->field[2]), + le32_to_cpu(trb->field[3])); +} #else static inline void xdbc_trace(const char *fmt, ...) { } static inline void xdbc_dump_debug_buffer(void) { } static inline void xdbc_dbg_dump_regs(char *str) { } static inline void xdbc_dbg_dump_data(char *str) { } +static inline void xdbc_dbg_dump_trb(struct xdbc_trb *trb, char *str) { } #endif /* DBC_DEBUG */ /* @@ -334,6 +344,7 @@ static void *xdbc_get_page(dma_addr_t *dma_addr, static char in_ring_page[PAGE_SIZE] __aligned(PAGE_SIZE); static char out_ring_page[PAGE_SIZE] __aligned(PAGE_SIZE); static char table_page[PAGE_SIZE] __aligned(PAGE_SIZE); + static char bulk_buf_page[PAGE_SIZE] __aligned(PAGE_SIZE); switch (type) { case XDBC_PAGE_EVENT: @@ -348,6 +359,9 @@ static void *xdbc_get_page(dma_addr_t *dma_addr, case XDBC_PAGE_TABLE: virt = (void *)table_page; break; + case XDBC_PAGE_BUFFER: + virt = (void *)bulk_buf_page; + break; default: return NULL; } @@ -707,6 +721,12 @@ static int xdbc_mem_init(void) dev_info = cpu_to_le32((XDBC_DEVICE_REV << 16) | XDBC_PRODUCT_ID); writel(dev_info, &xdbcp->xdbc_reg->devinfo2); + /* get and store the transfer buffer */ + xdbcp->out_buf = xdbc_get_page(&xdbcp->out_dma, + XDBC_PAGE_BUFFER); + xdbcp->in_buf = xdbcp->out_buf + XDBC_MAX_PACKET; + xdbcp->in_dma = xdbcp->out_dma + XDBC_MAX_PACKET; + return 0; } @@ -802,6 +822,9 @@ static int xdbc_start(void) xdbc_trace("root hub port number %d\n", DCST_DPN(status)); + xdbcp->in_ep_state = EP_RUNNING; + xdbcp->out_ep_state = EP_RUNNING; + xdbc_trace("DbC is running now, control 0x%08x\n", readl(&xdbcp->xdbc_reg->control)); @@ -895,3 +918,353 @@ int __init early_xdbc_init(char *s) return 0; } + +static void xdbc_queue_trb(struct xdbc_ring *ring, + u32 field1, u32 field2, u32 field3, u32 field4) +{ + struct xdbc_trb *trb, *link_trb; + + trb = ring->enqueue; + trb->field[0] = cpu_to_le32(field1); + trb->field[1] = cpu_to_le32(field2); + trb->field[2] = cpu_to_le32(field3); + trb->field[3] = cpu_to_le32(field4); + + xdbc_dbg_dump_trb(trb, "enqueue trb"); + + ++(ring->enqueue); + if (ring->enqueue >= &ring->segment->trbs[TRBS_PER_SEGMENT - 1]) { + link_trb = ring->enqueue; + if (ring->cycle_state) + link_trb->field[3] |= cpu_to_le32(TRB_CYCLE); + else + link_trb->field[3] &= cpu_to_le32(~TRB_CYCLE); + + ring->enqueue = ring->segment->trbs; + ring->cycle_state ^= 1; + } +} + +static void xdbc_ring_doorbell(int target) +{ + writel(DOOR_BELL_TARGET(target), &xdbcp->xdbc_reg->doorbell); +} + +static void xdbc_handle_port_status(struct xdbc_trb *evt_trb) +{ + u32 port_reg; + + port_reg = readl(&xdbcp->xdbc_reg->portsc); + + if (port_reg & PORTSC_CSC) { + xdbc_trace("%s: connect status change event\n", __func__); + writel(port_reg | PORTSC_CSC, &xdbcp->xdbc_reg->portsc); + port_reg = readl(&xdbcp->xdbc_reg->portsc); + } + + if (port_reg & PORTSC_PRC) { + xdbc_trace("%s: port reset change event\n", __func__); + writel(port_reg | PORTSC_PRC, &xdbcp->xdbc_reg->portsc); + port_reg = readl(&xdbcp->xdbc_reg->portsc); + } + + if (port_reg & PORTSC_PLC) { + xdbc_trace("%s: port l
[PATCH v2 10/12] usb: xhci: dbc: add handshake between debug target and host
After DbC setup, debug target needs to wait until tty driver and application (e.g. mincom) on debug taget start. Otherwise, out messages might be ignored. This patch adds a ping/pong mechanism between debug target and host. Debug target will be waiting there until user presses 'Y' or 'y' in the tty application. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 68a7139..b75c523 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -32,6 +32,9 @@ static struct xdbc_state xdbc_stat; static struct xdbc_state *xdbcp = &xdbc_stat; +static int early_xdbc_read(struct console *con, char *str, unsigned n); +static void early_xdbc_write(struct console *con, const char *str, u32 n); + #ifdef DBC_DEBUG #defineXDBC_DEBUG_BUF_SIZE (PAGE_SIZE * 32) #defineMSG_MAX_LINE128 @@ -873,8 +876,12 @@ int __init early_xdbc_init(char *s) { u32 bus = 0, dev = 0, func = 0; unsigned long dbgp_num = 0; + char *ping = "Press Y to continue...\n"; + char pong[64]; + size_t size; u32 offset; int ret; + int retry = 20; if (!early_pci_allowed()) return -EPERM; @@ -917,6 +924,21 @@ int __init early_xdbc_init(char *s) return ret; } + while (retry > 0) { + early_xdbc_write(NULL, ping, strlen(ping)); + size = early_xdbc_read(NULL, pong, 64); + if (size > 0) { + xdbc_trace("%s: pong message: %s\n", __func__, pong); + if (pong[0] == 'Y' || pong[0] == 'y') + break; + } else { + xdbc_trace("%s: pong message error %d\n", + __func__, size); + } + + retry--; + } + return 0; } @@ -1338,6 +1360,11 @@ int xdbc_bulk_write(const char *bytes, int size) * Start a bulk-in or bulk-out transfer, wait until transfer completion * or error. Return the count of actually transferred bytes or error. */ +static int early_xdbc_read(struct console *con, char *str, unsigned n) +{ + return xdbc_bulk_read(str, n, 0); +} + static void early_xdbc_write(struct console *con, const char *str, u32 n) { int chunk, ret; -- 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 v2 08/12] usb: xhci: dbc: handle endpoint stall
In case of endpoint stall, software is able to detect the situation by reading DCCTRL.HIT or DCCTRL.HOT bits. DbC follows the normal USB framework to handle endpoint stall. When software detects endpoint stall situation, it should wait until endpoint is recovered before read or write oprations. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 36 1 file changed, 36 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index 8a5a51f..aaf655f 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -1176,6 +1176,37 @@ static int xdbc_wait_until_dbc_configured(void) return -ETIMEDOUT; } +static int xdbc_wait_until_epstall_cleared(bool read) +{ + int timeout = 0; + + if (read) { + do { + if (!(readl(&xdbcp->xdbc_reg->control) & CTRL_HIT)) { + xdbcp->in_ep_state = EP_RUNNING; + + return 0; + } + + xdbcp->in_ep_state = EP_HALTED; + xdbc_udelay(10); + } while (timeout++ < XDBC_LOOPS); + } else { + do { + if (!(readl(&xdbcp->xdbc_reg->control) & CTRL_HOT)) { + xdbcp->out_ep_state = EP_RUNNING; + + return 0; + } + + xdbcp->out_ep_state = EP_HALTED; + xdbc_udelay(10); + } while (timeout++ < XDBC_LOOPS); + } + + return -ETIMEDOUT; +} + static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) { u64 addr; @@ -1195,6 +1226,11 @@ static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) return -EPERM; } + if (xdbc_wait_until_epstall_cleared(read)) { + xdbc_trace("%s: endpoint not ready\n", __func__); + return -EPERM; + } + ring = (read ? &xdbcp->in_ring : &xdbcp->out_ring); trb = ring->enqueue; cycle = ring->cycle_state; -- 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 v2 02/12] x86: fixmap: add permanent fixmap for xhci debug port
xHCI compatible USB3 host controller may provide debug capability which enables low-level system debug over USB. In order to probing this debug capability, Linux kernel needs to map and access the mmio of the host controller during early boot. This patch adds permenent fixmap pages in fixed_addresses table for xHCI mmio access. Signed-off-by: Lu Baolu --- arch/x86/include/asm/fixmap.h | 4 1 file changed, 4 insertions(+) diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index f80d700..fbf452f 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -82,6 +82,10 @@ enum fixed_addresses { #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT FIX_OHCI1394_BASE, #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + FIX_XDBC_BASE, + FIX_XDBC_END = FIX_XDBC_BASE + 15, +#endif #ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ #endif -- 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 v2 07/12] usb: xhci: dbc: handle dbc-configured exit
DbC might exit configured state in some cases (refer to 7.6.4.4 in xHCI spec 1.1). Software needs detect and clear this situation by clearing DCCTRL.DCR and wait until the DbC configured before read or write oprations. Signed-off-by: Lu Baolu --- drivers/usb/early/xhci-dbc.c | 28 1 file changed, 28 insertions(+) diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index f51daa4..8a5a51f 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -1153,6 +1153,29 @@ static int xdbc_wait_until_bulk_done(struct xdbc_trb *trb, int loops) return -EIO; } +static int xdbc_wait_until_dbc_configured(void) +{ + int timeout = 0; + u32 reg; + + /* Port exits configured state */ + reg = readl(&xdbcp->xdbc_reg->control); + if (!(reg & CTRL_DRC)) + return 0; + + /* clear run change bit (RW1C) */ + writel(reg | CTRL_DRC, &xdbcp->xdbc_reg->control); + + do { + if (readl(&xdbcp->xdbc_reg->control) & CTRL_DCR) + return 0; + + xdbc_udelay(10); + } while (timeout++ < XDBC_LOOPS); + + return -ETIMEDOUT; +} + static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) { u64 addr; @@ -1167,6 +1190,11 @@ static int xdbc_bulk_transfer(void *data, int size, int loops, bool read) return -EINVAL; } + if (xdbc_wait_until_dbc_configured()) { + xdbc_trace("%s: hardware not ready\n", __func__); + return -EPERM; + } + ring = (read ? &xdbcp->in_ring : &xdbcp->out_ring); trb = ring->enqueue; cycle = ring->cycle_state; -- 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 v2 01/12] usb: xhci: add sysfs file for xHCI debug port
This patch adds a sysfs file for users to check 1) whether the debug capability is implemented by hardware; 2) if supported, which state does it stay at. With a host that supports debug port, a file named "debug_port_state" will be created under the device sysfs directory. Reading this file will show users the state (disabled, enabled or configured) of the debug port. With a host that does NOT support debug port, "debug_port_state" file won't be created. Signed-off-by: Lu Baolu --- .../ABI/testing/sysfs-bus-pci-drivers-xhci_hcd | 23 + drivers/usb/host/Makefile | 2 +- drivers/usb/host/xhci-ext-caps.h | 14 ++- drivers/usb/host/xhci-sysfs.c | 100 + drivers/usb/host/xhci.c| 4 + drivers/usb/host/xhci.h| 4 + 6 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd create mode 100644 drivers/usb/host/xhci-sysfs.c diff --git a/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd new file mode 100644 index 000..dd3e722 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd @@ -0,0 +1,23 @@ +What: /sys/bus/pci/drivers/xhci_hcd/.../debug_port_state +Date: November 2015 +KernelVersion: 4.3.0 +Contact: Lu Baolu +Description: + This file is designed for users to check the state of a + USB3 debug port. On a machine which supports USB3 debug + port, this file will be created. Reading this file will + show the state (disabled, enabled or configured) of the + debug port. On a machine that doesn't support USB3 debug + port, this file doesn't exist. + + The state of a debug port could be: + 1) disabled: The debug port is not enabled and the root + port has been switched to xHCI host as a normal + root port. + 2) enabled: The debug port is enabled. The debug port + has been assigned to debug capability. The debug + capability is able to handle the control requests + defined in USB3 spec. + 3) configured: The debug port has been enumerated by the + debug host as a debug device. The debug port is + in use now. diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index e7558ab..810c304 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -12,7 +12,7 @@ fhci-$(CONFIG_FHCI_DEBUG) += fhci-dbg.o xhci-hcd-y := xhci.o xhci-mem.o xhci-hcd-y += xhci-ring.o xhci-hub.o xhci-dbg.o -xhci-hcd-y += xhci-trace.o +xhci-hcd-y += xhci-trace.o xhci-sysfs.o xhci-plat-hcd-y := xhci-plat.o ifneq ($(CONFIG_USB_XHCI_MVEBU), ) diff --git a/drivers/usb/host/xhci-ext-caps.h b/drivers/usb/host/xhci-ext-caps.h index 9fe3225..12c87e5 100644 --- a/drivers/usb/host/xhci-ext-caps.h +++ b/drivers/usb/host/xhci-ext-caps.h @@ -49,8 +49,15 @@ #define XHCI_EXT_CAPS_PM 3 #define XHCI_EXT_CAPS_VIRT 4 #define XHCI_EXT_CAPS_ROUTE5 -/* IDs 6-9 reserved */ +#define XHCI_EXT_CAPS_LOCALMEM 6 +/* IDs 7-9 reserved */ #define XHCI_EXT_CAPS_DEBUG10 +/* IDs 192-255 vendor specific */ +#define XHCI_EXT_CAPS_VEN_START192 +#define XHCI_EXT_CAPS_VEN_END 255 +#define XHCI_EXT_CAPS_VENDOR(p)(((p) >= XHCI_EXT_CAPS_VEN_START) && \ + ((p) <= XHCI_EXT_CAPS_VEN_END)) +#define XHCI_EXT_MAX_CAPID XHCI_EXT_CAPS_VEN_END /* USB Legacy Support Capability - section 7.1.1 */ #define XHCI_HC_BIOS_OWNED (1 << 16) #define XHCI_HC_OS_OWNED (1 << 24) @@ -73,6 +80,11 @@ #define XHCI_HLC (1 << 19) #define XHCI_BLC (1 << 20) +/* Debug capability - section 7.6.8 */ +#define XHCI_DBC_DCCTRL0x20 +#define XHCI_DBC_DCCTRL_DCR(1 << 0) +#defineXHCI_DBC_DCCTRL_DCE (1 << 31) + /* command register values to disable interrupts and halt the HC */ /* start/stop HC execution - do not write unless HC is halted*/ #define XHCI_CMD_RUN (1 << 0) diff --git a/drivers/usb/host/xhci-sysfs.c b/drivers/usb/host/xhci-sysfs.c new file mode 100644 index 000..0192ac4 --- /dev/null +++ b/drivers/usb/host/xhci-sysfs.c @@ -0,0 +1,100 @@ +/* + * sysfs interface for xHCI host controller driver + * + * Copyright (C) 2015 Intel Corp. + * + * Author: Lu Baolu + * + * 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 + +#include "xhci.h" + +/*
[PATCH v2 11/12] usb: serial: usb_debug: add support for dbc debug device
This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu --- drivers/usb/serial/usb_debug.c | 28 +--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..92f7e5c 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); /* This HW really does not support a serial break, so one will be * emulated when ever the break state is set to true. @@ -71,9 +82,20 @@ static struct usb_serial_driver debug_device = { .process_read_urb = usb_debug_process_read_urb, }; +static struct usb_serial_driver dbc_device = { + .driver = { + .owner =THIS_MODULE, + .name = "xhci_dbc", + }, + .id_table = dbc_id_table, + .num_ports =1, + .break_ctl =usb_debug_break_ctl, + .process_read_urb = usb_debug_process_read_urb, +}; + static struct usb_serial_driver * const serial_drivers[] = { - &debug_device, NULL + &debug_device, &dbc_device, NULL }; -module_usb_serial_driver(serial_drivers, id_table); +module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_LICENSE("GPL"); -- 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 v2 03/12] usb: xhci: dbc: probe and setup xhci debug capability
xHCI debug capability (DbC) is an optional functionality provided by an xHCI host controller. Software learns this capability by walking through the extended capability list in mmio of the host. This patch introduces the code to probe and initialize the debug capability hardware during early boot. With hardware initialization done, the debug target (system under debug which has DbC enabled) will present a debug device through the debug port. The debug device is fully compliant with the USB framework and provides the equivalent of a very high performance (USB3) full-duplex serial link between the debug host and target. Signed-off-by: Lu Baolu --- MAINTAINERS | 7 + arch/x86/Kconfig.debug | 12 + drivers/usb/early/Makefile | 1 + drivers/usb/early/xhci-dbc.c | 787 +++ include/linux/usb/xhci-dbc.h | 187 ++ 5 files changed, 994 insertions(+) create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 include/linux/usb/xhci-dbc.h diff --git a/MAINTAINERS b/MAINTAINERS index 0425167..585a369 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -11040,6 +11040,13 @@ S: Supported F: drivers/usb/host/xhci* F: drivers/usb/host/pci-quirks* +USB XHCI DEBUG PORT +M: Lu Baolu +L: linux-usb@vger.kernel.org +S: Supported +F: drivers/usb/early/xhci-dbc.c +F: include/linux/usb/xhci-dbc.h + USB ZD1201 DRIVER L: linux-wirel...@vger.kernel.org W: http://linux-lc100020.sourceforge.net diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index d8c0d32..8d95abd 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -65,6 +65,18 @@ config EARLY_PRINTK_EFI This is useful for kernel debugging when your machine crashes very early before the console code is initialized. +config EARLY_PRINTK_XDBC + bool "Early printk via xHCI debug port" + depends on EARLY_PRINTK && PCI + ---help--- + Write kernel log output directly into the xHCI debug port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config X86_PTDUMP bool "Export kernel pagetable layout to userspace via debugfs" depends on DEBUG_KERNEL diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile index 24bbe51..2db5906 100644 --- a/drivers/usb/early/Makefile +++ b/drivers/usb/early/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o +obj-$(CONFIG_EARLY_PRINTK_XDBC) += xhci-dbc.o diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c new file mode 100644 index 000..22a1de9 --- /dev/null +++ b/drivers/usb/early/xhci-dbc.c @@ -0,0 +1,787 @@ +/** + * xhci-dbc.c - xHCI debug capability driver + * + * Copyright (C) 2015 Intel Corporation + * + * Author: Lu Baolu + * Some code shared with EHCI debug port and xHCI driver. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../host/xhci.h" + +#defineXDBC_PROTOCOL 1 /* GNU Remote Debug Command Set */ +#defineXDBC_VENDOR_ID 0x1d6b /* Linux Foundation 0x1d6b */ +#defineXDBC_PRODUCT_ID 0x0004 /* __le16 idProduct; device 0004 */ +#defineXDBC_DEVICE_REV 0x0010 /* 0.10 */ + +static struct xdbc_state xdbc_stat; +static struct xdbc_state *xdbcp = &xdbc_stat; + +#ifdef DBC_DEBUG +/* place holder */ +#definexdbc_trace printk +static void xdbc_dbg_dump_regs(char *str) +{ + if (!xdbcp->xdbc_reg) { + xdbc_trace("register not mapped\n"); + return; + } + + xdbc_trace("XDBC registers: %s\n", str); + xdbc_trace(" Capability: %08x\n", + readl(&xdbcp->xdbc_reg->capability)); + xdbc_trace(" Door bell: %08x\n", + readl(&xdbcp->xdbc_reg->doorbell)); + xdbc_trace(" Event Ring Segment Table Size: %08x\n", + readl(&xdbcp->xdbc_reg->ersts)); + xdbc_trace(" Event Ring Segment Table Base Address: %16llx\n", + xdbc_read64(&xdbcp->xdbc_reg->erstba)); + xdbc_trace(" Event Ring Dequeue Pointer: %16llx\n", + xdbc_read64(&xdbcp->xdbc_reg->erdp)); +
Re: [PATCH 00/12] usb: early: add support for early printk through USB3 debug port
On 11/03/2015 05:42 PM, Dave Young wrote: On 10/28/15 at 04:00pm, Lu Baolu wrote: This patch series adds support for early printk through USB3 debug port. USB3 debug port is described in xHCI specification as an optional extended capability. The first patch adds a file in debugfs, through which users can check whether the debug capability is supported by a specific host controller. Patch 2 to 10 add the driver for xHCI debug capability. It interfaces with the register set and provides the required ops (read/write/control) to upper layers. Early printk is one consumer of these ops. The hooks for early printk are introduced in patch 9. This design is similar to what we have done in drivers/usb/early/ehci-dbgp.c. Patch 11 is a minor change to usb_debug module. This change is required to bind usb_debug with the USB3 debug device. Patch 12 is the design document and user guide. Nice work, I want to try your patches. But I have only one machine with debug capability, I think I can use it as debug target. Can I use another machine with usb 3.0 but no debug capability as the debug host? Yes, you can. The debug host doesn't require debug capability. Please follow guide in patch 12 when you try it. It has been verified on Intel Skylake machine. BTW, I hacked a cable according to usb 3 spec, cut vbus/d+/d-, cross wired ss pins. Good luck. I just bought one from http://www.datapro.net/products/usb-3-0-super-speed-a-a-debugging-cable.html. Thanks Dave -- 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: Overly conservative xHCI bandwidth estimation
Hi Steinar, Do you mind trying attached patch? This is not a fix but to verify whether LPM really works when only one device is used. You can follow below steps: 1) apply the attached patch on top the latest kernel. 2) build and install the kernel. 3) boot your machine with the new kernel. 4) insert one Blackmagic Design device into USB3 root port. 7) wait for a few seconds 6) check below sysfs nodes: $ cat /sys/bus/usb/devices//power/usb3_hardware_lpm_u1 $ cat /sys/bus/usb/devices//power/usb3_hardware_lpm_u2 Can you please post values of above two sysfs nodes? A copy of dmesg will also be helpful. Thanks, Baolu On 11/05/2015 02:23 AM, Steinar H. Gunderson wrote: On Mon, Nov 02, 2015 at 04:00:42PM -0500, Alan Stern wrote: That commit was included in (approximately) the 4.1.5 or later stable kernel, and it is included in 4.2. You should be able to put one of those on a bootable USB stick. I tried going down this route. After some back and forth, I realize that... the machine has only two USB ports, so I can't boot off USB stick and still test how it behaves with two cards. (I could buy a hub, but that would surely introduce new potential errors in the mix.) So I'm afraid I can't help you at this point. My recommendation to include the patch still stands, though. /* Steinar */ >From c8cd71a0703cf26cfca9d89a3ad451f79c7232af Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Thu, 5 Nov 2015 14:08:48 +0800 Subject: [PATCH 1/2] usb: core: LPM: fix usb3_hardware_lpm sysfs node Commit 655fe4effe0f ("usbcore: add sysfs support to xHCI usb3 hardware LPM") introduced usb3_hardware_lpm sysfs node. This doesn't show the correct status of USB3 U1 and U2 LPM status. This patch fixes this by replacing usb3_hardware_lpm with two nodes, usb3_hardware_lpm_u1 (for U1) and usb3_hardware_lpm_u2 (for U2), and recording the U1/U2 LPM status in right places. Signed-off-by: Lu Baolu --- Documentation/ABI/testing/sysfs-bus-usb | 16 +--- Documentation/usb/power-management.txt | 11 ++- drivers/usb/core/hub.c | 29 + drivers/usb/core/sysfs.c| 28 include/linux/usb.h | 2 ++ 5 files changed, 62 insertions(+), 24 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 3a4abfc..136ba17 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -134,19 +134,21 @@ Description: enabled for the device. Developer can write y/Y/1 or n/N/0 to the file to enable/disable the feature. -What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm -Date: June 2015 +What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm_u1 + /sys/bus/usb/devices/.../power/usb3_hardware_lpm_u2 +Date: November 2015 Contact: Kevin Strasser + Lu Baolu Description: If CONFIG_PM is set and a USB 3.0 lpm-capable device is plugged in to a xHCI host which supports link PM, it will check if U1 and U2 exit latencies have been set in the BOS descriptor; if - the check is is passed and the host supports USB3 hardware LPM, + the check is passed and the host supports USB3 hardware LPM, USB3 hardware LPM will be enabled for the device and the USB - device directory will contain a file named - power/usb3_hardware_lpm. The file holds a string value (enable - or disable) indicating whether or not USB3 hardware LPM is - enabled for the device. + device directory will contain two files named + power/usb3_hardware_lpm_u1 and power/usb3_hardware_lpm_u2. These + files hold a string value (enable or disable) indicating whether + or not USB3 hardware LPM U1 or U2 is enabled for the device. What: /sys/bus/usb/devices/.../removable Date: February 2012 diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt index 4a15c90..0a94ffe 100644 --- a/Documentation/usb/power-management.txt +++ b/Documentation/usb/power-management.txt @@ -537,17 +537,18 @@ relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm. can write y/Y/1 or n/N/0 to the file to enable/disable USB2 hardware LPM manually. This is for test purpose mainly. - power/usb3_hardware_lpm + power/usb3_hardware_lpm_u1 + power/usb3_hardware_lpm_u2 When a USB 3.0 lpm-capable device is plugged in to a xHCI host which supports link PM, it will check if U1 and U2 exit latencies have been set in the BOS descriptor; if the check is is passed and the host supports USB3 hardware LPM, USB3 hardware LPM will be - enabled for the device and this file will be created. - The file holds a string value (enable or disable) - indicating whether or not USB3 hardware LPM is - enabled for the device. + enabled for the device and these files will be created. + The files hold a string value (enable or disable) + indicating whether or not USB3 hardware LPM U1 o
Re: Overly conservative xHCI bandwidth estimation
On 11/06/2015 02:45 AM, Steinar H. Gunderson wrote: On Thu, Nov 05, 2015 at 04:12:24PM +0800, Lu, Baolu wrote: 1) apply the attached patch on top the latest kernel. I applied on top of a clean 4.3.0. $ cat /sys/bus/usb/devices//power/usb3_hardware_lpm_u1 $ cat /sys/bus/usb/devices//power/usb3_hardware_lpm_u2 klump:~> cat /sys/bus/usb/devices/2-2/product Intensity Shuttle klump:~> cat /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u1 disabled klump:~> cat /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u2 disabled Thank you. Have you set CONFIG_PM? Can you reproduce the problem with this kernel? Can you please post values of above two sysfs nodes? A copy of dmesg will also be helpful. Attached. /* Steinar */ -- 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: Overly conservative xHCI bandwidth estimation
On 11/06/2015 08:45 AM, Steinar H. Gunderson wrote: On Fri, Nov 06, 2015 at 08:39:28AM +0800, Lu, Baolu wrote: Have you set CONFIG_PM? Yes. CONFIG_PM=y. Can you reproduce the problem with this kernel? I reproduced the U1/U2 disconnect issues several times. I didn't try the issue of not enough bandwidth for two devices. Can you please try the not enough bandwidth issue? Can you cat /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u1 and /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u2 for several times? Don't use that device when cat these two files. I am hoping that LPM works when only one device is used (hence there is enough bus bandwidth). /* Steinar */ Thanks, Baolu -- 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: Overly conservative xHCI bandwidth estimation
On 11/07/2015 07:05 PM, Steinar H. Gunderson wrote: Can you cat /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u1 >and /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u2 for several >times? Don't use that device when cat these two files. I waited a bit longer, and indeed, now it consistently shows enabled on both cards. klump:~> cat /sys/bus/usb/devices/2-1/power/usb3_hardware_lpm_u1 enabled klump:~> cat /sys/bus/usb/devices/2-1/power/usb3_hardware_lpm_u2 enabled klump:~> cat /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u1 enabled klump:~> cat /sys/bus/usb/devices/2-2/power/usb3_hardware_lpm_u2 enabled That's good. Thank you for your time. We've got below facts: 1. One card works well w/ or w/o LPM enabled. 2. Two cards work well w/o LPM, but not work w/ LPM. The error is "not enough bus bandwidth". We can come to a conclusion that "LPM consumes extra usb bus bandwidth, this extra bandwidth could cause device not to work due to limited bandwidth resources." I have a patch attached in this email. It can disable LPM for any devices during run time. Do you mind having a try? You can follow below steps: 1) apply the attached two patches on top of the latest 4.3 kernel. 0001-usb-core-lpm-fix-usb3_hardware_lpm-sysfs-node.patch 0002-usb-core-lpm-add-sysfs-node-for-usb3-lpm-permit.patch 2) build and install the kernel. 3) boot your machine with the new kernel. 4) insert two Blackmagic Design device into USB3 root port. 5) disable LPM for devices in step 4). # echo "0" > /sys/bus/usb/devices/<1st_device_path>/port/usb3_lpm_permit # echo "0" > /sys/bus/usb/devices/<2nd_device_path>/port/usb3_lpm_permit You can check your setting by reading the sysfs file. They should read 0. 6) start the two devices at the same time, can they work at the same time? Thanks, Baolu For fun, I tried also with a USB 2.0 cable. U1 and U2 comes up as disabled, but of course, the device doesn't work. /* Steinar */ >From 836c0ab187bcc5a08ac3a6d55136203f922ad95b Mon Sep 17 00:00:00 2001 From: Lu Baolu Date: Fri, 6 Nov 2015 09:53:59 +0800 Subject: [PATCH 2/3] usb: core: lpm: add sysfs node for usb3 lpm permit USB3 LPM is default on in Linux kernel if both xHCI host controller and the USB devices declare to be LPM-capable. Unfortunately, some devices are known to work well with LPM disabled, but to be broken if LPM is enabled, although it declares the LPM capability. Users won't be able to use this kind of devices, until someone puts them in the kernel blacklist and gets the kernel upgraded. This patch adds a sysfs node to permit or forbit USB3 LPM U1 or U2 entry for a port. The settings apply to both before and after device enumeration. Supported values are "0" - neither u1 nor u2 permitted, "u1" - only u1 is permitted, "u2" - only u2 is permitted, "u1_u2" - both u1 and u2 are permitted. Signed-off-by: Lu Baolu Signed-off-by: Zhuang Jin Can --- Documentation/ABI/testing/sysfs-bus-usb | 11 drivers/usb/core/hub.c | 15 +- drivers/usb/core/hub.h | 5 +- drivers/usb/core/port.c | 89 - 4 files changed, 116 insertions(+), 4 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 136ba17..4165c37 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -189,6 +189,17 @@ Description: The file will read "hotplug", "wired" and "not used" if the information is available, and "unknown" otherwise. +What: /sys/bus/usb/devices/.../(hub interface)/portX/usb3_lpm_permit +Date: November 2015 +Contact: Lu Baolu +Description: + Some USB3.0 devices may not support usb3 lpm well. usb3_lpm_permit + attribute allows enabling/disabling usb3 lpm of a port. It takes + effect both before and after a usb device is enumerated. Supported + values are "0" if both u1 and u2 are NOT permitted, "u1" if only u1 + is permitted, "u2" if only u2 is permitted, "u1_u2" if both u1 and + u2 are permitted. + What: /sys/bus/usb/devices/.../power/usb2_lpm_l1_timeout Date: May 2013 Contact: Mathias Nyman diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 94a10e0..023e39f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4012,6 +4012,8 @@ EXPORT_SYMBOL_GPL(usb_unlocked_disable_lpm); void usb_enable_lpm(struct usb_device *udev) { struct usb_hcd *hcd; + struct usb_hub *hub; + struct usb_port *port_dev; if (!udev || !udev->parent || udev->speed != USB_SPEED_SUPER || @@ -4031,8 +4033,17 @@ void usb_enable_lpm(struct usb_device *udev) if (udev->lpm_disable_count > 0) return; - usb_enable_link_state(hcd, udev, USB3_LP
[PATCH v3 02/12] x86: fixmap: add permanent fixmap for xhci debug port
xHCI compatible USB3 host controller may provide debug capability which enables low-level system debug over USB. In order to probing this debug capability, Linux kernel needs to map and access the mmio of the host controller during early boot. This patch adds permenent fixmap pages in fixed_addresses table for xHCI mmio access. Signed-off-by: Lu Baolu --- arch/x86/include/asm/fixmap.h | 4 1 file changed, 4 insertions(+) diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h index f80d700..fbf452f 100644 --- a/arch/x86/include/asm/fixmap.h +++ b/arch/x86/include/asm/fixmap.h @@ -82,6 +82,10 @@ enum fixed_addresses { #ifdef CONFIG_PROVIDE_OHCI1394_DMA_INIT FIX_OHCI1394_BASE, #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + FIX_XDBC_BASE, + FIX_XDBC_END = FIX_XDBC_BASE + 15, +#endif #ifdef CONFIG_X86_LOCAL_APIC FIX_APIC_BASE, /* local (CPU) APIC) -- required for SMP or not */ #endif -- 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 v3 00/12] usb: early: add support for early printk through USB3 debug port
This patch series adds support for early printk through USB3 debug port. USB3 debug port is described in xHCI specification as an optional extended capability. The first patch adds a file in sysfs, through which users can check whether the debug capability is supported by a specific host controller, and the hardware state. Patch 2 to 10 add the driver for xHCI debug capability. It interfaces with the register set and provides the required ops (read/write/control) to upper layers. Early printk is one consumer of these ops. The hooks for early printk are introduced in patch 9. This design is similar to what we have done in drivers/usb/early/ehci-dbgp.c. Patch 11 is a minor change to usb_debug module. This change is required to bind usb_debug with the USB3 debug device. Patch 12 is the design document and user guide. Change log: v1->v2: (1) Patch 1 re-implemented. "debugfs" has been replaced with sysfs. The scope reduced from all extended capabilities to debug port specific. (2) Patch 11 changed. Removed unnecessary .bulk_out_size setting. v2->v3: (1) Patch 11 got acked by Johan Hovold. Lu Baolu (12): usb: xhci: add sysfs file for xHCI debug port x86: fixmap: add permanent fixmap for xhci debug port usb: xhci: dbc: probe and setup xhci debug capability usb: xhci: dbc: add support for Intel xHCI dbc quirk usb: xhci: dbc: add debug buffer usb: xhci: dbc: add bulk out and bulk in interfaces usb: xhci: dbc: handle dbc-configured exit usb: xhci: dbc: handle endpoint stall x86: early_printk: add USB3 debug port earlyprintk support usb: xhci: dbc: add handshake between debug target and host usb: serial: usb_debug: add support for dbc debug device usb: doc: add document for xHCI DbC driver .../ABI/testing/sysfs-bus-pci-drivers-xhci_hcd | 23 + Documentation/kernel-parameters.txt|1 + Documentation/usb/xhci-dbc.txt | 325 + MAINTAINERS|8 + arch/x86/Kconfig.debug | 12 + arch/x86/include/asm/fixmap.h |4 + arch/x86/kernel/early_printk.c |5 + drivers/usb/early/Makefile |1 + drivers/usb/early/xhci-dbc.c | 1407 drivers/usb/host/Makefile |2 +- drivers/usb/host/xhci-ext-caps.h | 14 +- drivers/usb/host/xhci-sysfs.c | 100 ++ drivers/usb/host/xhci.c|4 + drivers/usb/host/xhci.h|4 + drivers/usb/serial/usb_debug.c | 28 +- include/linux/usb/xhci-dbc.h | 224 16 files changed, 2157 insertions(+), 5 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-pci-drivers-xhci_hcd create mode 100644 Documentation/usb/xhci-dbc.txt create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 drivers/usb/host/xhci-sysfs.c create mode 100644 include/linux/usb/xhci-dbc.h -- 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 v3 11/12] usb: serial: usb_debug: add support for dbc debug device
This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu Acked-by: Johan Hovold --- drivers/usb/serial/usb_debug.c | 28 +--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..92f7e5c 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); /* This HW really does not support a serial break, so one will be * emulated when ever the break state is set to true. @@ -71,9 +82,20 @@ static struct usb_serial_driver debug_device = { .process_read_urb = usb_debug_process_read_urb, }; +static struct usb_serial_driver dbc_device = { + .driver = { + .owner =THIS_MODULE, + .name = "xhci_dbc", + }, + .id_table = dbc_id_table, + .num_ports =1, + .break_ctl =usb_debug_break_ctl, + .process_read_urb = usb_debug_process_read_urb, +}; + static struct usb_serial_driver * const serial_drivers[] = { - &debug_device, NULL + &debug_device, &dbc_device, NULL }; -module_usb_serial_driver(serial_drivers, id_table); +module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_LICENSE("GPL"); -- 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 v3 12/12] usb: doc: add document for xHCI DbC driver
Add Documentation/usb/xhci-dbc.txt. This document includes development status and user guide for USB3 debug port. Signed-off-by: Lu Baolu --- Documentation/usb/xhci-dbc.txt | 325 + MAINTAINERS| 1 + drivers/usb/early/xhci-dbc.c | 3 + 3 files changed, 329 insertions(+) create mode 100644 Documentation/usb/xhci-dbc.txt diff --git a/Documentation/usb/xhci-dbc.txt b/Documentation/usb/xhci-dbc.txt new file mode 100644 index 000..441b40c --- /dev/null +++ b/Documentation/usb/xhci-dbc.txt @@ -0,0 +1,325 @@ +xHCI debug capability driver + + Lu Baolu + +Last-updated: September 2015 + + + Contents: + - + * What is xHCI DbC? + * Debug topologies + * Debug stacks + * Port Multiplexing + * Hardware initialization + * External reset + * Port reset + * Interrupt/DMA/Memory during early boot + * Endpoint STALL + * Debug device information + * How to use DbC early printk? + * Limitations + + What is xHCI DbC? + - + +The xHCI Debugging Capability defined in section 7.6 of xHCI spec 1.1 +provides an optional functionality that enables low-level system debug +over USB. It provides a means of connecting two systems where one system +is a Debug Host and the other a Debug Target (System Under Test). The +Debug Capability provides an interface that is completely independent +of the xHCI interface. A Debug Target enumerates as a USB debug device +to the Debug Host, allowing a Debug Host to access a Debug Target through +the standard USB software stack. + + Debug topologies + + +Multiple Debug Targets may be attached to a single Debug Host. Debug +Targets may be connected to any downstream facing port below a Debug +Host (i.e. anywhere in the fabric, root port or external hub puts). +A Debug Target may only connect to a Debug Host through a Root Hub port +of the target. That means connection of a Debug Target to a Debug Host +through the ports of an external hub is not supported. + +Below is a typical connection between Debug Host and Debug target. Two +Debug targets are connected to a single Debug host. + + + +| Debug Host | | Debug Target | +|| || +|xHC without DbC | | xHC with DbC | +|or DbC disabled | | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + || | + ||_| + |_ +| + ___| +| HUB | | Debug Target | +|| || +| Superspeed hub | | xHC with DbC | +|| | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + | | + |_| + + Debug stacks + + +Below is a software stack diagram of both Debug Host and Debug Target. + + +| Debug Host | | Debug Target | +|| || +| debug App| || +|| | system debug | +| usb_debug| | hooks | +|| || +|usbcore | || +|| |debug capability| +|xhci_hcd| | driver | +|| || +|xHC without DbC | | xHC with DbC | +|or DbC disabled | | enabled| +|| || +|P1| |p2| |P1| |p2| +|__| |__| |__| |__| + | | + |_| + + + Port Multiplexing + - + +A debug port is always multiplexed with the first xHCI root hub port. +Whenever debug capability is supported and enabled, and the first root +hub port is detected to be connected to a downstream super-speed port +of a Debug Host, the root hub port is assigned to the debug capability +and operating
[PATCH v3 09/12] x86: early_printk: add USB3 debug port earlyprintk support
Add support for early printk by writing debug messages to the USB3 debug port. Users can use this type of early printk by specifying kernel parameter of "earlyprintk=xdbc". This gives users a chance of providing debug output. Signed-off-by: Lu Baolu --- Documentation/kernel-parameters.txt | 1 + arch/x86/kernel/early_printk.c | 5 + drivers/usb/early/xhci-dbc.c| 43 + include/linux/usb/xhci-dbc.h| 5 + 4 files changed, 54 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 22a4b68..b65b07f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1032,6 +1032,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] earlyprintk=pciserial,bus:device.function[,baudrate] + earlyprintk=xdbc[xhciController#] earlyprintk is useful when the kernel crashes before the normal console is initialized. It is not enabled by diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index eec40f5..5341a16 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -373,6 +374,10 @@ static int __init setup_early_printk(char *buf) if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4)) early_console_register(&early_dbgp_console, keep); #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!strncmp(buf, "xdbc", 4) && !early_xdbc_init(buf + 4)) + early_console_register(&early_xdbc_console, keep); +#endif #ifdef CONFIG_HVC_XEN if (!strncmp(buf, "xen", 3)) early_console_register(&xenboot_console, keep); diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c index aaf655f..68a7139 100644 --- a/drivers/usb/early/xhci-dbc.c +++ b/drivers/usb/early/xhci-dbc.c @@ -10,6 +10,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -1332,3 +1333,45 @@ int xdbc_bulk_write(const char *bytes, int size) return ret; } + +/* + * Start a bulk-in or bulk-out transfer, wait until transfer completion + * or error. Return the count of actually transferred bytes or error. + */ +static void early_xdbc_write(struct console *con, const char *str, u32 n) +{ + int chunk, ret; + static char buf[XDBC_MAX_PACKET]; + int use_cr = 0; + + if (!xdbcp->xdbc_reg) + return; + memset(buf, 0, XDBC_MAX_PACKET); + while (n > 0) { + for (chunk = 0; chunk < XDBC_MAX_PACKET && n > 0; +str++, chunk++, n--) { + if (!use_cr && *str == '\n') { + use_cr = 1; + buf[chunk] = '\r'; + str--; + n++; + continue; + } + if (use_cr) + use_cr = 0; + buf[chunk] = *str; + } + if (chunk > 0) { + ret = xdbc_bulk_write(buf, chunk); + if (ret < 0) + break; + } + } +} + +struct console early_xdbc_console = { + .name = "earlyxdbc", + .write =early_xdbc_write, + .flags =CON_PRINTBUFFER, + .index =-1, +}; diff --git a/include/linux/usb/xhci-dbc.h b/include/linux/usb/xhci-dbc.h index 289ba58..a556eb8 100644 --- a/include/linux/usb/xhci-dbc.h +++ b/include/linux/usb/xhci-dbc.h @@ -216,4 +216,9 @@ struct xdbc_state { #definexdbc_read64(regs) xhci_read_64(NULL, (regs)) #definexdbc_write64(val, regs) xhci_write_64(NULL, (val), (regs)) +#ifdef CONFIG_EARLY_PRINTK_XDBC +extern int early_xdbc_init(char *s); +extern struct console early_xdbc_console; +#endif /* CONFIG_EARLY_PRINTK_XDBC */ + #endif /* __LINUX_XHCI_DBC_H */ -- 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