Skip to content

Commit 5c1d644

Browse files
Marc Zyngierthierryreding
authored andcommitted
drm/tegra: sor: Ensure regulators are disabled on teardown
The Tegra SOR driver uses the devm infrastructure to request regulators, but enables them without registering them with the infrastructure. This results in the following splat if probing fails for any odd resaon (such as dependencies not being available): [ 8.974187] tegra-sor 15580000.sor: cannot get HDMI supply: -517 [ 9.414403] tegra-sor 15580000.sor: failed to probe HDMI: -517 [ 9.421240] ------------[ cut here ]------------ [ 9.425879] WARNING: CPU: 1 PID: 164 at drivers/regulator/core.c:2089 _regulator_put.part.0+0x16c/0x174 [ 9.435259] Modules linked in: tegra_drm(E+) cec(E) ahci_tegra(E) drm_kms_helper(E) drm(E) libahci_platform(E) libahci(E) max77620_regulator(E) xhci_tegra(E+) sdhci_tegra(E) xhci_hcd(E) libata(E) sdhci_pltfm(E) cqhci(E) fixed(E) usbcore(E) scsi_mod(E) sdhci(E) host1x(E) [ 9.459211] CPU: 1 PID: 164 Comm: systemd-udevd Tainted: G S D W E 5.9.0-rc7-00298-gf6337624c4fe #1980 [ 9.469285] Hardware name: NVIDIA Jetson TX2 Developer Kit (DT) [ 9.475202] pstate: 80000005 (Nzcv daif -PAN -UAO BTYPE=--) [ 9.480784] pc : _regulator_put.part.0+0x16c/0x174 [ 9.485581] lr : regulator_put+0x44/0x60 [ 9.489501] sp : ffffffc011d837b0 [ 9.492814] x29: ffffffc011d837b0 x28: ffffff81dd085900 [ 9.498141] x27: ffffff81de1c8ec0 x26: ffffff81de1c8c10 [ 9.503464] x25: ffffff81dd085800 x24: ffffffc008f2c6b0 [ 9.508790] x23: ffffffc0117373f0 x22: 0000000000000005 [ 9.514101] x21: ffffff81dd085900 x20: ffffffc01172b098 [ 9.515822] ata1: SATA link down (SStatus 0 SControl 300) [ 9.519426] x19: ffffff81dd085100 x18: 0000000000000030 [ 9.530122] x17: 0000000000000000 x16: 0000000000000000 [ 9.535453] x15: 0000000000000000 x14: 000000000000038f [ 9.540777] x13: 0000000000000003 x12: 0000000000000040 [ 9.546105] x11: ffffff81eb800000 x10: 0000000000000ae0 [ 9.551417] x9 : ffffffc0106fea24 x8 : ffffff81de83e6c0 [ 9.556728] x7 : 0000000000000018 x6 : 00000000000003c3 [ 9.562064] x5 : 0000000000005660 x4 : 0000000000000000 [ 9.567392] x3 : ffffffc01172b388 x2 : ffffff81de83db80 [ 9.572702] x1 : 0000000000000000 x0 : 0000000000000001 [ 9.578034] Call trace: [ 9.580494] _regulator_put.part.0+0x16c/0x174 [ 9.584940] regulator_put+0x44/0x60 [ 9.588522] devm_regulator_release+0x20/0x2c [ 9.592885] release_nodes+0x1c8/0x2c0 [ 9.596636] devres_release_all+0x44/0x6c [ 9.600649] really_probe+0x1ec/0x504 [ 9.604316] driver_probe_device+0x100/0x170 [ 9.608589] device_driver_attach+0xcc/0xd4 [ 9.612774] __driver_attach+0xb0/0x17c [ 9.616614] bus_for_each_dev+0x7c/0xd4 [ 9.620450] driver_attach+0x30/0x3c [ 9.624027] bus_add_driver+0x154/0x250 [ 9.627867] driver_register+0x84/0x140 [ 9.631719] __platform_register_drivers+0xa0/0x180 [ 9.636660] host1x_drm_init+0x60/0x1000 [tegra_drm] [ 9.641629] do_one_initcall+0x54/0x2d0 [ 9.645490] do_init_module+0x68/0x29c [ 9.649244] load_module+0x2178/0x26c0 [ 9.652997] __do_sys_finit_module+0xb0/0x120 [ 9.657356] __arm64_sys_finit_module+0x2c/0x40 [ 9.661902] el0_svc_common.constprop.0+0x80/0x240 [ 9.666701] do_el0_svc+0x30/0xa0 [ 9.670022] el0_svc+0x18/0x50 [ 9.673081] el0_sync_handler+0x90/0x318 [ 9.677006] el0_sync+0x158/0x180 [ 9.680324] ---[ end trace 90f6c89d62d85ff6 ]--- Instead, let's register a callback that will disable the regulators on teardown. This allows for the removal of the .remove callbacks, which are not needed anymore. Signed-off-by: Marc Zyngier <maz@kernel.org> Signed-off-by: Thierry Reding <treding@nvidia.com>
1 parent cb7ff31 commit 5c1d644

1 file changed

Lines changed: 24 additions & 35 deletions

File tree

  • drivers/gpu/drm/tegra

drivers/gpu/drm/tegra/sor.c

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,6 @@ struct tegra_sor;
397397
struct tegra_sor_ops {
398398
const char *name;
399399
int (*probe)(struct tegra_sor *sor);
400-
int (*remove)(struct tegra_sor *sor);
401400
void (*audio_enable)(struct tegra_sor *sor);
402401
void (*audio_disable)(struct tegra_sor *sor);
403402
};
@@ -2942,6 +2941,24 @@ static const struct drm_encoder_helper_funcs tegra_sor_dp_helpers = {
29422941
.atomic_check = tegra_sor_encoder_atomic_check,
29432942
};
29442943

