diff mbox

[v2] usb: gadget: at91_udc: move prepare clk into process context

Message ID 1407424296-12359-1-git-send-email-ronald.wahl@raritan.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ronald Wahl Aug. 7, 2014, 3:11 p.m. UTC
Commit 7628083227b6bc4a7e33d7c381d7a4e558424b6b added clock preparation in
interrupt context. This is not allowed as it might sleep. Move clock
preparation and setting clock rate into process context (at91udc_probe).

Signed-off-by: Ronald Wahl <ronald.wahl@raritan.com>
---
 drivers/usb/gadget/udc/at91_udc.c | 44 ++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 12 deletions(-)

Comments

Ronald Wahl Aug. 7, 2014, 3:23 p.m. UTC | #1
Hi,

actually this should have been patch v3 and not v2. Anyway, the major 
difference is that I moved setting the clock rate into process context 
as well as it may also sleep.

- ron

On 07.08.2014 17:11, Ronald Wahl wrote:
> Commit 7628083227b6bc4a7e33d7c381d7a4e558424b6b added clock preparation in
> interrupt context. This is not allowed as it might sleep. Move clock
> preparation and setting clock rate into process context (at91udc_probe).
>
> Signed-off-by: Ronald Wahl <ronald.wahl@raritan.com>
> ---
>   drivers/usb/gadget/udc/at91_udc.c | 44 ++++++++++++++++++++++++++++-----------
>   1 file changed, 32 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
> index cfd18bc..0d685d0 100644
> --- a/drivers/usb/gadget/udc/at91_udc.c
> +++ b/drivers/usb/gadget/udc/at91_udc.c
> @@ -870,12 +870,10 @@ static void clk_on(struct at91_udc *udc)
>   		return;
>   	udc->clocked = 1;
>
> -	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
> -		clk_set_rate(udc->uclk, 48000000);
> -		clk_prepare_enable(udc->uclk);
> -	}
> -	clk_prepare_enable(udc->iclk);
> -	clk_prepare_enable(udc->fclk);
> +	if (IS_ENABLED(CONFIG_COMMON_CLK))
> +		clk_enable(udc->uclk);
> +	clk_enable(udc->iclk);
> +	clk_enable(udc->fclk);
>   }
>
>   static void clk_off(struct at91_udc *udc)
> @@ -884,10 +882,10 @@ static void clk_off(struct at91_udc *udc)
>   		return;
>   	udc->clocked = 0;
>   	udc->gadget.speed = USB_SPEED_UNKNOWN;
> -	clk_disable_unprepare(udc->fclk);
> -	clk_disable_unprepare(udc->iclk);
> +	clk_disable(udc->fclk);
> +	clk_disable(udc->iclk);
>   	if (IS_ENABLED(CONFIG_COMMON_CLK))
> -		clk_disable_unprepare(udc->uclk);
> +		clk_disable(udc->uclk);
>   }
>
>   /*
> @@ -1780,14 +1778,24 @@ static int at91udc_probe(struct platform_device *pdev)
>   	}
>
>   	/* don't do anything until we have both gadget driver and VBUS */
> +	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
> +		clk_set_rate(udc->uclk, 48000000);
> +		retval = clk_prepare(udc->uclk);
> +		if (retval)
> +			goto fail1;
> +	}
> +	retval = clk_prepare(udc->fclk);
> +	if (retval)
> +		goto fail1a;
> +
>   	retval = clk_prepare_enable(udc->iclk);
>   	if (retval)
> -		goto fail1;
> +		goto fail1b;
>   	at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
>   	at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
>   	/* Clear all pending interrupts - UDP may be used by bootloader. */
>   	at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
> -	clk_disable_unprepare(udc->iclk);
> +	clk_disable(udc->iclk);
>
>   	/* request UDC and maybe VBUS irqs */
>   	udc->udp_irq = platform_get_irq(pdev, 0);
> @@ -1795,7 +1803,7 @@ static int at91udc_probe(struct platform_device *pdev)
>   			0, driver_name, udc);
>   	if (retval < 0) {
>   		DBG("request irq %d failed\n", udc->udp_irq);
> -		goto fail1;
> +		goto fail1c;
>   	}
>   	if (gpio_is_valid(udc->board.vbus_pin)) {
>   		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
> @@ -1848,6 +1856,13 @@ fail3:
>   		gpio_free(udc->board.vbus_pin);
>   fail2:
>   	free_irq(udc->udp_irq, udc);
> +fail1c:
> +	clk_unprepare(udc->iclk);
> +fail1b:
> +	clk_unprepare(udc->fclk);
> +fail1a:
> +	if (IS_ENABLED(CONFIG_COMMON_CLK))
> +		clk_unprepare(udc->uclk);
>   fail1:
>   	if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
>   		clk_put(udc->uclk);
> @@ -1896,6 +1911,11 @@ static int __exit at91udc_remove(struct platform_device *pdev)
>   	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   	release_mem_region(res->start, resource_size(res));
>
> +	if (IS_ENABLED(CONFIG_COMMON_CLK))
> +		clk_unprepare(udc->uclk);
> +	clk_unprepare(udc->fclk);
> +	clk_unprepare(udc->iclk);
> +
>   	clk_put(udc->iclk);
>   	clk_put(udc->fclk);
>   	if (IS_ENABLED(CONFIG_COMMON_CLK))
>
Sergei Shtylyov Aug. 7, 2014, 4:27 p.m. UTC | #2
Hello.

On 08/07/2014 07:11 PM, Ronald Wahl wrote:

> Commit 7628083227b6bc4a7e33d7c381d7a4e558424b6b added clock preparation in

    Please also specify that commit's summary in parens.

> interrupt context. This is not allowed as it might sleep. Move clock
> preparation and setting clock rate into process context (at91udc_probe).

> Signed-off-by: Ronald Wahl <ronald.wahl@raritan.com>

WBR, Sergei
Alexandre Belloni Aug. 7, 2014, 10:32 p.m. UTC | #3
Hi,

For the next revision, please include the changelog after the --- marker
and before the diffstat. Else, this looks good to me, with the same
comment as Boris on the PLLB gating. We will take care of that later.

Regards

On 07/08/2014 at 17:23:58 +0200, Ronald Wahl wrote :
> Hi,
> 
> actually this should have been patch v3 and not v2. Anyway, the
> major difference is that I moved setting the clock rate into process
> context as well as it may also sleep.
> 
> - ron
> 
> On 07.08.2014 17:11, Ronald Wahl wrote:
> >Commit 7628083227b6bc4a7e33d7c381d7a4e558424b6b added clock preparation in
> >interrupt context. This is not allowed as it might sleep. Move clock
> >preparation and setting clock rate into process context (at91udc_probe).
> >
> >Signed-off-by: Ronald Wahl <ronald.wahl@raritan.com>
> >---
> >  drivers/usb/gadget/udc/at91_udc.c | 44 ++++++++++++++++++++++++++++-----------
> >  1 file changed, 32 insertions(+), 12 deletions(-)
> >
> >diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
> >index cfd18bc..0d685d0 100644
> >--- a/drivers/usb/gadget/udc/at91_udc.c
> >+++ b/drivers/usb/gadget/udc/at91_udc.c
> >@@ -870,12 +870,10 @@ static void clk_on(struct at91_udc *udc)
> >  		return;
> >  	udc->clocked = 1;
> >
> >-	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
> >-		clk_set_rate(udc->uclk, 48000000);
> >-		clk_prepare_enable(udc->uclk);
> >-	}
> >-	clk_prepare_enable(udc->iclk);
> >-	clk_prepare_enable(udc->fclk);
> >+	if (IS_ENABLED(CONFIG_COMMON_CLK))
> >+		clk_enable(udc->uclk);
> >+	clk_enable(udc->iclk);
> >+	clk_enable(udc->fclk);
> >  }
> >
> >  static void clk_off(struct at91_udc *udc)
> >@@ -884,10 +882,10 @@ static void clk_off(struct at91_udc *udc)
> >  		return;
> >  	udc->clocked = 0;
> >  	udc->gadget.speed = USB_SPEED_UNKNOWN;
> >-	clk_disable_unprepare(udc->fclk);
> >-	clk_disable_unprepare(udc->iclk);
> >+	clk_disable(udc->fclk);
> >+	clk_disable(udc->iclk);
> >  	if (IS_ENABLED(CONFIG_COMMON_CLK))
> >-		clk_disable_unprepare(udc->uclk);
> >+		clk_disable(udc->uclk);
> >  }
> >
> >  /*
> >@@ -1780,14 +1778,24 @@ static int at91udc_probe(struct platform_device *pdev)
> >  	}
> >
> >  	/* don't do anything until we have both gadget driver and VBUS */
> >+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
> >+		clk_set_rate(udc->uclk, 48000000);
> >+		retval = clk_prepare(udc->uclk);
> >+		if (retval)
> >+			goto fail1;
> >+	}
> >+	retval = clk_prepare(udc->fclk);
> >+	if (retval)
> >+		goto fail1a;
> >+
> >  	retval = clk_prepare_enable(udc->iclk);
> >  	if (retval)
> >-		goto fail1;
> >+		goto fail1b;
> >  	at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
> >  	at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
> >  	/* Clear all pending interrupts - UDP may be used by bootloader. */
> >  	at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
> >-	clk_disable_unprepare(udc->iclk);
> >+	clk_disable(udc->iclk);
> >
> >  	/* request UDC and maybe VBUS irqs */
> >  	udc->udp_irq = platform_get_irq(pdev, 0);
> >@@ -1795,7 +1803,7 @@ static int at91udc_probe(struct platform_device *pdev)
> >  			0, driver_name, udc);
> >  	if (retval < 0) {
> >  		DBG("request irq %d failed\n", udc->udp_irq);
> >-		goto fail1;
> >+		goto fail1c;
> >  	}
> >  	if (gpio_is_valid(udc->board.vbus_pin)) {
> >  		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
> >@@ -1848,6 +1856,13 @@ fail3:
> >  		gpio_free(udc->board.vbus_pin);
> >  fail2:
> >  	free_irq(udc->udp_irq, udc);
> >+fail1c:
> >+	clk_unprepare(udc->iclk);
> >+fail1b:
> >+	clk_unprepare(udc->fclk);
> >+fail1a:
> >+	if (IS_ENABLED(CONFIG_COMMON_CLK))
> >+		clk_unprepare(udc->uclk);
> >  fail1:
> >  	if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
> >  		clk_put(udc->uclk);
> >@@ -1896,6 +1911,11 @@ static int __exit at91udc_remove(struct platform_device *pdev)
> >  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >  	release_mem_region(res->start, resource_size(res));
> >
> >+	if (IS_ENABLED(CONFIG_COMMON_CLK))
> >+		clk_unprepare(udc->uclk);
> >+	clk_unprepare(udc->fclk);
> >+	clk_unprepare(udc->iclk);
> >+
> >  	clk_put(udc->iclk);
> >  	clk_put(udc->fclk);
> >  	if (IS_ENABLED(CONFIG_COMMON_CLK))
> >
diff mbox

Patch

diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index cfd18bc..0d685d0 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -870,12 +870,10 @@  static void clk_on(struct at91_udc *udc)
 		return;
 	udc->clocked = 1;
 
-	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
-		clk_set_rate(udc->uclk, 48000000);
-		clk_prepare_enable(udc->uclk);
-	}
-	clk_prepare_enable(udc->iclk);
-	clk_prepare_enable(udc->fclk);
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_enable(udc->uclk);
+	clk_enable(udc->iclk);
+	clk_enable(udc->fclk);
 }
 
 static void clk_off(struct at91_udc *udc)
