drm/nouveau/disp/dp: remove workqueue for link training
authorBen Skeggs <bskeggs@redhat.com>
Fri, 4 Nov 2016 07:20:35 +0000 (17:20 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 7 Nov 2016 04:04:41 +0000 (14:04 +1000)
There haven't been any callers from an atomic context for a while now,
so let's remove the extra complexity.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dport.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/outpdp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c

index 9688970..4a93ceb 100644 (file)
@@ -319,9 +319,8 @@ static const struct dp_rates {
 };
 
 void
-nvkm_dp_train(struct work_struct *w)
+nvkm_dp_train(struct nvkm_output_dp *outp)
 {
-       struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work);
        struct nv50_disp *disp = nv50_disp(outp->base.disp);
        const struct dp_rates *cfg = nvkm_dp_rates;
        struct dp_state _dp = {
@@ -353,9 +352,6 @@ nvkm_dp_train(struct work_struct *w)
        }
        cfg--;
 
-       /* disable link interrupt handling during link training */
-       nvkm_notify_put(&outp->irq);
-
        /* ensure sink is not in a low-power state */
        if (!nvkm_rdaux(outp->aux, DPCD_SC00, &pwr, 1)) {
                if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
@@ -400,9 +396,6 @@ nvkm_dp_train(struct work_struct *w)
 
        dp_link_train_fini(dp);
 
-       /* signal completion and enable link interrupt handling */
        OUTP_DBG(&outp->base, "training complete");
        atomic_set(&outp->lt.done, 1);
-       wake_up(&outp->lt.wait);
-       nvkm_notify_get(&outp->irq);
 }
index 6e10c5e..baf1dd9 100644 (file)
@@ -1,6 +1,6 @@
 #ifndef __NVKM_DISP_DPORT_H__
 #define __NVKM_DISP_DPORT_H__
-#include <core/os.h>
+struct nvkm_output_dp;
 
 /* DPCD Receiver Capabilities */
 #define DPCD_RC00_DPCD_REV                                              0x00000
@@ -77,5 +77,5 @@
 #define DPCD_SC00_SET_POWER_D0                                             0x01
 #define DPCD_SC00_SET_POWER_D3                                             0x03
 
-void nvkm_dp_train(struct work_struct *);
+void nvkm_dp_train(struct nvkm_output_dp *);
 #endif
index 29e84b2..0face69 100644 (file)
@@ -314,7 +314,7 @@ gf119_disp_intr_unk2_2(struct nv50_disp *disp, int head)
                        break;
                }
 
-               if (nvkm_output_dp_train(outp, pclk, true))
+               if (nvkm_output_dp_train(outp, pclk))
                        OUTP_ERR(outp, "link not trained before attach");
        } else {
                if (disp->func->sor.magic)
index fbb8c7d..a2bd0f0 100644 (file)
@@ -779,7 +779,7 @@ nv50_disp_intr_unk20_2(struct nv50_disp *disp, int head)
                        break;
                }
 
-               if (nvkm_output_dp_train(outp, datarate / soff, true))
+               if (nvkm_output_dp_train(outp, datarate / soff))
                        OUTP_ERR(outp, "link not trained before attach");
        }
 
index 3b7a9e7..de36f73 100644 (file)
@@ -31,7 +31,7 @@
 #include <nvif/event.h>
 
 int
-nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
+nvkm_output_dp_train(struct nvkm_output *base, u32 datarate)
 {
        struct nvkm_output_dp *outp = nvkm_output_dp(base);
        bool retrain = true;
@@ -39,6 +39,8 @@ nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait)
        u32 linkrate;
        int ret, i;
 
+       mutex_lock(&outp->mutex);
+
        /* check that the link is trained at a high enough rate */
        ret = nvkm_rdaux(outp->aux, DPCD_LC00_LINK_BW_SET, link, 2);
        if (ret) {
@@ -88,19 +90,10 @@ done:
                        outp->dpcd[DPCD_RC02] =
                                outp->base.info.dpconf.link_nr;
                }
