Skip to content

Commit

Permalink
Merge tag 'topic/drm-misc-2016-06-01' of git://anongit.freedesktop.or…
Browse files Browse the repository at this point in the history
…g/drm-intel into drm-next

Frist -misc pull for 4.8, with pretty much just random all over plus a few
more lockless gem BO patches acked/reviewed by driver maintainers.

I'm starting a bit earlier this time around because there's a few invasive
patch series to land (nonblocking atomic prep work, fence prep work,
rst/sphinx kerneldoc finally happening) and I need a baseline with all the
branches merged.

* tag 'topic/drm-misc-2016-06-01' of git://anongit.freedesktop.org/drm-intel: (21 commits)
  drm/vc4: Use lockless gem BO free callback
  drm/vc4: Use drm_gem_object_unreference_unlocked
  drm: Initialize a linear gamma table by default
  drm/vgem: Use lockless gem BO free callback
  drm/qxl: Don't set a gamma table size
  drm/msm: Nuke dummy gamma_set/get functions
  drm/cirrus: Drop redundnant gamma size check
  drm/fb-helper: Remove dead code in setcolreg
  drm/mediatek: Use lockless gem BO free callback
  drm/hisilicon: Use lockless gem BO free callback
  drm/hlcd: Use lockless gem BO free callback
  vga_switcheroo: Support deferred probing of audio clients
  vga_switcheroo: Add helper for deferred probing
  virtio-gpu: fix output lookup
  drm/doc: Unify KMS Locking docs
  drm/atomic-helper: Do not call ->mode_fixup for CRTC which will be disabled
  Fix annoyingly awkward typo in drm_edid_load.c
  drm/doc: Drop vblank_disable_allow wording
  drm: use seqlock for vblank time/count
  drm/mm: avoid possible null pointer dereference
  ...
  • Loading branch information
Dave Airlie committed Jun 1, 2016
2 parents 1a695a9 + b82caaf commit 65439b6
Show file tree
Hide file tree
Showing 27 changed files with 104 additions and 216 deletions.
25 changes: 1 addition & 24 deletions Documentation/DocBook/gpu.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1092,22 +1092,6 @@ int max_width, max_height;</synopsis>
operation.
</para>
</sect2>
<sect2>
<title>Locking</title>
<para>
Beside some lookup structures with their own locking (which is hidden
behind the interface functions) most of the modeset state is protected
by the <code>dev-&lt;mode_config.lock</code> mutex and additionally
per-crtc locks to allow cursor updates, pageflips and similar operations
to occur concurrently with background tasks like output detection.
Operations which cross domains like a full modeset always grab all
locks. Drivers there need to protect resources shared between crtcs with
additional locking. They also need to be careful to always grab the
relevant crtc locks if a modset functions touches crtc state, e.g. for
load detection (which does only grab the <code>mode_config.lock</code>
to allow concurrent screen updates on live crtcs).
</para>
</sect2>
</sect1>

