Re: [PATCH v1 6/6] USB: MUSB: OMAP: get PHY by phandle for dt boot

2013-01-22 Thread Peter Ujfalusi
On 01/22/2013 04:21 PM, kishon wrote:
> But it's better to check if deferred probing
> takes place whenever a new driver is bound to a device as you just mentioned.

Whenever you load (might be also when you unload) a driver the deferred
modules will try to probe again. This is to check back if the dependency of
the deferred modules has been fulfilled by the new driver or not.

-- 
Péter
--
To unsubscribe from this list: send the line "unsubscribe 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 v5 5/6] usb: musb: cppi_dma: Clean up tusb_omap_dma structure

2017-02-06 Thread Peter Ujfalusi


On 01/25/2017 12:17 PM, Alexandre Bailon wrote:
> A pointer to musb is now present in the dma_controller structure.
> Remove the one present in tusb_omap_dma structure.

the subject line should be: usb: musb: tusb6010_omap: ...

> Signed-off-by: Alexandre Bailon 
> ---
>  drivers/usb/musb/tusb6010_omap.c | 7 +++
>  1 file changed, 3 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/musb/tusb6010_omap.c 
> b/drivers/usb/musb/tusb6010_omap.c
> index e6959cc..8b43c4b 100644
> --- a/drivers/usb/musb/tusb6010_omap.c
> +++ b/drivers/usb/musb/tusb6010_omap.c
> @@ -56,7 +56,6 @@ struct tusb_omap_dma_ch {
>  
>  struct tusb_omap_dma {
>   struct dma_controller   controller;
> - struct musb *musb;
>   void __iomem*tbase;
>  
>   int ch;
> @@ -497,7 +496,7 @@ tusb_omap_dma_allocate(struct dma_controller *c,
>   u32 reg;
>  
>   tusb_dma = container_of(c, struct tusb_omap_dma, controller);
> - musb = tusb_dma->musb;
> + musb = tusb_dma->controller.musb;
>   tbase = musb->ctrl_base;
>  
>   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
> @@ -534,7 +533,7 @@ tusb_omap_dma_allocate(struct dma_controller *c,
>   dev_name = "TUSB receive";
>   }
>  
> - chdat->musb = tusb_dma->musb;
> + chdat->musb = tusb_dma->controller.musb;
>   chdat->tbase = tusb_dma->tbase;
>   chdat->hw_ep = hw_ep;
>   chdat->epnum = hw_ep->epnum;
> @@ -667,7 +666,7 @@ tusb_dma_controller_create(struct musb *musb, void 
> __iomem *base)
>   if (!tusb_dma)
>   goto out;
>  
> - tusb_dma->musb = musb;
> + tusb_dma->controller.musb = musb;
>   tusb_dma->tbase = musb->ctrl_base;
>  
>   tusb_dma->ch = -1;
> 

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


usb: musb: regression since 4.9 on omap4-panda-es (caused by d8e5f0eca1e8)

2017-04-04 Thread Peter Ujfalusi

Tony,

since 4.9 (4.8 was fine) I can not boot omap4-panda-es if the musb is 
compiled in. The kernel will stuck printing:


** 206 printk messages dropped ** [8.926727] musb_bus_suspend 2584: 
trying to suspend as a_idle while active


The bisect (log is [1]) points to:
d8e5f0eca1e8 usb: musb: Fix hardirq-safe hardirq-unsafe lock order error

and reverting the d8e5f0eca1e8 makes the board to boot up fine (Linux 
4.11-rc5 and next-20170331).


any idea on how to fix this w/o reverting the commit?

[1] https://pastebin.com/Z2HJY229

- Péter
--
To unsubscribe from this list: send the line "unsubscribe 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: musb: regression since 4.9 on omap4-panda-es (caused by d8e5f0eca1e8)

2017-04-05 Thread Peter Ujfalusi

Tony,

On 2017-04-05 03:36, Tony Lindgren wrote:

* Tony Lindgren  [170404 07:06]:

* Bin Liu  [170404 05:30]:

On Tue, Apr 04, 2017 at 10:09:50AM +0300, Peter Ujfalusi wrote:

Tony,

since 4.9 (4.8 was fine) I can not boot omap4-panda-es if the musb
is compiled in. The kernel will stuck printing:

** 206 printk messages dropped ** [8.926727] musb_bus_suspend
2584: trying to suspend as a_idle while active


OK so compiled in. Do you have something connected also when
booting?


Does it sound a similar issue to
http://marc.info/?l=linux-usb&m=149036531809506&w=2


Yup.


The bisect (log is [1]) points to:
d8e5f0eca1e8 usb: musb: Fix hardirq-safe hardirq-unsafe lock order error

and reverting the d8e5f0eca1e8 makes the board to boot up fine
(Linux 4.11-rc5 and next-20170331).


OK thanks for bisecting it.


any idea on how to fix this w/o reverting the commit?


I'll take a look.


OK I was able to reproduce this with loadable modules by reloading
the modules while having OTG-A cable inserted with a hub and USB
drive connected.

Peter, care to check if the following fixes the problem for you?
There should no longer be much any musb core tinkering happening
in the glue layers..


I had similar hunch first, but did not worked. I have tested this patch 
and did not helped.


To be precise this is what I have tried:
- boot w/o cable connected
- boot w/ board connected to PC (device mode)
- boot w/ OTG-A cable with USB keyboard
- boot w/ OTG-A cable connected to powered USB hub and the same keyboard

w/ and w/o this patch I have the same flood of prints in all cases.

Fwiw I have checked where the is_active is set - which causes the prints:
musb_core.c:musb_start()

if (musb->port_mode != MUSB_PORT_MODE_HOST &&
musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON &&
(devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
musb->is_active = 1;
} else {
devctl |= MUSB_DEVCTL_SESSION;
}

this was the only place where the is_active was set to 1.



Regards,

Tony

8< ---
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -91,12 +91,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int 
is_on)
}

otg_set_vbus(otg, 1);
-   } else {
-   musb->is_active = 1;
-   otg->default_a = 1;
-   musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
-   devctl |= MUSB_DEVCTL_SESSION;
-   MUSB_HST_MODE(musb);
}
} else {
musb->is_active = 0;


- Péter
--
To unsubscribe from this list: send the line "unsubscribe 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: musb: regression since 4.9 on omap4-panda-es (caused by d8e5f0eca1e8)

2017-04-05 Thread Peter Ujfalusi

On 2017-04-05 10:13, Peter Ujfalusi wrote:

I had similar hunch first, but did not worked. I have tested this patch
and did not helped.

To be precise this is what I have tried:
- boot w/o cable connected
- boot w/ board connected to PC (device mode)
- boot w/ OTG-A cable with USB keyboard
- boot w/ OTG-A cable connected to powered USB hub and the same keyboard

w/ and w/o this patch I have the same flood of prints in all cases.


the config I have for linux-next:
https://pastebin.com/KixvyiRR



Fwiw I have checked where the is_active is set - which causes the prints:
musb_core.c:musb_start()

if (musb->port_mode != MUSB_PORT_MODE_HOST &&
musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON &&
(devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
musb->is_active = 1;
} else {
devctl |= MUSB_DEVCTL_SESSION;
}

this was the only place where the is_active was set to 1.



Regards,

Tony

8< ---
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -91,12 +91,6 @@ static void omap2430_musb_set_vbus(struct musb
*musb, int is_on)
 }

 otg_set_vbus(otg, 1);
-} else {
-musb->is_active = 1;
-otg->default_a = 1;
-musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
-devctl |= MUSB_DEVCTL_SESSION;
-MUSB_HST_MODE(musb);
 }
 } else {
 musb->is_active = 0;


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


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


[PATCH] USB: musb: Correct Kconfig in order to avoid non compilable selection

2013-01-31 Thread Peter Ujfalusi
Currently it is possible to have:
USB_MUSB_OMAP2PLUS=m
TWL4030_USB=y

which would result compile time error due to missing symbols.

With this change USB_MUSB_OMAP2PLUS and TWL4030_USB will be in sync.

Reported-by: Vincent Stehle 
Signed-off-by: Peter Ujfalusi 
---
Hi Felipe,

I have also noticed that we have similar issue around USB_MUSB_HDRC,
CONFIG_USB_MUSB_TUSB6010 and CONFIG_USB_TUSB_OMAP_DMA. You can easily have a
combination of y/m of these to have non compilable kernel.
I have tried to fix it but my Kconfig skills are not adequate for it ;)

Regards,
Peter

 drivers/usb/musb/Kconfig | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 23a0b7f..a3fa19c 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -9,8 +9,6 @@ config USB_MUSB_HDRC
depends on USB && USB_GADGET
select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
-   select TWL4030_USB if MACH_OMAP_3430SDP
-   select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
select USB_OTG_UTILS
help
  Say Y here if your system has a dual role high speed USB
@@ -49,6 +47,8 @@ config USB_MUSB_TUSB6010
 config USB_MUSB_OMAP2PLUS
tristate "OMAP2430 and onwards"
depends on ARCH_OMAP2PLUS
+   select TWL4030_USB if MACH_OMAP_3430SDP
+   select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
 
 config USB_MUSB_AM35X
tristate "AM35x"
-- 
1.8.1.1

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


Re: [PATCH 1/8] usb: phy: nop: Add some parameters to platform data

2013-03-13 Thread Peter Ujfalusi
On 03/12/2013 04:20 PM, Roger Quadros wrote:
> Adding Peter to the loop. I faintly remember him mentioning this issue before
> for beagle. We really need the deferred probe mechanism or we need to resort
> to device registering order.

Yes, BeagleBoard is a good example. Long story short: we have external
dependency and the correct way to handle that is via deferred probe.

As of now we are not ready to kill the legacy support but over time we should
move as much as we can to DT only mode.

> The first user for needs_vcc flag will be the beagleboard file. I just didn't
> implement it in this patch [1].
> 
> On second thoughts, since [1] does work on beagleboard without requiring the
> needs_vcc flag, I think we can just live without it.

The BeagleBoard works because the bootloader happen to enable the PWM
generator which is used as a GPIO for the external HUB enable port. As soon as
the bootloader stops doing this we are going to be in trouble.

> 
> Felipe, Peter, what do you think?
> 
> cheers,
> -roger
> 
> [1] https://lkml.org/lkml/2013/3/12/244
> 


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


[PATCH] usb: otg: twl4030: Change TWL4030_MODULE_* ids to TWL_MODULE_*

2012-11-13 Thread Peter Ujfalusi
To facilitate upcoming cleanup in twl stack.
No functional changes.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/otg/twl4030-usb.c | 46 ---
 1 file changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index f0d2e75..11b2a12 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -123,10 +123,10 @@
 #define PHY_CLK_CTRL_STS   0xFF
 #define PHY_DPLL_CLK   (1 << 0)
 
-/* In module TWL4030_MODULE_PM_MASTER */
+/* In module TWL_MODULE_PM_MASTER */
 #define STS_HW_CONDITIONS  0x0F
 
-/* In module TWL4030_MODULE_PM_RECEIVER */
+/* In module TWL_MODULE_PM_RECEIVER */
 #define VUSB_DEDICATED10x7D
 #define VUSB_DEDICATED20x7E
 #define VUSB1V5_DEV_GRP0x71
@@ -195,14 +195,14 @@ static int twl4030_i2c_write_u8_verify(struct twl4030_usb 
*twl,
 }
 
 #define twl4030_usb_write_verify(twl, address, data)   \
-   twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address))
+   twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
 
 static inline int twl4030_usb_write(struct twl4030_usb *twl,
u8 address, u8 data)
 {
int ret = 0;
 
-   ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address);
+   ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
if (ret < 0)
dev_dbg(twl->dev,
"TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
@@ -227,7 +227,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, u8 
module, u8 address)
 
 static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
 {
-   return twl4030_readb(twl, TWL4030_MODULE_USB, address);
+   return twl4030_readb(twl, TWL_MODULE_USB, address);
 }
 
 /*-*/
@@ -264,8 +264,7 @@ static enum omap_musb_vbus_id_status
 * signal is active, the OTG module is activated, and
 * its interrupt may be raised (may wake the system).
 */
-   status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER,
-   STS_HW_CONDITIONS);
+   status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
if (status < 0)
dev_err(twl->dev, "USB link status err %d\n", status);
else if (status & (BIT(7) | BIT(2))) {
@@ -372,8 +371,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int 
on)
 * SLEEP. We work around this by clearing the bit after usv3v1
 * is re-activated. This ensures that VUSB3V1 is really active.
 */
-   twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
-   VUSB_DEDICATED2);
+   twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
regulator_enable(twl->usb1v5);
__twl4030_phy_power(twl, 1);
twl4030_usb_write(twl, PHY_CLK_CTRL,
@@ -419,50 +417,48 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
 static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
 {
/* Enable writing to power configuration registers */
-   twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-   TWL4030_PM_MASTER_KEY_CFG1,
-   TWL4030_PM_MASTER_PROTECT_KEY);
+   twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
+TWL4030_PM_MASTER_PROTECT_KEY);
 
-   twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
-   TWL4030_PM_MASTER_KEY_CFG2,
-   TWL4030_PM_MASTER_PROTECT_KEY);
+   twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
+TWL4030_PM_MASTER_PROTECT_KEY);
 
/* Keep VUSB3V1 LDO in sleep state until VBUS/ID change detected*/
-   /*twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
+   /*twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);*/
 
/* input to VUSB3V1 LDO is from VBAT, not VBUS */
-   twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
+   twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1);
 
/* Initialize 3.1V regulator */
-   twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
+   twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP);
 
twl->usb3v1 = regulator_get(twl->dev, "usb3v1");
if (IS_ERR(twl->usb3v1))
return -ENODEV;
 
-   twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
+   twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE);
 
/* Initialize 1.5V regulator */
-   twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP);
+  

Re: [PATCH] usb: otg: twl4030: Change TWL4030_MODULE_* ids to TWL_MODULE_*

2012-11-13 Thread Peter Ujfalusi
Hi Felipe,

On 11/13/2012 10:47 AM, Felipe Balbi wrote:
> On Tue, Nov 13, 2012 at 10:43:38AM +0100, Peter Ujfalusi wrote:
>> To facilitate upcoming cleanup in twl stack.
>> No functional changes.
>>
>> Signed-off-by: Peter Ujfalusi 
> 
> I guess this one must go together with the rest of your series...

I made the split between the patches and they are good to go in their separate
ways to avoid cross tree hassle.
All of the defines were in place originally but they were used in non
consistent ways.
All of these will help in the future to clean up the twl core without breaking
the child drivers.

-- 
Péter

> Acked-by: Felipe Balbi 
> 
>> ---
>>  drivers/usb/otg/twl4030-usb.c | 46 
>> ---
>>  1 file changed, 21 insertions(+), 25 deletions(-)
>>
>> diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
>> index f0d2e75..11b2a12 100644
>> --- a/drivers/usb/otg/twl4030-usb.c
>> +++ b/drivers/usb/otg/twl4030-usb.c
>> @@ -123,10 +123,10 @@
>>  #define PHY_CLK_CTRL_STS0xFF
>>  #define PHY_DPLL_CLK(1 << 0)
>>  
>> -/* In module TWL4030_MODULE_PM_MASTER */
>> +/* In module TWL_MODULE_PM_MASTER */
>>  #define STS_HW_CONDITIONS   0x0F
>>  
>> -/* In module TWL4030_MODULE_PM_RECEIVER */
>> +/* In module TWL_MODULE_PM_RECEIVER */
>>  #define VUSB_DEDICATED1 0x7D
>>  #define VUSB_DEDICATED2 0x7E
>>  #define VUSB1V5_DEV_GRP 0x71
>> @@ -195,14 +195,14 @@ static int twl4030_i2c_write_u8_verify(struct 
>> twl4030_usb *twl,
>>  }
>>  
>>  #define twl4030_usb_write_verify(twl, address, data)\
>> -twl4030_i2c_write_u8_verify(twl, TWL4030_MODULE_USB, (data), (address))
>> +twl4030_i2c_write_u8_verify(twl, TWL_MODULE_USB, (data), (address))
>>  
>>  static inline int twl4030_usb_write(struct twl4030_usb *twl,
>>  u8 address, u8 data)
>>  {
>>  int ret = 0;
>>  
>> -ret = twl_i2c_write_u8(TWL4030_MODULE_USB, data, address);
>> +ret = twl_i2c_write_u8(TWL_MODULE_USB, data, address);
>>  if (ret < 0)
>>  dev_dbg(twl->dev,
>>  "TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
>> @@ -227,7 +227,7 @@ static inline int twl4030_readb(struct twl4030_usb *twl, 
>> u8 module, u8 address)
>>  
>>  static inline int twl4030_usb_read(struct twl4030_usb *twl, u8 address)
>>  {
>> -return twl4030_readb(twl, TWL4030_MODULE_USB, address);
>> +return twl4030_readb(twl, TWL_MODULE_USB, address);
>>  }
>>  
>>  
>> /*-*/
>> @@ -264,8 +264,7 @@ static enum omap_musb_vbus_id_status
>>   * signal is active, the OTG module is activated, and
>>   * its interrupt may be raised (may wake the system).
>>   */
>> -status = twl4030_readb(twl, TWL4030_MODULE_PM_MASTER,
>> -STS_HW_CONDITIONS);
>> +status = twl4030_readb(twl, TWL_MODULE_PM_MASTER, STS_HW_CONDITIONS);
>>  if (status < 0)
>>  dev_err(twl->dev, "USB link status err %d\n", status);
>>  else if (status & (BIT(7) | BIT(2))) {
>> @@ -372,8 +371,7 @@ static void twl4030_phy_power(struct twl4030_usb *twl, 
>> int on)
>>   * SLEEP. We work around this by clearing the bit after usv3v1
>>   * is re-activated. This ensures that VUSB3V1 is really active.
>>   */
>> -twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0,
>> -VUSB_DEDICATED2);
>> +twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2);
>>  regulator_enable(twl->usb1v5);
>>  __twl4030_phy_power(twl, 1);
>>  twl4030_usb_write(twl, PHY_CLK_CTRL,
>> @@ -419,50 +417,48 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
>>  static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
>>  {
>>  /* Enable writing to power configuration registers */
>> -twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
>> -TWL4030_PM_MASTER_KEY_CFG1,
>> -TWL4030_PM_MASTER_PROTECT_KEY);
>> +twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
>> + TWL4030_PM_MASTER_PROTECT_KEY);
>>  
>> -twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER,
>> -TWL4030_PM_MASTER_KEY_CF

Re: [PATCH] usb: otg: twl4030: Change TWL4030_MODULE_* ids to TWL_MODULE_*

2012-11-13 Thread Peter Ujfalusi
On 11/13/2012 11:37 AM, Felipe Balbi wrote:
> ok good. Unfortunately I have already sent this merge window's pull
> request to Greg so I'd have to delay this until v3.9. If that's ok with
> you, I can take it through my tree.

I hoped that this can go with 3.8 since in 3.9 I'm planning to remove all of
these TWL4030_MODULE_* defines which have TWL_MODULE_* counterpart.
In this case I will introduce dummy defines to point to the correct place for
the USB in 3.9 and we can get rid of the rest of these in 3.10. Oh well. This
is going to take a bit longer than I have anticipated.
I can't think of any other subsytem this can go through...

-- 
Péter
--
To unsubscribe from this list: send the line "unsubscribe 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: [-next PATCH 2/4] treewide: Use DEVICE_ATTR_RW

2018-01-10 Thread Peter Ujfalusi


On 2017-12-20 12:54, Jarkko Nikula wrote:
> On Wed, Dec 20, 2017 at 10:32:11AM +0100, Greg Kroah-Hartman wrote:
>> On Wed, Dec 20, 2017 at 01:24:44AM -0800, Joe Perches wrote:
>>> On Wed, 2017-12-20 at 10:34 +0200, Jarkko Nikula wrote:
>>>> On Tue, Dec 19, 2017 at 10:15:07AM -0800, Joe Perches wrote:
>>>>> Convert DEVICE_ATTR uses to DEVICE_ATTR_RW where possible.
>>> [] 
>>>>> diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
>>> []
>>>>> @@ -854,7 +854,7 @@ static ssize_t dma_op_mode_store(struct device *dev,
>>>>>   return size;
>>>>>  }
>>>>>  
>>>>> -static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, 
>>>>> dma_op_mode_store);
>>>>> +static DEVICE_ATTR_RW(dma_op_mode);
>>>>>  
>>>>
>>>> While I can ack this part here if it helps generic cleanup effort I
>>>> don't understart would it improve code readability in general? Mode 644
>>>> is clear and don't need any grepping but for DEVICE_ATTR_RW() I had to go
>>>> through all of these files in order to see what does it mean:
>>
>> Yeah, 644 is "clear", but _RW() is even more clear.  Ideally I want to
>> get rid of all of the "non-standard" users that set random modes of
>> sysfs files, as we get it wrong too many times.  Using the "defaults" is
>> much better.
>>
> Fair enough. For the sound/soc/omap/ (Acked-by was missing from my
> previous reply):
> 
> Acked-by: Jarkko Nikula 

