[PATCH V2] usb: phy: am335x: Use SIMPLE_DEV_PM_OPS macro

2014-03-06 Thread Jingoo Han
Use SIMPLE_DEV_PM_OPS macro and remove DEV_PM_OPS macro, in order
to make the code simpler.

Signed-off-by: Jingoo Han 
---
Changes since v1:
- Move SIMPLE_DEV_PM_OPS outside the #ifdef CONFIG_PM_SLEEP condition 
  and remove DEV_PM_OPS macro, per Roger Quadros

 drivers/usb/phy/phy-am335x.c |   12 +++-
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 12fc346..eafeeb6 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -122,16 +122,10 @@ static int am335x_phy_resume(struct device *dev)
 
return 0;
 }
-
-static const struct dev_pm_ops am335x_pm_ops = {
-   SET_SYSTEM_SLEEP_PM_OPS(am335x_phy_suspend, am335x_phy_resume)
-};
-
-#define DEV_PM_OPS (&am335x_pm_ops)
-#else
-#define DEV_PM_OPS NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(am335x_pm_ops, am335x_phy_suspend, am335x_phy_resume);
+
 static const struct of_device_id am335x_phy_ids[] = {
{ .compatible = "ti,am335x-usb-phy" },
{ }
@@ -144,7 +138,7 @@ static struct platform_driver am335x_phy_driver = {
.driver = {
.name   = "am335x-phy-driver",
.owner  = THIS_MODULE,
-   .pm = DEV_PM_OPS,
+   .pm = &am335x_pm_ops,
.of_match_table = am335x_phy_ids,
},
 };
-- 
1.7.10.4


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


[PATCH v2 2/2] xhci: Use pci_enable_msix_exact() instead of pci_enable_msix()

2014-03-06 Thread Alexander Gordeev
As result of deprecation of MSI-X/MSI enablement functions
pci_enable_msix() and pci_enable_msi_block() all drivers
using these two interfaces need to be updated to use the
new pci_enable_msi_range()  or pci_enable_msi_exact()
and pci_enable_msix_range() or pci_enable_msix_exact()
interfaces.

Signed-off-by: Alexander Gordeev 
Cc: Sarah Sharp 
Cc: Greg Kroah-Hartman 
Cc: linux-usb@vger.kernel.org
Cc: linux-...@vger.kernel.org
---
 drivers/usb/host/xhci.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6fbba7a..dc7cfb5 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -292,7 +292,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
xhci->msix_entries[i].vector = 0;
}
 
-   ret = pci_enable_msix(pdev, xhci->msix_entries, xhci->msix_count);
+   ret = pci_enable_msix_exact(pdev, xhci->msix_entries, xhci->msix_count);
if (ret) {
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Failed to enable MSI-X");
-- 
1.7.7.6

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


[PATCH v2 1/2] xhci: Cleanup xhci_setup_msi() and xhci_setup_msix()

2014-03-06 Thread Alexander Gordeev
Make xhci_setup_msi() and xhci_setup_msix() functions
return error code in a consistent and more clear way.

Signed-off-by: Alexander Gordeev 
Cc: Sarah Sharp 
Cc: Greg Kroah-Hartman 
Cc: linux-usb@vger.kernel.org
Cc: linux-...@vger.kernel.org
---
 drivers/usb/host/xhci.c |5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6fe577d..6fbba7a 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -232,9 +232,10 @@ static int xhci_setup_msi(struct xhci_hcd *xhci)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"disable MSI interrupt");
pci_disable_msi(pdev);
+   return ret;
}
 
-   return ret;
+   return 0;
 }
 
 /*
@@ -307,7 +308,7 @@ static int xhci_setup_msix(struct xhci_hcd *xhci)
}
 
hcd->msix_enabled = 1;
-   return ret;
+   return 0;
 
 disable_msix:
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "disable MSI-X interrupt");
-- 
1.7.7.6

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


[PATCH v3] phy: ti-pipe3: Add SATA DPLL support

2014-03-06 Thread Kishon Vijay Abraham I
From: Roger Quadros 

USB and SATA DPLLs need different settings. Provide
the SATA DPLL settings and use the proper DPLL settings
based on device tree node's compatible_id.

Signed-off-by: Roger Quadros 
Signed-off-by: Kishon Vijay Abraham I 
---
Changes from v2:
* kept only the drivers/phy part

 drivers/phy/phy-ti-pipe3.c |   76 
 1 file changed, 55 insertions(+), 21 deletions(-)

diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 211703c..f141237 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -66,6 +66,11 @@ struct pipe3_dpll_params {
u32 mf;
 };
 
+struct pipe3_dpll_map {
+   unsigned long rate;
+   struct pipe3_dpll_params params;
+};
+
 struct ti_pipe3 {
void __iomem*pll_ctrl_base;
struct device   *dev;
@@ -73,20 +78,27 @@ struct ti_pipe3 {
struct clk  *wkupclk;
struct clk  *sys_clk;
struct clk  *refclk;
+   struct pipe3_dpll_map   *dpll_map;
 };
 
-struct pipe3_dpll_map {
-   unsigned long rate;
-   struct pipe3_dpll_params params;
-};
-
-static struct pipe3_dpll_map dpll_map[] = {
+static struct pipe3_dpll_map dpll_map_usb[] = {
{1200, {1250, 5, 4, 20, 0} },   /* 12 MHz */
{1680, {3125, 20, 4, 20, 0} },  /* 16.8 MHz */
{1920, {1172, 8, 4, 20, 65537} },   /* 19.2 MHz */
{2000, {1000, 7, 4, 10, 0} },   /* 20 MHz */
{2600, {1250, 12, 4, 20, 0} },  /* 26 MHz */
{3840, {3125, 47, 4, 20, 92843} },  /* 38.4 MHz */
+   { },/* Terminator */
+};
+
+static struct pipe3_dpll_map dpll_map_sata[] = {
+   {1200, {1000, 7, 4, 6, 0} },/* 12 MHz */
+   {1680, {714, 7, 4, 6, 0} }, /* 16.8 MHz */
+   {1920, {625, 7, 4, 6, 0} }, /* 19.2 MHz */
+   {2000, {600, 7, 4, 6, 0} }, /* 20 MHz */
+   {2600, {461, 7, 4, 6, 0} }, /* 26 MHz */
+   {3840, {312, 7, 4, 6, 0} }, /* 38.4 MHz */
+   { },/* Terminator */
 };
 
 static inline u32 ti_pipe3_readl(void __iomem *addr, unsigned offset)
@@ -100,15 +112,20 @@ static inline void ti_pipe3_writel(void __iomem *addr, 
unsigned offset,
__raw_writel(data, addr + offset);
 }
 
-static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(unsigned long rate)
+static struct pipe3_dpll_params *ti_pipe3_get_dpll_params(struct ti_pipe3 *phy)
 {
-   int i;
+   unsigned long rate;
+   struct pipe3_dpll_map *dpll_map = phy->dpll_map;
 
-   for (i = 0; i < ARRAY_SIZE(dpll_map); i++) {
-   if (rate == dpll_map[i].rate)
-   return &dpll_map[i].params;
+   rate = clk_get_rate(phy->sys_clk);
+
+   for (; dpll_map->rate; dpll_map++) {
+   if (rate == dpll_map->rate)
+   return &dpll_map->params;
}
 
+   dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate);
+
return NULL;
 }
 
@@ -182,16 +199,11 @@ static void ti_pipe3_dpll_relock(struct ti_pipe3 *phy)
 static int ti_pipe3_dpll_lock(struct ti_pipe3 *phy)
 {
u32 val;
-   unsigned long   rate;
struct pipe3_dpll_params *dpll_params;
 
-   rate = clk_get_rate(phy->sys_clk);
-   dpll_params = ti_pipe3_get_dpll_params(rate);
-   if (!dpll_params) {
-   dev_err(phy->dev,
- "No DPLL configuration for %lu Hz SYS CLK\n", rate);
+   dpll_params = ti_pipe3_get_dpll_params(phy);
+   if (!dpll_params)
return -EINVAL;
-   }
 
val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
val &= ~PLL_REGN_MASK;
@@ -244,6 +256,10 @@ static struct phy_ops ops = {
.owner  = THIS_MODULE,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id ti_pipe3_id_table[];
+#endif
+
 static int ti_pipe3_probe(struct platform_device *pdev)
 {
struct ti_pipe3 *phy;
@@ -253,8 +269,10 @@ static int ti_pipe3_probe(struct platform_device *pdev)
struct device_node *node = pdev->dev.of_node;
struct device_node *control_node;
struct platform_device *control_pdev;
+   const struct of_device_id *match;
 
-   if (!node)
+   match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
+   if (!match)
return -EINVAL;
 
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
@@ -263,6 +281,12 @@ static int ti_pipe3_probe(struct platform_device *pdev)
return -ENOMEM;
}
 
+   phy->dpll_map = (struct pipe3_dpll_map *)match->data;
+   if (!phy->dpll_map) {
+   dev_err(&pdev->dev, "no DPLL data\n");
+   return -EINVAL;
+   }
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ct

Re: [PATCH v3] phy: omap-control: update dra7 and am437 usb2 bindings

2014-03-06 Thread George Cherian

On 3/7/2014 11:18 AM, Kishon Vijay Abraham I wrote:

From: Roger Quadros 

The dra7-usb2 and am437-usb2 bindings have not yet been used.
Change them to be more elegant.

Signed-off-by: Roger Quadros 
Signed-off-by: Kishon Vijay Abraham I 
---
Changes from v2:
Kept only the drivers/phy part in this patch

  drivers/phy/phy-omap-control.c |4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
index 17fc200..a7e2d7f 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -228,11 +228,11 @@ static const struct of_device_id 
omap_control_phy_id_table[] = {
.data = &pipe3_data,
},
{
-   .compatible = "ti,control-phy-dra7usb2",
+   .compatible = "ti,control-phy-dra7-usb2",
.data = &dra7usb2_data,
},
{
-   .compatible = "ti,control-phy-am437usb2",
+   .compatible = "ti,control-phy-am437-usb2",


Tony suggested to keep the compatible

ti,control-phy-usb2-dra7 and ti,control-phy-usb2-am437

http://www.spinics.net/lists/linux-omap/msg104040.html

Since we already have a ti,control-phy-usb2 I think it make sense to keep the 
new comaptible for dra7 and am437 as above.


.data = &am437usb2_data,
},
{},



--
-George

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


[PATCH v3] phy: ti-pipe3: cleanup clock handling

2014-03-06 Thread Kishon Vijay Abraham I
From: Roger Quadros 

As this driver is no longer USB specific, use generic clock names.
- Fix PLL_SD_SHIFT from 9 to 10
- Don't separate prepare/unprepare clock from enable/disable. This
  ensures optimal power savings.

Signed-off-by: Roger Quadros  
Signed-off-by: Kishon Vijay Abraham I 
---
Changes from v2:
* Kept only the drivers/phy part in this patch

 drivers/phy/phy-ti-pipe3.c |   55 ++--
 1 file changed, 28 insertions(+), 27 deletions(-)

diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index fd029b1..211703c 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -45,7 +45,7 @@
 #definePLL_SELFREQDCO_MASK 0x000E
 #definePLL_SELFREQDCO_SHIFT0x1
 #definePLL_SD_MASK 0x0003FC00
-#definePLL_SD_SHIFT0x9
+#definePLL_SD_SHIFT10
 #defineSET_PLL_GO  0x1
 #definePLL_TICOPWDN0x1
 #definePLL_LOCK0x2
@@ -72,7 +72,7 @@ struct ti_pipe3 {
struct device   *control_dev;
struct clk  *wkupclk;
struct clk  *sys_clk;
-   struct clk  *optclk;
+   struct clk  *refclk;
 };
 
 struct pipe3_dpll_map {
@@ -270,23 +270,21 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 
phy->dev= &pdev->dev;
 
-   phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
+   phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
if (IS_ERR(phy->wkupclk)) {
-   dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
+   dev_err(&pdev->dev, "unable to get wkupclk\n");
return PTR_ERR(phy->wkupclk);
}
-   clk_prepare(phy->wkupclk);
 
-   phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
-   if (IS_ERR(phy->optclk)) {
-   dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n");
-   return PTR_ERR(phy->optclk);
+   phy->refclk = devm_clk_get(phy->dev, "refclk");
+   if (IS_ERR(phy->refclk)) {
+   dev_err(&pdev->dev, "unable to get refclk\n");
+   return PTR_ERR(phy->refclk);
}
-   clk_prepare(phy->optclk);
 
-   phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin");
+   phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
if (IS_ERR(phy->sys_clk)) {
-   pr_err("%s: unable to get sys_clkin\n", __func__);
+   dev_err(&pdev->dev, "unable to get sysclk\n");
return -EINVAL;
}
 
@@ -326,10 +324,6 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 
 static int ti_pipe3_remove(struct platform_device *pdev)
 {
-   struct ti_pipe3 *phy = platform_get_drvdata(pdev);
-
-   clk_unprepare(phy->wkupclk);
-   clk_unprepare(phy->optclk);
if (!pm_runtime_suspended(&pdev->dev))
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
@@ -343,8 +337,10 @@ static int ti_pipe3_runtime_suspend(struct device *dev)
 {
struct ti_pipe3 *phy = dev_get_drvdata(dev);
 
-   clk_disable(phy->wkupclk);
-   clk_disable(phy->optclk);
+   if (!IS_ERR(phy->wkupclk))
+   clk_disable_unprepare(phy->wkupclk);
+   if (!IS_ERR(phy->refclk))
+   clk_disable_unprepare(phy->refclk);
 
return 0;
 }
@@ -354,22 +350,27 @@ static int ti_pipe3_runtime_resume(struct device *dev)
u32 ret = 0;
struct ti_pipe3 *phy = dev_get_drvdata(dev);
 
-   ret = clk_enable(phy->optclk);
-   if (ret) {
-   dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
-   goto err1;
+   if (!IS_ERR(phy->refclk)) {
+   ret = clk_prepare_enable(phy->refclk);
+   if (ret) {
+   dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
+   goto err1;
+   }
}
 
-   ret = clk_enable(phy->wkupclk);
-   if (ret) {
-   dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
-   goto err2;
+   if (!IS_ERR(phy->wkupclk)) {
+   ret = clk_prepare_enable(phy->wkupclk);
+   if (ret) {
+   dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
+   goto err2;
+   }
}
 
return 0;
 
 err2:
-   clk_disable(phy->optclk);
+   if (!IS_ERR(phy->refclk))
+   clk_disable_unprepare(phy->refclk);
 
 err1:
return ret;
-- 
1.7.9.5

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


[PATCH v3] phy: omap-control: update dra7 and am437 usb2 bindings

2014-03-06 Thread Kishon Vijay Abraham I
From: Roger Quadros 

The dra7-usb2 and am437-usb2 bindings have not yet been used.
Change them to be more elegant.

Signed-off-by: Roger Quadros 
Signed-off-by: Kishon Vijay Abraham I 
---
Changes from v2:
Kept only the drivers/phy part in this patch

 drivers/phy/phy-omap-control.c |4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
index 17fc200..a7e2d7f 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -228,11 +228,11 @@ static const struct of_device_id 
omap_control_phy_id_table[] = {
.data = &pipe3_data,
},
{
-   .compatible = "ti,control-phy-dra7usb2",
+   .compatible = "ti,control-phy-dra7-usb2",
.data = &dra7usb2_data,
},
{
-   .compatible = "ti,control-phy-am437usb2",
+   .compatible = "ti,control-phy-am437-usb2",
.data = &am437usb2_data,
},
{},
-- 
1.7.9.5

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


Re: [PATCH v2] phy-rcar-gen2-usb: add device tree support

2014-03-06 Thread Magnus Damm
On Sat, Mar 1, 2014 at 10:07 AM, Sergei Shtylyov
 wrote:
> Add support of the device tree probing for the Renesas R-Car generation 2 SoCs
> documenting the device tree binding as necessary.
>
> Signed-off-by: Sergei Shtylyov 
>
> ---
> This patch is against the 'next' branch of Felipe Balbi's 'usb.git' repo.
>
> Changes in version 2:
> - restored devm_clk_get() call and the error handling logic in the probe()
>   method, removed clk_put() call in the remove() method.
>
>  Documentation/devicetree/bindings/usb/rcar-gen2-phy.txt |   29 +++
>  drivers/usb/phy/phy-rcar-gen2-usb.c |   42 
> ++--
>  2 files changed, 68 insertions(+), 3 deletions(-)
>
> Index: usb/Documentation/devicetree/bindings/usb/rcar-gen2-phy.txt
> ===
> --- /dev/null
> +++ usb/Documentation/devicetree/bindings/usb/rcar-gen2-phy.txt
> @@ -0,0 +1,29 @@
> +* Renesas R-Car generation 2 USB PHY
> +
> +This file provides information on what the device node for the R-Car 
> generation
> +2 USB PHY contains.
> +
> +Required properties:
> +- compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 
> SoC.
> + "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 
> SoC.
> +- reg: offset and length of the register block.
> +- clocks: clock phandle and specifier pair.
> +- clock-names: string, clock input name, must be "usbhs".
> +
> +Optional properties:
> +- renesas,channel0-pci: boolean, specify when USB channel 0 should be 
> connected
> +   to PCI EHCI/OHCI; otherwise, it will be connected to 
> the
> +   USBHS controller.
> +- renesas,channel2-pci: boolean, specify when USB channel 2 should be 
> connected
> +   to PCI EHCI/OHCI; otherwise, it will be connected to 
> the
> +   USBSS controller (xHCI).

Thanks for your efforts here, but this DT binding looks like a mix of
software configuration and hardware description. I would like to omit
the software configuration portion if possible and only describe the
hardware.

> +Example (Lager board):
> +
> +   usb-phy@e6590100 {
> +   compatible = "renesas,usb-phy-r8a7790";
> +   reg = <0 0xe6590100 0 0x100>;
> +   clocks = <&mstp7_clks R8A7790_CLK_HSUSB>;
> +   clock-names = "usbhs";
> +   renesas,channel2-pci;
> +   };

As an example, instead of relying on "renesas,channel0-pci" or
"renesas,channel2-pci" to specify which hard coded software
configuration you want please rework this to expose 3 separate
channels and use DT to point each host controller to the right
channel.

That will give us the opportunity to perform any kind of run time
selection and not be limited by software policy set by DT.

So this is a NAK on my side. I expect better.

Thanks,

/ magnus
--
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: Renesas RCar device-tree USB series

2014-03-06 Thread Magnus Damm
Hi Ben,

On Fri, Mar 7, 2014 at 3:01 AM, Ben Dooks  wrote:
> This is a new series covering enabling the RCar series of SoCs USB
> with device-tree based booting. It has been tested on the R8A7790
> Lager board.
>
> Improvements from the previous series include:
>
> - mapping usb to the relevant phy by dt
> - better use of existing pci of functions
>
> Note, there is still an issue with the second gigabyte of memory on
> the Lager, which with current kernels causes the system to abort on
> startup. This series will only work if the top memory area is disabled.

Thanks for these patches. I think they start looking really good.

In my mind there are two outstanding issues:

1) Is the USB core code change acceptable or not?

The patch "[PATCH 4/9] usb: phy: check for of_node when getting phy"
looks quite fine to me, but I wonder if the USB maintainers will
accept it as-is or require some rework. I would say that the rest of
this series depends on that USB core change.

2) Per-port USB PHY driver configuration via DT

Right now each USB host controller points to the same PHY device.
Thanks for working on describing the topology! As you know, the PHY
driver itself handles several USB ports, and I'd like to use DT to
represent the mapping between which PHY port that maps to what USB
Host controller to allow proper run time configuration. Right now in
this version of the series there is no such mapping. Of course, that
depends on proper USB PHY DT bindings...

Thanks,

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


Re: [PATCH v3] phy: omap-control: update dra7 and am437 usb2 Documentation bindings

2014-03-06 Thread Kishon Vijay Abraham I



On Thursday 06 March 2014 09:33 PM, Felipe Balbi wrote:

From: Roger Quadros 

The dra7-usb2 and am437-usb2 bindings have not yet been used.
Change them to be more elegant.

Acked-by: Kishon Vijay Abraham I 
Signed-off-by: Roger Quadros 
Signed-off-by: Felipe Balbi 
---

Here's updated patch with only Documentation. Tell me if it's ok to apply.


looks good to me

Thanks
Kishon


  Documentation/devicetree/bindings/phy/ti-phy.txt | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt 
b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 41dc132..8694aae 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -9,9 +9,9 @@ Required properties:
  e.g. USB2_PHY on OMAP5.
   "ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
  e.g. USB3 PHY and SATA PHY on OMAP5.
- "ti,control-phy-dra7usb2" - if it has power down register like USB2 PHY on
+ "ti,control-phy-dra7-usb2" - if it has power down register like USB2 PHY on
  DRA7 platform.
- "ti,control-phy-am437usb2" - if it has power down register like USB2 PHY on
+ "ti,control-phy-am437-usb2" - if it has power down register like USB2 PHY on
  AM437 platform.
   - reg : Address and length of the register set for the device. It contains
 the address of "otghs_control" for control-phy-otghs or "power" register


--
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 3/4] phy: Add new Exynos USB 2.0 PHY driver

2014-03-06 Thread Anton Tikhomirov
Hi,

> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> 
> Hi,
> 
> On Thursday 06 March 2014 02:49 PM, Anton Tikhomirov wrote:
> > Hi,
> >
> >> Subject: RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> >>
> >> Hi,
> >>
> >>> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> >>>
> >>> Hi,
> >>>
> >>> On Thursday 06 March 2014 02:22 PM, Anton Tikhomirov wrote:
>  Hello,
> 
> > Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY
> driver
> >
> >
> >
> > On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
> >> Hi Kamil,
> >>
> >> ...
> >>
> >>> +| 3. Supporting SoCs
> >>> ++
> >>> +
> >>> +To support a new SoC a new file should be added to the
> >>> drivers/phy
> >>> +directory. Each SoC's configuration is stored in an instance
> of
> >>> the
> >>> +struct samsung_usb2_phy_config.
> >>> +
> >>> +struct samsung_usb2_phy_config {
> >>> + const struct samsung_usb2_common_phy *phys;
> >>> + unsigned int num_phys;
> >>> + bool has_mode_switch;
> >>
> >> You missed rate_to_clk here.
> >>
> >>> +};
> >>> +
> >>
> >> ...
> >>
> >>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
> > samsung-
> >>> usb2.c
> >>> new file mode 100644
> >>> index 000..c3b7719
> >>> --- /dev/null
> >>> +++ b/drivers/phy/phy-samsung-usb2.c
> >>> @@ -0,0 +1,222 @@
> >>> +/*
> >>> + * Samsung SoC USB 1.1/2.0 PHY driver
> >>> + *
> >>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> >>> + * Author: Kamil Debski 
> >>> + *
> >>> + * This program is free software; you can redistribute it
> >> and/or
> >>> modify
> >>> + * it under the terms of the GNU General Public License
> version
> >> 2
> > as
> >>> + * published by the Free Software Foundation.
> >>> + */
> >>> +
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include 
> >>> +#include "phy-samsung-usb2.h"
> >>> +
> >>> +static int samsung_usb2_phy_power_on(struct phy *phy)
> >>> +{
> >>> + struct samsung_usb2_phy_instance *inst =
> >>> phy_get_drvdata(phy);
> >>> + struct samsung_usb2_phy_driver *drv = inst->drv;
> >>> + int ret;
> >>> +
> >>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> >>> + inst->cfg->label);
> >>> + ret = clk_prepare_enable(drv->clk);
> >>
> >> clk_prepare_enable() can sleep, and therefore doesn't allow
> >> samusng_usb2_phy_power_on() to be used in atomic context
> >> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
> >> What about to prepare clock in probe, and just enable it here
> >> (note: clk_enable() doesn't sleep).
> >
> > The PHY power-on callback is anyway called with mutex held, so I
> >>> guess
> > it's fine to have clk_prepare_enable() here.
> 
>  If we rely totally on generic PHY functions such as phy_power_on()
>  and friends, why do we need to use locking in callbacks at all.
> >>>
> >>> Didn't get you.. We don't want to invoke power_on when init is
> >> getting
> >>> executed or you don't want power on or power off to get executed
> >>> simultaneously right? So we need to protect it.
> >>
> >> I mean callbacks such as samsung_usb2_phy_power_on() which uses
> >> spin_lock.
> >> It's already protected by mutex in phy_power_on().
> >
> > Well... phy_power_on() uses mutex to protect power_on() callback.
> > power_on() is samsung_usb2_phy_power_on() in our case.
> > samsung_usb2_phy_power_on() uses spinlock.
> > My question is why do we need to use spinlock _inside_ callback
> > if it is already protected by mutex.
> 
> It is needed when the same PHY provider implements multiple PHYs.
> phy-core can protect phy-ops of same PHY. However if the PHY provider
> implements multiple PHYs, phy-core won't be able to protect.

Thank you Kishon. Now it's clear.

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


Re: [PATCH v3 00/13] Add USB OTG HNP and SRP support on Chipidea usb driver

2014-03-06 Thread Peter Chen
On Thu, Feb 27, 2014 at 07:38:18AM +0800, Li Jun wrote:
> From: b47624 
> 
> This patchset adds USB OTG HNP and SRP support on chipidea usb driver,
> existing OTG port role swtich function by ID pin status kept unchanged,
> based on that, if select CONFIG_USB_OTG_FSM, OTG HNP and SRP will be
> supported.

The CONFIG_USB_OTG should also be needed?

> 
> Reference to:
> "On-The-Go and Embedded Host Supplement to the USB Revision 2.0 Specification 
> July 27, 2012
> Revision 2.0 version 1.1a"
> 

Jun, at next time, you can have a patch at Documentation/ to introduce
how to do it.

> How to test HNP&SRP with 2 Freescale i.MX6Q sabre SD boards:
> 1. Power up 2 Freescale i.MX6Q sabre SD boards with gadget class driver loaded
>(e.g. g_mass_storage).
> 
> 2. Connect 2 boards with usb cable with one end is micro A plug, the other end
>is micro B plug.
> 
> 3. The A device with micro A plug inserted should enumrate B device.
> 

If I swap step 1 and step 2, it can't enumerate. Plug out and plug in
again can work. Have a check please.

> 4. Role switch.
>On B device:
>echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
> 
>if HNP polling patchset is not applied, also need:

You can say if HNP polling is not supported

>On A device:
>echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
> 
>B device should take host role and enumrate A device(peripheral).

It works.

> 
> 5. A device switch back to host.
>On B device:
>echo 0 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
> 
>A device should switch back to host and enumrate B device.

works.

> 
> 6. Remove B device and insert again in 10 seconds, A device should
>enumrate B device again.
> 


> 7. Remove B device and insert again after 10 seconds, A device should
>NOT enumrate B device.
> 
>if A device wants to use bus:
>On A device:
>echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_req
> 
>if B device wants to use bus:
>On B device:
>echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req

Works.

What does A(B) device wants to use bus? The vbus should always
from A device, correct?

> 
> 8. A device power down the bus.
>On A device:
>echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/a_bus_drop
> 
> 9. B device do data pulse for SRP.
>On B device:
>echo 1 > /sys/bus/platform/devices/ci_hdrc.0/inputs/b_bus_req
> 
>A device usb bus should be resumed and enumrate B device.

Works.

Peter

> 
> Changes since v2:
> - Add ABI document for sysfs input files description:
>   Documentation/ABI/testing/sysfs-platform-chipidea-usb-otg
> - Add a debug file for show some USB registers value.
> - Split host driver change to be 2 patches, one for otg_port number init;
>   the other one for vbus control change.
> - Export interrupt enable and status read functions from udc driver.
> - Only enable AVV irq in otg fsm init.
> - Remove duplicated USBSTS bits definitions.
> - typo correction.
> - Add HowTo demo role switch with 2 Freescale i.MX6Q sabre SD boards
>   in cover letter.
> 
> Changes since v1:
> - Move out HNP polling patch from this series, which will be a seperated 
> patchset
>   followed this one
> - Change fsm timers global variables to be a structure embeded in ci_hdrc,
>   to make multiple OTG instances can exist in one system
> - Change some otg fsm functions to be static
> - Re-split timer init patch to avoid a later patch changing a previous one
>   in the same series
> - Change timer structure memory allocation to be devm_kzalloc
> - Update some format alignment and spelling errors
> 
> Li Jun (13):
>   usb: phy-fsm: update OTG HNP state transition conditions according to
> OTG and EH 2.0 spec.
>   usb: chipidea: usb OTG fsm initialization.
>   usb: chipidea: host: vbus control change for OTG HNP.
>   usb: chipidea: host: init otg port number.
>   usb: chipidea: udc: driver update for OTG HNP.
>   usb: chipidea: export interrupt enable and status register read
> functions.
>   usb: chipidea: add OTG fsm operation functions implemenation.
>   usb: chipidea: OTG fsm timers initialization.
>   usb: chipidea: OTG HNP and SRP fsm implementation.
>   usb: chipidea: add sys inputs for OTG fsm input.
>   usb: chipidea: debug: add debug file for OTG variables show.
>   usb: chipidea: debug: add debug file for controller registers dump.
>   Documentation: ABI: usb: chipidea USB OTG HNP sysfs interface
> description.
> 
>  .../ABI/testing/sysfs-platform-chipidea-usb-otg|   55 ++
>  drivers/usb/chipidea/Makefile  |1 +
>  drivers/usb/chipidea/bits.h|   12 +
>  drivers/usb/chipidea/ci.h  |6 +
>  drivers/usb/chipidea/core.c|   30 +-
>  drivers/usb/chipidea/debug.c   |  133 +++
>  drivers/usb/chipidea/host.c|   13 +-
>  drivers/usb/chipidea/host.h|9 +
>  

[PATCH net-next 3/7] r8152: up the priority of the transmission

2014-03-06 Thread Hayes Wang
move the tx_bottom() from delayed_work to tasklet. It makes the rx
and tx balanced. If the device is in runtime suspend when getting
the tx packet, wakeup the device before trasmitting.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 45 +++--
 1 file changed, 27 insertions(+), 18 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 00b3192..f1eaa18 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -447,6 +447,7 @@ enum rtl8152_flags {
RTL8152_LINK_CHG,
SELECTIVE_SUSPEND,
PHY_RESET,
+   SCHEDULE_TASKLET,
 };
 
 /* Define these values to match your device */
@@ -1071,7 +1072,7 @@ static void write_bulk_callback(struct urb *urb)
return;
 
if (!skb_queue_empty(&tp->tx_queue))
-   schedule_delayed_work(&tp->schedule, 0);
+   tasklet_schedule(&tp->tl);
 }
 
 static void intr_callback(struct urb *urb)
@@ -1335,9 +1336,9 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct 
tx_agg *agg)
u8 *tx_data;
 
__skb_queue_head_init(&skb_head);
-   spin_lock_bh(&tx_queue->lock);
+   spin_lock(&tx_queue->lock);
skb_queue_splice_init(tx_queue, &skb_head);
-   spin_unlock_bh(&tx_queue->lock);
+   spin_unlock(&tx_queue->lock);
 
tx_data = agg->head;
agg->skb_num = agg->skb_len = 0;
@@ -1374,20 +1375,20 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct 
tx_agg *agg)
}
 
if (!skb_queue_empty(&skb_head)) {
-   spin_lock_bh(&tx_queue->lock);
+   spin_lock(&tx_queue->lock);
skb_queue_splice(&skb_head, tx_queue);
-   spin_unlock_bh(&tx_queue->lock);
+   spin_unlock(&tx_queue->lock);
}
 
-   netif_tx_lock_bh(tp->netdev);
+   netif_tx_lock(tp->netdev);
 
if (netif_queue_stopped(tp->netdev) &&
skb_queue_len(&tp->tx_queue) < tp->tx_qlen)
netif_wake_queue(tp->netdev);
 
-   netif_tx_unlock_bh(tp->netdev);
+   netif_tx_unlock(tp->netdev);
 
-   ret = usb_autopm_get_interface(tp->intf);
+   ret = usb_autopm_get_interface_async(tp->intf);
if (ret < 0)
goto out_tx_fill;
 
@@ -1395,9 +1396,9 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct 
tx_agg *agg)
  agg->head, (int)(tx_data - (u8 *)agg->head),
  (usb_complete_t)write_bulk_callback, agg);
 
