Re: [PATCH v7 1/7] regulator: fixed: add support for ACPI interface

2016-05-03 Thread Lu Baolu
Hi,

On 05/03/2016 07:49 PM, Mark Brown wrote:
> On Tue, May 03, 2016 at 09:43:58AM +0800, Lu Baolu wrote:
>> On 05/02/2016 07:00 PM, Mark Brown wrote:
>>> On Fri, Apr 29, 2016 at 02:26:32PM +0800, Lu Baolu wrote:
>>>> +  gpiod = gpiod_get(dev, "vbus_en", GPIOD_ASIS);
>>>> +  if (IS_ERR(gpiod))
>>>> +  return PTR_ERR(gpiod);
>>> This is clearly an inappropriate name for the signal in generic code,
>>> it's specific to your use case.
>> I will change the gpio name to "gpio". Is that okay?
> Yes, that looks good (and lines up with DT so hopefully the code can be
> shared).

Fair enough. Thanks.

Best regards,
Lu 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 v8 4/7] usb: mux: add driver for Intel drcfg controlled port mux

2016-05-04 Thread Lu Baolu
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 
---
 drivers/usb/mux/Kconfig   |   8 ++
 drivers/usb/mux/Makefile  |   1 +
 drivers/usb/mux/portmux-intel-drcfg.c | 171 ++
 3 files changed, 180 insertions(+)
 create mode 100644 drivers/usb/mux/portmux-intel-drcfg.c

diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
index 1dc1f33..ae3f746 100644
--- a/drivers/usb/mux/Kconfig
+++ b/drivers/usb/mux/Kconfig
@@ -19,4 +19,12 @@ 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 USB_PORTMUX
+   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 4eb5582..0f102b5 100644
--- a/drivers/usb/mux/Makefile
+++ b/drivers/usb/mux/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
 obj-$(CONFIG_INTEL_MUX_GPIO)   += portmux-intel-gpio.o
+obj-$(CONFIG_INTEL_MUX_DRCFG)  += portmux-intel-drcfg.o
diff --git a/drivers/usb/mux/portmux-intel-drcfg.c 
b/drivers/usb/mux/portmux-intel-drcfg.c
new file mode 100644
index 000..0bb6b08
--- /dev/null
+++ b/drivers/usb/mux/portmux-intel-drcfg.c
@@ -0,0 +1,171 @@
+/**
+ * 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 
+#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_MODE  BIT(29)
+
+struct intel_mux_drcfg {
+   struct portmux_desc desc;
+   struct device *dev;
+   void __iomem *regs;
+   struct portmux_dev *pdev;
+};
+
+static inline int intel_mux_drcfg_switch(struct device *dev, bool host)
+{
+   u32 data;
+   struct intel_mux_drcfg *mux;
+
+   mux = dev_get_drvdata(dev);
+
+   /* 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);
+
+   return 0;
+}
+
+static int intel_mux_drcfg_cable_set(struct device *dev)
+{
+   dev_dbg(dev, "drcfg mux switch to HOST\n");
+
+   return intel_mux_drcfg_switch(dev, true);
+}
+
+static int intel_mux_drcfg_cable_unset(struct device *dev)
+{
+   dev_dbg(dev, "drcfg mux switch to DEVICE\n");
+
+   return intel_mux_drcfg_switch(dev, false);
+}
+
+static const struct portmux_ops drcfg_ops = {
+   .cable_set_cb = intel_mux_drcfg_cable_set,
+   .cable_unset_cb = intel_mux_drcfg_cable_unset,
+};
+
+static int intel_mux_drcfg_probe(struct platform_device *pdev)
+{
+   struct intel_mux_drcfg *mux;
+   struct device *dev = &pdev->dev;
+   const char *extcon_name = NULL;
+   u64 start, size;
+   int ret;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   ret = device_property_read_u64(dev, "reg-start", &start);
+   ret |= device_property_read_u64(dev, "reg-size", &size);
+   if (ret)
+   return -ENODEV;
+
+   ret = device_property_read_string(dev, "extcon-name", &extcon_name);
+   if (!ret)
+   mux->desc.extcon_name = extcon_name;
+
+   mux->regs = devm_ioremap_nocache(dev, start, size);
+   if (!mux->regs)
+   return -ENOMEM;
+
+   mux->desc.dev = dev;
+   mux->desc.name = "intel-mux-drcfg";
+   mux->desc.ops = &drcfg_ops;
+   mux->desc.initial_state =
+  

[PATCH v8 7/7] MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

2016-05-04 Thread Lu Baolu
Add a maintainer entry for Intel USB dual role mux drivers and
add myself as a maintainer.

Signed-off-by: Lu Baolu 
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1d5b4be..6ab9e02 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5879,6 +5879,16 @@ S:   Maintained
 F: arch/x86/include/asm/intel_telemetry.h
 F: drivers/platform/x86/intel_telemetry*
 
+INTEL USB DUAL ROLE PORT MUX DRIVERS
+M: Lu Baolu 
+L: linux-usb@vger.kernel.org
+S: Supported
+F: include/linux/usb/portmux.h
+F: drivers/usb/mux/portmux-core.c
+F: drivers/usb/mux/portmux-intel-gpio.c
+F: drivers/usb/mux/portmux-intel-drcfg.c
+F: drivers/mfd/intel-vuport.c
+
 IOC3 ETHERNET DRIVER
 M: Ralf Baechle 
 L: linux-m...@linux-mips.org
-- 
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 v8 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-05-04 Thread Lu Baolu
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| 45 ++--
 drivers/usb/host/xhci-ext-caps.h |  2 ++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 35af362..9bb7aa1 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,8 @@
 #define USB_INTEL_USB3_PSSEN   0xD8
 #define USB_INTEL_USB3PRM  0xDC
 
+#define DEVICE_ID_INTEL_BROXTON_P_XHCI 0x5aa8
+
 /*
  * amd_chipset_gen values represent AMD different chipset generations
  */
@@ -956,6 +959,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_NONE);
+   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 +1060,11 @@ 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_BROXTON_P_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 v8 3/7] usb: mux: add driver for Intel gpio controlled port mux

2016-05-04 Thread Lu Baolu
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.

[baolu: removed .owner per platform_no_drv_owner.cocci]
Signed-off-by: David Cohen 
Signed-off-by: Lu Baolu 
Reviewed-by: Heikki Krogerus 
Reviewed-by: Felipe Balbi 
---
 drivers/usb/mux/Kconfig  |  11 +++
 drivers/usb/mux/Makefile |   1 +
 drivers/usb/mux/portmux-intel-gpio.c | 149 +++
 3 files changed, 161 insertions(+)
 create mode 100644 drivers/usb/mux/portmux-intel-gpio.c

diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
index d91909f..1dc1f33 100644
--- a/drivers/usb/mux/Kconfig
+++ b/drivers/usb/mux/Kconfig
@@ -8,4 +8,15 @@ config USB_PORTMUX
def_bool n
help
  Generic USB dual role port mux support.
+
+config INTEL_MUX_GPIO
+   tristate "Intel dual role port mux controlled by GPIOs"
+   depends on GPIOLIB
+   depends on REGULATOR
+   depends on X86 && ACPI
+   select USB_PORTMUX
+   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 f85df92..4eb5582 100644
--- a/drivers/usb/mux/Makefile
+++ b/drivers/usb/mux/Makefile
@@ -2,3 +2,4 @@
 # Makefile for USB port mux drivers
 #
 obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
+obj-$(CONFIG_INTEL_MUX_GPIO)   += portmux-intel-gpio.o
diff --git a/drivers/usb/mux/portmux-intel-gpio.c 
b/drivers/usb/mux/portmux-intel-gpio.c
new file mode 100644
index 000..b07ae2c
--- /dev/null
+++ b/drivers/usb/mux/portmux-intel-gpio.c
@@ -0,0 +1,149 @@
+/*
+ * 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 
+#include 
+
+struct vuport {
+   struct portmux_desc desc;
+   struct portmux_dev *pdev;
+   struct regulator *regulator;
+   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 device *dev, int id)
+{
+   struct vuport *vup;
+
+   dev_dbg(dev, "USB PORT ID: %s\n", id ? "HOST" : "PERIPHERAL");
+
+   vup = dev_get_drvdata(dev);
+
+   gpiod_set_value_cansleep(vup->gpio_usb_mux, !id);
+
+   if (!id ^ regulator_is_enabled(vup->regulator))
+   return id ? regulator_disable(vup->regulator) :
+   regulator_enable(vup->regulator);
+
+   return 0;
+}
+
+static int vuport_cable_set(struct device *dev)
+{
+   return vuport_set_port(dev, 1);
+}
+
+static int vuport_cable_unset(struct device *dev)
+{
+   return vuport_set_port(dev, 0);
+}
+
+static const struct portmux_ops vuport_ops = {
+   .cable_set_cb = vuport_cable_set,
+   .cable_unset_cb = vuport_cable_unset,
+};
+
+static int vuport_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct vuport *vup;
+
+   vup = devm_kzalloc(dev, sizeof(*vup), GFP_KERNEL);
+   if (!vup)
+   return -ENOMEM;
+
+   vup->regulator = devm_regulator_get_exclusive(dev,
+ "regulator-usb-gpio");
+   if (IS_ERR(vup->regulator))
+   return -EPROBE_DEFER;
+
+   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);
+
+   vup->desc.dev = dev;
+   vup->desc.name = "intel-mux-gpio";
+   vup->desc.extcon_name = "extcon-usb-gpio";
+   vup->desc.ops = &vuport_ops;
+   vup->desc.initial_state = -1;
+   dev_set_drvdata(dev, vup);
+   vup->pdev = portmux_register(&vup->desc);
+
+   return PTR_ERR_OR_ZERO(vup->pdev);
+}
+
+static int vuport_remove(struct platform_device *pdev)
+{
+   struct vuport *vup;
+
+   vup = platform_get_drvdata(pdev);
+   portmux_unregister(vup->pdev);
+
+   return 0;
+}
+
+#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.
+ * 

[PATCH v8 1/7] regulator: fixed: add support for ACPI interface

2016-05-04 Thread Lu Baolu
Add support to retrieve fixed voltage configure information through
ACPI interface. This is needed for Intel Bay Trail devices, where a
GPIO is used to control the USB vbus.

Signed-off-by: Lu Baolu 
---
 drivers/regulator/fixed.c | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index ff62d69..207ab40 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -30,6 +30,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 struct fixed_voltage_data {
struct regulator_desc desc;
@@ -104,6 +107,44 @@ of_get_fixed_voltage_config(struct device *dev,
return config;
 }
 
+/**
+ * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info
+ * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
+ *
+ * Populates fixed_voltage_config structure by extracting data through ACPI
+ * interface, returns a pointer to the populated structure of NULL if memory
+ * alloc fails.
+ */
+static struct fixed_voltage_config *
+acpi_get_fixed_voltage_config(struct device *dev,
+ const struct regulator_desc *desc)
+{
+   struct fixed_voltage_config *config;
+   const char *supply_name;
+   struct gpio_desc *gpiod;
+   int ret;
+
+   config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+   if (!config)
+   return ERR_PTR(-ENOMEM);
+
+   ret = device_property_read_string(dev, "supply-name", &supply_name);
+   if (!ret)
+   config->supply_name = supply_name;
+
+   gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
+   if (IS_ERR(gpiod))
+   return ERR_PTR(-ENODEV);
+
+   config->gpio = desc_to_gpio(gpiod);
+   config->enable_high = device_property_read_bool(dev,
+   "enable-active-high");
+   gpiod_put(gpiod);
+
+   return config;
+}
+
 static struct regulator_ops fixed_voltage_ops = {
 };
 
@@ -124,6 +165,11 @@ static int reg_fixed_voltage_probe(struct platform_device 
*pdev)
 &drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
+   } else if (ACPI_HANDLE(&pdev->dev)) {
+   config = acpi_get_fixed_voltage_config(&pdev->dev,
+  &drvdata->desc);
+   if (IS_ERR(config))
+   return PTR_ERR(config);
} else {
config = dev_get_platdata(&pdev->dev);
}
-- 
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 v8 2/7] usb: mux: add generic code for dual role port mux

2016-05-04 Thread Lu Baolu
Several Intel platforms implement USB dual role by having completely
separate xHCI and dwc3 IPs in PCH or SOC silicons. These two IPs share
a single USB port. There is another external port mux which controls
where the data lines should go. While the USB controllers are part of
the silicon, the port mux design are platform specific.

This patch adds the generic code to handle such usb port mux. It listens
to the USB HOST extcon cable, and switch the port by calling the port
switch ops provided by the individual port mux driver. It also registers
the mux device with sysfs, so that users can control the port mux from
user space.

Some other archs (e.g. Renesas R-Car gen2 SoCs) need an external mux to
swap usb roles as well. This code could be leveraged for those archs
as well.

Signed-off-by: Lu Baolu 
Reviewed-by: Heikki Krogerus 
Reviewed-by: Felipe Balbi 
Reviewed-by: Chanwoo Choi 
[baolu: extcon usage reviewed by Chanwoo Choi]
---
 Documentation/ABI/testing/sysfs-bus-platform |  17 +++
 drivers/usb/Kconfig  |   2 +
 drivers/usb/Makefile |   1 +
 drivers/usb/mux/Kconfig  |  11 ++
 drivers/usb/mux/Makefile |   4 +
 drivers/usb/mux/portmux-core.c   | 217 +++
 include/linux/usb/portmux.h  |  78 ++
 7 files changed, 330 insertions(+)
 create mode 100644 drivers/usb/mux/Kconfig
 create mode 100644 drivers/usb/mux/Makefile
 create mode 100644 drivers/usb/mux/portmux-core.c
 create mode 100644 include/linux/usb/portmux.h

diff --git a/Documentation/ABI/testing/sysfs-bus-platform 
b/Documentation/ABI/testing/sysfs-bus-platform
index 5172a61..f33f0a5 100644
--- a/Documentation/ABI/testing/sysfs-bus-platform
+++ b/Documentation/ABI/testing/sysfs-bus-platform
@@ -18,3 +18,20 @@ 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/.../portmux.N/name
+   /sys/bus/platform/devices/.../portmux.N/state
+Date:  April 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. Read-only attribute "name" shows the name 
of
+   the port mux device. "state" 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/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8689dcb..328916e 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -148,6 +148,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..d91909f
--- /dev/null
+++ b/drivers/usb/mux/Kconfig
@@ -0,0 +1,11 @@
+#
+# USB port mux driver configuration
+#
+
+menu "USB Port MUX drivers"
+config USB_PORTMUX
+   select EXTCON
+   def_bool n
+   help
+ Generic USB dual role port mux support.
+endmenu
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
new file mode 100644
index 000..f85df92
--- /dev/null
+++ b/drivers/usb/mux/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for USB port mux drivers
+#
+obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
diff --git a/drivers/usb/mux/portmux-core.c b/drivers/usb/mux/portmux-core.c
new file mode 100644
index 000..0e3548b
--- /dev/null
+++ b/drivers/usb/mux/portmux-core.c
@@ -0,0 +1,217 @@
+/**
+ * intel_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 
+#include 
+
+static int usb_mux_change_state(struct port

[PATCH v8 5/7] mfd: intel_vuport: Add Intel virtual USB port MFD Driver

2016-05-04 Thread Lu Baolu
Some Intel platforms have an USB port mux controlled by GPIOs.
There's a single ACPI platform device that provides 1) USB ID
extcon device; 2) USB vbus regulator device; and 3) USB port
switch device. This MFD driver will split these 3 devices for
their respective drivers.

[baolu: removed .owner per platform_no_drv_owner.cocci]
Suggested-by: David Cohen 
Signed-off-by: Lu Baolu 
Reviewed-by: Felipe Balbi 
---
 drivers/mfd/Kconfig|  8 +
 drivers/mfd/Makefile   |  1 +
 drivers/mfd/intel-vuport.c | 89 ++
 3 files changed, 98 insertions(+)
 create mode 100644 drivers/mfd/intel-vuport.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index eea61e3..7e115ab 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1578,5 +1578,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's dual role port mux
+ controlled by GPIOs.
+
 endmenu
 endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 5eaa6465d..65b0518 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -203,3 +203,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..fa84ed7
--- /dev/null
+++ b/drivers/mfd/intel-vuport.c
@@ -0,0 +1,89 @@
+/*
+ * 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 
+#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 },
+   { "gpio-gpios", &vbus_gpio, 1 },
+   { "usb_mux-gpios", &mux_gpio, 1 },
+   { },
+};
+
+static struct property_entry reg_properties[] = {
+   PROPERTY_ENTRY_STRING("supply-name", "regulator-usb-gpio"),
+   { },
+};
+
+static const struct property_set reg_properties_pset = {
+   .properties = reg_properties,
+};
+
+static const struct mfd_cell intel_vuport_mfd_cells[] = {
+   { .name = "extcon-usb-gpio", },
+   {
+   .name = "reg-fixed-voltage",
+   .pset = ®_properties_pset,
+   },
+   { .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, PLATFORM_DEVID_NONE,
+   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 v8 0/7] usb: add support for Intel dual role port mux

2016-05-04 Thread Lu Baolu
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 a USB gpio extcon device, a fixed regulator for gpio
controlled USB VCC, 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):
  regulator: fixed: add support for ACPI interface
  usb: mux: add generic code for dual role port mux
  usb: mux: add driver for Intel gpio controlled port mux
  usb: mux: add driver for Intel drcfg controlled port mux
  mfd: intel_vuport: Add Intel virtual USB port MFD Driver
  usb: pci-quirks: add Intel USB drcfg mux device
  MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

Change log:

v7->v8:
 - In patch "regulator: fixed: add support for ACPI interface", the
   fixed regulator gpio name has been changed to "gpio".
 - In patch "MAINTAINERS: add maintainer entry for Intel USB dual role
   mux drivers", filenames have been updated.

v6->v7:
 - Two patches have been picked up by extcon maintainer. Hence,
   remove them since this version.
   - extcon: usb-gpio: add device binding for platform device
   - extcon: usb-gpio: add support for ACPI gpio interface
 - Below patch has been removed from this series because it's unnecessary.
   - regulator: fixed: add device binding for platform device
 - In patch "regulator: fixed: add support for ACPI interface",
   a static gpio name is used to get the regulator gpio.
 - In patch "mfd: intel_vuport: Add Intel virtual USB port MFD Driver",
   unnecessary "gpio-name" string property has been removed.

v5->v6:
 Work internally with Felipe to improve the whole patch series.
 Below changes have been made since last version.
 - rework the common code to make it a generic interface for mux devices;
 - split the vbus gpio handling to a fixed regulator device;
 - removed unnecessary filtering for state change;
 - removed unnecessary WARN statement;
 - removed globals in mux drivers;
 - removed unnecessary register polling and waiting in drcfg driver;

v4->v5:
 - Change the extcon interfaces with the new ones suggested by
   2a9de9c0f08d6 (extcon: Use the unique id for external connector
   instead of string)
 - remove patch "usb: pci-quirks: add Intel USB drcfg mux device"
   from this serial due to that it's not driver staff. Will be
   submitted seperately.

v3->v4:
 - Check all patches with "checkpatch.pl --strict", and fix all
   CHECKs;
 - Change sysfs node from "intel_mux" to "port_mux";
 - Refines below confusing functions:
   intel_usb_mux_register() -> intel_usb_mux_bind_cable()
   intel_usb_mux_unregister() -> intel_usb_mux_unbind_cable();
 - Remove unnecessary struct intel_mux_dev.

v2->v3:
 - uvport mfd driver got reviewed by Lee Jones, the following
   changes were made accordingly.
 - seperate uvport driver from the mux drivers in MAINTAINERS file
 - refine the description in Kconfig
 - refine the mfd_cell structure data

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.

 Documentation/ABI/testing/sysfs-bus-platform |  17 +++
 MAINTAINERS  |  10 ++
 drivers/mfd/Kconfig  |   8 +
 drivers/mfd/Makefile |   1 +
 drivers/mfd/intel-vuport.c   |  89 +++
 driver

Re: [PATCH v8 1/7] regulator: fixed: add support for ACPI interface

2016-05-15 Thread Lu Baolu
Hi,

On 05/13/2016 07:17 PM, Mark Brown wrote:
> On Thu, May 05, 2016 at 01:32:57PM +0800, Lu Baolu wrote:
>
>> +gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
>> +if (IS_ERR(gpiod))
>> +return ERR_PTR(-ENODEV);
>> +config->gpio = desc_to_gpio(gpiod);
>> +config->enable_high = device_property_read_bool(dev,
>> +"enable-active-high");
>> +gpiod_put(gpiod);
> This isn't going to work at all if the GPIO is shared between multiple
> regulators but I can't immediately see a sensible way to fix that
> without some surgery on the GPIO APIs so let's leave it for now.

Okay. Thanks.

Best regards,
Lu 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 v8 2/7] usb: mux: add generic code for dual role port mux

2016-05-25 Thread Lu Baolu
Hi Heikki,

On 05/25/2016 07:06 PM, Heikki Krogerus wrote:
> Hi Baolu,
>
> Sorry to comment this so late, but we got hardware that needs to
> configure the mux in OS, and I noticed some problem.

Comments are always welcome. :-)

> We are missing
> means to bind a port to the correct mux on multiport systems. That we
> need to solve later in any case, but there is an other issue related
> to the fact that the notifiers now have to be extcon devices. It's
> related, as extcon offers no means to solve the multiport issue, but
> in any case..
>
>> +struct portmux_dev *portmux_register(struct portmux_desc *desc)
>> +{
>> +static atomic_t portmux_no = ATOMIC_INIT(-1);
>> +struct portmux_dev *pdev;
>> +struct extcon_dev *edev = NULL;
>> +struct device *dev;
>> +int ret;
>> +
>> +/* parameter sanity check */
>> +if (!desc || !desc->name || !desc->ops || !desc->dev ||
>> +!desc->ops->cable_set_cb || !desc->ops->cable_unset_cb)
>> +return ERR_PTR(-EINVAL);
>> +
>> +dev = desc->dev;
>> +
>> +if (desc->extcon_name) {
>> +edev = extcon_get_extcon_dev(desc->extcon_name);
>> +if (IS_ERR_OR_NULL(edev))
>> +return ERR_PTR(-EPROBE_DEFER);
>> +}
>> +
>> +pdev = kzalloc(sizeof(*pdev), GFP_KERNEL);
>> +if (!pdev)
>> +return ERR_PTR(-ENOMEM);
>> +
>> +pdev->desc = desc;
>> +pdev->edev = edev;
>> +pdev->nb.notifier_call = usb_mux_notifier;
>> +mutex_init(&pdev->mux_mutex);
>> +
>> +pdev->dev.parent = dev;
>> +dev_set_name(&pdev->dev, "portmux.%lu",
>> + (unsigned long)atomic_inc_return(&portmux_no));
>> +pdev->dev.groups = portmux_group;
>> +ret = device_register(&pdev->dev);
>> +if (ret)
>> +goto cleanup_mem;
>> +
>> +dev_set_drvdata(&pdev->dev, pdev);
>> +
>> +if (edev) {
>> +ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
>> +   &pdev->nb);
>> +if (ret < 0) {
>> +dev_err(dev, "failed to register extcon notifier\n");
>> +goto cleanup_dev;
>> +}
>> +}
> So I don't actually think this is correct approach. We are forcing the
> notifying drivers, on top of depending on this framework, depend on
> extcon too, and that simply is too much. I don't think a USB PHY or
> charger detection driver should be forced to generate an extcon device
> just to satisfy the mux in general.

Fair enough.

>
> Instead IMO, this framework should provide an API also for the
> notifiers. The drivers that do the notification should not need to
> depend on extcon at all. Instead they should be able to just request
> an optional handle to a portmux, and use it with the function that you
> already provide (usb_mux_change_state(), which of course needs to be
> exported). That would make it much easier for us to make problems like
> figuring out the correct mux for the correct port a problem for the
> framework and not the drivers.
>
> extcon does not really add any value here, but it does complicate
> things a lot. We are even exposing new sysfs attributes to control the
> mux, complete separate from extcon.

I agree with you that we should move extcon out of the framework.

In order to support multiport systems, I have below proposal.

Currently, we have below interfaces.

struct portmux_dev *portmux_register(struct portmux_desc *desc);
void portmux_unregister(struct portmux_dev *pdev);

I will add below ones.

struct portmux_dev *portmux_lookup_by_name(char *name);
int portmux_switch(struct portmux_dev *pdev, enum port_role);

The normal usage mode is
1) the mux device is registered as soon as a mux is detected with
portmux_register();
2) In components like USB PHY or changer drivers, the mux could
be retrieved with portmux_lookup_by_name() and controlled via
portmux_switch().

Is this helpful?

Best regards,
Lu 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 v8 2/7] usb: mux: add generic code for dual role port mux

2016-05-27 Thread Lu Baolu
Hi,

On 05/27/2016 04:00 PM, Heikki Krogerus wrote:
>> I agree with you that we should move extcon out of the framework.
>> > 
>> > In order to support multiport systems, I have below proposal.
>> > 
>> > Currently, we have below interfaces.
>> > 
>> > struct portmux_dev *portmux_register(struct portmux_desc *desc);
>> > void portmux_unregister(struct portmux_dev *pdev);
>> > 
>> > I will add below ones.
>> > 
>> > struct portmux_dev *portmux_lookup_by_name(char *name);
>> > int portmux_switch(struct portmux_dev *pdev, enum port_role);
>> > 
>> > The normal usage mode is
>> > 1) the mux device is registered as soon as a mux is detected with
>> > portmux_register();
>> > 2) In components like USB PHY or changer drivers, the mux could
>> > be retrieved with portmux_lookup_by_name() and controlled via
>> > portmux_switch().
>> > 
>> > Is this helpful?
> It works for me, and we can improve it later if needed.

Okay, thanks.

Best regards,
Lu 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 v9 0/7] usb: add support for Intel dual role port mux

2016-05-29 Thread Lu Baolu
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 generic framework for port mux devices. It exports interfaces
to register and unregister a port mux device. It also exports
an interface for the port mux consumers (e.x. PHY and charger
drivers) to switch the port role according to the events they
have detected.
(2) Drivers for GPIO controlled port mux which could be found
on Baytrail devices. A mfd driver is used to split the GPIOs
into a USB gpio extcon device, a fixed regulator for gpio
controlled USB VCC, 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.

All patches have been verified to work on Intel's BayTrail,
CherryTrail, and Broxton P platforms.

Lu Baolu (7):
  regulator: fixed: add support for ACPI interface
  usb: mux: add generic code for dual role port mux
  usb: mux: add driver for Intel gpio controlled port mux
  usb: mux: add driver for Intel drcfg controlled port mux
  mfd: intel_vuport: Add Intel virtual USB port MFD Driver
  usb: pci-quirks: add Intel USB drcfg mux device
  MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

Change log:

