Ben Skeggs
2023-Jul-19 04:40 UTC
[Nouveau] [PATCH 1/3] drm/nouveau/i2c: fix number of aux event slots
From: Ben Skeggs <bskeggs at redhat.com> This was completely bogus before, using maximum DCB device index rather than maximum AUX ID to size the buffer that stores event refcounts. *Pretty* unlikely to have been an actual problem on most configurations, that is, unless you've got one of the rare boards that have off-chip DP. There, it'll likely crash. Signed-off-by: Ben Skeggs <bskeggs at redhat.com> --- drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h | 4 ++-- drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h index 40a1065ae626..ef441dfdea09 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h @@ -16,7 +16,7 @@ struct nvkm_i2c_bus { const struct nvkm_i2c_bus_func *func; struct nvkm_i2c_pad *pad; #define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n) -#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) +#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10) #define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1 #define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2 int id; @@ -38,7 +38,7 @@ struct nvkm_i2c_aux { const struct nvkm_i2c_aux_func *func; struct nvkm_i2c_pad *pad; #define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n) -#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) +#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10) int id; struct mutex mutex; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 976539de4220..731b2f68d3db 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, { struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c; + struct nvkm_i2c_aux *aux; struct dcb_i2c_entry ccbE; struct dcb_output dcbE; u8 ver, hdr; - int ret, i; + int ret, i, ids; if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) return -ENOMEM; @@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, } } - return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event); + ids = 0; + list_for_each_entry(aux, &i2c->aux, head) + ids = max(ids, aux->id + 1); + if (!ids) + return 0; + + return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event); } -- 2.41.0
Ben Skeggs
2023-Jul-19 04:40 UTC
[Nouveau] [PATCH 2/3] drm/nouveau/disp: PIOR DP uses GPIO for HPD, not PMGR AUX interrupts
From: Ben Skeggs <bskeggs at redhat.com> Fixes crash on boards with ANX9805 TMDS/DP encoders. Signed-off-by: Ben Skeggs <bskeggs at redhat.com> --- .../gpu/drm/nouveau/nvkm/engine/disp/uconn.c | 27 ++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c index dad942be6679..46b057fe1412 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_ return -ENOSYS; list_for_each_entry(outp, &conn->disp->outps, head) { - if (outp->info.connector == conn->index && outp->dp.aux) { - if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; - if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; - if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + if (outp->info.connector == conn->index) + break; + } - return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, - nvkm_uconn_uevent_aux); - } + if (&outp->head == &conn->disp->outps) + return -EINVAL; + + if (outp->dp.aux && !outp->info.location) { + if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ; + + return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits, + nvkm_uconn_uevent_aux); } if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI; if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO; - if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) - return -EINVAL; + if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) { + /* TODO: support DP IRQ on ANX9805 and remove this hack. */ + if (!outp->info.location) + return -EINVAL; + } return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits, nvkm_uconn_uevent_gpio); -- 2.41.0
Ben Skeggs
2023-Jul-19 04:40 UTC
[Nouveau] [PATCH 3/3] drm/nouveau/kms/nv50-: init hpd_irq_lock for PIOR DP
From: Ben Skeggs <bskeggs at redhat.com> Fixes OOPS on boards with ANX9805 DP encoders. Signed-off-by: Ben Skeggs <bskeggs at redhat.com> --- drivers/gpu/drm/nouveau/dispnv50/disp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 42e1665ba11a..1ecd3d63b108 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -1873,6 +1873,8 @@ nv50_pior_destroy(struct drm_encoder *encoder) nvif_outp_dtor(&nv_encoder->outp); drm_encoder_cleanup(encoder); + + mutex_destroy(&nv_encoder->dp.hpd_irq_lock); kfree(encoder); } @@ -1917,6 +1919,8 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) nv_encoder->i2c = ddc; nv_encoder->aux = aux; + mutex_init(&nv_encoder->dp.hpd_irq_lock); + encoder = to_drm_encoder(nv_encoder); encoder->possible_crtcs = dcbe->heads; encoder->possible_clones = 0; -- 2.41.0
Karol Herbst
2023-Jul-19 09:00 UTC
[Nouveau] [PATCH 1/3] drm/nouveau/i2c: fix number of aux event slots
On Wed, Jul 19, 2023 at 6:41?AM Ben Skeggs <skeggsb at gmail.com> wrote:> > From: Ben Skeggs <bskeggs at redhat.com> > > This was completely bogus before, using maximum DCB device index rather > than maximum AUX ID to size the buffer that stores event refcounts. > > *Pretty* unlikely to have been an actual problem on most configurations, > that is, unless you've got one of the rare boards that have off-chip DP. > > There, it'll likely crash. > > Signed-off-by: Ben Skeggs <bskeggs at redhat.com> > --- > drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h | 4 ++-- > drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c | 11 +++++++++-- > 2 files changed, 11 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h > index 40a1065ae626..ef441dfdea09 100644 > --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h > +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h > @@ -16,7 +16,7 @@ struct nvkm_i2c_bus { > const struct nvkm_i2c_bus_func *func; > struct nvkm_i2c_pad *pad; > #define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n) > -#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) > +#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10) > #define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1 > #define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2 > int id; > @@ -38,7 +38,7 @@ struct nvkm_i2c_aux { > const struct nvkm_i2c_aux_func *func; > struct nvkm_i2c_pad *pad; > #define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n) > -#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100) > +#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10) > int id; > > struct mutex mutex; > diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c > index 976539de4220..731b2f68d3db 100644 > --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c > +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c > @@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, > { > struct nvkm_bios *bios = device->bios; > struct nvkm_i2c *i2c; > + struct nvkm_i2c_aux *aux; > struct dcb_i2c_entry ccbE; > struct dcb_output dcbE; > u8 ver, hdr; > - int ret, i; > + int ret, i, ids; > > if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL))) > return -ENOMEM; > @@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device, > } > } > > - return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event); > + ids = 0; > + list_for_each_entry(aux, &i2c->aux, head) > + ids = max(ids, aux->id + 1); > + if (!ids) > + return 0; > + > + return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event); > } > -- > 2.41.0 >Reviewed-by: Karol Herbst <kherbst at redhat.com>