Karol Herbst
2015-Nov-14 17:27 UTC
[Nouveau] [PATCH] pmu: fix queued messages while getting no IRQ
I encountered while stresstesting the reclocking code, that rarely (1 out of 20.000+ requests) we don't get any IRQ in nvkm_pmu_intr. This means we have a queued message on the pmu, but nouveau doesn't read it and waits infinitely in nvkm_pmu_send: if (reply) { wait_event(pmu->recv.wait, (pmu->recv.process == 0)); therefore let us use wait_event_timeout with a 1s timeout frame and just check whether there is a message queued and handle it if there is one. Return -ETIMEDOUT whenever we timed out and there is no message queued or when we hit another timeout while trying to read the message without getting any IRQ The benefit of not using wait_event is, that we don't have a kworker waiting on an event, which makes it easier to reload the module at runtime, which helps me developing on nouveau on my laptop a lot, because I don't need to reboot anymore Nethertheless, we shouldn't use wait_event here, because we can't guarantee any answere at all, can we? Signed-off-by: Karol Herbst <nouveau at karolherbst.de> --- drm/nouveau/nvkm/subdev/pmu/base.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/drm/nouveau/nvkm/subdev/pmu/base.c b/drm/nouveau/nvkm/subdev/pmu/base.c index 6b2007f..f917293 100644 --- a/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drm/nouveau/nvkm/subdev/pmu/base.c @@ -89,10 +89,35 @@ nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2], /* wait for reply, if requested */ if (reply) { - wait_event(pmu->recv.wait, (pmu->recv.process == 0)); - reply[0] = pmu->recv.data[0]; - reply[1] = pmu->recv.data[1]; - mutex_unlock(&subdev->mutex); + if (wait_event_timeout(pmu->recv.wait, (pmu->recv.process == 0), msecs_to_jiffies(1000)) != 0) { + reply[0] = pmu->recv.data[0]; + reply[1] = pmu->recv.data[1]; + mutex_unlock(&subdev->mutex); + return 0; + } else { + u32 addr = nvkm_rd32(device, 0x10a4cc); + nvkm_error(subdev, "wait on reply timed out\n"); + + if (addr != nvkm_rd32(device, 0x10a4c8)) { + nvkm_error(subdev, "found queued message without getting an interrupt\n"); + schedule_work(&pmu->recv.work); + if (wait_event_timeout(pmu->recv.wait, (pmu->recv.process == 0), msecs_to_jiffies(1000)) != 0) { + reply[0] = pmu->recv.data[0]; + reply[1] = pmu->recv.data[1]; + mutex_unlock(&subdev->mutex); + return 0; + } else { + reply[0] = 0; + reply[1] = 0; + nvkm_error(subdev, "failed to repair PMU state\n"); + } + } + + mutex_unlock(&subdev->mutex); + /* we return an error even if we repaired the state, because we + can't be sure the data is usefull */ + return -ETIMEDOUT; + } } return 0; -- 2.6.3
Maybe Matching Threads
- [PATCH v3] pmu: fix queued messages while getting no IRQ
- [PATCH v2] pmu: fix queued messages while getting no IRQ
- [PATCH 0/2] PMU communications improvements
- [PATCH] drm/nouveau/pmu: don't print reply values if exec is false
- [PATCH AUTOSEL 4.19 203/671] drm/nouveau/pmu: don't print reply values if exec is false