v8->v9:
 - Patch "mfd: intel_vuport: Add Intel virtual USB port MFD Driver"
   has been ACK-ed by "Lee Jones ".
 - remove extcon dependency out of the generic mux code to support
   systems which have multiple port muxes.
 - Add dev.release for mux device, otherwise, the mux driver module
   couldn't be removed.
 - Use the refreshed device property interface updated in Commit (f4d0526
   device property: don't bother the drivers with struct property_set)

v7->v8:
 - In patch "regulator: fixed: add support for ACPI interface", the
   fixed regulator gpio name has been changed to "gpio".
 - In patch "MAINTAINERS: add maintainer entry for Intel USB dual role
   mux drivers", filenames have been updated.

v6->v7:
 - Two patches have been picked up by extcon maintainer. Hence,
   remove them since this version.
   - extcon: usb-gpio: add device binding for platform device
   - extcon: usb-gpio: add support for ACPI gpio interface
 - Below patch has been removed from this series because it's unnecessary.
   - regulator: fixed: add device binding for platform device
 - In patch "regulator: fixed: add support for ACPI interface",
   a static gpio name is used to get the regulator gpio.
 - In patch "mfd: intel_vuport: Add Intel virtual USB port MFD Driver",
   unnecessary "gpio-name" string property has been removed.

v5->v6:
 Work internally with Felipe to improve the whole patch series.
 Below changes have been made since last version.
 - rework the common code to make it a generic interface for mux devices;
 - split the vbus gpio handling to a fixed regulator device;
 - removed unnecessary filtering for state change;
 - removed unnecessary WARN statement;
 - removed globals in mux drivers;
 - removed unnecessary register polling and waiting in drcfg driver;

v4->v5:
 - Change the extcon interfaces with the new ones suggested by
   2a9de9c0f08d6 (extcon: Use the unique id for external connector
   instead of string)
 - remove patch "usb: pci-quirks: add Intel USB drcfg mux device"
   from this serial due to that it's not driver staff. Will be
   submitted seperately.

v3->v4:
 - Check all patches with "checkpatch.pl --strict", and fix all
   CHECKs;
 - Change sysfs node from "intel_mux" to "port_mux";
 - Refines below confusing functions:
   intel_usb_mux_register() -> intel_usb_mux_bind_cable()
   intel_usb_mux_unregister() -> intel_usb_mux_unbind_cable();
 - Remove unnecessary struct intel_mux_dev.

v2->v3:
 - uvport mfd driver got reviewed by Lee Jones, the following
   changes were made accordingly.
 - seperate uvport driver from the mux drivers in MAINTAINERS file
 - refine the description in Kconfig
 - refine the mfd_cell structure data

v1->v2:
 - move mux driver from drivers/usb/misc t

[PATCH v9 2/7] usb: mux: add generic code for dual role port mux

2016-05-29 Thread Lu Baolu
Several Intel platforms implement USB dual role by having completely
separate xHCI and dwc3 IPs in PCH or SOC silicons. These two IPs share
a single USB port. There is another external port mux which controls
where the data lines should go. While the USB controllers are part of
the silicon, the port mux design are platform specific.

This patch adds the generic code to handle such multiple roles of a
usb port. It exports the necessary interfaces for other components to
register or unregister a usb mux device, and to control its role.
It registers the mux device with sysfs as well, so that users are able
to control the port role from user space.

Some other archs (e.g. Renesas R-Car gen2 SoCs) need an external mux to
swap usb roles as well. This code could also be leveraged for those archs.

Signed-off-by: Lu Baolu 
Reviewed-by: Heikki Krogerus 
Reviewed-by: Felipe Balbi 
---
 Documentation/ABI/testing/sysfs-bus-platform |  18 +++
 drivers/usb/Kconfig  |   2 +
 drivers/usb/Makefile |   1 +
 drivers/usb/mux/Kconfig  |   8 ++
 drivers/usb/mux/Makefile |   4 +
 drivers/usb/mux/portmux-core.c   | 202 +++
 include/linux/usb/portmux.h  |  90 
 7 files changed, 325 insertions(+)
 create mode 100644 drivers/usb/mux/Kconfig
 create mode 100644 drivers/usb/mux/Makefile
 create mode 100644 drivers/usb/mux/portmux-core.c
 create mode 100644 include/linux/usb/portmux.h

diff --git a/Documentation/ABI/testing/sysfs-bus-platform 
b/Documentation/ABI/testing/sysfs-bus-platform
index 5172a61..b994e4e 100644
--- a/Documentation/ABI/testing/sysfs-bus-platform
+++ b/Documentation/ABI/testing/sysfs-bus-platform
@@ -18,3 +18,21 @@ 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/.../portmux.N/name
+   /sys/bus/platform/devices/.../portmux.N/state
+Date:  April 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. Read-only attribute "name" shows the name 
of
+   the port mux device. "state" attribute shows and stores the mux
+   state.
+   For read:
+   'unknown'- the mux hasn't been set yet;
+   'peripheral' - mux has been switched to PERIPHERAL controller;
+   'host'   - mux has been 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/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8689dcb..328916e 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -148,6 +148,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..ba778f2
--- /dev/null
+++ b/drivers/usb/mux/Kconfig
@@ -0,0 +1,8 @@
+#
+# USB port mux driver configuration
+#
+
+menuconfig USB_PORTMUX
+   bool "USB dual role port MUX support"
+   help
+ Generic USB dual role port mux support.
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
new file mode 100644
index 000..f85df92
--- /dev/null
+++ b/drivers/usb/mux/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for USB port mux drivers
+#
+obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
diff --git a/drivers/usb/mux/portmux-core.c b/drivers/usb/mux/portmux-core.c
new file mode 100644
index 000..75fbb45
--- /dev/null
+++ b/drivers/usb/mux/portmux-core.c
@@ -0,0 +1,202 @@
+/**
+ * portmux-core.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 
+
+static int usb_mux_change_state(struct portmux_d

[PATCH v9 5/7] mfd: intel_vuport: Add Intel virtual USB port MFD Driver

2016-05-29 Thread Lu Baolu
Some Intel platforms have an USB port mux controlled by GPIOs.
There's a single ACPI platform device that provides 1) USB ID
extcon device; 2) USB vbus regulator device; and 3) USB port
switch device. This MFD driver will split these 3 devices for
their respective drivers.

[baolu: removed .owner per platform_no_drv_owner.cocci]
Suggested-by: David Cohen 
Signed-off-by: Lu Baolu 
Reviewed-by: Felipe Balbi 
Acked-by: Lee Jones 
---
 drivers/mfd/Kconfig|  8 +
 drivers/mfd/Makefile   |  1 +
 drivers/mfd/intel-vuport.c | 86 ++
 3 files changed, 95 insertions(+)
 create mode 100644 drivers/mfd/intel-vuport.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1bcf601..94affb3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1603,5 +1603,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's dual role port mux
+ controlled by GPIOs.
+
 endmenu
 endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 42a66e1..b86d4f9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -205,3 +205,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..eb27a8f
--- /dev/null
+++ b/drivers/mfd/intel-vuport.c
@@ -0,0 +1,86 @@
+/*
+ * 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 
+#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 },
+   { "gpio-gpios", &vbus_gpio, 1 },
+   { "usb_mux-gpios", &mux_gpio, 1 },
+   { },
+};
+
+static struct property_entry reg_properties[] = {
+   PROPERTY_ENTRY_STRING("supply-name", "regulator-usb-gpio"),
+   { },
+};
+
+static const struct mfd_cell intel_vuport_mfd_cells[] = {
+   { .name = "extcon-usb-gpio", },
+   {
+   .name = "reg-fixed-voltage",
+   .properties = reg_properties,
+   },
+   { .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, PLATFORM_DEVID_NONE,
+   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 v9 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-05-29 Thread Lu Baolu
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| 42 +++-
 drivers/usb/host/xhci-ext-caps.h |  2 ++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 35af362..7e3194f 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -16,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include "pci-quirks.h"
 #include "xhci-ext-caps.h"
 
@@ -78,6 +80,9 @@
 #define USB_INTEL_USB3_PSSEN   0xD8
 #define USB_INTEL_USB3PRM  0xDC
 
+#define DEVICE_ID_INTEL_BROXTON_P_XHCI 0x5aa8
+#define DEVICE_ID_INTEL_CHERRYVIEW_XHCI0x22b5
+
 /*
  * amd_chipset_gen values represent AMD different chipset generations
  */
@@ -956,6 +961,36 @@ 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)
+{
+   int ret;
+   struct platform_device *plat_dev;
+   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_NONE);
+   if (!plat_dev)
+   return;
+
+   plat_dev->dev.parent = &xhci_pdev->dev;
+   platform_device_add_properties(plat_dev, pentry);
+   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,9 +1057,14 @@ 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_BROXTON_P_XHCI ||
+   pdev->device == DEVICE_ID_INTEL_CHERRYVIEW_XHCI)
+   create_intel_usb_mux_device(pdev, base);
+   }
+
op_reg_base = base + XHCI_HC_LENGTH(readl(base));
 
/* Wait for the host controller to be ready before writing any
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 v9 7/7] MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

2016-05-29 Thread Lu Baolu
Add a maintainer entry for Intel USB dual role mux drivers and
add myself as a maintainer.

Signed-off-by: Lu Baolu 
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index ed1229e..edaeebe 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5961,6 +5961,16 @@ S:   Maintained
 F: arch/x86/include/asm/intel_telemetry.h
 F: drivers/platform/x86/intel_telemetry*
 
+INTEL USB DUAL ROLE PORT MUX DRIVERS
+M: Lu Baolu 
+L: linux-usb@vger.kernel.org
+S: Supported
+F: include/linux/usb/portmux.h
+F: drivers/usb/mux/portmux-core.c
+F: drivers/usb/mux/portmux-intel-gpio.c
+F: drivers/usb/mux/portmux-intel-drcfg.c
+F: drivers/mfd/intel-vuport.c
+
 IOC3 ETHERNET DRIVER
 M: Ralf Baechle 
 L: linux-m...@linux-mips.org
-- 
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 v9 4/7] usb: mux: add driver for Intel drcfg controlled port mux

2016-05-29 Thread Lu Baolu
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 
---
 drivers/usb/mux/Kconfig   |   7 ++
 drivers/usb/mux/Makefile  |   1 +
 drivers/usb/mux/portmux-intel-drcfg.c | 162 ++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/usb/mux/portmux-intel-drcfg.c

diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
index 41b0f72..98b54d2 100644
--- a/drivers/usb/mux/Kconfig
+++ b/drivers/usb/mux/Kconfig
@@ -18,4 +18,11 @@ tristate "Intel dual role port mux controlled by GPIOs"
  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
+   help
+ Say Y here to enable support for Intel dual role port mux
+ controlled by the Dual Role Configuration Register.
+
 endif
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
index 4eb5582..0f102b5 100644
--- a/drivers/usb/mux/Makefile
+++ b/drivers/usb/mux/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
 obj-$(CONFIG_INTEL_MUX_GPIO)   += portmux-intel-gpio.o
+obj-$(CONFIG_INTEL_MUX_DRCFG)  += portmux-intel-drcfg.o
diff --git a/drivers/usb/mux/portmux-intel-drcfg.c 
b/drivers/usb/mux/portmux-intel-drcfg.c
new file mode 100644
index 000..67b11d2
--- /dev/null
+++ b/drivers/usb/mux/portmux-intel-drcfg.c
@@ -0,0 +1,162 @@
+/**
+ * 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 
+#include 
+
+#define INTEL_MUX_CFG0 0x00
+#define CFG0_SW_IDPIN  BIT(20)
+#define CFG0_SW_IDPIN_EN   BIT(21)
+#define CFG0_SW_VBUS_VALID BIT(24)
+
+struct intel_mux_drcfg {
+   struct portmux_desc desc;
+   struct device *dev;
+   void __iomem *regs;
+   struct portmux_dev *pdev;
+};
+
+static inline int intel_mux_drcfg_switch(struct device *dev, bool host)
+{
+   u32 data;
+   struct intel_mux_drcfg *mux;
+
+   mux = dev_get_drvdata(dev);
+
+   /* 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);
+
+   return 0;
+}
+
+static int intel_mux_drcfg_set_host(struct device *dev)
+{
+   dev_dbg(dev, "drcfg mux switch to HOST\n");
+
+   return intel_mux_drcfg_switch(dev, true);
+}
+
+static int intel_mux_drcfg_set_device(struct device *dev)
+{
+   dev_dbg(dev, "drcfg mux switch to DEVICE\n");
+
+   return intel_mux_drcfg_switch(dev, false);
+}
+
+static const struct portmux_ops drcfg_ops = {
+   .set_host_cb = intel_mux_drcfg_set_host,
+   .set_device_cb = intel_mux_drcfg_set_device,
+};
+
+static int intel_mux_drcfg_probe(struct platform_device *pdev)
+{
+   struct intel_mux_drcfg *mux;
+   struct device *dev = &pdev->dev;
+   u64 start, size;
+   int ret;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   ret = device_property_read_u64(dev, "reg-start", &start);
+   ret |= device_property_read_u64(dev, "reg-size", &size);
+   if (ret)
+   return -ENODEV;
+
+   mux->regs = devm_ioremap_nocache(dev, start, size);
+   if (!mux->regs)
+   return -ENOMEM;
+
+   mux->desc.dev = dev;
+   mux->desc.name = "intel-mux-drcfg";
+   mux->desc.ops = &drcfg_ops;
+   dev_set_drvdata(dev, mux);
+   mux->pdev = portmux_register(&mux->desc);
+
+   return PTR_ERR_OR_ZERO(mux->pdev);
+}
+
+static int intel_mux_drcfg_remove(struct platform_device *pdev)
+{
+   struct intel_mux_drcfg *mux;
+
+   mux = platform_get_drvdata(pdev);
+   portmux_unregister(mux->pde

[PATCH v9 3/7] usb: mux: add driver for Intel gpio controlled port mux

2016-05-29 Thread Lu Baolu
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.

[baolu: removed .owner per platform_no_drv_owner.cocci]
[baolu: extcon usage reviewed by Chanwoo Choi]
Signed-off-by: David Cohen 
Signed-off-by: Lu Baolu 
Reviewed-by: Heikki Krogerus 
Reviewed-by: Felipe Balbi 
Reviewed-by: Chanwoo Choi 
---
 drivers/usb/mux/Kconfig  |  13 +++
 drivers/usb/mux/Makefile |   1 +
 drivers/usb/mux/portmux-intel-gpio.c | 183 +++
 3 files changed, 197 insertions(+)
 create mode 100644 drivers/usb/mux/portmux-intel-gpio.c

diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
index ba778f2..41b0f72 100644
--- a/drivers/usb/mux/Kconfig
+++ b/drivers/usb/mux/Kconfig
@@ -6,3 +6,16 @@ menuconfig USB_PORTMUX
bool "USB dual role port MUX support"
help
  Generic USB dual role port mux support.
+
+if USB_PORTMUX
+
+config INTEL_MUX_GPIO
+tristate "Intel dual role port mux controlled by GPIOs"
+   depends on GPIOLIB
+   depends on REGULATOR
+   depends on X86 && ACPI
+   help
+ Say Y here to enable support for Intel dual role port mux
+ controlled by GPIOs.
+
+endif
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
index f85df92..4eb5582 100644
--- a/drivers/usb/mux/Makefile
+++ b/drivers/usb/mux/Makefile
@@ -2,3 +2,4 @@
 # Makefile for USB port mux drivers
 #
 obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
+obj-$(CONFIG_INTEL_MUX_GPIO)   += portmux-intel-gpio.o
diff --git a/drivers/usb/mux/portmux-intel-gpio.c 
b/drivers/usb/mux/portmux-intel-gpio.c
new file mode 100644
index 000..cada490
--- /dev/null
+++ b/drivers/usb/mux/portmux-intel-gpio.c
@@ -0,0 +1,183 @@
+/*
+ * 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 
+#include 
+#include 
+#include 
+
+struct vuport {
+   struct extcon_dev *edev;
+   struct notifier_block nb;
+   struct portmux_desc desc;
+   struct portmux_dev *pdev;
+   struct regulator *regulator;
+   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 device *dev, int id)
+{
+   struct vuport *vup;
+
+   dev_dbg(dev, "USB PORT ID: %s\n", id ? "HOST" : "PERIPHERAL");
+
+   vup = dev_get_drvdata(dev);
+
+   gpiod_set_value_cansleep(vup->gpio_usb_mux, !id);
+
+   if (!id ^ regulator_is_enabled(vup->regulator))
+   return id ? regulator_disable(vup->regulator) :
+   regulator_enable(vup->regulator);
+
+   return 0;
+}
+
+static int vuport_cable_set(struct device *dev)
+{
+   return vuport_set_port(dev, 1);
+}
+
+static int vuport_cable_unset(struct device *dev)
+{
+   return vuport_set_port(dev, 0);
+}
+
+static const struct portmux_ops vuport_ops = {
+   .set_host_cb = vuport_cable_set,
+   .set_device_cb = vuport_cable_unset,
+};
+
+static int vuport_notifier(struct notifier_block *nb,
+  unsigned long event, void *ptr)
+{
+   struct vuport *vup;
+   int state;
+
+   vup = container_of(nb, struct vuport, nb);
+   state = extcon_get_cable_state_(vup->edev, EXTCON_USB_HOST);
+   if (state < 0)
+   return state;
+
+   return portmux_switch(vup->pdev, state ? PORTMUX_HOST : PORTMUX_DEVICE);
+}
+
+static int vuport_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct vuport *vup;
+   int ret;
+
+   vup = devm_kzalloc(dev, sizeof(*vup), GFP_KERNEL);
+   if (!vup)
+   return -ENOMEM;
+
+   vup->regulator = devm_regulator_get_exclusive(dev,
+ "regulator-usb-gpio");
+   if (IS_ERR_OR_NULL(vup->regulator))
+   return -EPROBE_DEFER;
+
+   vup->edev = extcon_get_extcon_dev("extcon-usb-gpio");
+   if (IS_ERR_OR_NULL(vup->edev))
+   return -EPROBE_DEFER;
+
+   vup->gpio_usb_mux = devm_gpiod_get_optional(dev,
+   "usb_mux", GPIOD_ASIS);
+   if (IS_ERR(vup->gpio_usb_mux))
+   return PTR

[PATCH v9 1/7] regulator: fixed: add support for ACPI interface

2016-05-29 Thread Lu Baolu
Add support to retrieve fixed voltage configure information through
ACPI interface. This is needed for Intel Bay Trail devices, where a
GPIO is used to control the USB vbus.

Signed-off-by: Lu Baolu 
---
 drivers/regulator/fixed.c | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index ff62d69..207ab40 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -30,6 +30,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 struct fixed_voltage_data {
struct regulator_desc desc;
@@ -104,6 +107,44 @@ of_get_fixed_voltage_config(struct device *dev,
return config;
 }
 
+/**
+ * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info
+ * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
+ *
+ * Populates fixed_voltage_config structure by extracting data through ACPI
+ * interface, returns a pointer to the populated structure of NULL if memory
+ * alloc fails.
+ */
+static struct fixed_voltage_config *
+acpi_get_fixed_voltage_config(struct device *dev,
+ const struct regulator_desc *desc)
+{
+   struct fixed_voltage_config *config;
+   const char *supply_name;
+   struct gpio_desc *gpiod;
+   int ret;
+
+   config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+   if (!config)
+   return ERR_PTR(-ENOMEM);
+
+   ret = device_property_read_string(dev, "supply-name", &supply_name);
+   if (!ret)
+   config->supply_name = supply_name;
+
+   gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
+   if (IS_ERR(gpiod))
+   return ERR_PTR(-ENODEV);
+
+   config->gpio = desc_to_gpio(gpiod);
+   config->enable_high = device_property_read_bool(dev,
+   "enable-active-high");
+   gpiod_put(gpiod);
+
+   return config;
+}
+
 static struct regulator_ops fixed_voltage_ops = {
 };
 
@@ -124,6 +165,11 @@ static int reg_fixed_voltage_probe(struct platform_device 
*pdev)
 &drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
+   } else if (ACPI_HANDLE(&pdev->dev)) {
+   config = acpi_get_fixed_voltage_config(&pdev->dev,
+  &drvdata->desc);
+   if (IS_ERR(config))
+   return PTR_ERR(config);
} else {
config = dev_get_platdata(&pdev->dev);
}
-- 
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 v9 7/7] MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

2016-05-30 Thread Lu Baolu
Hi Heikki,

On 05/30/2016 04:16 PM, Heikki Krogerus wrote:
> Hi Baolu,
>
> On Mon, May 30, 2016 at 01:51:44PM +0800, Lu Baolu wrote:
>> Add a maintainer entry for Intel USB dual role mux drivers and
>> add myself as a maintainer.
>>
>> Signed-off-by: Lu Baolu 
>> ---
>>  MAINTAINERS | 10 ++
>>  1 file changed, 10 insertions(+)
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index ed1229e..edaeebe 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -5961,6 +5961,16 @@ S:Maintained
>>  F:  arch/x86/include/asm/intel_telemetry.h
>>  F:  drivers/platform/x86/intel_telemetry*
>>  
>> +INTEL USB DUAL ROLE PORT MUX DRIVERS
>> +M:  Lu Baolu 
>> +L:  linux-usb@vger.kernel.org
>> +S:  Supported
>> +F:  include/linux/usb/portmux.h
>> +F:  drivers/usb/mux/portmux-core.c
>> +F:  drivers/usb/mux/portmux-intel-gpio.c
>> +F:  drivers/usb/mux/portmux-intel-drcfg.c
>> +F:  drivers/mfd/intel-vuport.c
>> +
>>  IOC3 ETHERNET DRIVER
>>  M:  Ralf Baechle 
>>  L:  linux-m...@linux-mips.org
>> -- 
>> 2.1.4
> This one does not apply on top of v4.7-rc1.

Thanks for pointing this out.

I will send out a rebased version later, but for now I'll wait for further 
comments.

Best regards,
Lu 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 v9 7/7] MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

2016-05-31 Thread Lu Baolu
Hi,

On 05/30/2016 08:53 PM, Lu Baolu wrote:
> Hi Heikki,
>
> On 05/30/2016 04:16 PM, Heikki Krogerus wrote:
>> Hi Baolu,
>>
>> On Mon, May 30, 2016 at 01:51:44PM +0800, Lu Baolu wrote:
>>> Add a maintainer entry for Intel USB dual role mux drivers and
>>> add myself as a maintainer.
>>>
>>> Signed-off-by: Lu Baolu 
>>> ---
>>>  MAINTAINERS | 10 ++
>>>  1 file changed, 10 insertions(+)
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index ed1229e..edaeebe 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -5961,6 +5961,16 @@ S:   Maintained
>>>  F: arch/x86/include/asm/intel_telemetry.h
>>>  F: drivers/platform/x86/intel_telemetry*
>>>  
>>> +INTEL USB DUAL ROLE PORT MUX DRIVERS
>>> +M: Lu Baolu 
>>> +L: linux-usb@vger.kernel.org
>>> +S: Supported
>>> +F: include/linux/usb/portmux.h
>>> +F: drivers/usb/mux/portmux-core.c
>>> +F: drivers/usb/mux/portmux-intel-gpio.c
>>> +F: drivers/usb/mux/portmux-intel-drcfg.c
>>> +F: drivers/mfd/intel-vuport.c
>>> +
>>>  IOC3 ETHERNET DRIVER
>>>  M: Ralf Baechle 
>>>  L: linux-m...@linux-mips.org
>>> -- 
>>> 2.1.4
>> This one does not apply on top of v4.7-rc1.
> Thanks for pointing this out.
>
> I will send out a rebased version later, but for now I'll wait for further 
> comments.

I haven't got further comments by now.

I will send out the rebased version in 24 hrs if no objection.

Best regards,
Lu 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 v10 4/7] usb: mux: add driver for Intel drcfg controlled port mux

2016-06-01 Thread Lu Baolu
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 
---
 drivers/usb/mux/Kconfig   |   7 ++
 drivers/usb/mux/Makefile  |   1 +
 drivers/usb/mux/portmux-intel-drcfg.c | 162 ++
 3 files changed, 170 insertions(+)
 create mode 100644 drivers/usb/mux/portmux-intel-drcfg.c

diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
index 41b0f72..98b54d2 100644
--- a/drivers/usb/mux/Kconfig
+++ b/drivers/usb/mux/Kconfig
@@ -18,4 +18,11 @@ tristate "Intel dual role port mux controlled by GPIOs"
  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
+   help
+ Say Y here to enable support for Intel dual role port mux
+ controlled by the Dual Role Configuration Register.
+
 endif
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
index 4eb5582..0f102b5 100644
--- a/drivers/usb/mux/Makefile
+++ b/drivers/usb/mux/Makefile
@@ -3,3 +3,4 @@
 #
 obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
 obj-$(CONFIG_INTEL_MUX_GPIO)   += portmux-intel-gpio.o
+obj-$(CONFIG_INTEL_MUX_DRCFG)  += portmux-intel-drcfg.o
diff --git a/drivers/usb/mux/portmux-intel-drcfg.c 
b/drivers/usb/mux/portmux-intel-drcfg.c
new file mode 100644
index 000..67b11d2
--- /dev/null
+++ b/drivers/usb/mux/portmux-intel-drcfg.c
@@ -0,0 +1,162 @@
+/**
+ * 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 
+#include 
+
+#define INTEL_MUX_CFG0 0x00
+#define CFG0_SW_IDPIN  BIT(20)
+#define CFG0_SW_IDPIN_EN   BIT(21)
+#define CFG0_SW_VBUS_VALID BIT(24)
+
+struct intel_mux_drcfg {
+   struct portmux_desc desc;
+   struct device *dev;
+   void __iomem *regs;
+   struct portmux_dev *pdev;
+};
+
+static inline int intel_mux_drcfg_switch(struct device *dev, bool host)
+{
+   u32 data;
+   struct intel_mux_drcfg *mux;
+
+   mux = dev_get_drvdata(dev);
+
+   /* 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);
+
+   return 0;
+}
+
+static int intel_mux_drcfg_set_host(struct device *dev)
+{
+   dev_dbg(dev, "drcfg mux switch to HOST\n");
+
+   return intel_mux_drcfg_switch(dev, true);
+}
+
+static int intel_mux_drcfg_set_device(struct device *dev)
+{
+   dev_dbg(dev, "drcfg mux switch to DEVICE\n");
+
+   return intel_mux_drcfg_switch(dev, false);
+}
+
+static const struct portmux_ops drcfg_ops = {
+   .set_host_cb = intel_mux_drcfg_set_host,
+   .set_device_cb = intel_mux_drcfg_set_device,
+};
+
+static int intel_mux_drcfg_probe(struct platform_device *pdev)
+{
+   struct intel_mux_drcfg *mux;
+   struct device *dev = &pdev->dev;
+   u64 start, size;
+   int ret;
+
+   mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
+   if (!mux)
+   return -ENOMEM;
+
+   ret = device_property_read_u64(dev, "reg-start", &start);
+   ret |= device_property_read_u64(dev, "reg-size", &size);
+   if (ret)
+   return -ENODEV;
+
+   mux->regs = devm_ioremap_nocache(dev, start, size);
+   if (!mux->regs)
+   return -ENOMEM;
+
+   mux->desc.dev = dev;
+   mux->desc.name = "intel-mux-drcfg";
+   mux->desc.ops = &drcfg_ops;
+   dev_set_drvdata(dev, mux);
+   mux->pdev = portmux_register(&mux->desc);
+
+   return PTR_ERR_OR_ZERO(mux->pdev);
+}
+
+static int intel_mux_drcfg_remove(struct platform_device *pdev)
+{
+   struct intel_mux_drcfg *mux;
+
+   mux = platform_get_drvdata(pdev);
+   portmux_unregister(mux->pde

[PATCH v10 7/7] MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

2016-06-01 Thread Lu Baolu
Add a maintainer entry for Intel USB dual role mux drivers and
add myself as a maintainer.

Signed-off-by: Lu Baolu 
---
 MAINTAINERS | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7304d2e..56a98d2 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6111,6 +6111,16 @@ S:   Maintained
 F: arch/x86/include/asm/pmc_core.h
 F: drivers/platform/x86/intel_pmc_core*
 
+INTEL USB DUAL ROLE PORT MUX DRIVERS
+M: Lu Baolu 
+L: linux-usb@vger.kernel.org
+S: Supported
+F: include/linux/usb/portmux.h
+F: drivers/usb/mux/portmux-core.c
+F: drivers/usb/mux/portmux-intel-gpio.c
+F: drivers/usb/mux/portmux-intel-drcfg.c
+F: drivers/mfd/intel-vuport.c
+
 IOC3 ETHERNET DRIVER
 M: Ralf Baechle 
 L: linux-m...@linux-mips.org
-- 
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 v10 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-06-01 Thread Lu Baolu
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| 42 +++-
 drivers/usb/host/xhci-ext-caps.h |  2 ++
 2 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c
index 35af362..7e3194f 100644
--- a/drivers/usb/host/pci-quirks.c
+++ b/drivers/usb/host/pci-quirks.c
@@ -16,6 +16,8 @@
 #include 
 #include 
 #include 
+#include 
+
 #include "pci-quirks.h"
 #include "xhci-ext-caps.h"
 
@@ -78,6 +80,9 @@
 #define USB_INTEL_USB3_PSSEN   0xD8
 #define USB_INTEL_USB3PRM  0xDC
 
+#define DEVICE_ID_INTEL_BROXTON_P_XHCI 0x5aa8
+#define DEVICE_ID_INTEL_CHERRYVIEW_XHCI0x22b5
+
 /*
  * amd_chipset_gen values represent AMD different chipset generations
  */
@@ -956,6 +961,36 @@ 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)
+{
+   int ret;
+   struct platform_device *plat_dev;
+   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_NONE);
+   if (!plat_dev)
+   return;
+
+   plat_dev->dev.parent = &xhci_pdev->dev;
+   platform_device_add_properties(plat_dev, pentry);
+   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,9 +1057,14 @@ 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_BROXTON_P_XHCI ||
+   pdev->device == DEVICE_ID_INTEL_CHERRYVIEW_XHCI)
+   create_intel_usb_mux_device(pdev, base);
+   }
+
op_reg_base = base + XHCI_HC_LENGTH(readl(base));
 
