Skip to content

Commit

Permalink
drm/nouveau/pageflip: kick flip handling out of engsw and into fence
Browse files Browse the repository at this point in the history
This is all very much a policy thing, and hence will not belong in SW
after the rework.

engsw now only handles receiving the event to say "can flip now" and makes
a callback to perform the actual work.

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
  • Loading branch information
Ben Skeggs committed Oct 3, 2012
1 parent bc9e7b9 commit f589be8
Show file tree
Hide file tree
Showing 17 changed files with 265 additions and 114 deletions.
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ nouveau-y += nouveau_drm.o nouveau_compat.o \
nouveau_mxm.o nouveau_agp.o \
nouveau_abi16.o \
nouveau_bios.o \
nv04_fence.o nv10_fence.o nv84_fence.o nvc0_fence.o \
nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o \
nv04_software.o nv50_software.o nvc0_software.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
nv04_crtc.o nv04_display.o nv04_cursor.o \
Expand Down
8 changes: 6 additions & 2 deletions drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "nouveau_drv.h"
#include <core/mm.h>
#include <engine/fifo.h>
#include "nouveau_software.h"

static void nvc0_fifo_isr(struct drm_device *);

Expand Down Expand Up @@ -323,8 +324,11 @@ nvc0_fifo_page_flip(struct drm_device *dev, u32 chid)
spin_lock_irqsave(&dev_priv->channels.lock, flags);
if (likely(chid >= 0 && chid < priv->base.channels)) {
chan = dev_priv->channels.ptr[chid];
if (likely(chan))
ret = nouveau_finish_page_flip(chan, NULL);
if (likely(chan)) {
struct nouveau_software_chan *swch =
chan->engctx[NVOBJ_ENGINE_SW];
ret = swch->flip(swch->flip_data);
}
}
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
return ret;
Expand Down
10 changes: 7 additions & 3 deletions drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "nouveau_drv.h"
#include <core/mm.h>
#include <engine/fifo.h>
#include "nouveau_software.h"

#define NVE0_FIFO_ENGINE_NUM 32