-   ret = usb_submit_urb(agg->urb, GFP_KERNEL);
+   ret = usb_submit_urb(agg->urb, GFP_ATOMIC);
if (ret < 0)
-   usb_autopm_put_interface(tp->intf);
+   usb_autopm_put_interface_async(tp->intf);
 
 out_tx_fill:
return ret;
@@ -1535,6 +1536,7 @@ static void bottom_half(unsigned long data)
return;
 
rx_bottom(tp);
+   tx_bottom(tp);
 }
 
 static
@@ -1630,7 +1632,7 @@ static void _rtl8152_set_rx_mode(struct net_device 
*netdev)
 }
 
 static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb,
-   struct net_device *netdev)
+   struct net_device *netdev)
 {
struct r8152 *tp = netdev_priv(netdev);
 
@@ -1638,13 +1640,17 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff 
*skb,
 
skb_queue_tail(&tp->tx_queue, skb);
 
-   if (list_empty(&tp->tx_free) &&
-   skb_queue_len(&tp->tx_queue) > tp->tx_qlen)
+   if (!list_empty(&tp->tx_free)) {
+   if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
+   set_bit(SCHEDULE_TASKLET, &tp->flags);
+   schedule_delayed_work(&tp->schedule, 0);
+   } else {
+   usb_mark_last_busy(tp->udev);
+   tasklet_schedule(&tp->tl);
+   }
+   } else if (skb_queue_len(&tp->tx_queue) > tp->tx_qlen)
netif_stop_queue(netdev);
 
-   if (!list_empty(&tp->tx_free))
-   schedule_delayed_work(&tp->schedule, 0);
-
return NETDEV_TX_OK;
 }
 
@@ -2523,8 +2529,11 @@ static void rtl_work_func_t(struct work_struct *work)
if (test_bit(RTL8152_SET_RX_MODE, &tp->flags))
_rtl8152_set_rx_mode(tp->netdev);
 
-   if (tp->speed & LINK_STATUS)
-   tx_bottom(tp);
+   if (test_bit(SCHEDULE_TASKLET, &tp->flags) &&
+   (tp->speed & LINK_STATUS)) {
+   clear_bit(SCHEDULE_TASKLET, &tp->flags);
+   tasklet_schedule(&tp->tl);
+   }
 
if (test_bit(PHY_RESET, &tp->flags))
rtl_phy_reset(tp);
-- 
1.8.4.2

--
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 net-next 1/7] r8152: replace spin_lock_irqsave and spin_unlock_irqrestore

2014-03-06 Thread Hayes Wang
Use spin_lock and spin_unlock in interrupt context.

The ndo_start_xmit would not be called in interrupt context, so
replace the relative spin_lock_irqsave and spin_unlock_irqrestore
with spin_lock_bh and spin_unlock_bh.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 28 
 1 file changed, 12 insertions(+), 16 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index b8eee36..8ecb41b 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -963,7 +963,6 @@ static int rtl8152_set_mac_address(struct net_device 
*netdev, void *p)
 static void read_bulk_callback(struct urb *urb)
 {
struct net_device *netdev;
-   unsigned long flags;
int status = urb->status;
struct rx_agg *agg;
struct r8152 *tp;
@@ -997,9 +996,9 @@ static void read_bulk_callback(struct urb *urb)
if (urb->actual_length < ETH_ZLEN)
break;
 
-   spin_lock_irqsave(&tp->rx_lock, flags);
+   spin_lock(&tp->rx_lock);
list_add_tail(&agg->list, &tp->rx_done);
-   spin_unlock_irqrestore(&tp->rx_lock, flags);
+   spin_unlock(&tp->rx_lock);
tasklet_schedule(&tp->tl);
return;
case -ESHUTDOWN:
@@ -1022,9 +1021,9 @@ static void read_bulk_callback(struct urb *urb)
if (result == -ENODEV) {
netif_device_detach(tp->netdev);
} else if (result) {
-   spin_lock_irqsave(&tp->rx_lock, flags);
+   spin_lock(&tp->rx_lock);
list_add_tail(&agg->list, &tp->rx_done);
-   spin_unlock_irqrestore(&tp->rx_lock, flags);
+   spin_unlock(&tp->rx_lock);
tasklet_schedule(&tp->tl);
}
 }
@@ -1033,7 +1032,6 @@ static void write_bulk_callback(struct urb *urb)
 {
struct net_device_stats *stats;
struct net_device *netdev;
-   unsigned long flags;
struct tx_agg *agg;
struct r8152 *tp;
int status = urb->status;
@@ -1057,9 +1055,9 @@ static void write_bulk_callback(struct urb *urb)
stats->tx_bytes += agg->skb_len;
}
 
-   spin_lock_irqsave(&tp->tx_lock, flags);
+   spin_lock(&tp->tx_lock);
list_add_tail(&agg->list, &tp->tx_free);
-   spin_unlock_irqrestore(&tp->tx_lock, flags);
+   spin_unlock(&tp->tx_lock);
 
usb_autopm_put_interface_async(tp->intf);
 
@@ -1330,14 +1328,13 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, 
struct sk_buff *skb)
 static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
 {
struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
-   unsigned long flags;
int remain, ret;
u8 *tx_data;
 
__skb_queue_head_init(&skb_head);
-   spin_lock_irqsave(&tx_queue->lock, flags);
+   spin_lock_bh(&tx_queue->lock);
skb_queue_splice_init(tx_queue, &skb_head);
-   spin_unlock_irqrestore(&tx_queue->lock, flags);
+   spin_unlock_bh(&tx_queue->lock);
 
tx_data = agg->head;
agg->skb_num = agg->skb_len = 0;
@@ -1374,9 +1371,9 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct 
tx_agg *agg)
}
 
if (!skb_queue_empty(&skb_head)) {
-   spin_lock_irqsave(&tx_queue->lock, flags);
+   spin_lock_bh(&tx_queue->lock);
skb_queue_splice(&skb_head, tx_queue);
-   spin_unlock_irqrestore(&tx_queue->lock, flags);
+   spin_unlock_bh(&tx_queue->lock);
}
 
netif_tx_lock_bh(tp->netdev);
@@ -1551,16 +1548,15 @@ static void rtl_drop_queued_tx(struct r8152 *tp)
 {
struct net_device_stats *stats = &tp->netdev->stats;
struct sk_buff_head skb_head, *tx_queue = &tp->tx_queue;
-   unsigned long flags;
struct sk_buff *skb;
 
if (skb_queue_empty(tx_queue))
return;
 
__skb_queue_head_init(&skb_head);
-   spin_lock_irqsave(&tx_queue->lock, flags);
+   spin_lock_bh(&tx_queue->lock);
skb_queue_splice_init(tx_queue, &skb_head);
-   spin_unlock_irqrestore(&tx_queue->lock, flags);
+   spin_unlock_bh(&tx_queue->lock);
 
while ((skb = __skb_dequeue(&skb_head))) {
dev_kfree_skb(skb);
-- 
1.8.4.2

--
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 net-next 0/7] r8152: tx/rx improvement

2014-03-06 Thread Hayes Wang
 - Select the suitable spin lock for each function.
 - Add additional check to reduce the spin lock.
 - Up the priority of the tx to avoid interrupted by rx.
 - Support rx checksum, large send, and IPv6 hw checksum.

Hayes Wang (7):
  r8152: replace spin_lock_irqsave and spin_unlock_irqrestore
  r8152: check tx agg list before spin lock
  r8152: up the priority of the transmission
  r8152: calculate the dropped packets for rx
  r8152: support rx checksum
  r8152: support TSO
  r8152: support IPv6

 drivers/net/usb/r8152.c | 323 +++-
 1 file changed, 263 insertions(+), 60 deletions(-)

-- 
1.8.4.2

--
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 net-next 4/7] r8152: calculate the dropped packets for rx

2014-03-06 Thread Hayes Wang
Continue dealing with the remain rx packets, even though the allocation
of the skb fail. This could calculate the correct dropped packets.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index f1eaa18..08f4e870 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1456,7 +1456,7 @@ static void rx_bottom(struct r8152 *tp)
skb = netdev_alloc_skb_ip_align(netdev, pkt_len);
if (!skb) {
stats->rx_dropped++;
-   break;
+   goto find_next_rx;
}
memcpy(skb->data, rx_data, pkt_len);
skb_put(skb, pkt_len);
@@ -1465,6 +1465,7 @@ static void rx_bottom(struct r8152 *tp)
stats->rx_packets++;
stats->rx_bytes += pkt_len;
 
+find_next_rx:
rx_data = rx_agg_align(rx_data + pkt_len + CRC_SIZE);
rx_desc = (struct rx_desc *)rx_data;
len_used = (int)(rx_data - (u8 *)agg->head);
-- 
1.8.4.2

--
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 net-next 5/7] r8152: support rx checksum

2014-03-06 Thread Hayes Wang
Support hw rx checksum for TCP and UDP packets.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 41 +++--
 1 file changed, 39 insertions(+), 2 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 08f4e870..8bb8782 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -467,8 +467,17 @@ enum rtl8152_flags {
 struct rx_desc {
__le32 opts1;
 #define RX_LEN_MASK0x7fff
+
__le32 opts2;
+#define RD_UDP_CS  (1 << 23)
+#define RD_TCP_CS  (1 << 22)
+#define RD_IPV4_CS (1 << 19)
+
__le32 opts3;
+#define IPF(1 << 23) /* IP checksum fail */
+#define UDPF   (1 << 22) /* UDP checksum fail */
+#define TCPF   (1 << 21) /* TCP checksum fail */
+
__le32 opts4;
__le32 opts5;
__le32 opts6;
@@ -1404,6 +1413,32 @@ out_tx_fill:
return ret;
 }
 
+static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
+{
+   u8 checksum = CHECKSUM_NONE;
+   u32 opts2, opts3;
+
+   if (tp->version == RTL_VER_01)
+   goto return_result;
+
+   opts2 = le32_to_cpu(rx_desc->opts2);
+   opts3 = le32_to_cpu(rx_desc->opts3);
+
+   if (opts2 & RD_IPV4_CS) {
+   if (opts3 & IPF)
+   checksum = CHECKSUM_NONE;
+   else if ((opts2 & RD_UDP_CS) && (opts3 & UDPF))
+   checksum = CHECKSUM_NONE;
+   else if ((opts2 & RD_TCP_CS) && (opts3 & TCPF))
+   checksum = CHECKSUM_NONE;
+   else
+   checksum = CHECKSUM_UNNECESSARY;
+   }
+
+return_result:
+   return checksum;
+}
+
 static void rx_bottom(struct r8152 *tp)
 {
unsigned long flags;
@@ -1458,6 +1493,8 @@ static void rx_bottom(struct r8152 *tp)
stats->rx_dropped++;
goto find_next_rx;
}
+
+   skb->ip_summed = r8152_rx_csum(tp, rx_desc);
memcpy(skb->data, rx_data, pkt_len);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, netdev);
@@ -3103,8 +3140,8 @@ static int rtl8152_probe(struct usb_interface *intf,
netdev->netdev_ops = &rtl8152_netdev_ops;
netdev->watchdog_timeo = RTL8152_TX_TIMEOUT;
 
-   netdev->features |= NETIF_F_IP_CSUM;
-   netdev->hw_features = NETIF_F_IP_CSUM;
+   netdev->features |= NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
+   netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_IP_CSUM;
 
SET_ETHTOOL_OPS(netdev, &ops);
 
-- 
1.8.4.2

--
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 net-next 6/7] r8152: support TSO

2014-03-06 Thread Hayes Wang
Support scatter gather and TSO.

Adjust the tx checksum function and set the max gso size to fix the
size of the tx aggregation buffer.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 117 +++-
 1 file changed, 87 insertions(+), 30 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 8bb8782..b23b2ae 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -23,7 +23,7 @@
 #include 
 
 /* Version Information */
-#define DRIVER_VERSION "v1.05.0 (2014/02/18)"
+#define DRIVER_VERSION "v1.06.0 (2014/03/03)"
 #define DRIVER_AUTHOR "Realtek linux nic maintainers "
 #define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
 #define MODULENAME "r8152"
@@ -487,13 +487,18 @@ struct tx_desc {
__le32 opts1;
 #define TX_FS  (1 << 31) /* First segment of a packet */
 #define TX_LS  (1 << 30) /* Final segment of a packet */
-#define TX_LEN_MASK0x3
+#define GTSENDV4   (1 << 28)
+#define GTTCPHO_SHIFT  18
+#define TX_LEN_MAX 0x3U
 
__le32 opts2;
 #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */
 #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */
 #define IPV4_CS(1 << 29) /* Calculate IPv4 checksum */
 #define IPV6_CS(1 << 28) /* Calculate IPv6 checksum */
+#define MSS_SHIFT  17
+#define MSS_MAX0x7ffU
+#define TCPHO_SHIFT17
 };
 
 struct r8152;
@@ -560,12 +565,21 @@ enum rtl_version {
RTL_VER_MAX
 };
 
+enum tx_csum_stat {
+   TX_CSUM_SUCCESS = 0,
+   TX_CSUM_TSO,
+   TX_CSUM_NONE
+};
+
 /* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
  * The RTL chips use a 64 element hash table based on the Ethernet CRC.
  */
 static const int multicast_filter_limit = 32;
 static unsigned int rx_buf_sz = 16384;
 
+#define RTL_LIMITED_TSO_SIZE   (rx_buf_sz - sizeof(struct tx_desc) - \
+VLAN_ETH_HLEN - VLAN_HLEN)
+
 static
 int get_registers(struct r8152 *tp, u16 value, u16 index, u16 size, void *data)
 {
@@ -1292,24 +1306,46 @@ static struct tx_agg *r8152_get_tx_agg(struct r8152 *tp)
return agg;
 }
 