<!-- Internals: kms initialization and cleanup -->
Expand Down Expand Up @@ -2845,14 +2829,7 @@ void (*disable_vblank) (struct drm_device *dev, int crtc);</synopsis>
<para>
Drivers must initialize the vertical blanking handling core with a call to
<function>drm_vblank_init</function> in their
<methodname>load</methodname> operation. The function will set the struct
<structname>drm_device</structname>
<structfield>vblank_disable_allowed</structfield> field to 0. This will
keep vertical blanking interrupts enabled permanently until the first mode
set operation, where <structfield>vblank_disable_allowed</structfield> is
set to 1. The reason behind this is not clear. Drivers can set the field
to 1 after <function>calling drm_vblank_init</function> to make vertical
blanking interrupts dynamically managed from the beginning.
<methodname>load</methodname> operation.
</para>
<para>
Vertical blanking interrupts can be enabled by the DRM core or by drivers
Expand Down
3 changes: 3 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -3854,6 +3854,9 @@ T: git git://people.freedesktop.org/~airlied/linux
S: Maintained
F: drivers/gpu/drm/
F: drivers/gpu/vga/
F: Documentation/devicetree/bindings/display/
F: Documentation/devicetree/bindings/gpu/
F: Documentation/devicetree/bindings/video/
F: Documentation/DocBook/gpu.*
F: include/drm/
F: include/uapi/drm/
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/arm/hdlcd_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ static struct drm_driver hdlcd_driver = {
.get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = hdlcd_enable_vblank,
.disable_vblank = hdlcd_disable_vblank,
.gem_free_object = drm_gem_cma_free_object,
.gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_vm_ops = &drm_gem_cma_vm_ops,
.dumb_create = drm_gem_cma_dumb_create,
.dumb_map_offset = drm_gem_cma_dumb_map_offset,
Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/drm/cirrus/cirrus_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,6 @@ static void cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
int i;

if (size != CIRRUS_LUT_SIZE)
return;

for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
cirrus_crtc->lut_r[i] = red[i];
cirrus_crtc->lut_g[i] = green[i];
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/drm_atomic_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,9 @@ mode_fixup(struct drm_atomic_state *state)
for_each_crtc_in_state(state, crtc, crtc_state, i) {
const struct drm_crtc_helper_funcs *funcs;

if (!crtc_state->enable)
continue;

if (!crtc_state->mode_changed &&
!crtc_state->connectors_changed)
continue;
Expand Down
13 changes: 13 additions & 0 deletions drivers/gpu/drm/drm_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -5139,6 +5139,9 @@ EXPORT_SYMBOL(drm_mode_connector_attach_encoder);
int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
int gamma_size)
{
uint16_t *r_base, *g_base, *b_base;
int i;

crtc->gamma_size = gamma_size;

crtc->gamma_store = kcalloc(gamma_size, sizeof(uint16_t) * 3,
Expand All @@ -5148,6 +5151,16 @@ int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
return -ENOMEM;
}

r_base = crtc->gamma_store;
g_base = r_base + gamma_size;
b_base = g_base + gamma_size;
for (i = 0; i < gamma_size; i++) {
r_base[i] = i << 8;
g_base[i] = i << 8;
b_base[i] = i << 8;
}


return 0;
}
EXPORT_SYMBOL(drm_mode_crtc_set_gamma_size);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_edid_load.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ int drm_load_edid_firmware(struct drm_connector *connector)
* by commas, search through the list looking for one that
* matches the connector.
*
* If there's one or more that don't't specify a connector, keep
* If there's one or more that doesn't specify a connector, keep
* the last one found one as a fallback.
*/
fwstr = kstrdup(edid_firmware, GFP_KERNEL);
Expand Down
33 changes: 2 additions & 31 deletions drivers/gpu/drm/drm_fb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,6 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
int pindex;

if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
u32 *palette;
Expand Down Expand Up @@ -1074,38 +1073,10 @@ static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
!fb_helper->funcs->gamma_get))
return -EINVAL;

pindex = regno;
WARN_ON(fb->bits_per_pixel != 8);

if (fb->bits_per_pixel == 16) {
pindex = regno << 3;
fb_helper->funcs->gamma_set(crtc, red, green, blue, regno);

if (fb->depth == 16 && regno > 63)
return -EINVAL;
if (fb->depth == 15 && regno > 31)
return -EINVAL;

if (fb->depth == 16) {
u16 r, g, b;
int i;
if (regno < 32) {
for (i = 0; i < 8; i++)
fb_helper->funcs->gamma_set(crtc, red,
green, blue, pindex + i);
}

fb_helper->funcs->gamma_get(crtc, &r,
&g, &b,
pindex >> 1);

for (i = 0; i < 4; i++)
fb_helper->funcs->gamma_set(crtc, r,
green, b,
(pindex >> 1) + i);
}
}

if (fb->depth != 16)
fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
return 0;
}

Expand Down
90 changes: 12 additions & 78 deletions drivers/gpu/drm/drm_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,6 @@
#include <linux/vgaarb.h>
#include <linux/export.h>

/* Access macro for slots in vblank timestamp ringbuffer. */
#define vblanktimestamp(dev, pipe, count) \
((dev)->vblank[pipe].time[(count) % DRM_VBLANKTIME_RBSIZE])

/* Retry timestamp calculation up to 3 times to satisfy
* drm_timestamp_precision before giving up.
*/
Expand Down Expand Up @@ -82,29 +78,15 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
struct timeval *t_vblank, u32 last)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
u32 tslot;