And from me to the same file (sound/soc/omap/mcbsp.c):

Acked-by: Peter Ujfalusi 


- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
--
To unsubscribe from this list: send the line "unsubscribe 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: musb: regression since 4.9 on omap4-panda-es (caused by d8e5f0eca1e8)

2017-04-06 Thread Peter Ujfalusi

Tony,

On 04/05/2017 06:29 PM, Tony Lindgren wrote:

* Tony Lindgren  [170405 06:53]:

* Peter Ujfalusi  [170405 00:15]:

To be precise this is what I have tried:
- boot w/o cable connected
- boot w/ board connected to PC (device mode)
- boot w/ OTG-A cable with USB keyboard
- boot w/ OTG-A cable connected to powered USB hub and the same keyboard

w/ and w/o this patch I have the same flood of prints in all cases.


OK interesting that it also happens with nothing connected.


Fwiw I have checked where the is_active is set - which causes the prints:
musb_core.c:musb_start()

if (musb->port_mode != MUSB_PORT_MODE_HOST &&
musb->xceiv->otg->state != OTG_STATE_A_WAIT_BCON &&
(devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) {
musb->is_active = 1;
} else {
devctl |= MUSB_DEVCTL_SESSION;
}

this was the only place where the is_active was set to 1.


That seems normal in musb_start(). Will try with your .config
here.


If the the port is configured as OTG, we should not need to
try to force any states during init. The change below will stop
the warnings with your .config, needs to be tested more though
to make sure things still work in all cases.


With this change I can boot up without issues, thanks!
I can not get the kernel to react to anything I plug to the A/B connector. 
Keyboard (directly or via powered hub), flash drive, connecting the board to 
PC. Nothing.
Actually if I connect to a PC I got a print from twl6030 about an interrupt, 
but nothing happens in USB front.
The same thing happens with 4.8, so it is not regression. Most likely it is an 
error in my setup...


Tested-by: Peter Ujfalusi 



Regards,

Tony

8< --
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2780,10 +2780,11 @@ int musb_host_setup(struct musb *musb, int power_budget)
int ret;
struct usb_hcd *hcd = musb->hcd;

-   MUSB_HST_MODE(musb);
-   musb->xceiv->otg->default_a = 1;
-   musb->xceiv->otg->state = OTG_STATE_A_IDLE;
-
+   if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+   MUSB_HST_MODE(musb);
+   musb->xceiv->otg->default_a = 1;
+   musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+   }
otg_set_host(musb->xceiv->otg, &hcd->self);
hcd->self.otg_port = 1;
musb->xceiv->otg->host = &hcd->self;




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


Re: [PATCH] usb: musb: Fix trying to suspend while active for OTG configurations

2017-04-19 Thread Peter Ujfalusi



On 2017-04-07 17:35, Tony Lindgren wrote:

Commit d8e5f0eca1e8 ("usb: musb: Fix hardirq-safe hardirq-unsafe
lock order error") caused a regression where musb keeps trying to
enable host mode with no cable connected. This seems to be caused
by the fact that now phy is enabled earlier, and we are wrongly
trying to force USB host mode on an OTG port. The errors we are
getting are "trying to suspend as a_idle while active".

For ports configured as OTG, we should not need to do anything
to try to force USB host mode on it's OTG port. Trying to force host
mode in this case just seems to completely confuse the musb state
machine.

Let's fix the issue by making musb_host_setup() attempt to force the
mode only if port_mode is configured for host mode.


Tested-by: Peter Ujfalusi 



Fixes: d8e5f0eca1e8 ("usb: musb: Fix hardirq-safe hardirq-unsafe
lock order error")
Cc: Johan Hovold 
Reported-by: Laurent Pinchart 
Reported-by: Peter Ujfalusi 
Tested-by: Peter Ujfalusi 
Signed-off-by: Tony Lindgren 
---
 drivers/usb/musb/musb_host.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -2780,10 +2780,11 @@ int musb_host_setup(struct musb *musb, int power_budget)
int ret;
struct usb_hcd *hcd = musb->hcd;

-   MUSB_HST_MODE(musb);
-   musb->xceiv->otg->default_a = 1;
-   musb->xceiv->otg->state = OTG_STATE_A_IDLE;
-
+   if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+   MUSB_HST_MODE(musb);
+   musb->xceiv->otg->default_a = 1;
+   musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+   }
otg_set_host(musb->xceiv->otg, &hcd->self);
hcd->self.otg_port = 1;
musb->xceiv->otg->host = &hcd->self;



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


[PATCH 0/4] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-03 Thread Peter Ujfalusi
Hi,

With port_window support implemented in DMAengine and the sDMA DMAengine driver,
the tusb6010_omap driver can be converted away from the custom legacy omap-dma
API to generic DMAengine.

The first two patch is to prepare the tusb6010_omap driver for the conversion.
The third one adds the needed entries for the dma_slave_map so we can request
the DMA channels. This can be reverted when the stack is converted to DT.

The last patch does the main work to move the driver to DMAengine API.

I have tested the set on top of next-20170503 on Nokia n810 with nfsroot using
CDC Ethernet (g_cdc) and copying files with scp to/form my host.

To force that the DMA is actually used I have:
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 05aefcad40b5..a5fc2a6bdad3 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -216,8 +216,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 * use a timer for the callback, but it is unsafe as the XFR_SIZE
 * register is corrupt, and we won't know if the DMA worked.
 */
-   if (dma_addr & 0x2)
-   return false;
+// if (dma_addr & 0x2)
+// return false;
 
/*
 * Because of HW issue #10, it seems like mixing sync DMA and async

Since this condition will almost all the time was true - effectively disabling
the DMA use.

Regards.
Peter
---
Peter Ujfalusi (4):
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request
lines
  usb: musb: tusb6010_omap: Convert to dmaengine WIP

 arch/arm/mach-omap2/dma.c|  24 +++
 drivers/usb/musb/tusb6010_omap.c | 342 ++-
 2 files changed, 177 insertions(+), 189 deletions(-)

-- 
2.12.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 1/4] usb: musb: tusb6010_omap: Create new struct for DMA data/parameters

2017-05-03 Thread Peter Ujfalusi
For the DMA we have ch (channel), dmareq and sync_dev parameters both
within the tusb_omap_dma_ch and tusb_omap_dma_ch struct.
By creating a common struct the code can be simplified when selecting
between the shared or multichannel DMA parameters.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 163 ---
 1 file changed, 84 insertions(+), 79 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 8b43c4b99f04..2abd7895c3af 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -31,6 +31,12 @@
 #define OMAP242X_DMA_EXT_DMAREQ4   16
 #define OMAP242X_DMA_EXT_DMAREQ5   64
 
+struct tusb_dma_data {
+   int ch;
+   s8  dmareq;
+   s8  sync_dev;
+};
+
 struct tusb_omap_dma_ch {
struct musb *musb;
void __iomem*tbase;
@@ -39,9 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -58,9 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
unsignedmultichannel:1;
 };
 
@@ -119,9 +121,9 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
spin_lock_irqsave(&musb->lock, flags);
 
if (tusb_dma->multichannel)
-   ch = chdat->ch;
+   ch = chdat->dma_data.ch;
else
-   ch = tusb_dma->ch;
+   ch = tusb_dma->dma_data.ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -140,8 +142,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
-   remaining);
+   chdat->tx ? "tx" : "rx", ch, remaining);
remaining = 0;
}
 
@@ -219,9 +220,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
u32 dma_remaining;
int src_burst, dst_burst;
u16 csr;
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_data*dma_data;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -248,7 +247,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
+   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
dma_remaining);
return false;
}
@@ -261,15 +260,15 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
chdat->transfer_packet_sz = packet_sz;
 
if (tusb_dma->multichannel) {
-   ch = chdat->ch;
-   dmareq = chdat->dmareq;
-   sync_dev = chdat->sync_dev;
+   dma_data = &chdat->dma_data;
} else {
+   dma_data = &tusb_dma->dma_data;
+
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
}
-   if (tusb_dma->ch < 0) {
+   if (dma_data->ch < 0) {
/* REVISIT: This should get blocked earlier, happens
 * with MSC ErrorRecoveryTest
 */
@@ -277,10 +276,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
return false;
}
 
-

[PATCH 2/4] usb: musb: tusb6010_omap: Allocate DMA channels upfront

2017-05-03 Thread Peter Ujfalusi
Instead of requesting the DMA channel in tusb_omap_dma_allocate() do it
when the controller is created and in runtime work from the DMA channel
pool.

This change is needed for the DMAengine conversion of the driver since the
tusb_omap_dma_allocate() is called in interrupt context which might lead
to lock within the DMAengine API when requesting channel.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 184 +++
 1 file changed, 92 insertions(+), 92 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 2abd7895c3af..244b7b7cd26a 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -45,7 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_data*dma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -62,7 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_datadma_pool[MAX_DMAREQ];
unsignedmultichannel:1;
 };
 
@@ -120,10 +120,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
spin_lock_irqsave(&musb->lock, flags);
 
-   if (tusb_dma->multichannel)
-   ch = chdat->dma_data.ch;
-   else
-   ch = tusb_dma->dma_data.ch;
+   ch = chdat->dma_data->ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -247,7 +244,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
+   chdat->tx ? "tx" : "rx",
+   chdat->dma_data ? chdat->dma_data->ch : -1,
dma_remaining);
return false;
}
@@ -259,11 +257,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
else
chdat->transfer_packet_sz = packet_sz;
 
-   if (tusb_dma->multichannel) {
-   dma_data = &chdat->dma_data;
-   } else {
-   dma_data = &tusb_dma->dma_data;
-
+   dma_data = chdat->dma_data;
+   if (!tusb_dma->multichannel) {
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
@@ -275,10 +270,10 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
WARN_ON(1);
return false;
}
-
-   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
}
 
+   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
+
chdat->packet_sz = packet_sz;
chdat->len = len;
channel->actual_len = 0;
@@ -406,19 +401,9 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 static int tusb_omap_dma_abort(struct dma_channel *channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
-   struct tusb_omap_dma*tusb_dma = chdat->tusb_dma;
-   struct tusb_dma_data*dma_data = &tusb_dma->dma_data;
 
-   if (!tusb_dma->multichannel) {
-   if (dma_data->ch >= 0) {
-   omap_stop_dma(dma_data->ch);
-   omap_free_dma(dma_data->ch);
-   dma_data->ch = -1;
-   }
-
-   dma_data->dmareq = -1;
-   dma_data->sync_dev = -1;
-   }
+   if (chdat->dma_data)
+   omap_stop_dma(chdat->dma_data->ch);
 
channel->status = MUSB_DMA_STATUS_FREE;
 
@@ -430,15 +415,6 @@ static inline int tusb_omap_dma_allocate_dmareq(struct 
tusb_omap_dma_ch *chdat)
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
int i, dmareq_nr = -1;
 
-   const int sync_dev[6] = {
-   OMAP24XX_DMA_EXT_DMAREQ0,
-   OMAP24XX_DMA_EXT_DMAREQ1,
-   OMAP242X_DMA_EXT_DMAREQ2,
-   OMAP242X_DMA_EXT_DMAREQ3,
-   OMAP242X_DMA_EXT_DMAREQ4,
-   OMAP242X_DMA_EXT_DMAREQ5,
-   };
-
for (i = 0; i < MAX_DMAREQ; i++) {
int cur = (reg & (0xf << (i * 5))) >> (i * 5);

[PATCH 4/4] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-03 Thread Peter Ujfalusi
With the port_window support in DMAengine and the sDMA driver we can
convert the driver to DMAengine.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 201 ---
 1 file changed, 80 insertions(+), 121 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 244b7b7cd26a..05aefcad40b5 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include "musb_core.h"
 #include "tusb6010.h"
@@ -24,17 +24,9 @@
 
 #define MAX_DMAREQ 5   /* REVISIT: Really 6, but req5 not OK */
 
-#define OMAP24XX_DMA_EXT_DMAREQ0   2
-#define OMAP24XX_DMA_EXT_DMAREQ1   3
-#define OMAP242X_DMA_EXT_DMAREQ2   14
-#define OMAP242X_DMA_EXT_DMAREQ3   15
-#define OMAP242X_DMA_EXT_DMAREQ4   16
-#define OMAP242X_DMA_EXT_DMAREQ5   64
-
 struct tusb_dma_data {
-   int ch;
s8  dmareq;
-   s8  sync_dev;
+   struct dma_chan *chan;
 };
 
 struct tusb_omap_dma_ch {
@@ -105,7 +97,7 @@ static inline void tusb_omap_free_shared_dmareq(struct 
tusb_omap_dma_ch *chdat)
  * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
  * musb_gadget.c.
  */
-static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
+static void tusb_omap_dma_cb(void *data)
 {
struct dma_channel  *channel = (struct dma_channel *)data;
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
@@ -116,18 +108,11 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
void __iomem*ep_conf = hw_ep->conf;
void __iomem*mbase = musb->mregs;
unsigned long   remaining, flags, pio;
-   int ch;
 
spin_lock_irqsave(&musb->lock, flags);
 
-   ch = chdat->dma_data->ch;
-
-   if (ch_status != OMAP_DMA_BLOCK_IRQ)
-   printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
-
-   dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
-   chdat->epnum, chdat->tx ? "tx" : "rx",
-   ch, ch_status);
+   dev_dbg(musb->controller, "ep%i %s dma callback\n",
+   chdat->epnum, chdat->tx ? "tx" : "rx");
 
if (chdat->tx)
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
@@ -138,8 +123,8 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
-   dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", ch, remaining);
+   dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
+   chdat->tx ? "tx" : "rx", remaining);
remaining = 0;
}
 
@@ -212,12 +197,15 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
struct musb_hw_ep   *hw_ep = chdat->hw_ep;
void __iomem*mbase = musb->mregs;
void __iomem*ep_conf = hw_ep->conf;
-   dma_addr_t  fifo = hw_ep->fifo_sync;
-   struct omap_dma_channel_params  dma_params;
+   dma_addr_t  fifo_addr = hw_ep->fifo_sync;
u32 dma_remaining;
-   int src_burst, dst_burst;
u16 csr;
struct tusb_dma_data*dma_data;
+   struct dma_async_tx_descriptor  *dma_desc;
+   struct dma_slave_config dma_cfg;
+   enum dma_transfer_direction dma_dir;
+   u32 port_window;
+   int ret;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -243,10 +231,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
-   dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx",
-   chdat->dma_data ? chdat->dma_data->ch : -1,
-   dma_remaining);
+   dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
+   chdat->tx ? "tx" : "rx", dma_remaining);

[PATCH 0/4] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-03 Thread Peter Ujfalusi
Hi,

With port_window support implemented in DMAengine and the sDMA DMAengine driver,
the tusb6010_omap driver can be converted away from the custom legacy omap-dma
API to generic DMAengine.

The first two patch is to prepare the tusb6010_omap driver for the conversion.
The third one adds the needed entries for the dma_slave_map so we can request
the DMA channels. This can be reverted when the stack is converted to DT.

The last patch does the main work to move the driver to DMAengine API.

I have tested the set on top of next-20170503 on Nokia n810 with nfsroot using
CDC Ethernet (g_cdc) and copying files with scp to/form my host.

To force that the DMA is actually used I have:
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 05aefcad40b5..a5fc2a6bdad3 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -216,8 +216,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 * use a timer for the callback, but it is unsafe as the XFR_SIZE
 * register is corrupt, and we won't know if the DMA worked.
 */
-   if (dma_addr & 0x2)
-   return false;
+// if (dma_addr & 0x2)
+// return false;
 
/*
 * Because of HW issue #10, it seems like mixing sync DMA and async

Since this condition will almost all the time was true - effectively disabling
the DMA use.

Regards.
Peter
---
Peter Ujfalusi (4):
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request
lines
  usb: musb: tusb6010_omap: Convert to DMAengine API

 arch/arm/mach-omap2/dma.c|  24 +++
 drivers/usb/musb/tusb6010_omap.c | 342 ++-
 2 files changed, 177 insertions(+), 189 deletions(-)

-- 
2.12.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 3/4] ARM: OMAP2+: DMA: Add slave map entries for 24xx external request lines

2017-05-03 Thread Peter Ujfalusi
The external request lines are used by tusb6010 on OMAP24xx platforms.
Update the map so the driver can use dmaengine API to request the DMA
channel. At the same time add temporary map containing only the external
DMA request numbers for DT booted case on omap24xx since the tusb6010 stack
is not yet supports DT boot.

Signed-off-by: Peter Ujfalusi 
---
 arch/arm/mach-omap2/dma.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e58c13a9bea5..0b77a0176018 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -249,6 +249,24 @@ static const struct dma_slave_map omap24xx_sdma_map[] = {
{ "omap_uart.2", "rx", SDMA_FILTER_PARAM(54) },
{ "omap_hsmmc.0", "tx", SDMA_FILTER_PARAM(61) },
{ "omap_hsmmc.0", "rx", SDMA_FILTER_PARAM(62) },
+
+   /* external DMA requests when tusb6010 is used */
+   { "musb-tusb", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-tusb", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-tusb", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 only */
+};
+
+static const struct dma_slave_map omap24xx_sdma_dt_map[] = {
+   /* external DMA requests when tusb6010 is used */
+   { "musb-hdrc.1.auto", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-hdrc.1.auto", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-hdrc.1.auto", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 
only */
 };
 
 static const struct dma_slave_map omap3xxx_sdma_map[] = {
@@ -346,6 +364,12 @@ static int __init omap2_system_dma_init_dev(struct 
omap_hwmod *oh, void *unused)
   __func__);
return -ENODEV;
}
+   } else {
+   if (soc_is_omap24xx()) {
+   /* DMA slave map for drivers not yet converted to DT */
+   p.slave_map = omap24xx_sdma_dt_map;
+   p.slavecnt = ARRAY_SIZE(omap24xx_sdma_dt_map);
+   }
}
 
pdev = omap_device_build(name, 0, oh, &p, sizeof(p));
-- 
2.12.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: [PATCH 0/4] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-03 Thread Peter Ujfalusi

Sorry,

I have forgot to update the commit message for the last patch.

On 2017-05-03 13:54, Peter Ujfalusi wrote:

Hi,

With port_window support implemented in DMAengine and the sDMA DMAengine driver,
the tusb6010_omap driver can be converted away from the custom legacy omap-dma
API to generic DMAengine.

The first two patch is to prepare the tusb6010_omap driver for the conversion.
The third one adds the needed entries for the dma_slave_map so we can request
the DMA channels. This can be reverted when the stack is converted to DT.

The last patch does the main work to move the driver to DMAengine API.

I have tested the set on top of next-20170503 on Nokia n810 with nfsroot using
CDC Ethernet (g_cdc) and copying files with scp to/form my host.