-static void
-r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb)
+static inline __be16 get_protocol(struct sk_buff *skb)
 {
-   memset(desc, 0, sizeof(*desc));
+   __be16 protocol;
 
-   desc->opts1 = cpu_to_le32((skb->len & TX_LEN_MASK) | TX_FS | TX_LS);
+   if (skb->protocol == htons(ETH_P_8021Q))
+   protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
+   else
+   protocol = skb->protocol;
 
-   if (skb->ip_summed == CHECKSUM_PARTIAL) {
-   __be16 protocol;
-   u8 ip_protocol;
-   u32 opts2 = 0;
+   return protocol;
+}
 
-   if (skb->protocol == htons(ETH_P_8021Q))
-   protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto;
-   else
-   protocol = skb->protocol;
+static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
+struct sk_buff *skb, u32 len, u32 transport_offset)
+{
+   u32 mss = skb_shinfo(skb)->gso_size;
+   u32 opts1, opts2 = 0;
+   int ret = TX_CSUM_SUCCESS;
+
+   WARN_ON_ONCE(len > TX_LEN_MAX);
+
+   opts1 = len | TX_FS | TX_LS;
+
+   if (mss) {
+   switch (get_protocol(skb)) {
+   case htons(ETH_P_IP):
+   opts1 |= GTSENDV4;
+   break;
+
+   default:
+   WARN_ON_ONCE(1);
+   break;
+   }
+
+   opts1 |= transport_offset << GTTCPHO_SHIFT;
+   opts2 |= min(mss, MSS_MAX) << MSS_SHIFT;
+   } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+   u8 ip_protocol;
 
-   switch (protocol) {
+   switch (get_protocol(skb)) {
case htons(ETH_P_IP):
opts2 |= IPV4_CS;
ip_protocol = ip_hdr(skb)->protocol;
@@ -1325,17 +1361,20 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, 
struct sk_buff *skb)
break;
}
 
-   if (ip_protocol == IPPROTO_TCP) {
+   if (ip_protocol == IPPROTO_TCP)
opts2 |= TCP_CS;
-   opts2 |= (skb_transport_offset(skb) & 0x7fff) << 17;
-   } else if (ip_protocol == IPPROTO_UDP) {
+   else if (ip_protocol == IPPROTO_UDP)
opts2 |= UDP_CS;
-   } else {
+   else
WARN_ON_ONCE(1);
-   }
 
-   desc->opts2 = cpu_to_le32(opts2);
+   opts2 |= transport_offset << TCPHO_SHIFT;
 

[PATCH net-next 7/7] r8152: support IPv6

2014-03-06 Thread Hayes Wang
Support hw IPv6 checksum for TCP and UDP packets.

Note that the hw has the limitation of the range of the transport
offset. Besides, the TCP Pseudo Header of the IPv6 TSO of the hw
bases on the Microsoft document which excludes the packet length.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 106 ++--
 1 file changed, 103 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index b23b2ae..c7ef30d 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /* Version Information */
 #define DRIVER_VERSION "v1.06.0 (2014/03/03)"
@@ -471,6 +472,7 @@ struct rx_desc {
__le32 opts2;
 #define RD_UDP_CS  (1 << 23)
 #define RD_TCP_CS  (1 << 22)
+#define RD_IPV6_CS (1 << 20)
 #define RD_IPV4_CS (1 << 19)
 
__le32 opts3;
@@ -488,7 +490,9 @@ struct tx_desc {
 #define TX_FS  (1 << 31) /* First segment of a packet */
 #define TX_LS  (1 << 30) /* Final segment of a packet */
 #define GTSENDV4   (1 << 28)
+#define GTSENDV6   (1 << 27)
 #define GTTCPHO_SHIFT  18
+#define GTTCPHO_MAX0x7fU
 #define TX_LEN_MAX 0x3U
 
__le32 opts2;
@@ -499,6 +503,7 @@ struct tx_desc {
 #define MSS_SHIFT  17
 #define MSS_MAX0x7ffU
 #define TCPHO_SHIFT17
+#define TCPHO_MAX  0x7ffU
 };
 
 struct r8152;
@@ -1318,6 +1323,69 @@ static inline __be16 get_protocol(struct sk_buff *skb)
return protocol;
 }
 
+/*
+ * r8152_csum_workaround()
+ * The hw limites the value the transport offset. When the offset is out of the
+ * range, calculate the checksum by sw.
+ */
+static void r8152_csum_workaround(struct r8152 *tp, struct sk_buff *skb,
+ struct sk_buff_head *list)
+{
+   if (skb_shinfo(skb)->gso_size) {
+   netdev_features_t features = tp->netdev->features;
+   struct sk_buff_head seg_list;
+   struct sk_buff *segs, *nskb;
+
+   features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
+   segs = skb_gso_segment(skb, features);
+   if (IS_ERR(segs) || !segs)
+   goto drop;
+
+   __skb_queue_head_init(&seg_list);
+
+   do {
+   nskb = segs;
+   segs = segs->next;
+   nskb->next = NULL;
+   __skb_queue_tail(&seg_list, nskb);
+   } while (segs);
+
+   skb_queue_splice(&seg_list, list);
+   dev_kfree_skb(skb);
+   } else if (skb->ip_summed == CHECKSUM_PARTIAL) {
+   if (skb_checksum_help(skb) < 0)
+   goto drop;
+
+   __skb_queue_head(list, skb);
+   } else {
+   struct net_device_stats *stats;
+
+drop:
+   stats = &tp->netdev->stats;
+   stats->tx_dropped++;
+   dev_kfree_skb(skb);
+   }
+}
+
+/*
+ * msdn_giant_send_check()
+ * According to the document of microsoft, the TCP Pseudo Header excludes the
+ * packet length for IPv6 TCP large packets.
+ */
+static int msdn_giant_send_check(struct sk_buff *skb)
+{
+   const struct ipv6hdr *ipv6h;
+   struct tcphdr *th;
+
+   ipv6h = ipv6_hdr(skb);
+   th = tcp_hdr(skb);
+
+   th->check = 0;
+   th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0);
+
+   return 0;
+}
+
 static int r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc,
 struct sk_buff *skb, u32 len, u32 transport_offset)
 {
@@ -1330,11 +1398,24 @@ static int r8152_tx_csum(struct r8152 *tp, struct 
tx_desc *desc,
opts1 = len | TX_FS | TX_LS;
 
if (mss) {
+   if (transport_offset > GTTCPHO_MAX) {
+   netif_warn(tp, tx_err, tp->netdev,
+  "Invalid transport offset 0x%x for TSO\n",
+  transport_offset);
+   ret = TX_CSUM_TSO;
+   goto unavailable;
+   }
+
switch (get_protocol(skb)) {
case htons(ETH_P_IP):
opts1 |= GTSENDV4;
break;
 
+   case htons(ETH_P_IPV6):
+   opts1 |= GTSENDV6;
+   msdn_giant_send_check(skb);
+   break;
+
default:
WARN_ON_ONCE(1);
break;
@@ -1345,6 +1426,14 @@ static int r8152_tx_csum(struct r8152 *tp, struct 
tx_desc *desc,
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
u8 ip_protocol;
 
+   if (transport_offset > TCPHO_MAX) {
+   netif_warn(tp, tx_

[PATCH net-next 2/7] r8152: check tx agg list before spin lock

2014-03-06 Thread Hayes Wang
Check tx agg list before spin lock to avoid doing spin lock every
times.

Signed-off-by: Hayes Wang 
---
 drivers/net/usb/r8152.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 8ecb41b..00b3192 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1266,6 +1266,9 @@ static struct tx_agg *r8152_get_tx_agg(struct r8152 *tp)
struct tx_agg *agg = NULL;
unsigned long flags;
 
+   if (list_empty(&tp->tx_free))
+   return NULL;
+
spin_lock_irqsave(&tp->tx_lock, flags);
if (!list_empty(&tp->tx_free)) {
struct list_head *cursor;
-- 
1.8.4.2

--
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: BUG: USB Reset-Resume Mechanism does not work for runtime resume

2014-03-06 Thread Peter Chen
On Thu, Mar 06, 2014 at 10:10:48AM +, Poulain, Loic wrote:
> I agree, but because it's possible to have many different hardware for the 
> same class driver, you can't predict if all of them will be not broken. So in 
> this case, each USB class driver should have the reset-resume callback.

It is better like this, since .reset-resume is only called when the
normal resume has failed.

> A broken device can be a device which doesn't resume correctly 1 time per 
> thousand (due to timing reason or anything else). Today, this single resume 
> failure is enough to stuck the device (suspended forever).
> because mobile systems are more and more PM agressive, I think we could see 
> this problem occurring more often.

Okay, so the question is we should use the heavy operation to rebind the
class driver at usb core or light operation to reset interface at class
driver? Yes, I agree with you, if the class driver does not supply
light operation like reset its internal fsm, then a heavy operation
like reload driver has to be used.

You can submit a patch to Alan, and see his comment.

> 
> Unbind/rebind is here as a fallback mechanism for drivers that don't know how 
> to restore device after resume failure, and it works pretty well for system 
> PM. For runtime PM, half of the work is done, interface is declared as 
> needs_rebind but never rebind. So either the rebind work should be completed 
> for PM runtime or an other solution found (logical disconnect, reset_resume 
> mandatory...). But I think this dead end should be fixed.
> 

Yes, a patch is welcome.

BTW, using community email style to reply next time please.

Peter

> Regards,
> Loic Poulain
> 
> From: Peter Chen [peter.c...@freescale.com]
> Sent: Thursday, March 06, 2014 2:10 AM
> To: Alan Stern
> Cc: Poulain, Loic; linux-usb@vger.kernel.org
> Subject: Re: BUG: USB Reset-Resume Mechanism does not work for runtime resume
> 
> On Wed, Mar 05, 2014 at 11:26:06AM -0500, Alan Stern wrote:
> > On Wed, 5 Mar 2014, Poulain, Loic wrote:
> >
> > > + function 'do_rebind_interface' is in charge of unbind and rebind the 
> > > interfaces with the 'need_binfind' flag set.
> > > + However this method is only called in 'usb_resume_complete'.
> > > + Problem is that 'usb_resume_complete' is a dev_pm_ops callback 
> > > (core/usb.h) used by the System PM core which is never called in a 
> > > runtime PM scenario.
> > > + So interfaces remain suspended forever (or until the next PM system 
> > > suspend/resume), device is unusable.
> > > (unbinding/rebinding manually the interface via sysfs recovers the device)
> > >
> > > Could you please let me know if it's the expected behavior or a real 
> > > issue. Should we not call 'do_rebind_interface' in the runtime resume 
> > > sequence?
> >
> > I suspect this is an oversight.
> >
> > Still, implementing it would be difficult.  In usb_runtime_resume, the
> > device lock may or may not already be held.  Therefore we cannot simply
> > lock the device and call do_rebind_interfaces.
> >
> > Using a work queue for this seems like overkill (and it seems fragile).
> > I don't know what we should do.
> >
> 
> If the autosuspend supported device can't respond resume correctly, eg,
> after resume, it can't respond GET_STATUS correctly in this case, the
> .reset_resume interface is a must for class driver, it just like a
> workaround for broken hardware.
> 
> --
> 
> Best Regards,
> Peter Chen
> 
> -
> Intel Corporation SAS (French simplified joint stock company)
> Registered headquarters: "Les Montalets"- 2, rue de Paris, 
> 92196 Meudon Cedex, France
> Registration Number:  302 456 199 R.C.S. NANTERRE
> Capital: 4,572,000 Euros
> 
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
> 
> 
> 

-- 

Best Regards,
Peter Chen

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


Re: usb modem not working on xhci host

2014-03-06 Thread vichy
hi Sarah and Greg:

2014-03-06 23:25 GMT+08:00 vichy :
> hi Greg:
>
> 2014-03-06 22:49 GMT+08:00 Greg KH :
>> On Thu, Mar 06, 2014 at 10:35:24PM +0800, vichy wrote:
>>> hi sarah:
>>> > Can you send me the output of `sudo lsusb -v` for when the device is
>>> > under EHCI and when it's under xHCI?  Also, please take a usbmon trace,
>>> > as described by
>>> > http://lxr.free-electrons.com/source/Documentation/usb/usbmon.txt
>>> >
>>> > Start the trace just before you plug the device in.  Take one trace when
>>> > the device under EHCI, and one when it's under xHCI.
>>> Please reference the attachment
>>>
>>> >
>>> >> Below is my host environment
>>> >
>>> > Which kernel are you running?
>>> Linux 3.13.0
>>
>> Please try 3.13.5, as a number of known USB .3 bugs have been fixed in
>> there since 3.13.0
1. I attach lsusb -v log fro xhci and ehci.
2. I try kernel 3.14.rc5 but xhci port still cannot enable modem successfully

thanks for your help,


ehci.xhci.lsusb.log.tar.bz2
Description: BZip2 compressed data


Re: [PATCHv3 0/4] usb: dwc2/s3c-hsotg: Move the s3c-hsotg driver into dwc2

2014-03-06 Thread Jingoo Han
On Friday, March 07, 2014 6:48 AM, Dinh Nguyen wrote:
> 
> From: Dinh Nguyen 
> 
> Diffs from V2:
> - Renamed s3c-hsotg.c to gadget.c
> - For dynamically linked modules, dwc2_gadget.ko is built for peripheral mode
>   and for host mode, it remains dwc2.ko and dwc2_platform.ko or dwc2_pci.ko.
> - Split out the patch to have 4 patches instead of 3. Patch 4 contains edits
>   to the Makefile(s) and Kconfig(s) only.
> - Addressed comments from Felipe Balbi.
> 
> I don't think I can add the Tested-by: Jingoo Han  to 
> this
> version as I have made changes on how the peripheral mode driver gets built. 
> So
> Jingoo, if you can please test this version, it would be appreciated.

Tested-by: Jingoo Han 

I tested these patches on Exynos4210 platform.
'gadget.c' aka 's3c-hsotg.c' works properly.
Thank you.

Best regards,
Jingoo Han

> 
> Thanks,
> 
> Dinh Nguyen (4):
>   usb: dwc2: Add defines to support the s3c-hsotg driver
>   usb: s3c-hsotg: Move s3c-hsotg into dwc2 folder
>   usb: s3c-hsotg: Move s3c-hsotg data structures
>   usb: dwc2: Edit the Kconfig and Makefile to build dwc2_gadget driver
> 
>  drivers/usb/dwc2/Kconfig  |   36 +-
>  drivers/usb/dwc2/Makefile |   27 +-
>  drivers/usb/dwc2/core.h   |  182 +++
>  drivers/usb/{gadget/s3c-hsotg.c => dwc2/gadget.c} |  593 
> +++--
>  drivers/usb/dwc2/hw.h |   12 +-
>  drivers/usb/gadget/Kconfig|7 -
>  drivers/usb/gadget/Makefile   |1 -
>  drivers/usb/gadget/s3c-hsotg.h|  378 -
>  8 files changed, 439 insertions(+), 797 deletions(-)
>  rename drivers/usb/{gadget/s3c-hsotg.c => dwc2/gadget.c} (85%)
>  delete mode 100644 drivers/usb/gadget/s3c-hsotg.h
> ---
> Cc: Greg Kroah-Hartman 
> Cc: Paul Zimmerman 
> Cc: Felipe Balbi 
> Cc: Ben Dooks 
> Cc: Matt Porter 
> Cc: Kukjin Kim 
> Cc: Stephen Warren 
> Cc: Matthijs Kooijman 
> Cc: Jingoo Han 
> Cc: Sachin Kamat 
> Cc: Robert Baldyga 
> --
> 1.7.9.5

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


Re: [PATCH] usbip:usbip_common.c: check return value of sscanf

2014-03-06 Thread Joe Perches
On Thu, 2014-03-06 at 15:51 -0800, John de la Garza wrote:
> Added code to check return value of sscanf.
[]
> diff --git a/drivers/staging/usbip/usbip_common.c 
> b/drivers/staging/usbip/usbip_common.c
[]
> @@ -55,7 +55,8 @@ static ssize_t usbip_debug_store(struct device *dev,
>struct device_attribute *attr, const char *buf,
>size_t count)
>  {
> - sscanf(buf, "%lx", &usbip_debug_flag);
> + if (sscanf(buf, "%lx", &usbip_debug_flag) != 1)
> + return -EINVAL;

Generally, it's probably better to convert these
sscanf uses to kstrto, kstrtoul in this case.


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


[PATCH 08/76] xhci: For streams the dequeue ptr must be read from the stream ctx

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This fixes TR dequeue validation failing on Intel XHCI controllers with the
following warning:

Mismatch between completed Set TR Deq Ptr command & xHCI internal state.

Interestingly enough reading the deq ptr from the ep ctx after a
TR Deq Ptr command does work on a Nec XHCI controller, it seems the Nec
writes the ptr to both the ep and stream contexts when streams are used.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-ring.c | 22 +++---
 drivers/usb/host/xhci.h  |  1 +
 2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f17e5c8c1cb3..b3d27e6467ea 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1081,12 +1081,14 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
unsigned int stream_id;
struct xhci_ring *ep_ring;
struct xhci_virt_device *dev;
+   struct xhci_virt_ep *ep;
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
 
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
dev = xhci->devs[slot_id];
+   ep = &dev->eps[ep_index];
 
ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id);
if (!ep_ring) {
@@ -1134,12 +1136,19 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
 * cancelling URBs, which might not be an error...
 */
} else {
+   u64 deq;
+   /* 4.6.10 deq ptr is written to the stream ctx for streams */
+   if (ep->ep_state & EP_HAS_STREAMS) {
+   struct xhci_stream_ctx *ctx =
+   &ep->stream_info->stream_ctx_array[stream_id];
+   deq = le64_to_cpu(ctx->stream_ring) & SCTX_DEQ_MASK;
+   } else {
+   deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
+   }
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-   "Successful Set TR Deq Ptr cmd, deq = @%08llx",
-le64_to_cpu(ep_ctx->deq));
-   if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg,
-dev->eps[ep_index].queued_deq_ptr) ==
-   (le64_to_cpu(ep_ctx->deq) & ~(EP_CTX_CYCLE_MASK))) {
+   "Successful Set TR Deq Ptr cmd, deq = @%08llx", deq);
+   if (xhci_trb_virt_to_dma(ep->queued_deq_seg,
+ep->queued_deq_ptr) == deq) {
/* Update the ring's dequeue segment and dequeue pointer
 * to reflect the new position.
 */
@@ -1148,8 +1157,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
} else {
xhci_warn(xhci, "Mismatch between completed Set TR Deq 
Ptr command & xHCI internal state.\n");
xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
-   dev->eps[ep_index].queued_deq_seg,
-   dev->eps[ep_index].queued_deq_ptr);
+ ep->queued_deq_seg, ep->queued_deq_ptr);
}
}
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 2c77bf7ab9e5..d280e9213d08 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -703,6 +703,7 @@ struct xhci_ep_ctx {
 
 /* deq bitmasks */
 #define EP_CTX_CYCLE_MASK  (1 << 0)
+#define SCTX_DEQ_MASK  (~0xfL)
 
 
 /**
-- 
1.8.5.5

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


[PATCH 03/76] xhci: fix usb3 streams

2014-03-06 Thread Sarah Sharp
From: Gerd Hoffmann 

xhci maintains a radix tree for each stream endpoint because it must
be able to map a trb address to the stream ring.  Each ring segment
must be added to the ring for this to work.  Currently xhci sticks
only the first segment of each stream ring into the radix tree.

Result is that things work initially, but as soon as the first segment
is full xhci can't map the trb address from the completion event to the
stream ring any more -> BOOM.  You'll find this message in the logs:

  ERROR Transfer event for disabled endpoint or incorrect stream ring

This patch adds a helper function to update the radix tree, and a
function to remove ring segments from the tree.  Both functions loop
over the segment list and handles all segments instead of just the
first.

[Note: Sarah changed this patch to add radix_tree_maybe_preload() and
radix_tree_preload_end() calls around the radix tree insert, since we
can now insert entries in interrupt context.  There are now two helper
functions to make the code cleaner, and those functions are moved to
make them static.]

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-mem.c | 132 +---
 drivers/usb/host/xhci.h |   1 +
 2 files changed, 90 insertions(+), 43 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index bce4391a0e7d..39f9a99a503b 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -149,14 +149,95 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct 
xhci_ring *ring,
}
 }
 
+/*
+ * We need a radix tree for mapping physical addresses of TRBs to which stream
+ * ID they belong to.  We need to do this because the host controller won't 
tell
+ * us which stream ring the TRB came from.  We could store the stream ID in an
+ * event data TRB, but that doesn't help us for the cancellation case, since 
the
+ * endpoint may stop before it reaches that event data TRB.
+ *
+ * The radix tree maps the upper portion of the TRB DMA address to a ring
+ * segment that has the same upper portion of DMA addresses.  For example, say 
I
+ * have segments of size 1KB, that are always 64-byte aligned.  A segment may
+ * start at 0x10c91000 and end at 0x10c913f0.  If I use the upper 10 bits, the
+ * key to the stream ID is 0x43244.  I can use the DMA address of the TRB to
+ * pass the radix tree a key to get the right stream ID:
+ *
+ * 0x10c90fff >> 10 = 0x43243
+ * 0x10c912c0 >> 10 = 0x43244
+ * 0x10c91400 >> 10 = 0x43245
+ *
+ * Obviously, only those TRBs with DMA addresses that are within the segment
+ * will make the radix tree return the stream ID for that ring.
+ *
+ * Caveats for the radix tree:
+ *
+ * The radix tree uses an unsigned long as a key pair.  On 32-bit systems, an
+ * unsigned long will be 32-bits; on a 64-bit system an unsigned long will be
+ * 64-bits.  Since we only request 32-bit DMA addresses, we can use that as the
+ * key on 32-bit or 64-bit systems (it would also be fine if we asked for 
64-bit
+ * PCI DMA addresses on a 64-bit system).  There might be a problem on 32-bit
+ * extended systems (where the DMA address can be bigger than 32-bits),
+ * if we allow the PCI dma mask to be bigger than 32-bits.  So don't do that.
+ */
+static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
+{
+   struct xhci_segment *seg;
+   unsigned long key;
+   int ret;
+
+   if (WARN_ON_ONCE(ring->trb_address_map == NULL))
+   return 0;
+
+   seg = ring->first_seg;
+   do {
+   key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
+   /* Skip any segments that were already added. */
+   if (radix_tree_lookup(ring->trb_address_map, key))
+   continue;
+
+   ret = radix_tree_maybe_preload(mem_flags);
+   if (ret)
+   return ret;
+   ret = radix_tree_insert(ring->trb_address_map,
+   key, ring);
+   radix_tree_preload_end();
+   if (ret)
+   return ret;
+   seg = seg->next;
+   } while (seg != ring->first_seg);
+
+   return 0;
+}
+
+static void xhci_remove_stream_mapping(struct xhci_ring *ring)
+{
+   struct xhci_segment *seg;
+   unsigned long key;
+
+   if (WARN_ON_ONCE(ring->trb_address_map == NULL))
+   return;
+
+   seg = ring->first_seg;
+   do {
+   key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
+   if (radix_tree_lookup(ring->trb_address_map, key))
+   radix_tree_delete(ring->trb_address_map, key);
+   seg = seg->next;
+   } while (seg != ring->first_seg);
+}
+
 /* XXX: Do we need the hcd structure in all these functions? */
 void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
 {
if (!ring

[PATCH 15/76] usbfs: Kill urbs on interface before doing a set_interface

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The usb_set_interface documentation says:

 * Also, drivers must not change altsettings while urbs are scheduled for
 * endpoints in that interface; all such urbs must first be completed
 * (perhaps forced by unlinking).

For in kernel drivers we trust the drivers to get this right, but we
cannot trust userspace to get this right, so enforce it by killing any
urbs still pending on the interface.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/devio.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index f3ba2e076ee3..2a95e4e574bb 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1143,6 +1143,9 @@ static int proc_setintf(struct dev_state *ps, void __user 
*arg)
return -EFAULT;
if ((ret = checkintf(ps, setintf.interface)))
return ret;
+
+   destroy_async_on_interface(ps, setintf.interface);
+
return usb_set_interface(ps->dev, setintf.interface,
setintf.altsetting);
 }
-- 
1.8.5.5

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


[PATCH 12/76] usb-core: Move USB_MAXENDPOINTS definitions to usb.h

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

So that it can be used in other places too.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/config.c | 1 -
 include/linux/usb.h   | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 8d72f0c65937..14ba398d6def 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -10,7 +10,6 @@
 
 
 #define USB_MAXALTSETTING  128 /* Hard limit */
-#define USB_MAXENDPOINTS   30  /* Hard limit */
 
 #define USB_MAXCONFIG  8   /* Arbitrary limit */
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 7f6eb859873e..9b73dd782c09 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -202,6 +202,8 @@ static inline void usb_set_intfdata(struct usb_interface 
*intf, void *data)
 struct usb_interface *usb_get_intf(struct usb_interface *intf);
 void usb_put_intf(struct usb_interface *intf);
 
+/* Hard limit */
+#define USB_MAXENDPOINTS   30
 /* this maximum is arbitrary */
 #define USB_MAXINTERFACES  32
 #define USB_MAXIADS(USB_MAXINTERFACES/2)
-- 
1.8.5.5

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


[PATCH 20/76] uas: properly reinitialize in uas_eh_bus_reset_handler

2014-03-06 Thread Sarah Sharp
From: Gerd Hoffmann 

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index d966b59f7d7b..fc08ee919439 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -85,6 +85,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo, gfp_t gfp);
 static void uas_do_work(struct work_struct *work);
 static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
+static void uas_configure_endpoints(struct uas_dev_info *devinfo);
+static void uas_free_streams(struct uas_dev_info *devinfo);
 
 static DECLARE_WORK(uas_work, uas_do_work);
 static DEFINE_SPINLOCK(uas_work_lock);
@@ -800,7 +802,10 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
usb_kill_anchored_urbs(&devinfo->cmd_urbs);
usb_kill_anchored_urbs(&devinfo->sense_urbs);
usb_kill_anchored_urbs(&devinfo->data_urbs);
+   uas_free_streams(devinfo);
err = usb_reset_device(udev);
+   if (!err)
+   uas_configure_endpoints(devinfo);
devinfo->resetting = 0;
 
if (err) {
-- 
1.8.5.5

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


[PATCH 13/76] usb-core: Track if an endpoint has streams

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This is a preparation patch for adding support for bulk streams to usbfs.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/hcd.c | 34 ++
 include/linux/usb.h|  2 ++
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 9b445f43f825..9c4e2922b04d 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2049,7 +2049,7 @@ int usb_alloc_streams(struct usb_interface *interface,
 {
struct usb_hcd *hcd;
struct usb_device *dev;
-   int i;
+   int i, ret;
 
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
@@ -2058,13 +2058,24 @@ int usb_alloc_streams(struct usb_interface *interface,
if (dev->speed != USB_SPEED_SUPER)
return -EINVAL;
 
-   /* Streams only apply to bulk endpoints. */
-   for (i = 0; i < num_eps; i++)
+   for (i = 0; i < num_eps; i++) {
+   /* Streams only apply to bulk endpoints. */
if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
return -EINVAL;
+   /* Re-alloc is not allowed */
+   if (eps[i]->streams)
+   return -EINVAL;
+   }
 
-   return hcd->driver->alloc_streams(hcd, dev, eps, num_eps,
+   ret = hcd->driver->alloc_streams(hcd, dev, eps, num_eps,
num_streams, mem_flags);
+   if (ret < 0)
+   return ret;
+
+   for (i = 0; i < num_eps; i++)
+   eps[i]->streams = ret;
+
+   return ret;
 }
 EXPORT_SYMBOL_GPL(usb_alloc_streams);
 
@@ -2086,19 +2097,26 @@ int usb_free_streams(struct usb_interface *interface,
 {
struct usb_hcd *hcd;
struct usb_device *dev;
-   int i;
+   int i, ret;
 
dev = interface_to_usbdev(interface);
hcd = bus_to_hcd(dev->bus);
if (dev->speed != USB_SPEED_SUPER)
return -EINVAL;
 
-   /* Streams only apply to bulk endpoints. */
+   /* Double-free is not allowed */
for (i = 0; i < num_eps; i++)
-   if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
+   if (!eps[i] || !eps[i]->streams)
return -EINVAL;
 
-   return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
+   ret = hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
+   if (ret < 0)
+   return ret;
+
+   for (i = 0; i < num_eps; i++)
+   eps[i]->streams = 0;
+
+   return ret;
 }
 EXPORT_SYMBOL_GPL(usb_free_streams);
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 9b73dd782c09..f1015cee5944 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -57,6 +57,7 @@ struct ep_device;
  * @extra: descriptors following this endpoint in the configuration
  * @extralen: how many bytes of "extra" are valid
  * @enabled: URBs may be submitted to this endpoint
+ * @streams: number of USB-3 streams allocated on the endpoint
  *
  * USB requests are always queued to a given endpoint, identified by a
  * descriptor within an active interface in a given USB configuration.
@@ -71,6 +72,7 @@ struct usb_host_endpoint {
unsigned char *extra;   /* Extra descriptors */
int extralen;
int enabled;
+   int streams;
 };
 
 /* host-side wrapper for one interface setting's parsed descriptors */
-- 
1.8.5.5

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


[PATCH 05/76] xhci: Check size rather then number of streams when allocating stream ctxs

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Before this a device needing ie 32 stream ctxs would end up with an entry from
the small_streams_pool which has 256 bytes entries, where as 32 stream ctxs
need 512 bytes. Things actually keep running for a surprisingly long time
before crashing because of this.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-mem.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 39f9a99a503b..be7b7b6b5517 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -520,12 +520,12 @@ static void xhci_free_stream_ctx(struct xhci_hcd *xhci,
struct xhci_stream_ctx *stream_ctx, dma_addr_t dma)
 {
struct device *dev = xhci_to_hcd(xhci)->self.controller;
+   size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs;
 
-   if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE)
-   dma_free_coherent(dev,
-   sizeof(struct xhci_stream_ctx)*num_stream_ctxs,
+   if (size > MEDIUM_STREAM_ARRAY_SIZE)
+   dma_free_coherent(dev, size,
stream_ctx, dma);
-   else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE)
+   else if (size <= SMALL_STREAM_ARRAY_SIZE)
return dma_pool_free(xhci->small_streams_pool,
stream_ctx, dma);
else
@@ -548,12 +548,12 @@ static struct xhci_stream_ctx 
*xhci_alloc_stream_ctx(struct xhci_hcd *xhci,
gfp_t mem_flags)
 {
struct device *dev = xhci_to_hcd(xhci)->self.controller;
+   size_t size = sizeof(struct xhci_stream_ctx) * num_stream_ctxs;
 
-   if (num_stream_ctxs > MEDIUM_STREAM_ARRAY_SIZE)
-   return dma_alloc_coherent(dev,
-   sizeof(struct xhci_stream_ctx)*num_stream_ctxs,
+   if (size > MEDIUM_STREAM_ARRAY_SIZE)
+   return dma_alloc_coherent(dev, size,
dma, mem_flags);
-   else if (num_stream_ctxs <= SMALL_STREAM_ARRAY_SIZE)
+   else if (size <= SMALL_STREAM_ARRAY_SIZE)
return dma_pool_alloc(xhci->small_streams_pool,
mem_flags, dma);
else
-- 
1.8.5.5

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


[PATCH 23/76] uas: replace BUG_ON() + WARN_ON() with WARN_ON_ONCE()

2014-03-06 Thread Sarah Sharp
From: Gerd Hoffmann 

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index f0490382351d..046eedfc3828 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -154,7 +154,7 @@ static void uas_abort_work(struct uas_dev_info *devinfo)
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
uas_log_cmd_state(cmnd, __func__);
-   WARN_ON(cmdinfo->state & COMMAND_ABORTED);
+   WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
cmdinfo->state |= COMMAND_ABORTED;
cmdinfo->state &= ~IS_IN_WORK_LIST;
list_del(&cmdinfo->work);
@@ -169,7 +169,7 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
struct uas_dev_info *devinfo = cmnd->device->hostdata;
 
-   WARN_ON(!spin_is_locked(&devinfo->lock));
+   WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
list_add_tail(&cmdinfo->work, &devinfo->work_list);
cmdinfo->state |= IS_IN_WORK_LIST;
schedule_work(&devinfo->work);
@@ -187,7 +187,7 @@ static void uas_zap_dead(struct uas_dev_info *devinfo)
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
uas_log_cmd_state(cmnd, __func__);
-   WARN_ON(!(cmdinfo->state & COMMAND_ABORTED));
+   WARN_ON_ONCE(!(cmdinfo->state & COMMAND_ABORTED));
/* all urbs are killed, clear inflight bits */
cmdinfo->state &= ~(COMMAND_INFLIGHT |
DATA_IN_URB_INFLIGHT |
@@ -271,13 +271,13 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const 
char *caller)
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
 
-   WARN_ON(!spin_is_locked(&devinfo->lock));
+   WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
if (cmdinfo->state & (COMMAND_INFLIGHT |
  DATA_IN_URB_INFLIGHT |
  DATA_OUT_URB_INFLIGHT |
  UNLINK_DATA_URBS))
return -EBUSY;
-   BUG_ON(cmdinfo->state & COMMAND_COMPLETED);
+   WARN_ON_ONCE(cmdinfo->state & COMMAND_COMPLETED);
cmdinfo->state |= COMMAND_COMPLETED;
usb_free_urb(cmdinfo->data_in_urb);
usb_free_urb(cmdinfo->data_out_urb);
@@ -398,8 +398,9 @@ static void uas_data_cmplt(struct urb *urb)
sdb = scsi_out(cmnd);
cmdinfo->state &= ~DATA_OUT_URB_INFLIGHT;
}
-   BUG_ON(sdb == NULL);
-   if (urb->status) {
+   if (sdb == NULL) {
+   WARN_ON_ONCE(1);
+   } else if (urb->status) {
/* error: no data transfered */
sdb->resid = sdb->length;
} else {
@@ -573,7 +574,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
int err;
 
-   WARN_ON(!spin_is_locked(&devinfo->lock));
+   WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
if (cmdinfo->state & SUBMIT_STATUS_URB) {
err = uas_submit_sense_urb(cmnd->device->host, gfp,
   cmdinfo->stream);
@@ -771,7 +772,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
 
uas_log_cmd_state(cmnd, __func__);
spin_lock_irqsave(&devinfo->lock, flags);
-   WARN_ON(cmdinfo->state & COMMAND_ABORTED);
+   WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
cmdinfo->state |= COMMAND_ABORTED;
list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
if (cmdinfo->state & IS_IN_WORK_LIST) {
-- 
1.8.5.5

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


[PATCH 16/76] usbfs: proc_do_submiturb use a local variable for number_of_packets

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This is a preparation patch for adding support for bulk streams.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/devio.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 2a95e4e574bb..c88d8bfaca8d 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1208,6 +1208,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
int i, ret, is_in, num_sgs = 0, ifnum = -1;
+   int number_of_packets = 0;
void *buf;
 
if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
@@ -1261,7 +1262,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
  le16_to_cpup(&dr->wIndex));
if (ret)
goto error;
-   uurb->number_of_packets = 0;
uurb->buffer_length = le16_to_cpup(&dr->wLength);
uurb->buffer += 8;
if ((dr->bRequestType & USB_DIR_IN) && uurb->buffer_length) {
@@ -1291,7 +1291,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
uurb->type = USBDEVFS_URB_TYPE_INTERRUPT;
goto interrupt_urb;
}
-   uurb->number_of_packets = 0;
num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);
if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize)
num_sgs = 0;
@@ -1301,7 +1300,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
if (!usb_endpoint_xfer_int(&ep->desc))
return -EINVAL;
  interrupt_urb:
-   uurb->number_of_packets = 0;
break;
 
case USBDEVFS_URB_TYPE_ISO:
@@ -1311,15 +1309,16 @@ static int proc_do_submiturb(struct dev_state *ps, 
struct usbdevfs_urb *uurb,
return -EINVAL;
if (!usb_endpoint_xfer_isoc(&ep->desc))
return -EINVAL;
+   number_of_packets = uurb->number_of_packets;
isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) *
-  uurb->number_of_packets;
+  number_of_packets;
if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
return -ENOMEM;
if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
ret = -EFAULT;
goto error;
}
-   for (totlen = u = 0; u < uurb->number_of_packets; u++) {
+   for (totlen = u = 0; u < number_of_packets; u++) {
/*
 * arbitrary limit need for USB 3.0
 * bMaxBurst (0~15 allowed, 1~16 packets)
@@ -1350,7 +1349,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
ret = -EFAULT;
goto error;
}
-   as = alloc_async(uurb->number_of_packets);
+   as = alloc_async(number_of_packets);
if (!as) {
ret = -ENOMEM;
goto error;
@@ -1444,7 +1443,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
as->urb->setup_packet = (unsigned char *)dr;
dr = NULL;
as->urb->start_frame = uurb->start_frame;
-   as->urb->number_of_packets = uurb->number_of_packets;
+   as->urb->number_of_packets = number_of_packets;
if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
ps->dev->speed == USB_SPEED_HIGH)
as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
@@ -1452,7 +1451,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
as->urb->interval = ep->desc.bInterval;
as->urb->context = as;
as->urb->complete = async_completed;
-   for (totlen = u = 0; u < uurb->number_of_packets; u++) {
+   for (totlen = u = 0; u < number_of_packets; u++) {
as->urb->iso_frame_desc[u].offset = totlen;
as->urb->iso_frame_desc[u].length = isopkt[u].length;
totlen += isopkt[u].length;
-- 
1.8.5.5

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


[PATCH 01/76] usb/xhci: Change how we indicate a host supports Link PM.

2014-03-06 Thread Sarah Sharp
The xHCI driver currently uses a USB core internal field,
udev->lpm_capable, to indicate the xHCI driver knows how to calculate
the LPM timeout values.  If this value is set for the host controller
udev, it means Link PM can be enabled for child devices under that host.

Change the code so the xHCI driver isn't mucking with USB core internal
fields.  Instead, indicate the xHCI driver doesn't support Link PM on
this host by clearing the U1 and U2 exit latencies in the roothub
SuperSpeed Extended Capabilities BOS descriptor.

The code to check for the roothub setting U1 and U2 exit latencies to
zero will also disable LPM for external devices that do that same.  This
was already effectively done with commit
ae8963adb4ad8c5f2a89ca1d99fb7bb721e7599f "usb: Don't enable LPM if the
exit latency is zero."  Leave that code in place, so that if a device
sets one exit latency value to zero, but the other is set to a valid
value, LPM is only enabled for the U1 or U2 state that had the valid
value.  This is the same behavior the code had before.

Also, change messages about missing Link PM information from warning
level to info level.  Only print a warning about the first device that
doesn't support LPM, to avoid log spam.  Further, cleanup some
unnecessary line breaks to help people to grep for the error messages.

Signed-off-by: Sarah Sharp 
Cc: Alan Stern 
---
 drivers/usb/core/hub.c  | 24 
 drivers/usb/host/xhci-hub.c |  8 +---
 drivers/usb/host/xhci-pci.c |  6 --
 3 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index f6c6b6f7cc9c..763c3134dd78 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -141,19 +141,27 @@ static int usb_device_supports_lpm(struct usb_device 
*udev)
return 0;
}
 
-   /* All USB 3.0 must support LPM, but we need their max exit latency
-* information from the SuperSpeed Extended Capabilities BOS descriptor.
+   /*
+* According to the USB 3.0 spec, all USB 3.0 devices must support LPM.
+* However, there are some that don't, and they set the U1/U2 exit
+* latencies to zero.
 */
if (!udev->bos->ss_cap) {
-   dev_warn(&udev->dev, "No LPM exit latency info found.  "
-   "Power management will be impacted.\n");
+   dev_info(&udev->dev, "No LPM exit latency info found, disabling 
LPM.\n");
return 0;
}
-   if (udev->parent->lpm_capable)
-   return 1;
 
-   dev_warn(&udev->dev, "Parent hub missing LPM exit latency info.  "
-   "Power management will be impacted.\n");
+   if (udev->bos->ss_cap->bU1devExitLat == 0 &&
+   udev->bos->ss_cap->bU2DevExitLat == 0) {
+   if (udev->parent)
+   dev_info(&udev->dev, "LPM exit latency is zeroed, 
disabling LPM.\n");
+   else
+   dev_info(&udev->dev, "We don't know the algorithms for 
LPM for this host, disabling LPM.\n");
+   return 0;
+   }
+
+   if (!udev->parent || udev->parent->lpm_capable)
+   return 1;
return 0;
 }
 
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9992fbfec85f..1ad6bc1951c7 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -732,9 +732,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 
wValue,
/* Set the U1 and U2 exit latencies. */
memcpy(buf, &usb_bos_descriptor,
USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
-   temp = readl(&xhci->cap_regs->hcs_params3);
-   buf[12] = HCS_U1_LATENCY(temp);
-   put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
+   if ((xhci->quirks & XHCI_LPM_SUPPORT)) {
+   temp = readl(&xhci->cap_regs->hcs_params3);
+   buf[12] = HCS_U1_LATENCY(temp);
+   put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
+   }
 
/* Indicate whether the host has LTM support. */
temp = readl(&xhci->cap_regs->hcc_params);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 04f986d9234f..6c03584ac15f 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -222,12 +222,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
goto put_usb3_hcd;
/* Roothub already marked as USB 3.0 speed */
 
-   /* We know the LPM timeout algorithms for this host, let the USB core
-* enable and disable LPM for devices under the USB 3.0 roothub.
-*/
-   if (xhci->quirks & XHCI_LPM_SUPPORT)
-   hcd_to_bus(xhci->shared_hcd)->root_hub->lpm_capable = 1;
-
return 0;
 
 put_usb3_hcd:
-- 
1.8.5.5

--
To unsubscri

[PATCH 17/76] usbfs: Add support for bulk stream ids

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This patch makes it possible to specify a bulk stream id when submitting
an urb using the async usbfs API. It overloads the number_of_packets
usbdevfs_urb field for this. This is not pretty, but given other
constraints it is the best we can do. The reasoning leading to this goes
as follows:

1) We want to support bulk streams in the usbfs API
2) We do not want to extend the usbdevfs_urb struct with a new member, as
   that would mean defining new ioctl numbers for all async API ioctls +
   adding compat versions for the old ones (times 2 for 32 bit support)
3) 1 + 2 means we need to re-use an existing field
4) number_of_packets is only used for isoc urbs, and streams are bulk only
   so it is the best (and only) candidate for re-using

Note that:
1) This patch only uses number_of_packets as stream_id if the app has
   actually allocated streams on the ep, so that old apps which may have
   garbage in there (as it was unused until now in the bulk case), will not
   break
2) This patch does not add support for allocating / freeing bulk-streams, that
   is done in a follow up patch

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/devio.c  | 4 
 include/uapi/linux/usbdevice_fs.h | 5 -
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index c88d8bfaca8d..d7571a63181d 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1209,6 +1209,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
unsigned int u, totlen, isofrmlen;
int i, ret, is_in, num_sgs = 0, ifnum = -1;
int number_of_packets = 0;
+   unsigned int stream_id = 0;
void *buf;
 
if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP |
@@ -1294,6 +1295,8 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
num_sgs = DIV_ROUND_UP(uurb->buffer_length, USB_SG_SIZE);
if (num_sgs == 1 || num_sgs > ps->dev->bus->sg_tablesize)
num_sgs = 0;
+   if (ep->streams)
+   stream_id = uurb->stream_id;
break;
 
case USBDEVFS_URB_TYPE_INTERRUPT:
@@ -1444,6 +1447,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct 
usbdevfs_urb *uurb,
dr = NULL;
as->urb->start_frame = uurb->start_frame;
as->urb->number_of_packets = number_of_packets;
+   as->urb->stream_id = stream_id;
if (uurb->type == USBDEVFS_URB_TYPE_ISO ||
ps->dev->speed == USB_SPEED_HIGH)
as->urb->interval = 1 << min(15, ep->desc.bInterval - 1);
diff --git a/include/uapi/linux/usbdevice_fs.h 
b/include/uapi/linux/usbdevice_fs.h
index 0c65e4b12617..cbf122db56bc 100644
--- a/include/uapi/linux/usbdevice_fs.h
+++ b/include/uapi/linux/usbdevice_fs.h
@@ -102,7 +102,10 @@ struct usbdevfs_urb {
int buffer_length;
int actual_length;
int start_frame;
-   int number_of_packets;
+   union {
+   int number_of_packets;  /* Only used for isoc urbs */
+   unsigned int stream_id; /* Only used with bulk streams */
+   };
int error_count;
unsigned int signr; /* signal to be sent on completion,
  or 0 if none should be sent. */
-- 
1.8.5.5

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


[PATCH 25/76] uas: Properly set interface to altsetting 0 on probe failure

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

- Rename labels to properly reflect this
- Don't skip free-ing the streams when scsi_init_shared_tag_map fails

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 059ce62de4b0..ec1b22d29501 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -993,8 +993,8 @@ static void uas_free_streams(struct uas_dev_info *devinfo)
  */
 static int uas_probe(struct usb_interface *intf, const struct usb_device_id 
*id)
 {
-   int result;
-   struct Scsi_Host *shost;
+   int result = -ENOMEM;
+   struct Scsi_Host *shost = NULL;
struct uas_dev_info *devinfo;
struct usb_device *udev = interface_to_usbdev(intf);
 
@@ -1003,12 +1003,11 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
 
devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
if (!devinfo)
-   return -ENOMEM;
+   goto set_alt0;
 
-   result = -ENOMEM;
shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
if (!shost)
-   goto free;
+   goto set_alt0;
 
shost->max_cmd_len = 16 + 252;
shost->max_id = 1;
@@ -1030,11 +1029,11 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
 
result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 3);
if (result)
-   goto free;
+   goto free_streams;
 
result = scsi_add_host(shost, &intf->dev);
if (result)
-   goto deconfig_eps;
+   goto free_streams;
 
shost->hostdata[0] = (unsigned long)devinfo;
 
@@ -1042,9 +1041,10 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
usb_set_intfdata(intf, shost);
return result;
 
-deconfig_eps:
+free_streams:
uas_free_streams(devinfo);
- free:
+set_alt0:
+   usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
kfree(devinfo);
if (shost)
scsi_host_put(shost);
-- 
1.8.5.5

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


[PATCH 47/76] uas: Fix bounds check in uas_find_endpoints

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The loop uses up to 3 bytes of the endpoint extra data.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 1ac66f290fbf..7662b3e13c4d 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -907,7 +907,7 @@ static int uas_find_endpoints(struct usb_host_interface 
*alt,
for (i = 0; i < n_endpoints; i++) {
unsigned char *extra = endpoint[i].extra;
int len = endpoint[i].extralen;
-   while (len > 1) {
+   while (len >= 3) {
if (extra[1] == USB_DT_PIPE_USAGE) {
unsigned pipe_id = extra[2];
if (pipe_id > 0 && pipe_id < 5)
-- 
1.8.5.5

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


[PATCH 69/76] uas: remove BROKEN

2014-03-06 Thread Sarah Sharp
From: Gerd Hoffmann 

xhci streams support is fixed, unblock usb attached scsi.

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 666dcb692e12..13b5bfbaf951 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -204,7 +204,7 @@ config USB_STORAGE_ENE_UB6250
 
 config USB_UAS
tristate "USB Attached SCSI"
-   depends on SCSI && USB_STORAGE && BROKEN
+   depends on SCSI && USB_STORAGE
help
  The USB Attached SCSI protocol is supported by some USB
  storage devices.  It permits higher performance by supporting
-- 
1.8.5.5

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


[PATCH 06/76] xhci: For streams the css flag most be read from the stream-ctx on ep stop

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-ring.c | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3ec1d8fe06fa..51c5109bbefc 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -546,9 +546,9 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
struct xhci_dequeue_state *state)
 {
struct xhci_virt_device *dev = xhci->devs[slot_id];
+   struct xhci_virt_ep *ep = &dev->eps[ep_index];
struct xhci_ring *ep_ring;
struct xhci_generic_trb *trb;
-   struct xhci_ep_ctx *ep_ctx;
dma_addr_t addr;
 
ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id,
@@ -573,8 +573,16 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
/* Dig out the cycle state saved by the xHC during the stop ep cmd */
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Finding endpoint context");
-   ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
-   state->new_cycle_state = 0x1 & le64_to_cpu(ep_ctx->deq);
+   /* 4.6.9 the css flag is written to the stream context for streams */
+   if (ep->ep_state & EP_HAS_STREAMS) {
+   struct xhci_stream_ctx *ctx =
+   &ep->stream_info->stream_ctx_array[stream_id];
+   state->new_cycle_state = 0x1 & le64_to_cpu(ctx->stream_ring);
+   } else {
+   struct xhci_ep_ctx *ep_ctx
+   = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
+   state->new_cycle_state = 0x1 & le64_to_cpu(ep_ctx->deq);
+   }
 
state->new_deq_ptr = cur_td->last_trb;
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-- 
1.8.5.5

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


[PATCH 33/76] uas: Pack iu struct definitions

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The iu struct definitions are usb packet definitions, so no alignment should
happen. Notice that assuming 32 bit alignment this does not make any
difference at all.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 include/linux/usb/uas.h | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h
index 772b66bcdd7d..3fc8e8b9f043 100644
--- a/include/linux/usb/uas.h
+++ b/include/linux/usb/uas.h
@@ -9,7 +9,7 @@ struct iu {
__u8 iu_id;
__u8 rsvd1;
__be16 tag;
-};
+} __attribute__((__packed__));
 
 enum {
IU_ID_COMMAND   = 0x01,
@@ -52,7 +52,7 @@ struct command_iu {
__u8 rsvd7;
struct scsi_lun lun;
__u8 cdb[16];   /* XXX: Overflow-checking tools may misunderstand */
-};
+} __attribute__((__packed__));
 
 struct task_mgmt_iu {
__u8 iu_id;
@@ -62,7 +62,7 @@ struct task_mgmt_iu {
__u8 rsvd2;
__be16 task_tag;
struct scsi_lun lun;
-};
+} __attribute__((__packed__));
 
 /*
  * Also used for the Read Ready and Write Ready IUs since they have the
@@ -77,7 +77,7 @@ struct sense_iu {
__u8 rsvd7[7];
__be16 len;
__u8 sense[SCSI_SENSE_BUFFERSIZE];
-};
+} __attribute__((__packed__));
 
 struct response_iu {
__u8 iu_id;
@@ -85,7 +85,7 @@ struct response_iu {
__be16 tag;
__u8 add_response_info[3];
__u8 response_code;
-};
+} __attribute__((__packed__));
 
 struct usb_pipe_usage_descriptor {
__u8  bLength;
-- 
1.8.5.5

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


[PATCH 24/76] uas: Urbs must be anchored before submitting them

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Otherwise they may complete before they get anchored and thus never get
unanchored (as the unanchoring is done by the usb core on completion).

This commit also remove the usb_get_urb / usb_put_urb around cmd submission +
anchoring, since if done in the proper order this is not necessary.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 20 
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 046eedfc3828..059ce62de4b0 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -531,10 +531,12 @@ static int uas_submit_task_urb(struct scsi_cmnd *cmnd, 
gfp_t gfp,
  usb_free_urb, NULL);
urb->transfer_flags |= URB_FREE_BUFFER;
 
+   usb_anchor_urb(urb, &devinfo->cmd_urbs);
err = usb_submit_urb(urb, gfp);
-   if (err)
+   if (err) {
+   usb_unanchor_urb(urb);
goto err;
-   usb_anchor_urb(urb, &devinfo->cmd_urbs);
+   }
 
return 0;
 
@@ -558,13 +560,14 @@ static int uas_submit_sense_urb(struct Scsi_Host *shost,
urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
if (!urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
+   usb_anchor_urb(urb, &devinfo->sense_urbs);
if (usb_submit_urb(urb, gfp)) {
+   usb_unanchor_urb(urb);
shost_printk(KERN_INFO, shost,
 "sense urb submission failure\n");
usb_free_urb(urb);
return SCSI_MLQUEUE_DEVICE_BUSY;
}
-   usb_anchor_urb(urb, &devinfo->sense_urbs);
return 0;
 }
 
@@ -594,14 +597,15 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
}
 
if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
+   usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
+   usb_unanchor_urb(cmdinfo->data_in_urb);
scmd_printk(KERN_INFO, cmnd,
"data in urb submission failure\n");
return SCSI_MLQUEUE_DEVICE_BUSY;
}
cmdinfo->state &= ~SUBMIT_DATA_IN_URB;
cmdinfo->state |= DATA_IN_URB_INFLIGHT;
-   usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
}
 
if (cmdinfo->state & ALLOC_DATA_OUT_URB) {
@@ -614,14 +618,15 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
}
 
if (cmdinfo->state & SUBMIT_DATA_OUT_URB) {
+   usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
if (usb_submit_urb(cmdinfo->data_out_urb, gfp)) {
+   usb_unanchor_urb(cmdinfo->data_out_urb);
scmd_printk(KERN_INFO, cmnd,
"data out urb submission failure\n");
return SCSI_MLQUEUE_DEVICE_BUSY;
}
cmdinfo->state &= ~SUBMIT_DATA_OUT_URB;
cmdinfo->state |= DATA_OUT_URB_INFLIGHT;
-   usb_anchor_urb(cmdinfo->data_out_urb, &devinfo->data_urbs);
}
 
if (cmdinfo->state & ALLOC_CMD_URB) {
@@ -633,14 +638,13 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
}
 
if (cmdinfo->state & SUBMIT_CMD_URB) {
-   usb_get_urb(cmdinfo->cmd_urb);
+   usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) {
+   usb_unanchor_urb(cmdinfo->cmd_urb);
scmd_printk(KERN_INFO, cmnd,
"cmd urb submission failure\n");
return SCSI_MLQUEUE_DEVICE_BUSY;
}
-   usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs);
-   usb_put_urb(cmdinfo->cmd_urb);
cmdinfo->cmd_urb = NULL;
cmdinfo->state &= ~SUBMIT_CMD_URB;
cmdinfo->state |= COMMAND_INFLIGHT;
-- 
1.8.5.5

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


[PATCH 57/76] uas: Fix task-management not working when connected over USB-2

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

For USB-2 connections the stream-id must always be 0.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 019f2030ea0c..10e580e56d4c 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -746,7 +746,8 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 
devinfo->running_task = 1;
memset(&devinfo->response, 0, sizeof(devinfo->response));
-   sense_urb = uas_submit_sense_urb(shost, GFP_NOIO, tag);
+   sense_urb = uas_submit_sense_urb(shost, GFP_NOIO,
+devinfo->use_streams ? tag : 0);
if (!sense_urb) {
shost_printk(KERN_INFO, shost,
 "%s: %s: submit sense urb failed\n",
-- 
1.8.5.5

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


[PATCH 34/76] uas: Use all available stream ids

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

If we get ie 16 streams we can use stream-id 1-16, not 1-15.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 33f9dcd68e24..3f021f2fafdf 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -722,7 +722,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 {
struct Scsi_Host *shost = cmnd->device->host;
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
-   u16 tag = devinfo->qdepth - 1;
+   u16 tag = devinfo->qdepth;
unsigned long flags;
 
spin_lock_irqsave(&devinfo->lock, flags);
@@ -843,7 +843,7 @@ static int uas_slave_configure(struct scsi_device *sdev)
 {
struct uas_dev_info *devinfo = sdev->hostdata;
scsi_set_tag_type(sdev, MSG_ORDERED_TAG);
-   scsi_activate_tcq(sdev, devinfo->qdepth - 3);
+   scsi_activate_tcq(sdev, devinfo->qdepth - 2);
return 0;
 }
 
@@ -1027,7 +1027,7 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
INIT_LIST_HEAD(&devinfo->dead_list);
uas_configure_endpoints(devinfo);
 
-   result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 3);
+   result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
if (result)
goto free_streams;
 
-- 
1.8.5.5

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


[PATCH 19/76] usbfs: Add support for allocating / freeing streams

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This allows userspace to use bulk-streams, just like in kernel drivers, see
Documentation/usb/bulk-streams.txt for details on the in kernel API. This
is exported pretty much one on one to userspace.

To use streams an app must first make a USBDEVFS_ALLOC_STREAMS ioctl,
on success this will return the number of streams available (which may be
less then requested). If there are n streams the app can then submit
usbdevfs_urb-s with their stream_id member set to 1-n to use a specific
stream. IE if USBDEVFS_ALLOC_STREAMS returns 4 then stream_id 1-4 can be
used.

When the app is done using streams it should call USBDEVFS_FREE_STREAMS

Note applications are advised to use libusb rather then using the
usbdevfs api directly. The latest version of libusb has support for streams.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/devio.c  | 118 ++
 include/uapi/linux/usbdevice_fs.h |   7 +++
 2 files changed, 125 insertions(+)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 502974b4deb5..12401ee4ba0e 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -778,6 +778,79 @@ static struct usb_host_endpoint 
*ep_to_host_endpoint(struct usb_device *dev,
return dev->ep_out[ep & USB_ENDPOINT_NUMBER_MASK];
 }
 
+static int parse_usbdevfs_streams(struct dev_state *ps,
+ struct usbdevfs_streams __user *streams,
+ unsigned int *num_streams_ret,
+ unsigned int *num_eps_ret,
+ struct usb_host_endpoint ***eps_ret,
+ struct usb_interface **intf_ret)
+{
+   unsigned int i, num_streams, num_eps;
+   struct usb_host_endpoint **eps;
+   struct usb_interface *intf = NULL;
+   unsigned char ep;
+   int ifnum, ret;
+
+   if (get_user(num_streams, &streams->num_streams) ||
+   get_user(num_eps, &streams->num_eps))
+   return -EFAULT;
+
+   if (num_eps < 1 || num_eps > USB_MAXENDPOINTS)
+   return -EINVAL;
+
+   /* The XHCI controller allows max 2 ^ 16 streams */
+   if (num_streams_ret && (num_streams < 2 || num_streams > 65536))
+   return -EINVAL;
+
+   eps = kmalloc(num_eps * sizeof(*eps), GFP_KERNEL);
+   if (!eps)
+   return -ENOMEM;
+
+   for (i = 0; i < num_eps; i++) {
+   if (get_user(ep, &streams->eps[i])) {
+   ret = -EFAULT;
+   goto error;
+   }
+   eps[i] = ep_to_host_endpoint(ps->dev, ep);
+   if (!eps[i]) {
+   ret = -EINVAL;
+   goto error;
+   }
+
+   /* usb_alloc/free_streams operate on an usb_interface */
+   ifnum = findintfep(ps->dev, ep);
+   if (ifnum < 0) {
+   ret = ifnum;
+   goto error;
+   }
+
+   if (i == 0) {
+   ret = checkintf(ps, ifnum);
+   if (ret < 0)
+   goto error;
+   intf = usb_ifnum_to_if(ps->dev, ifnum);
+   } else {
+   /* Verify all eps belong to the same interface */
+   if (ifnum != intf->altsetting->desc.bInterfaceNumber) {
+   ret = -EINVAL;
+   goto error;
+   }
+   }
+   }
+
+   if (num_streams_ret)
+   *num_streams_ret = num_streams;
+   *num_eps_ret = num_eps;
+   *eps_ret = eps;
+   *intf_ret = intf;
+
+   return 0;
+
+error:
+   kfree(eps);
+   return ret;
+}
+
 static int match_devt(struct device *dev, void *data)
 {
return dev->devt == (dev_t) (unsigned long) data;
@@ -2009,6 +2082,45 @@ static int proc_disconnect_claim(struct dev_state *ps, 
void __user *arg)
return claimintf(ps, dc.interface);
 }
 
+static int proc_alloc_streams(struct dev_state *ps, void __user *arg)
+{
+   unsigned num_streams, num_eps;
+   struct usb_host_endpoint **eps;
+   struct usb_interface *intf;
+   int r;
+
+   r = parse_usbdevfs_streams(ps, arg, &num_streams, &num_eps,
+  &eps, &intf);
+   if (r)
+   return r;
+
+   destroy_async_on_interface(ps,
+  intf->altsetting[0].desc.bInterfaceNumber);
+
+   r = usb_alloc_streams(intf, eps, num_eps, num_streams, GFP_KERNEL);
+   kfree(eps);
+   return r;
+}
+
+static int proc_free_streams(struct dev_state *ps, void __user *arg)
+{
+   unsigned num_eps;
+   struct usb_host_endpoint **eps;
+   struct usb_interface *intf;
+   int r;
+
+   r = parse_usbdevfs_streams(ps, arg, NULL, &num_eps, &eps, &intf);
+ 

[PATCH 65/76] uas: Use the right error codes for different kinds of errors

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index fceffccc1be1..6ec48c2daf45 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -146,7 +146,8 @@ static void uas_do_work(struct work_struct *work)
 }
 
 static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
- struct uas_cmd_info *cmdinfo, const char *caller)
+ struct uas_cmd_info *cmdinfo,
+ int result, const char *caller)
 {
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
@@ -156,10 +157,12 @@ static void uas_mark_cmd_dead(struct uas_dev_info 
*devinfo,
WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
cmdinfo->state |= COMMAND_ABORTED;
cmdinfo->state &= ~IS_IN_WORK_LIST;
+   cmnd->result = result << 16;
list_move_tail(&cmdinfo->list, &devinfo->dead_list);
 }
 
-static void uas_abort_inflight(struct uas_dev_info *devinfo)
+static void uas_abort_inflight(struct uas_dev_info *devinfo, int result,
+  const char *caller)
 {
struct uas_cmd_info *cmdinfo;
struct uas_cmd_info *temp;
@@ -167,7 +170,7 @@ static void uas_abort_inflight(struct uas_dev_info *devinfo)
 
spin_lock_irqsave(&devinfo->lock, flags);
list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list, list)
-   uas_mark_cmd_dead(devinfo, cmdinfo, __func__);
+   uas_mark_cmd_dead(devinfo, cmdinfo, result, caller);
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
@@ -289,10 +292,8 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const 
char *caller)
cmdinfo->state |= COMMAND_COMPLETED;
usb_free_urb(cmdinfo->data_in_urb);
usb_free_urb(cmdinfo->data_out_urb);
-   if (cmdinfo->state & COMMAND_ABORTED) {
+   if (cmdinfo->state & COMMAND_ABORTED)
scmd_printk(KERN_INFO, cmnd, "abort completed\n");
-   cmnd->result = DID_ABORT << 16;
-   }
list_del(&cmdinfo->list);
cmnd->scsi_done(cmnd);
return 0;
@@ -824,7 +825,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
return FAILED;
}
 
-   uas_mark_cmd_dead(devinfo, cmdinfo, __func__);
+   uas_mark_cmd_dead(devinfo, cmdinfo, DID_ABORT, __func__);
if (cmdinfo->state & COMMAND_INFLIGHT) {
spin_unlock_irqrestore(&devinfo->lock, flags);
ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
@@ -860,7 +861,7 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
 
shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__);
devinfo->resetting = 1;
-   uas_abort_inflight(devinfo);
+   uas_abort_inflight(devinfo, DID_RESET, __func__);
usb_kill_anchored_urbs(&devinfo->cmd_urbs);
usb_kill_anchored_urbs(&devinfo->sense_urbs);
usb_kill_anchored_urbs(&devinfo->data_urbs);
@@ -1153,7 +1154,7 @@ static void uas_disconnect(struct usb_interface *intf)
 
devinfo->resetting = 1;
cancel_work_sync(&devinfo->work);
-   uas_abort_inflight(devinfo);
+   uas_abort_inflight(devinfo, DID_NO_CONNECT, __func__);
usb_kill_anchored_urbs(&devinfo->cmd_urbs);
usb_kill_anchored_urbs(&devinfo->sense_urbs);
usb_kill_anchored_urbs(&devinfo->data_urbs);
-- 
1.8.5.5

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


[PATCH 29/76] uas: Fix reset locking

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Fix the uas_eh_bus_reset_handler not properly taking the usbdev lock
before calling usb_device_reset, the usb-core expects this lock to be
taken when usb_device_reset is called.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 6ad5de9639d5..36ef82a34131 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -804,6 +804,13 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
struct usb_device *udev = devinfo->udev;
int err;
 
+   err = usb_lock_device_for_reset(udev, devinfo->intf);
+   if (err) {
+   shost_printk(KERN_ERR, sdev->host,
+"%s FAILED to get lock err %d\n", __func__, err);
+   return FAILED;
+   }
+
shost_printk(KERN_INFO, sdev->host, "%s start\n", __func__);
devinfo->resetting = 1;
uas_abort_work(devinfo);
@@ -817,6 +824,8 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
uas_configure_endpoints(devinfo);
devinfo->resetting = 0;
 
+   usb_unlock_device(udev);
+
if (err) {
shost_printk(KERN_INFO, sdev->host, "%s FAILED\n", __func__);
return FAILED;
-- 
1.8.5.5

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


[PATCH 73/76] xhci: Kill streams URBs when the host dies.

2014-03-06 Thread Sarah Sharp
If the host controller stops responding to commands, we need to kill all
the URBs that were queued to all endpoints.  The current code would only
kill URBs that had been queued to the endpoint rings.  ep->ring is set
to NULL if streams has been enabled for the endpoint, which means URBs
submitted with a non-zero stream_id would never get killed.  Fix this.

Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-ring.c | 28 +---
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 58cbc06ecdf9..5f926bea5ab1 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -922,13 +922,27 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
struct xhci_ring *ring;
 
ep = &xhci->devs[slot_id]->eps[ep_index];
-   ring = ep->ring;
-   if (!ring)
-   return;
-   xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-   "Killing URBs for slot ID %u, ep index %u",
-   slot_id, ep_index);
-   xhci_kill_ring_urbs(xhci, ring);
+   if ((ep->ep_state & EP_HAS_STREAMS) ||
+   (ep->ep_state & EP_GETTING_NO_STREAMS)) {
+   int stream_id;
+
+   for (stream_id = 0; stream_id < ep->stream_info->num_streams;
+   stream_id++) {
+   xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+   "Killing URBs for slot ID %u, ep index 
%u, stream %u",
+   slot_id, ep_index, stream_id + 1);
+   xhci_kill_ring_urbs(xhci,
+   
ep->stream_info->stream_rings[stream_id]);
+   }
+   } else {
+   ring = ep->ring;
+   if (!ring)
+   return;
+   xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+   "Killing URBs for slot ID %u, ep index %u",
+   slot_id, ep_index);
+   xhci_kill_ring_urbs(xhci, ring);
+   }
while (!list_empty(&ep->cancelled_td_list)) {
cur_td = list_first_entry(&ep->cancelled_td_list,
struct xhci_td, cancelled_td_list);
-- 
1.8.5.5

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


[PATCH 51/76] uas: Not being able to alloc streams when connected through usb-3 is an error

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 24 +---
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 754468bbbfdc..d758faef8664 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -93,7 +93,6 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo, gfp_t gfp);
 static void uas_do_work(struct work_struct *work);
 static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
-static void uas_configure_endpoints(struct uas_dev_info *devinfo);
 static void uas_free_streams(struct uas_dev_info *devinfo);
 static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller);
 
@@ -898,7 +897,7 @@ static int uas_switch_interface(struct usb_device *udev,
intf->altsetting[0].desc.bInterfaceNumber, alt);
 }
 
-static void uas_configure_endpoints(struct uas_dev_info *devinfo)
+static int uas_configure_endpoints(struct uas_dev_info *devinfo)
 {
struct usb_host_endpoint *eps[4] = { };
struct usb_device *udev = devinfo->udev;
@@ -920,14 +919,18 @@ static void uas_configure_endpoints(struct uas_dev_info 
*devinfo)
devinfo->data_out_pipe = usb_sndbulkpipe(udev,
usb_endpoint_num(&eps[3]->desc));
 
-   devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
-   GFP_KERNEL);
-   if (devinfo->qdepth < 0) {
+   if (udev->speed != USB_SPEED_SUPER) {
devinfo->qdepth = 256;
devinfo->use_streams = 0;
} else {
+   devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1,
+   3, 256, GFP_KERNEL);
+   if (devinfo->qdepth < 0)
+   return devinfo->qdepth;
devinfo->use_streams = 1;
}
+
+   return 0;
 }
 
 static void uas_free_streams(struct uas_dev_info *devinfo)
@@ -984,7 +987,10 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
INIT_WORK(&devinfo->work, uas_do_work);
INIT_LIST_HEAD(&devinfo->work_list);
INIT_LIST_HEAD(&devinfo->dead_list);
-   uas_configure_endpoints(devinfo);
+
+   result = uas_configure_endpoints(devinfo);
+   if (result)
+   goto set_alt0;
 
result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2);
if (result)
@@ -1039,7 +1045,11 @@ static int uas_post_reset(struct usb_interface *intf)
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
unsigned long flags;
 
-   uas_configure_endpoints(devinfo);
+   if (uas_configure_endpoints(devinfo) != 0) {
+   shost_printk(KERN_ERR, shost,
+"%s: alloc streams error after reset", __func__);
+   return 1;
+   }
 
spin_lock_irqsave(shost->host_lock, flags);
scsi_report_bus_reset(shost, 0);
-- 
1.8.5.5

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


[PATCH 68/76] uas: Make sure sg elements are properly aligned

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Copy the sg alignment trick from the usb-storage driver, without this I'm
seeing intermittent errors when using uas devices with an ehci controller.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 62086829af14..ad97615b75b1 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -925,6 +925,24 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
 static int uas_slave_alloc(struct scsi_device *sdev)
 {
sdev->hostdata = (void *)sdev->host->hostdata;
+
+   /* USB has unusual DMA-alignment requirements: Although the
+* starting address of each scatter-gather element doesn't matter,
+* the length of each element except the last must be divisible
+* by the Bulk maxpacket value.  There's currently no way to
+* express this by block-layer constraints, so we'll cop out
+* and simply require addresses to be aligned at 512-byte
+* boundaries.  This is okay since most block I/O involves
+* hardware sectors that are multiples of 512 bytes in length,
+* and since host controllers up through USB 2.0 have maxpacket
+* values no larger than 512.
+*
+* But it doesn't suffice for Wireless USB, where Bulk maxpacket
+* values can be as large as 2048.  To make that work properly
+* will require changes to the block layer.
+*/
+   blk_queue_update_dma_alignment(sdev->request_queue, (512 - 1));
+
return 0;
 }
 
-- 
1.8.5.5

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


[PATCH 32/76] uas: Fix response iu struct definition

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The response iu struct before this patch has a size of 7 bytes (discounting
padding), which is weird since all other iu-s are explictly padded to
a multiple of 4 bytes.

More over submitting a 7 byte bulk transfer to the status endpoint when
expecting a response iu results in an USB babble error, as the device
actually sends 8 bytes.

Up on closer reading of the UAS spec:
http://www.t10.org/cgi-bin/ac.pl?t=f&f=uas2r00.pdf

The reason for this becomes clear, the 2 entries in "Table 17 — RESPONSE IU"
are numbered 4 and 6, looking at other iu definitions in the spec, esp.
multi-byte fields, this indicates that the ADDITIONAL RESPONSE INFORMATION
field is not a 2 byte field as one might assume at a first look, but is
a multi-byte field containing 3 bytes.

This also aligns with the SCSI Architecture Model 4 spec, which UAS is based
on which states in paragraph "7.1 Task management function procedure calls"
that the "Additional Response Information" output argument for a Task
management function procedure call is 3 bytes.

Last but not least I've verified this by sending a logical unit reset task
management call with an invalid lun to an actual uasp device, and received
back a response-iu with byte 6 being 0, and byte 7 being 9, which is the
responce code for an invalid iu, which confirms that the response code is
being reported in byte 7 of the response iu rather then in byte 6.

Things were working before despite this error in the response iu struct
definition because the additional response info field is normally filled
with zeros, and 0 is the response code value for success.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 include/linux/usb/uas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h
index 14041780fb6c..772b66bcdd7d 100644
--- a/include/linux/usb/uas.h
+++ b/include/linux/usb/uas.h
@@ -83,7 +83,7 @@ struct response_iu {
__u8 iu_id;
__u8 rsvd1;
__be16 tag;
-   __be16 add_response_info;
+   __u8 add_response_info[3];
__u8 response_code;
 };
 
-- 
1.8.5.5

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


[PATCH 45/76] uas: Honor no-uas quirk set in usb-storage's quirks module parameter

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Falling back from uas to usb-storage requires coordination between uas and
usb-storage, so use usb-storage's quirks module parameter, rather then
requiring the user to pass a param to 2 different modules.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/Kconfig  | 2 +-
 drivers/usb/storage/uas-detect.h | 4 
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
index 1dd0604d1911..666dcb692e12 100644
--- a/drivers/usb/storage/Kconfig
+++ b/drivers/usb/storage/Kconfig
@@ -204,7 +204,7 @@ config USB_STORAGE_ENE_UB6250
 
 config USB_UAS
tristate "USB Attached SCSI"
-   depends on SCSI && BROKEN
+   depends on SCSI && USB_STORAGE && BROKEN
help
  The USB Attached SCSI protocol is supported by some USB
  storage devices.  It permits higher performance by supporting
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index 02bf5ec957f5..082bde1fa74d 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -1,5 +1,6 @@
 #include 
 #include 
+#include "usb.h"
 
 static int uas_is_interface(struct usb_host_interface *intf)
 {
@@ -42,8 +43,11 @@ static int uas_find_uas_alt_setting(struct usb_interface 
*intf)
 static int uas_use_uas_driver(struct usb_interface *intf,
  const struct usb_device_id *id)
 {
+   struct usb_device *udev = interface_to_usbdev(intf);
unsigned long flags = id->driver_info;
 
+   usb_stor_adjust_quirks(udev, &flags);
+
if (flags & US_FL_IGNORE_UAS)
return 0;
 
-- 
1.8.5.5

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


[PATCH 58/76] uas: uas_alloc_data_urb: Remove unnecessary use_streams check

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

uas_alloc_data_urb always gets called with a stream_id value of 0 when not
using streams. Removing the check makes it consistent with uas_alloc_sense_urb.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 10e580e56d4c..e06505c8f6f0 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -429,8 +429,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info 
*devinfo, gfp_t gfp,
goto out;
usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length,
  uas_data_cmplt, cmnd);
-   if (devinfo->use_streams)
-   urb->stream_id = stream_id;
+   urb->stream_id = stream_id;
urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0;
urb->sg = sdb->table.sgl;
  out:
-- 
1.8.5.5

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


[PATCH 11/76] usb-core: Fix usb_free_streams return value documentation

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/hcd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 2518c3250750..9b445f43f825 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2078,8 +2078,7 @@ EXPORT_SYMBOL_GPL(usb_alloc_streams);
  * Reverts a group of bulk endpoints back to not using stream IDs.
  * Can fail if we are given bad arguments, or HCD is broken.
  *
- * Return: On success, the number of allocated streams. On failure, a negative
- * error code.
+ * Return: 0 on success. On failure, a negative error code.
  */
 int usb_free_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,
-- 
1.8.5.5

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


[PATCH 09/76] xhci: use usb_ss_max_streams in xhci_check_streams_endpoint

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The ss_ep_comp bmAttributes filed can contain more info then just the
streams, use usb_ss_max_streams to properly get max streams.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c3fa32a905ec..6cb9c2235a0b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2971,7 +2971,7 @@ static int xhci_check_streams_endpoint(struct xhci_hcd 
*xhci,
ret = xhci_check_args(xhci_to_hcd(xhci), udev, ep, 1, true, __func__);
if (ret <= 0)
return -EINVAL;
-   if (ep->ss_ep_comp.bmAttributes == 0) {
+   if (usb_ss_max_streams(&ep->ss_ep_comp) == 0) {
xhci_warn(xhci, "WARN: SuperSpeed Endpoint Companion"
" descriptor for ep 0x%x does not support 
streams\n",
ep->desc.bEndpointAddress);
-- 
1.8.5.5

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


[PATCH 28/76] uas: Fix uas not working when plugged into an ehci port

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

I thought it would be a good idea to also test uas with usb-2, and it turns out
it was, as it did not work. The problem is that the uas driver was passing the
bEndpointAddress' direction bit to usb_rcvbulkpipe, the xhci code seems to not
care about this, but with the ehci code this causes usb_submit_urb failure.

With this fixed the uas code works nicely with an uas device plugged into
an ehci port.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 5eacb8054457..6ad5de9639d5 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -948,13 +948,13 @@ static void uas_configure_endpoints(struct uas_dev_info 
*devinfo)
eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
} else {
devinfo->cmd_pipe = usb_sndbulkpipe(udev,
-   eps[0]->desc.bEndpointAddress);
+usb_endpoint_num(&eps[0]->desc));
devinfo->status_pipe = usb_rcvbulkpipe(udev,
-   eps[1]->desc.bEndpointAddress);
+usb_endpoint_num(&eps[1]->desc));
devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
-   eps[2]->desc.bEndpointAddress);
+usb_endpoint_num(&eps[2]->desc));
devinfo->data_out_pipe = usb_sndbulkpipe(udev,
-   eps[3]->desc.bEndpointAddress);
+usb_endpoint_num(&eps[3]->desc));
}
 
devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
-- 
1.8.5.5

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


[PATCH 74/76] storage: accept some UAS devices if streams are unavailable

2014-03-06 Thread Sarah Sharp
From: Oliver Neukum 

On some older XHCIs streams are not supported and the UAS driver
will fail at probe time. For those devices storage should try
to bind to UAS devices.
This patch adds a flag for stream support to HCDs and evaluates
it.

[Note: Sarah fixed a bug where the USB 2.0 root hub, not USB 3.0 root
hub would get marked as being able to support streams.]

Signed-off-by: Oliver Neukum 
Signed-off-by: Sarah Sharp 
Acked-by: Hans de Goede 
---
 drivers/usb/host/xhci-pci.c  | 3 +++
 drivers/usb/host/xhci-plat.c | 3 +++
 drivers/usb/storage/uas-detect.h | 4 
 include/linux/usb/hcd.h  | 1 +
 4 files changed, 11 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6c03584ac15f..cbf0c5cffc92 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -222,6 +222,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
goto put_usb3_hcd;
/* Roothub already marked as USB 3.0 speed */
 
+   if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+   xhci->shared_hcd->can_do_streams = 1;
+
return 0;
 
 put_usb3_hcd:
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 8affef910782..151901ce1ba9 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -158,6 +158,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
 */
*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
 
+   if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
+   xhci->shared_hcd->can_do_streams = 1;
+
ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);
if (ret)
goto put_usb3_hcd;
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index b8a02e12a8a2..bb05b984d5f6 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -72,6 +72,7 @@ static int uas_use_uas_driver(struct usb_interface *intf,
 {
struct usb_host_endpoint *eps[4] = { };
struct usb_device *udev = interface_to_usbdev(intf);
+   struct usb_hcd *hcd = bus_to_hcd(udev->bus);
unsigned long flags = id->driver_info;
int r, alt;
 
@@ -80,6 +81,9 @@ static int uas_use_uas_driver(struct usb_interface *intf,
if (flags & US_FL_IGNORE_UAS)
return 0;
 
+   if (udev->speed >= USB_SPEED_SUPER && !hcd->can_do_streams)
+   return 0;
+
alt = uas_find_uas_alt_setting(intf);
if (alt < 0)
return 0;
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index efe8d8a7c7ad..485cd5e2100c 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -143,6 +143,7 @@ struct usb_hcd {
unsignedauthorized_default:1;
unsignedhas_tt:1;   /* Integrated TT in root hub */
unsignedamd_resume_bug:1; /* AMD remote wakeup quirk */
+   unsignedcan_do_streams:1; /* HC supports streams */
 
unsigned intirq;/* irq allocated */
void __iomem*regs;  /* device memory/io */
-- 
1.8.5.5

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


[PATCH 36/76] uas: Move uas detect code to uas-detect.h

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This is a preparation patch for teaching usb-storage to not bind to
uas devices.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas-detect.h | 40 
 drivers/usb/storage/uas.c| 40 ++--
 2 files changed, 42 insertions(+), 38 deletions(-)
 create mode 100644 drivers/usb/storage/uas-detect.h

diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
new file mode 100644
index ..28101c7e6a9f
--- /dev/null
+++ b/drivers/usb/storage/uas-detect.h
@@ -0,0 +1,40 @@
+#include 
+#include 
+
+static int uas_is_interface(struct usb_host_interface *intf)
+{
+   return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
+   intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
+   intf->desc.bInterfaceProtocol == USB_PR_UAS);
+}
+
+static int uas_isnt_supported(struct usb_device *udev)
+{
+   struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+   dev_warn(&udev->dev, "The driver for the USB controller %s does not "
+   "support scatter-gather which is\n",
+   hcd->driver->description);
+   dev_warn(&udev->dev, "required by the UAS driver. Please try an"
+   "alternative USB controller if you wish to use UAS.\n");
+   return -ENODEV;
+}
+
+static int uas_find_uas_alt_setting(struct usb_interface *intf)
+{
+   int i;
+   struct usb_device *udev = interface_to_usbdev(intf);
+   int sg_supported = udev->bus->sg_tablesize != 0;
+
+   for (i = 0; i < intf->num_altsetting; i++) {
+   struct usb_host_interface *alt = &intf->altsetting[i];
+
+   if (uas_is_interface(alt)) {
+   if (!sg_supported)
+   return uas_isnt_supported(udev);
+   return alt->desc.bAlternateSetting;
+   }
+   }
+
+   return -ENODEV;
+}
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 54db36541b93..6ea892f32f74 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -25,6 +25,8 @@
 #include 
 #include 
 
+#include "uas-detect.h"
+
 /*
  * The r00-r01c specs define this version of the SENSE IU data structure.
  * It's still in use by several different firmware releases.
@@ -873,44 +875,6 @@ static struct usb_device_id uas_usb_ids[] = {
 };
 MODULE_DEVICE_TABLE(usb, uas_usb_ids);
 
-static int uas_is_interface(struct usb_host_interface *intf)
-{
-   return (intf->desc.bInterfaceClass == USB_CLASS_MASS_STORAGE &&
-   intf->desc.bInterfaceSubClass == USB_SC_SCSI &&
-   intf->desc.bInterfaceProtocol == USB_PR_UAS);
-}
-
-static int uas_isnt_supported(struct usb_device *udev)
-{
-   struct usb_hcd *hcd = bus_to_hcd(udev->bus);
-
-   dev_warn(&udev->dev, "The driver for the USB controller %s does not "
-   "support scatter-gather which is\n",
-   hcd->driver->description);
-   dev_warn(&udev->dev, "required by the UAS driver. Please try an"
-   "alternative USB controller if you wish to use UAS.\n");
-   return -ENODEV;
-}
-
-static int uas_find_uas_alt_setting(struct usb_interface *intf)
-{
-   int i;
-   struct usb_device *udev = interface_to_usbdev(intf);
-   int sg_supported = udev->bus->sg_tablesize != 0;
-
-   for (i = 0; i < intf->num_altsetting; i++) {
-   struct usb_host_interface *alt = &intf->altsetting[i];
-
-   if (uas_is_interface(alt)) {
-   if (!sg_supported)
-   return uas_isnt_supported(udev);
-   return alt->desc.bAlternateSetting;
-   }
-   }
-
-   return -ENODEV;
-}
-
 static int uas_switch_interface(struct usb_device *udev,
struct usb_interface *intf)
 {
-- 
1.8.5.5

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


[PATCH 63/76] uas: Fix memory management

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The scsi-host structure is refcounted, scsi_remove_host tears down the
scsi-host but does not decrement the refcount, so we need to call
scsi_put_host on disconnect to get the underlying memory to be freed.

After calling scsi_remove_host, the scsi-core may still hold a reference to
the scsi-host, iow we may still get called after uas_disconnect, but we
do our own life cycle management of uas_devinfo, freeing it on disconnect,
and thus may end up using devinfo after it has been freed. Switch to letting
scsi_host_alloc allocate and manage the memory for us.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 33 ++---
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 8c685801e267..d81d041842f4 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -315,7 +315,7 @@ static void uas_stat_cmplt(struct urb *urb)
 {
struct iu *iu = urb->transfer_buffer;
struct Scsi_Host *shost = urb->context;
-   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
struct scsi_cmnd *cmnd;
struct uas_cmd_info *cmdinfo;
unsigned long flags;
@@ -562,7 +562,7 @@ err:
 static struct urb *uas_submit_sense_urb(struct Scsi_Host *shost,
gfp_t gfp, unsigned int stream)
 {
-   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
struct urb *urb;
 
urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
@@ -734,7 +734,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
const char *fname, u8 function)
 {
struct Scsi_Host *shost = cmnd->device->host;
-   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
u16 tag = devinfo->qdepth;
unsigned long flags;
struct urb *sense_urb;
@@ -879,7 +879,7 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
 
 static int uas_slave_alloc(struct scsi_device *sdev)
 {
-   sdev->hostdata = (void *)sdev->host->hostdata[0];
+   sdev->hostdata = (void *)sdev->host->hostdata;
return 0;
 }
 
@@ -1005,11 +1005,8 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
if (uas_switch_interface(udev, intf))
return -ENODEV;
 
-   devinfo = kmalloc(sizeof(struct uas_dev_info), GFP_KERNEL);
-   if (!devinfo)
-   goto set_alt0;
-
-   shost = scsi_host_alloc(&uas_host_template, sizeof(void *));
+   shost = scsi_host_alloc(&uas_host_template,
+   sizeof(struct uas_dev_info));
if (!shost)
goto set_alt0;
 
@@ -1019,6 +1016,7 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
shost->max_channel = 0;
shost->sg_tablesize = udev->bus->sg_tablesize;
 
+   devinfo = (struct uas_dev_info *)shost->hostdata;
devinfo->intf = intf;
devinfo->udev = udev;
devinfo->resetting = 0;
@@ -1044,8 +1042,6 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
if (result)
goto free_streams;
 
-   shost->hostdata[0] = (unsigned long)devinfo;
-
scsi_scan_host(shost);
usb_set_intfdata(intf, shost);
return result;
@@ -1054,7 +1050,6 @@ free_streams:
uas_free_streams(devinfo);
 set_alt0:
usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
-   kfree(devinfo);
if (shost)
scsi_host_put(shost);
return result;
@@ -1063,7 +1058,7 @@ set_alt0:
 static int uas_pre_reset(struct usb_interface *intf)
 {
struct Scsi_Host *shost = usb_get_intfdata(intf);
-   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
unsigned long flags;
 
if (devinfo->shutdown)
@@ -1089,7 +1084,7 @@ static int uas_pre_reset(struct usb_interface *intf)
 static int uas_post_reset(struct usb_interface *intf)
 {
struct Scsi_Host *shost = usb_get_intfdata(intf);
-   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
unsigned long flags;
 
if (devinfo->shutdown)
@@ -1113,7 +1108,7 @@ static int uas_post_reset(struct usb_interface *intf)
 static int uas_suspend(struct usb_interface *intf, pm_message_t message)
 {
struct Scsi_Host *shost = usb_get_intfdata(intf);
-   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   struct uas_dev_info *devinfo = (struct uas_dev_

[PATCH 50/76] uas: Verify endpoint descriptors from uas_use_uas_driver()

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas-detect.h | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index 8de030a0a4a4..b8a02e12a8a2 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -70,13 +70,23 @@ static int uas_find_endpoints(struct usb_host_interface 
*alt,
 static int uas_use_uas_driver(struct usb_interface *intf,
  const struct usb_device_id *id)
 {
+   struct usb_host_endpoint *eps[4] = { };
struct usb_device *udev = interface_to_usbdev(intf);
unsigned long flags = id->driver_info;
+   int r, alt;
 
usb_stor_adjust_quirks(udev, &flags);
 
if (flags & US_FL_IGNORE_UAS)
return 0;
 
-   return uas_find_uas_alt_setting(intf) >= 0;
+   alt = uas_find_uas_alt_setting(intf);
+   if (alt < 0)
+   return 0;
+
+   r = uas_find_endpoints(&intf->altsetting[alt], eps);
+   if (r < 0)
+   return 0;
+
+   return 1;
 }
-- 
1.8.5.5

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


[PATCH 18/76] usbfs: Add ep_to_host_endpoint helper function

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/devio.c | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index d7571a63181d..502974b4deb5 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -769,6 +769,15 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned 
int requesttype,
return ret;
 }
 
+static struct usb_host_endpoint *ep_to_host_endpoint(struct usb_device *dev,
+unsigned char ep)
+{
+   if (ep & USB_ENDPOINT_DIR_MASK)
+   return dev->ep_in[ep & USB_ENDPOINT_NUMBER_MASK];
+   else
+   return dev->ep_out[ep & USB_ENDPOINT_NUMBER_MASK];
+}
+
 static int match_devt(struct device *dev, void *data)
 {
return dev->devt == (dev_t) (unsigned long) data;
@@ -1230,15 +1239,10 @@ static int proc_do_submiturb(struct dev_state *ps, 
struct usbdevfs_urb *uurb,
if (ret)
return ret;
}
-   if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0) {
-   is_in = 1;
-   ep = ps->dev->ep_in[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
-   } else {
-   is_in = 0;
-   ep = ps->dev->ep_out[uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
-   }
+   ep = ep_to_host_endpoint(ps->dev, uurb->endpoint);
if (!ep)
return -ENOENT;
+   is_in = (uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0;
 
u = 0;
switch(uurb->type) {
-- 
1.8.5.5

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


[PATCH 75/76] xhci: Prevent runtime pm from autosuspending during initialization

2014-03-06 Thread Sarah Sharp
From: Mathias Nyman 

xHCI driver has its own pci probe function that will call usb_hcd_pci_probe
to register its usb-2 bus, and then continue to manually register the
usb-3 bus. usb_hcd_pci_probe does a pm_runtime_put_noidle at the end and
might thus trigger a runtime suspend before the usb-3 bus is ready.

Prevent the runtime suspend by increasing the usage count in the
beginning of xhci_pci_probe, and decrease it once the usb-3 bus is
ready.

xhci-platform driver is not using usb_hcd_pci_probe to set up
busses and should not need to have it's usage count increased during probe.

Signed-off-by: Mathias Nyman 
Acked-by: Dan Williams 
Acked-by: Alan Stern 
Signed-off-by: Sarah Sharp 
Cc: sta...@vger.kernel.org
---
 drivers/usb/host/xhci-pci.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index cbf0c5cffc92..47390e369cd4 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -190,6 +190,10 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
struct usb_hcd *hcd;
 
driver = (struct hc_driver *)id->driver_data;
+
+   /* Prevent runtime suspending between USB-2 and USB-3 initialization */
+   pm_runtime_get_noresume(&dev->dev);
+
/* Register the USB 2.0 roothub.
 * FIXME: USB core must know to register the USB 2.0 roothub first.
 * This is sort of silly, because we could just set the HCD driver flags
@@ -199,7 +203,7 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
retval = usb_hcd_pci_probe(dev, id);
 
if (retval)
-   return retval;
+   goto put_runtime_pm;
 
/* USB 2.0 roothub is stored in the PCI device now. */
hcd = dev_get_drvdata(&dev->dev);
@@ -225,12 +229,17 @@ static int xhci_pci_probe(struct pci_dev *dev, const 
struct pci_device_id *id)
if (HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1;
 
+   /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
+   pm_runtime_put_noidle(&dev->dev);
+
return 0;
 
 put_usb3_hcd:
usb_put_hcd(xhci->shared_hcd);
 dealloc_usb2_hcd:
usb_hcd_pci_remove(dev);
+put_runtime_pm:
+   pm_runtime_put_noidle(&dev->dev);
return retval;
 }
 
-- 
1.8.5.5

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


[PATCH 21/76] uas: make work list per-device

2014-03-06 Thread Sarah Sharp
From: Gerd Hoffmann 

Simplifies locking, we'll protect the list with the device spin lock.
Also plugs races which can happen when two devices operate on the
global list.

While being at it rename the list head from "list" to "work", preparing
for the addition of a second list.

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 106 +++---
 1 file changed, 44 insertions(+), 62 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index fc08ee919439..3cf5a5ff3d53 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -51,6 +51,8 @@ struct uas_dev_info {
unsigned uas_sense_old:1;
struct scsi_cmnd *cmnd;
spinlock_t lock;
+   struct work_struct work;
+   struct list_head work_list;
 };
 
 enum {
@@ -77,7 +79,7 @@ struct uas_cmd_info {
struct urb *cmd_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
-   struct list_head list;
+   struct list_head work;
 };
 
 /* I hate forward declarations, but I actually have a loop */
@@ -88,10 +90,6 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const 
char *caller);
 static void uas_configure_endpoints(struct uas_dev_info *devinfo);
 static void uas_free_streams(struct uas_dev_info *devinfo);
 
-static DECLARE_WORK(uas_work, uas_do_work);
-static DEFINE_SPINLOCK(uas_work_lock);
-static LIST_HEAD(uas_work_list);
-
 static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
 struct uas_cmd_info *cmdinfo)
 {
@@ -118,75 +116,66 @@ static void uas_unlink_data_urbs(struct uas_dev_info 
*devinfo,
 
 static void uas_do_work(struct work_struct *work)
 {
+   struct uas_dev_info *devinfo =
+   container_of(work, struct uas_dev_info, work);
struct uas_cmd_info *cmdinfo;
struct uas_cmd_info *temp;
-   struct list_head list;
unsigned long flags;
int err;
 
-   spin_lock_irq(&uas_work_lock);
-   list_replace_init(&uas_work_list, &list);
-   spin_unlock_irq(&uas_work_lock);
-
-   list_for_each_entry_safe(cmdinfo, temp, &list, list) {
+   spin_lock_irqsave(&devinfo->lock, flags);
+   list_for_each_entry_safe(cmdinfo, temp, &devinfo->work_list, work) {
struct scsi_pointer *scp = (void *)cmdinfo;
-   struct scsi_cmnd *cmnd = container_of(scp,
-   struct scsi_cmnd, SCp);
-   struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata;
-   spin_lock_irqsave(&devinfo->lock, flags);
+   struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
+ SCp);
err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
-   if (!err)
+   if (!err) {
cmdinfo->state &= ~IS_IN_WORK_LIST;
-   spin_unlock_irqrestore(&devinfo->lock, flags);
-   if (err) {
-   list_del(&cmdinfo->list);
-   spin_lock_irq(&uas_work_lock);
-   list_add_tail(&cmdinfo->list, &uas_work_list);
-   spin_unlock_irq(&uas_work_lock);
-   schedule_work(&uas_work);
+   list_del(&cmdinfo->work);
+   } else {
+   schedule_work(&devinfo->work);
}
}
+   spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
 static void uas_abort_work(struct uas_dev_info *devinfo)
 {
struct uas_cmd_info *cmdinfo;
struct uas_cmd_info *temp;
-   struct list_head list;
unsigned long flags;
 
-   spin_lock_irq(&uas_work_lock);
-   list_replace_init(&uas_work_list, &list);
-   spin_unlock_irq(&uas_work_lock);
-
spin_lock_irqsave(&devinfo->lock, flags);
-   list_for_each_entry_safe(cmdinfo, temp, &list, list) {
+   list_for_each_entry_safe(cmdinfo, temp, &devinfo->work_list, work) {
struct scsi_pointer *scp = (void *)cmdinfo;
-   struct scsi_cmnd *cmnd = container_of(scp,
-   struct scsi_cmnd, SCp);
-   struct uas_dev_info *di = (void *)cmnd->device->hostdata;
-
-   if (di == devinfo) {
-   cmdinfo->state |= COMMAND_ABORTED;
-   cmdinfo->state &= ~IS_IN_WORK_LIST;
-   if (devinfo->resetting) {
-   /* uas_stat_cmplt() will not do that
-* when a device reset is in
-* progress */
-   cmdinfo->state &= ~COMMAND_INFLIGHT;
-   }
-   uas_try_complete(cmnd, __func__);
-   } else {
-   /* not our ua

[PATCH 04/76] xhci: Free streams when they are still allocated on a set_interface call

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

And warn about this, as that would be a driver bug.

Like wise drivers should ensure that streams are properly free-ed before a
device is reset. So lets warn about that too. This already causes warnings
in the form of:

[   96.982398] xhci_hcd :01:00.0: WARN Can't disable streams for endpoint 
0x81
, streams are already disabled!
[   96.982400] xhci_hcd :01:00.0: WARN xhci_free_streams() called with 
non-streams endpoint

But it is better to also warn about the actual cause of this later warnings.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci.c | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6fe577d46fa2..c3fa32a905ec 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2678,6 +2678,20 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
return ret;
 }
 
+static void xhci_check_bw_drop_ep_streams(struct xhci_hcd *xhci,
+   struct xhci_virt_device *vdev, int i)
+{
+   struct xhci_virt_ep *ep = &vdev->eps[i];
+
+   if (ep->ep_state & EP_HAS_STREAMS) {
+   xhci_warn(xhci, "WARN: endpoint 0x%02x has streams on 
set_interface, freeing streams.\n",
+   xhci_get_endpoint_address(i));
+   xhci_free_stream_info(xhci, ep->stream_info);
+   ep->stream_info = NULL;
+   ep->ep_state &= ~EP_HAS_STREAMS;
+   }
+}
+
 /* Called after one or more calls to xhci_add_endpoint() or
  * xhci_drop_endpoint().  If this call fails, the USB core is expected
  * to call xhci_reset_bandwidth().
@@ -2742,8 +2756,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct 
usb_device *udev)
/* Free any rings that were dropped, but not changed. */
for (i = 1; i < 31; ++i) {
if ((le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) &&
-   !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1
+   !(le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1 {
xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+   xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
+   }
}
xhci_zero_in_ctx(xhci, virt_dev);
/*
@@ -2759,6 +2775,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct 
usb_device *udev)
if (virt_dev->eps[i].ring) {
xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
}
+   xhci_check_bw_drop_ep_streams(xhci, virt_dev, i);
virt_dev->eps[i].ring = virt_dev->eps[i].new_ring;
virt_dev->eps[i].new_ring = NULL;
}
@@ -3519,6 +3536,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, 
struct usb_device *udev)
struct xhci_virt_ep *ep = &virt_dev->eps[i];
 
if (ep->ep_state & EP_HAS_STREAMS) {
+   xhci_warn(xhci, "WARN: endpoint 0x%02x has streams on 
device reset, freeing streams.\n",
+   xhci_get_endpoint_address(i));
xhci_free_stream_info(xhci, ep->stream_info);
ep->stream_info = NULL;
ep->ep_state &= ~EP_HAS_STREAMS;
-- 
1.8.5.5

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


[PATCH 56/76] uas: Reset device on reboot

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Some BIOS-es will hang on reboot when an uas device is attached and left in
uas mode on reboot.

This commit adds a shutdown handler which on reboot puts the device back into
usb-storage mode, fixing the hang on reboot on these systems.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 7a16ed8e8aac..019f2030ea0c 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -54,6 +54,7 @@ struct uas_dev_info {
unsigned use_streams:1;
unsigned uas_sense_old:1;
unsigned running_task:1;
+   unsigned shutdown:1;
struct scsi_cmnd *cmnd;
spinlock_t lock;
struct work_struct work;
@@ -1011,6 +1012,7 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
devinfo->udev = udev;
devinfo->resetting = 0;
devinfo->running_task = 0;
+   devinfo->shutdown = 0;
init_usb_anchor(&devinfo->cmd_urbs);
init_usb_anchor(&devinfo->sense_urbs);
init_usb_anchor(&devinfo->data_urbs);
@@ -1053,6 +1055,9 @@ static int uas_pre_reset(struct usb_interface *intf)
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
unsigned long flags;
 
+   if (devinfo->shutdown)
+   return 0;
+
/* Block new requests */
spin_lock_irqsave(shost->host_lock, flags);
scsi_block_requests(shost);
@@ -1076,6 +1081,9 @@ static int uas_post_reset(struct usb_interface *intf)
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
unsigned long flags;
 
+   if (devinfo->shutdown)
+   return 0;
+
if (uas_configure_endpoints(devinfo) != 0) {
shost_printk(KERN_ERR, shost,
 "%s: alloc streams error after reset", __func__);
@@ -1147,6 +1155,27 @@ static void uas_disconnect(struct usb_interface *intf)
kfree(devinfo);
 }
 
+/*
+ * Put the device back in usb-storage mode on shutdown, as some BIOS-es
+ * hang on reboot when the device is still in uas mode. Note the reset is
+ * necessary as some devices won't revert to usb-storage mode without it.
+ */
+static void uas_shutdown(struct device *dev)
+{
+   struct usb_interface *intf = to_usb_interface(dev);
+   struct usb_device *udev = interface_to_usbdev(intf);
+   struct Scsi_Host *shost = usb_get_intfdata(intf);
+   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+
+   if (system_state != SYSTEM_RESTART)
+   return;
+
+   devinfo->shutdown = 1;
+   uas_free_streams(devinfo);
+   usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0);
+   usb_reset_device(udev);
+}
+
 static struct usb_driver uas_driver = {
.name = "uas",
.probe = uas_probe,
@@ -1156,6 +1185,7 @@ static struct usb_driver uas_driver = {
.suspend = uas_suspend,
.resume = uas_resume,
.reset_resume = uas_reset_resume,
+   .drvwrap.driver.shutdown = uas_shutdown,
.id_table = uas_usb_ids,
 };
 
-- 
1.8.5.5

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


[PATCH 53/76] uas: Don't allow more then one task to run at the same time

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Since we use a fixed tag / stream for tasks we cannot allow more then one
to run at the same time. This could happen before this time if a task timed
out.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 39 ++-
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 9c6f9f9804fd..7fc4ad207752 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -53,6 +53,7 @@ struct uas_dev_info {
unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
unsigned use_streams:1;
unsigned uas_sense_old:1;
+   unsigned running_task:1;
struct scsi_cmnd *cmnd;
spinlock_t lock;
struct work_struct work;
@@ -195,6 +196,7 @@ static void uas_zap_dead(struct uas_dev_info *devinfo)
DATA_OUT_URB_INFLIGHT);
uas_try_complete(cmnd, __func__);
}
+   devinfo->running_task = 0;
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
@@ -340,6 +342,9 @@ static void uas_stat_cmplt(struct urb *urb)
 
if (!cmnd) {
if (iu->iu_id == IU_ID_RESPONSE) {
+   if (!devinfo->running_task)
+   dev_warn(&urb->dev->dev,
+   "stat urb: recv unexpected response iu\n");
/* store results for uas_eh_task_mgmt() */
memcpy(&devinfo->response, iu, 
sizeof(devinfo->response));
}
@@ -726,14 +731,26 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
u16 tag = devinfo->qdepth;
unsigned long flags;
struct urb *sense_urb;
+   int result = SUCCESS;
 
spin_lock_irqsave(&devinfo->lock, flags);
+
+   if (devinfo->running_task) {
+   shost_printk(KERN_INFO, shost,
+"%s: %s: error already running a task\n",
+__func__, fname);
+   spin_unlock_irqrestore(&devinfo->lock, flags);
+   return FAILED;
+   }
+
+   devinfo->running_task = 1;
memset(&devinfo->response, 0, sizeof(devinfo->response));
sense_urb = uas_submit_sense_urb(shost, GFP_ATOMIC, tag);
if (!sense_urb) {
shost_printk(KERN_INFO, shost,
 "%s: %s: submit sense urb failed\n",
 __func__, fname);
+   devinfo->running_task = 0;
spin_unlock_irqrestore(&devinfo->lock, flags);
return FAILED;
}
@@ -741,6 +758,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
shost_printk(KERN_INFO, shost,
 "%s: %s: submit task mgmt urb failed\n",
 __func__, fname);
+   devinfo->running_task = 0;
spin_unlock_irqrestore(&devinfo->lock, flags);
usb_kill_urb(sense_urb);
return FAILED;
@@ -748,23 +766,33 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
spin_unlock_irqrestore(&devinfo->lock, flags);
 
if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) {
+   /*
+* Note we deliberately do not clear running_task here. If we
+* allow new tasks to be submitted, there is no way to figure
+* out if a received response_iu is for the failed task or for
+* the new one. A bus-reset will eventually clear running_task.
+*/
shost_printk(KERN_INFO, shost,
 "%s: %s timed out\n", __func__, fname);
return FAILED;
}
+
+   spin_lock_irqsave(&devinfo->lock, flags);
+   devinfo->running_task = 0;
if (be16_to_cpu(devinfo->response.tag) != tag) {
shost_printk(KERN_INFO, shost,
 "%s: %s failed (wrong tag %d/%d)\n", __func__,
 fname, be16_to_cpu(devinfo->response.tag), tag);
-   return FAILED;
-   }
-   if (devinfo->response.response_code != RC_TMF_COMPLETE) {
+   result = FAILED;
+   } else if (devinfo->response.response_code != RC_TMF_COMPLETE) {
shost_printk(KERN_INFO, shost,
 "%s: %s failed (rc 0x%x)\n", __func__,
 fname, devinfo->response.response_code);
-   return FAILED;
+   result = FAILED;
}
-   return SUCCESS;
+   spin_unlock_irqrestore(&devinfo->lock, flags);
+
+   return result;
 }
 
 static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
@@ -982,6 +1010,7 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
devinfo->intf = intf;
devinfo->udev = udev;
devinfo->resetting = 0;
+   

[PATCH 72/76] xhci: Refactor command watchdog and fix split string.

2014-03-06 Thread Sarah Sharp
In preparation for fixing this function for streams endpoints, refactor
code in the command watchdog timeout function into two new functions.
One kills all URBs on a ring (either stream or endpoint), the other
kills all URBs associated with an endpoint.  Fix a split string while
we're at it.

Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-ring.c | 70 
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b3d27e6467ea..58cbc06ecdf9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -900,6 +900,43 @@ remove_finished_td:
/* Return to the event handler with xhci->lock re-acquired */
 }
 
+static void xhci_kill_ring_urbs(struct xhci_hcd *xhci, struct xhci_ring *ring)
+{
+   struct xhci_td *cur_td;
+
+   while (!list_empty(&ring->td_list)) {
+   cur_td = list_first_entry(&ring->td_list,
+   struct xhci_td, td_list);
+   list_del_init(&cur_td->td_list);
+   if (!list_empty(&cur_td->cancelled_td_list))
+   list_del_init(&cur_td->cancelled_td_list);
+   xhci_giveback_urb_in_irq(xhci, cur_td, -ESHUTDOWN);
+   }
+}
+
+static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
+   int slot_id, int ep_index)
+{
+   struct xhci_td *cur_td;
+   struct xhci_virt_ep *ep;
+   struct xhci_ring *ring;
+
+   ep = &xhci->devs[slot_id]->eps[ep_index];
+   ring = ep->ring;
+   if (!ring)
+   return;
+   xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
+   "Killing URBs for slot ID %u, ep index %u",
+   slot_id, ep_index);
+   xhci_kill_ring_urbs(xhci, ring);
+   while (!list_empty(&ep->cancelled_td_list)) {
+   cur_td = list_first_entry(&ep->cancelled_td_list,
+   struct xhci_td, cancelled_td_list);
+   list_del_init(&cur_td->cancelled_td_list);
+   xhci_giveback_urb_in_irq(xhci, cur_td, -ESHUTDOWN);
+   }
+}
+
 /* Watchdog timer function for when a stop endpoint command fails to complete.
  * In this case, we assume the host controller is broken or dying or dead.  The
  * host may still be completing some other events, so we have to be careful to
@@ -923,9 +960,6 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
 {
struct xhci_hcd *xhci;
struct xhci_virt_ep *ep;
-   struct xhci_virt_ep *temp_ep;
-   struct xhci_ring *ring;
-   struct xhci_td *cur_td;
int ret, i, j;
unsigned long flags;
 
@@ -982,34 +1016,8 @@ void xhci_stop_endpoint_command_watchdog(unsigned long 
arg)
for (i = 0; i < MAX_HC_SLOTS; i++) {
if (!xhci->devs[i])
continue;
-   for (j = 0; j < 31; j++) {
-   temp_ep = &xhci->devs[i]->eps[j];
-   ring = temp_ep->ring;
-   if (!ring)
-   continue;
-   xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-   "Killing URBs for slot ID %u, "
-   "ep index %u", i, j);
-   while (!list_empty(&ring->td_list)) {
-   cur_td = list_first_entry(&ring->td_list,
-   struct xhci_td,
-   td_list);
-   list_del_init(&cur_td->td_list);
-   if (!list_empty(&cur_td->cancelled_td_list))
-   
list_del_init(&cur_td->cancelled_td_list);
-   xhci_giveback_urb_in_irq(xhci, cur_td,
-   -ESHUTDOWN);
-   }
-   while (!list_empty(&temp_ep->cancelled_td_list)) {
-   cur_td = list_first_entry(
-   &temp_ep->cancelled_td_list,
-   struct xhci_td,
-   cancelled_td_list);
-   list_del_init(&cur_td->cancelled_td_list);
-   xhci_giveback_urb_in_irq(xhci, cur_td,
-   -ESHUTDOWN);
-   }
-   }
+   for (j = 0; j < 31; j++)
+   xhci_kill_endpoint_urbs(xhci, i, j);
}
spin_unlock_irqrestore(&xhci->lock, flags);
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
-- 
1.8.5.5

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


[PATCH 64/76] uas: Clear cmdinfo on command queue-ing

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The scsi error handling path re-uses previously queued up (and errored-out)
cmds. If such a re-used cmd had a data-phase then cmdinfo will have
data_in_urb / data_out_urb still set to the free-ed urbs from the errored-out
cmd, and they will get free-ed a second time when the error handling cmd
completes, corrupting the kernel heap.

Clearing cmdinfo on command queue-ing fixes this, and seems like a good idea
in general.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index d81d041842f4..fceffccc1be1 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -684,6 +684,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
return SCSI_MLQUEUE_DEVICE_BUSY;
}
 
+   memset(cmdinfo, 0, sizeof(*cmdinfo));
+
if (blk_rq_tagged(cmnd->request)) {
cmdinfo->stream = cmnd->request->tag + 2;
} else {
-- 
1.8.5.5

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


[PATCH 71/76] uas: Remove comment about registering a uas scsi controller for each usb bus

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Although an interesting concept, I don't think that this is a good idea:

-This will result in lots of "virtual" scsi controllers confusing users
-If we get a scsi-bus-reset we will now need to do a usb-device-reset of all
 uas devices on the same usb bus, which is something to avoid if possible

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 08e9710f193d..a7ac97cc5949 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -1050,12 +1050,6 @@ static void uas_free_streams(struct uas_dev_info 
*devinfo)
usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL);
 }
 
-/*
- * XXX: What I'd like to do here is register a SCSI host for each USB host in
- * the system.  Follow usb-storage's design of registering a SCSI host for
- * each USB device for the moment.  Can implement this by walking up the
- * USB hierarchy until we find a USB host.
- */
 static int uas_probe(struct usb_interface *intf, const struct usb_device_id 
*id)
 {
int result = -ENOMEM;
-- 
1.8.5.5

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


[PATCH 37/76] xhci: xhci_mem_cleanup: make sure cmd_ring_reserved_trbs really is 0

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

cmd_ring_reserved_trbs gets decremented by xhci_free_stream_info(), so set it
to 0 after freeing all rings, otherwise it wraps around to a very large value
when rings with streams are free-ed.

Before this patch the wrap-around could be triggered when xhci_resume
calls xhci_mem_cleanup if the controller resume fails.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-mem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index edfb31ad5949..60fc6720007f 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1812,7 +1812,6 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
if (xhci->lpm_command)
xhci_free_command(xhci, xhci->lpm_command);
-   xhci->cmd_ring_reserved_trbs = 0;
if (xhci->cmd_ring)
xhci_ring_free(xhci, xhci->cmd_ring);
xhci->cmd_ring = NULL;
@@ -1877,6 +1876,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
}
 
 no_bw:
+   xhci->cmd_ring_reserved_trbs = 0;
xhci->num_usb2_ports = 0;
xhci->num_usb3_ports = 0;
xhci->num_active_eps = 0;
-- 
1.8.5.5

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


[PATCH 40/76] usb: Clear host_endpoint->streams when implicitly freeing streams

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

If streams are still allocated on device-reset or set-interface then the hcd
code implictly frees the streams. Clear host_endpoint->streams in this case
so that if a driver later tries to re-allocate them it won't run afoul of the
device already having streams check in usb_alloc_streams().

Note normally streams still being allocated at reset / set-intf  would be a
driver bug, but this can happen without it being a driver bug on reset-resume.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/hub.c | 5 -
 drivers/usb/core/message.c | 7 +--
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 763c3134dd78..4f7629d1ba6a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5131,7 +5131,7 @@ static int usb_reset_and_verify_device(struct usb_device 
*udev)
struct usb_hcd  *hcd = bus_to_hcd(udev->bus);
struct usb_device_descriptordescriptor = udev->descriptor;
struct usb_host_bos *bos;
-   int i, ret = 0;
+   int i, j, ret = 0;
int port1 = udev->portnum;
 
if (udev->state == USB_STATE_NOTATTACHED ||
@@ -5257,6 +5257,9 @@ static int usb_reset_and_verify_device(struct usb_device 
*udev)
ret);
goto re_enumerate;
}
+   /* Resetting also frees any allocated streams */
+   for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++)
+   intf->cur_altsetting->endpoint[j].streams = 0;
}
 
 done:
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index f829a1aad1c3..964695741031 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1293,8 +1293,7 @@ int usb_set_interface(struct usb_device *dev, int 
interface, int alternate)
struct usb_interface *iface;
struct usb_host_interface *alt;
struct usb_hcd *hcd = bus_to_hcd(dev->bus);
-   int ret;
-   int manual = 0;
+   int i, ret, manual = 0;
unsigned int epaddr;
unsigned int pipe;
 
@@ -1329,6 +1328,10 @@ int usb_set_interface(struct usb_device *dev, int 
interface, int alternate)
mutex_unlock(hcd->bandwidth_mutex);
return -ENOMEM;
}
+   /* Changing alt-setting also frees any allocated streams */
+   for (i = 0; i < iface->cur_altsetting->desc.bNumEndpoints; i++)
+   iface->cur_altsetting->endpoint[i].streams = 0;
+
ret = usb_hcd_alloc_bandwidth(dev, NULL, iface->cur_altsetting, alt);
if (ret < 0) {
dev_info(&dev->dev, "Not enough bandwidth for altsetting %d\n",
-- 
1.8.5.5

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


[PATCH 30/76] uas: Fix reset handling for externally triggered reset

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Handle usb-device resets not triggered from uas_eh_bus_reset_handler(), when
this happens, disable cmd queuing during the reset, and wait for existing
requests to finish in pre_reset.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 36ef82a34131..0ee5a05c0a7b 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -18,6 +18,7 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -818,10 +819,7 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd)
usb_kill_anchored_urbs(&devinfo->sense_urbs);
usb_kill_anchored_urbs(&devinfo->data_urbs);
uas_zap_dead(devinfo);
-   uas_free_streams(devinfo);
err = usb_reset_device(udev);
-   if (!err)
-   uas_configure_endpoints(devinfo);
devinfo->resetting = 0;
 
usb_unlock_device(udev);
@@ -1055,13 +1053,41 @@ set_alt0:
 
 static int uas_pre_reset(struct usb_interface *intf)
 {
-/* XXX: Need to return 1 if it's not our device in error handling */
+   struct Scsi_Host *shost = usb_get_intfdata(intf);
+   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   unsigned long flags;
+
+   /* Block new requests */
+   spin_lock_irqsave(shost->host_lock, flags);
+   scsi_block_requests(shost);
+   spin_unlock_irqrestore(shost->host_lock, flags);
+
+   /* Wait for any pending requests to complete */
+   flush_work(&devinfo->work);
+   if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000) == 0) {
+   shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__);
+   return 1;
+   }
+
+   uas_free_streams(devinfo);
+
return 0;
 }
 
 static int uas_post_reset(struct usb_interface *intf)
 {
-/* XXX: Need to return 1 if it's not our device in error handling */
+   struct Scsi_Host *shost = usb_get_intfdata(intf);
+   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   unsigned long flags;
+
+   uas_configure_endpoints(devinfo);
+
+   spin_lock_irqsave(shost->host_lock, flags);
+   scsi_report_bus_reset(shost, 0);
+   spin_unlock_irqrestore(shost->host_lock, flags);
+
+   scsi_unblock_requests(shost);
+
return 0;
 }
 
-- 
1.8.5.5

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


[PATCH 31/76] uas: s/response_ui/response_iu/

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 2 +-
 include/linux/usb/uas.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 0ee5a05c0a7b..33f9dcd68e24 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -46,7 +46,7 @@ struct uas_dev_info {
struct usb_anchor sense_urbs;
struct usb_anchor data_urbs;
int qdepth, resetting;
-   struct response_ui response;
+   struct response_iu response;
unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe;
unsigned use_streams:1;
unsigned uas_sense_old:1;
diff --git a/include/linux/usb/uas.h b/include/linux/usb/uas.h
index 5499ab5c94bd..14041780fb6c 100644
--- a/include/linux/usb/uas.h
+++ b/include/linux/usb/uas.h
@@ -79,7 +79,7 @@ struct sense_iu {
__u8 sense[SCSI_SENSE_BUFFERSIZE];
 };
 
-struct response_ui {
+struct response_iu {
__u8 iu_id;
__u8 rsvd1;
__be16 tag;
-- 
1.8.5.5

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


[PATCH 61/76] uas: cmdinfo: use only one list head

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

cmds are either on the inflight list or on the dead list, never both, so
we only need one list head.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 20 
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 7810c135a69e..cfe0102fcbae 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -86,8 +86,7 @@ struct uas_cmd_info {
struct urb *cmd_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
-   struct list_head inflight;
-   struct list_head dead;
+   struct list_head list;
 };
 
 /* I hate forward declarations, but I actually have a loop */
@@ -129,7 +128,7 @@ static void uas_do_work(struct work_struct *work)
int err;
 
spin_lock_irqsave(&devinfo->lock, flags);
-   list_for_each_entry(cmdinfo, &devinfo->inflight_list, inflight) {
+   list_for_each_entry(cmdinfo, &devinfo->inflight_list, list) {
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
@@ -157,8 +156,7 @@ static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
cmdinfo->state |= COMMAND_ABORTED;
cmdinfo->state &= ~IS_IN_WORK_LIST;
-   list_del(&cmdinfo->inflight);
-   list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
+   list_move_tail(&cmdinfo->list, &devinfo->dead_list);
 }
 
 static void uas_abort_inflight(struct uas_dev_info *devinfo)
@@ -168,8 +166,7 @@ static void uas_abort_inflight(struct uas_dev_info *devinfo)
unsigned long flags;
 
spin_lock_irqsave(&devinfo->lock, flags);
-   list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list,
-inflight)
+   list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list, list)
uas_mark_cmd_dead(devinfo, cmdinfo, __func__);
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
@@ -192,7 +189,7 @@ static void uas_zap_dead(struct uas_dev_info *devinfo)
unsigned long flags;
 
spin_lock_irqsave(&devinfo->lock, flags);
-   list_for_each_entry_safe(cmdinfo, temp, &devinfo->dead_list, dead) {
+   list_for_each_entry_safe(cmdinfo, temp, &devinfo->dead_list, list) {
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
@@ -295,9 +292,8 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const 
char *caller)
if (cmdinfo->state & COMMAND_ABORTED) {
scmd_printk(KERN_INFO, cmnd, "abort completed\n");
cmnd->result = DID_ABORT << 16;
-   list_del(&cmdinfo->dead);
-   } else
-   list_del(&cmdinfo->inflight);
+   }
+   list_del(&cmdinfo->list);
cmnd->scsi_done(cmnd);
return 0;
 }
@@ -725,7 +721,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
uas_add_work(cmdinfo);
}
 
-   list_add_tail(&cmdinfo->inflight, &devinfo->inflight_list);
+   list_add_tail(&cmdinfo->list, &devinfo->inflight_list);
spin_unlock_irqrestore(&devinfo->lock, flags);
return 0;
 }
-- 
1.8.5.5

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


[PATCH 39/76] xhci: Handle MaxPSASize == 0

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 6cb9c2235a0b..1db3c2794a49 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3138,6 +3138,12 @@ int xhci_alloc_streams(struct usb_hcd *hcd, struct 
usb_device *udev,
xhci_dbg(xhci, "Driver wants %u stream IDs (including stream 0).\n",
num_streams);
 
+   /* MaxPSASize value 0 (2 streams) means streams are not supported */
+   if (HCC_MAX_PSA(xhci->hcc_params) < 4) {
+   xhci_dbg(xhci, "xHCI controller does not support streams.\n");
+   return -ENOSYS;
+   }
+
config_cmd = xhci_alloc_command(xhci, true, true, mem_flags);
if (!config_cmd) {
xhci_dbg(xhci, "Could not allocate xHCI command structure.\n");
-- 
1.8.5.5

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


[PATCH 66/76] uas: Improve error reporting

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 60 ---
 1 file changed, 46 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 6ec48c2daf45..f09205b162e4 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -411,6 +411,12 @@ static void uas_data_cmplt(struct urb *urb)
if (sdb == NULL) {
WARN_ON_ONCE(1);
} else if (urb->status) {
+   if (urb->status != -ECONNRESET) {
+   uas_log_cmd_state(cmnd, __func__);
+   scmd_printk(KERN_ERR, cmnd,
+   "data cmplt err %d stream %d\n",
+   urb->status, urb->stream_id);
+   }
/* error: no data transfered */
sdb->resid = sdb->length;
} else {
@@ -420,6 +426,17 @@ static void uas_data_cmplt(struct urb *urb)
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
+static void uas_cmd_cmplt(struct urb *urb)
+{
+   struct scsi_cmnd *cmnd = urb->context;
+
+   if (urb->status) {
+   uas_log_cmd_state(cmnd, __func__);
+   scmd_printk(KERN_ERR, cmnd, "cmd cmplt err %d\n", urb->status);
+   }
+   usb_free_urb(urb);
+}
+
 static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp,
  unsigned int pipe, u16 stream_id,
  struct scsi_cmnd *cmnd,
@@ -497,7 +514,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info 
*devinfo, gfp_t gfp,
memcpy(iu->cdb, cmnd->cmnd, cmnd->cmd_len);
 
usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu) + len,
-   usb_free_urb, NULL);
+   uas_cmd_cmplt, cmnd);
urb->transfer_flags |= URB_FREE_BUFFER;
  out:
return urb;
@@ -537,13 +554,15 @@ static int uas_submit_task_urb(struct scsi_cmnd *cmnd, 
gfp_t gfp,
}
 
usb_fill_bulk_urb(urb, udev, devinfo->cmd_pipe, iu, sizeof(*iu),
- usb_free_urb, NULL);
+ uas_cmd_cmplt, cmnd);
urb->transfer_flags |= URB_FREE_BUFFER;
 
usb_anchor_urb(urb, &devinfo->cmd_urbs);
err = usb_submit_urb(urb, gfp);
if (err) {
usb_unanchor_urb(urb);
+   uas_log_cmd_state(cmnd, __func__);
+   scmd_printk(KERN_ERR, cmnd, "task submission err %d\n", err);
goto err;
}
 
@@ -560,20 +579,25 @@ err:
  * daft to me.
  */
 
-static struct urb *uas_submit_sense_urb(struct Scsi_Host *shost,
+static struct urb *uas_submit_sense_urb(struct scsi_cmnd *cmnd,
gfp_t gfp, unsigned int stream)
 {
+   struct Scsi_Host *shost = cmnd->device->host;
struct uas_dev_info *devinfo = (struct uas_dev_info *)shost->hostdata;
struct urb *urb;
+   int err;
 
urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
if (!urb)
return NULL;
usb_anchor_urb(urb, &devinfo->sense_urbs);
-   if (usb_submit_urb(urb, gfp)) {
+   err = usb_submit_urb(urb, gfp);
+   if (err) {
usb_unanchor_urb(urb);
+   uas_log_cmd_state(cmnd, __func__);
shost_printk(KERN_INFO, shost,
-"sense urb submission failure\n");
+"sense urb submission error %d stream %d\n",
+err, stream);
usb_free_urb(urb);
return NULL;
}
@@ -585,11 +609,11 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 {
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
struct urb *urb;
+   int err;
 
WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
if (cmdinfo->state & SUBMIT_STATUS_URB) {
-   urb = uas_submit_sense_urb(cmnd->device->host, gfp,
-  cmdinfo->stream);
+   urb = uas_submit_sense_urb(cmnd, gfp, cmdinfo->stream);
if (!urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~SUBMIT_STATUS_URB;
@@ -606,10 +630,13 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
 
if (cmdinfo->state & SUBMIT_DATA_IN_URB) {
usb_anchor_urb(cmdinfo->data_in_urb, &devinfo->data_urbs);
-   if (usb_submit_urb(cmdinfo->data_in_urb, gfp)) {
+   err = usb_submit_urb(cmdinfo->data_in_urb, gfp);
+   if (err) {
usb_unanchor_urb(cmdinfo->data_in_urb);
+   uas_log_cmd_state(cmnd, __func__);
scmd_printk(KERN_INFO, cmnd,
-   "data in urb submission fail

[PATCH 76/76] xhci: add the meaningful IRQ description if it is empty

2014-03-06 Thread Sarah Sharp
From: Adrian Huang 

When some xHCI host controllers fall back to use the legacy IRQ,
the member irq_descr of the usb_hcd structure will be empty. This
leads to the empty string of the xHCI host controller in
/proc/interrupts. Here is the example (The irq 19 is the xHCI host
controller):

   CPU0
  0: 91 IO-APIC-edgetimer
  8:  1 IO-APIC-edgertc0
  9:   7191 IO-APIC-fasteoi acpi
 18:104 IR-IO-APIC-fasteoi  ehci_hcd:usb1, ehci_hcd:usb2
 19:473 IR-IO-APIC-fasteoi

After applying the patch, the name of the registered xHCI host
controller can be displayed correctly. Here is the example:

   CPU0
  0: 91 IO-APIC-edgetimer
  8:  1 IO-APIC-edgertc0
  9:   7191 IO-APIC-fasteoi acpi
 18:104 IR-IO-APIC-fasteoi  ehci_hcd:usb1, ehci_hcd:usb2
 19:473 IR-IO-APIC-fasteoi  xhci_hcd:usb3

Tested on v3.14-rc4.

Signed-off-by: Adrian Huang 
Reviewed-by: Nagananda Chumbalkar 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1db3c2794a49..652be2138b4b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -390,6 +390,10 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
}
 
  legacy_irq:
+   if (!strlen(hcd->irq_descr))
+   snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+hcd->driver->description, hcd->self.busnum);
+
/* fall back to legacy interrupt*/
ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
hcd->irq_descr, hcd);
-- 
1.8.5.5

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


[PATCH 62/76] uas: Fix command / task mgmt submission racing with disconnect

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index cfe0102fcbae..8c685801e267 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -670,13 +670,15 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
 
BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer));
 
+   spin_lock_irqsave(&devinfo->lock, flags);
+
if (devinfo->resetting) {
cmnd->result = DID_ERROR << 16;
cmnd->scsi_done(cmnd);
+   spin_unlock_irqrestore(&devinfo->lock, flags);
return 0;
}
 
-   spin_lock_irqsave(&devinfo->lock, flags);
if (devinfo->cmnd) {
spin_unlock_irqrestore(&devinfo->lock, flags);
return SCSI_MLQUEUE_DEVICE_BUSY;
@@ -740,6 +742,11 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 
spin_lock_irqsave(&devinfo->lock, flags);
 
+   if (devinfo->resetting) {
+   spin_unlock_irqrestore(&devinfo->lock, flags);
+   return FAILED;
+   }
+
if (devinfo->running_task) {
shost_printk(KERN_INFO, shost,
 "%s: %s: error already running a task\n",
@@ -809,6 +816,12 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
int ret;
 
spin_lock_irqsave(&devinfo->lock, flags);
+
+   if (devinfo->resetting) {
+   spin_unlock_irqrestore(&devinfo->lock, flags);
+   return FAILED;
+   }
+
uas_mark_cmd_dead(devinfo, cmdinfo, __func__);
if (cmdinfo->state & COMMAND_INFLIGHT) {
spin_unlock_irqrestore(&devinfo->lock, flags);
-- 
1.8.5.5

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


[PATCH 70/76] uas: Add Hans de Goede as uas maintainer

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

At the kernel-summit Sarah Sharp asked me if I was willing to become the
uas maintainer. I said yes, and here is a patch to make this official.

Also remove Matthew Wilcox and Sarah Sharp as maintainers at their request.

I've also added myself to the module's author tag, so that if people look there
rather then in maintainers they will know they should bug me about uas too.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 MAINTAINERS   | 3 +--
 drivers/usb/storage/uas.c | 4 +++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index c6d0e93eff62..fc536bc74300 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9063,8 +9063,7 @@ S:Maintained
 F: drivers/net/wireless/ath/ar5523/
 
 USB ATTACHED SCSI
-M: Matthew Wilcox 
-M: Sarah Sharp 
+M: Hans de Goede 
 M: Gerd Hoffmann 
 L: linux-usb@vger.kernel.org
 L: linux-s...@vger.kernel.org
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index ad97615b75b1..08e9710f193d 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -2,6 +2,7 @@
  * USB Attached SCSI
  * Note that this is not the same as the USB Mass Storage driver
  *
+ * Copyright Hans de Goede  for Red Hat, Inc. 2013
  * Copyright Matthew Wilcox for Intel Corp, 2010
  * Copyright Sarah Sharp for Intel Corp, 2010
  *
@@ -1261,4 +1262,5 @@ static struct usb_driver uas_driver = {
 module_usb_driver(uas_driver);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Matthew Wilcox and Sarah Sharp");
+MODULE_AUTHOR(
+   "Hans de Goede , Matthew Wilcox and Sarah Sharp");
-- 
1.8.5.5

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


[PATCH 46/76] uas: Add uas_find_endpoints() helper function

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This is a preparation patch for adding better descriptor validation.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 34 +++---
 1 file changed, 23 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index e817e72d8673..1ac66f290fbf 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -898,16 +898,11 @@ static int uas_switch_interface(struct usb_device *udev,
intf->altsetting[0].desc.bInterfaceNumber, alt);
 }
 
-static void uas_configure_endpoints(struct uas_dev_info *devinfo)
+static int uas_find_endpoints(struct usb_host_interface *alt,
+ struct usb_host_endpoint *eps[])
 {
-   struct usb_host_endpoint *eps[4] = { };
-   struct usb_interface *intf = devinfo->intf;
-   struct usb_device *udev = devinfo->udev;
-   struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
-   unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints;
-
-   devinfo->uas_sense_old = 0;
-   devinfo->cmnd = NULL;
+   struct usb_host_endpoint *endpoint = alt->endpoint;
+   unsigned i, n_endpoints = alt->desc.bNumEndpoints;
 
for (i = 0; i < n_endpoints; i++) {
unsigned char *extra = endpoint[i].extra;
@@ -924,12 +919,29 @@ static void uas_configure_endpoints(struct uas_dev_info 
*devinfo)
}
}
 
+   if (!eps[0] || !eps[1] || !eps[2] || !eps[3])
+   return -ENODEV;
+
+   return 0;
+}
+
+static void uas_configure_endpoints(struct uas_dev_info *devinfo)
+{
+   struct usb_host_endpoint *eps[4] = { };
+   struct usb_device *udev = devinfo->udev;
+   int r;
+
+   devinfo->uas_sense_old = 0;
+   devinfo->cmnd = NULL;
+
+   r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps);
+
/*
-* Assume that if we didn't find a control pipe descriptor, we're
+* Assume that if we didn't find a proper set of descriptors, we're
 * using a device with old firmware that happens to be set up like
 * this.
 */
-   if (!eps[0]) {
+   if (r != 0) {
devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
-- 
1.8.5.5

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


[PATCH 67/76] uas: Add some data in/out ready iu sanity checks

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index f09205b162e4..62086829af14 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -379,9 +379,19 @@ static void uas_stat_cmplt(struct urb *urb)
uas_try_complete(cmnd, __func__);
break;
case IU_ID_READ_READY:
+   if (!cmdinfo->data_in_urb ||
+   (cmdinfo->state & DATA_IN_URB_INFLIGHT)) {
+   scmd_printk(KERN_ERR, cmnd, "unexpected read rdy\n");
+   break;
+   }
uas_xfer_data(urb, cmnd, SUBMIT_DATA_IN_URB);
break;
case IU_ID_WRITE_READY:
+   if (!cmdinfo->data_out_urb ||
+   (cmdinfo->state & DATA_OUT_URB_INFLIGHT)) {
+   scmd_printk(KERN_ERR, cmnd, "unexpected write rdy\n");
+   break;
+   }
uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
break;
default:
-- 
1.8.5.5

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


[PATCH 60/76] uas: add uas_mark_cmd_dead helper function

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 35 ++-
 1 file changed, 18 insertions(+), 17 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 1a188399e090..7810c135a69e 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -146,6 +146,21 @@ static void uas_do_work(struct work_struct *work)
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
+static void uas_mark_cmd_dead(struct uas_dev_info *devinfo,
+ struct uas_cmd_info *cmdinfo, const char *caller)
+{
+   struct scsi_pointer *scp = (void *)cmdinfo;
+   struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp);
+
+   uas_log_cmd_state(cmnd, caller);
+   WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
+   WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
+   cmdinfo->state |= COMMAND_ABORTED;
+   cmdinfo->state &= ~IS_IN_WORK_LIST;
+   list_del(&cmdinfo->inflight);
+   list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
+}
+
 static void uas_abort_inflight(struct uas_dev_info *devinfo)
 {
struct uas_cmd_info *cmdinfo;
@@ -154,17 +169,8 @@ static void uas_abort_inflight(struct uas_dev_info 
*devinfo)
 
spin_lock_irqsave(&devinfo->lock, flags);
list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list,
-inflight) {
-   struct scsi_pointer *scp = (void *)cmdinfo;
-   struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
- SCp);
-   uas_log_cmd_state(cmnd, __func__);
-   WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
-   cmdinfo->state |= COMMAND_ABORTED;
-   cmdinfo->state &= ~IS_IN_WORK_LIST;
-   list_del(&cmdinfo->inflight);
-   list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
-   }
+inflight)
+   uas_mark_cmd_dead(devinfo, cmdinfo, __func__);
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
@@ -806,13 +812,8 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
unsigned long flags;
int ret;
 
-   uas_log_cmd_state(cmnd, __func__);
spin_lock_irqsave(&devinfo->lock, flags);
-   WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
-   cmdinfo->state |= COMMAND_ABORTED;
-   cmdinfo->state &= ~IS_IN_WORK_LIST;
-   list_del(&cmdinfo->inflight);
-   list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
+   uas_mark_cmd_dead(devinfo, cmdinfo, __func__);
if (cmdinfo->state & COMMAND_INFLIGHT) {
spin_unlock_irqrestore(&devinfo->lock, flags);
ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
-- 
1.8.5.5

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


[PATCH 59/76] uas: Properly complete inflight commands on bus-reset or disconnect

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Before this commit the uas driver would keep track of scsi commands which still
need to have some urbs submitted to the device, and complete this with an
ABORT result code on bus-reset or disconnect, but in flight scsi commands
which have all their urbs submitted, and thus are not part of the work list,
would never get their done callback called.

The problem is killed sense urbs don't have any tag info, so it is impossible
to tell which scsi cmd they belong to, so merely making sure all the urbs
have completed one way or the other is not enough.

This commit fixes this by changing the work list to an inflight list, which
keeps tracks of all inflight scsi cmnds, using the IS_IN_WORK_LIST flag to
determine if actual work needs to be done in uas_do_work(), and by moving
marking all inflight scsi commands as aborted and moving them to the dead list
on bus-reset or disconnect.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 41 +
 1 file changed, 21 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index e06505c8f6f0..1a188399e090 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -58,7 +58,7 @@ struct uas_dev_info {
struct scsi_cmnd *cmnd;
spinlock_t lock;
struct work_struct work;
-   struct list_head work_list;
+   struct list_head inflight_list;
struct list_head dead_list;
 };
 
@@ -86,7 +86,7 @@ struct uas_cmd_info {
struct urb *cmd_urb;
struct urb *data_in_urb;
struct urb *data_out_urb;
-   struct list_head work;
+   struct list_head inflight;
struct list_head dead;
 };
 
@@ -125,34 +125,36 @@ static void uas_do_work(struct work_struct *work)
struct uas_dev_info *devinfo =
container_of(work, struct uas_dev_info, work);
struct uas_cmd_info *cmdinfo;
-   struct uas_cmd_info *temp;
unsigned long flags;
int err;
 
spin_lock_irqsave(&devinfo->lock, flags);
-   list_for_each_entry_safe(cmdinfo, temp, &devinfo->work_list, work) {
+   list_for_each_entry(cmdinfo, &devinfo->inflight_list, inflight) {
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
+
+   if (!(cmdinfo->state & IS_IN_WORK_LIST))
+   continue;
+
err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
-   if (!err) {
+   if (!err)
cmdinfo->state &= ~IS_IN_WORK_LIST;
-   list_del(&cmdinfo->work);
-   } else {
+   else
schedule_work(&devinfo->work);
-   }
}
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
-static void uas_abort_work(struct uas_dev_info *devinfo)
+static void uas_abort_inflight(struct uas_dev_info *devinfo)
 {
struct uas_cmd_info *cmdinfo;
struct uas_cmd_info *temp;
unsigned long flags;
 
spin_lock_irqsave(&devinfo->lock, flags);
-   list_for_each_entry_safe(cmdinfo, temp, &devinfo->work_list, work) {
+   list_for_each_entry_safe(cmdinfo, temp, &devinfo->inflight_list,
+inflight) {
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
@@ -160,7 +162,7 @@ static void uas_abort_work(struct uas_dev_info *devinfo)
WARN_ON_ONCE(cmdinfo->state & COMMAND_ABORTED);
cmdinfo->state |= COMMAND_ABORTED;
cmdinfo->state &= ~IS_IN_WORK_LIST;
-   list_del(&cmdinfo->work);
+   list_del(&cmdinfo->inflight);
list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
}
spin_unlock_irqrestore(&devinfo->lock, flags);
@@ -173,7 +175,6 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
struct uas_dev_info *devinfo = cmnd->device->hostdata;
 
WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
-   list_add_tail(&cmdinfo->work, &devinfo->work_list);
cmdinfo->state |= IS_IN_WORK_LIST;
schedule_work(&devinfo->work);
 }
@@ -289,7 +290,8 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const 
char *caller)
scmd_printk(KERN_INFO, cmnd, "abort completed\n");
cmnd->result = DID_ABORT << 16;
list_del(&cmdinfo->dead);
-   }
+   } else
+   list_del(&cmdinfo->inflight);
cmnd->scsi_done(cmnd);
return 0;
 }
@@ -717,6 +719,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
uas_add_work(cmdinfo);
}
 
+   list_add_tail(&cmdinfo->inflight, &devinfo

[PATCH 10/76] xhci: Remove segments from radix tree on failed insert.

2014-03-06 Thread Sarah Sharp
If we're expanding a stream ring, we want to make sure we can add those
ring segments to the radix tree that maps segments to ring pointers.
Try the radix tree insert after the new ring segments have been allocated
(the last segment in the new ring chunk will point to the first newly
allocated segment), but before the new ring segments are linked into the
old ring.

If insert fails on any one segment, remove each segment from the radix
tree, deallocate the new segments, and return.  Otherwise, link the new
segments into the tree.

HdG: Add a check to only update stream mappings in xhci_ring_expansion when
the ring is a stream ring.

Signed-off-by: Sarah Sharp 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-mem.c | 107 +---
 1 file changed, 81 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index be7b7b6b5517..edfb31ad5949 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -180,53 +180,98 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct 
xhci_ring *ring,
  * extended systems (where the DMA address can be bigger than 32-bits),
  * if we allow the PCI dma mask to be bigger than 32-bits.  So don't do that.
  */
-static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
+static int xhci_insert_segment_mapping(struct radix_tree_root *trb_address_map,
+   struct xhci_ring *ring,
+   struct xhci_segment *seg,
+   gfp_t mem_flags)
 {
-   struct xhci_segment *seg;
unsigned long key;
int ret;
 
-   if (WARN_ON_ONCE(ring->trb_address_map == NULL))
+   key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
+   /* Skip any segments that were already added. */
+   if (radix_tree_lookup(trb_address_map, key))
return 0;
 
-   seg = ring->first_seg;
-   do {
-   key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
-   /* Skip any segments that were already added. */
-   if (radix_tree_lookup(ring->trb_address_map, key))
-   continue;
+   ret = radix_tree_maybe_preload(mem_flags);
+   if (ret)
+   return ret;
+   ret = radix_tree_insert(trb_address_map,
+   key, ring);
+   radix_tree_preload_end();
+   return ret;
+}
 
-   ret = radix_tree_maybe_preload(mem_flags);
-   if (ret)
-   return ret;
-   ret = radix_tree_insert(ring->trb_address_map,
-   key, ring);
-   radix_tree_preload_end();
+static void xhci_remove_segment_mapping(struct radix_tree_root 
*trb_address_map,
+   struct xhci_segment *seg)
+{
+   unsigned long key;
+
+   key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
+   if (radix_tree_lookup(trb_address_map, key))
+   radix_tree_delete(trb_address_map, key);
+}
+
+static int xhci_update_stream_segment_mapping(
+   struct radix_tree_root *trb_address_map,
+   struct xhci_ring *ring,
+   struct xhci_segment *first_seg,
+   struct xhci_segment *last_seg,
+   gfp_t mem_flags)
+{
+   struct xhci_segment *seg;
+   struct xhci_segment *failed_seg;
+   int ret;
+
+   if (WARN_ON_ONCE(trb_address_map == NULL))
+   return 0;
+
+   seg = first_seg;
+   do {
+   ret = xhci_insert_segment_mapping(trb_address_map,
+   ring, seg, mem_flags);
if (ret)
-   return ret;
+   goto remove_streams;
+   if (seg == last_seg)
+   return 0;
seg = seg->next;
-   } while (seg != ring->first_seg);
+   } while (seg != first_seg);
 
return 0;
+
+remove_streams:
+   failed_seg = seg;
+   seg = first_seg;
+   do {
+   xhci_remove_segment_mapping(trb_address_map, seg);
+   if (seg == failed_seg)
+   return ret;
+   seg = seg->next;
+   } while (seg != first_seg);
+
+   return ret;
 }
 
 static void xhci_remove_stream_mapping(struct xhci_ring *ring)
 {
struct xhci_segment *seg;
-   unsigned long key;
 
if (WARN_ON_ONCE(ring->trb_address_map == NULL))
return;
 
seg = ring->first_seg;
do {
-   key = (unsigned long)(seg->dma >> TRB_SEGMENT_SHIFT);
-   if (radix_tree_lookup(ring->trb_address_map, key))
-   radix_tree_delete(ring->trb_address_map, key);
+   xhci_remove_segment_mapping(ring->trb_address_map, seg);
seg = seg->next;
} while (seg != ring->first_seg);
 }
 
+static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
+{
+   return xhci_upda

[PATCH 55/76] uas: Add suspend/resume support

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 8023944f2501..7a16ed8e8aac 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -1091,6 +1091,45 @@ static int uas_post_reset(struct usb_interface *intf)
return 0;
 }
 
+static int uas_suspend(struct usb_interface *intf, pm_message_t message)
+{
+   struct Scsi_Host *shost = usb_get_intfdata(intf);
+   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+
+   /* Wait for any pending requests to complete */
+   flush_work(&devinfo->work);
+   if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 5000) == 0) {
+   shost_printk(KERN_ERR, shost, "%s: timed out\n", __func__);
+   return -ETIME;
+   }
+
+   return 0;
+}
+
+static int uas_resume(struct usb_interface *intf)
+{
+   return 0;
+}
+
+static int uas_reset_resume(struct usb_interface *intf)
+{
+   struct Scsi_Host *shost = usb_get_intfdata(intf);
+   struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
+   unsigned long flags;
+
+   if (uas_configure_endpoints(devinfo) != 0) {
+   shost_printk(KERN_ERR, shost,
+"%s: alloc streams error after reset", __func__);
+   return -EIO;
+   }
+
+   spin_lock_irqsave(shost->host_lock, flags);
+   scsi_report_bus_reset(shost, 0);
+   spin_unlock_irqrestore(shost->host_lock, flags);
+
+   return 0;
+}
+
 static void uas_disconnect(struct usb_interface *intf)
 {
struct Scsi_Host *shost = usb_get_intfdata(intf);
@@ -1114,6 +1153,9 @@ static struct usb_driver uas_driver = {
.disconnect = uas_disconnect,
.pre_reset = uas_pre_reset,
.post_reset = uas_post_reset,
+   .suspend = uas_suspend,
+   .resume = uas_resume,
+   .reset_resume = uas_reset_resume,
.id_table = uas_usb_ids,
 };
 
-- 
1.8.5.5

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


[PATCH 48/76] uas: Move uas_find_endpoints to uas-detect.h

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

No changes, just the move.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas-detect.h | 27 +++
 drivers/usb/storage/uas.c| 27 ---
 2 files changed, 27 insertions(+), 27 deletions(-)

diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index 082bde1fa74d..8de030a0a4a4 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -40,6 +40,33 @@ static int uas_find_uas_alt_setting(struct usb_interface 
*intf)
return -ENODEV;
 }
 
+static int uas_find_endpoints(struct usb_host_interface *alt,
+ struct usb_host_endpoint *eps[])
+{
+   struct usb_host_endpoint *endpoint = alt->endpoint;
+   unsigned i, n_endpoints = alt->desc.bNumEndpoints;
+
+   for (i = 0; i < n_endpoints; i++) {
+   unsigned char *extra = endpoint[i].extra;
+   int len = endpoint[i].extralen;
+   while (len >= 3) {
+   if (extra[1] == USB_DT_PIPE_USAGE) {
+   unsigned pipe_id = extra[2];
+   if (pipe_id > 0 && pipe_id < 5)
+   eps[pipe_id - 1] = &endpoint[i];
+   break;
+   }
+   len -= extra[0];
+   extra += extra[0];
+   }
+   }
+
+   if (!eps[0] || !eps[1] || !eps[2] || !eps[3])
+   return -ENODEV;
+
+   return 0;
+}
+
 static int uas_use_uas_driver(struct usb_interface *intf,
  const struct usb_device_id *id)
 {
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 7662b3e13c4d..5cedc7f034b6 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -898,33 +898,6 @@ static int uas_switch_interface(struct usb_device *udev,
intf->altsetting[0].desc.bInterfaceNumber, alt);
 }
 
-static int uas_find_endpoints(struct usb_host_interface *alt,
- struct usb_host_endpoint *eps[])
-{
-   struct usb_host_endpoint *endpoint = alt->endpoint;
-   unsigned i, n_endpoints = alt->desc.bNumEndpoints;
-
-   for (i = 0; i < n_endpoints; i++) {
-   unsigned char *extra = endpoint[i].extra;
-   int len = endpoint[i].extralen;
-   while (len >= 3) {
-   if (extra[1] == USB_DT_PIPE_USAGE) {
-   unsigned pipe_id = extra[2];
-   if (pipe_id > 0 && pipe_id < 5)
-   eps[pipe_id - 1] = &endpoint[i];
-   break;
-   }
-   len -= extra[0];
-   extra += extra[0];
-   }
-   }
-
-   if (!eps[0] || !eps[1] || !eps[2] || !eps[3])
-   return -ENODEV;
-
-   return 0;
-}
-
 static void uas_configure_endpoints(struct uas_dev_info *devinfo)
 {
struct usb_host_endpoint *eps[4] = { };
-- 
1.8.5.5

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


[PATCH 42/76] uas: Add the posibilty to blacklist uas devices from using the uas driver

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Once we start supporting uas hardware, and as more and more uas devices
become available, we will likely start seeing broken devices. This patch
prepares for the inevitable need for blacklisting those devices from
using the uas driver (they will use usb-storage instead).

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas-detect.h  | 11 +
 drivers/usb/storage/uas.c | 17 ++---
 drivers/usb/storage/unusual_uas.h | 52 +++
 include/linux/usb_usual.h |  6 +++--
 4 files changed, 80 insertions(+), 6 deletions(-)
 create mode 100644 drivers/usb/storage/unusual_uas.h

diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index 28101c7e6a9f..02bf5ec957f5 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -38,3 +38,14 @@ static int uas_find_uas_alt_setting(struct usb_interface 
*intf)
 
return -ENODEV;
 }
+
+static int uas_use_uas_driver(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+   unsigned long flags = id->driver_info;
+
+   if (flags & US_FL_IGNORE_UAS)
+   return 0;
+
+   return uas_find_uas_alt_setting(intf) >= 0;
+}
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 6ea892f32f74..e817e72d8673 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -866,7 +867,14 @@ static struct scsi_host_template uas_host_template = {
.ordered_tag = 1,
 };
 
+#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \
+   vendorName, productName, useProtocol, useTransport, \
+   initFunction, flags) \
+{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \
+   .driver_info = (flags) }
+
 static struct usb_device_id uas_usb_ids[] = {
+#  include "unusual_uas.h"
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) 
},
{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_UAS) },
/* 0xaa is a prototype device I happen to have access to */
@@ -875,6 +883,8 @@ static struct usb_device_id uas_usb_ids[] = {
 };
 MODULE_DEVICE_TABLE(usb, uas_usb_ids);
 
+#undef UNUSUAL_DEV
+
 static int uas_switch_interface(struct usb_device *udev,
struct usb_interface *intf)
 {
@@ -973,6 +983,9 @@ static int uas_probe(struct usb_interface *intf, const 
struct usb_device_id *id)
struct uas_dev_info *devinfo;
struct usb_device *udev = interface_to_usbdev(intf);
 
+   if (!uas_use_uas_driver(intf, id))
+   return -ENODEV;
+
if (uas_switch_interface(udev, intf))
return -ENODEV;
 
@@ -1083,10 +1096,6 @@ static void uas_disconnect(struct usb_interface *intf)
kfree(devinfo);
 }
 
-/*
- * XXX: Should this plug into libusual so we can auto-upgrade devices from
- * Bulk-Only to UAS?
- */
 static struct usb_driver uas_driver = {
.name = "uas",
.probe = uas_probe,
diff --git a/drivers/usb/storage/unusual_uas.h 
b/drivers/usb/storage/unusual_uas.h
new file mode 100644
index ..724df8ee
--- /dev/null
+++ b/drivers/usb/storage/unusual_uas.h
@@ -0,0 +1,52 @@
+/* Driver for USB Attached SCSI devices - Unusual Devices File
+ *
+ *   (c) 2013 Hans de Goede 
+ *
+ * Based on the same file for the usb-storage driver, which is:
+ *   (c) 2000-2002 Matthew Dharm (mdharm-...@one-eyed-alien.net)
+ *   (c) 2000 Adam J. Richter (a...@yggdrasil.com), Yggdrasil Computing, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * IMPORTANT NOTE: This file must be included in another file which defines
+ * a UNUSUAL_DEV macro before this file is included.
+ */
+
+/*
+ * If you edit this file, please try to keep it sorted first by VendorID,
+ * then by ProductID.
+ *
+ * If you want to add an entry for this file, be sure to include the
+ * following information:
+ * - a patch that adds the entry for your device, including your
+ *   email address right above the entry (plus maybe a brief
+ *   explanation of the reason for the entry),
+ * - lsusb -v output for the 

[PATCH 49/76] uas: Drop fixed endpoint config handling

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The fixed endpoint config code was only necessary to deal with an early
uas prototype which has never been released, so lets drop it and enforce
proper uas endpoint descriptors.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 36 +++-
 1 file changed, 11 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 5cedc7f034b6..754468bbbfdc 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -908,31 +908,17 @@ static void uas_configure_endpoints(struct uas_dev_info 
*devinfo)
devinfo->cmnd = NULL;
 
r = uas_find_endpoints(devinfo->intf->cur_altsetting, eps);
-
-   /*
-* Assume that if we didn't find a proper set of descriptors, we're
-* using a device with old firmware that happens to be set up like
-* this.
-*/
-   if (r != 0) {
-   devinfo->cmd_pipe = usb_sndbulkpipe(udev, 1);
-   devinfo->status_pipe = usb_rcvbulkpipe(udev, 1);
-   devinfo->data_in_pipe = usb_rcvbulkpipe(udev, 2);
-   devinfo->data_out_pipe = usb_sndbulkpipe(udev, 2);
-
-   eps[1] = usb_pipe_endpoint(udev, devinfo->status_pipe);
-   eps[2] = usb_pipe_endpoint(udev, devinfo->data_in_pipe);
-   eps[3] = usb_pipe_endpoint(udev, devinfo->data_out_pipe);
-   } else {
-   devinfo->cmd_pipe = usb_sndbulkpipe(udev,
-usb_endpoint_num(&eps[0]->desc));
-   devinfo->status_pipe = usb_rcvbulkpipe(udev,
-usb_endpoint_num(&eps[1]->desc));
-   devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
-usb_endpoint_num(&eps[2]->desc));
-   devinfo->data_out_pipe = usb_sndbulkpipe(udev,
-usb_endpoint_num(&eps[3]->desc));
-   }
+   if (r)
+   return r;
+
+   devinfo->cmd_pipe = usb_sndbulkpipe(udev,
+   usb_endpoint_num(&eps[0]->desc));
+   devinfo->status_pipe = usb_rcvbulkpipe(udev,
+   usb_endpoint_num(&eps[1]->desc));
+   devinfo->data_in_pipe = usb_rcvbulkpipe(udev,
+   usb_endpoint_num(&eps[2]->desc));
+   devinfo->data_out_pipe = usb_sndbulkpipe(udev,
+   usb_endpoint_num(&eps[3]->desc));
 
devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, 3, 256,
GFP_KERNEL);
-- 
1.8.5.5

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


