[PATCH] drm/ttm: request zeroed system memory pages for new TT buffer objects

2011-09-14 Thread skeg...@gmail.com
From: Ben Skeggs 

Fixes an information leak to userspace, we were handing out un-zeroed pages
for any newly created TTM_PL_TT buffer.

Reported-by: Marcin Slusarz 
Signed-off-by: Ben Skeggs 
Tested-by: Marcin Slusarz 
Cc: stable at kernel.org
---
 drivers/gpu/drm/ttm/ttm_bo.c |3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index a4d38d8..ef06194 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -394,7 +394,8 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object 
*bo,

if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
if (bo->ttm == NULL) {
-   ret = ttm_bo_add_ttm(bo, false);
+   bool zero = !(old_man->flags & TTM_MEMTYPE_FLAG_FIXED);
+   ret = ttm_bo_add_ttm(bo, zero);
if (ret)
goto out_err;
}
-- 
1.7.6.1



[PATCH] drm: bump DRM_CONNECTOR_MAX_ENCODER from 2 to 3

2012-01-12 Thread skeg...@gmail.com
From: Ben Skeggs 

There exists at least one NVIDIA GPU (Quadro NVS 300) that has a DMS-59
connector which is capable of supporting DisplayPort, TMDS and VGA on
a single connector.

We need to bump the allowed encoder limit to support all three configs.