To force that the DMA is actually used I have:
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 05aefcad40b5..a5fc2a6bdad3 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -216,8 +216,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 * use a timer for the callback, but it is unsafe as the XFR_SIZE
 * register is corrupt, and we won't know if the DMA worked.
 */
-   if (dma_addr & 0x2)
-   return false;
+// if (dma_addr & 0x2)
+// return false;

/*
 * Because of HW issue #10, it seems like mixing sync DMA and async

Since this condition will almost all the time was true - effectively disabling
the DMA use.

Regards.
Peter
---
Peter Ujfalusi (4):
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request
lines
  usb: musb: tusb6010_omap: Convert to dmaengine WIP

 arch/arm/mach-omap2/dma.c|  24 +++
 drivers/usb/musb/tusb6010_omap.c | 342 ++-
 2 files changed, 177 insertions(+), 189 deletions(-)



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


Re: [PATCH 0/4] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-05 Thread Peter Ujfalusi



On 2017-05-04 17:31, Tony Lindgren wrote:

* Peter Ujfalusi  [170503 04:00]:

Hi,

With port_window support implemented in DMAengine and the sDMA DMAengine driver,
the tusb6010_omap driver can be converted away from the custom legacy omap-dma
API to generic DMAengine.

The first two patch is to prepare the tusb6010_omap driver for the conversion.
The third one adds the needed entries for the dma_slave_map so we can request
the DMA channels. This can be reverted when the stack is converted to DT.

The last patch does the main work to move the driver to DMAengine API.

I have tested the set on top of next-20170503 on Nokia n810 with nfsroot using
CDC Ethernet (g_cdc) and copying files with scp to/form my host.


Thanks for doing this! For this series:

Acked-by: Tony Lindgren 


To force that the DMA is actually used I have:
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 05aefcad40b5..a5fc2a6bdad3 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -216,8 +216,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 * use a timer for the callback, but it is unsafe as the XFR_SIZE
 * register is corrupt, and we won't know if the DMA worked.
 */
-   if (dma_addr & 0x2)
-   return false;
+// if (dma_addr & 0x2)
+// return false;

/*
 * Because of HW issue #10, it seems like mixing sync DMA and async

Since this condition will almost all the time was true - effectively disabling
the DMA use.


Yeah this really should have the transfers aligned to 32-bit like
the production kernel did. For reference, the following should do
the trick but of course would have to be done conditionally.

Regards,

Tony

8< --
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -2153,6 +2153,7 @@ __acquires(musb->lock)
musb->g.a_alt_hnp_support = 0;
musb->g.a_hnp_support = 0;
musb->g.quirk_zlp_not_supp = 1;
+   musb->g.quirk_avoids_skb_reserve = 1;


note for myself: this only works with g_ncm. I was using g_cdc, switched 
to g_ether, then to g_ncm.
However... If I revert this series and add this line, the ethernet will 
not work at all, I can not ping the n810 and it will not get the nfsroot 
either (next-20170503).


only f_ncm.c does:
ncm->port.no_skb_reserve =
gadget_avoids_skb_reserve(cdev->gadget);


/* Normal reset, as B-Device;
 * or else after HNP, as A-Device



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


Re: [PATCH 4/4] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-05 Thread Peter Ujfalusi

Tony,

On 2017-05-05 00:05, Tony Lindgren wrote:

* Tony Lindgren  [170504 12:43]:

Hi,

* Peter Ujfalusi  [170503 04:00]:

With the port_window support in DMAengine and the sDMA driver we can
convert the driver to DMAengine.


Actually looks like this patch still has some issues.. Pinging
the n8x0 with for example ping -s1 causes things to stop working.


Sorry it's actually ping -s2048, not -s1. Here's what happens
on n8x0 with first ping -s2048 with 4/4 applied:

musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0010
g_ether gadget: invalid EEM CRC
g_ether gadget: invalid EEM CRC
musb-hdrc musb-hdrc.1.auto: ep1 rx dma: 0x86803842 len: 512(512) packet_sz: 
512(512)
musb-hdrc musb-hdrc.1.auto: ep1 rx using 16-bit async dma from 0x02000620 to 
0x86803842
musb-hdrc musb-hdrc.1.auto: ep1 rx dma callback
musb-hdrc musb-hdrc.1.auto: DMA remaining 448/512
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 01c0
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0008
musb-hdrc musb-hdrc.1.auto: ep1 rx dma: 0x869fdc02 len: 512(512) packet_sz: 
512(512)
musb-hdrc musb-hdrc.1.auto: ep1 rx using 16-bit async dma from 0x02000620 to 
0x869fdc02
musb-hdrc musb-hdrc.1.auto: ep1 rx dma callback
musb-hdrc musb-hdrc.1.auto: DMA remaining 448/512
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 01c0
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0008
musb-hdrc musb-hdrc.1.auto: ep1 rx dma: 0x869fc642 len: 512(512) packet_sz: 
512(512)
musb-hdrc musb-hdrc.1.auto: ep1 rx using 16-bit async dma from 0x02000620 to 
0x869fc642
musb-hdrc musb-hdrc.1.auto: ep1 rx dma callback
musb-hdrc musb-hdrc.1.auto: Corrupt rx XFR_SIZE: 0x7ec0
musb-hdrc musb-hdrc.1.auto: DMA remaining 0/512
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 7ec0
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0008
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0010
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 7cf0

It seems the hardware dmareq line is not triggering anything
above?

Also with just ping with no size specified, it seems every other
packet is missed or DMA interrupts are not properly triggering
as I'm getting these:

g_ether gadget: invalid EEM CRC


This is when using only with the async gpmc access as the sync
gpmc access seems to have a regression not related to this series.
I'll try to track down that sync gpmc issue as that most likely
hints to something being wrong in the gpmc code in general.


And this sync gpmc issue seems to be timing related. Setting
DEBUG in tusb6010_omap.c makes it happen easily while without
it it's much harder to trigger. So probably some kind of issue
with GPMC sync timings.


Indeed there are some interesting things happening...
As I said, I was testing with g_cdc (CDC Composite (ECM + ACM)) and I 
found it pretty stable with DMAengine. But short story long:


With the series applied and getting rid of the dma_addr & 0x2, plus 
setting the set the quirk_avoids_skb_reserve flag:

g_cdc (ECM + ACM) boots to nfsroot most of the time, ping, scp works
g_ether (ECM) does not boot to nfsroot, ping does not work. However if I 
disable the rx DMA with:


diff --git a/drivers/usb/musb/tusb6010_omap.c 
b/drivers/usb/musb/tusb6010_omap.c

index 8b43c4b99f04..8e0a19b47132 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -512,6 +512,12 @@ tusb_omap_dma_allocate(struct dma_controller *c,
return NULL;
}

+   if (!tx) {
+   dev_err(musb->controller, "Not allowing RX DMA for ep%i %s\n",
+   chdat->epnum);
+   return NULL;
+   }
+
for (i = 0; i < MAX_DMAREQ; i++) {
struct dma_channel *ch = dma_channel_pool[i];
if (ch->status == MUSB_DMA_STATUS_UNKNOWN) {


nfsroot works, ping and scp also - TX is using DMA.

g_ncm (NCM): not booting to nfsroot, no ping, but if I disable the RX 
DMA, then I have NULL pointer dereference :o

Something is wrong for sure.

But to see what I have been comparing to, I have reverted my series and 
added the dma_addr & 2 and the quirk:


g_cdc (ECM + ACM): no nfsroot, no ping
g_ether (ECM): no nfsroot, no ping
g_ncm (NCM): no nfsroot, no ping, disabling RX DMA allow it to boot up, 
but ping kills the USB


None of this is issue I think currently as the DMA is effectively 
disabled for tusb by the dma_addr & 0x2 check, but it is somehow 
bothersome...


I'll try to pin-point out what is going on.

As reference, my configs are:
https://github.com/omap-audio/linux-audio/blob/peter/linux-next-wip/arch/arm/configs/nokia_n810_cdc_defconfig

https://github.com/omap-audio/linux-audio/blob/peter/linux-next-wip/arch/arm/configs/nokia_n810_ether_defconfig

https://github.com/omap-audio/linux-audio/blob/peter/linux-next-wip/arch/arm/configs/nokia_n810_ncm_defconfig

- Péter
--
To unsubscribe from this list: send the line "unsubsc

Re: [PATCH 4/4] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-05 Thread Peter Ujfalusi



On 2017-05-05 16:37, Peter Ujfalusi wrote:

Tony,

On 2017-05-05 00:05, Tony Lindgren wrote:

* Tony Lindgren  [170504 12:43]:

Hi,

* Peter Ujfalusi  [170503 04:00]:

With the port_window support in DMAengine and the sDMA driver we can
convert the driver to DMAengine.


Actually looks like this patch still has some issues.. Pinging
the n8x0 with for example ping -s1 causes things to stop working.


Sorry it's actually ping -s2048, not -s1. Here's what happens
on n8x0 with first ping -s2048 with 4/4 applied:

musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0010
g_ether gadget: invalid EEM CRC
g_ether gadget: invalid EEM CRC
musb-hdrc musb-hdrc.1.auto: ep1 rx dma: 0x86803842 len: 512(512)
packet_sz: 512(512)
musb-hdrc musb-hdrc.1.auto: ep1 rx using 16-bit async dma from
0x02000620 to 0x86803842
musb-hdrc musb-hdrc.1.auto: ep1 rx dma callback
musb-hdrc musb-hdrc.1.auto: DMA remaining 448/512
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 01c0
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0008
musb-hdrc musb-hdrc.1.auto: ep1 rx dma: 0x869fdc02 len: 512(512)
packet_sz: 512(512)
musb-hdrc musb-hdrc.1.auto: ep1 rx using 16-bit async dma from
0x02000620 to 0x869fdc02
musb-hdrc musb-hdrc.1.auto: ep1 rx dma callback
musb-hdrc musb-hdrc.1.auto: DMA remaining 448/512
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 01c0
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0008
musb-hdrc musb-hdrc.1.auto: ep1 rx dma: 0x869fc642 len: 512(512)
packet_sz: 512(512)
musb-hdrc musb-hdrc.1.auto: ep1 rx using 16-bit async dma from
0x02000620 to 0x869fc642
musb-hdrc musb-hdrc.1.auto: ep1 rx dma callback
musb-hdrc musb-hdrc.1.auto: Corrupt rx XFR_SIZE: 0x7ec0
musb-hdrc musb-hdrc.1.auto: DMA remaining 0/512
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 7ec0
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0008
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 0010
musb-hdrc musb-hdrc.1.auto: Busy rx dma, not using: 7cf0

It seems the hardware dmareq line is not triggering anything
above?

Also with just ping with no size specified, it seems every other
packet is missed or DMA interrupts are not properly triggering
as I'm getting these:

g_ether gadget: invalid EEM CRC


This is when using only with the async gpmc access as the sync
gpmc access seems to have a regression not related to this series.
I'll try to track down that sync gpmc issue as that most likely
hints to something being wrong in the gpmc code in general.


And this sync gpmc issue seems to be timing related. Setting
DEBUG in tusb6010_omap.c makes it happen easily while without
it it's much harder to trigger. So probably some kind of issue
with GPMC sync timings.


Indeed there are some interesting things happening...
As I said, I was testing with g_cdc (CDC Composite (ECM + ACM)) and I
found it pretty stable with DMAengine. But short story long:

With the series applied and getting rid of the dma_addr & 0x2, plus
setting the set the quirk_avoids_skb_reserve flag:
g_cdc (ECM + ACM) boots to nfsroot most of the time, ping, scp works
g_ether (ECM) does not boot to nfsroot, ping does not work. However if I
disable the rx DMA with:

diff --git a/drivers/usb/musb/tusb6010_omap.c
b/drivers/usb/musb/tusb6010_omap.c
index 8b43c4b99f04..8e0a19b47132 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -512,6 +512,12 @@ tusb_omap_dma_allocate(struct dma_controller *c,
 return NULL;
 }

+if (!tx) {
+dev_err(musb->controller, "Not allowing RX DMA for ep%i %s\n",
+chdat->epnum);


Remove the %s and s/chdat/hw_ep

and the kernel will not crash :( But still not booting with DMAengine 
when RX DMA is disabled :o



+return NULL;
+}
+
 for (i = 0; i < MAX_DMAREQ; i++) {
 struct dma_channel *ch = dma_channel_pool[i];
 if (ch->status == MUSB_DMA_STATUS_UNKNOWN) {


nfsroot works, ping and scp also - TX is using DMA.

g_ncm (NCM): not booting to nfsroot, no ping, but if I disable the RX
DMA, then I have NULL pointer dereference :o
Something is wrong for sure.

But to see what I have been comparing to, I have reverted my series and
added the dma_addr & 2 and the quirk:

g_cdc (ECM + ACM): no nfsroot, no ping
g_ether (ECM): no nfsroot, no ping
g_ncm (NCM): no nfsroot, no ping, disabling RX DMA allow it to boot up,
but ping kills the USB

None of this is issue I think currently as the DMA is effectively
disabled for tusb by the dma_addr & 0x2 check, but it is somehow
bothersome...

I'll try to pin-point out what is going on.

As reference, my configs are:
https://github.com/omap-audio/linux-audio/blob/peter/linux-next-wip/arch/arm/configs/nokia_n810_cdc_defconfig


https://github.com/omap-audio/linux-audio/blob/peter/linux-next-wip/arch/arm/configs/nokia_n810_ether_defconfig


https://github.com/omap-audio/linux-audio/blob/peter/linux-next-wip/arch/

Re: [PATCH 4/4] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-08 Thread Peter Ujfalusi

Tony,

On 2017-05-06 01:55, Tony Lindgren wrote:

OK I verified that with the current mainline kernel using dma
and g_ether and your patches 1 to 3 I can run the variable size
ping test loop for few minutes before it just stops working and
I can see the legacy DMA interrupt increase depending on the
size of the packet. Then I checked with v4.1 kernel, and that
too seems to have the same issue.

I've also verified running the same variable size ping test with
your patch 4/4 makes things stop within just a few seconds. The
script I'm using for ping is below.

Anyways, what we really should ensure here is that the external
dmarequest line is properly triggering things with dmaengine :)
That's why I'm a bit worried your patch 4/4.

Oh and I also verified the GPMC timings we're using are the same
as in production n810 kernel so that should not be the issue.

And using the async access on n800 will not work as it will
produce corrupt transfer size register the report I posted
earlier is from n800 allowing it to use async transfers. On
n810 async transfers may work as I recall it having a newer
tusb6010 version.


I think I have nailed the issue. I had a bug in the omap-dma 
implementation of the port_window (sigh) and couple of issues in the 
tusb6010/*_omap, not introduced by the series.
The ASYNC access is pretty unstable on n810 as well, I got corruption in 
the XFR_SIZE.
I have been using the g_ncm gadget with 
"musb->g.quirk_avoids_skb_reserve = 1;" to ensure that we are using SYNC 
access.


I'm running your variable ping script for 2 hours now, it wrapped >130 
times already, I also run a standalone ping with 2048 size in parallel, 
the n810 is booted to nfsroot:


# cat /proc/interrupts | grep dma
 29:9483598  INTC  13 Edge  omap-dma-engine
#

I need to clean up the code as I had debugs (disabled now) and stuff and 
I want to try the tusb6010 changes w/o the DMAengine conversion.




Regards,

Tony

8< 
#!/bin/bash

device=$1
size=$2


+ wraps = 0



while [ 1 ]; do
#echo "Pinging with size $size"
if ! ping -w0 -c1 -s$size $device > /dev/null 2>&1; then
break;
fi
size=$(expr $size + 1)

if [ $size -gt 8192 ]; then


+   wraps=$(expr $wraps + 1)
+   echo "wrapping ($wraps) at $size"


size=1
fi
done
echo "Test ran up to $size"



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


[PATCH v2 07/10] usb: musb: tusb6010_omap: Allocate DMA channels upfront

2017-05-10 Thread Peter Ujfalusi
Instead of requesting the DMA channel in tusb_omap_dma_allocate() do it
when the controller is created and in runtime work from the DMA channel
pool.

This change is needed for the DMAengine conversion of the driver since the
tusb_omap_dma_allocate() is called in interrupt context which might lead
to lock within the DMAengine API when requesting channel.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 184 +++
 1 file changed, 92 insertions(+), 92 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index f1e58e15e5bb..2daeef7e572d 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -45,7 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_data*dma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -62,7 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_datadma_pool[MAX_DMAREQ];
unsignedmultichannel:1;
 };
 
@@ -120,10 +120,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
spin_lock_irqsave(&musb->lock, flags);
 
-   if (tusb_dma->multichannel)
-   ch = chdat->dma_data.ch;
-   else
-   ch = tusb_dma->dma_data.ch;
+   ch = chdat->dma_data->ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -247,7 +244,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
+   chdat->tx ? "tx" : "rx",
+   chdat->dma_data ? chdat->dma_data->ch : -1,
dma_remaining);
return false;
}
@@ -259,11 +257,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
else
chdat->transfer_packet_sz = packet_sz;
 
-   if (tusb_dma->multichannel) {
-   dma_data = &chdat->dma_data;
-   } else {
-   dma_data = &tusb_dma->dma_data;
-
+   dma_data = chdat->dma_data;
+   if (!tusb_dma->multichannel) {
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
@@ -275,10 +270,10 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
WARN_ON(1);
return false;
}
-
-   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
}
 
+   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
+
chdat->packet_sz = packet_sz;
chdat->len = len;
channel->actual_len = 0;
@@ -409,19 +404,9 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 static int tusb_omap_dma_abort(struct dma_channel *channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
-   struct tusb_omap_dma*tusb_dma = chdat->tusb_dma;
-   struct tusb_dma_data*dma_data = &tusb_dma->dma_data;
 
-   if (!tusb_dma->multichannel) {
-   if (dma_data->ch >= 0) {
-   omap_stop_dma(dma_data->ch);
-   omap_free_dma(dma_data->ch);
-   dma_data->ch = -1;
-   }
-
-   dma_data->dmareq = -1;
-   dma_data->sync_dev = -1;
-   }
+   if (chdat->dma_data)
+   omap_stop_dma(chdat->dma_data->ch);
 
channel->status = MUSB_DMA_STATUS_FREE;
 
@@ -433,15 +418,6 @@ static inline int tusb_omap_dma_allocate_dmareq(struct 
tusb_omap_dma_ch *chdat)
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
int i, dmareq_nr = -1;
 
-   const int sync_dev[6] = {
-   OMAP24XX_DMA_EXT_DMAREQ0,
-   OMAP24XX_DMA_EXT_DMAREQ1,
-   OMAP242X_DMA_EXT_DMAREQ2,
-   OMAP242X_DMA_EXT_DMAREQ3,
-   OMAP242X_DMA_EXT_DMAREQ4,
-   OMAP242X_DMA_EXT_DMAREQ5,
-   };
-
for (i = 0; i < MAX_DMAREQ; i++) {
int cur = (reg & (0xf << (i * 5))) >> (i * 5);

[PATCH v2 04/10] usb: musb: tusb6010_omap: Use one musb_ep_select call in tusb_omap_dma_program

2017-05-10 Thread Peter Ujfalusi
Having one musb_ep_select() instead the two calls in if/else is the same
thing, but makes the code a bit simpler to follow.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 8b43c4b99f04..db2e4c379ccf 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -367,15 +367,14 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
/*
 * Prepare MUSB for DMA transfer
 */
+   musb_ep_select(mbase, chdat->epnum);
if (chdat->tx) {
-   musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
csr &= ~MUSB_TXCSR_P_UNDERRUN;
musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
} else {
-   musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
csr |= MUSB_RXCSR_DMAENAB;
csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
-- 
2.12.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 v2 09/10] ARM: OMAP2+: DMA: Add slave map entries for 24xx external request lines

2017-05-10 Thread Peter Ujfalusi
The external request lines are used by tusb6010 on OMAP24xx platforms.
Update the map so the driver can use dmaengine API to request the DMA
channel. At the same time add temporary map containing only the external
DMA request numbers for DT booted case on omap24xx since the tusb6010 stack
is not yet supports DT boot.

