Skip to content

Commit

Permalink
drm/nouveau: store a per-client channel list
Browse files Browse the repository at this point in the history
Removes the need to disable IRQs to lookup channel struct on every pushbuf
ioctl, among others.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Jun 23, 2011
1 parent f8656f0 commit e8a863c
Show file tree
Hide file tree
Showing 6 changed files with 32 additions and 26 deletions.
42 changes: 22 additions & 20 deletions drivers/gpu/drm/nouveau/nouveau_channel.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fifo_engine *pfifo = &dev_priv->engine.fifo;
struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
struct nouveau_channel *chan;
unsigned long flags;
int ret;
Expand Down Expand Up @@ -220,6 +221,11 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
nouveau_debugfs_channel_init(chan);

NV_DEBUG(dev, "channel %d initialised\n", chan->id);
if (fpriv) {
spin_lock(&fpriv->lock);
list_add(&chan->list, &fpriv->channels);
spin_unlock(&fpriv->lock);
}
*chan_ret = chan;
return 0;
}
Expand All @@ -236,29 +242,23 @@ nouveau_channel_get_unlocked(struct nouveau_channel *ref)
}

struct nouveau_channel *
nouveau_channel_get(struct drm_device *dev, struct drm_file *file_priv, int id)
nouveau_channel_get(struct drm_file *file_priv, int id)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fpriv *fpriv = nouveau_fpriv(file_priv);
struct nouveau_channel *chan;
unsigned long flags;

if (unlikely(id < 0 || id >= NOUVEAU_MAX_CHANNEL_NR))
return ERR_PTR(-EINVAL);

spin_lock_irqsave(&dev_priv->channels.lock, flags);
chan = nouveau_channel_get_unlocked(dev_priv->channels.ptr[id]);
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);

if (unlikely(!chan))
return ERR_PTR(-EINVAL);

if (unlikely(file_priv && chan->file_priv != file_priv)) {
nouveau_channel_put_unlocked(&chan);
return ERR_PTR(-EINVAL);
spin_lock(&fpriv->lock);
list_for_each_entry(chan, &fpriv->channels, list) {
if (chan->id == id) {
chan = nouveau_channel_get_unlocked(chan);
spin_unlock(&fpriv->lock);
mutex_lock(&chan->mutex);
return chan;
}
}
spin_unlock(&fpriv->lock);

mutex_lock(&chan->mutex);
return chan;
return ERR_PTR(-EINVAL);
}

void
Expand Down Expand Up @@ -383,10 +383,11 @@ nouveau_channel_cleanup(struct drm_device *dev, struct drm_file *file_priv)

NV_DEBUG(dev, "clearing FIFO enables from file_priv\n");
for (i = 0; i < engine->fifo.channels; i++) {
chan = nouveau_channel_get(dev, file_priv, i);
chan = nouveau_channel_get(file_priv, i);
if (IS_ERR(chan))
continue;

list_del(&chan->list);
atomic_dec(&chan->users);
nouveau_channel_put(&chan);
}
Expand Down Expand Up @@ -459,10 +460,11 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
struct drm_nouveau_channel_free *req = data;
struct nouveau_channel *chan;

chan = nouveau_channel_get(dev, file_priv, req->channel);
chan = nouveau_channel_get(file_priv, req->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);

list_del(&chan->list);
atomic_dec(&chan->users);
nouveau_channel_put(&chan);
return 0;
Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

struct nouveau_fpriv {
spinlock_t lock;
struct list_head channels;
};

static inline struct nouveau_fpriv *
Expand Down Expand Up @@ -208,6 +209,7 @@ enum nouveau_channel_mutex_class {

struct nouveau_channel {
struct drm_device *dev;
struct list_head list;
int id;

/* references to the channel data structure */
Expand Down Expand Up @@ -858,7 +860,7 @@ extern int nouveau_channel_alloc(struct drm_device *dev,
extern struct nouveau_channel *
nouveau_channel_get_unlocked(struct nouveau_channel *);
extern struct nouveau_channel *
nouveau_channel_get(struct drm_device *, struct drm_file *, int id);
nouveau_channel_get(struct drm_file *, int id);
extern void nouveau_channel_put_unlocked(struct nouveau_channel **);
extern void nouveau_channel_put(struct nouveau_channel **);
extern void nouveau_channel_ref(struct nouveau_channel *chan,
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
}

if (req->channel_hint) {
chan = nouveau_channel_get(dev, file_priv, req->channel_hint);
chan = nouveau_channel_get(file_priv, req->channel_hint);
if (IS_ERR(chan))
return PTR_ERR(chan);
}
Expand Down Expand Up @@ -548,7 +548,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
struct nouveau_fence *fence = NULL;
int i, j, ret = 0, do_reloc = 0;

chan = nouveau_channel_get(dev, file_priv, req->channel);
chan = nouveau_channel_get(file_priv, req->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nouveau_notifier.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
if (unlikely(dev_priv->card_type >= NV_C0))
return -EINVAL;

chan = nouveau_channel_get(dev, file_priv, na->channel);
chan = nouveau_channel_get(file_priv, na->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_object.c
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
if (init->handle == ~0)
return -EINVAL;

chan = nouveau_channel_get(dev, file_priv, init->channel);
chan = nouveau_channel_get(file_priv, init->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);

Expand All @@ -936,7 +936,7 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
struct nouveau_channel *chan;
int ret;

chan = nouveau_channel_get(dev, file_priv, objfree->channel);
chan = nouveau_channel_get(file_priv, objfree->channel);
if (IS_ERR(chan))
return PTR_ERR(chan);

Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,8 @@ nouveau_open(struct drm_device *dev, struct drm_file *file_priv)
return -ENOMEM;

spin_lock_init(&fpriv->lock);
INIT_LIST_HEAD(&fpriv->channels);

file_priv->driver_priv = fpriv;
return 0;
}
Expand Down

0 comments on commit e8a863c

Please sign in to comment.