linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook
@ 2021-11-30 23:09 Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 1/4] gpu/host1x: Add init/deinit callbacks to host1x driver framework Dmitry Osipenko
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Dmitry Osipenko @ 2021-11-30 23:09 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Lyude Paul, David Airlie,
	Daniel Vetter, Thomas Graichen
  Cc: dri-devel, linux-tegra, linux-kernel

This patchset restores regressed SOR driver probing on Nyan Chromebook.

Changelog:

v2: - Changed host1x and Tegra DRM drivers such that DRM device is
      registered early now. This removes the need to change DRM core.

    - Introduced dev_err_probe() patch again. Previously Thierry rejected
      it, saying that he likes his variant more, but I kept that patch in
      grate kernel and it happened to be very handy to have because I
      instantly identified the problem in the DP AUX driver with it,
      which would've been much more difficult to do otherwise.
      Please apply it this time.

Dmitry Osipenko (4):
  gpu/host1x: Add init/deinit callbacks to host1x driver framework
  drm/tegra: Create DRM device early
  drm/tegra: dpaux: Restore DP AUX DDC registration order
  drm/tegra: Use dev_err_probe()

 drivers/gpu/drm/tegra/dc.c    | 13 +++-------
 drivers/gpu/drm/tegra/dpaux.c | 26 +++++++++++++-------
 drivers/gpu/drm/tegra/drm.c   | 46 +++++++++++++++++++++++++----------
 drivers/gpu/drm/tegra/drm.h   |  2 ++
 drivers/gpu/drm/tegra/hdmi.c  | 34 +++++++-------------------
 drivers/gpu/host1x/bus.c      | 15 ++++++++++++
 include/linux/host1x.h        |  4 +++
 7 files changed, 83 insertions(+), 57 deletions(-)

-- 
2.33.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/4] gpu/host1x: Add init/deinit callbacks to host1x driver framework
  2021-11-30 23:09 [PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook Dmitry Osipenko
@ 2021-11-30 23:09 ` Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 2/4] drm/tegra: Create DRM device early Dmitry Osipenko
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Osipenko @ 2021-11-30 23:09 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Lyude Paul, David Airlie,
	Daniel Vetter, Thomas Graichen
  Cc: dri-devel, linux-tegra, linux-kernel

Add init/deinit callbacks to host1x driver framework which allow to
perform early pre-initialization required by Tegra DRM driver.

Cc: <stable@vger.kernel.org> # 5.13+
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/host1x/bus.c | 15 +++++++++++++++
 include/linux/host1x.h   |  4 ++++
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c
index 0d81eede1217..25d688e5c742 100644
--- a/drivers/gpu/host1x/bus.c
+++ b/drivers/gpu/host1x/bus.c
@@ -479,8 +479,18 @@ static int host1x_device_add(struct host1x *host1x,
 	device->dev.dma_parms = &device->dma_parms;
 	dma_set_max_seg_size(&device->dev, UINT_MAX);
 
+	if (driver->init) {
+		err = driver->init(device);
+		if (err < 0) {
+			kfree(device);
+			return err;
+		}
+	}
+
 	err = host1x_device_parse_dt(device, driver);
 	if (err < 0) {
+		if (driver->deinit)
+			driver->deinit(device);
 		kfree(device);
 		return err;
 	}
@@ -512,11 +522,16 @@ static int host1x_device_add(struct host1x *host1x,
 static void host1x_device_del(struct host1x *host1x,
 			      struct host1x_device *device)
 {
+	struct host1x_driver *driver = device->driver;
+
 	if (device->registered) {
 		device->registered = false;
 		device_del(&device->dev);
 	}
 
+	if (driver->deinit)
+		driver->deinit(device);
+
 	put_device(&device->dev);
 }
 
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index e8dc5bc41f79..5e5ba33af4ae 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -346,6 +346,8 @@ struct host1x_device;
  * @driver: core driver
  * @subdevs: table of OF device IDs matching subdevices for this driver
  * @list: list node for the driver
+ * @init: called when the host1x logical driver is registered
+ * @deinit: called when the host1x logical driver is unregistered
  * @probe: called when the host1x logical device is probed
  * @remove: called when the host1x logical device is removed
  * @shutdown: called when the host1x logical device is shut down
@@ -356,6 +358,8 @@ struct host1x_driver {
 	const struct of_device_id *subdevs;
 	struct list_head list;
 
+	int (*init)(struct host1x_device *device);
+	void (*deinit)(struct host1x_device *device);
 	int (*probe)(struct host1x_device *device);
 	int (*remove)(struct host1x_device *device);
 	void (*shutdown)(struct host1x_device *device);
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/4] drm/tegra: Create DRM device early
  2021-11-30 23:09 [PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 1/4] gpu/host1x: Add init/deinit callbacks to host1x driver framework Dmitry Osipenko
@ 2021-11-30 23:09 ` Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 3/4] drm/tegra: dpaux: Restore DP AUX DDC registration order Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 4/4] drm/tegra: Use dev_err_probe() Dmitry Osipenko
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Osipenko @ 2021-11-30 23:09 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Lyude Paul, David Airlie,
	Daniel Vetter, Thomas Graichen
  Cc: dri-devel, linux-tegra, linux-kernel

