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>
This commit is contained in:
Родитель
e4600d5632
Коммит
969a132723
|
@ -80,7 +80,8 @@ static struct musb *sunxi_musb;
|
|||
|
||||
struct sunxi_glue {
|
||||
struct device *dev;
|
||||
struct platform_device *musb;
|
||||
struct musb *musb;
|
||||
struct platform_device *musb_pdev;
|
||||
struct clk *clk;
|
||||
struct reset_control *rst;
|
||||
struct phy *phy;
|
||||
|
@ -102,7 +103,7 @@ static void sunxi_musb_work(struct work_struct *work)
|
|||
return;
|
||||
|
||||
if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
|
||||
struct musb *musb = platform_get_drvdata(glue->musb);
|
||||
struct musb *musb = glue->musb;
|
||||
unsigned long flags;
|
||||
u8 devctl;
|
||||
|
||||
|
@ -337,6 +338,8 @@ static void sunxi_musb_enable(struct musb *musb)
|
|||
{
|
||||
struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
|
||||
|
||||
glue->musb = musb;
|
||||
|
||||
/* musb_core does not call us in a balanced manner */
|
||||
if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
|
||||
return;
|
||||
|
@ -732,9 +735,9 @@ static int sunxi_musb_probe(struct platform_device *pdev)
|
|||
pinfo.data = &pdata;
|
||||
pinfo.size_data = sizeof(pdata);
|
||||
|
||||
glue->musb = platform_device_register_full(&pinfo);
|
||||
if (IS_ERR(glue->musb)) {
|
||||
ret = PTR_ERR(glue->musb);
|
||||
glue->musb_pdev = platform_device_register_full(&pinfo);
|
||||
if (IS_ERR(glue->musb_pdev)) {
|
||||
ret = PTR_ERR(glue->musb_pdev);
|
||||
dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
|
||||
goto err_unregister_usb_phy;
|
||||
}
|
||||
|
@ -751,7 +754,7 @@ static int sunxi_musb_remove(struct platform_device *pdev)
|
|||
struct sunxi_glue *glue = platform_get_drvdata(pdev);
|
||||
struct platform_device *usb_phy = glue->usb_phy;
|
||||
|
||||
platform_device_unregister(glue->musb); /* Frees glue ! */
|
||||
platform_device_unregister(glue->musb_pdev); /* Frees glue ! */
|
||||
usb_phy_generic_unregister(usb_phy);
|
||||
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче