On Fri, Jun 29, 2012 at 9:47 PM, Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx> wrote: > On 06/12/2012 10:52 AM, Kishon Vijay Abraham I wrote: >> Add a linked list for keeping multiple PHY instances with different >> types so that we can have separate USB2 and USB3 PHYs on one single >> board. _get_phy_ has been changed so that the controller gets >> the transceiver by type. _remove_phy_ has been added to let the phy >> be removed from the phy list. > > drivers/usb/otg/otg.c:106:16: warning: context imbalance in 'usb_get_phy' - wrong count at exit > > See below: > >> Signed-off-by: Kishon Vijay Abraham I <kishon@xxxxxx> >> Signed-off-by: Felipe Balbi <balbi@xxxxxx> >> --- >> drivers/usb/musb/omap2430.c | 2 +- >> drivers/usb/otg/ab8500-usb.c | 4 +- >> drivers/usb/otg/fsl_otg.c | 4 +- >> drivers/usb/otg/gpio_vbus.c | 4 +- >> drivers/usb/otg/isp1301_omap.c | 4 +- >> drivers/usb/otg/msm_otg.c | 4 +- >> drivers/usb/otg/mv_otg.c | 4 +- >> drivers/usb/otg/nop-usb-xceiv.c | 4 +- >> drivers/usb/otg/otg.c | 96 ++++++++++++++++++++++++++++++++++----- >> drivers/usb/otg/twl4030-usb.c | 2 +- >> drivers/usb/otg/twl6030-usb.c | 2 +- >> include/linux/usb/otg.h | 29 +++++++++++- >> 12 files changed, 127 insertions(+), 32 deletions(-) >> >> diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c >> index e16dbbf..e279cf3 100644 >> --- a/drivers/usb/musb/omap2430.c >> +++ b/drivers/usb/musb/omap2430.c >> @@ -292,7 +292,7 @@ static int omap2430_musb_init(struct musb *musb) >> * up through ULPI. TWL4030-family PMICs include one, >> * which needs a driver, drivers aren't always needed. >> */ >> - musb->xceiv = usb_get_phy(); >> + musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); >> if (!musb->xceiv) { >> pr_err("HS USB OTG: no transceiver configured\n"); >> return -ENODEV; >> diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c >> index 672e28c..ae8ad56 100644 >> --- a/drivers/usb/otg/ab8500-usb.c >> +++ b/drivers/usb/otg/ab8500-usb.c >> @@ -529,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev) >> if (err < 0) >> goto fail0; >> >> - err = usb_add_phy(&ab->phy); >> + err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2); >> if (err) { >> dev_err(&pdev->dev, "Can't register transceiver\n"); >> goto fail1; >> @@ -556,7 +556,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev) >> >> cancel_work_sync(&ab->phy_dis_work); >> >> - usb_add_phy(NULL); >> + usb_remove_phy(&ab->phy); >> >> ab8500_usb_host_phy_dis(ab); >> ab8500_usb_peri_phy_dis(ab); >> diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c >> index 73561ed..b68b610 100644 >> --- a/drivers/usb/otg/fsl_otg.c >> +++ b/drivers/usb/otg/fsl_otg.c >> @@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev) >> fsl_otg_dev = fsl_otg_tc; >> >> /* Store the otg transceiver */ >> - status = usb_add_phy(&fsl_otg_tc->phy); >> + status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2); >> if (status) { >> pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); >> goto err; >> @@ -1134,7 +1134,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev) >> { >> struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; >> >> - usb_add_phy(NULL); >> + usb_remove_phy(&fsl_otg_dev->phy); >> free_irq(fsl_otg_dev->irq, fsl_otg_dev); >> >> iounmap((void *)usb_dr_regs); >> diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c >> index 9b3c264..a67ffe2 100644 >> --- a/drivers/usb/otg/gpio_vbus.c >> +++ b/drivers/usb/otg/gpio_vbus.c >> @@ -320,7 +320,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) >> } >> >> /* only active when a gadget is registered */ >> - err = usb_add_phy(&gpio_vbus->phy); >> + err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2); >> if (err) { >> dev_err(&pdev->dev, "can't register transceiver, err: %d\n", >> err); >> @@ -354,7 +354,7 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev) >> cancel_delayed_work_sync(&gpio_vbus->work); >> regulator_put(gpio_vbus->vbus_draw); >> >> - usb_add_phy(NULL); >> + usb_remove_phy(&gpio_vbus->phy); >> >> free_irq(gpio_vbus->irq, pdev); >> if (gpio_is_valid(pdata->gpio_pullup)) >> diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c >> index 70f9950..9b8bfc1 100644 >> --- a/drivers/usb/otg/isp1301_omap.c >> +++ b/drivers/usb/otg/isp1301_omap.c >> @@ -1610,7 +1610,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) >> dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); >> #endif >> >> - status = usb_add_phy(&isp->phy); >> + status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2); >> if (status < 0) >> dev_err(&i2c->dev, "can't register transceiver, %d\n", >> status); >> @@ -1649,7 +1649,7 @@ subsys_initcall(isp_init); >> static void __exit isp_exit(void) >> { >> if (the_transceiver) >> - usb_add_phy(NULL); >> + usb_remove_phy(&the_transceiver->phy); >> i2c_del_driver(&isp1301_driver); >> } >> module_exit(isp_exit); >> diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c >> index 037d87c..dd281ca 100644 >> --- a/drivers/usb/otg/msm_otg.c >> +++ b/drivers/usb/otg/msm_otg.c >> @@ -1555,7 +1555,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) >> phy->otg->set_host = msm_otg_set_host; >> phy->otg->set_peripheral = msm_otg_set_peripheral; >> >> - ret = usb_add_phy(&motg->phy); >> + ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2); >> if (ret) { >> dev_err(&pdev->dev, "usb_set_transceiver failed\n"); >> goto free_irq; >> @@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) >> device_init_wakeup(&pdev->dev, 0); >> pm_runtime_disable(&pdev->dev); >> >> - usb_add_phy(NULL); >> + usb_remove_phy(phy); >> free_irq(motg->irq, motg); >> >> /* >> diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c >> index 18e90fe..1c5ed8e 100644 >> --- a/drivers/usb/otg/mv_otg.c >> +++ b/drivers/usb/otg/mv_otg.c >> @@ -690,7 +690,7 @@ int mv_otg_remove(struct platform_device *pdev) >> for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) >> clk_put(mvotg->clk[clk_i]); >> >> - usb_add_phy(NULL); >> + usb_remove_phy(&mvotg->phy); >> platform_set_drvdata(pdev, NULL); >> >> kfree(mvotg->phy.otg); >> @@ -880,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev) >> return 0; >> >> err_set_transceiver: >> - usb_add_phy(NULL); >> + usb_remove_phy(&mvotg->phy); >> err_free_irq: >> free_irq(mvotg->irq, mvotg); >> err_disable_clk: >> diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c >> index 33000da..803f958 100644 >> --- a/drivers/usb/otg/nop-usb-xceiv.c >> +++ b/drivers/usb/otg/nop-usb-xceiv.c >> @@ -117,7 +117,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) >> nop->phy.otg->set_host = nop_set_host; >> nop->phy.otg->set_peripheral = nop_set_peripheral; >> >> - err = usb_add_phy(&nop->phy); >> + err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2); >> if (err) { >> dev_err(&pdev->dev, "can't register transceiver, err: %d\n", >> err); >> @@ -139,7 +139,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) >> { >> struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); >> >> - usb_add_phy(NULL); >> + usb_remove_phy(&nop->phy); >> >> platform_set_drvdata(pdev, NULL); >> kfree(nop->phy.otg); >> diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c >> index 300a995..a230658 100644 >> --- a/drivers/usb/otg/otg.c >> +++ b/drivers/usb/otg/otg.c >> @@ -11,14 +11,32 @@ >> >> #include <linux/kernel.h> >> #include <linux/export.h> >> +#include <linux/err.h> >> #include <linux/device.h> >> >> #include <linux/usb/otg.h> >> >> -static struct usb_phy *phy; >> +static LIST_HEAD(phy_list); >> +static DEFINE_SPINLOCK(phy_lock); >> + >> +static struct usb_phy *__usb_find_phy(struct list_head *list, >> + enum usb_phy_type type) >> +{ >> + struct usb_phy *phy = NULL; >> + >> + list_for_each_entry(phy, list, head) { >> + if (phy->type != type) >> + continue; >> + >> + return phy; >> + } >> + >> + return ERR_PTR(-ENODEV); >> +} >> >> /** >> - * usb_get_phy - find the (single) USB PHY >> + * usb_get_phy - find the USB PHY >> + * @type - the type of the phy the controller requires >> * >> * Returns the phy driver, after getting a refcount to it; or >> * null if there is no such phy. The caller is responsible for >> @@ -26,16 +44,30 @@ static struct usb_phy *phy; >> * >> * For use by USB host and peripheral drivers. >> */ >> -struct usb_phy *usb_get_phy(void) >> +struct usb_phy *usb_get_phy(enum usb_phy_type type) >> { >> - if (phy) >> - get_device(phy->dev); >> + struct usb_phy *phy = NULL; >> + unsigned long flags; >> + >> + spin_lock_irqsave(&phy_lock, flags); >> + >> + phy = __usb_find_phy(&phy_list, type); >> + if (IS_ERR(phy)) { >> + pr_err("unable to find transceiver of type %s\n", >> + usb_phy_type_string(type)); > > missing spin_unlock_irqrestore(&phy_lock, flags); > (or goto exit) Ok, Will fix it. Thanks. -Kishon -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html