From: "Lothar Waßmann" <LW@KARO-electronics.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback
Date: Tue, 20 Jun 2017 13:32:58 +0200 [thread overview]
Message-ID: <20170620133258.114eba5c@karo-electronics.de> (raw)
In-Reply-To: <1497952751-28477-7-git-send-email-patrice.chotard@st.com>
Hi,
On Tue, 20 Jun 2017 11:59:07 +0200 patrice.chotard at st.com wrote:
> From: Patrice Chotard <patrice.chotard@st.com>
>
> Use an array to save enabled clocks reference and deasserted resets
> in order to respectively disabled and asserted them in case of error
> during probe() or during driver removal.
>
> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
> ---
>
> v7: _ replace clk_count() and reset_count() by ofnode_count_phandle_with_args()
>
> v6: _ none
>
> v5: _ none
>
> v4: _ update the memory allocation for deasserted resets and enabled
> clocks reference list. Replace lists by arrays.
> _ usage of new RESET and CLOCK methods clk_count(), reset_count(),
> reset_assert_all() and clk_disable_all().
>
> v3: _ keep enabled clocks and deasserted resets reference in list in order to
> disable clock or assert resets in error path or in .remove callback
> _ use struct generic_ehci * instead of struct udevice * as parameter for
> ehci_release_resets() and ehci_release_clocks()
>
> drivers/usb/host/ehci-generic.c | 125 ++++++++++++++++++++++++++++++++--------
> 1 file changed, 101 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
> index 2116ae1..388b242 100644
> --- a/drivers/usb/host/ehci-generic.c
> +++ b/drivers/usb/host/ehci-generic.c
> @@ -11,6 +11,8 @@
> #include <dm.h>
> #include "ehci.h"
>
> +#include <dm/ofnode.h>
> +
> /*
> * Even though here we don't explicitly use "struct ehci_ctrl"
> * ehci_register() expects it to be the first thing that resides in
> @@ -18,43 +20,119 @@
> */
> struct generic_ehci {
> struct ehci_ctrl ctrl;
> + struct clk *clocks;
> + struct reset_ctl *resets;
> + int clock_count;
> + int reset_count;
> };
>
> static int ehci_usb_probe(struct udevice *dev)
> {
> + struct generic_ehci *priv = dev_get_priv(dev);
> struct ehci_hccr *hccr;
> struct ehci_hcor *hcor;
> - int i;
> -
> - for (i = 0; ; i++) {
> - struct clk clk;
> - int ret;
> -
> - ret = clk_get_by_index(dev, i, &clk);
> - if (ret < 0)
> - break;
> - if (clk_enable(&clk))
> - error("failed to enable clock %d\n", i);
> - clk_free(&clk);
> - }
> + int i, err, ret, clock_nb, reset_nb;
> +
> + err = 0;
> + priv->clock_count = 0;
> + clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
> + "#clock-cells");
> + if (clock_nb > 0) {
> + priv->clocks = devm_kmalloc(dev, sizeof(struct clk) * clock_nb,
> + GFP_KERNEL);
> + if (!priv->clocks) {
> + error("Can't allocate resource\n");
> + return -ENOMEM;
> + }
> +
> + for (i = 0; i < clock_nb; i++) {
> + err = clk_get_by_index(dev, i, &priv->clocks[i]);
> +
> + if (err < 0)
> + break;
>
> - for (i = 0; ; i++) {
> - struct reset_ctl reset;
> - int ret;
> + priv->clock_count++;
>
> - ret = reset_get_by_index(dev, i, &reset);
> - if (ret < 0)
> - break;
> - if (reset_deassert(&reset))
> - error("failed to deassert reset %d\n", i);
> - reset_free(&reset);
> + if (clk_enable(&priv->clocks[i])) {
> + error("failed to enable clock %d\n", i);
> + clk_free(&priv->clocks[i]);
>
You free the clock here and again with clk_disable_all() in the error
path. Also you do not have a valid error code in 'err' which is
returned at the end of the function!
> + goto clk_err;
> + }
> + clk_free(&priv->clocks[i]);
> + }
> + } else {
> + if (clock_nb != -ENOENT) {
> + error("failed to get clock phandle(%d)\n", clock_nb);
> + return clock_nb;
> + }
> }
>
> + priv->reset_count = 0;
> + reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
> + "#reset-cells");
> + if (reset_nb > 0) {
> + priv->resets = devm_kmalloc(dev,
> + sizeof(struct reset_ctl) * reset_nb,
> + GFP_KERNEL);
> + if (!priv->resets) {
> + error("Can't allocate resource\n");
> + return -ENOMEM;
> + }
> +
> + for (i = 0; i < reset_nb; i++) {
> + err = reset_get_by_index(dev, i, &priv->resets[i]);
> + if (err < 0)
> + break;
> +
> + priv->reset_count++;
> +
> + if (reset_deassert(&priv->resets[i])) {
> + error("failed to deassert reset %d\n", i);
> + reset_free(&priv->resets[i]);
> + goto reset_err;
> + }
> + reset_free(&priv->resets[i]);
> + }
> + } else {
> + if (reset_nb != -ENOENT) {
> + error("failed to get reset phandle(%d)\n", reset_nb);
> + goto clk_err;
> + }
> + }
> hccr = map_physmem(devfdt_get_addr(dev), 0x100, MAP_NOCACHE);
> hcor = (struct ehci_hcor *)((uintptr_t)hccr +
> HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
>
> - return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
> + err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
> + if (!err)
> + return err;
> +
> +reset_err:
> + ret = reset_assert_all(priv->resets, priv->reset_count);
> + if (ret)
> + return ret;
>
You should do the clock cleanup even though the reset cleanup failed.
> +clk_err:
> + ret = clk_disable_all(priv->clocks, priv->clock_count);
> + if (ret)
> + return ret;
>
You should return the error code of the operation that failed
initially (err), not some error code that has occured during cleanup.
> + return err;
> +}
> +
> +static int ehci_usb_remove(struct udevice *dev)
> +{
> + struct generic_ehci *priv = dev_get_priv(dev);
> + int ret;
> +
> + ret = ehci_deregister(dev);
> + if (ret)
> + return ret;
> +
> + ret = reset_assert_all(priv->resets, priv->reset_count);
> + if (ret)
> + return ret;
> +
> + return clk_disable_all(priv->clocks, priv->clock_count);
> }
>
> static const struct udevice_id ehci_usb_ids[] = {
> @@ -67,7 +145,7 @@ U_BOOT_DRIVER(ehci_generic) = {
> .id = UCLASS_USB,
> .of_match = ehci_usb_ids,
> .probe = ehci_usb_probe,
> - .remove = ehci_deregister,
> + .remove = ehci_usb_remove,
> .ops = &ehci_usb_ops,
> .priv_auto_alloc_size = sizeof(struct generic_ehci),
> .flags = DM_FLAG_ALLOC_PRIV_DMA,
Lothar Waßmann
next prev parent reply other threads:[~2017-06-20 11:32 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-20 9:59 [U-Boot] [PATCH v7 00/10] usb: Extend ehci and ohci generic drivers patrice.chotard at st.com
2017-06-20 9:59 ` [U-Boot] [PATCH v7 01/10] reset: add reset_request() patrice.chotard at st.com
2017-06-20 9:59 ` [U-Boot] [PATCH v7 02/10] reset: add reset_assert_all() patrice.chotard at st.com
2017-06-20 9:59 ` [U-Boot] [PATCH v7 03/10] clk: add clk_disable_all() patrice.chotard at st.com
2017-06-20 12:11 ` Lothar Waßmann
2017-06-20 12:40 ` Patrice CHOTARD
2017-06-20 9:59 ` [U-Boot] [PATCH v7 04/10] dm: core: add ofnode_count_phandle_with_args() patrice.chotard at st.com
2017-06-20 18:26 ` Simon Glass
2017-06-20 9:59 ` [U-Boot] [PATCH v7 05/10] usb: host: ehci-generic: replace printf() by error() patrice.chotard at st.com
2017-06-20 9:59 ` [U-Boot] [PATCH v7 06/10] usb: host: ehci-generic: add error path and .remove callback patrice.chotard at st.com
2017-06-20 10:09 ` Marek Vasut
2017-06-20 11:26 ` Lothar Waßmann
2017-06-20 12:22 ` Patrice CHOTARD
2017-06-20 11:32 ` Lothar Waßmann [this message]
2017-06-20 12:28 ` Patrice CHOTARD
2017-06-20 9:59 ` [U-Boot] [PATCH v7 07/10] usb: host: ehci-generic: add generic PHY support patrice.chotard at st.com
2017-06-20 9:59 ` [U-Boot] [PATCH v7 08/10] usb: host: ohci-generic: add CLOCK support patrice.chotard at st.com
2017-06-20 12:06 ` Lothar Waßmann
2017-06-20 12:56 ` Patrice CHOTARD
2017-06-21 7:56 ` Lothar Waßmann
2017-06-21 8:36 ` Patrice CHOTARD
2017-06-20 9:59 ` [U-Boot] [PATCH v7 09/10] usb: host: ohci-generic: add RESET support patrice.chotard at st.com
2017-06-20 18:26 ` Simon Glass
2017-06-20 9:59 ` [U-Boot] [PATCH v7 10/10] usb: host: ohci-generic: add generic PHY support patrice.chotard at st.com
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170620133258.114eba5c@karo-electronics.de \
--to=lw@karo-electronics.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.