diff options
author | Chunfeng Yun <chunfeng.yun@mediatek.com> | 2021-05-19 14:39:44 +0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-05-21 14:09:54 +0200 |
commit | 880287910b1892ed2cb38977893b947382a09d21 (patch) | |
tree | 3a58ddb30cd85befe6da1e9474d990d5d2038d3b /drivers/usb/common | |
parent | c63fef4c4302f5d41945f5362ff0cf556cb6db19 (diff) |
usb: common: usb-conn-gpio: fix NULL pointer dereference of charger
When power on system with OTG cable, IDDIG's interrupt arises before
the charger registration, it will cause a NULL pointer dereference,
fix the issue by registering the power supply before requesting
IDDIG/VBUS irq.
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
Link: https://lore.kernel.org/r/1621406386-18838-1-git-send-email-chunfeng.yun@mediatek.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/common')
-rw-r--r-- | drivers/usb/common/usb-conn-gpio.c | 44 |
1 files changed, 26 insertions, 18 deletions
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index 6c4e3a19f42c..c9545a4eff66 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -149,14 +149,32 @@ static int usb_charger_get_property(struct power_supply *psy, return 0; } -static int usb_conn_probe(struct platform_device *pdev) +static int usb_conn_psy_register(struct usb_conn_info *info) { - struct device *dev = &pdev->dev; - struct power_supply_desc *desc; - struct usb_conn_info *info; + struct device *dev = info->dev; + struct power_supply_desc *desc = &info->desc; struct power_supply_config cfg = { .of_node = dev->of_node, }; + + desc->name = "usb-charger"; + desc->properties = usb_charger_properties; + desc->num_properties = ARRAY_SIZE(usb_charger_properties); + desc->get_property = usb_charger_get_property; + desc->type = POWER_SUPPLY_TYPE_USB; + cfg.drv_data = info; + + info->charger = devm_power_supply_register(dev, desc, &cfg); + if (IS_ERR(info->charger)) + dev_err(dev, "Unable to register charger\n"); + + return PTR_ERR_OR_ZERO(info->charger); +} + +static int usb_conn_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_conn_info *info; bool need_vbus = true; int ret = 0; @@ -218,6 +236,10 @@ static int usb_conn_probe(struct platform_device *pdev) return PTR_ERR(info->role_sw); } + ret = usb_conn_psy_register(info); + if (ret) + goto put_role_sw; + if (info->id_gpiod) { info->id_irq = gpiod_to_irq(info->id_gpiod); if (info->id_irq < 0) { @@ -252,20 +274,6 @@ static int usb_conn_probe(struct platform_device *pdev) } } - desc = &info->desc; - desc->name = "usb-charger"; - desc->properties = usb_charger_properties; - desc->num_properties = ARRAY_SIZE(usb_charger_properties); - desc->get_property = usb_charger_get_property; - desc->type = POWER_SUPPLY_TYPE_USB; - cfg.drv_data = info; - - info->charger = devm_power_supply_register(dev, desc, &cfg); - if (IS_ERR(info->charger)) { - dev_err(dev, "Unable to register charger\n"); - return PTR_ERR(info->charger); - } - platform_set_drvdata(pdev, info); /* Perform initial detection */ |