/* Wait for the host controller to be ready before writing any
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 v10 5/7] mfd: intel_vuport: Add Intel virtual USB port MFD Driver

2016-06-01 Thread Lu Baolu
Some Intel platforms have an USB port mux controlled by GPIOs.
There's a single ACPI platform device that provides 1) USB ID
extcon device; 2) USB vbus regulator device; and 3) USB port
switch device. This MFD driver will split these 3 devices for
their respective drivers.

[baolu: removed .owner per platform_no_drv_owner.cocci]
Suggested-by: David Cohen 
Signed-off-by: Lu Baolu 
Reviewed-by: Felipe Balbi 
Acked-by: Lee Jones 
---
 drivers/mfd/Kconfig|  8 +
 drivers/mfd/Makefile   |  1 +
 drivers/mfd/intel-vuport.c | 86 ++
 3 files changed, 95 insertions(+)
 create mode 100644 drivers/mfd/intel-vuport.c

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1bcf601..94affb3 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1603,5 +1603,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's dual role port mux
+ controlled by GPIOs.
+
 endmenu
 endif
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 42a66e1..b86d4f9 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -205,3 +205,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..eb27a8f
--- /dev/null
+++ b/drivers/mfd/intel-vuport.c
@@ -0,0 +1,86 @@
+/*
+ * 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 
+#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 },
+   { "gpio-gpios", &vbus_gpio, 1 },
+   { "usb_mux-gpios", &mux_gpio, 1 },
+   { },
+};
+
+static struct property_entry reg_properties[] = {
+   PROPERTY_ENTRY_STRING("supply-name", "regulator-usb-gpio"),
+   { },
+};
+
+static const struct mfd_cell intel_vuport_mfd_cells[] = {
+   { .name = "extcon-usb-gpio", },
+   {
+   .name = "reg-fixed-voltage",
+   .properties = reg_properties,
+   },
+   { .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, PLATFORM_DEVID_NONE,
+   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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-01 Thread Lu Baolu
Several Intel platforms implement USB dual role by having completely
separate xHCI and dwc3 IPs in PCH or SOC silicons. These two IPs share
a single USB port. There is another external port mux which controls
where the data lines should go. While the USB controllers are part of
the silicon, the port mux design are platform specific.

This patch adds the generic code to handle such multiple roles of a
usb port. It exports the necessary interfaces for other components to
register or unregister a usb mux device, and to control its role.
It registers the mux device with sysfs as well, so that users are able
to control the port role from user space.

Some other archs (e.g. Renesas R-Car gen2 SoCs) need an external mux to
swap usb roles as well. This code could also be leveraged for those archs.

Signed-off-by: Lu Baolu 
Reviewed-by: Heikki Krogerus 
Reviewed-by: Felipe Balbi 
---
 Documentation/ABI/testing/sysfs-bus-platform |  18 +++
 drivers/usb/Kconfig  |   2 +
 drivers/usb/Makefile |   1 +
 drivers/usb/mux/Kconfig  |   8 ++
 drivers/usb/mux/Makefile |   4 +
 drivers/usb/mux/portmux-core.c   | 202 +++
 include/linux/usb/portmux.h  |  90 
 7 files changed, 325 insertions(+)
 create mode 100644 drivers/usb/mux/Kconfig
 create mode 100644 drivers/usb/mux/Makefile
 create mode 100644 drivers/usb/mux/portmux-core.c
 create mode 100644 include/linux/usb/portmux.h

diff --git a/Documentation/ABI/testing/sysfs-bus-platform 
b/Documentation/ABI/testing/sysfs-bus-platform
index 5172a61..b994e4e 100644
--- a/Documentation/ABI/testing/sysfs-bus-platform
+++ b/Documentation/ABI/testing/sysfs-bus-platform
@@ -18,3 +18,21 @@ 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/.../portmux.N/name
+   /sys/bus/platform/devices/.../portmux.N/state
+Date:  April 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. Read-only attribute "name" shows the name 
of
+   the port mux device. "state" attribute shows and stores the mux
+   state.
+   For read:
+   'unknown'- the mux hasn't been set yet;
+   'peripheral' - mux has been switched to PERIPHERAL controller;
+   'host'   - mux has been 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/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 8689dcb..328916e 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -148,6 +148,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..ba778f2
--- /dev/null
+++ b/drivers/usb/mux/Kconfig
@@ -0,0 +1,8 @@
+#
+# USB port mux driver configuration
+#
+
+menuconfig USB_PORTMUX
+   bool "USB dual role port MUX support"
+   help
+ Generic USB dual role port mux support.
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
new file mode 100644
index 000..f85df92
--- /dev/null
+++ b/drivers/usb/mux/Makefile
@@ -0,0 +1,4 @@
+#
+# Makefile for USB port mux drivers
+#
+obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
diff --git a/drivers/usb/mux/portmux-core.c b/drivers/usb/mux/portmux-core.c
new file mode 100644
index 000..75fbb45
--- /dev/null
+++ b/drivers/usb/mux/portmux-core.c
@@ -0,0 +1,202 @@
+/**
+ * portmux-core.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 
+
+static int usb_mux_change_state(struct portmux_d

[PATCH v10 0/7] usb: add support for Intel dual role port mux

2016-06-01 Thread Lu Baolu
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 generic framework for port mux devices. It exports interfaces
to register and unregister a port mux device. It also exports
an interface for the port mux consumers (e.x. PHY and charger
drivers) to switch the port role according to the events they
have detected.
(2) Drivers for GPIO controlled port mux which could be found
on Baytrail devices. A mfd driver is used to split the GPIOs
into a USB gpio extcon device, a fixed regulator for gpio
controlled USB VCC, 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.

All patches have been verified on Intel's BayTrail, CherryTrail,
and Broxton P platforms.

Lu Baolu (7):
  regulator: fixed: add support for ACPI interface
  usb: mux: add generic code for dual role port mux
  usb: mux: add driver for Intel gpio controlled port mux
  usb: mux: add driver for Intel drcfg controlled port mux
  mfd: intel_vuport: Add Intel virtual USB port MFD Driver
  usb: pci-quirks: add Intel USB drcfg mux device
  MAINTAINERS: add maintainer entry for Intel USB dual role mux drivers

Change log:

v9->v10:
 - rebase the patch series on top of 4.7-rc1.

v8->v9:
 - Patch "mfd: intel_vuport: Add Intel virtual USB port MFD Driver"
   has been ACK-ed by "Lee Jones ".
 - remove extcon dependency out of the generic mux code to support
   systems which have multiple port muxes.
 - Add dev.release for mux device, otherwise, the mux driver module
   couldn't be removed.
 - Use the refreshed device property interface updated in Commit (f4d0526
   device property: don't bother the drivers with struct property_set)

v7->v8:
 - In patch "regulator: fixed: add support for ACPI interface", the
   fixed regulator gpio name has been changed to "gpio".
 - In patch "MAINTAINERS: add maintainer entry for Intel USB dual role
   mux drivers", filenames have been updated.

v6->v7:
 - Two patches have been picked up by extcon maintainer. Hence,
   remove them since this version.
   - extcon: usb-gpio: add device binding for platform device
   - extcon: usb-gpio: add support for ACPI gpio interface
 - Below patch has been removed from this series because it's unnecessary.
   - regulator: fixed: add device binding for platform device
 - In patch "regulator: fixed: add support for ACPI interface",
   a static gpio name is used to get the regulator gpio.
 - In patch "mfd: intel_vuport: Add Intel virtual USB port MFD Driver",
   unnecessary "gpio-name" string property has been removed.

v5->v6:
 Work internally with Felipe to improve the whole patch series.
 Below changes have been made since last version.
 - rework the common code to make it a generic interface for mux devices;
 - split the vbus gpio handling to a fixed regulator device;
 - removed unnecessary filtering for state change;
 - removed unnecessary WARN statement;
 - removed globals in mux drivers;
 - removed unnecessary register polling and waiting in drcfg driver;

v4->v5:
 - Change the extcon interfaces with the new ones suggested by
   2a9de9c0f08d6 (extcon: Use the unique id for external connector
   instead of string)
 - remove patch "usb: pci-quirks: add Intel USB drcfg mux device"
   from this serial due to that it's not driver staff. Will be
   submitted seperately.

v3->v4:
 - Check all patches with "checkpatch.pl --strict", and fix all
   CHECKs;
 - Change sysfs node from "intel_mux" to "port_mux";
 - Refines below confusing functions:
   intel_usb_mux_register() -> intel_usb_mux_bind_cable()
   intel_usb_mux_unregister() -> intel_usb_mux_unbind_cable();
 - Remove unnecessary struct intel_mux_dev.

v2->v3:
 - uvport mfd driver got reviewed by Lee Jones, the following
   changes were made accordingly.
 - seperate uvport driver from the mux drivers in MAINTAINERS file
 - refine the description in Kconfig
 - refine the mfd_cell structure dat

[PATCH v10 3/7] usb: mux: add driver for Intel gpio controlled port mux

2016-06-01 Thread Lu Baolu
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.

[baolu: removed .owner per platform_no_drv_owner.cocci]
[baolu: extcon usage reviewed by Chanwoo Choi]
Signed-off-by: David Cohen 
Signed-off-by: Lu Baolu 
Reviewed-by: Heikki Krogerus 
Reviewed-by: Felipe Balbi 
Reviewed-by: Chanwoo Choi 
---
 drivers/usb/mux/Kconfig  |  13 +++
 drivers/usb/mux/Makefile |   1 +
 drivers/usb/mux/portmux-intel-gpio.c | 183 +++
 3 files changed, 197 insertions(+)
 create mode 100644 drivers/usb/mux/portmux-intel-gpio.c

diff --git a/drivers/usb/mux/Kconfig b/drivers/usb/mux/Kconfig
index ba778f2..41b0f72 100644
--- a/drivers/usb/mux/Kconfig
+++ b/drivers/usb/mux/Kconfig
@@ -6,3 +6,16 @@ menuconfig USB_PORTMUX
bool "USB dual role port MUX support"
help
  Generic USB dual role port mux support.
+
+if USB_PORTMUX
+
+config INTEL_MUX_GPIO
+tristate "Intel dual role port mux controlled by GPIOs"
+   depends on GPIOLIB
+   depends on REGULATOR
+   depends on X86 && ACPI
+   help
+ Say Y here to enable support for Intel dual role port mux
+ controlled by GPIOs.
+
+endif
diff --git a/drivers/usb/mux/Makefile b/drivers/usb/mux/Makefile
index f85df92..4eb5582 100644
--- a/drivers/usb/mux/Makefile
+++ b/drivers/usb/mux/Makefile
@@ -2,3 +2,4 @@
 # Makefile for USB port mux drivers
 #
 obj-$(CONFIG_USB_PORTMUX)  += portmux-core.o
+obj-$(CONFIG_INTEL_MUX_GPIO)   += portmux-intel-gpio.o
diff --git a/drivers/usb/mux/portmux-intel-gpio.c 
b/drivers/usb/mux/portmux-intel-gpio.c
new file mode 100644
index 000..cada490
--- /dev/null
+++ b/drivers/usb/mux/portmux-intel-gpio.c
@@ -0,0 +1,183 @@
+/*
+ * 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 
+#include 
+#include 
+#include 
+
+struct vuport {
+   struct extcon_dev *edev;
+   struct notifier_block nb;
+   struct portmux_desc desc;
+   struct portmux_dev *pdev;
+   struct regulator *regulator;
+   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 device *dev, int id)
+{
+   struct vuport *vup;
+
+   dev_dbg(dev, "USB PORT ID: %s\n", id ? "HOST" : "PERIPHERAL");
+
+   vup = dev_get_drvdata(dev);
+
+   gpiod_set_value_cansleep(vup->gpio_usb_mux, !id);
+
+   if (!id ^ regulator_is_enabled(vup->regulator))
+   return id ? regulator_disable(vup->regulator) :
+   regulator_enable(vup->regulator);
+
+   return 0;
+}
+
+static int vuport_cable_set(struct device *dev)
+{
+   return vuport_set_port(dev, 1);
+}
+
+static int vuport_cable_unset(struct device *dev)
+{
+   return vuport_set_port(dev, 0);
+}
+
+static const struct portmux_ops vuport_ops = {
+   .set_host_cb = vuport_cable_set,
+   .set_device_cb = vuport_cable_unset,
+};
+
+static int vuport_notifier(struct notifier_block *nb,
+  unsigned long event, void *ptr)
+{
+   struct vuport *vup;
+   int state;
+
+   vup = container_of(nb, struct vuport, nb);
+   state = extcon_get_cable_state_(vup->edev, EXTCON_USB_HOST);
+   if (state < 0)
+   return state;
+
+   return portmux_switch(vup->pdev, state ? PORTMUX_HOST : PORTMUX_DEVICE);
+}
+
+static int vuport_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct vuport *vup;
+   int ret;
+
+   vup = devm_kzalloc(dev, sizeof(*vup), GFP_KERNEL);
+   if (!vup)
+   return -ENOMEM;
+
+   vup->regulator = devm_regulator_get_exclusive(dev,
+ "regulator-usb-gpio");
+   if (IS_ERR_OR_NULL(vup->regulator))
+   return -EPROBE_DEFER;
+
+   vup->edev = extcon_get_extcon_dev("extcon-usb-gpio");
+   if (IS_ERR_OR_NULL(vup->edev))
+   return -EPROBE_DEFER;
+
+   vup->gpio_usb_mux = devm_gpiod_get_optional(dev,
+   "usb_mux", GPIOD_ASIS);
+   if (IS_ERR(vup->gpio_usb_mux))
+   return PTR

[PATCH v10 1/7] regulator: fixed: add support for ACPI interface

2016-06-01 Thread Lu Baolu
Add support to retrieve fixed voltage configure information through
ACPI interface. This is needed for Intel Bay Trail devices, where a
GPIO is used to control the USB vbus.

Signed-off-by: Lu Baolu 
---
 drivers/regulator/fixed.c | 46 ++
 1 file changed, 46 insertions(+)

diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index ff62d69..207ab40 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -30,6 +30,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 struct fixed_voltage_data {
struct regulator_desc desc;
@@ -104,6 +107,44 @@ of_get_fixed_voltage_config(struct device *dev,
return config;
 }
 
+/**
+ * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info
+ * @dev: device requesting for fixed_voltage_config
+ * @desc: regulator description
+ *
+ * Populates fixed_voltage_config structure by extracting data through ACPI
+ * interface, returns a pointer to the populated structure of NULL if memory
+ * alloc fails.
+ */
+static struct fixed_voltage_config *
+acpi_get_fixed_voltage_config(struct device *dev,
+ const struct regulator_desc *desc)
+{
+   struct fixed_voltage_config *config;
+   const char *supply_name;
+   struct gpio_desc *gpiod;
+   int ret;
+
+   config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+   if (!config)
+   return ERR_PTR(-ENOMEM);
+
+   ret = device_property_read_string(dev, "supply-name", &supply_name);
+   if (!ret)
+   config->supply_name = supply_name;
+
+   gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS);
+   if (IS_ERR(gpiod))
+   return ERR_PTR(-ENODEV);
+
+   config->gpio = desc_to_gpio(gpiod);
+   config->enable_high = device_property_read_bool(dev,
+   "enable-active-high");
+   gpiod_put(gpiod);
+
+   return config;
+}
+
 static struct regulator_ops fixed_voltage_ops = {
 };
 
@@ -124,6 +165,11 @@ static int reg_fixed_voltage_probe(struct platform_device 
*pdev)
 &drvdata->desc);
if (IS_ERR(config))
return PTR_ERR(config);
+   } else if (ACPI_HANDLE(&pdev->dev)) {
+   config = acpi_get_fixed_voltage_config(&pdev->dev,
+  &drvdata->desc);
+   if (IS_ERR(config))
+   return PTR_ERR(config);
} else {
config = dev_get_platdata(&pdev->dev);
}
-- 
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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-03 Thread Lu Baolu
Hi Peter,

On 06/03/2016 03:41 PM, Peter Chen wrote:
> On Thu, Jun 02, 2016 at 09:37:24AM +0800, Lu Baolu wrote:
>> > Several Intel platforms implement USB dual role by having completely
>> > separate xHCI and dwc3 IPs in PCH or SOC silicons. These two IPs share
>> > a single USB port. There is another external port mux which controls
>> > where the data lines should go. While the USB controllers are part of
>> > the silicon, the port mux design are platform specific.
>> > 
>> > This patch adds the generic code to handle such multiple roles of a
>> > usb port. It exports the necessary interfaces for other components to
>> > register or unregister a usb mux device, and to control its role.
>> > It registers the mux device with sysfs as well, so that users are able
>> > to control the port role from user space.
>> > 
>> > Some other archs (e.g. Renesas R-Car gen2 SoCs) need an external mux to
>> > swap usb roles as well. This code could also be leveraged for those archs.
>> > 
> Sorry to review this so late,

It doesn't matter. Thanks for review. Comments are always welcome.:-)

> from my point,it is a dual-role switch
> driver too,

No, it's not a dual-role switch driver, but a driver for USB port multiplexing.

One example of port multiplexing can be found in several Intel SOC and PCH
chips, inside of which, there are two independent USB controllers: host and
device. They might share a single port and this port could be configured to
route the line to one of these two controllers. This patch introduced a generic
framework for port mux drivers. It aids the drivers to handle port mux by
providing interfaces to 1) register/unregister a mux device; 2) lookup the
mux device; and 3) switch the port.

Port multiplexing isn't equal to USB dual role. There are other cases in today's
systems. In several Intel PCH chips, there equips two USB host controllers: ehci
and xhci. The xhci USB2 ports are multiplexed with ehci. This guarantees all
USB ports work even running an old version of OS which lacks of USB3 support.
In theory, we can create a driver for the port mux and switch the ports between
xhci and ehci, but that's silly, isn't it? Why not always USB3?:-)

Another case is xHCI debug capability. The xHCI host controller might equip
a unit for system debugging (refer to 7.6 of xHCI spec). The debugging unit is
independent of xhci host controller. But it shares its port with xhci. Software
could switch the port between xhci and the debugging unit through the registers
defined in xHCI spec.

Best regards,
Lu Baolu

> we are reviewing USB OTG/dual-role framework [1], it is
> not necessary to create another framework to do it. And USB OTG framework
> has already tested at Renesas's platform [2].
>
> [1] http://www.spinics.net/lists/linux-usb/msg140835.html
> [2] http://www.spinics.net/lists/linux-usb/msg140827.html
>
> Peter
>

--
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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-04 Thread Lu Baolu
Hi Peter,

On 06/04/2016 10:28 AM, Peter Chen wrote:
> On Sat, Jun 04, 2016 at 12:06:06AM +0800, Lu Baolu wrote:
>>> from my point,it is a dual-role switch
>>> driver too,
>> No, it's not a dual-role switch driver, but a driver for USB port 
>> multiplexing.
>>
>> One example of port multiplexing can be found in several Intel SOC and PCH
>> chips, inside of which, there are two independent USB controllers: host and
>> device. They might share a single port and this port could be configured to
>> route the line to one of these two controllers. This patch introduced a 
>> generic
>> framework for port mux drivers. It aids the drivers to handle port mux by
>> providing interfaces to 1) register/unregister a mux device; 2) lookup the
>> mux device; and 3) switch the port.
>>
> For this case, I can't see it is different with dual-role switch.

Port mux is part of dual role switch, but not the whole thing.

Dual role switch includes at least below things:
 - ID or type-C event detection
 - port mux
 - VBUS management
 - start/stop host/device controllers

An OTG/Dual-role framework can be used to keep all these
things run together with an internal state machine. But it's
not duplicated with a generic framework for port mux and
the port mux drivers.

> Your
> case is just like Renesas case, which uses two different drivers between
> peripheral and host[1].

In my case, the port mux devices are physical devices and they
can be controlled through GPIO pins or device registers. They
are independent of both peripheral and host controllers.


>> Port multiplexing isn't equal to USB dual role. There are other cases in 
>> today's
>> systems. In several Intel PCH chips, there equips two USB host controllers: 
>> ehci
>> and xhci. The xhci USB2 ports are multiplexed with ehci. This guarantees all
>> USB ports work even running an old version of OS which lacks of USB3 support.
>> In theory, we can create a driver for the port mux and switch the ports 
>> between
>> xhci and ehci, but that's silly, isn't it? Why not always USB3?:-)
>>
>> Another case is xHCI debug capability. The xHCI host controller might equip
>> a unit for system debugging (refer to 7.6 of xHCI spec). The debugging unit 
>> is
>> independent of xhci host controller. But it shares its port with xhci. 
>> Software
>> could switch the port between xhci and the debugging unit through the 
>> registers
>> defined in xHCI spec.
>>
> Yes, above two are different with dual role switch. But in your code and
> Kconfig, it seems this framework is dedicated for dual-role. Eg:
>
> +menuconfig USB_PORTMUX
> +   bool "USB dual role port MUX support"
> +   help
> + Generic USB dual role port mux support.

Above two cases are examples for port multiplexing, but I don't think we
need drivers for them. At this moment, this framework is only for dual
role port mux devices.

>
> I think a general dual role port mux is necessary, it can be used to
> manage different dual-role switch method, eg

Yes, I agree.

> - ID pin
> - External connector through GPIO
> - SoC register
> - sysfs
> - type-C events

ID pin and type-C events are the *reasons* which trigger the port
mux switch. Currently, on our platforms, gpio, registers and sysfs
are methods to control the mux.

>
> But this code is better co-work with OTG/Dual-role framework, we'd
> better have only interface that the user can know which role for the
> current port.

OTG/Dual-role framework and portmux framework are not overlapped.
The sysfs interface shouldn't be overlapped as well. Say, I have a port
mux device and I have a driver for it. I am able to read the status of my
port mux device through sysfs. This is not part of OTG/Dual-role as far
as I can see.

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-05 Thread Lu Baolu
Hi,

On 06/05/2016 04:33 PM, Jun Li wrote:
>> Port mux is part of dual role switch, but not the whole thing.
>> > 
>> > Dual role switch includes at least below things:
>> >  - ID or type-C event detection
>> >  - port mux
>> >  - VBUS management
>> >  - start/stop host/device controllers
>> > 
>> > An OTG/Dual-role framework can be used to keep all these things run
>> > together with an internal state machine. But it's not duplicated with a
>> > generic framework for port mux and the port mux drivers.
>> > 
>>> > > Your
>>> > > case is just like Renesas case, which uses two different drivers
>>> > > between peripheral and host[1].
>> > 
>> > In my case, the port mux devices are physical devices and they can be
>> > controlled through GPIO pins or device registers. They are independent of
>> > both peripheral and host controllers.
>> > 
> I also think current OTG/Dual role framework can support your case, if you
> find there is any limitation of it which can't meet your requirement, we
> should improve it, Roger also provide an example of dual role switch with
> USB3 based on his OTG core.

Why do we need an OTG framework to support a device driver?
Is it something like a bus or class driver?

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-05 Thread Lu Baolu
Hi Jun,

On 06/06/2016 09:08 AM, Jun Li wrote:
>
>> -Original Message-
>> From: Lu Baolu [mailto:baolu...@linux.intel.com]
>> Sent: Sunday, June 05, 2016 4:47 PM
>> To: Jun Li ; Peter Chen 
>> Cc: felipe.ba...@linux.intel.com; Mathias Nyman ;
>> Greg Kroah-Hartman ; Lee Jones
>> ; Heikki Krogerus ;
>> Liam Girdwood ; Mark Brown ;
>> linux-usb@vger.kernel.org; linux-ker...@vger.kernel.org; Roger Quadros
>> 
>> Subject: Re: [PATCH v10 2/7] usb: mux: add generic code for dual role port
>> mux
>>
>> Hi,
>>
>> On 06/05/2016 04:33 PM, Jun Li wrote:
>>>> Port mux is part of dual role switch, but not the whole thing.
>>>>> Dual role switch includes at least below things:
>>>>>  - ID or type-C event detection
>>>>>  - port mux
>>>>>  - VBUS management
>>>>>  - start/stop host/device controllers
>>>>>
>>>>> An OTG/Dual-role framework can be used to keep all these things run
>>>>> together with an internal state machine. But it's not duplicated
>>>>> with a generic framework for port mux and the port mux drivers.
>>>>>
>>>>>>> Your
>>>>>>> case is just like Renesas case, which uses two different drivers
>>>>>>> between peripheral and host[1].
>>>>> In my case, the port mux devices are physical devices and they can
>>>>> be controlled through GPIO pins or device registers. They are
>>>>> independent of both peripheral and host controllers.
>>>>>
>>> I also think current OTG/Dual role framework can support your case, if
>>> you find there is any limitation of it which can't meet your
>>> requirement, we should improve it, Roger also provide an example of
>>> dual role switch with
>>> USB3 based on his OTG core.
>> Why do we need an OTG framework to support a device driver?
> Currently there are many controller drivers which are dual role
> capable, all has its specific approach/implementation, your case
> is another one, actually there are common part we can share and
> reuse, Roger is introducing a common framework which cooperates
> into usb core and udc-core. With that, each OTG/dual role user
> only need take care of its small specific part.

Intel's USB controllers aren't dual role capable, and we don't
need any dual role capable drivers either. It's just two USB
controllers which shares a single port and it has a physical
port mux device which could control the route of lines. We
only need drivers for the port mux devices.

>   
>> Is it something like a bus or class driver?
> It's not actually a driver, instead, it's more like a lib or
> helper routines. You just need register your host and gadget
> into OTG core, and define the ops routines if required, OTG state
> machine will help you do the switch.

As I said above, we don't have any dual role capable controllers.
We don't need to have any dual role capable host or gadget drivers
to register into OTG core. We only provide drivers for port mux
devices, just like what we already have for phy or regulator
devices.

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-05 Thread Lu Baolu
Hi Peter,

On 06/06/2016 10:05 AM, Peter Chen wrote:
> On Sun, Jun 05, 2016 at 04:46:55PM +0800, Lu Baolu wrote:
>> Hi,
>>
>> On 06/05/2016 04:33 PM, Jun Li wrote:
>>>> Port mux is part of dual role switch, but not the whole thing.
>>>>> Dual role switch includes at least below things:
>>>>>  - ID or type-C event detection
>>>>>  - port mux
>>>>>  - VBUS management
>>>>>  - start/stop host/device controllers
>>>>>
>>>>> An OTG/Dual-role framework can be used to keep all these things run
>>>>> together with an internal state machine. But it's not duplicated with a
>>>>> generic framework for port mux and the port mux drivers.
>>>>>
>>>>>>> Your
>>>>>>> case is just like Renesas case, which uses two different drivers
>>>>>>> between peripheral and host[1].
>>>>> In my case, the port mux devices are physical devices and they can be
>>>>> controlled through GPIO pins or device registers. They are independent of
>>>>> both peripheral and host controllers.
>>>>>
>>> I also think current OTG/Dual role framework can support your case, if you
>>> find there is any limitation of it which can't meet your requirement, we
>>> should improve it, Roger also provide an example of dual role switch with
>>> USB3 based on his OTG core.
>> Why do we need an OTG framework to support a device driver?
> Just like you said above, OTG framework can manage role switch, the
> role switch may need to start or stop host/gadget driver according to
> different hardware signals or user input.

We don't have any OTG or dual-role (reduced OTG) capable
controllers. So we don't need to aid OTG framework to
start/stop host/gadget drivers.

>
>> Is it something like a bus or class driver?
> The DRD/OTG framework uses the same device structure with the caller,
> the caller can be a dual-role controller driver (like dwc3, chipidea,
> etc), or a separate switch driver which like your mux port driver.
>

>From my point of view, this isn't the right way to handle a port
mux device.

We have many kinds of port mux devices across multiple archs,
we should have a generic framework for them, so that consumers,
(like OTG framework) can manipulate port mux devices through a
common interfaces. Just like we already have frameworks for PHY,
VBUS regulator and ...

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-05 Thread Lu Baolu
Hi Peter,

On 06/06/2016 09:25 AM, Peter Chen wrote:
> On Sun, Jun 05, 2016 at 02:55:56PM +0800, Lu Baolu wrote:
>> Hi Peter,
>>
>> On 06/04/2016 10:28 AM, Peter Chen wrote:
>>> On Sat, Jun 04, 2016 at 12:06:06AM +0800, Lu Baolu wrote:
>>>>> from my point,it is a dual-role switch
>>>>> driver too,
>>>> No, it's not a dual-role switch driver, but a driver for USB port 
>>>> multiplexing.
>>>>
>>>> One example of port multiplexing can be found in several Intel SOC and PCH
>>>> chips, inside of which, there are two independent USB controllers: host and
>>>> device. They might share a single port and this port could be configured to
>>>> route the line to one of these two controllers. This patch introduced a 
>>>> generic
>>>> framework for port mux drivers. It aids the drivers to handle port mux by
>>>> providing interfaces to 1) register/unregister a mux device; 2) lookup the
>>>> mux device; and 3) switch the port.
>>>>
>>> For this case, I can't see it is different with dual-role switch.
>> Port mux is part of dual role switch, but not the whole thing.
>>
>> Dual role switch includes at least below things:
>>  - ID or type-C event detection
>>  - port mux
>>  - VBUS management
>>  - start/stop host/device controllers
>>
>> An OTG/Dual-role framework can be used to keep all these
>> things run together with an internal state machine. But it's
>> not duplicated with a generic framework for port mux and
>> the port mux drivers.
> You have admitted port mux is one of the ports of dual-role switch,
> Then, how they can co-work with each other? If can't, the dual-role
> switch framework needs another input events management for switching.

My point is we need a generic framework for the port mux devices,
just like we have that for PHY and regulator. OTG framework
manages the port mux devices through the common interfaces
provided by the port mux framework.

If we integrate the port mux device support into OTG itself, this  will
force every use case of port mux to rely on the big OTG framework,
although what it needs is only a single driver. That causes unnecessary
software complexity.

>
>>> Your
>>> case is just like Renesas case, which uses two different drivers between
>>> peripheral and host[1].
>> In my case, the port mux devices are physical devices and they
>> can be controlled through GPIO pins or device registers. They
>> are independent of both peripheral and host controllers.
>>
> Yes, it is the same. GPIO pin or device registers is like ID pin
> event.
>



>> But this code is better co-work with OTG/Dual-role framework, we'd
>> better have only interface that the user can know which role for the
>> current port.
>> OTG/Dual-role framework and portmux framework are not overlapped.
>> The sysfs interface shouldn't be overlapped as well. Say, I have a port
>> mux device and I have a driver for it. I am able to read the status of my
>> port mux device through sysfs. This is not part of OTG/Dual-role as far
>> as I can see.
>>
> Then how the user wants to switch the role through the mux driver's
> sysfs or dual-role switch sysfs?
>

It depends. If you have an OTG/DRD capable controllers, you need to
do this through OTG sysfs; otherwise you only need to switch the port.

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-06 Thread Lu Baolu
Hi Peter,

