[PATCH] drm/ttm: request zeroed system memory pages for new TT buffer objects
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
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
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()
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
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
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
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
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
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
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
