aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Courbot <acourbot@nvidia.com>2017-02-22 06:48:30 -0500
committerBen Skeggs <bskeggs@redhat.com>2017-03-07 02:05:12 -0500
commit9e4397579fa4cd5cc411d47815eb805e337d0203 (patch)
treeeb9985d5865f45b44299e76c99a9c01bce09c2df
parent65d9376b74ff651a8d4c6736d32a3bb3aa47bf09 (diff)
drm/nouveau/falcon: delay construction of falcons to oneinit()
Reading registers at device construction time can be harmful, as there is no guarantee the underlying engine will be up, or in its runtime configuration. Defer register reading to the oneinit() hook and update users accordingly. Signed-off-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/base.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c10
4 files changed, 32 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
index 9384dff81494..b04d3a0e82e6 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
@@ -46,8 +46,14 @@ struct nvkm_falcon {
46 struct nvkm_engine engine; 46 struct nvkm_engine engine;
47}; 47};
48 48
49/* This constructor must be called from the owner's oneinit() hook and
50 * *not* its constructor. This is to ensure that DEVINIT has been
51 * completed, and that the device is correctly enabled before we touch
52 * falcon registers.
53 */
49int nvkm_falcon_v1_new(struct nvkm_subdev *owner, const char *name, u32 addr, 54int nvkm_falcon_v1_new(struct nvkm_subdev *owner, const char *name, u32 addr,
50 struct nvkm_falcon **); 55 struct nvkm_falcon **);
56
51void nvkm_falcon_del(struct nvkm_falcon **); 57void nvkm_falcon_del(struct nvkm_falcon **);
52int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *); 58int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *);
53void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *); 59void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index f9acb8a944d2..a4410ef19db5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -1647,8 +1647,18 @@ static int
1647gf100_gr_oneinit(struct nvkm_gr *base) 1647gf100_gr_oneinit(struct nvkm_gr *base)
1648{ 1648{
1649 struct gf100_gr *gr = gf100_gr(base); 1649 struct gf100_gr *gr = gf100_gr(base);
1650 struct nvkm_device *device = gr->base.engine.subdev.device; 1650 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1651 struct nvkm_device *device = subdev->device;
1651 int i, j; 1652 int i, j;
1653 int ret;
1654
1655 ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs);
1656 if (ret)
1657 return ret;
1658
1659 ret = nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs);
1660 if (ret)
1661 return ret;
1652 1662
1653 nvkm_pmu_pgob(device->pmu, false); 1663 nvkm_pmu_pgob(device->pmu, false);
1654 1664
@@ -1856,24 +1866,13 @@ int
1856gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device, 1866gf100_gr_ctor(const struct gf100_gr_func *func, struct nvkm_device *device,
1857 int index, struct gf100_gr *gr) 1867 int index, struct gf100_gr *gr)
1858{ 1868{
1859 struct nvkm_subdev *subdev = &gr->base.engine.subdev;
1860 int ret;
1861
1862 gr->func = func; 1869 gr->func = func;
1863 gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW", 1870 gr->firmware = nvkm_boolopt(device->cfgopt, "NvGrUseFW",
1864 func->fecs.ucode == NULL); 1871 func->fecs.ucode == NULL);
1865 1872
1866 ret = nvkm_gr_ctor(&gf100_gr_, device, index, 1873 return nvkm_gr_ctor(&gf100_gr_, device, index,
1867 gr->firmware || func->fecs.ucode != NULL, 1874 gr->firmware || func->fecs.ucode != NULL,
1868 &gr->base); 1875 &gr->base);
1869 if (ret)
1870 return ret;
1871
1872 ret = nvkm_falcon_v1_new(subdev, "FECS", 0x409000, &gr->fecs);
1873 if (ret)
1874 return ret;
1875
1876 return nvkm_falcon_v1_new(subdev, "GPCCS", 0x41a000, &gr->gpccs);
1877} 1876}
1878 1877
1879int 1878int
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
index ee25fdc21e1f..19b9d44ae1a9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
@@ -137,6 +137,9 @@ nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
137void 137void
138nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user) 138nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
139{ 139{
140 if (unlikely(!falcon))
141 return;
142
140 mutex_lock(&falcon->mutex); 143 mutex_lock(&falcon->mutex);
141 if (falcon->user == user) { 144 if (falcon->user == user) {
142 nvkm_debug(falcon->user, "released %s falcon\n", falcon->name); 145 nvkm_debug(falcon->user, "released %s falcon\n", falcon->name);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index 1871a92e8f2f..3306f9fe7140 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -115,6 +115,13 @@ nvkm_pmu_init(struct nvkm_subdev *subdev)
115 return ret; 115 return ret;
116} 116}
117 117
118static int
119nvkm_pmu_oneinit(struct nvkm_subdev *subdev)
120{
121 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
122 return nvkm_falcon_v1_new(&pmu->subdev, "PMU", 0x10a000, &pmu->falcon);
123}
124
118static void * 125static void *
119nvkm_pmu_dtor(struct nvkm_subdev *subdev) 126nvkm_pmu_dtor(struct nvkm_subdev *subdev)
120{ 127{
@@ -128,6 +135,7 @@ static const struct nvkm_subdev_func
128nvkm_pmu = { 135nvkm_pmu = {
129 .dtor = nvkm_pmu_dtor, 136 .dtor = nvkm_pmu_dtor,
130 .preinit = nvkm_pmu_preinit, 137 .preinit = nvkm_pmu_preinit,
138 .oneinit = nvkm_pmu_oneinit,
131 .init = nvkm_pmu_init, 139 .init = nvkm_pmu_init,
132 .fini = nvkm_pmu_fini, 140 .fini = nvkm_pmu_fini,
133 .intr = nvkm_pmu_intr, 141 .intr = nvkm_pmu_intr,
@@ -141,7 +149,7 @@ nvkm_pmu_ctor(const struct nvkm_pmu_func *func, struct nvkm_device *device,
141 pmu->func = func; 149 pmu->func = func;
142 INIT_WORK(&pmu->recv.work, nvkm_pmu_recv); 150 INIT_WORK(&pmu->recv.work, nvkm_pmu_recv);
143 init_waitqueue_head(&pmu->recv.wait); 151 init_waitqueue_head(&pmu->recv.wait);
144 return nvkm_falcon_v1_new(&pmu->subdev, "PMU", 0x10a000, &pmu->falcon); 152 return 0;
145} 153}
146 154
147int 155int