Skip to content

Commit 37e2f2e

Browse files
committed
Merge tag 'drm/tegra/for-5.13-rc5' of ssh://git.freedesktop.org/git/tegra/linux into drm-fixes
drm/tegra: Fixes for v5.13-rc5 The most important change here fixes a race condition that causes either HDA or (more frequently) display to malfunction because they race for enabling the SOR power domain at probe time. Other than that, there's a couple of build warnings for issues introduced in v5.13 as well as some minor fixes, such as reference leak plugs. Signed-off-by: Dave Airlie <[email protected]> From: Thierry Reding <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2 parents d6273d8 + 671cc35 commit 37e2f2e

File tree

5 files changed

+92
-42
lines changed

5 files changed

+92
-42
lines changed

drivers/gpu/drm/tegra/drm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include "trace.h"
2626

2727
/* XXX move to include/uapi/drm/drm_fourcc.h? */
28-
#define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT(22)
28+
#define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT_ULL(22)
2929

3030
struct reset_control;
3131

drivers/gpu/drm/tegra/hub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
510510
* dGPU sector layout.
511511
*/
512512
if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU)
513-
base |= BIT(39);
513+
base |= BIT_ULL(39);
514514
#endif
515515

516516
tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);

drivers/gpu/drm/tegra/sor.c

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3125,21 +3125,21 @@ static int tegra_sor_init(struct host1x_client *client)
31253125
if (err < 0) {
31263126
dev_err(sor->dev, "failed to acquire SOR reset: %d\n",
31273127
err);
3128-
return err;
3128+
goto rpm_put;
31293129
}
31303130

31313131
err = reset_control_assert(sor->rst);
31323132
if (err < 0) {
31333133
dev_err(sor->dev, "failed to assert SOR reset: %d\n",
31343134
err);
3135-
return err;
3135+
goto rpm_put;
31363136
}
31373137
}
31383138

31393139
err = clk_prepare_enable(sor->clk);
31403140
if (err < 0) {
31413141
dev_err(sor->dev, "failed to enable clock: %d\n", err);
3142-
return err;
3142+
goto rpm_put;
31433143
}
31443144

31453145
usleep_range(1000, 3000);
@@ -3150,7 +3150,7 @@ static int tegra_sor_init(struct host1x_client *client)
31503150
dev_err(sor->dev, "failed to deassert SOR reset: %d\n",
31513151
err);
31523152
clk_disable_unprepare(sor->clk);
3153-
return err;
3153+
goto rpm_put;
31543154
}
31553155

31563156
reset_control_release(sor->rst);
@@ -3171,6 +3171,12 @@ static int tegra_sor_init(struct host1x_client *client)
31713171
}
31723172

31733173
return 0;
3174+
3175+
rpm_put:
3176+
if (sor->rst)
3177+
pm_runtime_put(sor->dev);
3178+
3179+
return err;
31743180
}
31753181

31763182
static int tegra_sor_exit(struct host1x_client *client)
@@ -3739,12 +3745,8 @@ static int tegra_sor_probe(struct platform_device *pdev)
37393745
if (!sor->aux)
37403746
return -EPROBE_DEFER;
37413747

3742-
if (get_device(&sor->aux->ddc.dev)) {
3743-
if (try_module_get(sor->aux->ddc.owner))
3744-
sor->output.ddc = &sor->aux->ddc;
3745-
else
3746-
put_device(&sor->aux->ddc.dev);
3747-
}
3748+
if (get_device(sor->aux->dev))
3749+
sor->output.ddc = &sor->aux->ddc;
37483750
}
37493751

