Merge branch 'drm-nouveau-fixes-3.9' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

Oops fixers.
* 'drm-nouveau-fixes-3.9' of git://anongit.freedesktop.org/git/nouveau/linux-2.6:
  drm/nouveau: fix NULL ptr dereference from nv50_disp_intr()
  drm/nouveau: fix handling empty channel list in ioctl's
This commit is contained in:
Dave Airlie 2013-04-03 06:44:02 +10:00
commit 7cebefe6cc
3 changed files with 31 additions and 21 deletions

View File

@ -391,7 +391,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_device *device = nv_device(drm->device);
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
struct nouveau_abi16_chan *chan, *temp;
struct nouveau_abi16_chan *chan = NULL, *temp;
struct nouveau_abi16_ntfy *ntfy;
struct nouveau_object *object;
struct nv_dma_class args = {};
@ -404,10 +404,11 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
return nouveau_abi16_put(abi16, -EINVAL);
list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
if (chan->chan->handle == (NVDRM_CHAN | info->channel))
list_for_each_entry(temp, &abi16->channels, head) {
if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
chan = temp;
break;
chan = NULL;
}
}
if (!chan)
@ -459,17 +460,18 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
{
struct drm_nouveau_gpuobj_free *fini = data;
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
struct nouveau_abi16_chan *chan, *temp;
struct nouveau_abi16_chan *chan = NULL, *temp;
struct nouveau_abi16_ntfy *ntfy;
int ret;
if (unlikely(!abi16))
return -ENOMEM;
list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
if (chan->chan->handle == (NVDRM_CHAN | fini->channel))
list_for_each_entry(temp, &abi16->channels, head) {
if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
chan = temp;
break;
chan = NULL;
}
}
if (!chan)

View File

@ -71,12 +71,26 @@ module_param_named(modeset, nouveau_modeset, int, 0400);
static struct drm_driver driver;
static int
nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
{
struct nouveau_drm *drm =
container_of(event, struct nouveau_drm, vblank[head]);
drm_handle_vblank(drm->dev, head);
return NVKM_EVENT_KEEP;
}
static int
nouveau_drm_vblank_enable(struct drm_device *dev, int head)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
nouveau_event_get(pdisp->vblank, head, &drm->vblank);
if (WARN_ON_ONCE(head > ARRAY_SIZE(drm->vblank)))
return -EIO;
WARN_ON_ONCE(drm->vblank[head].func);
drm->vblank[head].func = nouveau_drm_vblank_handler;
nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]);
return 0;
}
@ -85,16 +99,11 @@ nouveau_drm_vblank_disable(struct drm_device *dev, int head)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_disp *pdisp = nouveau_disp(drm->device);
nouveau_event_put(pdisp->vblank, head, &drm->vblank);
}
static int
nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
{
struct nouveau_drm *drm =
container_of(event, struct nouveau_drm, vblank);
drm_handle_vblank(drm->dev, head);
return NVKM_EVENT_KEEP;
if (drm->vblank[head].func)
nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]);
else
WARN_ON_ONCE(1);
drm->vblank[head].func = NULL;
}
static u64
@ -292,7 +301,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = drm;
drm->dev = dev;
drm->vblank.func = nouveau_drm_vblank_handler;
INIT_LIST_HEAD(&drm->clients);
spin_lock_init(&drm->tile.lock);

View File

@ -113,7 +113,7 @@ struct nouveau_drm {
struct nvbios vbios;
struct nouveau_display *display;
struct backlight_device *backlight;
struct nouveau_eventh vblank;
struct nouveau_eventh vblank[4];
/* power management */
struct nouveau_pm *pm;