Skip to content

Commit

Permalink
drm/udl: Use drm_fb_helper deferred_io support
Browse files Browse the repository at this point in the history
Use the fbdev deferred io support in drm_fb_helper.
The (struct fb_ops *)->fb_{fillrect,copyarea,imageblit} functions will
now schedule a worker instead of being flushed directly like it was
previously (recorded when in atomic).

This patch has only been compile tested.

Signed-off-by: Noralf Trønnes <[email protected]>
Reviewed-by: Daniel Vetter <[email protected]>
Tested-by: Gerd Hoffmann <[email protected]>
Signed-off-by: Daniel Vetter <[email protected]>
Link: http://patchwork.freedesktop.org/patch/msgid/[email protected]
  • Loading branch information
notro authored and danvet committed May 2, 2016
1 parent 6819c3c commit e375882
Show file tree
Hide file tree
Showing 2 changed files with 6 additions and 136 deletions.
2 changes: 0 additions & 2 deletions drivers/gpu/drm/udl/udl_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ struct udl_framebuffer {
struct drm_framebuffer base;
struct udl_gem_object *obj;
bool active_16; /* active on the 16-bit channel */
int x1, y1, x2, y2; /* dirty rect */
spinlock_t dirty_lock;
};

#define to_udl_fb(x) container_of(x, struct udl_framebuffer, base)
Expand Down
140 changes: 6 additions & 134 deletions drivers/gpu/drm/udl/udl_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,68 +77,6 @@ static uint16_t rgb16(uint32_t col)
}
#endif

/*
* NOTE: fb_defio.c is holding info->fbdefio.mutex
* Touching ANY framebuffer memory that triggers a page fault
* in fb_defio will cause a deadlock, when it also tries to
* grab the same mutex.
*/
static void udlfb_dpy_deferred_io(struct fb_info *info,
struct list_head *pagelist)
{
struct page *cur;
struct fb_deferred_io *fbdefio = info->fbdefio;
struct udl_fbdev *ufbdev = info->par;
struct drm_device *dev = ufbdev->ufb.base.dev;
struct udl_device *udl = dev->dev_private;
struct urb *urb;
char *cmd;
cycles_t start_cycles, end_cycles;
int bytes_sent = 0;
int bytes_identical = 0;
int bytes_rendered = 0;

if (!fb_defio)
return;

start_cycles = get_cycles();

urb = udl_get_urb(dev);
if (!urb)
return;

cmd = urb->transfer_buffer;

/* walk the written page list and render each to device */
list_for_each_entry(cur, &fbdefio->pagelist, lru) {

if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8),
&urb, (char *) info->fix.smem_start,
&cmd, cur->index << PAGE_SHIFT,
cur->index << PAGE_SHIFT,
PAGE_SIZE, &bytes_identical, &bytes_sent))
goto error;
bytes_rendered += PAGE_SIZE;
}

if (cmd > (char *) urb->transfer_buffer) {
/* Send partial buffer remaining before exiting */
int len = cmd - (char *) urb->transfer_buffer;
udl_submit_urb(dev, urb, len);
bytes_sent += len;
} else
udl_urb_completion(urb);

error:
atomic_add(bytes_sent, &udl->bytes_sent);
atomic_add(bytes_identical, &udl->bytes_identical);
atomic_add(bytes_rendered, &udl->bytes_rendered);
end_cycles = get_cycles();
atomic_add(((unsigned int) ((end_cycles - start_cycles)
>> 10)), /* Kcycles */
&udl->cpu_kcycles_used);
}

int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
int width, int height)
{
Expand All @@ -152,9 +90,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
struct urb *urb;
int aligned_x;
int bpp = (fb->base.bits_per_pixel / 8);
int x2, y2;
bool store_for_later = false;
unsigned long flags;

if (!fb->active_16)
return 0;
Expand All @@ -180,53 +115,21 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,
(y + height > fb->base.height))
return -EINVAL;

/* if we are in atomic just store the info
can't test inside spin lock */
if (in_atomic())
store_for_later = true;

x2 = x + width - 1;
y2 = y + height - 1;

spin_lock_irqsave(&fb->dirty_lock, flags);

if (fb->y1 < y)
y = fb->y1;
if (fb->y2 > y2)
y2 = fb->y2;
if (fb->x1 < x)
x = fb->x1;
if (fb->x2 > x2)
x2 = fb->x2;

if (store_for_later) {
fb->x1 = x;
fb->x2 = x2;
fb->y1 = y;
fb->y2 = y2;
spin_unlock_irqrestore(&fb->dirty_lock, flags);
return 0;
}

fb->x1 = fb->y1 = INT_MAX;
fb->x2 = fb->y2 = 0;

spin_unlock_irqrestore(&fb->dirty_lock, flags);
start_cycles = get_cycles();

urb = udl_get_urb(dev);
if (!urb)
return 0;
cmd = urb->transfer_buffer;

for (i = y; i <= y2 ; i++) {
for (i = y; i < height ; i++) {
const int line_offset = fb->base.pitches[0] * i;
const int byte_offset = line_offset + (x * bpp);
const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);
if (udl_render_hline(dev, bpp, &urb,
(char *) fb->obj->vmapping,
&cmd, byte_offset, dev_byte_offset,
(x2 - x + 1) * bpp,
width * bpp,
&bytes_identical, &bytes_sent))
goto error;
}
Expand Down Expand Up @@ -283,36 +186,6 @@ static int udl_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
return 0;
}

static void udl_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{
struct udl_fbdev *ufbdev = info->par;

sys_fillrect(info, rect);

udl_handle_damage(&ufbdev->ufb, rect->dx, rect->dy, rect->width,
rect->height);
}

static void udl_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{
struct udl_fbdev *ufbdev = info->par;

sys_copyarea(info, region);

udl_handle_damage(&ufbdev->ufb, region->dx, region->dy, region->width,
region->height);
}

static void udl_fb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct udl_fbdev *ufbdev = info->par;

sys_imageblit(info, image);

udl_handle_damage(&ufbdev->ufb, image->dx, image->dy, image->width,
image->height);
}

/*
* It's common for several clients to have framebuffer open simultaneously.
* e.g. both fbcon and X. Makes things interesting.
Expand All @@ -339,7 +212,7 @@ static int udl_fb_open(struct fb_info *info, int user)

if (fbdefio) {
fbdefio->delay = DL_DEFIO_WRITE_DELAY;
fbdefio->deferred_io = udlfb_dpy_deferred_io;
fbdefio->deferred_io = drm_fb_helper_deferred_io;
}

info->fbdefio = fbdefio;
Expand Down Expand Up @@ -379,9 +252,9 @@ static struct fb_ops udlfb_ops = {
.owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_fillrect = udl_fb_fillrect,
.fb_copyarea = udl_fb_copyarea,
.fb_imageblit = udl_fb_imageblit,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap,
Expand Down Expand Up @@ -458,7 +331,6 @@ udl_framebuffer_init(struct drm_device *dev,
{
int ret;

spin_lock_init(&ufb->dirty_lock);
ufb->obj = obj;
drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs);
Expand Down

0 comments on commit e375882

Please sign in to comment.