[PATCH 54/76] uas: Use GFP_NOIO rather then GFP_ATOMIC where possible

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

We can sleep in our own workqueue (which is the whole reason for having
it), and scsi error handlers are also always called from a context which
may sleep.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 7fc4ad207752..8023944f2501 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -133,7 +133,7 @@ static void uas_do_work(struct work_struct *work)
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
-   err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC);
+   err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO);
if (!err) {
cmdinfo->state &= ~IS_IN_WORK_LIST;
list_del(&cmdinfo->work);
@@ -745,7 +745,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 
devinfo->running_task = 1;
memset(&devinfo->response, 0, sizeof(devinfo->response));
-   sense_urb = uas_submit_sense_urb(shost, GFP_ATOMIC, tag);
+   sense_urb = uas_submit_sense_urb(shost, GFP_NOIO, tag);
if (!sense_urb) {
shost_printk(KERN_INFO, shost,
 "%s: %s: submit sense urb failed\n",
@@ -754,7 +754,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
spin_unlock_irqrestore(&devinfo->lock, flags);
return FAILED;
}
-   if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) {
+   if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) {
shost_printk(KERN_INFO, shost,
 "%s: %s: submit task mgmt urb failed\n",
 __func__, fname);
-- 
1.8.5.5

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


[PATCH 52/76] uas: task_mgmt: Kill the sense-urb if we fail to submit the cmd urb

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 24 +---
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index d758faef8664..9c6f9f9804fd 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -550,39 +550,38 @@ err:
  * daft to me.
  */
 
-static int uas_submit_sense_urb(struct Scsi_Host *shost,
-   gfp_t gfp, unsigned int stream)
+static struct urb *uas_submit_sense_urb(struct Scsi_Host *shost,
+   gfp_t gfp, unsigned int stream)
 {
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
struct urb *urb;
 
urb = uas_alloc_sense_urb(devinfo, gfp, shost, stream);
if (!urb)
-   return SCSI_MLQUEUE_DEVICE_BUSY;
+   return NULL;
usb_anchor_urb(urb, &devinfo->sense_urbs);
if (usb_submit_urb(urb, gfp)) {
usb_unanchor_urb(urb);
shost_printk(KERN_INFO, shost,
 "sense urb submission failure\n");
usb_free_urb(urb);
-   return SCSI_MLQUEUE_DEVICE_BUSY;
+   return NULL;
}
-   return 0;
+   return urb;
 }
 
 static int uas_submit_urbs(struct scsi_cmnd *cmnd,
   struct uas_dev_info *devinfo, gfp_t gfp)
 {
struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp;
-   int err;
+   struct urb *urb;
 
WARN_ON_ONCE(!spin_is_locked(&devinfo->lock));
if (cmdinfo->state & SUBMIT_STATUS_URB) {
-   err = uas_submit_sense_urb(cmnd->device->host, gfp,
+   urb = uas_submit_sense_urb(cmnd->device->host, gfp,
   cmdinfo->stream);
-   if (err) {
-   return err;
-   }
+   if (!urb)
+   return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~SUBMIT_STATUS_URB;
}
 
@@ -726,10 +725,12 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
struct uas_dev_info *devinfo = (void *)shost->hostdata[0];
u16 tag = devinfo->qdepth;
unsigned long flags;
+   struct urb *sense_urb;
 
spin_lock_irqsave(&devinfo->lock, flags);
memset(&devinfo->response, 0, sizeof(devinfo->response));
-   if (uas_submit_sense_urb(shost, GFP_ATOMIC, tag)) {
+   sense_urb = uas_submit_sense_urb(shost, GFP_ATOMIC, tag);
+   if (!sense_urb) {
shost_printk(KERN_INFO, shost,
 "%s: %s: submit sense urb failed\n",
 __func__, fname);
@@ -741,6 +742,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd,
 "%s: %s: submit task mgmt urb failed\n",
 __func__, fname);
spin_unlock_irqrestore(&devinfo->lock, flags);
+   usb_kill_urb(sense_urb);
return FAILED;
}
spin_unlock_irqrestore(&devinfo->lock, flags);
-- 
1.8.5.5

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


[PATCH 27/76] uas: uas_alloc_cmd_urb: drop unused stream_id parameter

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

The cmd endpoint never has streams, so the stream_id parameter is unused.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index dcaf61197032..5eacb8054457 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -454,7 +454,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info 
*devinfo, gfp_t gfp,
 }
 
 static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp,
-   struct scsi_cmnd *cmnd, u16 stream_id)
+   struct scsi_cmnd *cmnd)
 {
struct usb_device *udev = devinfo->udev;
struct scsi_device *sdev = cmnd->device;
@@ -626,8 +626,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd,
}
 
if (cmdinfo->state & ALLOC_CMD_URB) {
-   cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd,
-cmdinfo->stream);
+   cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd);
if (!cmdinfo->cmd_urb)
return SCSI_MLQUEUE_DEVICE_BUSY;
cmdinfo->state &= ~ALLOC_CMD_URB;
-- 
1.8.5.5

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