assert_spin_locked(&dev->vblank_time_lock);

vblank->last = last;

/* All writers hold the spinlock, but readers are serialized by
* the latching of vblank->count below.
*/
tslot = vblank->count + vblank_count_inc;
vblanktimestamp(dev, pipe, tslot) = *t_vblank;

/*
* vblank timestamp updates are protected on the write side with
* vblank_time_lock, but on the read side done locklessly using a
* sequence-lock on the vblank counter. Ensure correct ordering using
* memory barrriers. We need the barrier both before and also after the
* counter update to synchronize with the next timestamp write.
* The read-side barriers for this are in drm_vblank_count_and_time.
*/
smp_wmb();
write_seqlock(&vblank->seqlock);
vblank->time = *t_vblank;
vblank->count += vblank_count_inc;
smp_wmb();
write_sequnlock(&vblank->seqlock);
}

/**
Expand Down Expand Up @@ -205,7 +187,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
const struct timeval *t_old;
u64 diff_ns;

t_old = &vblanktimestamp(dev, pipe, vblank->count);
t_old = &vblank->time;
diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old);

/*
Expand Down Expand Up @@ -239,49 +221,6 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
diff = 1;
}

/*
* FIMXE: Need to replace this hack with proper seqlocks.
*
* Restrict the bump of the software vblank counter to a safe maximum
* value of +1 whenever there is the possibility that concurrent readers
* of vblank timestamps could be active at the moment, as the current
* implementation of the timestamp caching and updating is not safe
* against concurrent readers for calls to store_vblank() with a bump
* of anything but +1. A bump != 1 would very likely return corrupted
* timestamps to userspace, because the same slot in the cache could
* be concurrently written by store_vblank() and read by one of those
* readers without the read-retry logic detecting the collision.
*
* Concurrent readers can exist when we are called from the
* drm_vblank_off() or drm_vblank_on() functions and other non-vblank-
* irq callers. However, all those calls to us are happening with the
* vbl_lock locked to prevent drm_vblank_get(), so the vblank refcount
* can't increase while we are executing. Therefore a zero refcount at
* this point is safe for arbitrary counter bumps if we are called
* outside vblank irq, a non-zero count is not 100% safe. Unfortunately
* we must also accept a refcount of 1, as whenever we are called from
* drm_vblank_get() -> drm_vblank_enable() the refcount will be 1 and
* we must let that one pass through in order to not lose vblank counts
* during vblank irq off - which would completely defeat the whole
* point of this routine.
*
* Whenever we are called from vblank irq, we have to assume concurrent
* readers exist or can show up any time during our execution, even if
* the refcount is currently zero, as vblank irqs are usually only
* enabled due to the presence of readers, and because when we are called
* from vblank irq we can't hold the vbl_lock to protect us from sudden
* bumps in vblank refcount. Therefore also restrict bumps to +1 when
* called from vblank irq.
*/
if ((diff > 1) && (atomic_read(&vblank->refcount) > 1 ||
(flags & DRM_CALLED_FROM_VBLIRQ))) {
DRM_DEBUG_VBL("clamping vblank bump to 1 on crtc %u: diffr=%u "
"refcount %u, vblirq %u\n", pipe, diff,
atomic_read(&vblank->refcount),
(flags & DRM_CALLED_FROM_VBLIRQ) != 0);
diff = 1;
}

DRM_DEBUG_VBL("updating vblank count on crtc %u:"
" current=%u, diff=%u, hw=%u hw_last=%u\n",
pipe, vblank->count, diff, cur_vblank, vblank->last);
Expand Down Expand Up @@ -417,6 +356,7 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs)
init_waitqueue_head(&vblank->queue);
setup_timer(&vblank->disable_timer, vblank_disable_fn,
(unsigned long)vblank);
seqlock_init(&vblank->seqlock);
}