Signed-off-by: Peter Ujfalusi 
---
 arch/arm/mach-omap2/dma.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e58c13a9bea5..0b77a0176018 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -249,6 +249,24 @@ static const struct dma_slave_map omap24xx_sdma_map[] = {
{ "omap_uart.2", "rx", SDMA_FILTER_PARAM(54) },
{ "omap_hsmmc.0", "tx", SDMA_FILTER_PARAM(61) },
{ "omap_hsmmc.0", "rx", SDMA_FILTER_PARAM(62) },
+
+   /* external DMA requests when tusb6010 is used */
+   { "musb-tusb", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-tusb", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-tusb", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 only */
+};
+
+static const struct dma_slave_map omap24xx_sdma_dt_map[] = {
+   /* external DMA requests when tusb6010 is used */
+   { "musb-hdrc.1.auto", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-hdrc.1.auto", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-hdrc.1.auto", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 
only */
 };
 
 static const struct dma_slave_map omap3xxx_sdma_map[] = {
@@ -346,6 +364,12 @@ static int __init omap2_system_dma_init_dev(struct 
omap_hwmod *oh, void *unused)
   __func__);
return -ENODEV;
}
+   } else {
+   if (soc_is_omap24xx()) {
+   /* DMA slave map for drivers not yet converted to DT */
+   p.slave_map = omap24xx_sdma_dt_map;
+   p.slavecnt = ARRAY_SIZE(omap24xx_sdma_dt_map);
+   }
}
 
pdev = omap_device_build(name, 0, oh, &p, sizeof(p));
-- 
2.12.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 v2 06/10] usb: musb: tusb6010_omap: Create new struct for DMA data/parameters

2017-05-10 Thread Peter Ujfalusi
For the DMA we have ch (channel), dmareq and sync_dev parameters both
within the tusb_omap_dma_ch and tusb_omap_dma_ch struct.
By creating a common struct the code can be simplified when selecting
between the shared or multichannel DMA parameters.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 163 ---
 1 file changed, 84 insertions(+), 79 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 4e1a6e4a61b8..f1e58e15e5bb 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -31,6 +31,12 @@
 #define OMAP242X_DMA_EXT_DMAREQ4   16
 #define OMAP242X_DMA_EXT_DMAREQ5   64
 
+struct tusb_dma_data {
+   int ch;
+   s8  dmareq;
+   s8  sync_dev;
+};
+
 struct tusb_omap_dma_ch {
struct musb *musb;
void __iomem*tbase;
@@ -39,9 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -58,9 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
unsignedmultichannel:1;
 };
 
@@ -119,9 +121,9 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
spin_lock_irqsave(&musb->lock, flags);
 
if (tusb_dma->multichannel)
-   ch = chdat->ch;
+   ch = chdat->dma_data.ch;
else
-   ch = tusb_dma->ch;
+   ch = tusb_dma->dma_data.ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -140,8 +142,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
-   remaining);
+   chdat->tx ? "tx" : "rx", ch, remaining);
remaining = 0;
}
 
@@ -219,9 +220,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
u32 dma_remaining;
int src_burst, dst_burst;
u16 csr;
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_data*dma_data;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -248,7 +247,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
+   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
dma_remaining);
return false;
}
@@ -261,15 +260,15 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
chdat->transfer_packet_sz = packet_sz;
 
if (tusb_dma->multichannel) {
-   ch = chdat->ch;
-   dmareq = chdat->dmareq;
-   sync_dev = chdat->sync_dev;
+   dma_data = &chdat->dma_data;
} else {
+   dma_data = &tusb_dma->dma_data;
+
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
}
-   if (tusb_dma->ch < 0) {
+   if (dma_data->ch < 0) {
/* REVISIT: This should get blocked earlier, happens
 * with MSC ErrorRecoveryTest
 */
@@ -277,10 +276,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
return false;
}
 
-

[PATCH v2 01/10] dmaengine: omap-dma: port_window support correction for both direction

2017-05-10 Thread Peter Ujfalusi
When the port_window support was verified it was done on setup where only
the MEM_TO_DEV direction was enabled. This got un-noticed and thus only
this direction worked.

Now that I have managed to get a setup to verify both direction it turned
out that the setup was incorrect:
omap_desc members are settings for the slave port while the omap_sg members
apply to the memory side of the sDMA setup.

Fixes: 527a27591312 ("dmaengine: omap-dma: Fix the port_window support")
Signed-off-by: Peter Ujfalusi 
Cc: Russell King 
Cc: dmaeng...@vger.kernel.org
Cc: dan.j.willi...@intel.com
Cc: vinod.k...@intel.com
---
 drivers/dma/omap-dma.c | 39 +++
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index eed745a598fa..4fc86d40b50c 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -948,12 +948,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
return NULL;
}
 
-   /* When the port_window is used, one frame must cover the window */
-   if (port_window) {
-   burst = port_window;
-   port_window_bytes = port_window * es_bytes[es];
-   }
-
/* Now allocate and setup the descriptor. */
d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
if (!d)
@@ -963,6 +957,21 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
d->dev_addr = dev_addr;
d->es = es;
 
+   /* When the port_window is used, one frame must cover the window */
+   if (port_window) {
+   burst = port_window;
+   port_window_bytes = port_window * es_bytes[es];
+
+   d->ei = 1;
+   /*
+* One frame covers the port_window and by  configure
+* the source frame index to be -1 * (port_window - 1)
+* we instruct the sDMA that after a frame is processed
+* it should move back to the start of the window.
+*/
+   d->fi = -(port_window_bytes - 1);
+   }
+
d->ccr = c->ccr | CCR_SYNC_FRAME;
if (dir == DMA_DEV_TO_MEM) {
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
@@ -987,14 +996,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
d->ccr |= CCR_SRC_AMODE_POSTINC;
if (port_window) {
d->ccr |= CCR_DST_AMODE_DBLIDX;
-   d->ei = 1;
-   /*
-* One frame covers the port_window and by  configure
-* the source frame index to be -1 * (port_window - 1)
-* we instruct the sDMA that after a frame is processed
-* it should move back to the start of the window.
-*/
-   d->fi = -(port_window_bytes - 1);
 
if (port_window_bytes >= 64)
d->csdp |= CSDP_DST_BURST_64;
@@ -1050,16 +1051,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
osg->addr = sg_dma_address(sgent);
osg->en = en;
osg->fn = sg_dma_len(sgent) / frame_bytes;
-   if (port_window && dir == DMA_DEV_TO_MEM) {
-   osg->ei = 1;
-   /*
-* One frame covers the port_window and by  configure
-* the source frame index to be -1 * (port_window - 1)
-* we instruct the sDMA that after a frame is processed
-* it should move back to the start of the window.
-*/
-   osg->fi = -(port_window_bytes - 1);
-   }
 
if (d->using_ll) {
osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC,
-- 
2.12.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 v2 08/10] usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well

2017-05-10 Thread Peter Ujfalusi
Handle the DMA TX in a similar way as we do for the RX: in the DMA
completion callback.

Since we are no longer using DMA completion interrupt for the TX we can as
wall keep these interrupts disabled, but keep the handler for debug
purposes.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010.c  | 18 +++---
 drivers/usb/musb/tusb6010_omap.c | 34 +-
 2 files changed, 4 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 4253bfb22043..4eb640c54f2c 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -881,26 +881,14 @@ static irqreturn_t tusb_musb_interrupt(int irq, void 
*__hci)
| TUSB_INT_SRC_ID_STATUS_CHNG))
idle_timeout = tusb_otg_ints(musb, int_src, tbase);
 
-   /* TX dma callback must be handled here, RX dma callback is
-* handled in tusb_omap_dma_cb.
+   /*
+* Just clear the DMA interrupt if it comes as the completion for both
+* TX and RX is handled by the DMA callback in tusb6010_omap
 */
if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE)) {
u32 dma_src = musb_readl(tbase, TUSB_DMA_INT_SRC);
-   u32 real_dma_src = musb_readl(tbase, TUSB_DMA_INT_MASK);
 
dev_dbg(musb->controller, "DMA IRQ %08x\n", dma_src);
-   real_dma_src = ~real_dma_src & dma_src;
-   if (tusb_dma_omap(musb) && real_dma_src) {
-   int tx_source = (real_dma_src & 0x);
-   int i;
-
-   for (i = 1; i <= 15; i++) {
-   if (tx_source & (1 << i)) {
-   dev_dbg(musb->controller, "completing 
ep%i %s\n", i, "tx");
-   musb_dma_completion(musb, i, 1);
-   }
-   }
-   }
musb_writel(tbase, TUSB_DMA_INT_CLEAR, dma_src);
}
 
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 2daeef7e572d..34e0115a4629 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -173,13 +173,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
channel->status = MUSB_DMA_STATUS_FREE;
 
-   /* Handle only RX callbacks here. TX callbacks must be handled based
-* on the TUSB DMA status interrupt.
-* REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
-* interrupt for RX and TX.
-*/
-   if (!chdat->tx)
-   musb_dma_completion(musb, chdat->epnum, chdat->tx);
+   musb_dma_completion(musb, chdat->epnum, chdat->tx);
 
/* We must terminate short tx transfers manually by setting TXPKTRDY.
 * REVISIT: This same problem may occur with other MUSB dma as well.
@@ -463,22 +457,12 @@ tusb_omap_dma_allocate(struct dma_controller *c,
int ret, i;
struct tusb_omap_dma*tusb_dma;
struct musb *musb;
-   void __iomem*tbase;
struct dma_channel  *channel = NULL;
struct tusb_omap_dma_ch *chdat = NULL;
struct tusb_dma_data*dma_data = NULL;
-   u32 reg;
 
tusb_dma = container_of(c, struct tusb_omap_dma, controller);
musb = tusb_dma->controller.musb;
-   tbase = musb->ctrl_base;
-
-   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
-   if (tx)
-   reg &= ~(1 << hw_ep->epnum);
-   else
-   reg &= ~(1 << (hw_ep->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
 
/* REVISIT: Why does dmareq5 not work? */
if (hw_ep->epnum == 0) {
@@ -547,26 +531,10 @@ static void tusb_omap_dma_release(struct dma_channel 
*channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
struct musb *musb = chdat->musb;
-   void __iomem*tbase = musb->ctrl_base;
-   u32 reg;
 
dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
chdat->dma_data->ch);
 
-   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
-   if (chdat->tx)
-   reg |= (1 << chdat->epnum);
-   else
-   reg |= (1 << (chdat->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
-
-   reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
-   if (chdat->tx)
-   reg |= (1 << chdat->epnum);
-   else
-   reg |= (1 << (chdat->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
-
channel->status = MUSB_DMA_STATUS_UNKNOWN;
 
omap_stop_dma(chdat->dma_data-&g

[PATCH v2 05/10] usb: musb: tusb6010_omap: Do not reset the other direction's packet size

2017-05-10 Thread Peter Ujfalusi
We have one register for each EP to set the maximum packet size for both
TX and RX.
If for example an RX programming would happen before the previous TX
transfer finishes we would reset the TX packet side.

To fix this issue, only modify the TX or RX part of the register.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index db2e4c379ccf..4e1a6e4a61b8 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -389,15 +389,19 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 
if (chdat->tx) {
/* Send transfer_packet_sz packets at a time */
-   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-   chdat->transfer_packet_sz);
+   u32 psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+   psize &= ~0x7ff;
+   psize |= chdat->transfer_packet_sz;
+   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
} else {
/* Receive transfer_packet_sz packets at a time */
-   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-   chdat->transfer_packet_sz << 16);
+   u32 psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+   psize &= ~(0x7ff << 16);
+   psize |= (chdat->transfer_packet_sz << 16);
+   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
-- 
2.12.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 v2 02/10] usb: musb: Add quirk to avoid skb reserve in gadget mode

2017-05-10 Thread Peter Ujfalusi
For tusb6010 the DMA functionality only possible if the buffer is 32bit
aligned (SYNC access to FIFO) since with ASYNC access the TX/RX offset
registers will corrupt eventually.
The MUSB_G_NO_SKB_RESERVE will set the quirk_avoids_skb_reserve flag in
usb_gadget struct to provide correctly aligned buffer.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/musb_core.c | 3 +++
 drivers/usb/musb/musb_core.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 870da18f5077..87cbd56cc761 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2224,6 +2224,9 @@ musb_init_controller(struct device *dev, int nIrq, void 
__iomem *ctrl)
musb->io.ep_select = musb_flat_ep_select;
}
 
+   if (musb->io.quirks & MUSB_G_NO_SKB_RESERVE)
+   musb->g.quirk_avoids_skb_reserve = 1;
+
/* At least tusb6010 has its own offsets */
if (musb->ops->ep_offset)
musb->io.ep_offset = musb->ops->ep_offset;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 3e98d4268a64..9f22c5b8ce37 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -172,6 +172,7 @@ struct musb_io;
  */
 struct musb_platform_ops {
 
+#define MUSB_G_NO_SKB_RESERVE  BIT(9)
 #define MUSB_DA8XX BIT(8)
 #define MUSB_PRESERVE_SESSION  BIT(7)
 #define MUSB_DMA_UX500 BIT(6)
-- 
2.12.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 v2 03/10] usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks

2017-05-10 Thread Peter Ujfalusi
When using the g_ncm for networking this flag will make sure that the
buffer is alligned to 32bit so the DMA can be used to offload the data
movement.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index e85cc8e4e7a9..4253bfb22043 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1181,7 +1181,8 @@ static int tusb_musb_exit(struct musb *musb)
 }
 
 static const struct musb_platform_ops tusb_ops = {
-   .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB,
+   .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB |
+ MUSB_G_NO_SKB_RESERVE,
.init   = tusb_musb_init,
.exit   = tusb_musb_exit,
 
-- 
2.12.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 v2 00/10] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-10 Thread Peter Ujfalusi
Hi,

Changes since v1:
- Fix the port_window support in omap-dma DMAengine driver
- MUSB_G_NO_SKB_RESERVE quirk flag addition to msub core
- packet size corruption fix for tusb6010
- Handle DMA completion for TX also in the DMA callback

The v1 series was tested with g_cdc where only the DMA was only enabled for TX
and because of that I have not noticed that the sDMA code was not correct for 
RX,
it only worked for TX case.

The ASYNC mode of tusb6010 is really unstable, we get corrupted TX/RX offset
register quite easily, but the SYNC mode is stable.

The series was tested on top of next-20170510 with g_ncm module since with this
we can use the quirk to avoid skb_reserve and get properly aligned buffers for
DMA.
The n810 is using nfsroot.

The device would not boot to prompt most of the time before patch 5 (packet size
reset fix).
With that patch in, the device would boot up fine most of the cases, but will
fail pretty fast with my stress test [1].
After the first 9 patch the legacy DMA mode is going to be stable with g_ncm, it
boots to prompt, and survives the stress test [1].

The last patch is going the DMAengine conversion and I have run the stress test
against it over 3 hours (ping-test.sh wrap count is 139).

[1] Running these in parallel:
ping -f 192.168.0.2
ping -f -s 2048 192.168.0.2
ping-test.sh 192.168.0.2 1

and (nfsroot) time to time:
scp root@192.168.0.1:/usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz /

$ ls -alh /usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz 
218M Apr 30 15:46 /usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz

In essence copy 218M from my host back to the host.

ping-test.sh (modified version from Tony to show the wrap count):
#!/bin/bash

device=$1
size=$2
wraps=0

while [ 1 ]; do
#echo "Pinging with size $size"
if ! ping -w0 -c1 -s$size $device > /dev/null 2>&1; then
break;
fi
size=$(expr $size + 1)

if [ $size -gt 8192 ]; then
wraps=$(expr $wraps + 1)
echo "wrapping ($wraps) at $size"
size=1
fi
done
echo "Test ran up to $size"

Regards,
Peter

CC: dmaeng...@vger.kernel.org
I only send the cover letter and the DMAengine patch for the dmaengine list, the
rest can be checked - if there is interest - via lkml
---
Peter Ujfalusi (10):
  dmaengine: omap-dma: port_window support correction for both direction
  usb: musb: Add quirk to avoid skb reserve in gadget mode
  usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks
  usb: musb: tusb6010_omap: Use one musb_ep_select call in
tusb_omap_dma_program
  usb: musb: tusb6010_omap: Do not reset the other direction's packet
size
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request
lines
  usb: musb: tusb6010_omap: Convert to DMAengine API

 arch/arm/mach-omap2/dma.c|  24 +++
 drivers/dma/omap-dma.c   |  39 ++--
 drivers/usb/musb/musb_core.c |   3 +
 drivers/usb/musb/musb_core.h |   1 +
 drivers/usb/musb/tusb6010.c  |  21 +--
 drivers/usb/musb/tusb6010_omap.c | 391 ---
 6 files changed, 211 insertions(+), 268 deletions(-)

-- 
2.12.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 v2 10/10] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-10 Thread Peter Ujfalusi
With the port_window support in DMAengine and the sDMA driver we can
convert the driver to DMAengine.

Signed-off-by: Peter Ujfalusi 
---
 drivers/usb/musb/tusb6010_omap.c | 201 ---
 1 file changed, 80 insertions(+), 121 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 34e0115a4629..0c2bd0befe72 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include "musb_core.h"
 #include "tusb6010.h"
@@ -24,17 +24,9 @@
 
 #define MAX_DMAREQ 5   /* REVISIT: Really 6, but req5 not OK */
 
-#define OMAP24XX_DMA_EXT_DMAREQ0   2
-#define OMAP24XX_DMA_EXT_DMAREQ1   3
-#define OMAP242X_DMA_EXT_DMAREQ2   14
-#define OMAP242X_DMA_EXT_DMAREQ3   15
-#define OMAP242X_DMA_EXT_DMAREQ4   16
-#define OMAP242X_DMA_EXT_DMAREQ5   64
-
 struct tusb_dma_data {
-   int ch;
s8  dmareq;
-   s8  sync_dev;
+   struct dma_chan *chan;
 };
 
 struct tusb_omap_dma_ch {
@@ -105,7 +97,7 @@ static inline void tusb_omap_free_shared_dmareq(struct 
tusb_omap_dma_ch *chdat)
  * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
  * musb_gadget.c.
  */
-static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
+static void tusb_omap_dma_cb(void *data)
 {
struct dma_channel  *channel = (struct dma_channel *)data;
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
@@ -116,18 +108,11 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
void __iomem*ep_conf = hw_ep->conf;
void __iomem*mbase = musb->mregs;
unsigned long   remaining, flags, pio;
-   int ch;
 
spin_lock_irqsave(&musb->lock, flags);
 
-   ch = chdat->dma_data->ch;
-
-   if (ch_status != OMAP_DMA_BLOCK_IRQ)
-   printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
-
-   dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
-   chdat->epnum, chdat->tx ? "tx" : "rx",
-   ch, ch_status);
+   dev_dbg(musb->controller, "ep%i %s dma callback\n",
+   chdat->epnum, chdat->tx ? "tx" : "rx");
 
if (chdat->tx)
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
@@ -138,8 +123,8 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
-   dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", ch, remaining);
+   dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
+   chdat->tx ? "tx" : "rx", remaining);
remaining = 0;
}
 
@@ -206,12 +191,15 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
struct musb_hw_ep   *hw_ep = chdat->hw_ep;
void __iomem*mbase = musb->mregs;
void __iomem*ep_conf = hw_ep->conf;
-   dma_addr_t  fifo = hw_ep->fifo_sync;
-   struct omap_dma_channel_params  dma_params;
+   dma_addr_t  fifo_addr = hw_ep->fifo_sync;
u32 dma_remaining;
-   int src_burst, dst_burst;
u16 csr;
struct tusb_dma_data*dma_data;
+   struct dma_async_tx_descriptor  *dma_desc;
+   struct dma_slave_config dma_cfg;
+   enum dma_transfer_direction dma_dir;
+   u32 port_window;
+   int ret;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -237,10 +225,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
-   dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx",
-   chdat->dma_data ? chdat->dma_data->ch : -1,
-   dma_remaining);
+   dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
+   chdat->tx ? "tx" : "rx", dma_remaining);