2944+
static void tegra_sor_disable_regulator(void *data)
2945+
{
2946+
struct regulator *reg = data;
2947+
2948+
regulator_disable(reg);
2949+
}
2950+
2951+
static int tegra_sor_enable_regulator(struct tegra_sor *sor, struct regulator *reg)
2952+
{
2953+
int err;
2954+
2955+
err = regulator_enable(reg);
2956+
if (err)
2957+
return err;
2958+
2959+
return devm_add_action_or_reset(sor->dev, tegra_sor_disable_regulator, reg);
2960+
}
2961+
29452962
static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
29462963
{
29472964
int err;
@@ -2953,7 +2970,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
29532970
return PTR_ERR(sor->avdd_io_supply);
29542971
}
29552972

2956-
err = regulator_enable(sor->avdd_io_supply);
2973+
err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);
29572974
if (err < 0) {
29582975
dev_err(sor->dev, "failed to enable AVDD I/O supply: %d\n",
29592976
err);
@@ -2967,7 +2984,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
29672984
return PTR_ERR(sor->vdd_pll_supply);
29682985
}
29692986

2970-
err = regulator_enable(sor->vdd_pll_supply);
2987+
err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);
29712988
if (err < 0) {
29722989
dev_err(sor->dev, "failed to enable VDD PLL supply: %d\n",
29732990
err);
@@ -2981,7 +2998,7 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
29812998
return PTR_ERR(sor->hdmi_supply);
29822999
}
29833000

2984-
err = regulator_enable(sor->hdmi_supply);
3001+
err = tegra_sor_enable_regulator(sor, sor->hdmi_supply);
29853002
if (err < 0) {
29863003
dev_err(sor->dev, "failed to enable HDMI supply: %d\n", err);
29873004
return err;
@@ -2992,19 +3009,9 @@ static int tegra_sor_hdmi_probe(struct tegra_sor *sor)
29923009
return 0;
29933010
}
29943011

2995-
static int tegra_sor_hdmi_remove(struct tegra_sor *sor)
2996-
{
2997-
regulator_disable(sor->hdmi_supply);
2998-
regulator_disable(sor->vdd_pll_supply);
2999-
regulator_disable(sor->avdd_io_supply);
3000-
3001-
return 0;
3002-
}
3003-
30043012
static const struct tegra_sor_ops tegra_sor_hdmi_ops = {
30053013
.name = "HDMI",
30063014
.probe = tegra_sor_hdmi_probe,
3007-
.remove = tegra_sor_hdmi_remove,
30083015
.audio_enable = tegra_sor_hdmi_audio_enable,
30093016
.audio_disable = tegra_sor_hdmi_audio_disable,
30103017
};
@@ -3017,33 +3024,24 @@ static int tegra_sor_dp_probe(struct tegra_sor *sor)
30173024
if (IS_ERR(sor->avdd_io_supply))
30183025
return PTR_ERR(sor->avdd_io_supply);
30193026

3020-
err = regulator_enable(sor->avdd_io_supply);
3027+
err = tegra_sor_enable_regulator(sor, sor->avdd_io_supply);
30213028
if (err < 0)
30223029
return err;
30233030

30243031
sor->vdd_pll_supply = devm_regulator_get(sor->dev, "vdd-hdmi-dp-pll");
30253032
if (IS_ERR(sor->vdd_pll_supply))
30263033
return PTR_ERR(sor->vdd_pll_supply);
30273034

3028-
err = regulator_enable(sor->vdd_pll_supply);
3035+
err = tegra_sor_enable_regulator(sor, sor->vdd_pll_supply);
30293036
if (err < 0)
30303037
return err;
30313038

30323039
return 0;
30333040
}
30343041

3035-
static int tegra_sor_dp_remove(struct tegra_sor *sor)
3036-
{
3037-
regulator_disable(sor->vdd_pll_supply);
3038-
regulator_disable(sor->avdd_io_supply);
3039-
3040-
return 0;
3041-
}
3042-
30433042
static const struct tegra_sor_ops tegra_sor_dp_ops = {
30443043
.name = "DP",
30453044
.probe = tegra_sor_dp_probe,
3046-
.remove = tegra_sor_dp_remove,
30473045
};
30483046

30493047
static int tegra_sor_init(struct host1x_client *client)
@@ -3773,7 +3771,7 @@ static int tegra_sor_probe(struct platform_device *pdev)
37733771
if (err < 0) {
37743772
dev_err(&pdev->dev, "failed to probe %s: %d\n",
37753773
sor->ops->name, err);
3776-
goto output;
3774+
goto remove;
37773775
}
37783776
}
37793777

@@ -3954,9 +3952,6 @@ static int tegra_sor_probe(struct platform_device *pdev)
39543952
rpm_disable:
39553953
pm_runtime_disable(&pdev->dev);
39563954
remove:
3957-
if (sor->ops && sor->ops->remove)
3958-
sor->ops->remove(sor);
3959-
output:
39603955
tegra_output_remove(&sor->output);
39613956
return err;
39623957
}
@@ -3975,12 +3970,6 @@ static int tegra_sor_remove(struct platform_device *pdev)
39753970

39763971
pm_runtime_disable(&pdev->dev);
39773972

3978-
if (sor->ops && sor->ops->remove) {
3979-
err = sor->ops->remove(sor);
3980-
if (err < 0)
3981-
dev_err(&pdev->dev, "failed to remove SOR: %d\n", err);
3982-
}
3983-
39843973
tegra_output_remove(&sor->output);
39853974

39863975
return 0;

0 commit comments

Comments
 (0)