On 06/06/2016 03:02 PM, Peter Chen wrote:
>>>> > >> But this code is better co-work with OTG/Dual-role framework, we'd
>>>> > >> better have only interface that the user can know which role for the
>>>> > >> current port.
>>>> > >> OTG/Dual-role framework and portmux framework are not overlapped.
>>>> > >> The sysfs interface shouldn't be overlapped as well. Say, I have a 
>>>> > >> port
>>>> > >> mux device and I have a driver for it. I am able to read the status 
>>>> > >> of my
>>>> > >> port mux device through sysfs. This is not part of OTG/Dual-role as 
>>>> > >> far
>>>> > >> as I can see.
>>>> > >>
>>> > > Then how the user wants to switch the role through the mux driver's
>>> > > sysfs or dual-role switch sysfs?
>>> > >
>> > 
>> > It depends. If you have an OTG/DRD capable controllers, you need to
>> > do this through OTG sysfs; otherwise you only need to switch the port.
>> > 
> The user may not know the detail, they will do role switch according to
> sysfs documentation. Yes, in your role switch case, only port mux is enough,
> but for others, it needs other operations.

So we need to make it clear in Documentation/ABI/testing/sysfs-bus-platform.

>
> I agree with Roger that the dual-role switch part in your code is better
> to use OTG framework to reduce redundancy.

I agree that we should use dual-role framework for role switch. Actually,
my code doesn't do this work. It only adds a generic framework for port
mux device and two mux device drivers used in Intel platform.

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-06 Thread Lu Baolu
Hi Jun,

On 06/07/2016 11:03 AM, Jun Li wrote:
> Hi Roger
>
>>  
>> For Mux devices implementing dual-role, the mux device driver _must_ use
>> OTG/dual-role core API so that a common ABI is presented to user space for
>> OTG/dual-role.
> That's the only point we have concern, do dual role switch through
> OTG/dual-role core, not do it by itself.

That really depends on how do you define "dual role". Can you please
provide an unambiguous definition of "dual role" used in OTG/dual-role
framework?

Best regards,
Lu Baolu

>
>> I haven't yet looked at the mux framework but if we take care of the above
>> point then we are not introducing any redundancy.
>>
> Roger, actually this is my worry on OTG core: those dual role switch
> users just tends to do it simply by itself(straightforward and easy),
> not through the OTG core(some complicated in first look),
> this is just an example for us to convince people to select a better
> way:)
>
> Li Jun
>

--
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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-07 Thread Lu Baolu
Hi,

On 06/07/2016 02:34 PM, Jun Li wrote:
>> > On 06/07/2016 11:03 AM, Jun Li wrote:
>>> > > Hi Roger
>>> > >
>>>> > >>
>>>> > >> For Mux devices implementing dual-role, the mux device driver _must_
>>>> > >> use OTG/dual-role core API so that a common ABI is presented to user
>>>> > >> space for OTG/dual-role.
>>> > > That's the only point we have concern, do dual role switch through
>>> > > OTG/dual-role core, not do it by itself.
>> > 
>> > That really depends on how do you define "dual role". Can you please
>> > provide an unambiguous definition of "dual role" used in OTG/dual-role
>> > framework?
> Host and peripheral.
>

This is definitely ambiguous.

By reading OTG/dual-role code, my understanding is that "dual-role" is a
"reduced OTG" which is for DRD devices lacking of some OTG negotiation
protocols.

We really can't say "it's the scope of OTG/dual-role" whenever it comes to
"host and peripheral".

Best regards,
Lu 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 v10 2/7] usb: mux: add generic code for dual role port mux

2016-06-07 Thread Lu Baolu
Hi,

On 06/07/2016 11:03 AM, Jun Li wrote:
> Hi Roger
>
>>  
>> For Mux devices implementing dual-role, the mux device driver _must_ use
>> OTG/dual-role core API so that a common ABI is presented to user space for
>> OTG/dual-role.
> That's the only point we have concern, do dual role switch through
> OTG/dual-role core, not do it by itself.
>
>> I haven't yet looked at the mux framework but if we take care of the above
>> point then we are not introducing any redundancy.
>>
> Roger, actually this is my worry on OTG core: those dual role switch
> users just tends to do it simply by itself(straightforward and easy),
> not through the OTG core(some complicated in first look),

I'm sorry, but I'm really confused.

Why do we need to drop "straightforward and easy", but have to run
an *unnecessary* OTG state machine? Don't you think that will (1) add
*unnecessary* software complexity; (2) increase *unnecessary* memory
footprint; and (3) increase the debugging efforts?

> this is just an example for us to convince people to select a better
> way:)

Sure. Let's take my case for an example.

My system has a third-party port mux, which is not part any USB controllers.
Also, my system doesn't have any DRD capable devices. I need a
"straightforward and easy" driver for it. Otherwise, the system could not be
waken up from system suspend.

But you said I must run an unnecessary OTG state machine, even thought it
has nothing to do with my system, only because the two sides of my port
mux device is a host and peripheral controller.

Why?

Best regards,
Lu 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 v10 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-06-08 Thread Lu Baolu
Hi Greg,

On 06/08/2016 12:45 PM, Greg Kroah-Hartman wrote:
> On Thu, Jun 02, 2016 at 09:37:28AM +0800, Lu Baolu wrote:
>> 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.
> Why do you need a platform device for this?  You do nothing with this
> device, why create it at all?

In this patch series, I have a generic framework for port mux devices
and two port mux drivers sitting on top the generic code.

In this patch, I create a platform device for the real mux device in
Intel Cherry Trail or Broxton SOCs. In it's driver, I registered a mux
into the generic framework and handle the power management
things in driver's pm entries (otherwise, the system can't be waken
up from system suspend).

> And why is it a platform device, isn't is really a PCI device?  Why
> would you ever find a "platform" device below a PCI device?  Don't abuse
> platform devices for things that aren't.  It makes me want to delete
> that whole interface more and more...

Port mux devices are physical devices in Intel Cherry Trail and Broxton
SOCs. It doesn't sit on any PCIe bus. But it maps its registers in xHCI
space. OS kernel can enumerate it by looking up the xhci extended
capability list with a vendor specific capability ID.

Best regards,
Lu 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 v10 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-06-08 Thread Lu Baolu
Hi Greg,

On 06/08/2016 11:45 PM, Greg Kroah-Hartman wrote:
> On Wed, Jun 08, 2016 at 03:56:04PM +0800, Lu Baolu wrote:
>> Hi Greg,
>>
>> On 06/08/2016 12:45 PM, Greg Kroah-Hartman wrote:
>>> On Thu, Jun 02, 2016 at 09:37:28AM +0800, Lu Baolu wrote:
>>>> 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.
>>> Why do you need a platform device for this?  You do nothing with this
>>> device, why create it at all?
>> In this patch series, I have a generic framework for port mux devices
>> and two port mux drivers sitting on top the generic code.
>>
>> In this patch, I create a platform device for the real mux device in
>> Intel Cherry Trail or Broxton SOCs. In it's driver, I registered a mux
>> into the generic framework and handle the power management
>> things in driver's pm entries (otherwise, the system can't be waken
>> up from system suspend).:)
>>
>>> And why is it a platform device, isn't is really a PCI device?  Why
>>> would you ever find a "platform" device below a PCI device?  Don't abuse
>>> platform devices for things that aren't.  It makes me want to delete
>>> that whole interface more and more...
>> Port mux devices are physical devices in Intel Cherry Trail and Broxton
>> SOCs. It doesn't sit on any PCIe bus. But it maps its registers in xHCI
>> space. OS kernel can enumerate it by looking up the xhci extended
>> capability list with a vendor specific capability ID.
> A physical device that maps registers into PCI space seems like a PCI
> device of some type to me :)
>
> Again, I hate platform devices for obvious reasons like this...
>

It's not PCI configure space, but xhci's io memory. XHCI spec reserves
a range in its extended capability list for vendor specific things. Intel's
platform leverages this for the port mux device register mapping.
It looks odd though. :)

Best regards,
Lu 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 v10 1/7] regulator: fixed: add support for ACPI interface

2016-06-08 Thread Lu Baolu
Hi Felipe and Heikki,

On 06/08/2016 12:42 PM, Greg Kroah-Hartman wrote:
> On Thu, Jun 02, 2016 at 09:37:23AM +0800, Lu Baolu wrote:
>> Add support to retrieve fixed voltage configure information through
>> ACPI interface. This is needed for Intel Bay Trail devices, where a
>> GPIO is used to control the USB vbus.
>>
>> Signed-off-by: Lu Baolu 
>> ---
>>  drivers/regulator/fixed.c | 46 
>> ++
>>  1 file changed, 46 insertions(+)
> Can't do anything with this until I get an ack from the "owners" of this
> file.
>
> And what happened to the acks from other Intel developers for this whole
> patch series, I don't see that here :(
>

You have reviewed the whole patches in this series. Are you willing
to ack them?

Best regards,
Lu 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 v10 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-06-15 Thread Lu Baolu
Hi Greg,

On 06/09/2016 10:39 AM, Lu Baolu wrote:
> Hi Greg,
>
> On 06/08/2016 11:45 PM, Greg Kroah-Hartman wrote:
>> On Wed, Jun 08, 2016 at 03:56:04PM +0800, Lu Baolu wrote:
>>> Hi Greg,
>>>
>>> On 06/08/2016 12:45 PM, Greg Kroah-Hartman wrote:
>>>> On Thu, Jun 02, 2016 at 09:37:28AM +0800, Lu Baolu wrote:
>>>>> 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.
>>>> Why do you need a platform device for this?  You do nothing with this
>>>> device, why create it at all?
>>> In this patch series, I have a generic framework for port mux devices
>>> and two port mux drivers sitting on top the generic code.
>>>
>>> In this patch, I create a platform device for the real mux device in
>>> Intel Cherry Trail or Broxton SOCs. In it's driver, I registered a mux
>>> into the generic framework and handle the power management
>>> things in driver's pm entries (otherwise, the system can't be waken
>>> up from system suspend).:)
>>>
>>>> And why is it a platform device, isn't is really a PCI device?  Why
>>>> would you ever find a "platform" device below a PCI device?  Don't abuse
>>>> platform devices for things that aren't.  It makes me want to delete
>>>> that whole interface more and more...
>>> Port mux devices are physical devices in Intel Cherry Trail and Broxton
>>> SOCs. It doesn't sit on any PCIe bus. But it maps its registers in xHCI
>>> space. OS kernel can enumerate it by looking up the xhci extended
>>> capability list with a vendor specific capability ID.
>> A physical device that maps registers into PCI space seems like a PCI
>> device of some type to me :)
>>
>> Again, I hate platform devices for obvious reasons like this...
>>
> It's not PCI configure space, but xhci's io memory. XHCI spec reserves
> a range in its extended capability list for vendor specific things. Intel's
> platform leverages this for the port mux device register mapping.
> It looks odd though. :)

A gentle ping. :)

This port mux is not a PCI device. It only leverages the vendor
specific capability defined in xhci specification for enumeration.

Best regards,
Lu 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 v10 6/7] usb: pci-quirks: add Intel USB drcfg mux device

2016-06-19 Thread Lu Baolu
Hi Greg,

On 06/18/2016 08:58 AM, Greg Kroah-Hartman wrote:
> On Thu, Jun 16, 2016 at 08:27:41AM +0800, Lu Baolu wrote:
>> Hi Greg,
>>
>> On 06/09/2016 10:39 AM, Lu Baolu wrote:
>>> Hi Greg,
>>>
>>> On 06/08/2016 11:45 PM, Greg Kroah-Hartman wrote:
>>>> On Wed, Jun 08, 2016 at 03:56:04PM +0800, Lu Baolu wrote:
>>>>> Hi Greg,
>>>>>
>>>>> On 06/08/2016 12:45 PM, Greg Kroah-Hartman wrote:
>>>>>> On Thu, Jun 02, 2016 at 09:37:28AM +0800, Lu Baolu wrote:
>>>>>>> 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.
>>>>>> Why do you need a platform device for this?  You do nothing with this
>>>>>> device, why create it at all?
>>>>> In this patch series, I have a generic framework for port mux devices
>>>>> and two port mux drivers sitting on top the generic code.
>>>>>
>>>>> In this patch, I create a platform device for the real mux device in
>>>>> Intel Cherry Trail or Broxton SOCs. In it's driver, I registered a mux
>>>>> into the generic framework and handle the power management
>>>>> things in driver's pm entries (otherwise, the system can't be waken
>>>>> up from system suspend).:)
>>>>>
>>>>>> And why is it a platform device, isn't is really a PCI device?  Why
>>>>>> would you ever find a "platform" device below a PCI device?  Don't abuse
>>>>>> platform devices for things that aren't.  It makes me want to delete
>>>>>> that whole interface more and more...
>>>>> Port mux devices are physical devices in Intel Cherry Trail and Broxton
>>>>> SOCs. It doesn't sit on any PCIe bus. But it maps its registers in xHCI
>>>>> space. OS kernel can enumerate it by looking up the xhci extended
>>>>> capability list with a vendor specific capability ID.
>>>> A physical device that maps registers into PCI space seems like a PCI
>>>> device of some type to me :)
>>>>
>>>> Again, I hate platform devices for obvious reasons like this...
>>>>
>>> It's not PCI configure space, but xhci's io memory. XHCI spec reserves
>>> a range in its extended capability list for vendor specific things. Intel's
>>> platform leverages this for the port mux device register mapping.
>>> It looks odd though. :)
>> A gentle ping. :)
> For what?  This patchset is long gone from my queue for the other
> various things that came up with it, what can I do with it now?

I see now. Thanks for your reply.

Best regards,
Lu Baolu

>
>> This port mux is not a PCI device. It only leverages the vendor
>> specific capability defined in xhci specification for enumeration.
> It's still crap :)
>
> I don't know, and don't really remember the patch anymore anyway,
> remember, I have the sort-term memory of a squirrel, you need repost
> patches, with a proper changelog for me to be able to do anything...
>
> 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: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Lu Baolu
Hi,

On 11/30/2016 05:02 PM, Baolin Wang wrote:
> If the hardware never responds to the stop endpoint command, the
> URBs will never be completed, and we might hang the USB subsystem.
> The original watchdog timer is used to watch if one stop endpoint
> command is timeout, if timeout, then the watchdog timer will set
> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
> pending URBs.
>
> But now we already have one command timer to control command timeout,
> thus we can also use the command timer to watch the stop endpoint
> command, instead of one duplicate watchdog timer which need to be
> removed.
>
> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
> this is the last stop endpoint command of one endpoint. Since we
> can make sure we only set one stop endpoint command for one endpoint
> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
> this flag.

I am afraid you can't do this. "stop_cmds_pending" was added
to fix the problem described in the comments that you want to
remove. But I didn't find any fix of this problem in your patch.

- * The timer may also fire if the host takes a very long time to respond to the
- * command, and the stop endpoint command completion handler cannot delete the
- * timer before the timer function is called.  Another endpoint cancellation 
may
- * sneak in before the timer function can grab the lock, and that may queue
- * another stop endpoint command and add the timer back.  So we cannot use a
- * simple flag to say whether there is a pending stop endpoint command for a
- * particular endpoint.
- *
- * Instead we use a combination of that flag and a counter for the number of
- * pending stop endpoint commands.  If the timer is the tail end of the last
- * stop endpoint command, and the endpoint's command is still pending, we 
assume
- * the host is dying.

Best regards,
Lu Baolu

>
> We also need to clean up the command queue before trying to halt the
> xHCI host in xhci_stop_endpoint_command_timeout() function.
>
> Signed-off-by: Baolin Wang 

--
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: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Lu Baolu
Hi,

On 12/01/2016 02:04 PM, Baolin Wang wrote:
> Hi Baolu,
>
> On 1 December 2016 at 13:45, Lu Baolu  wrote:
>> Hi,
>>
>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>> If the hardware never responds to the stop endpoint command, the
>>> URBs will never be completed, and we might hang the USB subsystem.
>>> The original watchdog timer is used to watch if one stop endpoint
>>> command is timeout, if timeout, then the watchdog timer will set
>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>> pending URBs.
>>>
>>> But now we already have one command timer to control command timeout,
>>> thus we can also use the command timer to watch the stop endpoint
>>> command, instead of one duplicate watchdog timer which need to be
>>> removed.
>>>
>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>> this is the last stop endpoint command of one endpoint. Since we
>>> can make sure we only set one stop endpoint command for one endpoint
>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>> this flag.
>> I am afraid you can't do this. "stop_cmds_pending" was added
>> to fix the problem described in the comments that you want to
>> remove. But I didn't find any fix of this problem in your patch.
> Now we can not pending another stop endpoint command for the same one
> endpoint, since will check 'EP_HALT_PENDING' flag in
> xhci_urb_dequeue() function to avoid this. But after some
> investigation, I think I missed the stop endpoint command in
> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
> maybe need to add 'EP_HALT_PENDING' flag checking in
> xhci_stop_device() function. DId I miss something else? Thanks.

Consider below three threads running on different CPUs at the same time.

Thread A: xhci_handle_cmd_stop_ep()  --- in interrupt handler
Thread B: xhci_stop_endpoint_command_timeout() --- timer expired
Thread C: xhci_urb_dequeue --- called by usb core

They are serialized by xhci->lock. Let's consider below sequence:

Thread A:
- delete xhci->cmd_timer), but will fail due to Thread B.
- clear EP_HALT_PENDING bit

Thread B:
- halt the host controller

Thread C:
- set EP_HALT_PENDING bit
- enqueue another stop endpoint command
- add the timer back

Best regards,
Lu Baolu

>
>> - * The timer may also fire if the host takes a very long time to respond to 
>> the
>> - * command, and the stop endpoint command completion handler cannot delete 
>> the
>> - * timer before the timer function is called.  Another endpoint 
>> cancellation may
>> - * sneak in before the timer function can grab the lock, and that may queue
>> - * another stop endpoint command and add the timer back.  So we cannot use a
>> - * simple flag to say whether there is a pending stop endpoint command for a
>> - * particular endpoint.
>> - *
>> - * Instead we use a combination of that flag and a counter for the number of
>> - * pending stop endpoint commands.  If the timer is the tail end of the last
>> - * stop endpoint command, and the endpoint's command is still pending, we 
>> assume
>> - * the host is dying.
>>
>> Best regards,
>> Lu Baolu
>>
>>> We also need to clean up the command queue before trying to halt the
>>> xHCI host in xhci_stop_endpoint_command_timeout() function.
>>>
>>> Signed-off-by: Baolin Wang 
>
>

--
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: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-11-30 Thread Lu Baolu
Hi,

On 12/01/2016 03:35 PM, Baolin Wang wrote:
> On 1 December 2016 at 14:35, Lu Baolu  wrote:
>> Hi,
>>
>> On 12/01/2016 02:04 PM, Baolin Wang wrote:
>>> Hi Baolu,
>>>
>>> On 1 December 2016 at 13:45, Lu Baolu  wrote:
>>>> Hi,
>>>>
>>>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>>>> If the hardware never responds to the stop endpoint command, the
>>>>> URBs will never be completed, and we might hang the USB subsystem.
>>>>> The original watchdog timer is used to watch if one stop endpoint
>>>>> command is timeout, if timeout, then the watchdog timer will set
>>>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>>>> pending URBs.
>>>>>
>>>>> But now we already have one command timer to control command timeout,
>>>>> thus we can also use the command timer to watch the stop endpoint
>>>>> command, instead of one duplicate watchdog timer which need to be
>>>>> removed.
>>>>>
>>>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>>>> this is the last stop endpoint command of one endpoint. Since we
>>>>> can make sure we only set one stop endpoint command for one endpoint
>>>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>>>> this flag.
>>>> I am afraid you can't do this. "stop_cmds_pending" was added
>>>> to fix the problem described in the comments that you want to
>>>> remove. But I didn't find any fix of this problem in your patch.
>>> Now we can not pending another stop endpoint command for the same one
>>> endpoint, since will check 'EP_HALT_PENDING' flag in
>>> xhci_urb_dequeue() function to avoid this. But after some
>>> investigation, I think I missed the stop endpoint command in
>>> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
>>> maybe need to add 'EP_HALT_PENDING' flag checking in
>>> xhci_stop_device() function. DId I miss something else? Thanks.
>> Consider below three threads running on different CPUs at the same time.
>>
>> Thread A: xhci_handle_cmd_stop_ep()  --- in interrupt handler
>> Thread B: xhci_stop_endpoint_command_timeout() --- timer expired
>> Thread C: xhci_urb_dequeue --- called by usb core
>>
>> They are serialized by xhci->lock. Let's consider below sequence:
>>
>> Thread A:
>> - delete xhci->cmd_timer), but will fail due to Thread B.
>> - clear EP_HALT_PENDING bit
>>
>> Thread B:
>> - halt the host controller
>>
>> Thread C:
>> - set EP_HALT_PENDING bit
>> - enqueue another stop endpoint command
>> - add the timer back
> Ah, thanks for you comments.
> If thread B halted the host, then the thread C xhci_urb_dequeue() will
> check host state failed, then just return and can not set another stop
> endpoint command.

Not so simple. Thread B will release xhci->lock before xhci_halt().

> But from your example, I think your meaning is we
> should not halt the host by thread B, since we have handled the stop
> endpoint command event.
>
> So I think we need to check the xhci command of this stop endpoint
> command in xhci_stop_endpoint_command_timeout(), if the xhci command
> of this stop endpoint command is not in the command list (which means
> the stop endpoint command event has been handled), then just return
> and do not halt the controller. Right?
>

I'd like suggest you to put this change into a separated patch.
It's actually a different topic from the main purpose of this patch.

Best regards,
Lu 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: [RFC] usb: host: xhci: Remove the watchdog timer and use command timer to watch stop endpoint command

2016-12-01 Thread Lu Baolu
Hi,

On 12/01/2016 04:03 PM, Baolin Wang wrote:
> On 1 December 2016 at 15:44, Lu Baolu  wrote:
>> Hi,
>>
>> On 12/01/2016 03:35 PM, Baolin Wang wrote:
>>> On 1 December 2016 at 14:35, Lu Baolu  wrote:
>>>> Hi,
>>>>
>>>> On 12/01/2016 02:04 PM, Baolin Wang wrote:
>>>>> Hi Baolu,
>>>>>
>>>>> On 1 December 2016 at 13:45, Lu Baolu  wrote:
>>>>>> Hi,
>>>>>>
>>>>>> On 11/30/2016 05:02 PM, Baolin Wang wrote:
>>>>>>> If the hardware never responds to the stop endpoint command, the
>>>>>>> URBs will never be completed, and we might hang the USB subsystem.
>>>>>>> The original watchdog timer is used to watch if one stop endpoint
>>>>>>> command is timeout, if timeout, then the watchdog timer will set
>>>>>>> XHCI_STATE_DYING, try to halt the xHCI host, and give back all
>>>>>>> pending URBs.
>>>>>>>
>>>>>>> But now we already have one command timer to control command timeout,
>>>>>>> thus we can also use the command timer to watch the stop endpoint
>>>>>>> command, instead of one duplicate watchdog timer which need to be
>>>>>>> removed.
>>>>>>>
>>>>>>> Meanwhile we don't need the 'stop_cmds_pending' flag to identy if
>>>>>>> this is the last stop endpoint command of one endpoint. Since we
>>>>>>> can make sure we only set one stop endpoint command for one endpoint
>>>>>>> by 'EP_HALT_PENDING' flag in xhci_urb_dequeue() function. Thus remove
>>>>>>> this flag.
>>>>>> I am afraid you can't do this. "stop_cmds_pending" was added
>>>>>> to fix the problem described in the comments that you want to
>>>>>> remove. But I didn't find any fix of this problem in your patch.
>>>>> Now we can not pending another stop endpoint command for the same one
>>>>> endpoint, since will check 'EP_HALT_PENDING' flag in
>>>>> xhci_urb_dequeue() function to avoid this. But after some
>>>>> investigation, I think I missed the stop endpoint command in
>>>>> xhci_stop_device() which did not check the 'EP_HALT_PENDING' flag,
>>>>> maybe need to add 'EP_HALT_PENDING' flag checking in
>>>>> xhci_stop_device() function. DId I miss something else? Thanks.
>>>> Consider below three threads running on different CPUs at the same time.
>>>>
>>>> Thread A: xhci_handle_cmd_stop_ep()  --- in interrupt handler
>>>> Thread B: xhci_stop_endpoint_command_timeout() --- timer expired
>>>> Thread C: xhci_urb_dequeue --- called by usb core
>>>>
>>>> They are serialized by xhci->lock. Let's consider below sequence:
>>>>
>>>> Thread A:
>>>> - delete xhci->cmd_timer), but will fail due to Thread B.
>>>> - clear EP_HALT_PENDING bit
>>>>
>>>> Thread B:
>>>> - halt the host controller
>>>>
>>>> Thread C:
>>>> - set EP_HALT_PENDING bit
>>>> - enqueue another stop endpoint command
>>>> - add the timer back
>>> Ah, thanks for you comments.
>>> If thread B halted the host, then the thread C xhci_urb_dequeue() will
>>> check host state failed, then just return and can not set another stop
>>> endpoint command.
>> Not so simple. Thread B will release xhci->lock before xhci_halt().
> Yes.
>
>>> But from your example, I think your meaning is we
>>> should not halt the host by thread B, since we have handled the stop
>>> endpoint command event.
>>>
>>> So I think we need to check the xhci command of this stop endpoint
>>> command in xhci_stop_endpoint_command_timeout(), if the xhci command
>>> of this stop endpoint command is not in the command list (which means
>>> the stop endpoint command event has been handled), then just return
>>> and do not halt the controller. Right?
>>>
>> I'd like suggest you to put this change into a separated patch.
>> It's actually a different topic from the main purpose of this patch.
> OK, I will. Thanks for your comments.
>

If you are going to work out a v2 patch, please consider whether
we can totally leverage the common command mechanism to
handle this stop endpoint command.

Currently, when a stop endpoint command is issued for urb unlink,
there are two timers for this command. This is duplicated and we
should remove the stop-endpoint-only timer. The timeout functions
are also different. The stop-endpoint-only timer just halt the host
controller (this should be the last sort of way), while the common
command timer will try to recover the situation by aborting and
restart the command ring.

Best regards,
Lu 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: xhci: fix possible wild pointer

2016-12-01 Thread Lu Baolu
handle_cmd_completion() frees a command structure which might
be still referenced by xhci->current_cmd. This might cause
problem when xhci->current_cmd is accessed after that.

A real-life case could be like this. The host takes a very long
time to respond to a command, and the command timer is fired at
the same time when the command completion event arrives. The
command completion handler frees xhci->current_cmd before the
timer function can grab xhci->lock. Afterward, timer function
grabs the lock and go ahead with checking and setting members
of xhci->current_cmd.

Cc:  # v3.16+
Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bdf6b13..13e05f6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1267,14 +1267,16 @@ void xhci_handle_command_timeout(unsigned long data)
bool second_timeout = false;
xhci = (struct xhci_hcd *) data;
 
-   /* mark this command to be cancelled */
spin_lock_irqsave(&xhci->lock, flags);
-   if (xhci->current_cmd) {
-   if (xhci->current_cmd->status == COMP_CMD_ABORT)
-   second_timeout = true;
-   xhci->current_cmd->status = COMP_CMD_ABORT;
+   if (!xhci->current_cmd) {
+   spin_unlock_irqrestore(&xhci->lock, flags);
+   return;
}
 
+   if (xhci->current_cmd->status == COMP_CMD_ABORT)
+   second_timeout = true;
+   xhci->current_cmd->status = COMP_CMD_ABORT;
+
/* Make sure command ring is running before aborting it */
hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
@@ -1422,6 +1424,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
xhci->current_cmd = list_entry(cmd->cmd_list.next,
   struct xhci_command, cmd_list);
mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+   } else if (xhci->current_cmd == cmd) {
+   xhci->current_cmd = NULL;
+   } else {
+   xhci_warn(xhci, "WARN current_cmd doesn't match command\n");
}
 
 event_handled:
-- 
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: xhci: fix possible wild pointer

2016-12-01 Thread Lu Baolu
Hi,

On 12/02/2016 12:18 PM, Baolin Wang wrote:
> On 2 December 2016 at 10:29, Lu Baolu  wrote:
>> handle_cmd_completion() frees a command structure which might
>> be still referenced by xhci->current_cmd. This might cause
>> problem when xhci->current_cmd is accessed after that.
>>
>> A real-life case could be like this. The host takes a very long
>> time to respond to a command, and the command timer is fired at
>> the same time when the command completion event arrives. The
>> command completion handler frees xhci->current_cmd before the
>> timer function can grab xhci->lock. Afterward, timer function
>> grabs the lock and go ahead with checking and setting members
>> of xhci->current_cmd.
>>
>> Cc:  # v3.16+
>> Signed-off-by: Lu Baolu 
> Nice catch. I was also curious where set xhci->current_cmd to be NULL
> when current command is freed.

Below code does:

xhci->current_cmd = list_entry(cmd->cmd_list.next,
   struct xhci_command, cmd_list);
mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
+   } else if (xhci->current_cmd == cmd) {
+   xhci->current_cmd = NULL;
+   } else {
+   xhci_warn(xhci, "WARN current_cmd doesn't match command\n");
}


Best regards,
Lu Baolu