Expand Down Expand Up @@ -302,8 +303,11 @@ nve0_fifo_page_flip(struct drm_device *dev, u32 chid)
spin_lock_irqsave(&dev_priv->channels.lock, flags);
if (likely(chid >= 0 && chid < priv->base.channels)) {
chan = dev_priv->channels.ptr[chid];
if (likely(chan))
ret = nouveau_finish_page_flip(chan, NULL);
if (likely(chan)) {
struct nouveau_software_chan *swch =
chan->engctx[NVOBJ_ENGINE_SW];
ret = swch->flip(swch->flip_data);
}
}
spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
return ret;
Expand All @@ -315,7 +319,7 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
u32 stat = nv_rd32(dev, 0x040108 + (unit * 0x2000));
u32 addr = nv_rd32(dev, 0x0400c0 + (unit * 0x2000));
u32 data = nv_rd32(dev, 0x0400c4 + (unit * 0x2000));
u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0x7f;
u32 chid = nv_rd32(dev, 0x040120 + (unit * 0x2000)) & 0xfff;
u32 subc = (addr & 0x00070000);
u32 mthd = (addr & 0x00003ffc);
u32 show = stat;
Expand Down
29 changes: 24 additions & 5 deletions drivers/gpu/drm/nouveau/nouveau_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,15 +435,15 @@ nouveau_page_flip_emit(struct nouveau_channel *chan,
struct nouveau_page_flip_state *s,
struct nouveau_fence **pfence)
{
struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
struct nouveau_fence_chan *fctx = chan->fence;
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
struct drm_device *dev = chan->dev;
unsigned long flags;
int ret;

/* Queue it to the pending list */
spin_lock_irqsave(&dev->event_lock, flags);
list_add_tail(&s->head, &swch->flip);
list_add_tail(&s->head, &fctx->flip);
spin_unlock_irqrestore(&dev->event_lock, flags);

/* Synchronize with the old framebuffer */
Expand Down Expand Up @@ -553,20 +553,20 @@ int
nouveau_finish_page_flip(struct nouveau_channel *chan,
struct nouveau_page_flip_state *ps)
{
struct nouveau_software_chan *swch = chan->engctx[NVOBJ_ENGINE_SW];
struct nouveau_fence_chan *fctx = chan->fence;
struct drm_device *dev = chan->dev;
struct nouveau_page_flip_state *s;
unsigned long flags;

spin_lock_irqsave(&dev->event_lock, flags);

if (list_empty(&swch->flip)) {
if (list_empty(&fctx->flip)) {
NV_ERROR(dev, "Unexpected pageflip in channel %d.\n", chan->id);
spin_unlock_irqrestore(&dev->event_lock, flags);
return -EINVAL;
}

s = list_first_entry(&swch->flip, struct nouveau_page_flip_state, head);
s = list_first_entry(&fctx->flip, struct nouveau_page_flip_state, head);
if (s->event) {
struct drm_pending_vblank_event *e = s->event;
struct timeval now;
Expand All @@ -588,6 +588,25 @@ nouveau_finish_page_flip(struct nouveau_channel *chan,
return 0;
}

int
nouveau_flip_complete(void *data)
{
struct nouveau_channel *chan = data;
struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_page_flip_state state;

if (!nouveau_finish_page_flip(chan, &state)) {
if (dev_priv->card_type < NV_50) {
nv_set_crtc_base(dev, state.crtc, state.offset +
state.y * state.pitch +
state.x * state.bpp / 8);
}
}

return 0;
}

int
nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
struct drm_mode_create_dumb *args)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
void
nouveau_fence_context_new(struct nouveau_fence_chan *fctx)
{
INIT_LIST_HEAD(&fctx->flip);
INIT_LIST_HEAD(&fctx->pending);
spin_lock_init(&fctx->lock);
}
Expand Down
15 changes: 14 additions & 1 deletion drivers/gpu/drm/nouveau/nouveau_fence.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ void nouveau_fence_update(struct nouveau_channel *);

struct nouveau_fence_chan {
struct list_head pending;
struct list_head flip;

spinlock_t lock;
u32 sequence;
};
Expand All @@ -49,8 +51,19 @@ void nouveau_fence_context_del(struct nouveau_fence_chan *);
int nv04_fence_create(struct drm_device *dev);
int nv04_fence_mthd(struct nouveau_channel *, u32, u32, u32);

int nv10_fence_create(struct drm_device *dev);
int nv10_fence_emit(struct nouveau_fence *);
int nv17_fence_sync(struct nouveau_fence *, struct nouveau_channel *,
struct nouveau_channel *);
u32 nv10_fence_read(struct nouveau_channel *);
void nv10_fence_context_del(struct nouveau_channel *);
void nv10_fence_destroy(struct drm_device *);
int nv10_fence_create(struct drm_device *dev);

int nv50_fence_create(struct drm_device *dev);
int nv84_fence_create(struct drm_device *dev);
int nvc0_fence_create(struct drm_device *dev);
u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc);

int nouveau_flip_complete(void *chan);

#endif
14 changes: 9 additions & 5 deletions drivers/gpu/drm/nouveau/nouveau_software.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
#ifndef __NOUVEAU_SOFTWARE_H__
#define __NOUVEAU_SOFTWARE_H__

#include "nouveau_fence.h"

struct nouveau_software_priv {
struct nouveau_exec_engine base;
struct list_head vblank;
spinlock_t peephole_lock;
};

struct nouveau_software_chan {
struct list_head flip;
int (*flip)(void *data);
void *flip_data;

struct {
struct list_head list;
u32 channel;
Expand All @@ -20,10 +24,11 @@ struct nouveau_software_chan {
};

static inline void
nouveau_software_context_new(struct nouveau_software_chan *pch)
nouveau_software_context_new(struct nouveau_channel *chan,
struct nouveau_software_chan *pch)
{
INIT_LIST_HEAD(&pch->flip);
INIT_LIST_HEAD(&pch->vblank.list);
pch->flip = nouveau_flip_complete;
pch->flip_data = chan;
}

static inline void
Expand Down Expand Up @@ -51,6 +56,5 @@ nouveau_software_class(struct drm_device *dev)
int nv04_software_create(struct drm_device *);
int nv50_software_create(struct drm_device *);
int nvc0_software_create(struct drm_device *);
u64 nvc0_software_crtc(struct nouveau_channel *, int crtc);

#endif
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nouveau_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ nouveau_card_init(struct drm_device *dev)
case NV_40:
case NV_50:
if (dev_priv->chipset < 0x84)
nv10_fence_create(dev);
nv50_fence_create(dev);
else
nv84_fence_create(dev);
break;
Expand Down
14 changes: 3 additions & 11 deletions drivers/gpu/drm/nouveau/nv04_software.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,8 @@ struct nv04_software_chan {
static int
mthd_flip(struct nouveau_channel *chan, u32 class, u32 mthd, u32 data)
{

struct nouveau_page_flip_state state;

if (!nouveau_finish_page_flip(chan, &state)) {
nv_set_crtc_base(chan->dev, state.crtc, state.offset +
state.y * state.pitch +
state.x * state.bpp / 8);
}

return 0;
struct nv04_software_chan *pch = chan->engctx[NVOBJ_ENGINE_SW];
return pch->base.flip(pch->base.flip_data);
}

static int
Expand All @@ -62,7 +54,7 @@ nv04_software_context_new(struct nouveau_channel *chan, int engine)
if (!pch)
return -ENOMEM;

nouveau_software_context_new(&pch->base);
nouveau_software_context_new(chan, &pch->base);
chan->engctx[engine] = pch;
return 0;
}
Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/nouveau/nv10_fence.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct nv10_fence_priv {
u32 sequence;
};

static int
int
nv10_fence_emit(struct nouveau_fence *fence)
{
struct nouveau_channel *chan = fence->channel;
Expand All @@ -60,7 +60,7 @@ nv10_fence_sync(struct nouveau_fence *fence,
return -ENODEV;
}

static int
int
nv17_fence_sync(struct nouveau_fence *fence,
struct nouveau_channel *prev, struct nouveau_channel *chan)
{
Expand Down Expand Up @@ -100,13 +100,13 @@ nv17_fence_sync(struct nouveau_fence *fence,
return 0;
}

static u32
u32
nv10_fence_read(struct nouveau_channel *chan)
{
return nvchan_rd32(chan, 0x0048);
}

static void
void
nv10_fence_context_del(struct nouveau_channel *chan)
{
struct nv10_fence_chan *fctx = chan->fence;
Expand Down Expand Up @@ -148,7 +148,7 @@ nv10_fence_context_new(struct nouveau_channel *chan)
return ret;
}

static void
void
nv10_fence_destroy(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nv50_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
#include "nouveau_fb.h"
#include "nouveau_fbcon.h"
#include <core/ramht.h>
#include "nouveau_software.h"
#include "drm_crtc_helper.h"
#include "nouveau_fence.h"

static void nv50_display_isr(struct drm_device *);
static void nv50_display_bh(unsigned long);
Expand Down Expand Up @@ -446,7 +446,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
else
OUT_RING (chan, chan->vram_handle);
} else {
u64 offset = nvc0_software_crtc(chan, nv_crtc->index);
u64 offset = nvc0_fence_crtc(chan, nv_crtc->index);
offset += dispc->sem.offset;
BEGIN_NVC0(chan, 0, 0x0010, 4);
OUT_RING (chan, upper_32_bits(offset));
Expand Down
Loading

0 comments on commit f589be8

Please sign in to comment.