DRM sub-drivers need to access DRM device early during first stage of
drivers' probing. Use new host1x init/deinit callbacks to create DRM
device early and destroy late.

Cc: <stable@vger.kernel.org> # 5.13+
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/drm.c | 46 ++++++++++++++++++++++++++-----------
 drivers/gpu/drm/tegra/drm.h |  2 ++
 2 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index e9de91a4e7e8..e9cbcaf6e017 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1133,21 +1133,42 @@ static bool host1x_drm_wants_iommu(struct host1x_device *dev)
 	return domain != NULL;
 }
 
-static int host1x_drm_probe(struct host1x_device *dev)
+static struct drm_device *terga_drm_dev;
+
+struct drm_device *tegra_drm_device(void)
 {
-	struct tegra_drm *tegra;
-	struct drm_device *drm;
-	int err;
+	return terga_drm_dev;
+}
 
-	drm = drm_dev_alloc(&tegra_drm_driver, &dev->dev);
+static int host1x_drm_dev_init(struct host1x_device *dev)
+{
+	struct drm_device *drm = drm_dev_alloc(&tegra_drm_driver, &dev->dev);
 	if (IS_ERR(drm))
 		return PTR_ERR(drm);
 
+	dev_set_drvdata(&dev->dev, drm);
+	terga_drm_dev = drm;
+
+	return 0;
+}
+
+static void host1x_drm_dev_deinit(struct host1x_device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(&dev->dev);
+
+	terga_drm_dev = NULL;
+	drm_dev_put(drm);
+}
+
+static int host1x_drm_probe(struct host1x_device *dev)
+{
+	struct drm_device *drm = dev_get_drvdata(&dev->dev);
+	struct tegra_drm *tegra;
+	int err;
+
 	tegra = kzalloc(sizeof(*tegra), GFP_KERNEL);
-	if (!tegra) {
-		err = -ENOMEM;
-		goto put;
-	}
+	if (!tegra)
+		return -ENOMEM;
 
 	if (host1x_drm_wants_iommu(dev) && iommu_present(&platform_bus_type)) {
 		tegra->domain = iommu_domain_alloc(&platform_bus_type);
@@ -1164,7 +1185,6 @@ static int host1x_drm_probe(struct host1x_device *dev)
 	mutex_init(&tegra->clients_lock);
 	INIT_LIST_HEAD(&tegra->clients);
 
-	dev_set_drvdata(&dev->dev, drm);
 	drm->dev_private = tegra;
 	tegra->drm = drm;
 
@@ -1285,8 +1305,7 @@ static int host1x_drm_probe(struct host1x_device *dev)
 		iommu_domain_free(tegra->domain);
 free:
 	kfree(tegra);
-put:
-	drm_dev_put(drm);
+
 	return err;
 }
 
@@ -1319,7 +1338,6 @@ static int host1x_drm_remove(struct host1x_device *dev)
 	}
 
 	kfree(tegra);
-	drm_dev_put(drm);
 
 	return 0;
 }
@@ -1391,6 +1409,8 @@ static struct host1x_driver host1x_drm_driver = {
 	.probe = host1x_drm_probe,
 	.remove = host1x_drm_remove,
 	.subdevs = host1x_drm_subdevs,
+	.init = host1x_drm_dev_init,
+	.deinit = host1x_drm_dev_deinit,
 };
 
 static struct platform_driver * const drivers[] = {
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index fc0a19554eac..8b7c9508070f 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -121,6 +121,8 @@ int tegra_drm_unregister_client(struct tegra_drm *tegra,
 int host1x_client_iommu_attach(struct host1x_client *client);
 void host1x_client_iommu_detach(struct host1x_client *client);
 
+struct drm_device *tegra_drm_device(void);
+
 int tegra_drm_init(struct tegra_drm *tegra, struct drm_device *drm);
 int tegra_drm_exit(struct tegra_drm *tegra);
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/4] drm/tegra: dpaux: Restore DP AUX DDC registration order
  2021-11-30 23:09 [PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 1/4] gpu/host1x: Add init/deinit callbacks to host1x driver framework Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 2/4] drm/tegra: Create DRM device early Dmitry Osipenko
