drm/nouveau/i2c: Enable i2c pads & busses during preinit [Linux 4.9.187]

This Linux kernel change "drm/nouveau/i2c: Enable i2c pads & busses during preinit" is included in the Linux 4.9.187 release. This change is authored by Lyude Paul <lyude [at] redhat.com> on Wed Jun 26 14:10:27 2019 -0400. The commit for this change in Linux stable tree is 0e0d33f (patch) which is from upstream commit 7cb95ee. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 7cb95ee.

drm/nouveau/i2c: Enable i2c pads & busses during preinit

commit 7cb95eeea6706c790571042a06782e378b2561ea upstream.

It turns out that while disabling i2c bus access from software when the
GPU is suspended was a step in the right direction with:

commit 342406e4fbba ("drm/nouveau/i2c: Disable i2c bus access after
->fini()")

We also ended up accidentally breaking the vbios init scripts on some
older Tesla GPUs, as apparently said scripts can actually use the i2c
bus. Since these scripts are executed before initializing any
subdevices, we end up failing to acquire access to the i2c bus which has
left a number of cards with their fan controllers uninitialized. Luckily
this doesn't break hardware - it just means the fan gets stuck at 100%.

This also means that we've always been using our i2c busses before
initializing them during the init scripts for older GPUs, we just didn't
notice it until we started preventing them from being used until init.
It's pretty impressive this never caused us any issues before!

So, fix this by initializing our i2c pad and busses during subdev
pre-init. We skip initializing aux busses during pre-init, as those are
guaranteed to only ever be used by nouveau for DP aux transactions.

Signed-off-by: Lyude Paul <[email protected]>
Tested-by: Marc Meledandri <[email protected]>
Fixes: 342406e4fbba ("drm/nouveau/i2c: Disable i2c bus access after ->fini()")
Cc: [email protected]
Signed-off-by: Ben Skeggs <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

There are 20 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
index ecacb22..7193450 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
@@ -185,6 +185,25 @@ struct nvkm_i2c_aux *
 }

 static int
+nvkm_i2c_preinit(struct nvkm_subdev *subdev)
+{
+   struct nvkm_i2c *i2c = nvkm_i2c(subdev);
+   struct nvkm_i2c_bus *bus;
+   struct nvkm_i2c_pad *pad;
+
+   /*
+    * We init our i2c busses as early as possible, since they may be
+    * needed by the vbios init scripts on some cards
+    */
+   list_for_each_entry(pad, &i2c->pad, head)
+       nvkm_i2c_pad_init(pad);
+   list_for_each_entry(bus, &i2c->bus, head)
+       nvkm_i2c_bus_init(bus);
+
+   return 0;
+}
+
+static int
 nvkm_i2c_init(struct nvkm_subdev *subdev)
 {
    struct nvkm_i2c *i2c = nvkm_i2c(subdev);
@@ -238,6 +257,7 @@ struct nvkm_i2c_aux *
 static const struct nvkm_subdev_func
 nvkm_i2c = {
    .dtor = nvkm_i2c_dtor,
+   .preinit = nvkm_i2c_preinit,
    .init = nvkm_i2c_init,
    .fini = nvkm_i2c_fini,
    .intr = nvkm_i2c_intr,

Leave a Reply

Your email address will not be published. Required fields are marked *