[PATCH 22/76] uas: add dead request list

2014-03-06 Thread Sarah Sharp
From: Gerd Hoffmann 

This patch adds a new list where all requests which are canceled are
added to, so we don't loose them.  Then, after killing all inflight
urbs on bus reset (and disconnect) we'll walk over the list and clean
them up.

Without this we can end up with aborted requests lingering around in
case of status pipe transfer errors.

Signed-off-by: Gerd Hoffmann 
Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 50 +++
 1 file changed, 42 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 3cf5a5ff3d53..f0490382351d 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -53,6 +53,7 @@ struct uas_dev_info {
spinlock_t lock;
struct work_struct work;
struct list_head work_list;
+   struct list_head dead_list;
 };
 
 enum {
@@ -80,6 +81,7 @@ struct uas_cmd_info {
struct urb *data_in_urb;
struct urb *data_out_urb;
struct list_head work;
+   struct list_head dead;
 };
 
 /* I hate forward declarations, but I actually have a loop */
@@ -89,6 +91,7 @@ static void uas_do_work(struct work_struct *work);
 static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller);
 static void uas_configure_endpoints(struct uas_dev_info *devinfo);
 static void uas_free_streams(struct uas_dev_info *devinfo);
+static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller);
 
 static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
 struct uas_cmd_info *cmdinfo)