> Tested-by: Baolin Wang 
>
>> ---
>>  drivers/usb/host/xhci-ring.c | 16 +++-
>>  1 file changed, 11 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index bdf6b13..13e05f6 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>> @@ -1267,14 +1267,16 @@ void xhci_handle_command_timeout(unsigned long data)
>> bool second_timeout = false;
>> xhci = (struct xhci_hcd *) data;
>>
>> -   /* mark this command to be cancelled */
>> spin_lock_irqsave(&xhci->lock, flags);
>> -   if (xhci->current_cmd) {
>> -   if (xhci->current_cmd->status == COMP_CMD_ABORT)
>> -   second_timeout = true;
>> -   xhci->current_cmd->status = COMP_CMD_ABORT;
>> +   if (!xhci->current_cmd) {
>> +   spin_unlock_irqrestore(&xhci->lock, flags);
>> +   return;
>> }
>>
>> +   if (xhci->current_cmd->status == COMP_CMD_ABORT)
>> +   second_timeout = true;
>> +   xhci->current_cmd->status = COMP_CMD_ABORT;
>> +
>> /* Make sure command ring is running before aborting it */
>> hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
>> if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
>> @@ -1422,6 +1424,10 @@ static void handle_cmd_completion(struct xhci_hcd 
>> *xhci,
>> xhci->current_cmd = list_entry(cmd->cmd_list.next,
>>struct xhci_command, 
>> cmd_list);
>> mod_timer(&xhci->cmd_timer, jiffies + 
>> XHCI_CMD_DEFAULT_TIMEOUT);
>> +   } else if (xhci->current_cmd == cmd) {
>> +   xhci->current_cmd = NULL;
>> +   } else {
>> +   xhci_warn(xhci, "WARN current_cmd doesn't match command\n");
>> }
>>
>>  event_handled:
>> --
>> 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
>
>

--
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 possible wild pointer

2016-12-05 Thread Lu Baolu
Hi,

On 12/02/2016 09:39 PM, Mathias Nyman wrote:
> On 02.12.2016 04:29, Lu Baolu wrote:
>> handle_cmd_completion() frees a command structure which might
>> be still referenced by xhci->current_cmd. This might cause
>> problem when xhci->current_cmd is accessed after that.
>>
>> A real-life case could be like this. The host takes a very long
>> time to respond to a command, and the command timer is fired at
>> the same time when the command completion event arrives. The
>> command completion handler frees xhci->current_cmd before the
>> timer function can grab xhci->lock. Afterward, timer function
>> grabs the lock and go ahead with checking and setting members
>> of xhci->current_cmd.
>>
>> Cc:  # v3.16+
>> Signed-off-by: Lu Baolu 
>> ---
>>   drivers/usb/host/xhci-ring.c | 16 +++-
>>   1 file changed, 11 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>> index bdf6b13..13e05f6 100644
>> --- a/drivers/usb/host/xhci-ring.c
>> +++ b/drivers/usb/host/xhci-ring.c
>> @@ -1267,14 +1267,16 @@ void xhci_handle_command_timeout(unsigned long data)
>>   bool second_timeout = false;
>>   xhci = (struct xhci_hcd *) data;
>>
>> -/* mark this command to be cancelled */
>>   spin_lock_irqsave(&xhci->lock, flags);
>> -if (xhci->current_cmd) {
>> -if (xhci->current_cmd->status == COMP_CMD_ABORT)
>> -second_timeout = true;
>> -xhci->current_cmd->status = COMP_CMD_ABORT;
>> +if (!xhci->current_cmd) {
>> +spin_unlock_irqrestore(&xhci->lock, flags);
>> +return;
>>   }
>>
>> +if (xhci->current_cmd->status == COMP_CMD_ABORT)
>> +second_timeout = true;
>> +xhci->current_cmd->status = COMP_CMD_ABORT;
>> +
>>   /* Make sure command ring is running before aborting it */
>>   hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
>>   if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
>> @@ -1422,6 +1424,10 @@ static void handle_cmd_completion(struct xhci_hcd 
>> *xhci,
>>   xhci->current_cmd = list_entry(cmd->cmd_list.next,
>>  struct xhci_command, cmd_list);
>>   mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
>> +} else if (xhci->current_cmd == cmd) {
>> +xhci->current_cmd = NULL;
>> +} else {
>> +xhci_warn(xhci, "WARN current_cmd doesn't match command\n");
>>   }
>>
>>   event_handled:
>>
>
> Thanks,
>
> I might do some tweaking to (or remove)  the warn message when applying if
> that is ok

Sure.

>
> -Mathias
>

Best regards,
Lu 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 2/2] usb: host: xhci: Handle the right timeout command

2016-12-19 Thread Lu Baolu
;>>>
>>>>
>>>> Yes, that's the cases what I want to handle, thanks for your explicit
>>>> explanation.
>>>>
>>>
>>> Gave this some more thought over the weekend, and this implementation
>>> doesn't solve the case when the last command times out and races with the
>>> completion handler:
>>>
>>> cpu1cpu2
>>>
>>> queue_command(first), p++ (=1)
>>> --completion irq fires---- timer times out at same time--
>>> handle_cmd_completion() handle_cmd_timeout(),)
>>> lock(xhci_lock )spin_on(xhci_lock)
>>> del_timer() fail, p (=1, nochange)
>>> no more commands, P (=1, nochange)
>>> unlock(xhci_lock)
>>>  lock(xhci_lock)
>>>  p-- (=0)
>>>  p == 0, continue, even if we should
>>> not.
>>>For this we still need to rely on
>>> checking cur_cmd == NULL in the timeout function.
>>> (Baolus patch sets it to NULL if there are no more commands pending)
>>
>> As I pointed out in patch 1 of this patchset, this patchset is based
>> on Lu Baolu's new fix patch:
>> usb: xhci: fix possible wild pointer
>> https://www.spinics.net/lists/linux-usb/msg150219.html
>>
>> After applying Baolu's patch, after decrement the counter, we will
>> check the xhci->cur_command if is NULL. So in this situation:
>> cpu1cpu2
>>
>>   queue_command(first), p++ (=1)
>>   --completion irq fires---- timer times out at same time--
>>   handle_cmd_completion() handle_cmd_timeout(),)
>>   lock(xhci_lock )spin_on(xhci_lock)
>>   del_timer() fail, p (=1, nochange)
>>   no more commands, P (=1, nochange)
>>   unlock(xhci_lock)
>>   lock(xhci_lock)
>>   p-- (=0)
>>   no current command, return
>>   if (!xhci->current_cmd) {
>>unlock(xhci_lock);
>>return;
>>   }
>>
>> It can work.
>
> Yes,
>
> What I wanted to say is that as it relies on Baolus patch for that one case
> it seems that patch 2/2 can be replaced by a single line change:
>
> if (!xhci->current_cmd || timer_pending(&xhci->cmd_timer))
>
> Right?
>
> -Mathias
>

It seems that the watch dog algorithm for command queue becomes
more and more complicated and hard for maintain. I am also seeing
another case where a command may lose the chance to be tracked by
the watch dog timer.

Say,

queue_command(the only command in queue)
  - completion irq fires--- timer times out at same time--  
- another command enqueue--
  - lock(xhci_lock ) - spin_on(xhci_lock)   
- spin_on(xhci_lock)
  - del_timer() fail
  - free the command and
set current_cmd to NULL
  - unlock(xhci_lock)

- lock(xhci_lock)

- queue_command()(timer will

   not rescheduled since the timer

   is pending)
 - lock(xhci_lock)
 - no current command
 - return

As the result, the later command isn't under track of the watch dog.
If hardware fails to response to this command, kernel will hang in
the thread which is waiting for the completion of the command.

I can write a patch to fix this and cc stable kernel as well. For long
term, in order to make it simple and easy to maintain, how about
allocating a watch dog timer for each command? It could be part
of the command structure and be managed just like the life cycle
of a command structure.

I can write a patch for review and discussion, if you think this
change is possible.

Best regards,
Lu 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 2/2] usb: host: xhci: Handle the right timeout command

2016-12-19 Thread Lu Baolu
Hi,

On 12/20/2016 02:06 PM, Baolin Wang wrote:
> Hi,
>
> On 20 December 2016 at 12:29, Lu Baolu  wrote:
>> Hi Mathias,
>>
>> On 12/19/2016 08:13 PM, Mathias Nyman wrote:
>>> On 19.12.2016 13:34, Baolin Wang wrote:
>>>> Hi Mathias,
>>>>
>>>> On 19 December 2016 at 18:33, Mathias Nyman
>>>>  wrote:
>>>>> On 13.12.2016 05:21, Baolin Wang wrote:
>>>>>> Hi Mathias,
>>>>>>
>>>>>> On 12 December 2016 at 23:52, Mathias Nyman
>>>>>>  wrote:
>>>>>>> On 05.12.2016 09:51, Baolin Wang wrote:
>>>>>>>>
>>>>>>>> If a command event is found on the event ring during an interrupt,
>>>>>>>> we need to stop the command timer with del_timer(). Since del_timer()
>>>>>>>> can fail if the timer is running and waiting on the xHCI lock, then
>>>>>>>> it maybe get the wrong timeout command in xhci_handle_command_timeout()
>>>>>>>> if host fetched a new command and updated the xhci->current_cmd in
>>>>>>>> handle_cmd_completion(). For this situation, we need a way to signal
>>>>>>>> to the command timer that everything is fine and it should exit.
>>>>>>>
>>>>>>>
>>>>>>> Ah, right, this could actually happen.
>>>>>>>
>>>>>>>>
>>>>>>>> We should introduce a counter (xhci->current_cmd_pending) for the 
>>>>>>>> number
>>>>>>>> of pending commands. If we need to cancel the command timer and
>>>>>>>> del_timer()
>>>>>>>> succeeds, we decrement the number of pending commands. If del_timer()
>>>>>>>> fails,
>>>>>>>> we leave the number of pending commands alone.
>>>>>>>>
>>>>>>>> For handling timeout command, in xhci_handle_command_timeout() we will
>>>>>>>> check
>>>>>>>> the counter after decrementing it, if the counter
>>>>>>>> (xhci->current_cmd_pending)
>>>>>>>> is 0, which means xhci->current_cmd is the right timeout command. If 
>>>>>>>> the
>>>>>>>> counter (xhci->current_cmd_pending) is greater than 0, which means
>>>>>>>> current
>>>>>>>> timeout command has been handled by host and host has fetched new
>>>>>>>> command
>>>>>>>> as
>>>>>>>> xhci->current_cmd, then just return and wait for new current command.
>>>>>>>
>>>>>>>
>>>>>>> A counter like this could work.
>>>>>>>
>>>>>>> Writing the abort bit can generate either ABORT+STOP, or just STOP
>>>>>>> event, this seems to cover both.
>>>>>>>
>>>>>>> quick check, case 1: timeout and cmd completion at the same time.
>>>>>>>
>>>>>>> cpu1cpu2
>>>>>>>
>>>>>>> queue_command(first), p++ (=1)
>>>>>>> queue_command(more),
>>>>>>> --completion irq fires---- timer times out at same 
>>>>>>> time--
>>>>>>> handle_cmd_completion() handle_cmd_timeout(),)
>>>>>>> lock(xhci_lock  )   spin_on(xhci_lock)
>>>>>>> del_timer() fail, p (=1, nochange)
>>>>>>> cur_cmd = list_next(), p++ (=2)
>>>>>>> unlock(xhci_lock)
>>>>>>>   lock(xhci_lock)
>>>>>>>   p-- (=1)
>>>>>>>   if (p > 0), exit
>>>>>>> OK works
>>>>>>>
>>>>>>> case 2: normal timeout case with ABORT+STOP, no race.
>>>>>>>
>>>>>>> cpu1cpu2
>>>>>>>
>>>>>>> queue_command(first), p++ (=1)
>>>>>>> queue_command(more),
>>>>>>>   handle_cmd_timeout()
>>>>>>>   p-- (P=0), don&#x

Re: [PATCH 2/2] usb: host: xhci: Handle the right timeout command

2016-12-19 Thread Lu Baolu
Hi,

On 12/20/2016 02:46 PM, Baolin Wang wrote:
> On 20 December 2016 at 14:39, Lu Baolu  wrote:
>> Hi,
>>
>> On 12/20/2016 02:06 PM, Baolin Wang wrote:
>>> Hi,
>>>
>>> On 20 December 2016 at 12:29, Lu Baolu  wrote:
>>>> Hi Mathias,
>>>>
>>>> On 12/19/2016 08:13 PM, Mathias Nyman wrote:
>>>>> On 19.12.2016 13:34, Baolin Wang wrote:
>>>>>> Hi Mathias,
>>>>>>
>>>>>> On 19 December 2016 at 18:33, Mathias Nyman
>>>>>>  wrote:
>>>>>>> On 13.12.2016 05:21, Baolin Wang wrote:
>>>>>>>> Hi Mathias,
>>>>>>>>
>>>>>>>> On 12 December 2016 at 23:52, Mathias Nyman
>>>>>>>>  wrote:
>>>>>>>>> On 05.12.2016 09:51, Baolin Wang wrote:
>>>>>>>>>> If a command event is found on the event ring during an interrupt,
>>>>>>>>>> we need to stop the command timer with del_timer(). Since del_timer()
>>>>>>>>>> can fail if the timer is running and waiting on the xHCI lock, then
>>>>>>>>>> it maybe get the wrong timeout command in 
>>>>>>>>>> xhci_handle_command_timeout()
>>>>>>>>>> if host fetched a new command and updated the xhci->current_cmd in
>>>>>>>>>> handle_cmd_completion(). For this situation, we need a way to signal
>>>>>>>>>> to the command timer that everything is fine and it should exit.
>>>>>>>>>
>>>>>>>>> Ah, right, this could actually happen.
>>>>>>>>>
>>>>>>>>>> We should introduce a counter (xhci->current_cmd_pending) for the 
>>>>>>>>>> number
>>>>>>>>>> of pending commands. If we need to cancel the command timer and
>>>>>>>>>> del_timer()
>>>>>>>>>> succeeds, we decrement the number of pending commands. If del_timer()
>>>>>>>>>> fails,
>>>>>>>>>> we leave the number of pending commands alone.
>>>>>>>>>>
>>>>>>>>>> For handling timeout command, in xhci_handle_command_timeout() we 
>>>>>>>>>> will
>>>>>>>>>> check
>>>>>>>>>> the counter after decrementing it, if the counter
>>>>>>>>>> (xhci->current_cmd_pending)
>>>>>>>>>> is 0, which means xhci->current_cmd is the right timeout command. If 
>>>>>>>>>> the
>>>>>>>>>> counter (xhci->current_cmd_pending) is greater than 0, which means
>>>>>>>>>> current
>>>>>>>>>> timeout command has been handled by host and host has fetched new
>>>>>>>>>> command
>>>>>>>>>> as
>>>>>>>>>> xhci->current_cmd, then just return and wait for new current command.
>>>>>>>>>
>>>>>>>>> A counter like this could work.
>>>>>>>>>
>>>>>>>>> Writing the abort bit can generate either ABORT+STOP, or just STOP
>>>>>>>>> event, this seems to cover both.
>>>>>>>>>
>>>>>>>>> quick check, case 1: timeout and cmd completion at the same time.
>>>>>>>>>
>>>>>>>>> cpu1cpu2
>>>>>>>>>
>>>>>>>>> queue_command(first), p++ (=1)
>>>>>>>>> queue_command(more),
>>>>>>>>> --completion irq fires---- timer times out at same 
>>>>>>>>> time--
>>>>>>>>> handle_cmd_completion() handle_cmd_timeout(),)
>>>>>>>>> lock(xhci_lock  )   spin_on(xhci_lock)
>>>>>>>>> del_timer() fail, p (=1, nochange)
>>>>>>>>> cur_cmd = list_next(), p++ (=2)
>>>>>>>>> unlock(xhci_lock)
>>>>>>>>>   lock(xhci_lock)
>>>>>>>>>   p-- (=1)
>>>>>>>&

Re: [PATCH 2/2] usb: host: xhci: Handle the right timeout command

2016-12-20 Thread Lu Baolu
Hi Mathias,

I have some comments for the implementation of xhci_abort_cmd_ring() below.

On 12/20/2016 11:13 PM, Mathias Nyman wrote:
> On 20.12.2016 09:30, Baolin Wang wrote:
> ...
>
> Alright, I gathered all current work related to xhci races and timeouts
> and put them into a branch:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git 
> timeout_race_fixes
>
> Its based on 4.9
> It includes a few other patches just to avoid conflicts and  make my life 
> easier
>
> Interesting patches are:
>
> ee4eb91 xhci: remove unnecessary check for pending timer
> 0cba67d xhci: detect stop endpoint race using pending timer instead of 
> counter.
> 4f2535f xhci: Handle command completion and timeout race
> b9d00d7 usb: host: xhci: Fix possible wild pointer when handling abort command
> 529a5a0 usb: xhci: fix possible wild pointer
> 4766555 xhci: Fix race related to abort operation
> de834a3 xhci: Use delayed_work instead of timer for command timeout
> 69973b8 Linux 4.9
>
> The fixes for command queue races will go to usb-linus and stable, the
> reworks for stop ep watchdog timer will go to usb-next.
>
> Still completely untested, (well it compiles)
>
> Felipe gave instructions how to modify dwc3 driver to timeout on address
> devicecommands to test these, I'll try to set that up.
>
> All additional testing is welcome, especially if you can trigger timeouts
> and races
>
> -Mathias
>
>

Below is the latest code. I put my comments in line.

 322 static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
 323 {
 324 u64 temp_64;
 325 int ret;
 326
 327 xhci_dbg(xhci, "Abort command ring\n");
 328
 329 reinit_completion(&xhci->cmd_ring_stop_completion);
 330
 331 temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
 332 xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
 333 &xhci->op_regs->cmd_ring);

We should hold xhci->lock when we are modifying xhci registers
at runtime.


 334
 335 /* Section 4.6.1.2 of xHCI 1.0 spec says software should
 336  * time the completion od all xHCI commands, including

s/od/of/g

 337  * the Command Abort operation. If software doesn't see
 338  * CRR negated in a timely manner (e.g. longer than 5
 339  * seconds), then it should assume that the there are
 340  * larger problems with the xHC and assert HCRST.
 341  */
 342 ret = xhci_handshake(&xhci->op_regs->cmd_ring,
 343 CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
 344 if (ret < 0) {
 345 /* we are about to kill xhci, give it one more chance */

The retry of setting CMD_RING_ABORT is not necessary according to
previous discussion. We have cleaned code for second try in
xhci_handle_command_timeout(). Need to clean up here as well.

 346 xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
 347   &xhci->op_regs->cmd_ring);
 348 udelay(1000);
 349 ret = xhci_handshake(&xhci->op_regs->cmd_ring,
 350  CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
 351 if (ret < 0) {
 352 xhci_err(xhci, "Stopped the command ring failed, "
 353  "maybe the host is dead\n");
 354 xhci->xhc_state |= XHCI_STATE_DYING;
 355 xhci_halt(xhci);
 356 return -ESHUTDOWN;
 357 }
 358 }
 359 /*
 360  * Writing the CMD_RING_ABORT bit should cause a cmd completion 
event,
 361  * however on some host hw the CMD_RING_RUNNING bit is correctly 
cleared
 362  * but the completion event in never sent. Wait 2 secs (arbitrary

s/in never sent/is never sent/g

 363  * number) to handle those cases after negation of 
CMD_RING_RUNNING.
 364  */

This should be implemented with a quirk bit. It's not common for all host 
controllers.

 365 if (!wait_for_completion_timeout(&xhci->cmd_ring_stop_completion,
 366  2 * HZ)) {
 367 xhci_dbg(xhci, "No stop event for abort, ring start 
fail?\n");
 368 xhci_cleanup_command_queue(xhci);
 369 } else {
 370 unsigned long flags;
 371
 372 spin_lock_irqsave(&xhci->lock, flags);
 373 xhci_handle_stopped_cmd_ring(xhci, 
xhci_next_queued_cmd(xhci));
 374 spin_unlock_irqrestore(&xhci->lock, flags);
 375 }
 376 return 0;
 377 }

Best regards,
Lu 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 2/2] usb: host: xhci: Handle the right timeout command

2016-12-20 Thread Lu Baolu
Hi Mathias,

I have some comments for the implementation of
xhci_handle_command_timeout() as well.

On 12/20/2016 11:13 PM, Mathias Nyman wrote:
> On 20.12.2016 09:30, Baolin Wang wrote:
> ...
>
> Alright, I gathered all current work related to xhci races and timeouts
> and put them into a branch:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git 
> timeout_race_fixes
>
> Its based on 4.9
> It includes a few other patches just to avoid conflicts and  make my life 
> easier
>
> Interesting patches are:
>
> ee4eb91 xhci: remove unnecessary check for pending timer
> 0cba67d xhci: detect stop endpoint race using pending timer instead of 
> counter.
> 4f2535f xhci: Handle command completion and timeout race
> b9d00d7 usb: host: xhci: Fix possible wild pointer when handling abort command
> 529a5a0 usb: xhci: fix possible wild pointer
> 4766555 xhci: Fix race related to abort operation
> de834a3 xhci: Use delayed_work instead of timer for command timeout
> 69973b8 Linux 4.9
>
> The fixes for command queue races will go to usb-linus and stable, the
> reworks for stop ep watchdog timer will go to usb-next.
>
> Still completely untested, (well it compiles)
>
> Felipe gave instructions how to modify dwc3 driver to timeout on address
> devicecommands to test these, I'll try to set that up.
>
> All additional testing is welcome, especially if you can trigger timeouts
> and races
>
> -Mathias
>
>

I post the code below and add my comments in line.

1276 void xhci_handle_command_timeout(struct work_struct *work)
1277 {
1278 struct xhci_hcd *xhci;
1279 int ret;
1280 unsigned long flags;
1281 u64 hw_ring_state;
1282
1283 xhci = container_of(to_delayed_work(work), struct xhci_hcd, 
cmd_timer);
1284
1285 spin_lock_irqsave(&xhci->lock, flags);
1286
1287 /*
1288  * If timeout work is pending, or current_cmd is NULL, it means we
1289  * raced with command completion. Command is handled so just 
return.
1290  */
1291 if (!xhci->current_cmd || delayed_work_pending(&xhci->cmd_timer)) {
1292 spin_unlock_irqrestore(&xhci->lock, flags);
1293 return;
1294 }
1295 /* mark this command to be cancelled */
1296 xhci->current_cmd->status = COMP_CMD_ABORT;
1297
1298 /* Make sure command ring is running before aborting it */
1299 hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
1300 if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
1301 (hw_ring_state & CMD_RING_RUNNING))  {
1302 /* Prevent new doorbell, and start command abort */
1303 xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
1304 spin_unlock_irqrestore(&xhci->lock, flags);
1305 xhci_dbg(xhci, "Command timeout\n");
1306 ret = xhci_abort_cmd_ring(xhci);
1307 if (unlikely(ret == -ESHUTDOWN)) {
1308 xhci_err(xhci, "Abort command ring failed\n");
1309 xhci_cleanup_command_queue(xhci);
1310 usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
1311 xhci_dbg(xhci, "xHCI host controller is dead.\n");
1312 }
1313 return;
1314 }
1315
1316 /* host removed. Bail out */
1317 if (xhci->xhc_state & XHCI_STATE_REMOVING) {
1318 spin_unlock_irqrestore(&xhci->lock, flags);
1319 xhci_dbg(xhci, "host removed, ring start fail?\n");
1320 xhci_cleanup_command_queue(xhci);
1321 return;
1322 }

I think this part of code should be moved up to line 1295.

1323
1324 /* command timeout on stopped ring, ring can't be aborted */
1325 xhci_dbg(xhci, "Command timeout on stopped ring\n");
1326 xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
1327 spin_unlock_irqrestore(&xhci->lock, flags);

This part of code is tricky. I have no idea about in which case should this
code be executed? Anyway, we shouldn't call xhci_handle_stopped_cmd_ring()
here, right?

1328 return;
1329 }

Best regards,
Lu 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 2/2] usb: host: xhci: Handle the right timeout command

2016-12-21 Thread Lu Baolu
Hi,

On 12/21/2016 08:57 PM, Mathias Nyman wrote:
> On 21.12.2016 08:57, Lu Baolu wrote:
>> Hi Mathias,
>>
>> I have some comments for the implementation of
>> xhci_handle_command_timeout() as well.
>>
>> On 12/20/2016 11:13 PM, Mathias Nyman wrote:
>>> On 20.12.2016 09:30, Baolin Wang wrote:
>>> ...
>>>
>>> Alright, I gathered all current work related to xhci races and timeouts
>>> and put them into a branch:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git 
>>> timeout_race_fixes
>>>
>>> Its based on 4.9
>>> It includes a few other patches just to avoid conflicts and  make my life 
>>> easier
>>>
>>> Interesting patches are:
>>>
>>> ee4eb91 xhci: remove unnecessary check for pending timer
>>> 0cba67d xhci: detect stop endpoint race using pending timer instead of 
>>> counter.
>>> 4f2535f xhci: Handle command completion and timeout race
>>> b9d00d7 usb: host: xhci: Fix possible wild pointer when handling abort 
>>> command
>>> 529a5a0 usb: xhci: fix possible wild pointer
>>> 4766555 xhci: Fix race related to abort operation
>>> de834a3 xhci: Use delayed_work instead of timer for command timeout
>>> 69973b8 Linux 4.9
>>>
>>> The fixes for command queue races will go to usb-linus and stable, the
>>> reworks for stop ep watchdog timer will go to usb-next.
>>>
>>> Still completely untested, (well it compiles)
>>>
>>> Felipe gave instructions how to modify dwc3 driver to timeout on address
>>> devicecommands to test these, I'll try to set that up.
>>>
>>> All additional testing is welcome, especially if you can trigger timeouts
>>> and races
>>>
>>> -Mathias
>>>
>>>
>>
>> I post the code below and add my comments in line.
>>
>> 1276 void xhci_handle_command_timeout(struct work_struct *work)
>> 1277 {
>> 1278 struct xhci_hcd *xhci;
>> 1279 int ret;
>> 1280 unsigned long flags;
>> 1281 u64 hw_ring_state;
>> 1282
>> 1283 xhci = container_of(to_delayed_work(work), struct xhci_hcd, 
>> cmd_timer);
>> 1284
>> 1285 spin_lock_irqsave(&xhci->lock, flags);
>> 1286
>> 1287 /*
>> 1288  * If timeout work is pending, or current_cmd is NULL, it means 
>> we
>> 1289  * raced with command completion. Command is handled so just 
>> return.
>> 1290  */
>> 1291 if (!xhci->current_cmd || 
>> delayed_work_pending(&xhci->cmd_timer)) {
>> 1292 spin_unlock_irqrestore(&xhci->lock, flags);
>> 1293 return;
>> 1294 }
>> 1295 /* mark this command to be cancelled */
>> 1296 xhci->current_cmd->status = COMP_CMD_ABORT;
>> 1297
>> 1298 /* Make sure command ring is running before aborting it */
>> 1299 hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
>> 1300 if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
>> 1301 (hw_ring_state & CMD_RING_RUNNING))  {
>> 1302 /* Prevent new doorbell, and start command abort */
>> 1303 xhci->cmd_ring_state = CMD_RING_STATE_ABORTED;
>> 1304 spin_unlock_irqrestore(&xhci->lock, flags);
>> 1305 xhci_dbg(xhci, "Command timeout\n");
>> 1306 ret = xhci_abort_cmd_ring(xhci);
>> 1307 if (unlikely(ret == -ESHUTDOWN)) {
>> 1308 xhci_err(xhci, "Abort command ring failed\n");
>> 1309 xhci_cleanup_command_queue(xhci);
>> 1310 usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
>> 1311 xhci_dbg(xhci, "xHCI host controller is 
>> dead.\n");
>> 1312 }
>> 1313 return;
>> 1314 }
>> 1315
>> 1316 /* host removed. Bail out */
>> 1317 if (xhci->xhc_state & XHCI_STATE_REMOVING) {
>> 1318 spin_unlock_irqrestore(&xhci->lock, flags);
>> 1319 xhci_dbg(xhci, "host removed, ring start fail?\n");
>> 1320 xhci_cleanup_command_queue(xhci);
>> 1321 return;
>> 1322 }
>>
>> I think this part of code should be moved up to line 1295.
>
> The XHCI_STATE

Re: [PATCH 2/2] usb: host: xhci: Handle the right timeout command

2016-12-21 Thread Lu Baolu
Hi,

On 12/21/2016 08:48 PM, Mathias Nyman wrote:
> On 21.12.2016 08:17, Lu Baolu wrote:
>> Hi Mathias,
>>
>> I have some comments for the implementation of xhci_abort_cmd_ring() below.
>>
>> On 12/20/2016 11:13 PM, Mathias Nyman wrote:
>>> On 20.12.2016 09:30, Baolin Wang wrote:
>>> ...
>>>
>>> Alright, I gathered all current work related to xhci races and timeouts
>>> and put them into a branch:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git 
>>> timeout_race_fixes
>>>
>>> Its based on 4.9
>>> It includes a few other patches just to avoid conflicts and  make my life 
>>> easier
>>>
>>> Interesting patches are:
>>>
>>> ee4eb91 xhci: remove unnecessary check for pending timer
>>> 0cba67d xhci: detect stop endpoint race using pending timer instead of 
>>> counter.
>>> 4f2535f xhci: Handle command completion and timeout race
>>> b9d00d7 usb: host: xhci: Fix possible wild pointer when handling abort 
>>> command
>>> 529a5a0 usb: xhci: fix possible wild pointer
>>> 4766555 xhci: Fix race related to abort operation
>>> de834a3 xhci: Use delayed_work instead of timer for command timeout
>>> 69973b8 Linux 4.9
>>>
>>> The fixes for command queue races will go to usb-linus and stable, the
>>> reworks for stop ep watchdog timer will go to usb-next.
>>>
>>> Still completely untested, (well it compiles)
>>>
>>> Felipe gave instructions how to modify dwc3 driver to timeout on address
>>> devicecommands to test these, I'll try to set that up.
>>>
>>> All additional testing is welcome, especially if you can trigger timeouts
>>> and races
>>>
>>> -Mathias
>>>
>>>
>>
>> Below is the latest code. I put my comments in line.
>>
>>   322 static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
>>   323 {
>>   324 u64 temp_64;
>>   325 int ret;
>>   326
>>   327 xhci_dbg(xhci, "Abort command ring\n");
>>   328
>>   329 reinit_completion(&xhci->cmd_ring_stop_completion);
>>   330
>>   331 temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
>>   332 xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
>>   333 &xhci->op_regs->cmd_ring);
>>
>> We should hold xhci->lock when we are modifying xhci registers
>> at runtime.
>>
>
> Makes sense, but we need to unlock it before sleeping or waiting for 
> completion.
> I need to look into that in more detail.
>
> But this was an issue already before these changes.
>
>> The retry of setting CMD_RING_ABORT is not necessary according to
>> previous discussion. We have cleaned code for second try in
>> xhci_handle_command_timeout(). Need to clean up here as well.
>>
>
> Yes it can be cleaned up as well, but the two cases are a bit different.
> The cleaned up one was about command ring not starting again after it was 
> stopped.
>
> This second try is a workaround for what we thought was the command ring 
> failing
> to stop in the first place, but is most likely due to the race that OGAWA 
> Hirofumi
> fixed.  It races if the stop command ring interrupt happens between writing 
> the abort
> bit and polling for the ring stopped bit. The interrupt hander may start the 
> command
> ring again, and we would believe we failed to stop it in the first place.
>
> This race could probably be fixed by just extending the lock (and preventing
> interrupts) to cover both writing the abort bit and polling for the command 
> ring
> running bit, as you pointed out here previously.
>
> But then again I really like OGAWA Hiroumi's solution that separates the
> command ring stopping from aborting commands and restarting the ring.
>
> The current way of always restarting the command ring as a response to
> a stop command ring command really limits its usage.
>
> So, with this in mind most reasonable would be to
> 1. fix the lock to cover abort+CRR check, and send it to usb-linus +stable
> 2. rebase OGAWA Hirofumi's changes on top of that, and send to usb-linus only
> 3. remove unnecessary second abort try as a separate patch, send to usb-next
> 4. remove polling for the Command ring running (CRR), waiting for completion
>is enough, if completion times out then we can check CRR. for usb-next
>I'll fix the typos these patches would introduce. Fixing old typos can be 
> done as separate
> patches later.

This is exactly the same as what I am thinking of. I will submit the patches 
later.

Best regards,
Lu 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 2/2] usb: host: xhci: Handle the right timeout command

