diff options
author | Hans de Goede <hdegoede@redhat.com> | 2016-06-14 16:13:05 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-06-14 16:36:23 -0400 |
commit | 969a132723434f3723cc0606373785d19c1d2f05 (patch) | |
tree | c3ba8c523258e8ef758744e0e7e4a6ddb102f7da | |
parent | e4600d56323ed119469fdcb21564f7544e1e6b3c (diff) |
usb: musb: sunxi: Fix NULL ptr deref when gadget is registered before musb
Stop using the return value of platform_device_register_full() to get to
the struct musb in sunxi_musb_work(). If a gadget has been registered
(insmod-ed) before the musb driver, then musb_start will get called
from the musb_core probe function and sunxi_musb_work() may run before
platform_device_register_full() has returned.
Instead store a pointer to struct musb in struct sunxi_glue when
sunxi_musb_enable gets called. Note that sunxi_musb_enable always gets
called before sunxi_musb_work() can run.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
[b-liu@ti.com: revise subject prefix]
Signed-off-by: Bin Liu <b-liu@ti.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/musb/sunxi.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index e7d46179b485..dc49041498a3 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c | |||
@@ -80,7 +80,8 @@ static struct musb *sunxi_musb; | |||
80 | 80 | ||
81 | struct sunxi_glue { | 81 | struct sunxi_glue { |
82 | struct device *dev; | 82 | struct device *dev; |
83 | struct platform_device *musb; | 83 | struct musb *musb; |
84 | struct platform_device *musb_pdev; | ||
84 | struct clk *clk; | 85 | struct clk *clk; |
85 | struct reset_control *rst; | 86 | struct reset_control *rst; |
86 | struct phy *phy; | 87 | struct phy *phy; |
@@ -102,7 +103,7 @@ static void sunxi_musb_work(struct work_struct *work) | |||
102 | return; | 103 | return; |
103 | 104 | ||
104 | if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) { | 105 | if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) { |
105 | struct musb *musb = platform_get_drvdata(glue->musb); | 106 | struct musb *musb = glue->musb; |
106 | unsigned long flags; | 107 | unsigned long flags; |
107 | u8 devctl; | 108 | u8 devctl; |
108 | 109 | ||
@@ -337,6 +338,8 @@ static void sunxi_musb_enable(struct musb *musb) | |||
337 | { | 338 | { |
338 | struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); | 339 | struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent); |
339 | 340 | ||
341 | glue->musb = musb; | ||
342 | |||
340 | /* musb_core does not call us in a balanced manner */ | 343 | /* musb_core does not call us in a balanced manner */ |
341 | if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags)) | 344 | if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags)) |
342 | return; | 345 | return; |
@@ -732,9 +735,9 @@ static int sunxi_musb_probe(struct platform_device *pdev) | |||
732 | pinfo.data = &pdata; | 735 | pinfo.data = &pdata; |
733 | pinfo.size_data = sizeof(pdata); | 736 | pinfo.size_data = sizeof(pdata); |
734 | 737 | ||
735 | glue->musb = platform_device_register_full(&pinfo); | 738 | glue->musb_pdev = platform_device_register_full(&pinfo); |
736 | if (IS_ERR(glue->musb)) { | 739 | if (IS_ERR(glue->musb_pdev)) { |
737 | ret = PTR_ERR(glue->musb); | 740 | ret = PTR_ERR(glue->musb_pdev); |
738 | dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret); | 741 | dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret); |
739 | goto err_unregister_usb_phy; | 742 | goto err_unregister_usb_phy; |
740 | } | 743 | } |
@@ -751,7 +754,7 @@ static int sunxi_musb_remove(struct platform_device *pdev) | |||
751 | struct sunxi_glue *glue = platform_get_drvdata(pdev); | 754 | struct sunxi_glue *glue = platform_get_drvdata(pdev); |
752 | struct platform_device *usb_phy = glue->usb_phy; | 755 | struct platform_device *usb_phy = glue->usb_phy; |
753 | 756 | ||
754 | platform_device_unregister(glue->musb); /* Frees glue ! */ | 757 | platform_device_unregister(glue->musb_pdev); /* Frees glue ! */ |
755 | usb_phy_generic_unregister(usb_phy); | 758 | usb_phy_generic_unregister(usb_phy); |
756 | 759 | ||
757 | return 0; | 760 | return 0; |