37503752
if (!sor->aux) {
@@ -3772,12 +3774,13 @@ static int tegra_sor_probe(struct platform_device *pdev)
37723774

37733775
err = tegra_sor_parse_dt(sor);
37743776
if (err < 0)
3775-
return err;
3777+
goto put_aux;
37763778

37773779
err = tegra_output_probe(&sor->output);
3778-
if (err < 0)
3779-
return dev_err_probe(&pdev->dev, err,
3780-
"failed to probe output\n");
3780+
if (err < 0) {
3781+
dev_err_probe(&pdev->dev, err, "failed to probe output\n");
3782+
goto put_aux;
3783+
}
37813784

37823785
if (sor->ops && sor->ops->probe) {
37833786
err = sor->ops->probe(sor);
@@ -3916,17 +3919,10 @@ static int tegra_sor_probe(struct platform_device *pdev)
39163919
platform_set_drvdata(pdev, sor);
39173920
pm_runtime_enable(&pdev->dev);
39183921

3919-
INIT_LIST_HEAD(&sor->client.list);
3922+
host1x_client_init(&sor->client);
39203923
sor->client.ops = &sor_client_ops;
39213924
sor->client.dev = &pdev->dev;
39223925

3923-
err = host1x_client_register(&sor->client);
3924-
if (err < 0) {
3925-
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
3926-
err);
3927-
goto rpm_disable;
3928-
}
3929-
39303926
/*
39313927
* On Tegra210 and earlier, provide our own implementation for the
39323928
* pad output clock.
@@ -3938,13 +3934,13 @@ static int tegra_sor_probe(struct platform_device *pdev)
39383934
sor->index);
39393935
if (!name) {
39403936
err = -ENOMEM;
3941-
goto unregister;
3937+
goto uninit;
39423938
}
39433939

39443940
err = host1x_client_resume(&sor->client);
39453941
if (err < 0) {
39463942
dev_err(sor->dev, "failed to resume: %d\n", err);
3947-
goto unregister;
3943+
goto uninit;
39483944
}
39493945

39503946
sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
@@ -3955,17 +3951,30 @@ static int tegra_sor_probe(struct platform_device *pdev)
39553951
err = PTR_ERR(sor->clk_pad);
39563952
dev_err(sor->dev, "failed to register SOR pad clock: %d\n",
39573953
err);
3958-
goto unregister;
3954+
goto uninit;
3955+
}
3956+
3957+
err = __host1x_client_register(&sor->client);
3958+
if (err < 0) {
3959+
dev_err(&pdev->dev, "failed to register host1x client: %d\n",
3960+
err);
3961+
goto uninit;
39593962
}
39603963

39613964
return 0;
39623965

3963-
unregister:
3964-
host1x_client_unregister(&sor->client);
3965-
rpm_disable:
3966+
uninit:
3967+
host1x_client_exit(&sor->client);
39663968
pm_runtime_disable(&pdev->dev);
39673969
remove:
3970+
if (sor->aux)
3971+
sor->output.ddc = NULL;
3972+
39683973
tegra_output_remove(&sor->output);
3974+
put_aux:
3975+
if (sor->aux)
3976+
put_device(sor->aux->dev);
3977+
39693978
return err;
39703979
}
39713980

@@ -3983,6 +3992,11 @@ static int tegra_sor_remove(struct platform_device *pdev)
39833992

39843993
pm_runtime_disable(&pdev->dev);
39853994

3995+
if (sor->aux) {
3996+
put_device(sor->aux->dev);
3997+
sor->output.ddc = NULL;
3998+
}
3999+
39864000
tegra_output_remove(&sor->output);
39874001

39884002
return 0;

drivers/gpu/host1x/bus.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,29 @@ void host1x_driver_unregister(struct host1x_driver *driver)
735735
}
736736
EXPORT_SYMBOL(host1x_driver_unregister);
737737

738+
/**
739+
* __host1x_client_init() - initialize a host1x client
740+
* @client: host1x client
741+
* @key: lock class key for the client-specific mutex
742+
*/
743+
void __host1x_client_init(struct host1x_client *client, struct lock_class_key *key)
744+
{
745+
INIT_LIST_HEAD(&client->list);
746+
__mutex_init(&client->lock, "host1x client lock", key);
747+
client->usecount = 0;
748+
}
749+
EXPORT_SYMBOL(__host1x_client_init);
750+
751+
/**
752+
* host1x_client_exit() - uninitialize a host1x client
753+
* @client: host1x client
754+
*/
755+
void host1x_client_exit(struct host1x_client *client)
756+
{
757+
mutex_destroy(&client->lock);
758+
}
759+
EXPORT_SYMBOL(host1x_client_exit);
760+
738761
/**
739762
* __host1x_client_register() - register a host1x client
740763
* @client: host1x client
@@ -747,16 +770,11 @@ EXPORT_SYMBOL(host1x_driver_unregister);
747770
* device and call host1x_device_init(), which will in turn call each client's
748771
* &host1x_client_ops.init implementation.
749772
*/
750-
int __host1x_client_register(struct host1x_client *client,
751-
struct lock_class_key *key)
773+
int __host1x_client_register(struct host1x_client *client)
752774
{
753775
struct host1x *host1x;
754776
int err;
755777

756-
INIT_LIST_HEAD(&client->list);
757-
__mutex_init(&client->lock, "host1x client lock", key);
758-
client->usecount = 0;
759-
760778
mutex_lock(&devices_lock);
761779

762780
list_for_each_entry(host1x, &devices, list) {

include/linux/host1x.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -332,12 +332,30 @@ static inline struct host1x_device *to_host1x_device(struct device *dev)
332332
int host1x_device_init(struct host1x_device *device);
333333
int host1x_device_exit(struct host1x_device *device);
334334

335-
int __host1x_client_register(struct host1x_client *client,
336-
struct lock_class_key *key);
337-
#define host1x_client_register(class) \
338-
({ \
339-
static struct lock_class_key __key; \
340-
__host1x_client_register(class, &__key); \
335+
void __host1x_client_init(struct host1x_client *client, struct lock_class_key *key);
336+
void host1x_client_exit(struct host1x_client *client);
337+
338+
#define host1x_client_init(client) \
339+
({ \
340+
static struct lock_class_key __key; \
341+
__host1x_client_init(client, &__key); \
342+
})
343+
344+
int __host1x_client_register(struct host1x_client *client);
345+
346+
/*
347+
* Note that this wrapper calls __host1x_client_init() for compatibility
348+
* with existing callers. Callers that want to separately initialize and
349+
* register a host1x client must first initialize using either of the
350+
* __host1x_client_init() or host1x_client_init() functions and then use
351+
* the low-level __host1x_client_register() function to avoid the client
352+
* getting reinitialized.
353+
*/
354+
#define host1x_client_register(client) \
355+
({ \
356+
static struct lock_class_key __key; \
357+
__host1x_client_init(client, &__key); \
358+
__host1x_client_register(client); \
341359
})
342360

343361
int host1x_client_unregister(struct host1x_client *client);

0 commit comments

Comments
 (0)