2016-12-21 Thread Lu Baolu
Hi,

On 12/21/2016 11:18 PM, OGAWA Hirofumi wrote:
> Mathias Nyman  writes:
>
>>> We set CMD_RING_STATE_ABORTED state under locking. I'm not checking what
>>> is for taking lock for register though, I guess it should be enough just
>>> lock around of read=>write of ->cmd_ring if need lock.
>> After your patch it should be enough to have the lock only while
>> reading and writing the cmd_ring register.
>>
>> If we want a locking fix that applies more easily to older stable
>> releases before your change then the lock needs to cover set
>> CMD_RING_STATE_ABORT, read cmd_reg, write cmd_reg and busiloop
>> checking CRR bit.  Otherwise the stop cmd ring interrupt handler may
>> restart the ring just before we start checing CRR. The stop cmd ring
>> interrupt will set the CMD_RING_STATE_ABORTED to
>> CMD_RING_STATE_RUNNING so ring will really restart in the interrupt
>> handler.
> Just for record (no chance to make patch I myself for now, sorry), while
> checking locking slightly, I noticed unrelated missing locking.
>
>   xhci_cleanup_command_queue()
>
> We are calling it without locking, but we need to lock for accessing list.

Yeah. I can make the patch.

Best regards,
Lu 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 2/2] phy: Add new Intel Cherrytrail USB OTG phy driver

2016-12-22 Thread Lu Baolu
Hi,

On 12/22/2016 07:47 PM, Hans de Goede wrote:
> +static int intel_cht_usb_phy_probe(struct platform_device *pdev)
> +{
> + struct intel_cht_usb_phy *phy;
> + struct device *dev = &pdev->dev;
> + struct resource *res;
> + resource_size_t size;
> + int i, ret;
> +
> + phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
> + if (!phy)
> + return -ENOMEM;
> +
> + phy->dev = dev;
> + phy->mode = PHY_MODE_USB_OTG;
> + INIT_WORK(&phy->work, intel_cht_usb_phy_work);
> + platform_set_drvdata(pdev, phy);
> +
> + phy->id_extcon = extcon_get_extcon_dev(USB_HOST_EXTCON_DEV_NAME);
> + if (phy->id_extcon == NULL) {
> + dev_dbg(dev, "id_extcon is not ready, probe deferred\n");
> + return -EPROBE_DEFER;
> + }
> +
> + phy->vbus_extcon = extcon_get_extcon_dev(AXP288_EXTCON_DEV_NAME);
> + if (phy->vbus_extcon == NULL) {
> + dev_dbg(dev, "vbus_extcon is not ready, probe deferred\n");
> + return -EPROBE_DEFER;
> + }
> +
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + size = (res->end + 1) - res->start;

"res" is used without check.

> + phy->base = devm_ioremap_nocache(dev, res->start, size);

This resource is part of xHCI MMIO. xHCI driver has already declared
to use the whole memory space. I am afraid you are not able to do this
due to resource conflict.

Best regards,
Lu Baolu

> + if (IS_ERR(phy->base)) {
> + ret = PTR_ERR(phy->base);
> + dev_err(dev, "can't iomap registers: %d\n", ret);
> + return ret;
> + }
> +
> + phy->phy = devm_phy_create(dev, NULL, &intel_cht_usb_phy_ops);
> + if (IS_ERR(phy->phy)) {
> + ret = PTR_ERR(phy->phy);
> + dev_err(dev, "can't create PHY: %d\n", ret);
> + return ret;
> + }
> + phy_set_drvdata(phy->phy, phy);
> +
> + /* Register for id notification */
> + phy->id_nb.notifier_call = intel_cht_usb_phy_id_cable_evt;
> + ret = devm_extcon_register_notifier(dev, phy->id_extcon,
> + EXTCON_USB_HOST, &phy->id_nb);
> + if (ret) {
> + dev_err(dev, "can't register id extcon notifier: %d\n", ret);
> + return ret;
> + }
> +
> + /* Register for vbus notification */
> + phy->vbus_nb[0].notifier_call = intel_cht_usb_phy_vbus_cable0_evt;
> + phy->vbus_nb[1].notifier_call = intel_cht_usb_phy_vbus_cable1_evt;
> + phy->vbus_nb[2].notifier_call = intel_cht_usb_phy_vbus_cable2_evt;
> + for (i = 0; i < ARRAY_SIZE(vbus_cable_ids); i++) {
> + ret = devm_extcon_register_notifier(dev, phy->vbus_extcon,
> + vbus_cable_ids[i], &phy->vbus_nb[i]);
> + if (ret) {
> + dev_err(dev, "can't register extcon notifier for %u: 
> %d\n",
> + vbus_cable_ids[i], ret);
> + return ret;
> + }
> + }
> +
> + /* Get and process initial cable states */
> + schedule_work(&phy->work);
> +
> + device_create_file(dev, &dev_attr_mode);
> +
> + return phy_create_lookup(phy->phy, "dwc3.0", "usb3-phy");
> +}

--
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 0/2] Intel cherrytrail xhci extended cap phy/mux support

2016-12-22 Thread Lu Baolu
Hi,

On 12/22/2016 09:18 PM, Felipe Balbi wrote:
> Hi,
>
> Hans de Goede  writes:
>>>> Here are 2 patches which can and should be merged separately, but
>>>> which do belong together, as together they add support for the
>>>> usb-phy / mux bits found in the Intel Cherrytrail xhci vendor defined
>>>> extended capabilities registers.
>>>>
>>>> I did not want to hide an entire phy driver inside the xhci code,
>>>> nor did I want to add an extcon dependency to the xhci code, so
>>>> I've chosen to simply make the xhci code register a platform childdev
>>>> with an IOMEM resource with the Intel Cherrytrail xhci vendor defined
>>>> extended capabilities registers when these are found. This keeps the
>>>> xhci driver clean and allows writing a separate phy driver, this is
>>>> the first patch, which should be merged through the USB tree.
>>>>
>>>> The second patch adds the actual phy driver, one thing which stands
>>>> out is that it completely depends on extcon devices to get idpin and
>>>> vbus state as that is done by other chips on cherrytrail devices,
>>>> atm the extcon devices are hardcoded to axp288_extcon for the vbus
>>>> detection and the ACPI INT3496:00 device for the idpin detection.
>>>>
>>>> On some boards a different pmic then the axp288 may be used, so in
>>>> the future we may end up with an array with extcon device names to
>>>> try until we've found one.
>>>>
>>>> The phy driver also adds a mode sysfs attribute, this is useful for
>>>> testing, as well with a so called charging oth hub, where the idpin
>>>> will indicate device/charge mode, but we can also use usb-devices
>>>> plugged into the hub by switching the data lines to host mode.
>>> Baolu has worked on this for months but it turned out that several folks
>>> said 'no' to his patchset. You're not really dealing with a PHY, it's
>>> just a portmux which can generate some UTMI messages to make sure dwc3
>>> is happy.
>> Right, I opted for a phy driver because that is the closest I could
>> get to something resembling what this thing does.
>>
>>> The end of the story about this, at least for broxton, was that mux
>>> control was moved to ASL. I'm not sure why folks didn't update CHT (or
>>> other devices') BIOS though.
>> I don't think expecting things to get "fixed" by firmware updates, esp.
>> firmware updates adding whole new functionality is going to happen, that
>> just is not realistic (esp. with cheap devices like these). And even if
>> it were fixed in firmware users are really bad add updating there firmware.
> True that. If you can convince all folks involved that a PHY driver or a
> portmux framework is acceptable, then more power for you :-)
>
> Frankly, though, this should always have been handled at ASL level
> because port role is really decided at cable connection time
> (well... not 100% true).
>
>>> Baolu, any comments to this series?
>>>
>>> Personally, I'm unwilling to take this (or the other 2-patch dwc3 series
>>> adding IDA) because there will only be a single user.
>> Only a single user ? You mean only a single SoC will use this I guess ?
> yeah
>
>> But there are many many devices with this SoC and lots of people are
>> trying to run "plain" Linux on these.
> don't get me wrong. I'd really like to have Up Board running mainline
> with no extra hacks necessary ;-)
>
>> I can see how you don't want this as a phy driver though, I would
>> be happy to drop the phy-binding bits (they're not really used
>> anyways) and drop this under drivers/misc adding myself to MAINTAINERS
>> for it, would that be an acceptable solution ?
> For me? sure :-) Let's get Greg and Oliver to agree though.
>
>> About the "other 2-patch dwc3 series", I'm fine with you not taking
>> the IDA patch, but the first patch is unrelated to IDA, it is a pure
>> bug-fix and really should be upstreamed.
> right, that's true.
>
>> Matthias, assuming Felipe is ok with putting this in drivers/misc
>> (minus the phy bindings), are you ok with the xhci blurb which
>> registers the platform-device for the "misc" driver to bind to?
> This is the one thing Greg was against. The creation of the "fake"
> platform-device from XHCI. 

Greg was unhappy with my portmux patch set due to "faking
a platform-device from a PCI device". We need to avoid this.

Best regards,
Lu Baolu

> I mean, turning it into a real PCI device
> will require firmware update, so we might as well update the firmware to
> move MUX handling to ASL altogether ;-)
>

--
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 0/2] Intel cherrytrail xhci extended cap phy/mux support

2016-12-22 Thread Lu Baolu
Hi,

On 12/23/2016 06:10 AM, Hans de Goede wrote:
> Hi,
>
> On 22-12-16 17:28, Mathias Nyman wrote:
>> On 22.12.2016 14:45, Hans de Goede wrote:
>>> Hi,
>>>
>>> On 22-12-16 13:11, Felipe Balbi wrote:
>>>>
>>>> Hi,
>>>>
>>>> Hans de Goede  writes:
>>>>> Hi All,
>>>>>
>>>>> Here are 2 patches which can and should be merged separately, but
>>>>> which do belong together, as together they add support for the
>>>>> usb-phy / mux bits found in the Intel Cherrytrail xhci vendor defined
>>>>> extended capabilities registers.
>>>>>
>>>>> I did not want to hide an entire phy driver inside the xhci code,
>>>>> nor did I want to add an extcon dependency to the xhci code, so
>>>>> I've chosen to simply make the xhci code register a platform childdev
>>>>> with an IOMEM resource with the Intel Cherrytrail xhci vendor defined
>>>>> extended capabilities registers when these are found. This keeps the
>>>>> xhci driver clean and allows writing a separate phy driver, this is
>>>>> the first patch, which should be merged through the USB tree.
>>>>>
>>>>> The second patch adds the actual phy driver, one thing which stands
>>>>> out is that it completely depends on extcon devices to get idpin and
>>>>> vbus state as that is done by other chips on cherrytrail devices,
>>>>> atm the extcon devices are hardcoded to axp288_extcon for the vbus
>>>>> detection and the ACPI INT3496:00 device for the idpin detection.
>>>>>
>>>>> On some boards a different pmic then the axp288 may be used, so in
>>>>> the future we may end up with an array with extcon device names to
>>>>> try until we've found one.
>>>>>
>>>>> The phy driver also adds a mode sysfs attribute, this is useful for
>>>>> testing, as well with a so called charging oth hub, where the idpin
>>>>> will indicate device/charge mode, but we can also use usb-devices
>>>>> plugged into the hub by switching the data lines to host mode.
>>>>
>>>> Baolu has worked on this for months but it turned out that several folks
>>>> said 'no' to his patchset. You're not really dealing with a PHY, it's
>>>> just a portmux which can generate some UTMI messages to make sure dwc3
>>>> is happy.
>>>
>>> Right, I opted for a phy driver because that is the closest I could
>>> get to something resembling what this thing does.
>>>
>>>> The end of the story about this, at least for broxton, was that mux
>>>> control was moved to ASL. I'm not sure why folks didn't update CHT (or
>>>> other devices') BIOS though.
>>>
>>> I don't think expecting things to get "fixed" by firmware updates, esp.
>>> firmware updates adding whole new functionality is going to happen, that
>>> just is not realistic (esp. with cheap devices like these). And even if
>>> it were fixed in firmware users are really bad add updating there firmware.
>>>
>>>> Baolu, any comments to this series?
>>>>
>>>> Personally, I'm unwilling to take this (or the other 2-patch dwc3 series
>>>> adding IDA) because there will only be a single user.
>>>
>>> Only a single user ? You mean only a single SoC will use this I guess ?
>>>
>>> But there are many many devices with this SoC and lots of people are
>>> trying to run "plain" Linux on these.
>>>
>>> I can see how you don't want this as a phy driver though, I would
>>> be happy to drop the phy-binding bits (they're not really used
>>> anyways) and drop this under drivers/misc adding myself to MAINTAINERS
>>> for it, would that be an acceptable solution ?
>>>
>>> About the "other 2-patch dwc3 series", I'm fine with you not taking
>>> the IDA patch, but the first patch is unrelated to IDA, it is a pure
>>> bug-fix and really should be upstreamed.
>>>
>>> Matthias, assuming Felipe is ok with putting this in drivers/misc
>>> (minus the phy bindings), are you ok with the xhci blurb which
>>> registers the platform-device for the "misc" driver to bind to?
>>
>> Not the ideal solution, but creating a device would sound better than 
>> carrying it
>> in xhci driver.

[PATCH 1/1] usb: xhci: hold lock over xhci_abort_cmd_ring()

2016-12-22 Thread Lu Baolu
In command timer function, xhci_handle_command_timeout(), xhci->lock
is unlocked before call into xhci_abort_cmd_ring(). This might cause
race between the timer function and the event handler.

The xhci_abort_cmd_ring() function sets the CMD_RING_ABORT bit in the
command register and polling it until the setting takes effect. A stop
command ring event might be handled between writing the abort bit and
polling for it. The event handler will restart the command ring, which
causes the failure of polling, and we ever believed that we failed to
stop it.

As a bonus, this also fixes some issues of calling functions without
locking in xhci_handle_command_timeout().

Cc:  # 3.7+
Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 797137e..0f99078 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1283,29 +1283,34 @@ void xhci_handle_command_timeout(unsigned long data)
hw_ring_state = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
if ((xhci->cmd_ring_state & CMD_RING_STATE_RUNNING) &&
(hw_ring_state & CMD_RING_RUNNING))  {
-   spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "Command timeout\n");
ret = xhci_abort_cmd_ring(xhci);
if (unlikely(ret == -ESHUTDOWN)) {
xhci_err(xhci, "Abort command ring failed\n");
xhci_cleanup_command_queue(xhci);
+   spin_unlock_irqrestore(&xhci->lock, flags);
usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
xhci_dbg(xhci, "xHCI host controller is dead.\n");
+
+   return;
}
-   return;
+
+   goto time_out_completed;
}
 
/* command ring failed to restart, or host removed. Bail out */
if (second_timeout || xhci->xhc_state & XHCI_STATE_REMOVING) {
-   spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg(xhci, "command timed out twice, ring start fail?\n");
xhci_cleanup_command_queue(xhci);
-   return;
+
+   goto time_out_completed;
}
 
/* command timeout on stopped ring, ring can't be aborted */
xhci_dbg(xhci, "Command timeout on stopped ring\n");
xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
+
+time_out_completed:
spin_unlock_irqrestore(&xhci->lock, flags);
return;
 }
-- 
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 0/1] usb: xhci: hold lock over xhci_abort_cmd_ring()

2016-12-22 Thread Lu Baolu
Hi Mathias,

This is a follow-up patch for below comment

"fix the lock to cover abort+CRR check, and send it to usb-linus +stable"

in below discussion thread.

https://lkml.org/lkml/2016/12/21/186

It's based on v4.9.

Best regards,
Lu Baolu

Lu Baolu (1):
  usb: xhci: hold lock over xhci_abort_cmd_ring()

 drivers/usb/host/xhci-ring.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/1] xhci: Fix race related to abort operation

2016-12-22 Thread Lu Baolu
Hi Mathias,

This is a follow-up patch for below comment

"rebase OGAWA Hirofumi's changes on top of that, and send to usb-linus only"

in below discussion thread.

https://lkml.org/lkml/2016/12/21/186

I rebased the patch and added unlock-before and lock-after xhci->lock during
waiting for the command stopped event.

It sits at the same place in your timeout_race_fixes branch.

(git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git 
timeout_race_fixes)

Best regards,
Lu Baolu

OGAWA Hirofumi (1):
  xhci: Fix race related to abort operation

 drivers/usb/host/xhci-mem.c  |   1 +
 drivers/usb/host/xhci-ring.c | 171 ++-
 drivers/usb/host/xhci.h  |   1 +
 3 files changed, 91 insertions(+), 82 deletions(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/1] xhci: Fix race related to abort operation

2016-12-22 Thread Lu Baolu
From: OGAWA Hirofumi 

Current abort operation has race.

xhci_handle_command_timeout()
  xhci_abort_cmd_ring()
xhci_write_64(CMD_RING_ABORT)
xhci_handshake(5s)
  do {
check CMD_RING_RUNNING
udelay(1)
 ...
 COMP_CMD_ABORT event
 COMP_CMD_STOP event
 xhci_handle_stopped_cmd_ring()
   restart cmd_ring
   CMD_RING_RUNNING become 1 again
  } while ()
  return -ETIMEDOUT
xhci_write_64(CMD_RING_ABORT)
/* can abort random command */

To do abort operation correctly, we have to wait both of COMP_CMD_STOP
event and negation of CMD_RING_RUNNING.

But like above, while timeout handler is waiting negation of
CMD_RING_RUNNING, event handler can restart cmd_ring. So timeout
handler never be notice negation of CMD_RING_RUNNING, and retry of
CMD_RING_ABORT can abort random command (BTW, I guess retry of
CMD_RING_ABORT was workaround of this race).

To fix this race, this moves xhci_handle_stopped_cmd_ring() to
xhci_abort_cmd_ring().  And timeout handler waits COMP_CMD_STOP event.

At this point, timeout handler is owner of cmd_ring, and safely
restart cmd_ring by using xhci_handle_stopped_cmd_ring().

[FWIW, as bonus, this way would be easily extend to add CMD_RING_PAUSE
operation]

[baolu: release xhci->lock before wait and apply it back again after
wait. This is the reason my signed-off-by is added.]

CC: 
Signed-off-by: OGAWA Hirofumi 
Signed-off-by: Lu Baolu 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mem.c  |   1 +
 drivers/usb/host/xhci-ring.c | 171 ++-
 drivers/usb/host/xhci.h  |   1 +
 3 files changed, 91 insertions(+), 82 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 536f572..70c9204 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2379,6 +2379,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
 
/* init command timeout work */
INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);
+   init_completion(&xhci->cmd_ring_stop_completion);
 
page_size = readl(&xhci->op_regs->page_size);
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 63af013..d5fde9a 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -265,23 +265,71 @@ static bool xhci_mod_cmd_timer(struct xhci_hcd *xhci, 
unsigned long delay)
return mod_delayed_work(system_wq, &xhci->cmd_timer, delay);
 }
 
-static int xhci_abort_cmd_ring(struct xhci_hcd *xhci)
+static struct xhci_command *xhci_next_queued_cmd(struct xhci_hcd *xhci)
 {
+   return list_first_entry_or_null(&xhci->cmd_list, struct xhci_command,
+   cmd_list);
+}
+
+/*
+ * Turn all commands on command ring with status set to "aborted" to no-op 
trbs.
+ * If there are other commands waiting then restart the ring and kick the 
timer.
+ * This must be called with command ring stopped and xhci->lock held.
+ */
+static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
+struct xhci_command *cur_cmd)
+{
+   struct xhci_command *i_cmd;
+   u32 cycle_state;
+
+   /* Turn all aborted commands in list to no-ops, then restart */
+   list_for_each_entry(i_cmd, &xhci->cmd_list, cmd_list) {
+
+   if (i_cmd->status != COMP_CMD_ABORT)
+   continue;
+
+   i_cmd->status = COMP_CMD_STOP;
+
+   xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
+i_cmd->command_trb);
+   /* get cycle state from the original cmd trb */
+   cycle_state = le32_to_cpu(
+   i_cmd->command_trb->generic.field[3]) & TRB_CYCLE;
+   /* modify the command trb to no-op command */
+   i_cmd->command_trb->generic.field[0] = 0;
+   i_cmd->command_trb->generic.field[1] = 0;
+   i_cmd->command_trb->generic.field[2] = 0;
+   i_cmd->command_trb->generic.field[3] = cpu_to_le32(
+   TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
+
+   /*
+* caller waiting for completion is called when command
+*  completion event is received for these no-op commands
+*/
+   }
+
+   xhci->cmd_ring_state = CMD_RING_STATE_RUNNING;
+
+   /* ring command ring doorbell to restart the command ring */
+   if ((xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) &&

[PATCH 4/4] usb: xhci: warn on command timeout in stopped command ring

2016-12-22 Thread Lu Baolu
If xhci host fails to response to a command, the command
watchdog timer will be fired. The callback function will
abort and clear current command and restart the command
execution. If driver fails to restart command execution,
it will assume there is a larger problem in host and
report the situation to the upper layer. In rare cases,
if the driver sees a command timeout in a stopped command
ring, driver should let the user know it.

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6a23c37..16baefc 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1308,8 +1308,12 @@ void xhci_handle_command_timeout(struct work_struct 
*work)
goto time_out_completed;
}
 
-   /* command timeout on stopped ring, ring can't be aborted */
-   xhci_dbg(xhci, "Command timeout on stopped ring\n");
+   /*
+* We should never reach here until a command times out on a stopped
+* ring and xhci driver has no idea about the reason why the command
+* ring was stopped.
+*/
+   xhci_warn(xhci, "WARN command timeout on stopped ring\n");
xhci_handle_stopped_cmd_ring(xhci, xhci->current_cmd);
 
 time_out_completed:
-- 
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 0/4] refactor command timeout handling

2016-12-22 Thread Lu Baolu
Hi Mathias,

This patch series is for command timeout refactoring.

Patches
  usb: xhci: remove unnecessary second abort try
  usb: xhci: remove CRR polling in xhci_abort_cmd_ring()
are follow-ups of your comments of
  "remove unnecessary second abort try as a separate patch, send to usb-next"
and
   "remove polling for the Command ring running (CRR), waiting for completion
   is enough, if completion times out then we can check CRR. for usb-next" 
in below discussion thread.
   https://lkml.org/lkml/2016/12/21/186

Patches
  usb: xhci: add XHCI_MISS_CA_EVENT quirk bit
  usb: xhci: warn on command timeout in stopped command ring
are my proposals.

They base on the top of your timeout_race_fixes branch.

(git://git.kernel.org/pub/scm/linux/kernel/git/mnyman/xhci.git 
timeout_race_fixes)

Lu Baolu (4):
  usb: xhci: remove unnecessary second abort try
  usb: xhci: remove CRR polling in xhci_abort_cmd_ring()
  usb: xhci: add XHCI_MISS_CA_EVENT quirk bit
  usb: xhci: warn on command timeout in stopped command ring

 drivers/usb/host/xhci-ring.c | 64 ++--
 drivers/usb/host/xhci.h  |  6 +
 2 files changed, 32 insertions(+), 38 deletions(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] usb: xhci: remove unnecessary second abort try