-               atomic_set(&outp->lt.done, 0);
-               schedule_work(&outp->lt.work);
-       } else {
-               nvkm_notify_get(&outp->irq);
-       }
-
-       if (wait) {
-               if (!wait_event_timeout(outp->lt.wait,
-                                       atomic_read(&outp->lt.done),
-                                       msecs_to_jiffies(2000)))
-                       ret = -ETIMEDOUT;
+               nvkm_dp_train(outp);
        }
 
+       mutex_unlock(&outp->mutex);
        return ret;
 }
 
@@ -118,7 +111,7 @@ nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool enable)
 
                if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dpcd,
                                sizeof(outp->dpcd))) {
-                       nvkm_output_dp_train(&outp->base, 0, true);
+                       nvkm_output_dp_train(&outp->base, 0);
                        return;
                }
        }
@@ -165,10 +158,10 @@ nvkm_output_dp_irq(struct nvkm_notify *notify)
        };
 
        OUTP_DBG(&outp->base, "IRQ: %d", line->mask);
-       nvkm_output_dp_train(&outp->base, 0, true);
+       nvkm_output_dp_train(&outp->base, 0);
 
        nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep));
-       return NVKM_NOTIFY_DROP;
+       return NVKM_NOTIFY_KEEP;
 }
 
 static void
@@ -177,7 +170,6 @@ nvkm_output_dp_fini(struct nvkm_output *base)
        struct nvkm_output_dp *outp = nvkm_output_dp(base);
        nvkm_notify_put(&outp->hpd);
        nvkm_notify_put(&outp->irq);
-       flush_work(&outp->lt.work);
        nvkm_output_dp_enable(outp, false);
 }
 
@@ -187,6 +179,7 @@ nvkm_output_dp_init(struct nvkm_output *base)
        struct nvkm_output_dp *outp = nvkm_output_dp(base);
        nvkm_notify_put(&outp->base.conn->hpd);
        nvkm_output_dp_enable(outp, true);
+       nvkm_notify_get(&outp->irq);
        nvkm_notify_get(&outp->hpd);
 }
 
@@ -238,11 +231,6 @@ nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func,
        OUTP_DBG(&outp->base, "bios dp %02x %02x %02x %02x",
                 outp->version, hdr, cnt, len);
 
-       /* link training */
-       INIT_WORK(&outp->lt.work, nvkm_dp_train);
-       init_waitqueue_head(&outp->lt.wait);
-       atomic_set(&outp->lt.done, 0);
-
        /* link maintenance */
        ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_irq, true,
                               &(struct nvkm_i2c_ntfy_req) {
@@ -257,6 +245,9 @@ nvkm_output_dp_ctor(const struct nvkm_output_dp_func *func,
                return ret;
        }
 
+       mutex_init(&outp->mutex);
+       atomic_set(&outp->lt.done, 0);
+
        /* hotplug detect, replaces gpio-based mechanism with aux events */
        ret = nvkm_notify_init(NULL, &i2c->event, nvkm_output_dp_hpd, true,
                               &(struct nvkm_i2c_ntfy_req) {
index 4e983f6..7b63d97 100644 (file)
@@ -29,9 +29,8 @@ struct nvkm_output_dp {
        bool present;
        u8 dpcd[16];
 
+       struct mutex mutex;
        struct {
-               struct work_struct work;
-               wait_queue_head_t wait;
                atomic_t done;
        } lt;
 };
@@ -43,7 +42,7 @@ struct nvkm_output_dp_func {
        int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc);
 };
 
-int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait);
+int nvkm_output_dp_train(struct nvkm_output *, u32 rate);
 
 int nvkm_output_dp_ctor(const struct nvkm_output_dp_func *, struct nvkm_disp *,
                        int index, struct dcb_output *, struct nvkm_i2c_aux *,
index 6424b39..e9548e4 100644 (file)
@@ -173,7 +173,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
                                return 0;
                        } else
                        if (args->v0.state != 0) {
-                               nvkm_output_dp_train(&outpdp->base, 0, true);
+                               nvkm_output_dp_train(&outpdp->base, 0);
                                return 0;
                        }
                } else