DRM_INFO("Supports vblank timestamp caching Rev 2 (21.10.2013).\n");
Expand Down Expand Up @@ -986,25 +926,19 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
struct timeval *vblanktime)
{
struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
int count = DRM_TIMESTAMP_MAXRETRIES;
u32 cur_vblank;
u32 vblank_count;
unsigned int seq;

if (WARN_ON(pipe >= dev->num_crtcs))
return 0;

/*
* Vblank timestamps are read lockless. To ensure consistency the vblank
* counter is rechecked and ordering is ensured using memory barriers.
* This works like a seqlock. The write-side barriers are in store_vblank.
*/
do {
cur_vblank = vblank->count;
smp_rmb();
*vblanktime = vblanktimestamp(dev, pipe, cur_vblank);
smp_rmb();
} while (cur_vblank != vblank->count && --count > 0);
seq = read_seqbegin(&vblank->seqlock);
vblank_count = vblank->count;
*vblanktime = vblank->time;
} while (read_seqretry(&vblank->seqlock, seq));

return cur_vblank;
return vblank_count;
}
EXPORT_SYMBOL(drm_vblank_count_and_time);

Expand Down
4 changes: 3 additions & 1 deletion drivers/gpu/drm/drm_mm.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,14 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
{
struct drm_mm_node *hole;
u64 end = node->start + node->size;
u64 end;
u64 hole_start;
u64 hole_end;

BUG_ON(node == NULL);

end = node->start + node->size;

/* Find the relevant hole to add our node to */
drm_mm_for_each_hole(hole, mm, hole_start, hole_end) {
if (hole_start > node->start || hole_end < end)
Expand Down
11 changes: 9 additions & 2 deletions drivers/gpu/drm/drm_modeset_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
*
* As KMS moves toward more fine grained locking, and atomic ioctl where
* userspace can indirectly control locking order, it becomes necessary
* to use ww_mutex and acquire-contexts to avoid deadlocks. But because
* to use &ww_mutex and acquire-contexts to avoid deadlocks. But because
* the locking is more distributed around the driver code, we want a bit
* of extra utility/tracking out of our acquire-ctx. This is provided
* by drm_modeset_lock / drm_modeset_acquire_ctx.
*
* For basic principles of ww_mutex, see: Documentation/locking/ww-mutex-design.txt
* For basic principles of &ww_mutex, see: Documentation/locking/ww-mutex-design.txt
*
* The basic usage pattern is to:
*
Expand All @@ -51,6 +51,13 @@
* ... do stuff ...
* drm_modeset_drop_locks(&ctx);
* drm_modeset_acquire_fini(&ctx);
*
* On top of of these per-object locks using &ww_mutex there's also an overall
* dev->mode_config.lock, for protecting everything else. Mostly this means
* probe state of connectors, and preventing hotplug add/removal of connectors.
*
* Finally there's a bunch of dedicated locks to protect drm core internal
* lists and lookup data structures.
*/

/**
Expand Down
7 changes: 0 additions & 7 deletions drivers/gpu/drm/gma500/psb_intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,6 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
struct drm_psb_private *dev_priv = dev->dev_private;
struct gma_crtc *gma_crtc;
int i;
uint16_t *r_base, *g_base, *b_base;

/* We allocate a extra array of drm_connector pointers
* for fbdev after the crtc */
Expand Down Expand Up @@ -519,16 +518,10 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
gma_crtc->pipe = pipe;
gma_crtc->plane = pipe;

r_base = gma_crtc->base.gamma_store;
g_base = r_base + 256;
b_base = g_base + 256;
for (i = 0; i < 256; i++) {
gma_crtc->lut_r[i] = i;
gma_crtc->lut_g[i] = i;
gma_crtc->lut_b[i] = i;
r_base[i] = i << 8;
g_base[i] = i << 8;
b_base[i] = i << 8;

gma_crtc->lut_adj[i] = 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ static struct drm_driver kirin_drm_driver = {
.fops = &kirin_drm_fops,
.set_busid = drm_platform_set_busid,

.gem_free_object = drm_gem_cma_free_object,
.gem_free_object_unlocked = drm_gem_cma_free_object,
.gem_vm_ops = &drm_gem_cma_vm_ops,
.dumb_create = kirin_gem_cma_dumb_create,
.dumb_map_offset = drm_gem_cma_dumb_map_offset,
Expand Down
Loading

0 comments on commit 65439b6

Please sign in to comment.