Re: [PATCH v2 05/10] usb: musb: tusb6010_omap: Do not reset the other direction's packet size

2017-05-10 Thread Peter Ujfalusi



On 2017-05-11 02:16, Joe Perches wrote:

On Wed, 2017-05-10 at 12:07 -0500, Bin Liu wrote:

On Wed, May 10, 2017 at 11:42:27AM +0300, Peter Ujfalusi wrote:

We have one register for each EP to set the maximum packet size for both
TX and RX.
If for example an RX programming would happen before the previous TX
transfer finishes we would reset the TX packet side.

To fix this issue, only modify the TX or RX part of the register.

[]

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c

[]

@@ -389,15 +389,19 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
  
  	if (chdat->tx) {

/* Send transfer_packet_sz packets at a time */
-   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-   chdat->transfer_packet_sz);
+   u32 psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);


checkpatch.pl complains about declaration and assignment together.


No it doesn't.


It 'only' complains about:
WARNING: Missing a blank line after declarations

which is valid.

- Péter
--
To unsubscribe from this list: send the line "unsubscribe 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 05/10] usb: musb: tusb6010_omap: Do not reset the other direction's packet size

2017-05-11 Thread Peter Ujfalusi

Bin,

On 2017-05-11 17:12, Bin Liu wrote:

which is valid.


So will you update the patch to move the declaration to the beginning of
the function to avoid this WARNING. I would just fix it locally if you
prefer.


I was waiting for Vinod or someone from the DMAengine guys to say 
something for the first patch to send the v3, but I guess I can do it 
right away.


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


[PATCH] usb: musb: tusb6010_omap: Do not reset the other direction's packet size

2017-05-12 Thread Peter Ujfalusi
We have one register for each EP to set the maximum packet size for both
TX and RX.
If for example an RX programming would happen before the previous TX
transfer finishes we would reset the TX packet side.

To fix this issue, only modify the TX or RX part of the register.

Fixes: 550a7375fe72 ("USB: Add MUSB and TUSB support")
Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
Bin,

I have separated the patch from the tusb DMAengine conversion series and that
will depend on this patch.

Regards,
Peter

 drivers/usb/musb/tusb6010_omap.c | 13 +
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 8b43c4b99f04..7870b37e0ea5 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -219,6 +219,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
u32 dma_remaining;
int src_burst, dst_burst;
u16 csr;
+   u32 psize;
int ch;
s8  dmareq;
s8  sync_dev;
@@ -390,15 +391,19 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 
if (chdat->tx) {
/* Send transfer_packet_sz packets at a time */
-   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-   chdat->transfer_packet_sz);
+   psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+   psize &= ~0x7ff;
+   psize |= chdat->transfer_packet_sz;
+   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
musb_writel(ep_conf, TUSB_EP_TX_OFFSET,
TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
} else {
/* Receive transfer_packet_sz packets at a time */
-   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET,
-   chdat->transfer_packet_sz << 16);
+   psize = musb_readl(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET);
+   psize &= ~(0x7ff << 16);
+   psize |= (chdat->transfer_packet_sz << 16);
+   musb_writel(ep_conf, TUSB_EP_MAX_PACKET_SIZE_OFFSET, psize);
 
musb_writel(ep_conf, TUSB_EP_RX_OFFSET,
TUSB_EP_CONFIG_XFR_SIZE(chdat->transfer_len));
-- 
2.13.0

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


[PATCH v3 5/9] usb: musb: tusb6010_omap: Create new struct for DMA data/parameters

2017-05-12 Thread Peter Ujfalusi
For the DMA we have ch (channel), dmareq and sync_dev parameters both
within the tusb_omap_dma_ch and tusb_omap_dma_ch struct.
By creating a common struct the code can be simplified when selecting
between the shared or multichannel DMA parameters.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 163 ---
 1 file changed, 84 insertions(+), 79 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 025b52e0b34d..938ded0c407b 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -31,6 +31,12 @@
 #define OMAP242X_DMA_EXT_DMAREQ4   16
 #define OMAP242X_DMA_EXT_DMAREQ5   64
 
+struct tusb_dma_data {
+   int ch;
+   s8  dmareq;
+   s8  sync_dev;
+};
+
 struct tusb_omap_dma_ch {
struct musb *musb;
void __iomem*tbase;
@@ -39,9 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -58,9 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
unsignedmultichannel:1;
 };
 
@@ -119,9 +121,9 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
spin_lock_irqsave(&musb->lock, flags);
 
if (tusb_dma->multichannel)
-   ch = chdat->ch;
+   ch = chdat->dma_data.ch;
else
-   ch = tusb_dma->ch;
+   ch = tusb_dma->dma_data.ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -140,8 +142,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
-   remaining);
+   chdat->tx ? "tx" : "rx", ch, remaining);
remaining = 0;
}
 
@@ -220,9 +221,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
int src_burst, dst_burst;
u16 csr;
u32 psize;
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_data*dma_data;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -249,7 +248,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
+   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
dma_remaining);
return false;
}
@@ -262,15 +261,15 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
chdat->transfer_packet_sz = packet_sz;
 