@@ -884,10 +882,10 @@  static void clk_off(struct at91_udc *udc)
 		return;
 	udc->clocked = 0;
 	udc->gadget.speed = USB_SPEED_UNKNOWN;
-	clk_disable_unprepare(udc->fclk);
-	clk_disable_unprepare(udc->iclk);
+	clk_disable(udc->fclk);
+	clk_disable(udc->iclk);
 	if (IS_ENABLED(CONFIG_COMMON_CLK))
-		clk_disable_unprepare(udc->uclk);
+		clk_disable(udc->uclk);
 }
 
 /*
@@ -1780,14 +1778,24 @@  static int at91udc_probe(struct platform_device *pdev)
 	}
 
 	/* don't do anything until we have both gadget driver and VBUS */
+	if (IS_ENABLED(CONFIG_COMMON_CLK)) {
+		clk_set_rate(udc->uclk, 48000000);
+		retval = clk_prepare(udc->uclk);
+		if (retval)
+			goto fail1;
+	}
+	retval = clk_prepare(udc->fclk);
+	if (retval)
+		goto fail1a;
+
 	retval = clk_prepare_enable(udc->iclk);
 	if (retval)
-		goto fail1;
+		goto fail1b;
 	at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
 	at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
 	/* Clear all pending interrupts - UDP may be used by bootloader. */
 	at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
