| From 65de1bd9f2b5b67da4f20fb5863819a7567d67a5 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Wed, 19 May 2021 14:39:44 +0800 |
| Subject: usb: common: usb-conn-gpio: fix NULL pointer dereference of charger |
| |
| From: Chunfeng Yun <chunfeng.yun@mediatek.com> |
| |
| [ Upstream commit 880287910b1892ed2cb38977893b947382a09d21 ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/usb/common/usb-conn-gpio.c | 44 ++++++++++++++++++------------ |
| 1 file 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 */ |
| -- |
| 2.30.2 |
| |