2016-12-22 Thread Lu Baolu
The second try was a workaround for (what we thought was) command
ring failing to stop in the first place. But this turns out to be
due to the race that we have fixed(see "xhci: Fix race related to
abort operation"). With that fix, it is time to remove the second
try.

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 18 +-
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 2f4ea21..e3bcf6d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -343,19 +343,11 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, 
unsigned long *flags)
ret = xhci_handshake(&xhci->op_regs->cmd_ring,
CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
if (ret < 0) {
-   /* we are about to kill xhci, give it one more chance */
-   xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
- &xhci->op_regs->cmd_ring);
-   udelay(1000);
-   ret = xhci_handshake(&xhci->op_regs->cmd_ring,
-CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
-   if (ret < 0) {
-   xhci_err(xhci, "Stopped the command ring failed, "
-"maybe the host is dead\n");
-   xhci->xhc_state |= XHCI_STATE_DYING;
-   xhci_halt(xhci);
-   return -ESHUTDOWN;
-   }
+   xhci_err(xhci,
+"Stop command ring failed, maybe the host is dead\n");
+   xhci->xhc_state |= XHCI_STATE_DYING;
+   xhci_halt(xhci);
+   return -ESHUTDOWN;
}
/*
 * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
-- 
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 2/4] usb: xhci: remove CRR polling in xhci_abort_cmd_ring()

2016-12-22 Thread Lu Baolu
xHCI driver aborts the command ring by setting CA (Command
Abort) bit in the command register. With this setting, host
should abort all command executions and generate a command
completion event with the completion code set to command
ring stopped. Software should time the completion of command
abort by checking the CRR (Command Ring Running) and waiting
for the command ring stopped event.

Current xhci_abort_cmd_ring() does this in the following
way: setting CA bit; busy polling CRR bit until it negates;
sleep and wait for the command ring stopped event. This is
not an efficient way since cpu cycles are wasted on polling
registers. This patch removes polling for CRR (Command Ring
Running). Wait for completion, and check CRR if completion
times out is enough.

Suggested-by: Mathias Nyman 
Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 49 ++--
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index e3bcf6d..5935dce 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -323,7 +323,6 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, 
unsigned long *flags)
 {
unsigned long timeleft;
u64 temp_64;
-   int ret;
 
xhci_dbg(xhci, "Abort command ring\n");
 
@@ -333,34 +332,34 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, 
unsigned long *flags)
xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
&xhci->op_regs->cmd_ring);
 
-   /* Section 4.6.1.2 of xHCI 1.0 spec says software should
-* time the completion od all xHCI commands, including
-* the Command Abort operation. If software doesn't see
-* CRR negated in a timely manner (e.g. longer than 5
-* seconds), then it should assume that the there are
-* larger problems with the xHC and assert HCRST.
-*/
-   ret = xhci_handshake(&xhci->op_regs->cmd_ring,
-   CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
-   if (ret < 0) {
-   xhci_err(xhci,
-"Stop command ring failed, maybe the host is dead\n");
-   xhci->xhc_state |= XHCI_STATE_DYING;
-   xhci_halt(xhci);
-   return -ESHUTDOWN;
-   }
-   /*
-* Writing the CMD_RING_ABORT bit should cause a cmd completion event,
-* however on some host hw the CMD_RING_RUNNING bit is correctly cleared
-* but the completion event in never sent. Wait 2 secs (arbitrary
-* number) to handle those cases after negation of CMD_RING_RUNNING.
-*/
spin_unlock_irqrestore(&xhci->lock, *flags);
timeleft = wait_for_completion_timeout(&xhci->cmd_ring_stop_completion,
-  2 * HZ);
+  XHCI_CMD_DEFAULT_TIMEOUT);
spin_lock_irqsave(&xhci->lock, *flags);
if (!timeleft) {
-   xhci_dbg(xhci, "No stop event for abort, ring start fail?\n");
+   /* Section 4.6.1.2 of xHCI 1.0 spec says software should
+* time the completion of all xHCI commands, including
+* the Command Abort operation. If software doesn't see
+* CRR negated in a timely manner (e.g. longer than 5
+* seconds), then it should assume that the there are
+* larger problems with the xHC and assert HCRST.
+*/
+   temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+   if (temp_64 & CMD_RING_RUNNING) {
+   xhci_err(xhci,
+"Stop command ring failed, maybe the host is 
dead\n");
+   xhci->xhc_state |= XHCI_STATE_DYING;
+   xhci_halt(xhci);
+   return -ESHUTDOWN;
+   }
+
+   /*
+* Writing the CMD_RING_ABORT bit should cause a cmd
+* completion event, however on some hosts the bit is
+* correctly cleared but the completion event is never
+* sent.
+*/
+   xhci_warn(xhci, "No stop event for abort, ring start fail?\n");
xhci_cleanup_command_queue(xhci);
} else {
xhci_handle_stopped_cmd_ring(xhci, xhci_next_queued_cmd(xhci));
-- 
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 3/4] usb: xhci: add XHCI_MISS_CA_EVENT quirk bit

2016-12-22 Thread Lu Baolu
Writing the CMD_RING_ABORT bit in xhci command register should
cause a command completion event with the command completion
code set to command ring stopped. However on some hosts, the
CMD_RING_RUNNING bit is correctly cleared but the completion
event is never sent.

Current xhci driver treats the behavior of "CMD_RING_RUNNING
bit is correctly cleared but the completion event is missed"
as a correct behavior for all hosts. This is different from
that defined in xhci spec. Refer to 4.6.1.2 in xhci spec.

This patch introduces a quirk bit for those quirky hardwares.
For normal hosts, if the command completion for abort command
ring misses, we shall assume that there are larger problems
with the host and assert HCRST.

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 17 +
 drivers/usb/host/xhci.h  |  6 ++
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 5935dce..6a23c37 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -345,25 +345,18 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, 
unsigned long *flags)
 * larger problems with the xHC and assert HCRST.
 */
temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
-   if (temp_64 & CMD_RING_RUNNING) {
+   if ((temp_64 & CMD_RING_RUNNING) ||
+   !(xhci->quirks & XHCI_MISS_CA_EVENT)) {
xhci_err(xhci,
 "Stop command ring failed, maybe the host is 
dead\n");
xhci->xhc_state |= XHCI_STATE_DYING;
xhci_halt(xhci);
return -ESHUTDOWN;
}
-
-   /*
-* Writing the CMD_RING_ABORT bit should cause a cmd
-* completion event, however on some hosts the bit is
-* correctly cleared but the completion event is never
-* sent.
-*/
-   xhci_warn(xhci, "No stop event for abort, ring start fail?\n");
-   xhci_cleanup_command_queue(xhci);
-   } else {
-   xhci_handle_stopped_cmd_ring(xhci, xhci_next_queued_cmd(xhci));
}
+
+   xhci_handle_stopped_cmd_ring(xhci, xhci_next_queued_cmd(xhci));
+
return 0;
 }
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 09fe63f..c550bf0 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1656,6 +1656,12 @@ struct xhci_hcd {
 #define XHCI_SSIC_PORT_UNUSED  (1 << 22)
 #define XHCI_NO_64BIT_SUPPORT  (1 << 23)
 #define XHCI_MISSING_CAS   (1 << 24)
+/*
+ * Writing the CMD_RING_ABORT bit should cause a cmd completion event,
+ * however on some host hw the CMD_RING_RUNNING bit is correctly cleared
+ * but the completion event is never sent.
+ */
+#define XHCI_MISS_CA_EVENT (1 << 25)
unsigned intnum_active_eps;
unsigned intlimit_active_eps;
/* There are two roothubs to keep track of bus suspend info for */
-- 
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: dwc3: gadget: Avoid race between dwc3 interrupt handler and irq thread handler

2016-12-26 Thread Lu Baolu
Hi,

On 12/26/2016 04:01 PM, Baolin Wang wrote:
> On some platfroms(like x86 platform), when one core is running the USB gadget
> irq thread handler by dwc3_thread_interrupt(), meanwhile another core also can
> respond other interrupts from dwc3 controller and modify the event buffer by
> dwc3_interrupt() function, that will cause getting the wrong event count in
> irq thread handler to make the USB function abnormal.
>
> We should add spin_lock/unlock() in dwc3_check_event_buf() to avoid this race.

Why not spin_lock_irq ones? This lock seems to be used in both
normal and interrupt threads. Or, I missed anything?

Best regards,
Lu Baolu

>
> Signed-off-by: Baolin Wang 
> ---
>  drivers/usb/dwc3/gadget.c |6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 6785595..1a1e1f4 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2894,10 +2894,13 @@ static irqreturn_t dwc3_check_event_buf(struct 
> dwc3_event_buffer *evt)
>   return IRQ_HANDLED;
>   }
>  
> + spin_lock(&dwc->lock);
>   count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
>   count &= DWC3_GEVNTCOUNT_MASK;
> - if (!count)
> + if (!count) {
> + spin_unlock(&dwc->lock);
>   return IRQ_NONE;
> + }
>  
>   evt->count = count;
>   evt->flags |= DWC3_EVENT_PENDING;
> @@ -2914,6 +2917,7 @@ static irqreturn_t dwc3_check_event_buf(struct 
> dwc3_event_buffer *evt)
>   memcpy(evt->cache, evt->buf, count - amount);
>  
>   dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
> + spin_unlock(&dwc->lock);
>  
>   return IRQ_WAKE_THREAD;
>  }

--
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: dwc3: gadget: Avoid race between dwc3 interrupt handler and irq thread handler

2016-12-26 Thread Lu Baolu
Hi,

On 12/27/2016 10:58 AM, Baolin Wang wrote:
> Hi,
>
> On 27 December 2016 at 10:39, Lu Baolu  wrote:
>> Hi,
>>
>> On 12/26/2016 04:01 PM, Baolin Wang wrote:
>>> On some platfroms(like x86 platform), when one core is running the USB 
>>> gadget
>>> irq thread handler by dwc3_thread_interrupt(), meanwhile another core also 
>>> can
>>> respond other interrupts from dwc3 controller and modify the event buffer by
>>> dwc3_interrupt() function, that will cause getting the wrong event count in
>>> irq thread handler to make the USB function abnormal.
>>>
>>> We should add spin_lock/unlock() in dwc3_check_event_buf() to avoid this 
>>> race.
>> Why not spin_lock_irq ones? This lock seems to be used in both
>> normal and interrupt threads. Or, I missed anything?
> I assumed there are no nested interrupts, when one core is running at
> interrupt context, then it can not respond any other interrupts, which
> means we don't need to disable local IRQ now, right?
>

Fair enough. Thanks.

Best regards,
Lu 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 06/37] usb: host: xhci: WARN on unexpected COMP_SUCCESS

2016-12-29 Thread Lu Baolu
Hi,

On 12/29/2016 07:00 PM, Felipe Balbi wrote:
> COMP_SUCCESS should only be asserted on a *true* sucessful transfer. Any
> other cases are bogus and we should aim to catch them. One easy way to
> get bug reports is to trigger a WARN_ONCE() on such cases.
>
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/host/xhci-ring.c | 28 +++-
>  1 file changed, 15 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index 17b878b53b46..772e07e2ef16 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -1934,6 +1934,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, 
> struct xhci_td *td,
>  {
>   struct xhci_virt_device *xdev;
>   struct xhci_ring *ep_ring;
> + struct device *dev;
>   unsigned int slot_id;
>   int ep_index;
>   struct xhci_ep_ctx *ep_ctx;
> @@ -1950,15 +1951,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, 
> struct xhci_td *td,
>   trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
>   requested = td->urb->transfer_buffer_length;
>   remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
> + dev = xhci_to_hcd(xhci)->self.controller;
>  
>   switch (trb_comp_code) {
>   case COMP_SUCCESS:
> - if (trb_type != TRB_STATUS) {
> - xhci_warn(xhci, "WARN: Success on ctrl %s TRB without 
> IOC set?\n",
> - (trb_type == TRB_DATA) ? "data" : 
> "setup");
> - *status = -ESHUTDOWN;
> - break;
> - }
> + dev_WARN_ONCE(dev, trb_type != TRB_STATUS,
> + "ep%d%s: unexpected success! TRB Type %d\n",
> + usb_endpoint_num(&td->urb->ep->desc),
> + usb_endpoint_dir_in(&td->urb->ep->desc) ?
> + "in" : "out", trb_type);
>   *status = 0;

Still setting status to 0 even "trb_type != TRB_STATUS"?

Previous code set it to -ESHUTDOWN.

>   break;
>   case COMP_SHORT_PACKET:
> @@ -2150,6 +2151,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
> struct xhci_td *td,
>   struct xhci_virt_ep *ep, int *status)
>  {
>   struct xhci_ring *ep_ring;
> + struct device *dev;
>   u32 trb_comp_code;
>   u32 remaining, requested, ep_trb_len;
>  
> @@ -2158,16 +2160,16 @@ static int process_bulk_intr_td(struct xhci_hcd 
> *xhci, struct xhci_td *td,
>   remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
>   ep_trb_len = TRB_LEN(le32_to_cpu(ep_trb->generic.field[2]));
>   requested = td->urb->transfer_buffer_length;
> + dev = xhci_to_hcd(xhci)->self.controller;
>  
>   switch (trb_comp_code) {
>   case COMP_SUCCESS:
> - /* handle success with untransferred data as short packet */
> - if (ep_trb != td->last_trb || remaining) {
> - xhci_warn(xhci, "WARN Successful completion on short 
> TX\n");
> - xhci_dbg(xhci, "ep %#x - asked for %d bytes, %d bytes 
> untransferred\n",
> -  td->urb->ep->desc.bEndpointAddress,
> -  requested, remaining);
> - }
> + dev_WARN_ONCE(dev, (ep_trb != td->last_trb) || remaining,
> + "ep%d%s: unexpected success! TRB %p/%p size 
> %d/%d\n",
> + usb_endpoint_num(&td->urb->ep->desc),
> + usb_endpoint_dir_in(&td->urb->ep->desc) ?
> + "in" : "out", ep_trb, td->last_trb, remaining,
> + requested);
>   *status = 0;

The same consideration here.

Best regards,
Lu Baolu

>   break;
>   case COMP_SHORT_PACKET:

--
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 09/37] usb: host: xhci: clear only STS_EINT

2016-12-29 Thread Lu Baolu
Hi,

On 12/29/2016 07:00 PM, Felipe Balbi wrote:
> Many other bits in USBSTS register are "clear-by-writing-1". Let's make
> sure that we clear *only* STS_EINT and not any of the other bits as they
> might be needed later.

Bit 13~31 in status register is for RsvdP (Reserved and Preserved).
This means these bits are reserved for future RW implementations.
Software shall preserve the value read for writes.

How about below helper?

static inline void clear_status_rw1c_bit(u32 bit)
{
u32 status;

status = readl(&xhci->op_regs->status);
/* preserve RsvP bits and clear RO/RW1C/RsvZ bits */
status &= ~0x1fff;
status |= bit;

writel(status, &xhci->op_regs->status);
}

Look into the code, I still find other two places where RW1C bits
are not cleared correctly.

In xhci_stop() and xhci_resume(), the RW1C bit is treated as a RW type.

 724 temp = readl(&xhci->op_regs->status);
 725 writel(temp & ~STS_EINT, &xhci->op_regs->status);

I will correct these in a separated patch and cc stable as well.

Best regards,
Lu Baolu

>
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/host/xhci-ring.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index b4ec80d18078..116b4a0dadbb 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -2630,8 +2630,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
>* so we can receive interrupts from other MSI-X interrupters.
>* Write 1 to clear the interrupt status.
>*/
> - status |= STS_EINT;
> - writel(status, &xhci->op_regs->status);
> + writel(STS_EINT, &xhci->op_regs->status);
>   /* FIXME when MSI-X is supported and there are multiple vectors */
>   /* Clear the MSI-X event interrupt status */
>  

--
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 24/37] usb: host: xhci: use trb_to_noop() from xhci_handle_stopped_cmd_ring()

2016-12-29 Thread Lu Baolu
Hi,

On 12/29/2016 07:00 PM, Felipe Balbi wrote:
> instead of open coding how to convert a TRB to no-op, let's use our
> newly introduced helper.
>
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/host/xhci-ring.c | 33 +++--
>  1 file changed, 23 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
> index f369d97f663d..0b8f728d6e77 100644
> --- a/drivers/usb/host/xhci-ring.c
> +++ b/drivers/usb/host/xhci-ring.c
> @@ -542,6 +542,27 @@ static void trb_to_noop(union xhci_trb *trb)
>   trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
>   trb->generic.field[3] |= cpu_to_le32(TRB_TYPE(TRB_TR_NOOP));
>   break;
> + case TRB_ENABLE_SLOT:
> + case TRB_DISABLE_SLOT:
> + case TRB_ADDR_DEV:
> + case TRB_CONFIG_EP:
> + case TRB_EVAL_CONTEXT:
> + case TRB_RESET_EP:
> + case TRB_STOP_RING:
> + case TRB_SET_DEQ:
> + case TRB_RESET_DEV:
> + case TRB_FORCE_EVENT:
> + case TRB_NEG_BANDWIDTH:
> + case TRB_SET_LT:
> + case TRB_GET_BW:
> + case TRB_FORCE_HEADER:

How about merging

+   case TRB_ENABLE_SLOT:
+   case TRB_DISABLE_SLOT:
+   case TRB_ADDR_DEV:
+   case TRB_CONFIG_EP:
+   case TRB_EVAL_CONTEXT:
+   case TRB_RESET_EP:
+   case TRB_STOP_RING:
+   case TRB_SET_DEQ:
+   case TRB_RESET_DEV:
+   case TRB_FORCE_EVENT:
+   case TRB_NEG_BANDWIDTH:
+   case TRB_SET_LT:
+   case TRB_GET_BW:
+   case TRB_FORCE_HEADER:

into


+case TRB_ENABLE_SLOT ... TRB_FORCE_HEADER:

?


> + trb->generic.field[0] = 0;
> + trb->generic.field[1] = 0;
> + trb->generic.field[2] = 0;
> + /* Preserve only the cycle bit of this TRB */
> + trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
> + trb->generic.field[3] = cpu_to_le32(TRB_TYPE(TRB_CMD_NOOP));
> + break;
>   default:
>   /* nothing */

Need a warning?

Best regards,
Lu Baolu

>   break;
> @@ -1229,7 +1250,6 @@ static void xhci_handle_stopped_cmd_ring(struct 
> xhci_hcd *xhci,
>struct xhci_command *cur_cmd)
>  {
>   struct xhci_command *cmd;
> - u32 cycle_state;
>  
>   /* Turn all aborted commands in list to no-ops, then restart */
>   list_for_each_entry(cmd, &xhci->cmd_list,
> @@ -1242,15 +1262,8 @@ static void xhci_handle_stopped_cmd_ring(struct 
> xhci_hcd *xhci,
>  
>   xhci_dbg(xhci, "Turn aborted command %p to no-op\n",
>cmd->command_trb);
> - /* get cycle state from the original cmd trb */
> - cycle_state = le32_to_cpu(
> - cmd->command_trb->generic.field[3]) & TRB_CYCLE;
> - /* modify the command trb to no-op command */
> - cmd->command_trb->generic.field[0] = 0;
> - cmd->command_trb->generic.field[1] = 0;
> - cmd->command_trb->generic.field[2] = 0;
> - cmd->command_trb->generic.field[3] = cpu_to_le32(
> - TRB_TYPE(TRB_CMD_NOOP) | cycle_state);
> +
> + trb_to_noop(cmd->command_trb);
>  
>   /*
>* caller waiting for completion is called when command

--
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 30/37] usb: host: xhci: make a generic TRB tracer

2016-12-29 Thread Lu Baolu
 (unsigned long long) __entry->dma, __entry->va,
> - __entry->status, __entry->flags
> + TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
> + xhci_decode_trb(__entry->field0, __entry->field1,
> + __entry->field2, __entry->field3)
>   )
>  );
>  
> -DEFINE_EVENT(xhci_log_event, xhci_cmd_completion,
> - TP_PROTO(void *trb_va, struct xhci_generic_trb *ev),
> - TP_ARGS(trb_va, ev)
> +DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
> + TP_ARGS(ring, trb)
> +);
> +
> +DEFINE_EVENT(xhci_log_trb, xhci_handle_command,
> +     TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
> + TP_ARGS(ring, trb)
> +);
> +
> +DEFINE_EVENT(xhci_log_trb, xhci_handle_transfer,
> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
> + TP_ARGS(ring, trb)
> +);
> +
> +DEFINE_EVENT(xhci_log_trb, xhci_queue_trb,
> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
> + TP_ARGS(ring, trb)
>  );

How about add xhci_dequeue_trb for those dequeued from event ring?

It should be helpful, if we can track the link trb as well.

Best regards,
Lu Baolu

>  
>  #endif /* __XHCI_TRACE_H */
> diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
> index c7e95a6e39a7..eb72ad4c0d72 100644
> --- a/drivers/usb/host/xhci.h
> +++ b/drivers/usb/host/xhci.h
> @@ -1200,6 +1200,27 @@ struct xhci_event_cmd {
>  
>  /* Address device - disable SetAddress */
>  #define TRB_BSR  (1<<9)
> +
> +/* Configure Endpoint - Deconfigure */
> +#define TRB_DC   (1<<9)
> +
> +/* Stop Ring - Transfer State Preserve */
> +#define TRB_TSP  (1<<9)
> +
> +/* Force Event */
> +#define TRB_TO_VF_INTR_TARGET(p) (((p) & (0x3ff << 22)) >> 22)
> +#define TRB_TO_VF_ID(p)  (((p) & (0xff << 16)) >> 16)
> +
> +/* Set Latency Tolerance Value */
> +#define TRB_TO_BELT(p)   (((p) & (0xfff << 16)) >> 16)
> +
> +/* Get Port Bandwidth */
> +#define TRB_TO_DEV_SPEED(p)  (((p) & (0xf << 16)) >> 16)
> +
> +/* Force Header */
> +#define TRB_TO_PACKET_TYPE(p)((p) & 0x1f)
> +#define TRB_TO_ROOTHUB_PORT(p)   (((p) & (0xff << 24)) >> 24)
> +
>  enum xhci_setup_dev {
>   SETUP_CONTEXT_ONLY,
>   SETUP_CONTEXT_ADDRESS,
> @@ -1223,16 +1244,21 @@ enum xhci_setup_dev {
>  #define STREAM_ID_FOR_TRB(p) p)) & 0x) << 16)
>  #define SCT_FOR_TRB(p)   (((p) << 1) & 0x7)
>  
> +/* Link TRB specific fields */
> +#define TRB_TC   (1<<1)
>  
>  /* Port Status Change Event TRB fields */
>  /* Port ID - bits 31:24 */
>  #define GET_PORT_ID(p)   (((p) & (0xff << 24)) >> 24)
>  
> +#define EVENT_DATA   (1 << 2)
> +
>  /* Normal TRB fields */
>  /* transfer_len bitmasks - bits 0:16 */
>  #define  TRB_LEN(p)  ((p) & 0x1)
>  /* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */
>  #define TRB_TD_SIZE(p)  (min((p), (u32)31) << 17)
> +#define GET_TD_SIZE(p)   (((p) & 0x3e) >> 17)
>  /* xhci 1.1 uses the TD_SIZE field for TBC if Extended TBC is enabled (ETE) 
> */
>  #define TRB_TD_SIZE_TBC(p)  (min((p), (u32)31) << 17)
>  /* Interrupter Target - which MSI-X vector to target the completion event at 
> */
> @@ -1360,6 +1386,80 @@ union xhci_trb {
>  /* Get NEC firmware revision. */
>  #define  TRB_NEC_GET_FW  49
>  
> +static inline const char *xhci_trb_type_string(u8 type)
> +{
> + switch (type) {
> + case TRB_NORMAL:
> + return "Normal";
> + case TRB_SETUP:
> + return "Setup Stage";
> + case TRB_DATA:
> + return "Data Stage";
> + case TRB_STATUS:
> + return "Status Stage";
> + case TRB_ISOC:
> + return "Isoch";
> + case TRB_LINK:
> + return "Link";
> + case TRB_EVENT_DATA:
> + return "Event Data";
> + case TRB_TR_NOOP:
> + return "No-Op";
> + case TRB_ENABLE_SLOT:
> + return "Enable Slot Command";
> + case TRB_DISABLE_SLOT:
> + return "Disable Slot Command";
> + case TRB_ADDR_DEV:
> +  

[PATCH 1/1] usb: xhci: clear EINT bit in status correctly

2016-12-29 Thread Lu Baolu
EINT(Event Interrupt) is a write-1-to-clear type of bit in xhci
status register. It should be cleared by writing a 1. Writing 0
to this bit has no effect.

Xhci driver tries to clear this bit by writing 0 to it. This is
not the right way to go. This patch corrects this by reading the
register first, then clearing all RO/RW1C/RsvZ bits and setting
the clearing bit, and writing back the new value at last.

Xhci spec requires that software that uses EINT shall clear it
prior to clearing any IP flags in section 5.4.2. This is the
reason why this patch is CC'ed stable as well.

Cc:  # v3.14+
CC: Felipe Balbi 
Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1cd5641..18ea6b8 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -721,7 +721,7 @@ void xhci_stop(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Disabling event ring interrupts");
temp = readl(&xhci->op_regs->status);
-   writel(temp & ~STS_EINT, &xhci->op_regs->status);
+   writel(temp & ~0x1fff | STS_EINT, &xhci->op_regs->status);
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
xhci_print_ir_set(xhci, 0);
@@ -1054,7 +1054,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 
xhci_dbg(xhci, "// Disabling event ring interrupts\n");
temp = readl(&xhci->op_regs->status);
-   writel(temp & ~STS_EINT, &xhci->op_regs->status);
+   writel(temp & ~0x1fff | STS_EINT, &xhci->op_regs->status);
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
xhci_print_ir_set(xhci, 0);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 09/37] usb: host: xhci: clear only STS_EINT

2016-12-31 Thread Lu Baolu
Hi,

On 12/30/2016 03:52 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>> On 12/29/2016 07:00 PM, Felipe Balbi wrote:
>>> Many other bits in USBSTS register are "clear-by-writing-1". Let's make
>>> sure that we clear *only* STS_EINT and not any of the other bits as they
>>> might be needed later.
>> Bit 13~31 in status register is for RsvdP (Reserved and Preserved).
> totally missed the "Preserved" part. Thanks
>
>> This means these bits are reserved for future RW implementations.
>> Software shall preserve the value read for writes.
>>
>> How about below helper?
>>
>> static inline void clear_status_rw1c_bit(u32 bit)
>> {
>> u32 status;
>>
>> status = readl(&xhci->op_regs->status);
>> /* preserve RsvP bits and clear RO/RW1C/RsvZ bits */
>> status &= ~0x1fff;
>> status |= bit;
>>
>> writel(status, &xhci->op_regs->status);
>> }
> not sure, I have no problems with it, but it's for mathias to decide. If
> anything, it should be prefixed by xhci_ so it's easier to use ftrace.
>
>> Look into the code, I still find other two places where RW1C bits
>> are not cleared correctly.
>>
>> In xhci_stop() and xhci_resume(), the RW1C bit is treated as a RW type.
>>
>>  724 temp = readl(&xhci->op_regs->status);
>>  725 writel(temp & ~STS_EINT, &xhci->op_regs->status);
>>
>> I will correct these in a separated patch and cc stable as well.
> That's cool. Then I can drop this patch from my series.

You don't need to drop this patch from your series. My patch
didn't include your change.


Best regards,
Lu 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 24/37] usb: host: xhci: use trb_to_noop() from xhci_handle_stopped_cmd_ring()

2016-12-31 Thread Lu Baolu
Hi,

On 12/30/2016 03:54 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>> On 12/29/2016 07:00 PM, Felipe Balbi wrote:
>>> instead of open coding how to convert a TRB to no-op, let's use our
>>> newly introduced helper.
>>>
>>> Signed-off-by: Felipe Balbi 
>>> ---
>>>  drivers/usb/host/xhci-ring.c | 33 +++--
>>>  1 file changed, 23 insertions(+), 10 deletions(-)
>>>
>>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>>> index f369d97f663d..0b8f728d6e77 100644
>>> --- a/drivers/usb/host/xhci-ring.c
>>> +++ b/drivers/usb/host/xhci-ring.c
>>> @@ -542,6 +542,27 @@ static void trb_to_noop(union xhci_trb *trb)
>>> trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
>>> trb->generic.field[3] |= cpu_to_le32(TRB_TYPE(TRB_TR_NOOP));
>>> break;
>>> +   case TRB_ENABLE_SLOT:
>>> +   case TRB_DISABLE_SLOT:
>>> +   case TRB_ADDR_DEV:
>>> +   case TRB_CONFIG_EP:
>>> +   case TRB_EVAL_CONTEXT:
>>> +   case TRB_RESET_EP:
>>> +   case TRB_STOP_RING:
>>> +   case TRB_SET_DEQ:
>>> +   case TRB_RESET_DEV:
>>> +   case TRB_FORCE_EVENT:
>>> +   case TRB_NEG_BANDWIDTH:
>>> +   case TRB_SET_LT:
>>> +   case TRB_GET_BW:
>>> +   case TRB_FORCE_HEADER:
>> How about merging
>>
>> +case TRB_ENABLE_SLOT:
>> +case TRB_DISABLE_SLOT:
>> +case TRB_ADDR_DEV:
>> +case TRB_CONFIG_EP:
>> +case TRB_EVAL_CONTEXT:
>> +case TRB_RESET_EP:
>> +case TRB_STOP_RING:
>> +case TRB_SET_DEQ:
>> +case TRB_RESET_DEV:
>> +case TRB_FORCE_EVENT:
>> +case TRB_NEG_BANDWIDTH:
>> +case TRB_SET_LT:
>> +case TRB_GET_BW:
>> +case TRB_FORCE_HEADER:
>>
>> into
>>
>>
>> +case TRB_ENABLE_SLOT ... TRB_FORCE_HEADER:
>>
>> ?
> to me it's pointless obfuscation :-)
>
>>  
>>
>>> +   trb->generic.field[0] = 0;
>>> +   trb->generic.field[1] = 0;
>>> +   trb->generic.field[2] = 0;
>>> +   /* Preserve only the cycle bit of this TRB */
>>> +   trb->generic.field[3] &= cpu_to_le32(TRB_CYCLE);
>>> +   trb->generic.field[3] = cpu_to_le32(TRB_TYPE(TRB_CMD_NOOP));
>>> +   break;
>>> default:
>>> /* nothing */
>> Need a warning?
> We have two users for this function and we know we won't pass unexistent
> TRB types to it. Maybe we can defer that warning until a problem shows up?
>

Fair enough.

Best regards,
Lu 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 30/37] usb: host: xhci: make a generic TRB tracer

2016-12-31 Thread Lu Baolu
Hi,

On 12/30/2016 03:47 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
>>> +   TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>> +   TP_ARGS(ring, trb)
>>> +);
>>> +
>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_command,
>>> +   TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>> +   TP_ARGS(ring, trb)
>>> +);
>>> +
>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_transfer,
>>> +   TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>> +   TP_ARGS(ring, trb)
>>> +);
>>> +
>>> +DEFINE_EVENT(xhci_log_trb, xhci_queue_trb,
>>> +   TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>> +   TP_ARGS(ring, trb)
>>>  );
>> How about add xhci_dequeue_trb for those dequeued from event ring?
> Sure, and where would the tracer be? When do we "dequeue" TRBs?

How about xhci_handle_event()? TRBs are dequeued from the event
ring there.

Best regards,
Lu Baolu

>
>> It should be helpful, if we can track the link trb as well.
> right
>

--
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 09/37] usb: host: xhci: clear only STS_EINT

2017-01-02 Thread Lu Baolu
Hi,

On 01/02/2017 04:47 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>> Hi,
>>
>> On 12/30/2016 03:52 PM, Felipe Balbi wrote:
>>> Hi,
>>>
>>> Lu Baolu  writes:
>>>> On 12/29/2016 07:00 PM, Felipe Balbi wrote:
>>>>> Many other bits in USBSTS register are "clear-by-writing-1". Let's make
>>>>> sure that we clear *only* STS_EINT and not any of the other bits as they
>>>>> might be needed later.
>>>> Bit 13~31 in status register is for RsvdP (Reserved and Preserved).
>>> totally missed the "Preserved" part. Thanks
>>>
>>>> This means these bits are reserved for future RW implementations.
>>>> Software shall preserve the value read for writes.
>>>>
>>>> How about below helper?
>>>>
>>>> static inline void clear_status_rw1c_bit(u32 bit)
>>>> {
>>>> u32 status;
>>>>
>>>> status = readl(&xhci->op_regs->status);
>>>> /* preserve RsvP bits and clear RO/RW1C/RsvZ bits */
>>>> status &= ~0x1fff;
>>>> status |= bit;
>>>>
>>>> writel(status, &xhci->op_regs->status);
>>>> }
>>> not sure, I have no problems with it, but it's for mathias to decide. If
>>> anything, it should be prefixed by xhci_ so it's easier to use ftrace.
>>>
>>>> Look into the code, I still find other two places where RW1C bits
>>>> are not cleared correctly.
>>>>
>>>> In xhci_stop() and xhci_resume(), the RW1C bit is treated as a RW type.
>>>>
>>>>  724 temp = readl(&xhci->op_regs->status);
>>>>  725 writel(temp & ~STS_EINT, &xhci->op_regs->status);
>>>>
>>>> I will correct these in a separated patch and cc stable as well.
>>> That's cool. Then I can drop this patch from my series.
>> You don't need to drop this patch from your series. My patch
>> didn't include your change.
> Fair enough, thanks :-) So this still needs an update nevertheless,
> right ?
>

Yes.

Best regards,
Lu 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 30/37] usb: host: xhci: make a generic TRB tracer

2017-01-02 Thread Lu Baolu
Hi,

On 01/02/2017 04:53 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>> Hi,
>>
>> On 12/30/2016 03:47 PM, Felipe Balbi wrote:
>>> Hi,
>>>
>>> Lu Baolu  writes:
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>> +);
>>>>> +
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_command,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>> +);
>>>>> +
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_transfer,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>> +);
>>>>> +
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_queue_trb,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>>  );
>>>> How about add xhci_dequeue_trb for those dequeued from event ring?
>>> Sure, and where would the tracer be? When do we "dequeue" TRBs?
>> How about xhci_handle_event()? TRBs are dequeued from the event
>> ring there.
> we already have a tracer there ;-)
>
> @@ -2475,6 +2480,8 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
> xhci->event_ring->cycle_state)
> return 0;
>  
> +   trace_xhci_handle_event(xhci->event_ring, &event->generic);
> +
> /*
>  * Barrier between reading the TRB_CYCLE (valid) flag above and any
>  * speculative reads of the event's flags/data below.
>
> We also have one for cmd completion:
>
> @@ -1346,6 +1346,9 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
>  
> cmd_dma = le64_to_cpu(event->cmd_trb);
> cmd_trb = xhci->cmd_ring->dequeue;
> +
> +   trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
> +
> cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
> cmd_trb);
> /*
>
> and another for transfer completion:
>
> @@ -2475,6 +2480,8 @@ static int xhci_handle_event(struct xhci_hcd *xhci)
> xhci->event_ring->cycle_state)
> return 0;
>  
> +   trace_xhci_handle_event(xhci->event_ring, &event->generic);
> +
> /*
>  * Barrier between reading the TRB_CYCLE (valid) flag above and any
>  * speculative reads of the event's flags/data below.
>
>
> I can't see what we're missing here.
>

Oh, yes. Thanks.

Best regards,
Lu 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 v2 1/1] usb: xhci: clear EINT bit in status correctly

2017-01-02 Thread Lu Baolu
EINT(Event Interrupt) is a write-1-to-clear type of bit in xhci
status register. It should be cleared by writing a 1. Writing 0
to this bit has no effect.

Xhci driver tries to clear this bit by writing 0 to it. This is
not the right way to go. This patch corrects this by reading the
register first, then clearing all RO/RW1C/RsvZ bits and setting
the clearing bit, and writing back the new value at last.

Xhci spec requires that software that uses EINT shall clear it
prior to clearing any IP flags in section 5.4.2. This is the
reason why this patch is CC'ed stable as well.

Cc:  # v3.14+
Cc: Felipe Balbi 
Signed-off-by: Lu Baolu 
---
Change log:
v1->v2:
 - Fixed a warning reported by 0-day kbuild robot.

 drivers/usb/host/xhci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1cd5641..bb08c6b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -721,7 +721,7 @@ void xhci_stop(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Disabling event ring interrupts");
temp = readl(&xhci->op_regs->status);
-   writel(temp & ~STS_EINT, &xhci->op_regs->status);
+   writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
xhci_print_ir_set(xhci, 0);
@@ -1054,7 +1054,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 
xhci_dbg(xhci, "// Disabling event ring interrupts\n");
temp = readl(&xhci->op_regs->status);
-   writel(temp & ~STS_EINT, &xhci->op_regs->status);
+   writel((temp & ~0x1fff) | STS_EINT, &xhci->op_regs->status);
temp = readl(&xhci->ir_set->irq_pending);
writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
xhci_print_ir_set(xhci, 0);
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/4] usb: xhci: use list_is_singular for cmd_list

2017-01-03 Thread Lu Baolu
Use list_is_singular() to check if cmd_list has only one entry.

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 95be9e8..40947e7 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1418,7 +1418,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
}
 
/* restart timer if this wasn't the last command */
-   if (cmd->cmd_list.next != &xhci->cmd_list) {
+   if (!list_is_singular(&xhci->cmd_list)) {
xhci->current_cmd = list_entry(cmd->cmd_list.next,
   struct xhci_command, cmd_list);
mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
@@ -3787,7 +3787,7 @@ static int queue_command(struct xhci_hcd *xhci, struct 
xhci_command *cmd,
list_add_tail(&cmd->cmd_list, &xhci->cmd_list);
 
/* if there are no other commands queued we start the timeout timer */
-   if (xhci->cmd_list.next == &cmd->cmd_list &&
+   if (list_is_singular(&xhci->cmd_list) &&
!timer_pending(&xhci->cmd_timer)) {
xhci->current_cmd = cmd;
mod_timer(&xhci->cmd_timer, jiffies + XHCI_CMD_DEFAULT_TIMEOUT);
-- 
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 4/4] usb: xhci: remove unnecessary return in xhci_pci_setup()

2017-01-03 Thread Lu Baolu
Remove the unnecessary return line in xhci_pci_setup().

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-pci.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index e96ae80..ace3f57 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -242,8 +242,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
 
/* Find any debug ports */
retval = xhci_pci_reinit(xhci, pdev);
-   if (!retval)
-   return retval;
 
return retval;
 }
-- 
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 0/4] several cleanup patches

2017-01-03 Thread Lu Baolu
Hi Mathias,

This series includes several tiny cleanup patches for xhci host
controller driver. These make the code slightly more readable.
There's no functional change.

Please consider it for your for-usb-next branch.

Best regards,
Lu Baolu

Lu Baolu (4):
  usb: xhci: remove unnecessary assignment
  usb: xhci: avoid unnecessary calculation
  usb: xhci: use list_is_singular for cmd_list
  usb: xhci: remove unnecessary return in xhci_pci_setup()

 drivers/usb/host/xhci-pci.c  |  2 --
 drivers/usb/host/xhci-ring.c | 26 --
 2 files changed, 12 insertions(+), 16 deletions(-)

-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/4] usb: xhci: remove unnecessary assignment

2017-01-03 Thread Lu Baolu
Drop an unnecessary assignment in prepare_transfer().

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index bdf6b13..3cc303f 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2826,8 +2826,6 @@ static int prepare_transfer(struct xhci_hcd *xhci,
td->start_seg = ep_ring->enq_seg;
td->first_trb = ep_ring->enqueue;
 
-   urb_priv->td[td_index] = td;
-
return 0;
 }
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/4] usb: xhci: avoid unnecessary calculation