@@ -150,16 +153,12 @@ static void uas_abort_work(struct uas_dev_info *devinfo)
struct scsi_pointer *scp = (void *)cmdinfo;
struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
  SCp);
+   uas_log_cmd_state(cmnd, __func__);
+   WARN_ON(cmdinfo->state & COMMAND_ABORTED);
cmdinfo->state |= COMMAND_ABORTED;
cmdinfo->state &= ~IS_IN_WORK_LIST;
-   if (devinfo->resetting) {
-   /* uas_stat_cmplt() will not do that
-* when a device reset is in
-* progress */
-   cmdinfo->state &= ~COMMAND_INFLIGHT;
-   }
-   uas_try_complete(cmnd, __func__);
list_del(&cmdinfo->work);
+   list_add_tail(&cmdinfo->dead, &devinfo->dead_list);
}
spin_unlock_irqrestore(&devinfo->lock, flags);
 }
@@ -176,6 +175,28 @@ static void uas_add_work(struct uas_cmd_info *cmdinfo)
schedule_work(&devinfo->work);
 }
 
+static void uas_zap_dead(struct uas_dev_info *devinfo)
+{
+   struct uas_cmd_info *cmdinfo;
+   struct uas_cmd_info *temp;
+   unsigned long flags;
+
+   spin_lock_irqsave(&devinfo->lock, flags);
+   list_for_each_entry_safe(cmdinfo, temp, &devinfo->dead_list, dead) {
+   struct scsi_pointer *scp = (void *)cmdinfo;
+   struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd,
+ SCp);
+   uas_log_cmd_state(cmnd, __func__);
+   WARN_ON(!(cmdinfo->state & COMMAND_ABORTED));
+   /* all urbs are killed, clear inflight bits */
+   cmdinfo->state &= ~(COMMAND_INFLIGHT |
+   DATA_IN_URB_INFLIGHT |
+   DATA_OUT_URB_INFLIGHT);
+   uas_try_complete(cmnd, __func__);
+   }
+   spin_unlock_irqrestore(&devinfo->lock, flags);
+}
+
 static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd)
 {
struct sense_iu *sense_iu = urb->transfer_buffer;
@@ -263,6 +284,7 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const 
char *caller)
if (cmdinfo->state & COMMAND_ABORTED) {
scmd_printk(KERN_INFO, cmnd, "abort completed\n");
cmnd->result = DID_ABORT << 16;
+   list_del(&cmdinfo->dead);
}
cmnd->scsi_done(cmnd);
return 0;
@@ -292,7 +314,13 @@ static void uas_stat_cmplt(struct urb *urb)
u16 tag;
 