@ 2021-11-30 23:09 ` Dmitry Osipenko
  2021-11-30 23:09 ` [PATCH v2 4/4] drm/tegra: Use dev_err_probe() Dmitry Osipenko
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Osipenko @ 2021-11-30 23:09 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Lyude Paul, David Airlie,
	Daniel Vetter, Thomas Graichen
  Cc: dri-devel, linux-tegra, linux-kernel

Restore DP AUX I2C DDC registration order by moving registration to
DP AUX driver probe phase. This fixes broken display panel driver of
Acer Chromebook CB5-311 that fails to probe starting with v5.13 kernel
when DP AUX registration order was changed to prevent accessing
uninitialized aux->drm_dev. Tegra SOR driver is never probed now using
the new registration order because tegra-output always fails with
-EPROBE_DEFER due to missing display panel that requires DP AUX DDC to
be registered first. The offending commit made DDC to be registered after
SOR's output, which can't ever happen. Use new tegra_drm_device() helper
that allows to set aux->drm_dev during DP AUX probe, restoring the DCC
registration order and reviving display panel.

Cc: <stable@vger.kernel.org> # 5.13+
Fixes: 39c17ae60ea9 ("drm/tegra: Don't register DP AUX channels before connectors")
Reported-by: Thomas Graichen <thomas.graichen@gmail.com> # T124 Nyan Big
Tested-by: Thomas Graichen <thomas.graichen@gmail.com> # T124 Nyan Big
Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dpaux.c | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 1f96e416fa08..148d3c00dd8e 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -530,9 +530,12 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
 	disable_irq(dpaux->irq);
 
 	dpaux->aux.transfer = tegra_dpaux_transfer;
+	dpaux->aux.drm_dev = tegra_drm_device();
 	dpaux->aux.dev = &pdev->dev;
 
-	drm_dp_aux_init(&dpaux->aux);
+	err = drm_dp_aux_register(&dpaux->aux);
+	if (err < 0)
+		goto put_pm;
 
 	/*
 	 * Assume that by default the DPAUX/I2C pads will be used for HDMI,
@@ -544,7 +547,7 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
 	 */
 	err = tegra_dpaux_pad_config(dpaux, DPAUX_PADCTL_FUNC_I2C);
 	if (err < 0)
-		return err;
+		goto dp_aux_unreg;
 
 #ifdef CONFIG_GENERIC_PINCONF
 	dpaux->desc.name = dev_name(&pdev->dev);
@@ -557,7 +560,8 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
 	dpaux->pinctrl = devm_pinctrl_register(&pdev->dev, &dpaux->desc, dpaux);
 	if (IS_ERR(dpaux->pinctrl)) {
 		dev_err(&pdev->dev, "failed to register pincontrol\n");
-		return PTR_ERR(dpaux->pinctrl);
+		err = PTR_ERR(dpaux->pinctrl);
+		goto dp_aux_unreg;
 	}
 #endif
 	/* enable and clear all interrupts */
@@ -571,6 +575,14 @@ static int tegra_dpaux_probe(struct platform_device *pdev)
 	mutex_unlock(&dpaux_lock);
 
 	return 0;
+
+dp_aux_unreg:
+	drm_dp_aux_unregister(&dpaux->aux);
+put_pm:
+	pm_runtime_put_sync(&pdev->dev);
+	pm_runtime_disable(&pdev->dev);
+
+	return err;
 }
 
 static int tegra_dpaux_remove(struct platform_device *pdev)
@@ -579,6 +591,8 @@ static int tegra_dpaux_remove(struct platform_device *pdev)
 
 	cancel_work_sync(&dpaux->work);
 
+	drm_dp_aux_unregister(&dpaux->aux);
+
 	/* make sure pads are powered down when not in use */
 	tegra_dpaux_pad_power_down(dpaux);
 
@@ -717,11 +731,6 @@ int drm_dp_aux_attach(struct drm_dp_aux *aux, struct tegra_output *output)
 	unsigned long timeout;
 	int err;
 
-	aux->drm_dev = output->connector.dev;
-	err = drm_dp_aux_register(aux);
-	if (err < 0)
-		return err;
-
 	output->connector.polled = DRM_CONNECTOR_POLL_HPD;
 	dpaux->output = output;
 
@@ -759,7 +768,6 @@ int drm_dp_aux_detach(struct drm_dp_aux *aux)
 	unsigned long timeout;
 	int err;
 
