Commit 37e2f2e8 authored by Dave Airlie's avatar Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@redhat.com>

From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210603144624.788861-1-thierry.reding@gmail.com
parents d6273d8f 671cc352
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
#include "trace.h"

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

struct reset_control;

+1 −1
Original line number Diff line number Diff line
@@ -510,7 +510,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
	 * dGPU sector layout.
	 */
	if (tegra_plane_state->tiling.sector_layout == TEGRA_BO_SECTOR_LAYOUT_GPU)
		base |= BIT(39);
		base |= BIT_ULL(39);
#endif

	tegra_plane_writel(p, tegra_plane_state->format, DC_WIN_COLOR_DEPTH);
+42 −28
Original line number Diff line number Diff line
@@ -3125,21 +3125,21 @@ static int tegra_sor_init(struct host1x_client *client)
		if (err < 0) {
			dev_err(sor->dev, "failed to acquire SOR reset: %d\n",
				err);
			return err;
			goto rpm_put;
		}

		err = reset_control_assert(sor->rst);
		if (err < 0) {
			dev_err(sor->dev, "failed to assert SOR reset: %d\n",
				err);
			return err;
			goto rpm_put;
		}
	}

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

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

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

	return 0;

rpm_put:
	if (sor->rst)
		pm_runtime_put(sor->dev);

	return err;
}

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

		if (get_device(&sor->aux->ddc.dev)) {
			if (try_module_get(sor->aux->ddc.owner))
		if (get_device(sor->aux->dev))
			sor->output.ddc = &sor->aux->ddc;
			else
				put_device(&sor->aux->ddc.dev);
		}
	}

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

	err = tegra_sor_parse_dt(sor);
	if (err < 0)
		return err;
		goto put_aux;

	err = tegra_output_probe(&sor->output);
	if (err < 0)
		return dev_err_probe(&pdev->dev, err,
				     "failed to probe output\n");
	if (err < 0) {
		dev_err_probe(&pdev->dev, err, "failed to probe output\n");
		goto put_aux;
	}

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

	INIT_LIST_HEAD(&sor->client.list);
	host1x_client_init(&sor->client);
	sor->client.ops = &sor_client_ops;
	sor->client.dev = &pdev->dev;

	err = host1x_client_register(&sor->client);
	if (err < 0) {
		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
			err);
		goto rpm_disable;
	}

	/*
	 * On Tegra210 and earlier, provide our own implementation for the
	 * pad output clock.
@@ -3938,13 +3934,13 @@ static int tegra_sor_probe(struct platform_device *pdev)
				      sor->index);
		if (!name) {
			err = -ENOMEM;
			goto unregister;
			goto uninit;
		}

		err = host1x_client_resume(&sor->client);
		if (err < 0) {
			dev_err(sor->dev, "failed to resume: %d\n", err);
			goto unregister;
			goto uninit;
		}

		sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
@@ -3955,17 +3951,30 @@ static int tegra_sor_probe(struct platform_device *pdev)
		err = PTR_ERR(sor->clk_pad);
		dev_err(sor->dev, "failed to register SOR pad clock: %d\n",
			err);
		goto unregister;
		goto uninit;
	}

	err = __host1x_client_register(&sor->client);
	if (err < 0) {
		dev_err(&pdev->dev, "failed to register host1x client: %d\n",
			err);
		goto uninit;
	}

	return 0;

unregister:
	host1x_client_unregister(&sor->client);
rpm_disable:
uninit:
	host1x_client_exit(&sor->client);
	pm_runtime_disable(&pdev->dev);
remove:
	if (sor->aux)
		sor->output.ddc = NULL;

	tegra_output_remove(&sor->output);
put_aux:
	if (sor->aux)
		put_device(sor->aux->dev);

	return err;
}

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

	pm_runtime_disable(&pdev->dev);

	if (sor->aux) {
		put_device(sor->aux->dev);
		sor->output.ddc = NULL;
	}

	tegra_output_remove(&sor->output);

	return 0;
+24 −6
Original line number Diff line number Diff line
@@ -735,6 +735,29 @@ void host1x_driver_unregister(struct host1x_driver *driver)
}
EXPORT_SYMBOL(host1x_driver_unregister);

/**
 * __host1x_client_init() - initialize a host1x client
 * @client: host1x client
 * @key: lock class key for the client-specific mutex
 */
void __host1x_client_init(struct host1x_client *client, struct lock_class_key *key)
{
	INIT_LIST_HEAD(&client->list);
	__mutex_init(&client->lock, "host1x client lock", key);
	client->usecount = 0;
}
EXPORT_SYMBOL(__host1x_client_init);

/**
 * host1x_client_exit() - uninitialize a host1x client
 * @client: host1x client
 */
void host1x_client_exit(struct host1x_client *client)
{
	mutex_destroy(&client->lock);
}
EXPORT_SYMBOL(host1x_client_exit);

/**
 * __host1x_client_register() - register a host1x client
 * @client: host1x client
@@ -747,16 +770,11 @@ EXPORT_SYMBOL(host1x_driver_unregister);
 * device and call host1x_device_init(), which will in turn call each client's
 * &host1x_client_ops.init implementation.
 */
int __host1x_client_register(struct host1x_client *client,
			     struct lock_class_key *key)
int __host1x_client_register(struct host1x_client *client)
{
	struct host1x *host1x;
	int err;

	INIT_LIST_HEAD(&client->list);
	__mutex_init(&client->lock, "host1x client lock", key);
	client->usecount = 0;

	mutex_lock(&devices_lock);

	list_for_each_entry(host1x, &devices, list) {
+24 −6
Original line number Diff line number Diff line
@@ -332,12 +332,30 @@ static inline struct host1x_device *to_host1x_device(struct device *dev)
int host1x_device_init(struct host1x_device *device);
int host1x_device_exit(struct host1x_device *device);

int __host1x_client_register(struct host1x_client *client,
			     struct lock_class_key *key);
#define host1x_client_register(class) \
void __host1x_client_init(struct host1x_client *client, struct lock_class_key *key);
void host1x_client_exit(struct host1x_client *client);

#define host1x_client_init(client)			\
	({						\
		static struct lock_class_key __key;	\
		__host1x_client_init(client, &__key);	\
	})

int __host1x_client_register(struct host1x_client *client);

/*
 * Note that this wrapper calls __host1x_client_init() for compatibility
 * with existing callers. Callers that want to separately initialize and
 * register a host1x client must first initialize using either of the
 * __host1x_client_init() or host1x_client_init() functions and then use
 * the low-level __host1x_client_register() function to avoid the client
 * getting reinitialized.
 */
#define host1x_client_register(client)			\
	({						\
		static struct lock_class_key __key;	\
		__host1x_client_register(class, &__key); \
		__host1x_client_init(client, &__key);	\
		__host1x_client_register(client);	\
	})

int host1x_client_unregister(struct host1x_client *client);