Signed-off-by: Ben Skeggs 
---
 include/drm/drm_crtc.h |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8020798..bbd0448 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -431,7 +431,7 @@ struct drm_encoder_funcs {
 #define DRM_CONNECTOR_MAX_UMODES 16
 #define DRM_CONNECTOR_MAX_PROPERTY 16
 #define DRM_CONNECTOR_LEN 32
-#define DRM_CONNECTOR_MAX_ENCODER 2
+#define DRM_CONNECTOR_MAX_ENCODER 3

 /**
  * drm_encoder - central DRM encoder structure
-- 
1.7.7.5



[PATCH 1/2] drm/ttm: unbind ttm before destroying node in accel move cleanup

2011-08-22 Thread skeg...@gmail.com
From: Ben Skeggs 

Nouveau makes the assumption that if a TTM is bound there will be a mm_node
around for it and the backwards ordering here resulted in a use-after-free
on some eviction paths.

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/ttm/ttm_bo_util.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c 
b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 77dbf40..ae3c6f5 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -635,13 +635,13 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object 
*bo,
if (ret)
return ret;

-   ttm_bo_free_old_node(bo);
if ((man->flags & TTM_MEMTYPE_FLAG_FIXED) &&
(bo->ttm != NULL)) {
ttm_tt_unbind(bo->ttm);
ttm_tt_destroy(bo->ttm);
bo->ttm = NULL;
}
+   ttm_bo_free_old_node(bo);
} else {
/**
 * This should help pipeline ordinary buffer moves.
-- 
1.7.6



[PATCH 2/2] drm/ttm: ensure ttm for new node is bound before calling move_notify()

2011-08-22 Thread skeg...@gmail.com
From: Ben Skeggs 

This was true for new TTM_PL_SYSTEM and new TTM_PL_TT cases, but wasn't
the case on TTM_PL_SYSTEM<->TTM_PL_TT moves, which causes trouble on some
paths as nouveau's move_notify() hook requires that the dma addresses be
valid at this point.

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_mem.c |1 +
 drivers/gpu/drm/ttm/ttm_bo.c  |   10 ++
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c 
b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 2eecf5d..b4af850 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -831,6 +831,7 @@ nouveau_gart_manager_fini(struct ttm_mem_type_manager *man)
return 0;
 }

+
 static void
 nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
 struct ttm_mem_reg *mem)
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 2e618b5..9095b5b 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -390,10 +390,12 @@ static int ttm_bo_handle_move_mem(struct 
ttm_buffer_object *bo,
 * Create and bind a ttm if required.
 */

-   if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED) && (bo->ttm == NULL)) {
-   ret = ttm_bo_add_ttm(bo, false);
-   if (ret)
-   goto out_err;
+   if (!(new_man->flags & TTM_MEMTYPE_FLAG_FIXED)) {
+   if (bo->ttm == NULL) {
+   ret = ttm_bo_add_ttm(bo, false);
+   if (ret)
+   goto out_err;
+   }

ret = ttm_tt_set_placement_caching(bo->ttm, mem->placement);
if (ret)
-- 
1.7.6



[PATCH] drm: export drm_find_cea_extension to drivers

2011-03-30 Thread skeg...@gmail.com
From: Ben Skeggs 

Nouveau needs access to this structure to build an ELD block for use
by the HDA audio codec.

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/drm_edid.c |3 ++-
 include/drm/drm_crtc.h |1 +
 2 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a245d17..0c39b09 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -1288,7 +1288,7 @@ add_detailed_modes(struct drm_connector *connector, 
struct edid *edid,
 /**
  * Search EDID for CEA extension block.
  */
-static u8 *drm_find_cea_extension(struct edid *edid)
+u8 *drm_find_cea_extension(struct edid *edid)
 {
u8 *edid_ext = NULL;
int i;
@@ -1309,6 +1309,7 @@ static u8 *drm_find_cea_extension(struct edid *edid)

return edid_ext;
 }
+EXPORT_SYMBOL(drm_find_cea_extension);

 /**
  * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 801be59..5422004 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -778,6 +778,7 @@ extern int drm_mode_gamma_get_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
 extern int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
+extern u8 *drm_find_cea_extension(struct edid *edid);
 extern bool drm_detect_hdmi_monitor(struct edid *edid);
 extern bool drm_detect_monitor_audio(struct edid *edid);
 extern int drm_mode_page_flip_ioctl(struct drm_device *dev,
-- 
1.7.4.2



[PATCH 1/2] drm/nouveau: fixup init/fini sequence to deal with no CRTCs

2011-07-04 Thread skeg...@gmail.com
From: Ben Skeggs 

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/nouveau/nouveau_object.c |4 +-
 drivers/gpu/drm/nouveau/nouveau_state.c  |   64 +-
 2 files changed, 30 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c 
b/drivers/gpu/drm/nouveau/nouveau_object.c
index 363379c..4406c175 100644
--- a/drivers/gpu/drm/nouveau/nouveau_object.c
+++ b/drivers/gpu/drm/nouveau/nouveau_object.c
@@ -793,7 +793,7 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
return ret;

/* dma objects for display sync channel semaphore blocks */
-   for (i = 0; i < 2; i++) {
+   for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nouveau_gpuobj *sem = NULL;
struct nv50_display_crtc *dispc =
&nv50_display(dev)->crtc[i];
@@ -878,7 +878,7 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel 
*chan)
if (dev_priv->card_type >= NV_50) {
struct nv50_display *disp = nv50_display(dev);

-   for (i = 0; i < 2; i++) {
+   for (i = 0; i < dev->mode_config.num_crtc; i++) {
struct nv50_display_crtc *dispc = &disp->crtc[i];
nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]);
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c 
b/drivers/gpu/drm/nouveau/nouveau_state.c
index a5619a4..a7df8ea 100644
--- a/drivers/gpu/drm/nouveau/nouveau_state.c
+++ b/drivers/gpu/drm/nouveau/nouveau_state.c
@@ -452,21 +452,6 @@ nouveau_vga_set_decode(void *priv, bool state)
return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
 }

-static int
-nouveau_card_init_channel(struct drm_device *dev)
-{
-   struct drm_nouveau_private *dev_priv = dev->dev_private;
-   int ret;
-
-   ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
-   NvDmaFB, NvDmaTT);
-   if (ret)
-   return ret;
-
-   mutex_unlock(&dev_priv->channel->mutex);
-   return 0;
-}
-
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
 enum vga_switcheroo_state state)
 {
@@ -657,6 +642,10 @@ nouveau_card_init(struct drm_device *dev)
goto out_engine;
}

+   ret = nouveau_irq_init(dev);
+   if (ret)
+   goto out_fifo;
+
/* initialise general modesetting */
drm_mode_config_init(dev);
drm_mode_create_scaling_mode_property(dev);
@@ -679,39 +668,40 @@ nouveau_card_init(struct drm_device *dev)

ret = engine->display.create(dev);
if (ret)
-   goto out_fifo;
-
-   ret = drm_vblank_init(dev, nv_two_heads(dev) ? 2 : 1);
-   if (ret)
-   goto out_vblank;
-
-   ret = nouveau_irq_init(dev);
-   if (ret)
-   goto out_vblank;
-
-   /* what about PVIDEO/PCRTC/PRAMDAC etc? */
+   goto out_irq;

if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
ret = nouveau_fence_init(dev);
if (ret)
-   goto out_irq;
+   goto out_disp;

-   ret = nouveau_card_init_channel(dev);
+   ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
+   NvDmaFB, NvDmaTT);
if (ret)
goto out_fence;
+
+   mutex_unlock(&dev_priv->channel->mutex);
+   }
+
+   if (dev->mode_config.num_crtc) {
+   ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
+   if (ret)
+   goto out_chan;
+
+   nouveau_fbcon_init(dev);
+   drm_kms_helper_poll_init(dev);
}