-	drm_dp_aux_unregister(aux);
 	disable_irq(dpaux->irq);
 
 	if (dpaux->output->panel) {
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 4/4] drm/tegra: Use dev_err_probe()
  2021-11-30 23:09 [PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2021-11-30 23:09 ` [PATCH v2 3/4] drm/tegra: dpaux: Restore DP AUX DDC registration order Dmitry Osipenko
@ 2021-11-30 23:09 ` Dmitry Osipenko
  3 siblings, 0 replies; 5+ messages in thread
From: Dmitry Osipenko @ 2021-11-30 23:09 UTC (permalink / raw)
  To: Thierry Reding, Jonathan Hunter, Lyude Paul, David Airlie,
	Daniel Vetter, Thomas Graichen
  Cc: dri-devel, linux-tegra, linux-kernel

Replace dev_printk() with a generic dev_err_probe() helper which silences
noisy error messages about deferred probe and makes easy to debug failing
deferred probe by printing notification about the failure to KMSG in the
end of kernel booting process and by adding failing device and the reason
of deferred probe to devices_deferred of debugfs. This was proven to be
useful in the case of eDP driver regression by immediately showing why
display driver was failing when user asked for help, otherwise it would've
been much more difficult to debug such problems on a third party device
that doesn't have developer setup.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 drivers/gpu/drm/tegra/dc.c   | 13 +++----------
 drivers/gpu/drm/tegra/hdmi.c | 34 +++++++++-------------------------
 2 files changed, 12 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 7ea3c045a6f7..f7370d28816f 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -3236,16 +3236,9 @@ static int tegra_dc_probe(struct platform_device *pdev)
 		return -ENXIO;
 
 	err = tegra_dc_rgb_probe(dc);
-	if (err < 0 && err != -ENODEV) {
-		const char *level = KERN_ERR;
-
-		if (err == -EPROBE_DEFER)
-			level = KERN_DEBUG;
-
-		dev_printk(level, dc->dev, "failed to probe RGB output: %d\n",
-			   err);
-		return err;
-	}
+	if (err < 0 && err != -ENODEV)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to probe RGB output\n");
 
 	platform_set_drvdata(pdev, dc);
 	pm_runtime_enable(&pdev->dev);
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 9a87d351a828..3242baddc5e7 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1638,7 +1638,6 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data)
 
 static int tegra_hdmi_probe(struct platform_device *pdev)
 {
-	const char *level = KERN_ERR;
 	struct tegra_hdmi *hdmi;
 	struct resource *regs;
 	int err;
@@ -1678,36 +1677,21 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
 
 	hdmi->hdmi = devm_regulator_get(&pdev->dev, "hdmi");
 	err = PTR_ERR_OR_ZERO(hdmi->hdmi);
-	if (err) {
-		if (err == -EPROBE_DEFER)
-			level = KERN_DEBUG;
-
-		dev_printk(level, &pdev->dev,
-			   "failed to get HDMI regulator: %d\n", err);
-		return err;
-	}
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to get HDMI regulator\n");
 
 	hdmi->pll = devm_regulator_get(&pdev->dev, "pll");
 	err = PTR_ERR_OR_ZERO(hdmi->pll);
-	if (err) {
-		if (err == -EPROBE_DEFER)
-			level = KERN_DEBUG;
-
-		dev_printk(level, &pdev->dev,
-			   "failed to get PLL regulator: %d\n", err);
-		return err;
-	}
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to get PLL regulator\n");
 
 	hdmi->vdd = devm_regulator_get(&pdev->dev, "vdd");
 	err = PTR_ERR_OR_ZERO(hdmi->vdd);
-	if (err) {
-		if (err == -EPROBE_DEFER)
-			level = KERN_DEBUG;
-
-		dev_printk(level, &pdev->dev,
-			   "failed to get VDD regulator: %d\n", err);
-		return err;
-	}
+	if (err)
+		return dev_err_probe(&pdev->dev, err,
+				     "failed to get VDD regulator\n");
 
 	hdmi->output.dev = &pdev->dev;
 
-- 
2.33.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-11-30 23:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-30 23:09 [PATCH v2 0/4] Restore Tegra DRM on Nyan Big Chromebook Dmitry Osipenko
2021-11-30 23:09 ` [PATCH v2 1/4] gpu/host1x: Add init/deinit callbacks to host1x driver framework Dmitry Osipenko
2021-11-30 23:09 ` [PATCH v2 2/4] drm/tegra: Create DRM device early Dmitry Osipenko
2021-11-30 23:09 ` [PATCH v2 3/4] drm/tegra: dpaux: Restore DP AUX DDC registration order Dmitry Osipenko
2021-11-30 23:09 ` [PATCH v2 4/4] drm/tegra: Use dev_err_probe() Dmitry Osipenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).