Maarten Maathuis
2009-Dec-26 21:43 UTC
[Nouveau] [PATCH 1/5] drm/nouveau: better alignment of bo sizes and use roundup instead of ALIGN
- Aligning to block size should ensure that the extra size is enough.
- Using roundup, because not all sizes are powers of two.
Signed-off-by: Maarten Maathuis <madman2003 at gmail.com>
---
drivers/gpu/drm/nouveau/nouveau_bo.c | 8 ++++++--
drivers/gpu/drm/nouveau/nouveau_fbcon.c | 4 ++--
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 98c46bd..fd767e7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -73,6 +73,7 @@ nouveau_bo_fixup_align(struct drm_device *dev,
case 0x4800:
case 0x7a00:
if (dev_priv->chipset >= 0xA0) {
+ *size = roundup(*size, 28672);
/* This is based on high end cards with 448 bits
* memory bus, could be different elsewhere.*/
*size += 6 * 28672;
@@ -80,9 +81,11 @@ nouveau_bo_fixup_align(struct drm_device *dev,
* but we must also align to page size. */
*align = 2 * 8 * 28672;
} else if (dev_priv->chipset >= 0x90) {
+ *size = roundup(*size, 16384);
*size += 3 * 16384;
*align = 12 * 16834;
} else {
+ *size = roundup(*size, 8192);
*size += 3 * 8192;
/* 12 * 8192 is the actual alignment requirement
* but we must also align to page size. */
@@ -110,10 +113,11 @@ nouveau_bo_fixup_align(struct drm_device *dev,
}
}
- *size = ALIGN(*size, PAGE_SIZE);
+ /* ALIGN works only on powers of two. */
+ *size = roundup(*size, PAGE_SIZE);
if (dev_priv->card_type == NV_50) {
- *size = ALIGN(*size, 65536);
+ *size = roundup(*size, 65536);
*align = max(65536, *align);
}
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 84af25c..44cbbee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -212,11 +212,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t
fb_width,
mode_cmd.bpp = surface_bpp;
mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3);
- mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256);
+ mode_cmd.pitch = roundup(mode_cmd.pitch, 256);
mode_cmd.depth = surface_depth;
size = mode_cmd.pitch * mode_cmd.height;
- size = ALIGN(size, PAGE_SIZE);
+ size = roundup(size, PAGE_SIZE);
ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM,
0, 0x0000, false, true, &nvbo);
--
1.6.6.rc4
Maarten Maathuis
2009-Dec-26 21:43 UTC
[Nouveau] [PATCH 2/5] drm/nv50: improve handling of tiled buffers wrt to cpu/gpu access
- Always make sure they are in vram (this is the only place where we have the
proper aperture).
- Hide the padding away from users, accessing this can cause problems for
neighbour buffer objects.
Signed-off-by: Maarten Maathuis <madman2003 at gmail.com>
---
drivers/gpu/drm/nouveau/nouveau_bo.c | 20 ++++++++++++++++----
drivers/gpu/drm/nouveau/nouveau_drv.h | 2 ++
drivers/gpu/drm/nouveau/nouveau_gem.c | 15 ++++++++++++++-
3 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index fd767e7..a052016 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -130,7 +130,7 @@ nouveau_bo_new(struct drm_device *dev, struct
nouveau_channel *chan,
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_bo *nvbo;
- int ret = 0;
+ int ret = 0, original_size;
nvbo = kzalloc(sizeof(struct nouveau_bo), GFP_KERNEL);
if (!nvbo)
@@ -142,7 +142,17 @@ nouveau_bo_new(struct drm_device *dev, struct
nouveau_channel *chan,
nvbo->tile_mode = tile_mode;
nvbo->tile_flags = tile_flags;
+ /* NV50: align to page size, any extra size after that is padding. */
+ if (dev_priv->card_type == NV_50)
+ original_size = size = roundup(size, 65536);
+ else
+ original_size = size = roundup(size, PAGE_SIZE);
nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size);
+ /* Touching this padding is dangerous as it will interfere with other
+ * buffer objects.
+ */
+ if (dev_priv->card_type == NV_50)
+ nvbo->padding = (size - original_size) >> PAGE_SHIFT;
align >>= PAGE_SHIFT;
nvbo->placement.fpfn = 0;
@@ -277,7 +287,8 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
if (ret)
return ret;
- ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
&nvbo->kmap);
+ ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages -
nvbo->padding,
+ &nvbo->kmap);
ttm_bo_unreserve(&nvbo->bo);
return ret;
}
@@ -661,8 +672,9 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct
ttm_mem_reg *new_mem,
if (dev_priv->card_type == NV_50) {
ret = nv50_mem_vm_bind_linear(dev,
offset + dev_priv->vm_vram_base,
- new_mem->size, nvbo->tile_flags,
- offset);
+ new_mem->size -
+ (nvbo->padding << PAGE_SHIFT),
+ nvbo->tile_flags, offset);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h
b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 7da88a9..ed9bb0d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -91,6 +91,8 @@ struct nouveau_bo {
uint32_t tile_mode;
uint32_t tile_flags;
+ /* tile_flags dependent padding (in pages). */
+ int padding;
struct nouveau_tile_reg *tile;
struct drm_gem_object *gem;
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c
b/drivers/gpu/drm/nouveau/nouveau_gem.c
index 18fd8ac..427b43c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -95,7 +95,7 @@ nouveau_gem_info(struct drm_gem_object *gem, struct
drm_nouveau_gem_info *rep)
else
rep->domain = NOUVEAU_GEM_DOMAIN_VRAM;
- rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
+ rep->size = (nvbo->bo.mem.num_pages - nvbo->padding) <<
PAGE_SHIFT;
rep->offset = nvbo->bo.offset;
rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0;
rep->tile_mode = nvbo->tile_mode;
@@ -908,6 +908,19 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void
*data,
return ret;
nvbo = nouveau_gem_object(gem);
+ /* Buffer objects with tile flags need to be in vram, so move them. */
+ if (nvbo->tile_flags) {
+ ret = ttm_bo_reserve(&nvbo->bo, false, false, false, 0);
+ if (ret)
+ return ret;
+
+ ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement, false,
false);
+ if (ret)
+ return ret;
+
+ ttm_bo_unreserve(&nvbo->bo);
+ }
+
if (nvbo->cpu_filp) {
if (nvbo->cpu_filp == file_priv)
goto out;
--
1.6.6.rc4
Maarten Maathuis
2009-Dec-26 21:43 UTC
[Nouveau] [PATCH 3/5] drm/nv50: fix align typo for g9x
- The resulting misallignment was causing stuff to be overwritten everywhere,
resulting in card hangs eventually.
Signed-off-by: Maarten Maathuis <madman2003 at gmail.com>
---
drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c
b/drivers/gpu/drm/nouveau/nouveau_bo.c
index a052016..0a08ece 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -83,7 +83,7 @@ nouveau_bo_fixup_align(struct drm_device *dev,
} else if (dev_priv->chipset >= 0x90) {
*size = roundup(*size, 16384);
*size += 3 * 16384;
- *align = 12 * 16834;
+ *align = 12 * 16384;
} else {
*size = roundup(*size, 8192);
*size += 3 * 8192;
--
1.6.6.rc4
Maarten Maathuis
2009-Dec-27 00:21 UTC
[Nouveau] [PATCH 1/5] drm/nouveau: better alignment of bo sizes and use roundup instead of ALIGN
pushed 1 to 4 On Sat, Dec 26, 2009 at 10:43 PM, Maarten Maathuis <madman2003 at gmail.com> wrote:> - Aligning to block size should ensure that the extra size is enough. > - Using roundup, because not all sizes are powers of two. > > Signed-off-by: Maarten Maathuis <madman2003 at gmail.com> > --- > ?drivers/gpu/drm/nouveau/nouveau_bo.c ? ?| ? ?8 ++++++-- > ?drivers/gpu/drm/nouveau/nouveau_fbcon.c | ? ?4 ++-- > ?2 files changed, 8 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c > index 98c46bd..fd767e7 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_bo.c > +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c > @@ -73,6 +73,7 @@ nouveau_bo_fixup_align(struct drm_device *dev, > ? ? ? ? ? ? ? ?case 0x4800: > ? ? ? ? ? ? ? ?case 0x7a00: > ? ? ? ? ? ? ? ? ? ? ? ?if (dev_priv->chipset >= 0xA0) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *size = roundup(*size, 28672); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* This is based on high end cards with 448 bits > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * memory bus, could be different elsewhere.*/ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*size += 6 * 28672; > @@ -80,9 +81,11 @@ nouveau_bo_fixup_align(struct drm_device *dev, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * but we must also align to page size. */ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*align = 2 * 8 * 28672; > ? ? ? ? ? ? ? ? ? ? ? ?} else if (dev_priv->chipset >= 0x90) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *size = roundup(*size, 16384); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*size += 3 * 16384; > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*align = 12 * 16834; > ? ? ? ? ? ? ? ? ? ? ? ?} else { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *size = roundup(*size, 8192); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?*size += 3 * 8192; > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* 12 * 8192 is the actual alignment requirement > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? * but we must also align to page size. */ > @@ -110,10 +113,11 @@ nouveau_bo_fixup_align(struct drm_device *dev, > ? ? ? ? ? ? ? ?} > ? ? ? ?} > > - ? ? ? *size = ALIGN(*size, PAGE_SIZE); > + ? ? ? /* ALIGN works only on powers of two. */ > + ? ? ? *size = roundup(*size, PAGE_SIZE); > > ? ? ? ?if (dev_priv->card_type == NV_50) { > - ? ? ? ? ? ? ? *size = ALIGN(*size, 65536); > + ? ? ? ? ? ? ? *size = roundup(*size, 65536); > ? ? ? ? ? ? ? ?*align = max(65536, *align); > ? ? ? ?} > ?} > diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c > index 84af25c..44cbbee 100644 > --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c > +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c > @@ -212,11 +212,11 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, > > ? ? ? ?mode_cmd.bpp = surface_bpp; > ? ? ? ?mode_cmd.pitch = mode_cmd.width * (mode_cmd.bpp >> 3); > - ? ? ? mode_cmd.pitch = ALIGN(mode_cmd.pitch, 256); > + ? ? ? mode_cmd.pitch = roundup(mode_cmd.pitch, 256); > ? ? ? ?mode_cmd.depth = surface_depth; > > ? ? ? ?size = mode_cmd.pitch * mode_cmd.height; > - ? ? ? size = ALIGN(size, PAGE_SIZE); > + ? ? ? size = roundup(size, PAGE_SIZE); > > ? ? ? ?ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0, 0x0000, false, true, &nvbo); > -- > 1.6.6.rc4 > >