if (urb->status) {
-   dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status);
+   if (urb->status == -ENOENT) {
+   dev_err(&urb->dev->dev, "stat urb: killed, stream %d\n",
+   urb->stream_id);
+   } else {
+   dev_err(&urb->dev->dev, "stat urb: status %d\n",
+   urb->status);
+   }
usb_free_urb(urb);
return;
}
@@ -743,7 +771,9 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
 
uas_log_cmd_state(cmnd, __func__);
spin_lock_irqsave(&devinfo->lock, flags);
+   WARN_ON(cmdinfo->state & COMMAND_ABO

[PATCH 41/76] usb: Reset USB-3 devices on USB-3 link bounce

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

On disconnect USB3 protocol ports transit from U0 to SS.Inactive to Rx.Detect,
on a recoverable error, the port stays in SS.Inactive and we recover from it by
doing a warm-reset (through usb_device_reset if we have a udev for the port).

If this really is a disconnect we may end up trying the warm-reset anyways,
since khubd may run before the SS.Inactive to Rx.Detect transition, or it
may get skipped if the transition to Rx.Detect happens before khubd gets run.

With a loose connector, or in the case which actually led me to debugging this
bad ACPI firmware toggling Vbus off and on in quick succession, the port
may transition from Rx.Detect to U0 again before khubd gets run. In this case
the device state is unknown really, but khubd happily goes into the resuscitate
an existing device path, and the device driver never gets notified about the
device state being messed up.

If the above scenario happens with a streams using device, as soon as an urb
is submitted to an endpoint with streams, the following appears in dmesg:

ERROR Transfer event for disabled endpoint or incorrect stream ring
@36807420   0400 04078000

Notice how the TRB address is all zeros. I've seen this both on Intel
Pantherpoint and Nec xhci hosts.

Luckily we can detect the U0 to SS.Inactive to Rx.Detect to U0 all having
happened before khubd runs case since the C_LINK_STATE bit gets set in the
portchange bits on the U0 -> SS.Inactive change. This bit will also be set on
suspend / resume, but then it gets cleared by port_hub_init before khubd runs.

So if the C_LINK_STATE bit is set and a warm-reset is not needed, iow the port
is not still in SS.Inactive, and the port still has a connection, then the
device needs to be reset to put it back in a known state.

I've verified that doing the device reset also fixes the transfer event with
all zeros address issue.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/hub.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 4f7629d1ba6a..5da5394127e9 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4758,6 +4758,8 @@ static void hub_events(void)
 
/* deal with port status changes */
for (i = 1; i <= hdev->maxchild; i++) {
+   struct usb_device *udev = hub->ports[i - 1]->child;
+
if (test_bit(i, hub->busy_bits))
continue;
connect_change = test_bit(i, hub->change_bits);
@@ -4856,8 +4858,6 @@ static void hub_events(void)
 */
if (hub_port_warm_reset_required(hub, portstatus)) {
int status;
-   struct usb_device *udev =
-   hub->ports[i - 1]->child;
 
dev_dbg(hub_dev, "warm reset port %d\n", i);
if (!udev ||
@@ -4874,6 +4874,24 @@ static void hub_events(void)
usb_unlock_device(udev);
connect_change = 0;
}
+   /*
+* On disconnect USB3 protocol ports transit from U0 to
+* SS.Inactive to Rx.Detect. If this happens a warm-
+* reset is not needed, but a (re)connect may happen
+* before khubd runs and sees the disconnect, and the
+* device may be an unknown state.
+*
+* If the port went through SS.Inactive without khubd
+* seeing it the C_LINK_STATE change flag will be set,
+* and we reset the dev to put it in a known state.
+*/
+   } else if (udev && hub_is_superspeed(hub->hdev) &&
+  (portchange & USB_PORT_STAT_C_LINK_STATE) &&
+  (portstatus & USB_PORT_STAT_CONNECTION)) {
+   usb_lock_device(udev);
+   usb_reset_device(udev);
+   usb_unlock_device(udev);
+   connect_change = 0;
}
 
if (connect_change)
-- 
1.8.5.5

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


[PATCH 38/76] xhci: The trb_address_map radix tree expects 1KB segment memory aligment

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

If we align segment dma pool memory to 64 bytes, then a segment can be located
at 0x1040 - 0x143f, and a segment from another ring at 0x1440 -
0x183f. The last trb in the first segment at 0x1430 will then translate
to the same radix tree key as the first trb of the second segment, while they
are in different rings!

This patches fixes this by changing the alignment of the dma pool to be 1KB
rather then 64 bytes. An alternative fix would be to reduce the shift used
to calculate the radix tree keys, but that would (slighlty) grow the radix
trees so I believe this is the better fix.

Note this patch is mostly theoretical since in practice I've not seen
the dma_pool actually return not 1KB aligned memory.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-mem.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 60fc6720007f..c089668308ad 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -158,7 +158,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct 
xhci_ring *ring,
  *
  * The radix tree maps the upper portion of the TRB DMA address to a ring
  * segment that has the same upper portion of DMA addresses.  For example, say 
I
- * have segments of size 1KB, that are always 64-byte aligned.  A segment may
+ * have segments of size 1KB, that are always 1KB aligned.  A segment may
  * start at 0x10c91000 and end at 0x10c913f0.  If I use the upper 10 bits, the
  * key to the stream ID is 0x43244.  I can use the DMA address of the TRB to
  * pass the radix tree a key to get the right stream ID:
@@ -2375,11 +2375,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
/*
 * Initialize the ring segment pool.  The ring must be a contiguous
 * structure comprised of TRBs.  The TRBs must be 16 byte aligned,
-* however, the command ring segment needs 64-byte aligned segments,
-* so we pick the greater alignment need.
+* however, the command ring segment needs 64-byte aligned segments
+* and our use of dma addresses in the trb_address_map radix tree needs
+* TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.
 */
xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
-   TRB_SEGMENT_SIZE, 64, xhci->page_size);
+   TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
 
/* See Table 46 and Note on Figure 55 */
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
-- 
1.8.5.5

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


[PATCH 44/76] usb-storage: Modify and export adjust_quirks so that it can be used by uas

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/usb.c | 16 ++--
 drivers/usb/storage/usb.h |  3 +++
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 388f567524d8..f1c96261a501 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -463,14 +463,14 @@ static int associate_dev(struct us_data *us, struct 
usb_interface *intf)
 #define TOLOWER(x) ((x) | 0x20)
 
 /* Adjust device flags based on the "quirks=" module parameter */
-static void adjust_quirks(struct us_data *us)
+void usb_stor_adjust_quirks(struct usb_device *udev, unsigned long *fflags)
 {
char *p;
-   u16 vid = le16_to_cpu(us->pusb_dev->descriptor.idVendor);
-   u16 pid = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
+   u16 vid = le16_to_cpu(udev->descriptor.idVendor);
+   u16 pid = le16_to_cpu(udev->descriptor.idProduct);
unsigned f = 0;
unsigned int mask = (US_FL_SANE_SENSE | US_FL_BAD_SENSE |
-   US_FL_FIX_CAPACITY |
+   US_FL_FIX_CAPACITY | US_FL_IGNORE_UAS |
US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
@@ -541,14 +541,18 @@ static void adjust_quirks(struct us_data *us)
case 's':
f |= US_FL_SINGLE_LUN;
break;
+   case 'u':
+   f |= US_FL_IGNORE_UAS;
+   break;
case 'w':
f |= US_FL_NO_WP_DETECT;
break;
/* Ignore unrecognized flag characters */
}
}
-   us->fflags = (us->fflags & ~mask) | f;
+   *fflags = (*fflags & ~mask) | f;
 }