if (tusb_dma->multichannel) {
-   ch = chdat->ch;
-   dmareq = chdat->dmareq;
-   sync_dev = chdat->sync_dev;
+   dma_data = &chdat->dma_data;
} else {
+   dma_data = &tusb_dma->dma_data;
+
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
}
-   if (tusb_dma->ch < 0) {
+   if (dma_data->ch < 0) {
/* REVISIT: This should get blocked earlier, happens
 * with MSC ErrorRecoveryTest
 */
@@ -278,10 +277,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
return false;

[PATCH v3 1/9] dmaengine: omap-dma: port_window support correction for both direction

2017-05-12 Thread Peter Ujfalusi
When the port_window support was verified it was done on setup where only
the MEM_TO_DEV direction was enabled. This got un-noticed and thus only
this direction worked.

Now that I have managed to get a setup to verify both direction it turned
out that the setup was incorrect:
omap_desc members are settings for the slave port while the omap_sg members
apply to the memory side of the sDMA setup.

Fixes: 527a27591312 ("dmaengine: omap-dma: Fix the port_window support")
Signed-off-by: Peter Ujfalusi 
Cc: Russell King 
Cc: dmaeng...@vger.kernel.org
Cc: dan.j.willi...@intel.com
Cc: vinod.k...@intel.com
Tested-by: Tony Lindgren 
---
 drivers/dma/omap-dma.c | 39 +++
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index daf479cce691..8c1665c8fe33 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -916,12 +916,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
return NULL;
}
 
-   /* When the port_window is used, one frame must cover the window */
-   if (port_window) {
-   burst = port_window;
-   port_window_bytes = port_window * es_bytes[es];
-   }
-
/* Now allocate and setup the descriptor. */
d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
if (!d)
@@ -931,6 +925,21 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
d->dev_addr = dev_addr;
d->es = es;
 
+   /* When the port_window is used, one frame must cover the window */
+   if (port_window) {
+   burst = port_window;
+   port_window_bytes = port_window * es_bytes[es];
+
+   d->ei = 1;
+   /*
+* One frame covers the port_window and by  configure
+* the source frame index to be -1 * (port_window - 1)
+* we instruct the sDMA that after a frame is processed
+* it should move back to the start of the window.
+*/
+   d->fi = -(port_window_bytes - 1);
+   }
+
d->ccr = c->ccr | CCR_SYNC_FRAME;
if (dir == DMA_DEV_TO_MEM) {
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
@@ -955,14 +964,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
d->ccr |= CCR_SRC_AMODE_POSTINC;
if (port_window) {
d->ccr |= CCR_DST_AMODE_DBLIDX;
-   d->ei = 1;
-   /*
-* One frame covers the port_window and by  configure
-* the source frame index to be -1 * (port_window - 1)
-* we instruct the sDMA that after a frame is processed
-* it should move back to the start of the window.
-*/
-   d->fi = -(port_window_bytes - 1);
 
if (port_window_bytes >= 64)
d->csdp |= CSDP_DST_BURST_64;
@@ -1018,16 +1019,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
osg->addr = sg_dma_address(sgent);
osg->en = en;
osg->fn = sg_dma_len(sgent) / frame_bytes;
-   if (port_window && dir == DMA_DEV_TO_MEM) {
-   osg->ei = 1;
-   /*
-* One frame covers the port_window and by  configure
-* the source frame index to be -1 * (port_window - 1)
-* we instruct the sDMA that after a frame is processed
-* it should move back to the start of the window.
-*/
-   osg->fi = -(port_window_bytes - 1);
-   }
 
if (d->using_ll) {
osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC,
-- 
2.13.0

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


[PATCH v3 8/9] ARM: OMAP2+: DMA: Add slave map entries for 24xx external request lines

2017-05-12 Thread Peter Ujfalusi
The external request lines are used by tusb6010 on OMAP24xx platforms.
Update the map so the driver can use dmaengine API to request the DMA
channel. At the same time add temporary map containing only the external
DMA request numbers for DT booted case on omap24xx since the tusb6010 stack
is not yet supports DT boot.

Signed-off-by: Peter Ujfalusi 
Acked-by: Tony Lindgren 
---
 arch/arm/mach-omap2/dma.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e58c13a9bea5..0b77a0176018 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -249,6 +249,24 @@ static const struct dma_slave_map omap24xx_sdma_map[] = {
{ "omap_uart.2", "rx", SDMA_FILTER_PARAM(54) },
{ "omap_hsmmc.0", "tx", SDMA_FILTER_PARAM(61) },
{ "omap_hsmmc.0", "rx", SDMA_FILTER_PARAM(62) },
+
+   /* external DMA requests when tusb6010 is used */
+   { "musb-tusb", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-tusb", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-tusb", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 only */
+};
+
+static const struct dma_slave_map omap24xx_sdma_dt_map[] = {
+   /* external DMA requests when tusb6010 is used */
+   { "musb-hdrc.1.auto", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-hdrc.1.auto", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-hdrc.1.auto", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 
only */
 };
 
 static const struct dma_slave_map omap3xxx_sdma_map[] = {
@@ -346,6 +364,12 @@ static int __init omap2_system_dma_init_dev(struct 
omap_hwmod *oh, void *unused)
   __func__);
return -ENODEV;
}
+   } else {
+   if (soc_is_omap24xx()) {
+   /* DMA slave map for drivers not yet converted to DT */
+   p.slave_map = omap24xx_sdma_dt_map;
+   p.slavecnt = ARRAY_SIZE(omap24xx_sdma_dt_map);
+   }
}
 
pdev = omap_device_build(name, 0, oh, &p, sizeof(p));
-- 
2.13.0

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


[PATCH v3 2/9] usb: musb: Add quirk to avoid skb reserve in gadget mode

2017-05-12 Thread Peter Ujfalusi
For tusb6010 the DMA functionality only possible if the buffer is 32bit
aligned (SYNC access to FIFO) since with ASYNC access the TX/RX offset
registers will corrupt eventually.
The MUSB_G_NO_SKB_RESERVE will set the quirk_avoids_skb_reserve flag in
usb_gadget struct to provide correctly aligned buffer.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/musb_core.c | 3 +++
 drivers/usb/musb/musb_core.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 870da18f5077..87cbd56cc761 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2224,6 +2224,9 @@ musb_init_controller(struct device *dev, int nIrq, void 
__iomem *ctrl)
musb->io.ep_select = musb_flat_ep_select;
}
 
+   if (musb->io.quirks & MUSB_G_NO_SKB_RESERVE)
+   musb->g.quirk_avoids_skb_reserve = 1;
+
/* At least tusb6010 has its own offsets */
if (musb->ops->ep_offset)
musb->io.ep_offset = musb->ops->ep_offset;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 3e98d4268a64..9f22c5b8ce37 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -172,6 +172,7 @@ struct musb_io;
  */
 struct musb_platform_ops {
 
+#define MUSB_G_NO_SKB_RESERVE  BIT(9)
 #define MUSB_DA8XX BIT(8)
 #define MUSB_PRESERVE_SESSION  BIT(7)
 #define MUSB_DMA_UX500 BIT(6)
-- 
2.13.0

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


[PATCH v3 7/9] usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well

2017-05-12 Thread Peter Ujfalusi
Handle the DMA TX in a similar way as we do for the RX: in the DMA
completion callback.

Since we are no longer using DMA completion interrupt for the TX we can as
wall keep these interrupts disabled, but keep the handler for debug
purposes.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010.c  | 18 +++---
 drivers/usb/musb/tusb6010_omap.c | 34 +-
 2 files changed, 4 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 4253bfb22043..4eb640c54f2c 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -881,26 +881,14 @@ static irqreturn_t tusb_musb_interrupt(int irq, void 
*__hci)
| TUSB_INT_SRC_ID_STATUS_CHNG))
idle_timeout = tusb_otg_ints(musb, int_src, tbase);
 
-   /* TX dma callback must be handled here, RX dma callback is
-* handled in tusb_omap_dma_cb.
+   /*
+* Just clear the DMA interrupt if it comes as the completion for both
+* TX and RX is handled by the DMA callback in tusb6010_omap
 */
if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE)) {
u32 dma_src = musb_readl(tbase, TUSB_DMA_INT_SRC);
-   u32 real_dma_src = musb_readl(tbase, TUSB_DMA_INT_MASK);
 
dev_dbg(musb->controller, "DMA IRQ %08x\n", dma_src);
-   real_dma_src = ~real_dma_src & dma_src;
-   if (tusb_dma_omap(musb) && real_dma_src) {
-   int tx_source = (real_dma_src & 0x);
-   int i;
-
-   for (i = 1; i <= 15; i++) {
-   if (tx_source & (1 << i)) {
-   dev_dbg(musb->controller, "completing 
ep%i %s\n", i, "tx");
-   musb_dma_completion(musb, i, 1);
-   }
-   }
-   }
musb_writel(tbase, TUSB_DMA_INT_CLEAR, dma_src);
}
 
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index f8671110168b..1c4592d753bf 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -173,13 +173,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
channel->status = MUSB_DMA_STATUS_FREE;
 
-   /* Handle only RX callbacks here. TX callbacks must be handled based
-* on the TUSB DMA status interrupt.
-* REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
-* interrupt for RX and TX.
-*/
-   if (!chdat->tx)
-   musb_dma_completion(musb, chdat->epnum, chdat->tx);
+   musb_dma_completion(musb, chdat->epnum, chdat->tx);
 
/* We must terminate short tx transfers manually by setting TXPKTRDY.
 * REVISIT: This same problem may occur with other MUSB dma as well.
@@ -464,22 +458,12 @@ tusb_omap_dma_allocate(struct dma_controller *c,
int ret, i;
struct tusb_omap_dma*tusb_dma;
struct musb *musb;
-   void __iomem*tbase;
struct dma_channel  *channel = NULL;
struct tusb_omap_dma_ch *chdat = NULL;
struct tusb_dma_data*dma_data = NULL;
-   u32 reg;
 
tusb_dma = container_of(c, struct tusb_omap_dma, controller);
musb = tusb_dma->controller.musb;
-   tbase = musb->ctrl_base;
-
-   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
-   if (tx)
-   reg &= ~(1 << hw_ep->epnum);
-   else
-   reg &= ~(1 << (hw_ep->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
 
/* REVISIT: Why does dmareq5 not work? */
if (hw_ep->epnum == 0) {
@@ -548,26 +532,10 @@ static void tusb_omap_dma_release(struct dma_channel 
*channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
struct musb *musb = chdat->musb;
-   void __iomem*tbase = musb->ctrl_base;
-   u32 reg;
 
dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
chdat->dma_data->ch);
 
-   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
-   if (chdat->tx)
-   reg |= (1 << chdat->epnum);
-   else
-   reg |= (1 << (chdat->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
-
-   reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
-   if (chdat->tx)
-   reg |= (1 << chdat->epnum);
-   else
-   reg |= (1 << (chdat->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
-
channel->status = MUSB_DMA_STATUS_UNKNOWN;
 
omap_st

[PATCH v3 9/9] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-12 Thread Peter Ujfalusi
With the port_window support in DMAengine and the sDMA driver we can
convert the driver to DMAengine.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 201 ---
 1 file changed, 80 insertions(+), 121 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 1c4592d753bf..e8060e49b0f4 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include "musb_core.h"
 #include "tusb6010.h"
@@ -24,17 +24,9 @@
 
 #define MAX_DMAREQ 5   /* REVISIT: Really 6, but req5 not OK */
 
-#define OMAP24XX_DMA_EXT_DMAREQ0   2
-#define OMAP24XX_DMA_EXT_DMAREQ1   3
-#define OMAP242X_DMA_EXT_DMAREQ2   14
-#define OMAP242X_DMA_EXT_DMAREQ3   15
-#define OMAP242X_DMA_EXT_DMAREQ4   16
-#define OMAP242X_DMA_EXT_DMAREQ5   64
-
 struct tusb_dma_data {
-   int ch;
s8  dmareq;
-   s8  sync_dev;
+   struct dma_chan *chan;
 };
 
 struct tusb_omap_dma_ch {
@@ -105,7 +97,7 @@ static inline void tusb_omap_free_shared_dmareq(struct 
tusb_omap_dma_ch *chdat)
  * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
  * musb_gadget.c.
  */
-static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
+static void tusb_omap_dma_cb(void *data)
 {
struct dma_channel  *channel = (struct dma_channel *)data;
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
@@ -116,18 +108,11 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
void __iomem*ep_conf = hw_ep->conf;
void __iomem*mbase = musb->mregs;
unsigned long   remaining, flags, pio;
-   int ch;
 
spin_lock_irqsave(&musb->lock, flags);
 
-   ch = chdat->dma_data->ch;
-
-   if (ch_status != OMAP_DMA_BLOCK_IRQ)
-   printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
-
-   dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
-   chdat->epnum, chdat->tx ? "tx" : "rx",
-   ch, ch_status);
+   dev_dbg(musb->controller, "ep%i %s dma callback\n",
+   chdat->epnum, chdat->tx ? "tx" : "rx");
 
if (chdat->tx)
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
@@ -138,8 +123,8 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
-   dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", ch, remaining);
+   dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
+   chdat->tx ? "tx" : "rx", remaining);
remaining = 0;
}
 
@@ -206,13 +191,16 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
struct musb_hw_ep   *hw_ep = chdat->hw_ep;
void __iomem*mbase = musb->mregs;
void __iomem*ep_conf = hw_ep->conf;
-   dma_addr_t  fifo = hw_ep->fifo_sync;
-   struct omap_dma_channel_params  dma_params;
+   dma_addr_t  fifo_addr = hw_ep->fifo_sync;
u32 dma_remaining;
-   int src_burst, dst_burst;
u16 csr;
u32 psize;
struct tusb_dma_data*dma_data;
+   struct dma_async_tx_descriptor  *dma_desc;
+   struct dma_slave_config dma_cfg;
+   enum dma_transfer_direction dma_dir;
+   u32 port_window;
+   int ret;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -238,10 +226,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
-   dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx",
-   chdat->dma_data ? chdat->dma_data->ch : -1,
-   dma_remaining);
+   dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
+   chdat->tx ? "

[PATCH v3 0/9] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-12 Thread Peter Ujfalusi
Hi,

Changes since v2:
- patch 5 from the v1 has been sent separately
 (usb: musb: tusb6010_omap: Do not reset the other direction's packet size)
- Added Tested-by from Tony.

Changes since v1:
- Fix the port_window support in omap-dma DMAengine driver
- MUSB_G_NO_SKB_RESERVE quirk flag addition to msub core
- packet size corruption fix for tusb6010
- Handle DMA completion for TX also in the DMA callback

The v1 series was tested with g_cdc where only the DMA was only enabled for TX
and because of that I have not noticed that the sDMA code was not correct for 
RX,
it only worked for TX case.

The ASYNC mode of tusb6010 is really unstable, we get corrupted TX/RX offset
register quite easily, but the SYNC mode is stable.

The series was tested on top of next-20170510 with g_ncm module since with this
we can use the quirk to avoid skb_reserve and get properly aligned buffers for
DMA.
The n810 is using nfsroot.

The device would not boot to prompt most of the time before patch 5 (packet size
reset fix).
With that patch in, the device would boot up fine most of the cases, but will
fail pretty fast with my stress test [1].
After the first 9 patch the legacy DMA mode is going to be stable with g_ncm, it
boots to prompt, and survives the stress test [1].

The last patch is going the DMAengine conversion and I have run the stress test
against it over 3 hours (ping-test.sh wrap count is 139).

[1] Running these in parallel:
ping -f 192.168.0.2
ping -f -s 2048 192.168.0.2
ping-test.sh 192.168.0.2 1

and (nfsroot) time to time:
scp root@192.168.0.1:/usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz /

$ ls -alh /usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz 
218M Apr 30 15:46 /usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz

In essence copy 218M from my host back to the host.

ping-test.sh (modified version from Tony to show the wrap count):
#!/bin/bash

device=$1
size=$2
wraps=0

while [ 1 ]; do
#echo "Pinging with size $size"
if ! ping -w0 -c1 -s$size $device > /dev/null 2>&1; then
break;
fi
size=$(expr $size + 1)

if [ $size -gt 8192 ]; then
wraps=$(expr $wraps + 1)
echo "wrapping ($wraps) at $size"
size=1
fi
done
echo "Test ran up to $size"

Regards,
Peter

CC: dmaeng...@vger.kernel.org
I only send the cover letter and the DMAengine patch for the dmaengine list, the
rest can be checked - if there is interest - via lkml
---
Peter Ujfalusi (9):
  dmaengine: omap-dma: port_window support correction for both direction
  usb: musb: Add quirk to avoid skb reserve in gadget mode
  usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks
  usb: musb: tusb6010_omap: Use one musb_ep_select call in
tusb_omap_dma_program
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request
lines
  usb: musb: tusb6010_omap: Convert to DMAengine API

 arch/arm/mach-omap2/dma.c|  24 +++
 drivers/dma/omap-dma.c   |  39 ++--
 drivers/usb/musb/musb_core.c |   3 +
 drivers/usb/musb/musb_core.h |   1 +
 drivers/usb/musb/tusb6010.c  |  21 +--
 drivers/usb/musb/tusb6010_omap.c | 379 ---
 6 files changed, 203 insertions(+), 264 deletions(-)

-- 
2.13.0

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


[PATCH v3 6/9] usb: musb: tusb6010_omap: Allocate DMA channels upfront

2017-05-12 Thread Peter Ujfalusi
Instead of requesting the DMA channel in tusb_omap_dma_allocate() do it
when the controller is created and in runtime work from the DMA channel
pool.

This change is needed for the DMAengine conversion of the driver since the
tusb_omap_dma_allocate() is called in interrupt context which might lead
to lock within the DMAengine API when requesting channel.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 184 +++
 1 file changed, 92 insertions(+), 92 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 938ded0c407b..f8671110168b 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -45,7 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_data*dma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -62,7 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_datadma_pool[MAX_DMAREQ];
unsignedmultichannel:1;
 };
 
@@ -120,10 +120,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
spin_lock_irqsave(&musb->lock, flags);
 
-   if (tusb_dma->multichannel)
-   ch = chdat->dma_data.ch;
-   else
-   ch = tusb_dma->dma_data.ch;
+   ch = chdat->dma_data->ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -248,7 +245,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
+   chdat->tx ? "tx" : "rx",
+   chdat->dma_data ? chdat->dma_data->ch : -1,
dma_remaining);
return false;
}
@@ -260,11 +258,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
else
chdat->transfer_packet_sz = packet_sz;
 
-   if (tusb_dma->multichannel) {
-   dma_data = &chdat->dma_data;
-   } else {
-   dma_data = &tusb_dma->dma_data;
-
+   dma_data = chdat->dma_data;
+   if (!tusb_dma->multichannel) {
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
@@ -276,10 +271,10 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
WARN_ON(1);
return false;
}
-
-   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
}
 
+   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
+
chdat->packet_sz = packet_sz;
chdat->len = len;
channel->actual_len = 0;
@@ -410,19 +405,9 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 static int tusb_omap_dma_abort(struct dma_channel *channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
-   struct tusb_omap_dma*tusb_dma = chdat->tusb_dma;
-   struct tusb_dma_data*dma_data = &tusb_dma->dma_data;
 
-   if (!tusb_dma->multichannel) {
-   if (dma_data->ch >= 0) {
-   omap_stop_dma(dma_data->ch);
-   omap_free_dma(dma_data->ch);
-   dma_data->ch = -1;
-   }
-
-   dma_data->dmareq = -1;
-   dma_data->sync_dev = -1;
-   }
+   if (chdat->dma_data)
+   omap_stop_dma(chdat->dma_data->ch);
 
channel->status = MUSB_DMA_STATUS_FREE;
 
@@ -434,15 +419,6 @@ static inline int tusb_omap_dma_allocate_dmareq(struct 
tusb_omap_dma_ch *chdat)
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
int i, dmareq_nr = -1;
 
-   const int sync_dev[6] = {
-   OMAP24XX_DMA_EXT_DMAREQ0,
-   OMAP24XX_DMA_EXT_DMAREQ1,
-   OMAP242X_DMA_EXT_DMAREQ2,
-   OMAP242X_DMA_EXT_DMAREQ3,
-   OMAP242X_DMA_EXT_DMAREQ4,
-   OMAP242X_DMA_EXT_DMAREQ5,
-   };
-
for (i = 0; i < MAX_DMAREQ; i++) {
int cur = (reg & (0xf << (i * 5))) &g

[PATCH v3 4/9] usb: musb: tusb6010_omap: Use one musb_ep_select call in tusb_omap_dma_program

2017-05-12 Thread Peter Ujfalusi
Having one musb_ep_select() instead the two calls in if/else is the same
thing, but makes the code a bit simpler to follow.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7870b37e0ea5..025b52e0b34d 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -368,15 +368,14 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
/*
 * Prepare MUSB for DMA transfer
 */
+   musb_ep_select(mbase, chdat->epnum);
if (chdat->tx) {
-   musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
csr &= ~MUSB_TXCSR_P_UNDERRUN;
musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
} else {
-   musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
csr |= MUSB_RXCSR_DMAENAB;
csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
-- 
2.13.0

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


[PATCH v3 3/9] usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks

2017-05-12 Thread Peter Ujfalusi
When using the g_ncm for networking this flag will make sure that the
buffer is alligned to 32bit so the DMA can be used to offload the data
movement.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index e85cc8e4e7a9..4253bfb22043 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1181,7 +1181,8 @@ static int tusb_musb_exit(struct musb *musb)
 }
 
 static const struct musb_platform_ops tusb_ops = {
-   .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB,
+   .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB |
+ MUSB_G_NO_SKB_RESERVE,
.init   = tusb_musb_init,
.exit   = tusb_musb_exit,
 
-- 
2.13.0

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


[PATCH v4 1/9] dmaengine: omap-dma: port_window support correction for both direction

2017-05-18 Thread Peter Ujfalusi
When the port_window support was verified it was done on setup where only
the MEM_TO_DEV direction was enabled. This got un-noticed and thus only
this direction worked.

Now that I have managed to get a setup to verify both direction it turned
out that the setup was incorrect:
omap_desc members are settings for the slave port while the omap_sg members
apply to the memory side of the sDMA setup.

Fixes: 527a27591312 ("dmaengine: omap-dma: Fix the port_window support")
Signed-off-by: Peter Ujfalusi 
Cc: Russell King 
Cc: dmaeng...@vger.kernel.org
Cc: dan.j.willi...@intel.com
Cc: vinod.k...@intel.com
Tested-by: Tony Lindgren 
Acked-by: Vinod Koul 
---
 drivers/dma/omap-dma.c | 39 +++
 1 file changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index daf479cce691..8c1665c8fe33 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -916,12 +916,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
return NULL;
}
 
-   /* When the port_window is used, one frame must cover the window */
-   if (port_window) {
-   burst = port_window;
-   port_window_bytes = port_window * es_bytes[es];
-   }
-
/* Now allocate and setup the descriptor. */
d = kzalloc(sizeof(*d) + sglen * sizeof(d->sg[0]), GFP_ATOMIC);
if (!d)
@@ -931,6 +925,21 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
d->dev_addr = dev_addr;
d->es = es;
 
+   /* When the port_window is used, one frame must cover the window */
+   if (port_window) {
+   burst = port_window;
+   port_window_bytes = port_window * es_bytes[es];
+
+   d->ei = 1;
+   /*
+* One frame covers the port_window and by  configure
+* the source frame index to be -1 * (port_window - 1)
+* we instruct the sDMA that after a frame is processed
+* it should move back to the start of the window.
+*/
+   d->fi = -(port_window_bytes - 1);
+   }
+
d->ccr = c->ccr | CCR_SYNC_FRAME;
if (dir == DMA_DEV_TO_MEM) {
d->csdp = CSDP_DST_BURST_64 | CSDP_DST_PACKED;
@@ -955,14 +964,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
d->ccr |= CCR_SRC_AMODE_POSTINC;
if (port_window) {
d->ccr |= CCR_DST_AMODE_DBLIDX;
-   d->ei = 1;
-   /*
-* One frame covers the port_window and by  configure
-* the source frame index to be -1 * (port_window - 1)
-* we instruct the sDMA that after a frame is processed
-* it should move back to the start of the window.
-*/
-   d->fi = -(port_window_bytes - 1);
 
if (port_window_bytes >= 64)
d->csdp |= CSDP_DST_BURST_64;
@@ -1018,16 +1019,6 @@ static struct dma_async_tx_descriptor 
*omap_dma_prep_slave_sg(
osg->addr = sg_dma_address(sgent);
osg->en = en;
osg->fn = sg_dma_len(sgent) / frame_bytes;
-   if (port_window && dir == DMA_DEV_TO_MEM) {
-   osg->ei = 1;
-   /*
-* One frame covers the port_window and by  configure
-* the source frame index to be -1 * (port_window - 1)
-* we instruct the sDMA that after a frame is processed
-* it should move back to the start of the window.
-*/
-   osg->fi = -(port_window_bytes - 1);
-   }
 
if (d->using_ll) {
osg->t2_desc = dma_pool_alloc(od->desc_pool, GFP_ATOMIC,
-- 
2.13.0

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


[PATCH v4 9/9] usb: musb: tusb6010_omap: Convert to DMAengine API

2017-05-18 Thread Peter Ujfalusi
With the port_window support in DMAengine and the sDMA driver we can
convert the driver to DMAengine.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 201 ---
 1 file changed, 80 insertions(+), 121 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 1c4592d753bf..e8060e49b0f4 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -15,7 +15,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include "musb_core.h"
 #include "tusb6010.h"
@@ -24,17 +24,9 @@
 
 #define MAX_DMAREQ 5   /* REVISIT: Really 6, but req5 not OK */
 
-#define OMAP24XX_DMA_EXT_DMAREQ0   2
-#define OMAP24XX_DMA_EXT_DMAREQ1   3
-#define OMAP242X_DMA_EXT_DMAREQ2   14
-#define OMAP242X_DMA_EXT_DMAREQ3   15
-#define OMAP242X_DMA_EXT_DMAREQ4   16
-#define OMAP242X_DMA_EXT_DMAREQ5   64
-
 struct tusb_dma_data {
-   int ch;
s8  dmareq;
-   s8  sync_dev;
+   struct dma_chan *chan;
 };
 
 struct tusb_omap_dma_ch {
@@ -105,7 +97,7 @@ static inline void tusb_omap_free_shared_dmareq(struct 
tusb_omap_dma_ch *chdat)
  * See also musb_dma_completion in plat_uds.c and musb_g_[tx|rx]() in
  * musb_gadget.c.
  */
-static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
+static void tusb_omap_dma_cb(void *data)
 {
struct dma_channel  *channel = (struct dma_channel *)data;
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
@@ -116,18 +108,11 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
void __iomem*ep_conf = hw_ep->conf;
void __iomem*mbase = musb->mregs;
unsigned long   remaining, flags, pio;
-   int ch;
 
spin_lock_irqsave(&musb->lock, flags);
 
-   ch = chdat->dma_data->ch;
-
-   if (ch_status != OMAP_DMA_BLOCK_IRQ)
-   printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
-
-   dev_dbg(musb->controller, "ep%i %s dma callback ch: %i status: %x\n",
-   chdat->epnum, chdat->tx ? "tx" : "rx",
-   ch, ch_status);
+   dev_dbg(musb->controller, "ep%i %s dma callback\n",
+   chdat->epnum, chdat->tx ? "tx" : "rx");
 
if (chdat->tx)
remaining = musb_readl(ep_conf, TUSB_EP_TX_OFFSET);
@@ -138,8 +123,8 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
-   dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", ch, remaining);
+   dev_dbg(musb->controller, "Corrupt %s XFR_SIZE: 0x%08lx\n",
+   chdat->tx ? "tx" : "rx", remaining);
remaining = 0;
}
 
@@ -206,13 +191,16 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
struct musb_hw_ep   *hw_ep = chdat->hw_ep;
void __iomem*mbase = musb->mregs;
void __iomem*ep_conf = hw_ep->conf;
-   dma_addr_t  fifo = hw_ep->fifo_sync;
-   struct omap_dma_channel_params  dma_params;
+   dma_addr_t  fifo_addr = hw_ep->fifo_sync;
u32 dma_remaining;
-   int src_burst, dst_burst;
u16 csr;
u32 psize;
struct tusb_dma_data*dma_data;
+   struct dma_async_tx_descriptor  *dma_desc;
+   struct dma_slave_config dma_cfg;
+   enum dma_transfer_direction dma_dir;
+   u32 port_window;
+   int ret;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -238,10 +226,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
-   dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx",
-   chdat->dma_data ? chdat->dma_data->ch : -1,
-   dma_remaining);
+   dev_dbg(musb->controller, "Busy %s dma, not using: %08x\n",
+   chdat->tx ? "

[PATCH v4 0/9] usb: musb: tusb6010_omap: Convert to DMAengine

2017-05-18 Thread Peter Ujfalusi
Hi,

Changes since v3:
- typos in commit message of patch 3 and 5 fixed
- long line fixed in patch 5
- Ack from Vinod is added to the first patch
- The series depends on: http://marc.info/?l=linux-omap&m=149459699415599&w=2

Changes since v2:
- patch 5 from the v1 has been sent separately
 (usb: musb: tusb6010_omap: Do not reset the other direction's packet size)
- Added Tested-by from Tony.

Changes since v1:
- Fix the port_window support in omap-dma DMAengine driver
- MUSB_G_NO_SKB_RESERVE quirk flag addition to msub core
- packet size corruption fix for tusb6010
- Handle DMA completion for TX also in the DMA callback

The v1 series was tested with g_cdc where only the DMA was only enabled for TX
and because of that I have not noticed that the sDMA code was not correct for 
RX,
it only worked for TX case.

The ASYNC mode of tusb6010 is really unstable, we get corrupted TX/RX offset
register quite easily, but the SYNC mode is stable.

The series was tested on top of next-20170510 with g_ncm module since with this
we can use the quirk to avoid skb_reserve and get properly aligned buffers for
DMA.
The n810 is using nfsroot.

The device would not boot to prompt most of the time before patch 5 (packet size
reset fix).
With that patch in, the device would boot up fine most of the cases, but will
fail pretty fast with my stress test [1].
After the first 9 patch the legacy DMA mode is going to be stable with g_ncm, it
boots to prompt, and survives the stress test [1].

The last patch is going the DMAengine conversion and I have run the stress test
against it over 3 hours (ping-test.sh wrap count is 139).

[1] Running these in parallel:
ping -f 192.168.0.2
ping -f -s 2048 192.168.0.2
ping-test.sh 192.168.0.2 1

and (nfsroot) time to time:
scp root@192.168.0.1:/usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz /

$ ls -alh /usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz 
218M Apr 30 15:46 /usr/portage/distfiles/thunderbird-52.1.0.source.tar.xz

In essence copy 218M from my host back to the host.

ping-test.sh (modified version from Tony to show the wrap count):
#!/bin/bash

device=$1
size=$2
wraps=0

while [ 1 ]; do
#echo "Pinging with size $size"
if ! ping -w0 -c1 -s$size $device > /dev/null 2>&1; then
break;
fi
size=$(expr $size + 1)

if [ $size -gt 8192 ]; then
wraps=$(expr $wraps + 1)
echo "wrapping ($wraps) at $size"
size=1
fi
done
echo "Test ran up to $size"

Regards,
Peter

CC: dmaeng...@vger.kernel.org
I only send the cover letter and the DMAengine patch for the dmaengine list, the
rest can be checked - if there is interest - via lkml
---
Peter Ujfalusi (9):
  dmaengine: omap-dma: port_window support correction for both direction
  usb: musb: Add quirk to avoid skb reserve in gadget mode
  usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks
  usb: musb: tusb6010_omap: Use one musb_ep_select call in
tusb_omap_dma_program
  usb: musb: tusb6010_omap: Create new struct for DMA data/parameters
  usb: musb: tusb6010_omap: Allocate DMA channels upfront
  usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well
  ARM: OMAP2+: DMA: Add slave map entries for 24xx external request
lines
  usb: musb: tusb6010_omap: Convert to DMAengine API

 arch/arm/mach-omap2/dma.c|  24 +++
 drivers/dma/omap-dma.c   |  39 ++--
 drivers/usb/musb/musb_core.c |   3 +
 drivers/usb/musb/musb_core.h |   1 +
 drivers/usb/musb/tusb6010.c  |  21 +--
 drivers/usb/musb/tusb6010_omap.c | 379 ---
 6 files changed, 203 insertions(+), 264 deletions(-)

-- 
2.13.0

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


[PATCH v4 7/9] usb: musb: tusb6010: Handle DMA TX completion in DMA callback as well

2017-05-18 Thread Peter Ujfalusi
Handle the DMA TX in a similar way as we do for the RX: in the DMA
completion callback.

Since we are no longer using DMA completion interrupt for the TX we can as
wall keep these interrupts disabled, but keep the handler for debug
purposes.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010.c  | 18 +++---
 drivers/usb/musb/tusb6010_omap.c | 34 +-
 2 files changed, 4 insertions(+), 48 deletions(-)

diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 4253bfb22043..4eb640c54f2c 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -881,26 +881,14 @@ static irqreturn_t tusb_musb_interrupt(int irq, void 
*__hci)
| TUSB_INT_SRC_ID_STATUS_CHNG))
idle_timeout = tusb_otg_ints(musb, int_src, tbase);
 
-   /* TX dma callback must be handled here, RX dma callback is
-* handled in tusb_omap_dma_cb.
+   /*
+* Just clear the DMA interrupt if it comes as the completion for both
+* TX and RX is handled by the DMA callback in tusb6010_omap
 */
if ((int_src & TUSB_INT_SRC_TXRX_DMA_DONE)) {
u32 dma_src = musb_readl(tbase, TUSB_DMA_INT_SRC);
-   u32 real_dma_src = musb_readl(tbase, TUSB_DMA_INT_MASK);
 
dev_dbg(musb->controller, "DMA IRQ %08x\n", dma_src);
-   real_dma_src = ~real_dma_src & dma_src;
-   if (tusb_dma_omap(musb) && real_dma_src) {
-   int tx_source = (real_dma_src & 0x);
-   int i;
-
-   for (i = 1; i <= 15; i++) {
-   if (tx_source & (1 << i)) {
-   dev_dbg(musb->controller, "completing 
ep%i %s\n", i, "tx");
-   musb_dma_completion(musb, i, 1);
-   }
-   }
-   }
musb_writel(tbase, TUSB_DMA_INT_CLEAR, dma_src);
}
 
diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index f8671110168b..1c4592d753bf 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -173,13 +173,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
channel->status = MUSB_DMA_STATUS_FREE;
 
-   /* Handle only RX callbacks here. TX callbacks must be handled based
-* on the TUSB DMA status interrupt.
-* REVISIT: Use both TUSB DMA status interrupt and OMAP DMA callback
-* interrupt for RX and TX.
-*/
-   if (!chdat->tx)
-   musb_dma_completion(musb, chdat->epnum, chdat->tx);
+   musb_dma_completion(musb, chdat->epnum, chdat->tx);
 
/* We must terminate short tx transfers manually by setting TXPKTRDY.
 * REVISIT: This same problem may occur with other MUSB dma as well.
@@ -464,22 +458,12 @@ tusb_omap_dma_allocate(struct dma_controller *c,
int ret, i;
struct tusb_omap_dma*tusb_dma;
struct musb *musb;
-   void __iomem*tbase;
struct dma_channel  *channel = NULL;
struct tusb_omap_dma_ch *chdat = NULL;
struct tusb_dma_data*dma_data = NULL;
-   u32 reg;
 
tusb_dma = container_of(c, struct tusb_omap_dma, controller);
musb = tusb_dma->controller.musb;
-   tbase = musb->ctrl_base;
-
-   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
-   if (tx)
-   reg &= ~(1 << hw_ep->epnum);
-   else
-   reg &= ~(1 << (hw_ep->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
 
/* REVISIT: Why does dmareq5 not work? */
if (hw_ep->epnum == 0) {
@@ -548,26 +532,10 @@ static void tusb_omap_dma_release(struct dma_channel 
*channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
struct musb *musb = chdat->musb;
-   void __iomem*tbase = musb->ctrl_base;
-   u32 reg;
 
dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
chdat->dma_data->ch);
 
-   reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
-   if (chdat->tx)
-   reg |= (1 << chdat->epnum);
-   else
-   reg |= (1 << (chdat->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_MASK, reg);
-
-   reg = musb_readl(tbase, TUSB_DMA_INT_CLEAR);
-   if (chdat->tx)
-   reg |= (1 << chdat->epnum);
-   else
-   reg |= (1 << (chdat->epnum + 15));
-   musb_writel(tbase, TUSB_DMA_INT_CLEAR, reg);
-
channel->status = MUSB_DMA_STATUS_UNKNOWN;
 
omap_st

[PATCH v4 8/9] ARM: OMAP2+: DMA: Add slave map entries for 24xx external request lines

2017-05-18 Thread Peter Ujfalusi
The external request lines are used by tusb6010 on OMAP24xx platforms.
Update the map so the driver can use dmaengine API to request the DMA
channel. At the same time add temporary map containing only the external
DMA request numbers for DT booted case on omap24xx since the tusb6010 stack
is not yet supports DT boot.

Signed-off-by: Peter Ujfalusi 
Acked-by: Tony Lindgren 
---
 arch/arm/mach-omap2/dma.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index e58c13a9bea5..0b77a0176018 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -249,6 +249,24 @@ static const struct dma_slave_map omap24xx_sdma_map[] = {
{ "omap_uart.2", "rx", SDMA_FILTER_PARAM(54) },
{ "omap_hsmmc.0", "tx", SDMA_FILTER_PARAM(61) },
{ "omap_hsmmc.0", "rx", SDMA_FILTER_PARAM(62) },
+
+   /* external DMA requests when tusb6010 is used */
+   { "musb-tusb", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-tusb", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-tusb", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 only */
+   { "musb-tusb", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 only */
+};
+
+static const struct dma_slave_map omap24xx_sdma_dt_map[] = {
+   /* external DMA requests when tusb6010 is used */
+   { "musb-hdrc.1.auto", "dmareq0", SDMA_FILTER_PARAM(2) },
+   { "musb-hdrc.1.auto", "dmareq1", SDMA_FILTER_PARAM(3) },
+   { "musb-hdrc.1.auto", "dmareq2", SDMA_FILTER_PARAM(14) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq3", SDMA_FILTER_PARAM(15) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq4", SDMA_FILTER_PARAM(16) }, /* OMAP2420 
only */
+   { "musb-hdrc.1.auto", "dmareq5", SDMA_FILTER_PARAM(64) }, /* OMAP2420 
only */
 };
 
 static const struct dma_slave_map omap3xxx_sdma_map[] = {
@@ -346,6 +364,12 @@ static int __init omap2_system_dma_init_dev(struct 
omap_hwmod *oh, void *unused)
   __func__);
return -ENODEV;
}
+   } else {
+   if (soc_is_omap24xx()) {
+   /* DMA slave map for drivers not yet converted to DT */
+   p.slave_map = omap24xx_sdma_dt_map;
+   p.slavecnt = ARRAY_SIZE(omap24xx_sdma_dt_map);
+   }
}
 
pdev = omap_device_build(name, 0, oh, &p, sizeof(p));
-- 
2.13.0

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


[PATCH v4 6/9] usb: musb: tusb6010_omap: Allocate DMA channels upfront

2017-05-18 Thread Peter Ujfalusi
Instead of requesting the DMA channel in tusb_omap_dma_allocate() do it
when the controller is created and in runtime work from the DMA channel
pool.

This change is needed for the DMAengine conversion of the driver since the
tusb_omap_dma_allocate() is called in interrupt context which might lead
to lock within the DMAengine API when requesting channel.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 185 +++
 1 file changed, 92 insertions(+), 93 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index c2ef8e3eb91e..f8671110168b 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -45,7 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_data*dma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -62,7 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   struct tusb_dma_datadma_data;
+   struct tusb_dma_datadma_pool[MAX_DMAREQ];
unsignedmultichannel:1;
 };
 
@@ -120,10 +120,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
 
spin_lock_irqsave(&musb->lock, flags);
 
-   if (tusb_dma->multichannel)
-   ch = chdat->dma_data.ch;
-   else
-   ch = tusb_dma->dma_data.ch;
+   ch = chdat->dma_data->ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -248,7 +245,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
+   chdat->tx ? "tx" : "rx",
+   chdat->dma_data ? chdat->dma_data->ch : -1,
dma_remaining);
return false;
}
@@ -260,11 +258,8 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
else
chdat->transfer_packet_sz = packet_sz;
 
-   if (tusb_dma->multichannel) {
-   dma_data = &chdat->dma_data;
-   } else {
-   dma_data = &tusb_dma->dma_data;
-
+   dma_data = chdat->dma_data;
+   if (!tusb_dma->multichannel) {
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
@@ -276,10 +271,10 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
WARN_ON(1);
return false;
}
-
-   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
}
 
+   omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
+
chdat->packet_sz = packet_sz;
chdat->len = len;
channel->actual_len = 0;
@@ -410,19 +405,9 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
 static int tusb_omap_dma_abort(struct dma_channel *channel)
 {
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
-   struct tusb_omap_dma*tusb_dma = chdat->tusb_dma;
-   struct tusb_dma_data*dma_data = &tusb_dma->dma_data;
 
-   if (!tusb_dma->multichannel) {
-   if (dma_data->ch >= 0) {
-   omap_stop_dma(dma_data->ch);
-   omap_free_dma(dma_data->ch);
-   dma_data->ch = -1;
-   }
-
-   dma_data->dmareq = -1;
-   dma_data->sync_dev = -1;
-   }
+   if (chdat->dma_data)
+   omap_stop_dma(chdat->dma_data->ch);
 
channel->status = MUSB_DMA_STATUS_FREE;
 
@@ -434,15 +419,6 @@ static inline int tusb_omap_dma_allocate_dmareq(struct 
tusb_omap_dma_ch *chdat)
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
int i, dmareq_nr = -1;
 
-   const int sync_dev[6] = {
-   OMAP24XX_DMA_EXT_DMAREQ0,
-   OMAP24XX_DMA_EXT_DMAREQ1,
-   OMAP242X_DMA_EXT_DMAREQ2,
-   OMAP242X_DMA_EXT_DMAREQ3,
-   OMAP242X_DMA_EXT_DMAREQ4,
-   OMAP242X_DMA_EXT_DMAREQ5,
-   };
-
for (i = 0; i < MAX_DMAREQ; i++) {
int cur = (reg & (0xf << (i * 5))) &g

[PATCH v4 5/9] usb: musb: tusb6010_omap: Create new struct for DMA data/parameters

2017-05-18 Thread Peter Ujfalusi
For the DMA we have ch (channel), dmareq and sync_dev parameters both
within the tusb_omap_dma_ch and tusb_omap_dma struct.
By creating a common struct the code can be simplified when selecting
between the shared or multichannel DMA parameters.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 164 ---
 1 file changed, 85 insertions(+), 79 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 025b52e0b34d..c2ef8e3eb91e 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -31,6 +31,12 @@
 #define OMAP242X_DMA_EXT_DMAREQ4   16
 #define OMAP242X_DMA_EXT_DMAREQ5   64
 
+struct tusb_dma_data {
+   int ch;
+   s8  dmareq;
+   s8  sync_dev;
+};
+
 struct tusb_omap_dma_ch {
struct musb *musb;
void __iomem*tbase;
@@ -39,9 +45,7 @@ struct tusb_omap_dma_ch {
u8  tx;
struct musb_hw_ep   *hw_ep;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
 
struct tusb_omap_dma*tusb_dma;
 
@@ -58,9 +62,7 @@ struct tusb_omap_dma {
struct dma_controller   controller;
void __iomem*tbase;
 
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_datadma_data;
unsignedmultichannel:1;
 };
 
@@ -119,9 +121,9 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
spin_lock_irqsave(&musb->lock, flags);
 
if (tusb_dma->multichannel)
-   ch = chdat->ch;
+   ch = chdat->dma_data.ch;
else
-   ch = tusb_dma->ch;
+   ch = tusb_dma->dma_data.ch;
 
if (ch_status != OMAP_DMA_BLOCK_IRQ)
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -140,8 +142,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void 
*data)
/* HW issue #10: XFR_SIZE may get corrupt on DMA (both async & sync) */
if (unlikely(remaining > chdat->transfer_len)) {
dev_dbg(musb->controller, "Corrupt %s dma ch%i XFR_SIZE: 
0x%08lx\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
-   remaining);
+   chdat->tx ? "tx" : "rx", ch, remaining);
remaining = 0;
}
 
@@ -220,9 +221,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
int src_burst, dst_burst;
u16 csr;
u32 psize;
-   int ch;
-   s8  dmareq;
-   s8  sync_dev;
+   struct tusb_dma_data*dma_data;
 
if (unlikely(dma_addr & 0x1) || (len < 32) || (len > packet_sz))
return false;
@@ -249,7 +248,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
if (dma_remaining) {
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
-   chdat->tx ? "tx" : "rx", chdat->ch,
+   chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
dma_remaining);
return false;
}
@@ -262,15 +261,15 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
chdat->transfer_packet_sz = packet_sz;
 
if (tusb_dma->multichannel) {
-   ch = chdat->ch;
-   dmareq = chdat->dmareq;
-   sync_dev = chdat->sync_dev;
+   dma_data = &chdat->dma_data;
} else {
+   dma_data = &tusb_dma->dma_data;
+
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
dev_dbg(musb->controller, "could not get dma for 
ep%i\n", chdat->epnum);
return false;
}
-   if (tusb_dma->ch < 0) {
+   if (dma_data->ch < 0) {
/* REVISIT: This should get blocked earlier, happens
 * with MSC ErrorRecoveryTest
 */
@@ -278,10 +277,7 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
return false;

[PATCH v4 3/9] usb: musb: tusb6010: Add MUSB_G_NO_SKB_RESERVE to quirks

2017-05-18 Thread Peter Ujfalusi
When using the g_ncm for networking this flag will make sure that the
buffer is aligned to 32bit so the DMA can be used to offload the data
movement.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index e85cc8e4e7a9..4253bfb22043 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1181,7 +1181,8 @@ static int tusb_musb_exit(struct musb *musb)
 }
 
 static const struct musb_platform_ops tusb_ops = {
-   .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB,
+   .quirks = MUSB_DMA_TUSB_OMAP | MUSB_IN_TUSB |
+ MUSB_G_NO_SKB_RESERVE,
.init   = tusb_musb_init,
.exit   = tusb_musb_exit,
 
-- 
2.13.0

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


[PATCH v4 4/9] usb: musb: tusb6010_omap: Use one musb_ep_select call in tusb_omap_dma_program

2017-05-18 Thread Peter Ujfalusi
Having one musb_ep_select() instead the two calls in if/else is the same
thing, but makes the code a bit simpler to follow.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/tusb6010_omap.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c
index 7870b37e0ea5..025b52e0b34d 100644
--- a/drivers/usb/musb/tusb6010_omap.c
+++ b/drivers/usb/musb/tusb6010_omap.c
@@ -368,15 +368,14 @@ static int tusb_omap_dma_program(struct dma_channel 
*channel, u16 packet_sz,
/*
 * Prepare MUSB for DMA transfer
 */
+   musb_ep_select(mbase, chdat->epnum);
if (chdat->tx) {
-   musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_TXCSR);
csr |= (MUSB_TXCSR_AUTOSET | MUSB_TXCSR_DMAENAB
| MUSB_TXCSR_DMAMODE | MUSB_TXCSR_MODE);
csr &= ~MUSB_TXCSR_P_UNDERRUN;
musb_writew(hw_ep->regs, MUSB_TXCSR, csr);
} else {
-   musb_ep_select(mbase, chdat->epnum);
csr = musb_readw(hw_ep->regs, MUSB_RXCSR);
csr |= MUSB_RXCSR_DMAENAB;
csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAMODE);
-- 
2.13.0

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


[PATCH v4 2/9] usb: musb: Add quirk to avoid skb reserve in gadget mode

2017-05-18 Thread Peter Ujfalusi
For tusb6010 the DMA functionality only possible if the buffer is 32bit
aligned (SYNC access to FIFO) since with ASYNC access the TX/RX offset
registers will corrupt eventually.
The MUSB_G_NO_SKB_RESERVE will set the quirk_avoids_skb_reserve flag in
usb_gadget struct to provide correctly aligned buffer.

Signed-off-by: Peter Ujfalusi 
Tested-by: Tony Lindgren 
---
 drivers/usb/musb/musb_core.c | 3 +++
 drivers/usb/musb/musb_core.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 870da18f5077..87cbd56cc761 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2224,6 +2224,9 @@ musb_init_controller(struct device *dev, int nIrq, void 
__iomem *ctrl)
musb->io.ep_select = musb_flat_ep_select;
}
 
+   if (musb->io.quirks & MUSB_G_NO_SKB_RESERVE)
+   musb->g.quirk_avoids_skb_reserve = 1;
+
/* At least tusb6010 has its own offsets */
if (musb->ops->ep_offset)
musb->io.ep_offset = musb->ops->ep_offset;
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 3e98d4268a64..9f22c5b8ce37 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -172,6 +172,7 @@ struct musb_io;
  */
 struct musb_platform_ops {
 
+#define MUSB_G_NO_SKB_RESERVE  BIT(9)
 #define MUSB_DA8XX BIT(8)
 #define MUSB_PRESERVE_SESSION  BIT(7)
 #define MUSB_DMA_UX500 BIT(6)
-- 
2.13.0

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


Re: [PATCH] dma: cppi41: delete channel from pending list when stop channel

2018-11-28 Thread Peter Ujfalusi



On 12/11/2018 17.40, Bin Liu wrote:

Can you fix up the subject line to:
dmaengine: ti: cppi4: delete channel from pending list when stop channel

> The driver defines three states for a cppi channel.
> - idle: .chan_busy == 0 && not in .pending list
> - pending: .chan_busy == 0 && in .pending list
> - busy: .chan_busy == 1 && not in .pending list
> 
> There are cases in which the cppi channel could be in the pending state
> when cppi41_dma_issue_pending() is called after cppi41_runtime_suspend()
> is called.
> 
> cppi41_stop_chan() has a bug for these cases to set channels to idle state.
> It only checks the .chan_busy flag, but not the .pending list, then later
> when cppi41_runtime_resume() is called the channels in .pending list will
> be transitioned to busy state.
> 
> Removing channels from the .pending list solves the problem.

So, let me see if I understand this correctly:
- client issued a transfer _after_ the cppi4 driver is suspended
- cppi41_dma_issue_pending() will place it to pending list and will not
start the transfer right away as cdd->is_suspended is true.
- on resume the cppi4 will pick up the pending transfers from the
pending list

This is so far a sane thing to do.

If I guess right, then after the issue_pending the client driver will
call terminate_all, presumably from it's suspend callback?

As per the purpose of terminate_all we should terminated all future
transfers on the channel, so clearing the pending list is the correct
thing to do.

With the fixed subject:
Reviewed-by: Peter Ujfalusi 

I have one question:

> Fixes: 975faaeb9985 ("dma: cppi41: start tear down only if channel is busy")
> Cc: sta...@vger.kernel.org # v3.15+
> Signed-off-by: Bin Liu 
> ---
>  drivers/dma/ti/cppi41.c | 16 +++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
> index 1497da367710..e507ec36c0d3 100644
> --- a/drivers/dma/ti/cppi41.c
> +++ b/drivers/dma/ti/cppi41.c
> @@ -723,8 +723,22 @@ static int cppi41_stop_chan(struct dma_chan *chan)
>  
>   desc_phys = lower_32_bits(c->desc_phys);
>   desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
> - if (!cdd->chan_busy[desc_num])
> + if (!cdd->chan_busy[desc_num]) {
> + struct cppi41_channel *cc, *_ct;
> +
> + /*
> +  * channels might still be in the pendling list if
> +  * cppi41_dma_issue_pending() is called after
> +  * cppi41_runtime_suspend() is called
> +  */
> + list_for_each_entry_safe(cc, _ct, &cdd->pending, node) {
> + if (cc != c)
> + continue;
> + list_del(&cc->node);

If we delete from the pending list, are we going to leak memory?
I'm not familiar with the cppi4, it might not be an issue for it.

> + break;
> + }
>   return 0;
> + }
>  
>   ret = cppi41_tear_down_chan(c);
>   if (ret)
> 

- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH] dma: cppi41: delete channel from pending list when stop channel

2018-11-28 Thread Peter Ujfalusi
Hi,

On 28/11/2018 13.15, Peter Ujfalusi wrote:

forgot to fix up Vinod's email address.

> 
> 
> On 12/11/2018 17.40, Bin Liu wrote:
> 
> Can you fix up the subject line to:
> dmaengine: ti: cppi4: delete channel from pending list when stop channel
> 
>> The driver defines three states for a cppi channel.
>> - idle: .chan_busy == 0 && not in .pending list
>> - pending: .chan_busy == 0 && in .pending list
>> - busy: .chan_busy == 1 && not in .pending list
>>
>> There are cases in which the cppi channel could be in the pending state
>> when cppi41_dma_issue_pending() is called after cppi41_runtime_suspend()
>> is called.
>>
>> cppi41_stop_chan() has a bug for these cases to set channels to idle state.
>> It only checks the .chan_busy flag, but not the .pending list, then later
>> when cppi41_runtime_resume() is called the channels in .pending list will
>> be transitioned to busy state.
>>
>> Removing channels from the .pending list solves the problem.
> 
> So, let me see if I understand this correctly:
> - client issued a transfer _after_ the cppi4 driver is suspended
> - cppi41_dma_issue_pending() will place it to pending list and will not
> start the transfer right away as cdd->is_suspended is true.
> - on resume the cppi4 will pick up the pending transfers from the
> pending list
> 
> This is so far a sane thing to do.
> 
> If I guess right, then after the issue_pending the client driver will
> call terminate_all, presumably from it's suspend callback?
> 
> As per the purpose of terminate_all we should terminated all future
> transfers on the channel, so clearing the pending list is the correct
> thing to do.
> 
> With the fixed subject:
> Reviewed-by: Peter Ujfalusi 
> 
> I have one question:
> 
>> Fixes: 975faaeb9985 ("dma: cppi41: start tear down only if channel is busy")
>> Cc: sta...@vger.kernel.org # v3.15+
>> Signed-off-by: Bin Liu 
>> ---
>>  drivers/dma/ti/cppi41.c | 16 +++-
>>  1 file changed, 15 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
>> index 1497da367710..e507ec36c0d3 100644
>> --- a/drivers/dma/ti/cppi41.c
>> +++ b/drivers/dma/ti/cppi41.c
>> @@ -723,8 +723,22 @@ static int cppi41_stop_chan(struct dma_chan *chan)
>>  
>>  desc_phys = lower_32_bits(c->desc_phys);
>>  desc_num = (desc_phys - cdd->descs_phys) / sizeof(struct cppi41_desc);
>> -if (!cdd->chan_busy[desc_num])
>> +if (!cdd->chan_busy[desc_num]) {
>> +struct cppi41_channel *cc, *_ct;
>> +
>> +/*
>> + * channels might still be in the pendling list if
>> + * cppi41_dma_issue_pending() is called after
>> + * cppi41_runtime_suspend() is called
>> + */
>> +list_for_each_entry_safe(cc, _ct, &cdd->pending, node) {
>> +if (cc != c)
>> +continue;
>> +list_del(&cc->node);
> 
> If we delete from the pending list, are we going to leak memory?
> I'm not familiar with the cppi4, it might not be an issue for it.
> 
>> +break;
>> +}
>>  return 0;
>> +}
>>  
>>  ret = cppi41_tear_down_chan(c);
>>  if (ret)
>>
> 
> - Péter
> 
> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
> Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
> 

- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH v1 1/5] drivercore: Revert "deferral race condition fix"

2018-11-12 Thread Peter Ujfalusi
Hi Andy,

On 2018-11-10 20:10, Andy Shevchenko wrote:
> Consider the following scenario.
> 
> There are two independent devices coupled together by functional dependencies:
>  - USB OTG (dwc3-pci)
>  - extcon (tested with extcon-intel-mrfld, not yet in upstream)
> 
> Each of the driver services a corresponding device is built as a module. In 
> the
> Buildroot environment the modules are probed by alphabetical ordering of their
> modaliases. The latter comes to the case when USB OTG driver will be probed
> first followed by extcon one.
> 
> So, if the platform anticipates extcon device to be appeared, in the above 
> case
> we will get deferred probe of USB OTG, because of ordering.
> 
> Now, a cherry on top of the cake, the deferred probing list contains
> the only two modules, i.e. USB OTG and extcon. Due to above circumstances,
> values in the local_trigger_count and deferred_trigger_count are not the same,
> and thus provokes deferred probe triggering again and again.
> 
> ...
> [   20.678332] platform dwc3.0.auto: Retrying from deferred list
> [   20.694743] platform dwc3.0.auto: Driver dwc3 requests probe deferral
> [   20.701254] platform dwc3.0.auto: Added to deferred list
> [   20.706620] platform dwc3.0.auto: driver_deferred_probe_add_trigger 1 2
> [   20.713732] platform dwc3.0.auto: Retrying from deferred list
> [   20.730035] platform dwc3.0.auto: Driver dwc3 requests probe deferral
> [   20.736540] platform dwc3.0.auto: Added to deferred list
> [   20.741889] platform dwc3.0.auto: driver_deferred_probe_add_trigger 3 4
> [   20.748991] platform dwc3.0.auto: Retrying from deferred list
> [   20.765416] platform dwc3.0.auto: Driver dwc3 requests probe deferral
> [   20.771914] platform dwc3.0.auto: Added to deferred list
> [   20.777279] platform dwc3.0.auto: driver_deferred_probe_add_trigger 5 6
> ...
> 
> Deeper investigation shows the culprit commit 58b116bce136
> ("drivercore: deferral race condition fix") which was dedicated to fix some
> other issue while bringing a regression.
> 
> This reverts commit 58b116bce13612e5aa6fcd49ecbd4cf8bb59e835 for good until
> we will have better solution.

if we revert the commit then the original issue will re-surfaces. afaik
it was not only audio which hit the 'last driver to be probed from the
deferred list would never probe, unless we provoke the kernel to load
additional module, or remove/reload the module' issue.

Do I understand correctly that in your case you have two modules
(dwc3-pci and extcon-intel-mrfld) in a deferred probe loop, iow both of
the drivers returns -EPROBE_DEFER and they just spin?

If both is deferring, how this supposed to work?

If we revert 58b116bce13612e5aa6fcd49ecbd4cf8bb59e835, then you might be
hitting the very same issue as described by the commit:
s/davinci_evm sound.3/dwc3-pci
s/davinci-mcasp 4803c000.mcasp/extcon-intel-mrfld

Am I missing something?

> 
> Cc: Grant Likely 
> Cc: Peter Ujfalusi 
> Cc: Greg Kroah-Hartman 
> Cc: Mark Brown 
> Cc: Felipe Balbi 
> Cc: Andrzej Hajda 
> Signed-off-by: Andy Shevchenko 
> ---
>  drivers/base/dd.c | 27 ++-
>  1 file changed, 2 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index 169412ee4ae8..9a966e45fda5 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -53,7 +53,6 @@
>  static DEFINE_MUTEX(deferred_probe_mutex);
>  static LIST_HEAD(deferred_probe_pending_list);
>  static LIST_HEAD(deferred_probe_active_list);
> -static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
>  static struct dentry *deferred_devices;
>  static bool initcalls_done;
>  
> @@ -143,17 +142,6 @@ static bool driver_deferred_probe_enable = false;
>   * This functions moves all devices from the pending list to the active
>   * list and schedules the deferred probe workqueue to process them.  It
>   * should be called anytime a driver is successfully bound to a device.
> - *
> - * Note, there is a race condition in multi-threaded probe. In the case where
> - * more than one device is probing at the same time, it is possible for one
> - * probe to complete successfully while another is about to defer. If the 
> second
> - * depends on the first, then it will get put on the pending list after the
> - * trigger event has already occurred and will be stuck there.
> - *
> - * The atomic 'deferred_trigger_count' is used to determine if a successful
> - * trigger has occurred in the midst of probing a driver. If the trigger 
> count
> - * changes in the midst of a probe, then deferred processing should be 
> triggered
> - * again.
>   */
>  static void driver_deferred_probe_trigger(void)
>  {
> @@ -

Re: [PATCH v1 1/5] drivercore: Revert "deferral race condition fix"

2018-11-14 Thread Peter Ujfalusi
Andy,

On 2018-11-14 10:45, Andy Shevchenko wrote:
> On Wed, Nov 14, 2018 at 2:34 AM Mark Brown  wrote:
>>
>> On Mon, Nov 12, 2018 at 06:11:26PM +0200, Peter Ujfalusi wrote:
>>
>>> if we revert the commit then the original issue will re-surfaces. afaik
>>> it was not only audio which hit the 'last driver to be probed from the
>>> deferred list would never probe, unless we provoke the kernel to load
>>> additional module, or remove/reload the module' issue.
>>
>> Right, aren't we just going to be swapping one bug for another?
> 
> Have anyone in possession of Davinchi tested most recent kernel with
> this revert?

I don't think it is related to daVinci, in fact we have seen the very
same issue with OMAP4.
Fwiw this was my initial patch
http://lkml.iu.edu/hypermail/linux/kernel/1404.0/01603.html
Grant based his change on this.

Note the part in the commit message:
"The issue has been observed on embedded systems with CONFIG_PREEMPT
enabled, audio support built as modules and using nfsroot for root
filesystem."

as I recall I was only able to reproduce the stall with nfsroot and
buildroot fs. The timings were different compared to MMC rootfs.

Anyways the patch fixes a real race condition which is generic:
We have driverA and driverB as modules. driverB needs driverA to be
registered to a framework (no direct, hard dependency).

1. driverA starts to probe
2. driverB starts to probe
3. driverB can not continue as driverA is not registered itself to the
framework -> driverB will defer
4. driverA registers to the framework
5. driverA probes successfully
6. driver core will prepare the deferred probe list (note: driverB is
still in it's probe, not in the deferred list)
7. driverB returns from it's probe with -EPROBE_DEFER

and here we are, driverB is alone in the deferred list and the list is
not going to be tried as driverA and driverB were the last ones to
probe.

So, driverB is in the deferred list and stays there until other driver
probes successfully as the deferred driver list only tried when a driver
loads successfully (to see if that satisfy any of the deferred driver).

We have evidence that this has happened, it is a generic issue given
that now days we have more frameworks drivers are relying on.

>>> Do I understand correctly that in your case you have two modules
>>> (dwc3-pci and extcon-intel-mrfld) in a deferred probe loop, iow both of
>>> the drivers returns -EPROBE_DEFER and they just spin?
>>
>>> If both is deferring, how this supposed to work?
>>
>> I'm struggling to follow the original explanation too :(
> 
> Sorry, guys, I confused a nit myself. The bug is there, but
> exxplanation is not fully corrent, indeed. I'll come back with more
> details later.
> 

- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH] USB: ehci-omap: Fix deferred probe for phy handling

2018-12-12 Thread Peter Ujfalusi



On 13/12/2018 4.17, Tony Lindgren wrote:
> The only case where we can bail out safely without a phy is port_mode
> is OMAP_USBHS_PORT_MODE_UNUSED. It used to be that OMAP_EHCI_PORT_MODE_PHY
> was optional, but that's not a good assumption. We should already have
> "ehci-phy" in all the dts files using OMAP_EHCI_PORT_MODE_PHY.
> 
> Note that this fix should not be needed for kernels earlier than v4.19
> as that's when we started moving devices to probe with ti-sysc. We now
> probe l4 interconnects separately, which can cause deferred probe with
> the phy being on a separate l4 interconnect from EHCI.
> 
> And old kernels would need to be checked for "ehci-phy" property for
> this fix to avoid regressions.

Tested-by: Peter Ujfalusi 

> Cc: Alan Stern 
> Cc: Johan Hovold 
> Cc: Ladislav Michl 
> Cc: Peter Ujfalusi 
> Cc: Roger Quadros 
> Reported-by: Peter Ujfalusi 
> Signed-off-by: Tony Lindgren 
> ---
>  drivers/usb/host/ehci-omap.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
> --- a/drivers/usb/host/ehci-omap.c
> +++ b/drivers/usb/host/ehci-omap.c
> @@ -159,8 +159,8 @@ static int ehci_hcd_omap_probe(struct platform_device 
> *pdev)
>   /* get the PHY device */
>   phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
>   if (IS_ERR(phy)) {
> - /* Don't bail out if PHY is not absolutely necessary */
> - if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
> + /* Don't bail out if PHY is unused */
> + if (pdata->port_mode[i] == OMAP_USBHS_PORT_MODE_UNUSED)
>   continue;
>  
>   ret = PTR_ERR(phy);
> 

- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH v3] usb: ehci-omap: Fix deferred probe for phy handling

2018-12-14 Thread Peter Ujfalusi
Roger,

On 14/12/2018 11.36, Roger Quadros wrote:
> PHY model is being used on omap5 platforms even if port mode
> is not OMAP_EHCI_PORT_MODE_PHY. So don't guess if PHY is required
> or not based on PHY mode.
> 
> If PHY is provided in device tree, it must be required. So, if
> devm_usb_get_phy_by_phandle() gives us an error code other
> than -ENODEV (no PHY) then error out.
> 
> This fixes USB Ethernet on omap5-uevm if PHY happens to
> probe after EHCI thus causing a -EPROBE_DEFER.

Thanks, it works.

Tested-by: Peter Ujfalusi 

> Cc: Alan Stern 
> Cc: Johan Hovold 
> Cc: Ladislav Michl 
> Cc: Peter Ujfalusi 
> Cc: Tony Lindgren 
> Reported-by: Peter Ujfalusi 
> Signed-off-by: Roger Quadros 
> ---
>  drivers/usb/host/ehci-omap.c | 7 ---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
> index 7e4c1334..7d20296 100644
> --- a/drivers/usb/host/ehci-omap.c
> +++ b/drivers/usb/host/ehci-omap.c
> @@ -159,11 +159,12 @@ static int ehci_hcd_omap_probe(struct platform_device 
> *pdev)
>   /* get the PHY device */
>   phy = devm_usb_get_phy_by_phandle(dev, "phys", i);
>   if (IS_ERR(phy)) {
> - /* Don't bail out if PHY is not absolutely necessary */
> - if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY)
> + ret = PTR_ERR(phy);
> + if (ret == -ENODEV) { /* no PHY */
> + phy = NULL;
>   continue;
> + }
>  
> - ret = PTR_ERR(phy);
>   if (ret != -EPROBE_DEFER)
>   dev_err(dev, "Can't get PHY for port %d: %d\n",
>   i, ret);
> 

- Péter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH] dmaengine: cppi41: Fix cppi41_dma_prep_slave_sg() when idle

2019-10-23 Thread Peter Ujfalusi
Hi Tony,

On 10/23/19 6:31 PM, Tony Lindgren wrote:
> Yegor Yefremov  reported that musb and ftdi
> uart can fail for the first open of the uart unless connected using
> a hub.
> 
> This is because the first dma call done by musb_ep_program() must wait
> if cppi41 is PM runtime suspended. Otherwise musb_ep_program() continues
> with other non-dma packets before the DMA transfer is started causing at
> least ftdi uarts to fail to receive data.
> 
> Let's fix the issue by waking up cppi41 with PM runtime calls added to
> cppi41_dma_prep_slave_sg() and return NULL if still idled. This way we
> have musb_ep_program() continue with PIO until cppi41 is awake.
> 
> Fixes: fdea2d09b997 ("dmaengine: cppi41: Add basic PM runtime support")
> Cc: Bin Liu 
> Cc: giulio.bene...@benettiengineering.com
> Cc: Sebastian Andrzej Siewior 
> Cc: Sebastian Reichel 
> Cc: Skvortsov 
> Reported-by: Yegor Yefremov 
> Signed-off-by: Tony Lindgren 
> ---
> 
> Please consider adding Cc stable v4.9+ tag when committing
> 
> ---
>  drivers/dma/ti/cppi41.c | 21 -
>  1 file changed, 20 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
> --- a/drivers/dma/ti/cppi41.c
> +++ b/drivers/dma/ti/cppi41.c
> @@ -586,9 +586,22 @@ static struct dma_async_tx_descriptor 
> *cppi41_dma_prep_slave_sg(
>   enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
>  {
>   struct cppi41_channel *c = to_cpp41_chan(chan);
> + struct dma_async_tx_descriptor *txd = NULL;
> + struct cppi41_dd *cdd = c->cdd;
>   struct cppi41_desc *d;
>   struct scatterlist *sg;
>   unsigned int i;
> + int error;
> +
> + error = pm_runtime_get(cdd->ddev.dev);

If pm_runtime_get()
pm_runtime_mark_last_busy()+pm_runtime_put_autosuspend() around a code
which updates a descriptor in _memory_ helps then this best described as
works by luck ;)

I have a feeling that if you put enough delay between prepare_sg and
issue_pending in the usb driver then it will keep failing, no?

fwiw, in the cppi41_dma_issue_pending() the driver does:

error = pm_runtime_get(cdd->ddev.dev);
...
if (!cdd->is_suspended)
cppi41_run_queue(cdd);
...
pm_runtime_mark_last_busy(cdd->ddev.dev);
pm_runtime_put_autosuspend(cdd->ddev.dev);

Without waiting for the transfer to complete?

If issue_pending is not starting the transfer right away then the whole
pm handling is broken in there. imho.

runtime_get in prep_slave_sg and runtime_put when the transfer is finished?

> + if (error < 0) {
> + pm_runtime_put_noidle(cdd->ddev.dev);
> +
> + return NULL;
> + }
> +
> + if (cdd->is_suspended)
> + goto err_out_not_ready;
>  
>   d = c->desc;
>   for_each_sg(sgl, sg, sg_len, i) {
> @@ -611,7 +624,13 @@ static struct dma_async_tx_descriptor 
> *cppi41_dma_prep_slave_sg(
>   d++;
>   }
>  
> - return &c->txd;
> + txd = &c->txd;
> +
> +err_out_not_ready:
> + pm_runtime_mark_last_busy(cdd->ddev.dev);
> + pm_runtime_put_autosuspend(cdd->ddev.dev);
> +
> + return txd;
>  }
>  
>  static void cppi41_compute_td_desc(struct cppi41_desc *d)
> 

- Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki


Re: [PATCH] dmaengine: cppi41: Fix cppi41_dma_prep_slave_sg() when idle

2019-10-23 Thread Peter Ujfalusi



On 10/23/19 8:16 PM, Tony Lindgren wrote:
> * Peter Ujfalusi  [191023 17:04]:
>> On 10/23/19 6:31 PM, Tony Lindgren wrote:
>>> diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
>>> --- a/drivers/dma/ti/cppi41.c
>>> +++ b/drivers/dma/ti/cppi41.c
>>> @@ -586,9 +586,22 @@ static struct dma_async_tx_descriptor 
>>> *cppi41_dma_prep_slave_sg(
>>> enum dma_transfer_direction dir, unsigned long tx_flags, void *context)
>>>  {
>>> struct cppi41_channel *c = to_cpp41_chan(chan);
>>> +   struct dma_async_tx_descriptor *txd = NULL;
>>> +   struct cppi41_dd *cdd = c->cdd;
>>> struct cppi41_desc *d;
>>> struct scatterlist *sg;
>>> unsigned int i;
>>> +   int error;
>>> +
>>> +   error = pm_runtime_get(cdd->ddev.dev);
>>
>> If pm_runtime_get()
>> pm_runtime_mark_last_busy()+pm_runtime_put_autosuspend() around a code
>> which updates a descriptor in _memory_ helps then this best described as
>> works by luck ;)
> 
> It also checks the cpp41 state for cdd->is_suspended
> though.

Which is cleared/set in the suspend/resume callbacks and they are called
from a work (the driver uses async runtime_get).

> AFAIK we do not currently have any other place
> to tell the driver a DMA request is about to start at
> some point soon.

True, but still.

>> I have a feeling that if you put enough delay between prepare_sg and
>> issue_pending in the usb driver then it will keep failing, no?
> 
> Nope, it will just queue it and run the queue when awake.

the autosuspend_delay is set 100 ms, so if you put a udelay(101) between
prep_sg and issue_pending in the usb driver this trickery will be for
nothing, right?
If the usb driver is preempted for longer than 100ms between the two
calls, same issue.
Not sure, but if for some reason the transfer would take longer than
100ms than pm_runtime will bring down the dma, no?

>> fwiw, in the cppi41_dma_issue_pending() the driver does:
>>
>>  error = pm_runtime_get(cdd->ddev.dev);
>> ...
>>  if (!cdd->is_suspended)
>>  cppi41_run_queue(cdd);
>> ...
>>  pm_runtime_mark_last_busy(cdd->ddev.dev);
>>  pm_runtime_put_autosuspend(cdd->ddev.dev);
>>
>> Without waiting for the transfer to complete?
> 
> The queue gets run when cpp41 is awake, runtime PM
> reference is not released until completed.
> 
>> If issue_pending is not starting the transfer right away then the whole
>> pm handling is broken in there. imho.
> 
> AFAIK there is no other way to do this without tagging
> devices with pm_runtime_irq_safe(), which is nasty as
> it takes a permanent use count on the parent device.
> 
> But yeah, some dmaengine API that can sleep to tell
> a request is about to come would simplify things.

any of the prep callbacks kind of indicates that a client is preparing a
transfer so in a perfect world it is going to want to execute it..

> I don't think we have anything like that available
> right now?

Well, it would have the same issues. If the time between
dmaengine_be_warned_i_m_going_to_call_issue_pending_soon and
issue_pending is more than the autosuspend_delay then it is not going to
help.

On the other hand: if the usb driver assumes that the dma transfer is
already finished when issue_pending returned and carry on with
subsequent request, that is also a problematic assumption. One can only
consider a transfer to be done if the completion callback is called or
you have polled for the completion and it tells you the same.
This is problematic if you are in atomic context as the DMA completion
interrupt might not come while you are there.

imho, this fix is working by lucky constellation of the stars ;)
Or we can assume that there will never be more than 100ms delay between
prepare_sg and issue_pending...

- Peter

Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki