Merge tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel into drm-next

So small drm stuff all over for 3.18. Biggest one is the cmdline parsing
from Chris with a few fixes from me to make it work for stupid kernel
configs.

Plus the atomic prep series.

Tested for more than a week in -nightly and Ville/Imre indeed discovered
some fun which is now fixed (and i915 vblank patches postponed since the
fixups need this branch plus drm-intel-next merged together).

* tag 'topic/core-stuff-2014-08-15' of git://anongit.freedesktop.org/drm-intel:
  drm: Use the type of the array element when reallocating
  drm: Don't return 0 for a value used as a denominator
  drm: Docbook fixes
  drm/irq: Implement a generic vblank_wait function
  drm: Add a plane->reset hook
  drm: trylock modest locking for fbdev panics
  drm: Move ->old_fb from crtc to plane
  drm: Handle legacy per-crtc locking with full acquire ctx
  drm: Move modeset_lock_all helpers to drm_modeset_lock.[hc]
  drm: Add drm_plane/connector_index
  drm: idiot-proof vblank
  drm: Warn when leaking flip events on close
  drm: Perform cmdline mode parsing during connector initialisation
  video/fbdev: Always built-in video= cmdline parsing
  drm: Don't grab an fb reference for the idr
This commit is contained in:
Dave Airlie
2014-08-26 09:04:03 +10:00
20 changed files with 630 additions and 331 deletions

View File

@@ -720,6 +720,8 @@ EXPORT_SYMBOL(drm_get_last_vbltimestamp);
*/
u32 drm_vblank_count(struct drm_device *dev, int crtc)
{
if (WARN_ON(crtc >= dev->num_crtcs))
return 0;
return atomic_read(&dev->vblank[crtc].count);
}
EXPORT_SYMBOL(drm_vblank_count);
@@ -742,6 +744,9 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
{
u32 cur_vblank;
if (WARN_ON(crtc >= dev->num_crtcs))
return 0;
/* Read timestamp from slot of _vblank_time ringbuffer
* that corresponds to current vblank count. Retry if
* count has incremented during readout. This works like
@@ -917,6 +922,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
unsigned long irqflags;
int ret = 0;
if (WARN_ON(crtc >= dev->num_crtcs))
return -EINVAL;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* Going from 0->1 means we have to enable interrupts again */
if (atomic_add_return(1, &dev->vblank[crtc].refcount) == 1) {
@@ -965,6 +973,9 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
{
BUG_ON(atomic_read(&dev->vblank[crtc].refcount) == 0);
if (WARN_ON(crtc >= dev->num_crtcs))
return;
/* Last user schedules interrupt disable */
if (atomic_dec_and_test(&dev->vblank[crtc].refcount) &&
(drm_vblank_offdelay > 0))
@@ -988,6 +999,50 @@ void drm_crtc_vblank_put(struct drm_crtc *crtc)
}
EXPORT_SYMBOL(drm_crtc_vblank_put);
/**
* drm_wait_one_vblank - wait for one vblank
* @dev: DRM device
* @crtc: crtc index
*
* This waits for one vblank to pass on @crtc, using the irq driver interfaces.
* It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
* due to lack of driver support or because the crtc is off.
*/
void drm_wait_one_vblank(struct drm_device *dev, int crtc)
{
int ret;
u32 last;
ret = drm_vblank_get(dev, crtc);
if (WARN_ON(ret))
return;
last = drm_vblank_count(dev, crtc);
ret = wait_event_timeout(dev->vblank[crtc].queue,
last != drm_vblank_count(dev, crtc),
msecs_to_jiffies(100));
WARN_ON(ret == 0);
drm_vblank_put(dev, crtc);
}
EXPORT_SYMBOL(drm_wait_one_vblank);
/**
* drm_crtc_wait_one_vblank - wait for one vblank
* @crtc: DRM crtc
*
* This waits for one vblank to pass on @crtc, using the irq driver interfaces.
* It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
* due to lack of driver support or because the crtc is off.
*/
void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
{
drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
}
EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
/**
* drm_vblank_off - disable vblank events on a CRTC
* @dev: DRM device
@@ -1009,6 +1064,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
unsigned long irqflags;
unsigned int seq;
if (WARN_ON(crtc >= dev->num_crtcs))
return;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
vblank_disable_and_save(dev, crtc);
wake_up(&dev->vblank[crtc].queue);
@@ -1068,6 +1126,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
{
unsigned long irqflags;
if (WARN_ON(crtc >= dev->num_crtcs))
return;
spin_lock_irqsave(&dev->vbl_lock, irqflags);
/* re-enable interrupts if there's are users left */
if (atomic_read(&dev->vblank[crtc].refcount) != 0)
@@ -1121,6 +1182,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
/* vblank is not initialized (IRQ not installed ?), or has been freed */
if (!dev->num_crtcs)
return;
if (WARN_ON(crtc >= dev->num_crtcs))
return;
/*
* To avoid all the problems that might happen if interrupts
* were enabled/disabled around or between these calls, we just
@@ -1429,6 +1494,9 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
if (!dev->num_crtcs)
return false;
if (WARN_ON(crtc >= dev->num_crtcs))
return false;
/* Need timestamp lock to prevent concurrent execution with
* vblank enable/disable, as this would cause inconsistent
* or corrupted timestamps and vblank counts.