On Sat, Feb 1, 2014 at 1:16 PM, Alexandre Courbot <acourbot@xxxxxxxxxx> wrote: > Adapt the NVC0 BAR driver to make it able to support chips that do not > expose a BAR3. When this happens, BAR1 is then used for USERD mapping > and the BAR alloc() functions is disabled, making GPU objects unable > to rely on BAR for data access and falling back to PRAMIN. > > Signed-off-by: Alexandre Courbot <acourbot@xxxxxxxxxx> > --- > drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c | 115 +++++++++++++------------ > 1 file changed, 61 insertions(+), 54 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c > index 3f30db6..c2bb0e5 100644 > --- a/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c > +++ b/drivers/gpu/drm/nouveau/core/subdev/bar/nvc0.c > @@ -79,87 +79,88 @@ nvc0_bar_unmap(struct nouveau_bar *bar, struct nouveau_vma *vma) > } > > static int > -nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, > - struct nouveau_oclass *oclass, void *data, u32 size, > - struct nouveau_object **pobject) > +nvc0_bar_init_vm(struct nvc0_bar_priv *priv, int nr, int bar) > { > - struct nouveau_device *device = nv_device(parent); > - struct nvc0_bar_priv *priv; > + struct nouveau_device *device = nv_device(&priv->base); > struct nouveau_gpuobj *mem; > struct nouveau_vm *vm; > + resource_size_t bar_len; > int ret; > > - ret = nouveau_bar_create(parent, engine, oclass, &priv); > - *pobject = nv_object(priv); > - if (ret) > - return ret; > - > - /* BAR3 */ > ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, > - &priv->bar[0].mem); > - mem = priv->bar[0].mem; > + &priv->bar[nr].mem); > + mem = priv->bar[nr].mem; > if (ret) > return ret; > > ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, > - &priv->bar[0].pgd); > + &priv->bar[nr].pgd); > if (ret) > return ret; > > - ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 3), 0, &vm); > + bar_len = nv_device_resource_len(device, bar); > + > + ret = nouveau_vm_new(device, 0, bar_len, 0, &vm); > if (ret) > return ret; > > atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); > > - ret = nouveau_gpuobj_new(nv_object(priv), NULL, > - (nv_device_resource_len(device, 3) >> 12) * 8, > - 0x1000, NVOBJ_FLAG_ZERO_ALLOC, > - &vm->pgt[0].obj[0]); > - vm->pgt[0].refcount[0] = 1; > - if (ret) > - return ret; > + /* > + * Bootstrap page table lookup. > + */ > + if (bar == 3) { > + ret = nouveau_gpuobj_new(nv_object(priv), NULL, > + (bar_len >> 12) * 8, 0x1000, > + NVOBJ_FLAG_ZERO_ALLOC, > + &vm->pgt[0].obj[0]); > + vm->pgt[0].refcount[0] = 1; > + if (ret) > + return ret; > + } > > - ret = nouveau_vm_ref(vm, &priv->bar[0].vm, priv->bar[0].pgd); > + ret = nouveau_vm_ref(vm, &priv->bar[nr].vm, priv->bar[nr].pgd); > nouveau_vm_ref(NULL, &vm, NULL); > if (ret) > return ret; > > - nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[0].pgd->addr)); > - nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[0].pgd->addr)); > - nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 3) - 1)); > - nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 3) - 1)); > + nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[nr].pgd->addr)); > + nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[nr].pgd->addr)); > + nv_wo32(mem, 0x0208, lower_32_bits(bar_len - 1)); > + nv_wo32(mem, 0x020c, upper_32_bits(bar_len - 1)); > > - /* BAR1 */ > - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x1000, 0, 0, > - &priv->bar[1].mem); > - mem = priv->bar[1].mem; > - if (ret) > - return ret; > + return 0; > +} > > - ret = nouveau_gpuobj_new(nv_object(priv), NULL, 0x8000, 0, 0, > - &priv->bar[1].pgd); > - if (ret) > - return ret; > +static int > +nvc0_bar_ctor(struct nouveau_object *parent, struct nouveau_object *engine, > + struct nouveau_oclass *oclass, void *data, u32 size, > + struct nouveau_object **pobject) > +{ > + struct nouveau_device *device = nv_device(parent); > + struct nvc0_bar_priv *priv; > + bool has_bar3 = nv_device_resource_len(device, 3) != 0; > + int ret; > > - ret = nouveau_vm_new(device, 0, nv_device_resource_len(device, 1), 0, &vm); > + ret = nouveau_bar_create(parent, engine, oclass, &priv); > + *pobject = nv_object(priv); > if (ret) > return ret; > > - atomic_inc(&vm->engref[NVDEV_SUBDEV_BAR]); > + /* BAR3 */ > + if (has_bar3) { > + ret = nvc0_bar_init_vm(priv, 0, 3); > + if (ret) > + return ret; > + priv->base.alloc = nouveau_bar_alloc; > + priv->base.kmap = nvc0_bar_kmap; > + } > > - ret = nouveau_vm_ref(vm, &priv->bar[1].vm, priv->bar[1].pgd); > - nouveau_vm_ref(NULL, &vm, NULL); > + /* BAR1 */ > + ret = nvc0_bar_init_vm(priv, 1, 1); > if (ret) > return ret; > > - nv_wo32(mem, 0x0200, lower_32_bits(priv->bar[1].pgd->addr)); > - nv_wo32(mem, 0x0204, upper_32_bits(priv->bar[1].pgd->addr)); > - nv_wo32(mem, 0x0208, lower_32_bits(nv_device_resource_len(device, 1) - 1)); > - nv_wo32(mem, 0x020c, upper_32_bits(nv_device_resource_len(device, 1) - 1)); > - > - priv->base.alloc = nouveau_bar_alloc; > - priv->base.kmap = nvc0_bar_kmap; > priv->base.umap = nvc0_bar_umap; > priv->base.unmap = nvc0_bar_unmap; > priv->base.flush = nv84_bar_flush; > @@ -176,12 +177,16 @@ nvc0_bar_dtor(struct nouveau_object *object) > nouveau_gpuobj_ref(NULL, &priv->bar[1].pgd); > nouveau_gpuobj_ref(NULL, &priv->bar[1].mem); > > - if (priv->bar[0].vm) { > - nouveau_gpuobj_ref(NULL, &priv->bar[0].vm->pgt[0].obj[0]); > - nouveau_vm_ref(NULL, &priv->bar[0].vm, priv->bar[0].pgd); > + if (priv->bar[0].mem) { > + if (priv->bar[0].vm) { > + nouveau_gpuobj_ref(NULL, > + &priv->bar[0].vm->pgt[0].obj[0]); > + nouveau_vm_ref(NULL, &priv->bar[0].vm, > + priv->bar[0].pgd); > + } > + nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); > + nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); > } > - nouveau_gpuobj_ref(NULL, &priv->bar[0].pgd); > - nouveau_gpuobj_ref(NULL, &priv->bar[0].mem); Did the conditional on priv->bar[0].mem fix anything here? The ref() functions called are designed to handle the NULL pointers already. > > nouveau_bar_destroy(&priv->base); > } > @@ -201,7 +206,9 @@ nvc0_bar_init(struct nouveau_object *object) > nv_mask(priv, 0x100c80, 0x00000001, 0x00000000); > > nv_wr32(priv, 0x001704, 0x80000000 | priv->bar[1].mem->addr >> 12); > - nv_wr32(priv, 0x001714, 0xc0000000 | priv->bar[0].mem->addr >> 12); > + if (priv->bar[0].mem) > + nv_wr32(priv, 0x001714, > + 0xc0000000 | priv->bar[0].mem->addr >> 12); > return 0; > } > > -- > 1.8.5.3 > > _______________________________________________ > dri-devel mailing list > dri-devel@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/dri-devel -- To unsubscribe from this list: send the line "unsubscribe linux-tegra" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html