+EXPORT_SYMBOL_GPL(usb_stor_adjust_quirks);
 
 /* Get the unusual_devs entries and the string descriptors */
 static int get_device_info(struct us_data *us, const struct usb_device_id *id,
@@ -568,7 +572,7 @@ static int get_device_info(struct us_data *us, const struct 
usb_device_id *id,
idesc->bInterfaceProtocol :
unusual_dev->useTransport;
us->fflags = id->driver_info;
-   adjust_quirks(us);
+   usb_stor_adjust_quirks(us->pusb_dev, &us->fflags);
 
if (us->fflags & US_FL_IGNORE_DEVICE) {
dev_info(pdev, "device ignored\n");
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index 75f70f04f37b..307e339a9478 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -201,4 +201,7 @@ extern int usb_stor_probe1(struct us_data **pus,
 extern int usb_stor_probe2(struct us_data *us);
 extern void usb_stor_disconnect(struct usb_interface *intf);
 
+extern void usb_stor_adjust_quirks(struct usb_device *dev,
+   unsigned long *fflags);
+
 #endif
-- 
1.8.5.5

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


[PATCH 07/76] xhci: Set SCT field for Set TR dequeue on streams

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Nec XHCI controllers don't seem to care, but without this Intel XHCI
controllers reject Set TR dequeue commands with a COMP_TRB_ERR, leading
to the following warning:

WARN Set TR Deq Ptr cmd invalid because of stream ID configuration

And very shortly after this the system completely freezes.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-ring.c | 5 -
 drivers/usb/host/xhci.h  | 3 ++-
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 51c5109bbefc..f17e5c8c1cb3 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -4073,6 +4073,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int 
slot_id,
u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
u32 trb_ep_index = EP_ID_FOR_TRB(ep_index);
u32 trb_stream_id = STREAM_ID_FOR_TRB(stream_id);
+   u32 trb_sct = 0;
u32 type = TRB_TYPE(TRB_SET_DEQ);
struct xhci_virt_ep *ep;
 
@@ -4091,7 +4092,9 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int 
slot_id,
}
ep->queued_deq_seg = deq_seg;
ep->queued_deq_ptr = deq_ptr;
-   return queue_command(xhci, lower_32_bits(addr) | cycle_state,
+   if (stream_id)
+   trb_sct = SCT_FOR_TRB(SCT_PRI_TR);
+   return queue_command(xhci, lower_32_bits(addr) | trb_sct | cycle_state,
upper_32_bits(addr), trb_stream_id,
trb_slot_id | trb_ep_index | type, false);
 }
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index a6aa98f19a1f..2c77bf7ab9e5 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1118,9 +1118,10 @@ enum xhci_setup_dev {
 #define TRB_TO_SUSPEND_PORT(p) (((p) & (1 << 23)) >> 23)
 #define LAST_EP_INDEX  30
 
-/* Set TR Dequeue Pointer command TRB fields */
+/* Set TR Dequeue Pointer command TRB fields, 6.4.3.9 */
 #define TRB_TO_STREAM_ID(p)p) & (0x << 16)) >> 16))
 #define STREAM_ID_FOR_TRB(p)   p)) & 0x) << 16)
+#define SCT_FOR_TRB(p) (((p) << 1) & 0x7)
 
 
 /* Port Status Change Event TRB fields */
-- 
1.8.5.5

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


[PATCH 26/76] uas: Avoid unnecessary unlock / lock calls around unlink_data_urbs

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

All callers of unlink_data_urbs drop devinfo->lock before calling it, and
then immediately take it again after the call. And the first thing
unlink_data_urbs does is take the lock again, and the last thing it does
is drop it. This commit removes all the unnecessary lock dropping and taking.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 20 +++-
 1 file changed, 7 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index ec1b22d29501..dcaf61197032 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -93,28 +93,26 @@ static void uas_configure_endpoints(struct uas_dev_info 
*devinfo);
 static void uas_free_streams(struct uas_dev_info *devinfo);
 static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller);
 
+/* Must be called with devinfo->lock held, will temporary unlock the lock */
 static void uas_unlink_data_urbs(struct uas_dev_info *devinfo,
-struct uas_cmd_info *cmdinfo)
+struct uas_cmd_info *cmdinfo,
+unsigned long *lock_flags)
 {
-   unsigned long flags;
-
/*
 * The UNLINK_DATA_URBS flag makes sure uas_try_complete
 * (called by urb completion) doesn't release cmdinfo
 * underneath us.
 */
-   spin_lock_irqsave(&devinfo->lock, flags);
cmdinfo->state |= UNLINK_DATA_URBS;
-   spin_unlock_irqrestore(&devinfo->lock, flags);
+   spin_unlock_irqrestore(&devinfo->lock, *lock_flags);
 
if (cmdinfo->data_in_urb)
usb_unlink_urb(cmdinfo->data_in_urb);
if (cmdinfo->data_out_urb)
usb_unlink_urb(cmdinfo->data_out_urb);
 
-   spin_lock_irqsave(&devinfo->lock, flags);
+   spin_lock_irqsave(&devinfo->lock, *lock_flags);
cmdinfo->state &= ~UNLINK_DATA_URBS;
-   spin_unlock_irqrestore(&devinfo->lock, flags);
 }
 
 static void uas_do_work(struct work_struct *work)
@@ -361,9 +359,7 @@ static void uas_stat_cmplt(struct urb *urb)
uas_sense(urb, cmnd);
if (cmnd->result != 0) {
/* cancel data transfers on error */
-   spin_unlock_irqrestore(&devinfo->lock, flags);
-   uas_unlink_data_urbs(devinfo, cmdinfo);
-   spin_lock_irqsave(&devinfo->lock, flags);
+   uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
}
cmdinfo->state &= ~COMMAND_INFLIGHT;
uas_try_complete(cmnd, __func__);
@@ -787,9 +783,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd)
spin_unlock_irqrestore(&devinfo->lock, flags);
ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK);
} else {
-   spin_unlock_irqrestore(&devinfo->lock, flags);
-   uas_unlink_data_urbs(devinfo, cmdinfo);
-   spin_lock_irqsave(&devinfo->lock, flags);
+   uas_unlink_data_urbs(devinfo, cmdinfo, &flags);
uas_try_complete(cmnd, __func__);
spin_unlock_irqrestore(&devinfo->lock, flags);
ret = SUCCESS;
-- 
1.8.5.5

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


[PATCH 43/76] usb-storage: Don't bind to uas devices if the uas driver is enabled

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

uas devices have 2 alternative settings on their usb-storage interface,
one for usb-storage and one for uas. Using the uas driver is preferred, so if
the uas driver is enabled, and the device has an uas alt setting, don't bind.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/unusual_devs.h |  5 +
 drivers/usb/storage/usb.c  | 10 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/usb/storage/unusual_devs.h 
b/drivers/usb/storage/unusual_devs.h
index adbeb255616a..f4a82291894a 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2086,6 +2086,11 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001,
"Digital MP3 Audio Player",
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
 
+/* Unusual uas devices */
+#if IS_ENABLED(CONFIG_USB_UAS)
+#include "unusual_uas.h"
+#endif
+
 /* Control/Bulk transport for all SubClass values */
 USUAL_DEV(USB_SC_RBC, USB_PR_CB),
 USUAL_DEV(USB_SC_8020, USB_PR_CB),
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 1c0b89f2a138..388f567524d8 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -72,6 +72,10 @@
 #include "sierra_ms.h"
 #include "option_ms.h"
 
+#if IS_ENABLED(CONFIG_USB_UAS)
+#include "uas-detect.h"
+#endif
+
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm ");
 MODULE_DESCRIPTION("USB Mass Storage driver for Linux");
@@ -1035,6 +1039,12 @@ static int storage_probe(struct usb_interface *intf,
int result;
int size;
 
+   /* If uas is enabled and this device can do uas then ignore it. */
+#if IS_ENABLED(CONFIG_USB_UAS)
+   if (uas_use_uas_driver(intf, id))
+   return -ENXIO;
+#endif
+
/*
 * If the device isn't standard (is handled by a subdriver
 * module) then don't accept it.
-- 
1.8.5.5

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


[PATCH 14/76] usb-core: Free bulk streams on interface release

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

Documentation/usb/bulk-streams.txt says:

All stream IDs will be deallocated when the driver releases the interface, to
ensure that drivers that don't support streams will be able to use the endpoint

This commit actually implements this.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/core/driver.c | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 85e0450a2bc7..08283d40616c 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -400,8 +400,9 @@ static int usb_unbind_interface(struct device *dev)
 {
struct usb_driver *driver = to_usb_driver(dev->driver);
struct usb_interface *intf = to_usb_interface(dev);
+   struct usb_host_endpoint *ep, **eps = NULL;
struct usb_device *udev;
-   int error, r, lpm_disable_error;
+   int i, j, error, r, lpm_disable_error;
 
intf->condition = USB_INTERFACE_UNBINDING;
 
@@ -425,6 +426,26 @@ static int usb_unbind_interface(struct device *dev)
driver->disconnect(intf);
usb_cancel_queued_reset(intf);
 
+   /* Free streams */
+   for (i = 0, j = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
+   ep = &intf->cur_altsetting->endpoint[i];
+   if (ep->streams == 0)
+   continue;
+   if (j == 0) {
+   eps = kmalloc(USB_MAXENDPOINTS * sizeof(void *),
+ GFP_KERNEL);
+   if (!eps) {
+   dev_warn(dev, "oom, leaking streams\n");
+   break;
+   }
+   }
+   eps[j++] = ep;
+   }
+   if (j) {
+   usb_free_streams(intf, eps, j, GFP_KERNEL);
+   kfree(eps);
+   }
+
/* Reset other interface state.
 * We cannot do a Set-Interface if the device is suspended or
 * if it is prepared for a system sleep (since installing a new
-- 
1.8.5.5

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


[PATCH 35/76] uas: Add a uas_find_uas_alt_setting helper function

2014-03-06 Thread Sarah Sharp
From: Hans de Goede 

This is a preparation patch for teaching usb-storage to not bind to
uas devices.

Signed-off-by: Hans de Goede 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/storage/uas.c | 21 -
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 3f021f2fafdf..54db36541b93 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -892,10 +892,10 @@ static int uas_isnt_supported(struct usb_device *udev)
return -ENODEV;
 }
 
-static int uas_switch_interface(struct usb_device *udev,
-   struct usb_interface *intf)
+static int uas_find_uas_alt_setting(struct usb_interface *intf)
 {
int i;
+   struct usb_device *udev = interface_to_usbdev(intf);
int sg_supported = udev->bus->sg_tablesize != 0;
 
for (i = 0; i < intf->num_altsetting; i++) {
@@ -904,15 +904,26 @@ static int uas_switch_interface(struct usb_device *udev,
if (uas_is_interface(alt)) {
if (!sg_supported)
return uas_isnt_supported(udev);
-   return usb_set_interface(udev,
-   alt->desc.bInterfaceNumber,
-   alt->desc.bAlternateSetting);
+   return alt->desc.bAlternateSetting;
}
}
 
return -ENODEV;
 }
 
+static int uas_switch_interface(struct usb_device *udev,
+   struct usb_interface *intf)
+{
+   int alt;
+
+   alt = uas_find_uas_alt_setting(intf);
+   if (alt < 0)
+   return alt;
+
+   return usb_set_interface(udev,
+   intf->altsetting[0].desc.bInterfaceNumber, alt);
+}
+
 static void uas_configure_endpoints(struct uas_dev_info *devinfo)
 {
struct usb_host_endpoint *eps[4] = { };
-- 
1.8.5.5

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


[PATCH 02/76] xhci: make warnings greppable

2014-03-06 Thread Sarah Sharp
From: Oliver Neukum 

This changes debug messages and warnings in xhci-ring.c
to be on a single line so grep can find them. grep must
have precedence over the 80 column limit.

[Sarah fixed two checkpatch.pl issues with split lines
introduced by this commit.]

Signed-off-by: Oliver Neukum 
Signed-off-by: Sarah Sharp 
---
 drivers/usb/host/xhci-ring.c | 21 -
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 0ed64eb68e48..3ec1d8fe06fa 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1082,8 +1082,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
 
ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id);
if (!ep_ring) {
-   xhci_warn(xhci, "WARN Set TR deq ptr command for "
-   "freed stream ID %u\n",
+   xhci_warn(xhci, "WARN Set TR deq ptr command for freed stream 
ID %u\n",
stream_id);
/* XXX: Harmless??? */
dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
@@ -1099,12 +1098,10 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
 
switch (cmd_comp_code) {
case COMP_TRB_ERR:
-   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd invalid 
because "
-   "of stream ID configuration\n");
+   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd invalid 
because of stream ID configuration\n");
break;
case COMP_CTX_STATE:
-   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due "
-   "to incorrect slot or ep state.\n");
+   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due to 
incorrect slot or ep state.\n");
ep_state = le32_to_cpu(ep_ctx->ep_info);
ep_state &= EP_STATE_MASK;
slot_state = le32_to_cpu(slot_ctx->dev_state);
@@ -1114,13 +,12 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
slot_state, ep_state);
break;
case COMP_EBADSLT:
-   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed because 
"
-   "slot %u was not enabled.\n", slot_id);
+   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed because 
slot %u was not enabled.\n",
+   slot_id);
break;
default:
-   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd with unknown "
-   "completion code of %u.\n",
- cmd_comp_code);
+   xhci_warn(xhci, "WARN Set TR Deq Ptr cmd with unknown 
completion code of %u.\n",
+   cmd_comp_code);
break;
}
/* OK what do we do now?  The endpoint state is hosed, and we
@@ -1142,8 +1138,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd 
*xhci, int slot_id,
update_ring_for_set_deq_completion(xhci, dev,
ep_ring, ep_index);
} else {
-   xhci_warn(xhci, "Mismatch between completed Set TR Deq "
-   "Ptr command & xHCI internal state.\n");
+   xhci_warn(xhci, "Mismatch between completed Set TR Deq 
Ptr command & xHCI internal state.\n");
xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
dev->eps[ep_index].queued_deq_seg,
dev->eps[ep_index].queued_deq_ptr);
-- 
1.8.5.5

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


  1   2   3   >