diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_abi16.c | 5 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 31 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_chan.c | 35 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_chan.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.c | 22 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drm.h | 1 |
7 files changed, 72 insertions, 26 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 9e6ced3b941a..cc79c796afee 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
| @@ -264,6 +264,11 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) | |||
| 264 | abi16->handles |= (1 << init->channel); | 264 | abi16->handles |= (1 << init->channel); |
| 265 | 265 | ||
| 266 | /* create channel object and initialise dma and fence management */ | 266 | /* create channel object and initialise dma and fence management */ |
| 267 | if (device->card_type >= NV_E0) { | ||
| 268 | init->fb_ctxdma_handle = NVE0_CHANNEL_IND_ENGINE_GR; | ||
| 269 | init->tt_ctxdma_handle = 0; | ||
| 270 | } | ||
| 271 | |||
| 267 | ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | | 272 | ret = nouveau_channel_new(drm, cli, NVDRM_DEVICE, NVDRM_CHAN | |
| 268 | init->channel, init->fb_ctxdma_handle, | 273 | init->channel, init->fb_ctxdma_handle, |
| 269 | init->tt_ctxdma_handle, &chan->chan); | 274 | init->tt_ctxdma_handle, &chan->chan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index ef96bdbb5255..259e5f1adf47 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
| @@ -571,6 +571,18 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
| 571 | } | 571 | } |
| 572 | 572 | ||
| 573 | static int | 573 | static int |
| 574 | nve0_bo_move_init(struct nouveau_channel *chan, u32 handle) | ||
| 575 | { | ||
| 576 | int ret = RING_SPACE(chan, 2); | ||
| 577 | if (ret == 0) { | ||
| 578 | BEGIN_NVC0(chan, NvSubCopy, 0x0000, 1); | ||
| 579 | OUT_RING (chan, handle); | ||
| 580 | FIRE_RING (chan); | ||
| 581 | } | ||
| 582 | return ret; | ||
| 583 | } | ||
| 584 | |||
| 585 | static int | ||
| 574 | nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | 586 | nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, |
| 575 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) | 587 | struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem) |
| 576 | { | 588 | { |
| @@ -991,10 +1003,8 @@ out: | |||
| 991 | } | 1003 | } |
| 992 | 1004 | ||
| 993 | void | 1005 | void |
| 994 | nouveau_bo_move_init(struct nouveau_channel *chan) | 1006 | nouveau_bo_move_init(struct nouveau_drm *drm) |
| 995 | { | 1007 | { |
| 996 | struct nouveau_cli *cli = chan->cli; | ||
| 997 | struct nouveau_drm *drm = chan->drm; | ||
| 998 | static const struct { | 1008 | static const struct { |
| 999 | const char *name; | 1009 | const char *name; |
| 1000 | int engine; | 1010 | int engine; |
| @@ -1004,7 +1014,8 @@ nouveau_bo_move_init(struct nouveau_channel *chan) | |||
| 1004 | struct ttm_mem_reg *, struct ttm_mem_reg *); | 1014 | struct ttm_mem_reg *, struct ttm_mem_reg *); |
| 1005 | int (*init)(struct nouveau_channel *, u32 handle); | 1015 | int (*init)(struct nouveau_channel *, u32 handle); |
| 1006 | } _methods[] = { | 1016 | } _methods[] = { |
| 1007 | { "COPY", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init }, | 1017 | { "COPY", 0, 0xa0b5, nve0_bo_move_copy, nve0_bo_move_init }, |
| 1018 | { "GRCE", 0, 0xa0b5, nve0_bo_move_copy, nvc0_bo_move_init }, | ||
| 1008 | { "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init }, | 1019 | { "COPY1", 5, 0x90b8, nvc0_bo_move_copy, nvc0_bo_move_init }, |
| 1009 | { "COPY0", 4, 0x90b5, nvc0_bo_move_copy, nvc0_bo_move_init }, | 1020 | { "COPY0", 4, 0x90b5, nvc0_bo_move_copy, nvc0_bo_move_init }, |
| 1010 | { "COPY", 0, 0x85b5, nva3_bo_move_copy, nv50_bo_move_init }, | 1021 | { "COPY", 0, 0x85b5, nva3_bo_move_copy, nv50_bo_move_init }, |
| @@ -1020,14 +1031,22 @@ nouveau_bo_move_init(struct nouveau_channel *chan) | |||
| 1020 | 1031 | ||
| 1021 | do { | 1032 | do { |
| 1022 | struct nouveau_object *object; | 1033 | struct nouveau_object *object; |
| 1034 | struct nouveau_channel *chan; | ||
| 1023 | u32 handle = (mthd->engine << 16) | mthd->oclass; | 1035 | u32 handle = (mthd->engine << 16) | mthd->oclass; |
| 1024 | 1036 | ||
| 1025 | ret = nouveau_object_new(nv_object(cli), chan->handle, handle, | 1037 | if (mthd->init == nve0_bo_move_init) |
| 1038 | chan = drm->cechan; | ||
| 1039 | else | ||
| 1040 | chan = drm->channel; | ||
| 1041 | if (chan == NULL) | ||
| 1042 | continue; | ||
| 1043 | |||
| 1044 | ret = nouveau_object_new(nv_object(drm), chan->handle, handle, | ||
| 1026 | mthd->oclass, NULL, 0, &object); | 1045 | mthd->oclass, NULL, 0, &object); |
| 1027 | if (ret == 0) { | 1046 | if (ret == 0) { |
| 1028 | ret = mthd->init(chan, handle); | 1047 | ret = mthd->init(chan, handle); |
| 1029 | if (ret) { | 1048 | if (ret) { |
| 1030 | nouveau_object_del(nv_object(cli), | 1049 | nouveau_object_del(nv_object(drm), |
| 1031 | chan->handle, handle); | 1050 | chan->handle, handle); |
| 1032 | continue; | 1051 | continue; |
| 1033 | } | 1052 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index c42aea9fb546..dec51b1098fe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h | |||
| @@ -61,7 +61,7 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo) | |||
| 61 | 61 | ||
| 62 | extern struct ttm_bo_driver nouveau_bo_driver; | 62 | extern struct ttm_bo_driver nouveau_bo_driver; |
| 63 | 63 | ||
| 64 | void nouveau_bo_move_init(struct nouveau_channel *); | 64 | void nouveau_bo_move_init(struct nouveau_drm *); |
| 65 | int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags, | 65 | int nouveau_bo_new(struct drm_device *, int size, int align, u32 flags, |
| 66 | u32 tile_mode, u32 tile_flags, struct sg_table *sg, | 66 | u32 tile_mode, u32 tile_flags, struct sg_table *sg, |
| 67 | struct nouveau_bo **); | 67 | struct nouveau_bo **); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index b1eea19d99a6..62c7edf08e5a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c | |||
| @@ -184,7 +184,8 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nouveau_cli *cli, | |||
| 184 | 184 | ||
| 185 | int | 185 | int |
| 186 | nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, | 186 | nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, |
| 187 | u32 parent, u32 handle, struct nouveau_channel **pchan) | 187 | u32 parent, u32 handle, u32 engine, |
| 188 | struct nouveau_channel **pchan) | ||
| 188 | { | 189 | { |
| 189 | static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 }; | 190 | static const u16 oclasses[] = { 0xa06f, 0x906f, 0x826f, 0x506f, 0 }; |
| 190 | const u16 *oclass = oclasses; | 191 | const u16 *oclass = oclasses; |
| @@ -202,7 +203,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nouveau_cli *cli, | |||
| 202 | args.pushbuf = chan->push.handle; | 203 | args.pushbuf = chan->push.handle; |
| 203 | args.ioffset = 0x10000 + chan->push.vma.offset; | 204 | args.ioffset = 0x10000 + chan->push.vma.offset; |
| 204 | args.ilength = 0x02000; | 205 | args.ilength = 0x02000; |
| 205 | args.engine = NVE0_CHANNEL_IND_ENGINE_GR; | 206 | args.engine = engine; |
| 206 | 207 | ||
| 207 | do { | 208 | do { |
| 208 | ret = nouveau_object_new(nv_object(cli), parent, handle, | 209 | ret = nouveau_object_new(nv_object(cli), parent, handle, |
| @@ -261,9 +262,6 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
| 261 | struct nv_dma_class args; | 262 | struct nv_dma_class args; |
| 262 | int ret, i; | 263 | int ret, i; |
| 263 | 264 | ||
| 264 | chan->vram = vram; | ||
| 265 | chan->gart = gart; | ||
| 266 | |||
| 267 | /* allocate dma objects to cover all allowed vram, and gart */ | 265 | /* allocate dma objects to cover all allowed vram, and gart */ |
| 268 | if (device->card_type < NV_C0) { | 266 | if (device->card_type < NV_C0) { |
| 269 | if (device->card_type >= NV_50) { | 267 | if (device->card_type >= NV_50) { |
| @@ -301,6 +299,9 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
| 301 | 0x003d, &args, sizeof(args), &object); | 299 | 0x003d, &args, sizeof(args), &object); |
| 302 | if (ret) | 300 | if (ret) |
| 303 | return ret; | 301 | return ret; |
| 302 | |||
| 303 | chan->vram = vram; | ||
| 304 | chan->gart = gart; | ||
| 304 | } | 305 | } |
| 305 | 306 | ||
| 306 | /* initialise dma tracking parameters */ | 307 | /* initialise dma tracking parameters */ |
| @@ -336,15 +337,17 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
| 336 | /* allocate software object class (used for fences on <= nv05, and | 337 | /* allocate software object class (used for fences on <= nv05, and |
| 337 | * to signal flip completion), bind it to a subchannel. | 338 | * to signal flip completion), bind it to a subchannel. |
| 338 | */ | 339 | */ |
| 339 | ret = nouveau_object_new(nv_object(client), chan->handle, | 340 | if (chan != chan->drm->cechan) { |
| 340 | NvSw, nouveau_abi16_swclass(chan->drm), | 341 | ret = nouveau_object_new(nv_object(client), chan->handle, |
| 341 | NULL, 0, &object); | 342 | NvSw, nouveau_abi16_swclass(chan->drm), |
| 342 | if (ret) | 343 | NULL, 0, &object); |
| 343 | return ret; | 344 | if (ret) |
| 345 | return ret; | ||
| 344 | 346 | ||
| 345 | swch = (void *)object->parent; | 347 | swch = (void *)object->parent; |
| 346 | swch->flip = nouveau_flip_complete; | 348 | swch->flip = nouveau_flip_complete; |
| 347 | swch->flip_data = chan; | 349 | swch->flip_data = chan; |
| 350 | } | ||
| 348 | 351 | ||
| 349 | if (device->card_type < NV_C0) { | 352 | if (device->card_type < NV_C0) { |
| 350 | ret = RING_SPACE(chan, 2); | 353 | ret = RING_SPACE(chan, 2); |
| @@ -362,12 +365,12 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
| 362 | 365 | ||
| 363 | int | 366 | int |
| 364 | nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, | 367 | nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, |
| 365 | u32 parent, u32 handle, u32 vram, u32 gart, | 368 | u32 parent, u32 handle, u32 arg0, u32 arg1, |
| 366 | struct nouveau_channel **pchan) | 369 | struct nouveau_channel **pchan) |
| 367 | { | 370 | { |
| 368 | int ret; | 371 | int ret; |
| 369 | 372 | ||
| 370 | ret = nouveau_channel_ind(drm, cli, parent, handle, pchan); | 373 | ret = nouveau_channel_ind(drm, cli, parent, handle, arg0, pchan); |
| 371 | if (ret) { | 374 | if (ret) { |
| 372 | NV_DEBUG(drm, "ib channel create, %d\n", ret); | 375 | NV_DEBUG(drm, "ib channel create, %d\n", ret); |
| 373 | ret = nouveau_channel_dma(drm, cli, parent, handle, pchan); | 376 | ret = nouveau_channel_dma(drm, cli, parent, handle, pchan); |
| @@ -377,7 +380,7 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nouveau_cli *cli, | |||
| 377 | } | 380 | } |
| 378 | } | 381 | } |
| 379 | 382 | ||
| 380 | ret = nouveau_channel_init(*pchan, vram, gart); | 383 | ret = nouveau_channel_init(*pchan, arg0, arg1); |
| 381 | if (ret) { | 384 | if (ret) { |
| 382 | NV_ERROR(drm, "channel failed to initialise, %d\n", ret); | 385 | NV_ERROR(drm, "channel failed to initialise, %d\n", ret); |
| 383 | nouveau_channel_del(pchan); | 386 | nouveau_channel_del(pchan); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 0fa94244bed1..40f97e2c47b6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h | |||
| @@ -39,7 +39,7 @@ struct nouveau_channel { | |||
| 39 | 39 | ||
| 40 | 40 | ||
| 41 | int nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *, | 41 | int nouveau_channel_new(struct nouveau_drm *, struct nouveau_cli *, |
| 42 | u32 parent, u32 handle, u32 vram, u32 gart, | 42 | u32 parent, u32 handle, u32 arg0, u32 arg1, |
| 43 | struct nouveau_channel **); | 43 | struct nouveau_channel **); |
| 44 | void nouveau_channel_del(struct nouveau_channel **); | 44 | void nouveau_channel_del(struct nouveau_channel **); |
| 45 | int nouveau_channel_idle(struct nouveau_channel *); | 45 | int nouveau_channel_idle(struct nouveau_channel *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 8b508cec65a2..4dfc40e3dabe 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
| @@ -109,6 +109,7 @@ nouveau_accel_fini(struct nouveau_drm *drm) | |||
| 109 | { | 109 | { |
| 110 | nouveau_gpuobj_ref(NULL, &drm->notify); | 110 | nouveau_gpuobj_ref(NULL, &drm->notify); |
| 111 | nouveau_channel_del(&drm->channel); | 111 | nouveau_channel_del(&drm->channel); |
| 112 | nouveau_channel_del(&drm->cechan); | ||
| 112 | if (drm->fence) | 113 | if (drm->fence) |
| 113 | nouveau_fence(drm)->dtor(drm); | 114 | nouveau_fence(drm)->dtor(drm); |
| 114 | } | 115 | } |
| @@ -118,6 +119,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
| 118 | { | 119 | { |
| 119 | struct nouveau_device *device = nv_device(drm->device); | 120 | struct nouveau_device *device = nv_device(drm->device); |
| 120 | struct nouveau_object *object; | 121 | struct nouveau_object *object; |
| 122 | u32 arg0, arg1; | ||
| 121 | int ret; | 123 | int ret; |
| 122 | 124 | ||
| 123 | if (nouveau_noaccel) | 125 | if (nouveau_noaccel) |
| @@ -134,8 +136,24 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
| 134 | return; | 136 | return; |
| 135 | } | 137 | } |
| 136 | 138 | ||
| 139 | if (device->card_type >= NV_E0) { | ||
| 140 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, | ||
| 141 | NVDRM_CHAN + 1, | ||
| 142 | NVE0_CHANNEL_IND_ENGINE_CE0 | | ||
| 143 | NVE0_CHANNEL_IND_ENGINE_CE1, 0, | ||
| 144 | &drm->cechan); | ||
| 145 | if (ret) | ||
| 146 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); | ||
| 147 | |||
| 148 | arg0 = NVE0_CHANNEL_IND_ENGINE_GR; | ||
| 149 | arg1 = 0; | ||
| 150 | } else { | ||
| 151 | arg0 = NvDmaFB; | ||
| 152 | arg1 = NvDmaTT; | ||
| 153 | } | ||
| 154 | |||
| 137 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, | 155 | ret = nouveau_channel_new(drm, &drm->client, NVDRM_DEVICE, NVDRM_CHAN, |
| 138 | NvDmaFB, NvDmaTT, &drm->channel); | 156 | arg0, arg1, &drm->channel); |
| 139 | if (ret) { | 157 | if (ret) { |
| 140 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); | 158 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); |
| 141 | nouveau_accel_fini(drm); | 159 | nouveau_accel_fini(drm); |
| @@ -167,7 +185,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
| 167 | } | 185 | } |
| 168 | 186 | ||
| 169 | 187 | ||
| 170 | nouveau_bo_move_init(drm->channel); | 188 | nouveau_bo_move_init(drm); |
| 171 | } | 189 | } |
| 172 | 190 | ||
| 173 | static int __devinit | 191 | static int __devinit |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 6abd1a15e742..ab0c17430c66 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h | |||
| @@ -97,6 +97,7 @@ struct nouveau_drm { | |||
| 97 | void *fence; | 97 | void *fence; |
| 98 | 98 | ||
| 99 | /* context for accelerated drm-internal operations */ | 99 | /* context for accelerated drm-internal operations */ |
| 100 | struct nouveau_channel *cechan; | ||
| 100 | struct nouveau_channel *channel; | 101 | struct nouveau_channel *channel; |
| 101 | struct nouveau_gpuobj *notify; | 102 | struct nouveau_gpuobj *notify; |
| 102 | struct nouveau_fbdev *fbcon; | 103 | struct nouveau_fbdev *fbcon; |