-	clk_disable_unprepare(udc->iclk);
+	clk_disable(udc->iclk);
 
 	/* request UDC and maybe VBUS irqs */
 	udc->udp_irq = platform_get_irq(pdev, 0);
@@ -1795,7 +1803,7 @@  static int at91udc_probe(struct platform_device *pdev)
 			0, driver_name, udc);
 	if (retval < 0) {
 		DBG("request irq %d failed\n", udc->udp_irq);
-		goto fail1;
+		goto fail1c;
 	}
 	if (gpio_is_valid(udc->board.vbus_pin)) {
 		retval = gpio_request(udc->board.vbus_pin, "udc_vbus");
@@ -1848,6 +1856,13 @@  fail3:
 		gpio_free(udc->board.vbus_pin);
 fail2:
 	free_irq(udc->udp_irq, udc);
+fail1c:
+	clk_unprepare(udc->iclk);
+fail1b:
+	clk_unprepare(udc->fclk);
+fail1a:
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_unprepare(udc->uclk);
 fail1:
 	if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
 		clk_put(udc->uclk);
@@ -1896,6 +1911,11 @@  static int __exit at91udc_remove(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, resource_size(res));
 
+	if (IS_ENABLED(CONFIG_COMMON_CLK))
+		clk_unprepare(udc->uclk);
+	clk_unprepare(udc->fclk);
+	clk_unprepare(udc->iclk);
+
 	clk_put(udc->iclk);
 	clk_put(udc->fclk);
 	if (IS_ENABLED(CONFIG_COMMON_CLK))