-   nouveau_fbcon_init(dev);
-   drm_kms_helper_poll_init(dev);
return 0;

+out_chan:
+   nouveau_channel_put_unlocked(&dev_priv->channel);
 out_fence:
nouveau_fence_fini(dev);
+out_disp:
+   engine->display.destroy(dev);
 out_irq:
nouveau_irq_fini(dev);
-out_vblank:
-   drm_vblank_cleanup(dev);
-   engine->display.destroy(dev);
 out_fifo:
if (!dev_priv->noaccel)
engine->fifo.takedown(dev);
@@ -758,8 +748,11 @@ static void nouveau_card_takedown(struct drm_device *dev)
struct nouveau_engine *engine = &dev_priv->engine;
int e;

-   drm_kms_helper_poll_fini(dev);
-   nouveau_fbcon_fini(dev);
+   if (dev->mode_config.num_crtc) {
+   drm_kms_helper_poll_fini(dev);
+   nouveau_fbcon_fini(dev);
+   drm_vblank_cleanup(dev);
+   }

if (dev_priv->channel) {
nouveau_channel_put_unlocked(&dev_priv->channel);
@@ -801,7 +794,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
engine->vram.takedown(dev);

nouveau_irq_fini(dev);
-   d

[PATCH] drm/kms: allow drm_mode_group with no objects

2011-07-04 Thread skeg...@gmail.com
From: Ben Skeggs 

Sometimes we could be controlling a device (such as an NVIDIA Tesla) that
has no crtcs/encoders/connectors.

One could argue that the driver should unset DRIVER_MODESET in this case,
but that changes a whole heap of the DRM's other behaviours, and it's much
easier to just be a modesetting driver without any outputs.

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/drm_crtc.c |3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 21058e6..82db185 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -886,9 +886,6 @@ int drm_mode_group_init(struct drm_device *dev, struct 
drm_mode_group *group)
total_objects += dev->mode_config.num_connector;
total_objects += dev->mode_config.num_encoder;

-   if (total_objects == 0)
-   return -EINVAL;
-
group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);
if (!group->id_list)
return -ENOMEM;
-- 
1.7.5.4



[PATCH] drm: make sure drm_vblank_init() has been called before touching vbl_lock

2011-07-04 Thread skeg...@gmail.com
From: Ben Skeggs 

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/drm_irq.c |   15 +--
 1 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 2022a5c..c3c87a1 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -397,13 +397,16 @@ int drm_irq_uninstall(struct drm_device *dev)
/*
 * Wake up any waiters so they don't hang.
 */
-   spin_lock_irqsave(&dev->vbl_lock, irqflags);
-   for (i = 0; i < dev->num_crtcs; i++) {
-   DRM_WAKEUP(&dev->vbl_queue[i]);
-   dev->vblank_enabled[i] = 0;
-   dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
+   if (dev->num_crtcs) {
+   spin_lock_irqsave(&dev->vbl_lock, irqflags);
+   for (i = 0; i < dev->num_crtcs; i++) {
+   DRM_WAKEUP(&dev->vbl_queue[i]);
+   dev->vblank_enabled[i] = 0;
+   dev->last_vblank[i] =
+   dev->driver->get_vblank_counter(dev, i);
+   }
+   spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
}
-   spin_unlock_irqrestore(&dev->vbl_lock, irqflags);

if (!irq_enabled)
return -EINVAL;
-- 
1.7.5.4



[PATCH] drm/gem: add hooks to notify driver when object handle is created/destroyed

2011-06-08 Thread skeg...@gmail.com
From: Ben Skeggs 

Nouveau is going to use these hooks to map/unmap objects from a client's
private GPU address space.

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/drm_gem.c |   21 +++--
 include/drm/drmP.h|2 ++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 74e4ff5..59d2417 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -207,6 +207,8 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
dev = obj->dev;

/* Release reference and decrement refcount. */
+   if (dev->driver->gem_close_object)
+   dev->driver->gem_close_object(obj, filp);
idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);

