diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/core/include/core/device.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/core/subdev/device/base.c | 38 |
2 files changed, 38 insertions, 16 deletions
diff --git a/drivers/gpu/drm/nouveau/core/include/core/device.h b/drivers/gpu/drm/nouveau/core/include/core/device.h index 57899fc3b87..e58b6f0984c 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/device.h +++ b/drivers/gpu/drm/nouveau/core/include/core/device.h | |||
@@ -8,11 +8,23 @@ | |||
8 | enum nv_subdev_type { | 8 | enum nv_subdev_type { |
9 | NVDEV_SUBDEV_DEVICE, | 9 | NVDEV_SUBDEV_DEVICE, |
10 | NVDEV_SUBDEV_VBIOS, | 10 | NVDEV_SUBDEV_VBIOS, |
11 | |||
12 | /* All subdevs from DEVINIT to DEVINIT_LAST will be created before | ||
13 | * *any* of them are initialised. This subdev category is used | ||
14 | * for any subdevs that the VBIOS init table parsing may call out | ||
15 | * to during POST. | ||
16 | */ | ||
17 | NVDEV_SUBDEV_DEVINIT, | ||
11 | NVDEV_SUBDEV_GPIO, | 18 | NVDEV_SUBDEV_GPIO, |
12 | NVDEV_SUBDEV_I2C, | 19 | NVDEV_SUBDEV_I2C, |
13 | NVDEV_SUBDEV_CLOCK, | 20 | NVDEV_SUBDEV_CLOCK, |
21 | NVDEV_SUBDEV_DEVINIT_LAST = NVDEV_SUBDEV_CLOCK, | ||
22 | |||
23 | /* This grouping of subdevs are initialised right after they've | ||
24 | * been created, and are allowed to assume any subdevs in the | ||
25 | * list above them exist and have been initialised. | ||
26 | */ | ||
14 | NVDEV_SUBDEV_MXM, | 27 | NVDEV_SUBDEV_MXM, |
15 | NVDEV_SUBDEV_DEVINIT, | ||
16 | NVDEV_SUBDEV_MC, | 28 | NVDEV_SUBDEV_MC, |
17 | NVDEV_SUBDEV_TIMER, | 29 | NVDEV_SUBDEV_TIMER, |
18 | NVDEV_SUBDEV_FB, | 30 | NVDEV_SUBDEV_FB, |
@@ -23,6 +35,7 @@ enum nv_subdev_type { | |||
23 | NVDEV_SUBDEV_BAR, | 35 | NVDEV_SUBDEV_BAR, |
24 | NVDEV_SUBDEV_VOLT, | 36 | NVDEV_SUBDEV_VOLT, |
25 | NVDEV_SUBDEV_THERM, | 37 | NVDEV_SUBDEV_THERM, |
38 | |||
26 | NVDEV_ENGINE_DMAOBJ, | 39 | NVDEV_ENGINE_DMAOBJ, |
27 | NVDEV_ENGINE_FIFO, | 40 | NVDEV_ENGINE_FIFO, |
28 | NVDEV_ENGINE_SW, | 41 | NVDEV_ENGINE_SW, |
@@ -38,6 +51,7 @@ enum nv_subdev_type { | |||
38 | NVDEV_ENGINE_UNK1C1, | 51 | NVDEV_ENGINE_UNK1C1, |
39 | NVDEV_ENGINE_VENC, | 52 | NVDEV_ENGINE_VENC, |
40 | NVDEV_ENGINE_DISP, | 53 | NVDEV_ENGINE_DISP, |
54 | |||
41 | NVDEV_SUBDEV_NR, | 55 | NVDEV_SUBDEV_NR, |
42 | }; | 56 | }; |
43 | 57 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/device/base.c b/drivers/gpu/drm/nouveau/core/subdev/device/base.c index 7bf6f3760b9..ca9a4648bd8 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/device/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/device/base.c | |||
@@ -96,14 +96,13 @@ nouveau_devobj_ctor(struct nouveau_object *parent, | |||
96 | struct nouveau_object **pobject) | 96 | struct nouveau_object **pobject) |
97 | { | 97 | { |
98 | struct nouveau_client *client = nv_client(parent); | 98 | struct nouveau_client *client = nv_client(parent); |
99 | struct nouveau_object *subdev = NULL; | ||
100 | struct nouveau_device *device; | 99 | struct nouveau_device *device; |
101 | struct nouveau_devobj *devobj; | 100 | struct nouveau_devobj *devobj; |
102 | struct nv_device_class *args = data; | 101 | struct nv_device_class *args = data; |
103 | u64 disable, boot0, strap; | 102 | u64 disable, boot0, strap; |
104 | u64 mmio_base, mmio_size; | 103 | u64 mmio_base, mmio_size; |
105 | void __iomem *map; | 104 | void __iomem *map; |
106 | int ret, i; | 105 | int ret, i, c; |
107 | 106 | ||
108 | if (size < sizeof(struct nv_device_class)) | 107 | if (size < sizeof(struct nv_device_class)) |
109 | return -EINVAL; | 108 | return -EINVAL; |
@@ -234,34 +233,43 @@ nouveau_devobj_ctor(struct nouveau_object *parent, | |||
234 | } | 233 | } |
235 | 234 | ||
236 | /* ensure requested subsystems are available for use */ | 235 | /* ensure requested subsystems are available for use */ |
237 | for (i = 0; i < NVDEV_SUBDEV_NR; i++) { | 236 | for (i = 0, c = 0; i < NVDEV_SUBDEV_NR; i++) { |
238 | if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) | 237 | if (!(oclass = device->oclass[i]) || (disable & (1ULL << i))) |
239 | continue; | 238 | continue; |
240 | 239 | ||
241 | if (!device->subdev[i]) { | 240 | if (!device->subdev[i]) { |
242 | ret = nouveau_object_ctor(nv_object(device), NULL, | 241 | ret = nouveau_object_ctor(nv_object(device), NULL, |
243 | oclass, NULL, i, &subdev); | 242 | oclass, NULL, i, |
243 | &devobj->subdev[i]); | ||
244 | if (ret == -ENODEV) | 244 | if (ret == -ENODEV) |
245 | continue; | 245 | continue; |
246 | if (ret) | 246 | if (ret) |
247 | return ret; | 247 | return ret; |
248 | 248 | ||
249 | if (nv_iclass(subdev, NV_ENGINE_CLASS)) | 249 | if (nv_iclass(devobj->subdev[i], NV_ENGINE_CLASS)) |
250 | nouveau_subdev_reset(subdev); | 250 | nouveau_subdev_reset(devobj->subdev[i]); |
251 | } else { | 251 | } else { |
252 | nouveau_object_ref(device->subdev[i], &subdev); | 252 | nouveau_object_ref(device->subdev[i], |
253 | &devobj->subdev[i]); | ||
253 | } | 254 | } |
254 | 255 | ||
255 | if (!nv_iclass(subdev, NV_ENGINE_CLASS)) { | 256 | /* note: can't init *any* subdevs until devinit has been run |
256 | ret = nouveau_object_inc(subdev); | 257 | * due to not knowing exactly what the vbios init tables will |
257 | if (ret) { | 258 | * mess with. devinit also can't be run until all of its |
258 | nouveau_object_ref(NULL, &subdev); | 259 | * dependencies have been created. |
259 | return ret; | 260 | * |
261 | * this code delays init of any subdev until all of devinit's | ||
262 | * dependencies have been created, and then initialises each | ||
263 | * subdev in turn as they're created. | ||
264 | */ | ||
265 | while (i >= NVDEV_SUBDEV_DEVINIT_LAST && c <= i) { | ||
266 | struct nouveau_object *subdev = devobj->subdev[c++]; | ||
267 | if (subdev && !nv_iclass(subdev, NV_ENGINE_CLASS)) { | ||
268 | ret = nouveau_object_inc(subdev); | ||
269 | if (ret) | ||
270 | return ret; | ||
260 | } | 271 | } |
261 | } | 272 | } |
262 | |||
263 | nouveau_object_ref(subdev, &devobj->subdev[i]); | ||
264 | nouveau_object_ref(NULL, &subdev); | ||
265 | } | 273 | } |
266 | 274 | ||
267 | return 0; | 275 | return 0; |