2017-01-03 Thread Lu Baolu
No need to calculate remainder and length_field, if there is
no data phase of a control transfer.

Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci-ring.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3cc303f..95be9e8 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -3219,7 +3219,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
struct usb_ctrlrequest *setup;
struct xhci_generic_trb *start_trb;
int start_cycle;
-   u32 field, length_field, remainder;
+   u32 field;
struct urb_priv *urb_priv;
struct xhci_td *td;
 
@@ -3292,16 +3292,16 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t 
mem_flags,
else
field = TRB_TYPE(TRB_DATA);
 
-   remainder = xhci_td_remainder(xhci, 0,
-  urb->transfer_buffer_length,
-  urb->transfer_buffer_length,
-  urb, 1);
-
-   length_field = TRB_LEN(urb->transfer_buffer_length) |
-   TRB_TD_SIZE(remainder) |
-   TRB_INTR_TARGET(0);
-
if (urb->transfer_buffer_length > 0) {
+   u32 length_field, remainder;
+
+   remainder = xhci_td_remainder(xhci, 0,
+   urb->transfer_buffer_length,
+   urb->transfer_buffer_length,
+   urb, 1);
+   length_field = TRB_LEN(urb->transfer_buffer_length) |
+   TRB_TD_SIZE(remainder) |
+   TRB_INTR_TARGET(0);
if (setup->bRequestType & USB_DIR_IN)
field |= TRB_DIR_IN;
queue_trb(xhci, ep_ring, true,
-- 
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 4/4] usb: xhci: remove unnecessary return in xhci_pci_setup()

2017-01-04 Thread Lu Baolu
Hi,

On 01/05/2017 02:12 AM, Andy Shevchenko wrote:
> On Wed, Jan 4, 2017 at 3:51 AM, Lu Baolu  wrote:
>> Remove the unnecessary return line in xhci_pci_setup().
>>
>> Signed-off-by: Lu Baolu 
>> ---
>>  drivers/usb/host/xhci-pci.c | 2 --
>>  1 file changed, 2 deletions(-)
>>
>> diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
>> index e96ae80..ace3f57 100644
>> --- a/drivers/usb/host/xhci-pci.c
>> +++ b/drivers/usb/host/xhci-pci.c
>> @@ -242,8 +242,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
>>
>> /* Find any debug ports */
>> retval = xhci_pci_reinit(xhci, pdev);
>> -   if (!retval)
>> -   return retval;
>>
>>     return retval;
> Then better just
>
> return xhci_pci_reinit(xhci, pdev);
>

Fair enough. Thanks.

Best regards,
Lu 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: xhci: set RWE only for remote wakeup capable devices

2017-01-12 Thread Lu Baolu
Xhci spec requires in section 4.23.5.1.1.1 that the RWE bit of USB2
PORTPMSC register should only set for remote wakeup capble devices.

This was suggested by Mathias in the following discussion thread.
http://marc.info/?l=linux-usb&m=148154757829677&w=2

Suggested-by: Mathias Nyman 
Signed-off-by: Lu Baolu 
---
 drivers/usb/host/xhci.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 0c8deb9..d887e09 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4191,7 +4191,9 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
}
 
pm_val &= ~PORT_HIRD_MASK;
-   pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id);
+   pm_val |= PORT_HIRD(hird) | PORT_L1DS(udev->slot_id);
+   if (udev->do_remote_wakeup)
+   pm_val |= PORT_RWE;
writel(pm_val, pm_addr);
pm_val = readl(pm_addr);
pm_val |= PORT_HLE;
-- 
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: xhci: set RWE only for remote wakeup capable devices

2017-01-12 Thread Lu Baolu
Hi Mathias,

On 01/12/2017 04:53 PM, Lu Baolu wrote:
> Xhci spec requires in section 4.23.5.1.1.1 that the RWE bit of USB2
> PORTPMSC register should only set for remote wakeup capble devices.
>
> This was suggested by Mathias in the following discussion thread.
> http://marc.info/?l=linux-usb&m=148154757829677&w=2
>
> Suggested-by: Mathias Nyman 
> Signed-off-by: Lu Baolu 
> ---
>  drivers/usb/host/xhci.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 0c8deb9..d887e09 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -4191,7 +4191,9 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd,
>   }
>  
>   pm_val &= ~PORT_HIRD_MASK;
> - pm_val |= PORT_HIRD(hird) | PORT_RWE | PORT_L1DS(udev->slot_id);
> + pm_val |= PORT_HIRD(hird) | PORT_L1DS(udev->slot_id);
> + if (udev->do_remote_wakeup)

This is not the right thing to check remote wakeup capability of a device.
I will rework it and submit v2. Please just ignore this one.

Sorry about this.

Best regards,
Lu Baolu

> + pm_val |= PORT_RWE;
>   writel(pm_val, pm_addr);
>   pm_val = readl(pm_addr);
>   pm_val |= PORT_HLE;

--
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 30/37] usb: host: xhci: make a generic TRB tracer

2017-01-15 Thread Lu Baolu
IDT ? 'I' : 'i',
> + field3 & TRB_IOC ? 'I' : 'i',
> + field3 & TRB_CHAIN ? 'C' : 'c',
> + field3 & TRB_NO_SNOOP ? 'S' : 's',
> + field3 & TRB_ISP ? 'I' : 'i',
> + field3 & TRB_ENT ? 'E' : 'e',
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_NORMAL:
> + case TRB_DATA:
> + case TRB_STATUS:
> + case TRB_ISOC:
> + case TRB_EVENT_DATA:
> + case TRB_TR_NOOP:
> + sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type 
> '%s' flags %c:%c:%c:%c:%c:%c:%c:%c",
> + field1, field0, TRB_LEN(field2), 
> GET_TD_SIZE(field2),
> + GET_INTR_TARGET(field2),
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + field3 & TRB_BEI ? 'B' : 'b',
> + field3 & TRB_IDT ? 'I' : 'i',
> + field3 & TRB_IOC ? 'I' : 'i',
> + field3 & TRB_CHAIN ? 'C' : 'c',
> + field3 & TRB_NO_SNOOP ? 'S' : 's',
> + field3 & TRB_ISP ? 'I' : 'i',
> + field3 & TRB_ENT ? 'E' : 'e',
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> +
> + case TRB_CMD_NOOP:
> + case TRB_ENABLE_SLOT:
> + sprintf(str, "%s: flags %c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_DISABLE_SLOT:
> + case TRB_NEG_BANDWIDTH:
> + sprintf(str, "%s: slot %d flags %c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + TRB_TO_SLOT_ID(field3),
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_ADDR_DEV:
> + sprintf(str, "%s: ctx %08x%08x slot %d flags %c:%c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + field1, field0,
> + TRB_TO_SLOT_ID(field3),
> + field3 & TRB_BSR ? 'B' : 'b',
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_CONFIG_EP:
> + sprintf(str, "%s: ctx %08x%08x slot %d flags %c:%c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + field1, field0,
> + TRB_TO_SLOT_ID(field3),
> + field3 & TRB_DC ? 'D' : 'd',
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_EVAL_CONTEXT:
> + sprintf(str, "%s: ctx %08x%08x slot %d flags %c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + field1, field0,
> + TRB_TO_SLOT_ID(field3),
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_RESET_EP:
> + sprintf(str, "%s: ctx %08x%08x slot %d ep %d flags %c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> + field1, field0,
> + TRB_TO_SLOT_ID(field3),
> + /* Macro decrements 1, maybe it shouldn't?!? */
> + TRB_TO_EP_INDEX(field3) + 1,
> + field3 & TRB_CYCLE ? 'C' : 'c');
> + break;
> + case TRB_STOP_RING:
> + sprintf(str, "%s: slot %d sp %d ep %d flags %c",
> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(field3)),
> +         TRB_TO_SLOT_ID(field3),
> + TRB_TO_SUSPEND_PORT(field3),
> 

Re: [PATCH 31/37] usb: host: xhci: add urb_enqueue/dequeue/giveback tracers

2017-01-15 Thread Lu Baolu
 + TP_ARGS(urb)
> +);
> +
> +DEFINE_EVENT(xhci_log_urb, xhci_urb_dequeue,
> + TP_PROTO(struct urb *urb),
> + TP_ARGS(urb)
> +);
> +
>  #endif /* __XHCI_TRACE_H */
>  
>  /* this part must be outside header guard */
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 06d294d7e01f..c0f3670e5a51 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -1383,6 +1383,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb 
> *urb, gfp_t mem_flags)
>   urb_priv->td_cnt = 0;
>   urb->hcpriv = urb_priv;
>  
> + trace_xhci_urb_enqueue(urb);
> +
>   if (usb_endpoint_xfer_control(&urb->ep->desc)) {
>   /* Check to see if the max packet size for the default control
>* endpoint changed during FS device enumeration
> @@ -1509,6 +1511,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb 
> *urb, int status)
>  
>   xhci = hcd_to_xhci(hcd);
>   spin_lock_irqsave(&xhci->lock, flags);
> +
> + trace_xhci_urb_dequeue(urb);
> +
>   /* Make sure the URB hasn't completed or been unlinked already */
>   ret = usb_hcd_check_unlink_urb(hcd, urb, status);
>   if (ret || !urb->hcpriv)

Best regards,
Lu 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 30/37] usb: host: xhci: make a generic TRB tracer

2017-01-15 Thread Lu Baolu
Hi,

On 01/16/2017 03:03 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>> On 12/29/2016 07:01 PM, Felipe Balbi wrote:
>>> instead of having a tracer that can only trace command completions,
>>> let's promote this tracer so it can trace and decode any TRB.
>>>
>>> With that, it will be easier to extrapolate the lifetime of any TRB
>>> which might help debugging certain issues.
>>>
>>> Signed-off-by: Felipe Balbi 
>>> ---
>>>  drivers/usb/host/xhci-ring.c  |  14 +-
>>>  drivers/usb/host/xhci-trace.h |  55 +---
>>>  drivers/usb/host/xhci.h   | 311 
>>> ++
>>>  3 files changed, 357 insertions(+), 23 deletions(-)
>>>
>>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>>> index 393c64f8acef..0ee7d358b812 100644
>>> --- a/drivers/usb/host/xhci-ring.c
>>> +++ b/drivers/usb/host/xhci-ring.c
>>> @@ -1346,6 +1346,9 @@ static void handle_cmd_completion(struct xhci_hcd 
>>> *xhci,
>>>  
>>> cmd_dma = le64_to_cpu(event->cmd_trb);
>>> cmd_trb = xhci->cmd_ring->dequeue;
>>> +
>>> +   trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
>>> +
>> This is duplicated with trace_xhci_handle_event().
> no it's not. They separate events from the same event class, but they're
> different things.

Comments below.

>
>>> @@ -2407,6 +2408,10 @@ static int handle_tx_event(struct xhci_hcd *xhci,
>>>  
>>> ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) /
>>> sizeof(*ep_trb)];
>>> +
>>> +   trace_xhci_handle_transfer(ep_ring,
>>> +   (struct xhci_generic_trb *) ep_trb);
>>> +
>> This is duplicated with trace_xhci_handle_event().
> ditto
>
>>> +   __entry->type = ring->type;
>>> +   __entry->field0 = le32_to_cpu(trb->field[0]);
>>> +   __entry->field1 = le32_to_cpu(trb->field[1]);
>>> +   __entry->field2 = le32_to_cpu(trb->field[2]);
>>> +   __entry->field3 = le32_to_cpu(trb->field[3]);
>>> ),
>>> -   TP_printk("\ntrb_dma=@%llx, trb_va=@%p, status=%08x, flags=%08x",
>>> -   (unsigned long long) __entry->dma, __entry->va,
>>> -   __entry->status, __entry->flags
>>> +   TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
>> How about moving the common fields of a TRB (like TRB type and
>> the cycle bit) to the place between ring type and trb decoding string?
>> And remove type and cycle decoding in xhci_decode_trb() as well.
>>
>> Something like:
>>
>> diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
>> index d01524b..f8ef7b8 100644
>> --- a/drivers/usb/host/xhci-trace.h
>> +++ b/drivers/usb/host/xhci-trace.h
>> @@ -132,9 +132,11 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
>> __entry->field2 = le32_to_cpu(trb->field[2]);
>> __entry->field3 = le32_to_cpu(trb->field[3]);
>> ),
>> -   TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
>> -   xhci_decode_trb(__entry->field0, __entry->field1,
>> -   __entry->field2, __entry->field3)
>> +   TP_printk("%s: %s: %c: %s", xhci_ring_type_string(__entry->type),
>> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(__entry->field3)),
>> + __entry->field3 & TRB_CYCLE ? 'C' : 'c',
>> + xhci_decode_trb(__entry->field0, __entry->field1,
>> + __entry->field2, __entry->field3)
> and what do I get with that? What's the actual benefit?

I thought that it could make xhci_decode_trb() a bit simpler.

>
>> )
>>  );
>>
>>
>>> +   xhci_decode_trb(__entry->field0, __entry->field1,
>>> +   __entry->field2, __entry->field3)
>>> )
>>>  );
>>>  
>>> -DEFINE_EVENT(xhci_log_event, xhci_cmd_completion,
>>> -   TP_PROTO(void *trb_va, struct xhci_generic_trb *ev),
>>> -   TP_ARGS(trb_va, ev)
>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
>>> +   TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
&

Re: [PATCH 35/37] usb: host: xhci: remove newline from tracer

2017-01-15 Thread Lu Baolu
Hi,

On 12/29/2016 07:01 PM, Felipe Balbi wrote:
> If we add that newline, the output will like like the following:
>
>  kworker/2:1-42[002]    169.811435: xhci_address_ctx:
> ctx_64=0, ctx_type=2, ctx_dma=@153fbd000, ctx_va=@880153fbd000
>
> We would rather have that in a single line.
>
> Signed-off-by: Felipe Balbi 
> ---
>  drivers/usb/host/xhci-trace.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
> index 4bad0d6d2c8a..08bed2f07e50 100644
> --- a/drivers/usb/host/xhci-trace.h
> +++ b/drivers/usb/host/xhci-trace.h
> @@ -103,7 +103,7 @@ DECLARE_EVENT_CLASS(xhci_log_ctx,
>   ((HCC_64BYTE_CONTEXT(xhci->hcc_params) + 1) * 32) *
>   ((ctx->type == XHCI_CTX_TYPE_INPUT) + ep_num + 1));
>   ),
> - TP_printk("\nctx_64=%d, ctx_type=%u, ctx_dma=@%llx, ctx_va=@%p",
> + TP_printk("ctx_64=%d, ctx_type=%u, ctx_dma=@%llx, ctx_va=@%p",
>   __entry->ctx_64, __entry->ctx_type,
>   (unsigned long long) __entry->ctx_dma, __entry->ctx_va
>   )

This patch looks good to me.

Best regards,
Lu 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 36/37] usb: host: xhci: add xhci_virt_device tracer

2017-01-16 Thread Lu Baolu
  TP_PROTO(struct xhci_virt_device *vdev),
> + TP_ARGS(vdev)
> +);
> +
> +DEFINE_EVENT(xhci_log_virt_dev, xhci_setup_addressable_virt_device,
> + TP_PROTO(struct xhci_virt_device *vdev),
> + TP_ARGS(vdev)
> +);
> +
> +DEFINE_EVENT(xhci_log_virt_dev, xhci_stop_device,
> + TP_PROTO(struct xhci_virt_device *vdev),
> + TP_ARGS(vdev)
> +);

The lifetime of a USB virtual device in xhci host is defined by
"Figure 10: Slot State Diagram" on spec page 83. These events
are partial of the life. It's okay to me as the commit message
has covered this anyway.

For long term purpose, since the states of a virt_device are driven
by the xhci commands, it's better to define the event names according
to 1) command name; 2) the new state after command.

I am still confused by the difference between xhci_setup_device
and xhci_setup_addressable_virt_device. It seems that these
two events traces "set address phase" at the same time.

> +
>  DECLARE_EVENT_CLASS(xhci_log_urb,
>   TP_PROTO(struct urb *urb),
>   TP_ARGS(urb),
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index c0f3670e5a51..e5f095b276fc 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -3860,6 +3860,7 @@ static int xhci_setup_device(struct usb_hcd *hcd, 
> struct usb_device *udev,
>   le32_to_cpu(slot_ctx->dev_info) >> 27);
>  
>   spin_lock_irqsave(&xhci->lock, flags);
> + trace_xhci_setup_device(virt_dev);

Same here.

Move the trace down until the address device command completes.

>   ret = xhci_queue_address_device(xhci, command, virt_dev->in_ctx->dma,
>   udev->slot_id, setup);
>   if (ret) {

Best regards,
Lu 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 30/37] usb: host: xhci: make a generic TRB tracer

2017-01-16 Thread Lu Baolu
Hi,

On 01/16/2017 04:55 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>>>>> + __entry->type = ring->type;
>>>>> + __entry->field0 = le32_to_cpu(trb->field[0]);
>>>>> + __entry->field1 = le32_to_cpu(trb->field[1]);
>>>>> + __entry->field2 = le32_to_cpu(trb->field[2]);
>>>>> + __entry->field3 = le32_to_cpu(trb->field[3]);
>>>>>   ),
>>>>> - TP_printk("\ntrb_dma=@%llx, trb_va=@%p, status=%08x, flags=%08x",
>>>>> - (unsigned long long) __entry->dma, __entry->va,
>>>>> - __entry->status, __entry->flags
>>>>> + TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
>>>> How about moving the common fields of a TRB (like TRB type and
>>>> the cycle bit) to the place between ring type and trb decoding string?
>>>> And remove type and cycle decoding in xhci_decode_trb() as well.
>>>>
>>>> Something like:
>>>>
>>>> diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
>>>> index d01524b..f8ef7b8 100644
>>>> --- a/drivers/usb/host/xhci-trace.h
>>>> +++ b/drivers/usb/host/xhci-trace.h
>>>> @@ -132,9 +132,11 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
>>>> __entry->field2 = le32_to_cpu(trb->field[2]);
>>>> __entry->field3 = le32_to_cpu(trb->field[3]);
>>>> ),
>>>> -   TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
>>>> -   xhci_decode_trb(__entry->field0, __entry->field1,
>>>> -   __entry->field2, __entry->field3)
>>>> +   TP_printk("%s: %s: %c: %s", xhci_ring_type_string(__entry->type),
>>>> + xhci_trb_type_string(TRB_FIELD_TO_TYPE(__entry->field3)),
>>>> + __entry->field3 & TRB_CYCLE ? 'C' : 'c',
>>>> + xhci_decode_trb(__entry->field0, __entry->field1,
>>>> + __entry->field2, __entry->field3)
>>> and what do I get with that? What's the actual benefit?
>> I thought that it could make xhci_decode_trb() a bit simpler.
> It'll have a very marginal simplification of a single function that's
> only called from tracepoints. I wonder if there's an actual benefit
> there.

Fair enough.

>
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>> +);
>>>>> +
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_command,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>> +);
>>>>> +
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_handle_transfer,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>> +);
>>>>> +
>>>>> +DEFINE_EVENT(xhci_log_trb, xhci_queue_trb,
>>>>> + TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
>>>>> + TP_ARGS(ring, trb)
>>>>>  );
>>>> xhci_handle_command and xhci_handle_transfer are duplications
>>>> of xhci_handle_event. I suggest to remove them.
>>> no, they are not. They give us more granularity into which events we
>>> want to enable. 
>> Fair enough.
>>
>> But why not defining events for all possible event types as well
>> and dropping the all-in-one xhci_handle_event switch.
>>
>> A single event TRB will be traced twice in the same execution
>> path if xhci_handle_event and xhci_handle_command/transfer
>> are both enabled.
> no, it won't. Commands sit in the Command Ring. Events sit in the Event
> Ring. Transfers sit in the various Endpoint Rings.
>
> Compile the branch, enable the tracers and look at the output.
>
>>> They also make it clear where the even is coming
>>> from. Imagine how the trace would look like if I had a single event and
>>> just called trace_xhci_handle_event() from all locations. How would you
>>> differentiate from all possible call sites?
>> These events happen only in interrupt handler. There are no other
>> possible call sites.
> you

Re: [PATCH 31/37] usb: host: xhci: add urb_enqueue/dequeue/giveback tracers

2017-01-16 Thread Lu Baolu
Hi,

On 01/16/2017 04:59 PM, Felipe Balbi wrote:
> Hi,
>
> Lu Baolu  writes:
>> Hi,
>>
>> On 12/29/2016 07:01 PM, Felipe Balbi wrote:
>>> These three new tracers will help us tie TRBs into URBs by *also*
>>> looking into URB lifetime.
>> I didn't see anything related to TRBs in the patch.
>> Anything I missed?
> yes. Ordering of events. Seriously, you ought to compile my xhci-cleanup
> patches and run with tracers enabled. Here's what I'm talking about:
>
> before $subject, we would only see TRBs being queued to HW and
> completed, etc. After $subject, we see URBs being queued by class
> drivers, which in turn triggers xHCI driver to prepare TRBs which will
> be queued to HW. Once a completion IRQ fires, we see TRBs being
> "dequeued" from HW and URBs being given back.
>
> IOW, after $subject we know that a particular TRB (or a set of them)
> were queued because an URB was queued. We know the size of the URB, a
> pointer to it, etc. We can actually match urb->transfer_length to
> sum_of_trb_sizes().

Yes. Get it now. Thanks for this comment.

>>> Signed-off-by: Felipe Balbi 
>>> ---
>>>  drivers/usb/host/xhci-ring.c  |  1 +
>>>  drivers/usb/host/xhci-trace.h | 70 
>>> +++
>>>  drivers/usb/host/xhci.c   |  5 
>>>  3 files changed, 76 insertions(+)
>>>
>>> diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
>>> index 0ee7d358b812..1431e0651e78 100644
>>> --- a/drivers/usb/host/xhci-ring.c
>>> +++ b/drivers/usb/host/xhci-ring.c
>>> @@ -627,6 +627,7 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd 
>>> *xhci,
>>> usb_hcd_unlink_urb_from_ep(hcd, urb);
>>> spin_unlock(&xhci->lock);
>>> usb_hcd_giveback_urb(hcd, urb, status);
>>> +   trace_xhci_urb_giveback(urb);
>> There is another trace point in xhci_urb_dequeue().
>>
>> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
>> index b49588f..ee46877 100644
>> --- a/drivers/usb/host/xhci.c
>> +++ b/drivers/usb/host/xhci.c
>> @@ -1535,6 +1535,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb 
>> *urb, int status)
>>  
>> usb_hcd_unlink_urb_from_ep(hcd, urb);
>> spin_unlock_irqrestore(&xhci->lock, flags);
>> +   trace_xhci_urb_giveback(urb);
> yes, so? I want to know that the URB *was* indeed given back.
>

Got it. There is no need to trace a giveback which ties no real trbs.

I have no further questions about this patch. Thanks.

Best regards,
Lu 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


  1   2   3   4   5   6   7   >