@@ -226,7 +228,8 @@ drm_gem_handle_create(struct drm_file *file_priv,
   struct drm_gem_object *obj,
   u32 *handlep)
 {
-   int ret;
+   struct drm_device *dev = obj->dev;
+   int ret;

/*
 * Get the user-visible handle using idr.
@@ -247,6 +250,15 @@ again:
return ret;

drm_gem_object_handle_reference(obj);
+
+   if (dev->driver->gem_open_object) {
+   ret = dev->driver->gem_open_object(obj, file_priv);
+   if (ret) {
+   drm_gem_handle_delete(file_priv, *handlep);
+   return ret;
+   }
+   }
+
return 0;
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
@@ -401,7 +413,12 @@ drm_gem_open(struct drm_device *dev, struct drm_file 
*file_private)
 static int
 drm_gem_object_release_handle(int id, void *ptr, void *data)
 {
+   struct drm_file *file_priv = data;
struct drm_gem_object *obj = ptr;
+   struct drm_device *dev = obj->dev;
+
+   if (dev->driver->gem_close_object)
+   dev->driver->gem_close_object(obj, file_priv);

drm_gem_object_handle_unreference_unlocked(obj);

@@ -417,7 +434,7 @@ void
 drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 {
idr_for_each(&file_private->object_idr,
-&drm_gem_object_release_handle, NULL);
+&drm_gem_object_release_handle, file_private);

idr_remove_all(&file_private->object_idr);
idr_destroy(&file_private->object_idr);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 738b3a5..4912cb7 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -886,6 +886,8 @@ struct drm_driver {
 */
int (*gem_init_object) (struct drm_gem_object *obj);
void (*gem_free_object) (struct drm_gem_object *obj);
+   int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+   void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);

/* vga arb irq handler */
void (*vgaarb_irq)(struct drm_device *dev, bool state);
-- 
1.7.5.2



[PATCH] drm/gem: add hooks to notify driver when object handle is created/destroyed

2011-06-09 Thread skeg...@gmail.com
From: Ben Skeggs 

Nouveau is going to use these hooks to map/unmap objects from a client's
private GPU address space.

Signed-off-by: Ben Skeggs 
---
 drivers/gpu/drm/drm_gem.c |   21 +++--
 include/drm/drmP.h|2 ++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 74e4ff5..bad3359 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -210,6 +210,8 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
idr_remove(&filp->object_idr, handle);
spin_unlock(&filp->table_lock);

+   if (dev->driver->gem_close_object)
+   dev->driver->gem_close_object(obj, filp);
drm_gem_object_handle_unreference_unlocked(obj);

return 0;
@@ -226,7 +228,8 @@ drm_gem_handle_create(struct drm_file *file_priv,
   struct drm_gem_object *obj,
   u32 *handlep)
 {
-   int ret;
+   struct drm_device *dev = obj->dev;
+   int ret;

/*
 * Get the user-visible handle using idr.
@@ -247,6 +250,15 @@ again:
return ret;

drm_gem_object_handle_reference(obj);
+
+   if (dev->driver->gem_open_object) {
+   ret = dev->driver->gem_open_object(obj, file_priv);
+   if (ret) {
+   drm_gem_handle_delete(file_priv, *handlep);
+   return ret;
+   }
+   }
+
return 0;
 }
 EXPORT_SYMBOL(drm_gem_handle_create);
@@ -401,7 +413,12 @@ drm_gem_open(struct drm_device *dev, struct drm_file 
*file_private)
 static int
 drm_gem_object_release_handle(int id, void *ptr, void *data)
 {
+   struct drm_file *file_priv = data;
struct drm_gem_object *obj = ptr;
+   struct drm_device *dev = obj->dev;
+
+   if (dev->driver->gem_close_object)
+   dev->driver->gem_close_object(obj, file_priv);

drm_gem_object_handle_unreference_unlocked(obj);

@@ -417,7 +434,7 @@ void
 drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 {
idr_for_each(&file_private->object_idr,
-&drm_gem_object_release_handle, NULL);
+&drm_gem_object_release_handle, file_private);

idr_remove_all(&file_private->object_idr);
idr_destroy(&file_private->object_idr);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 738b3a5..4912cb7 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -886,6 +886,8 @@ struct drm_driver {
 */
int (*gem_init_object) (struct drm_gem_object *obj);
void (*gem_free_object) (struct drm_gem_object *obj);
+   int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
+   void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);

/* vga arb irq handler */
void (*vgaarb_irq)(struct drm_device *dev, bool state);
-- 
1.7.5.2