aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorBen Widawsky <ben@bwidawsk.net>2012-05-24 18:03:08 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-05-25 03:55:08 -0400
commit5c81fe85dad3c8c2bcec03e3fc2bfd4ea198763c (patch)
treec1e3c57116b5bb18eacba093653fda1242e353ca /drivers/gpu/drm/i915/i915_gem.c
parentc8d4bb54c11c66610aaf8829acff6aa0506c7c29 (diff)
drm/i915: timeout parameter for seqno wait
Insert a wait parameter in the code so we can possibly timeout on a seqno wait if need be. The code should be functionally the same as before because all the callers will continue to retry if an arbitrary timeout elapses. We'd like to have nanosecond granularity, but the only way to do this is with hrtimer, and that doesn't fit well with the needs of this code. v2: Fix rebase error (Chris) Return proper time even in wedged + signal case (Chris + Ben) Use timespec constructs (Ben) Didn't take Daniel's advice regarding the Frankenstein-ness of the function. I did try his advice, but in the end I liked the way the original code looked, better. v3: Make wakeups far less frequent for infinite waits (Chris) v4: Remove dummy_wait variable (Daniel) Use raw monotonic time instead of jiffies (made the code a bit cleaner) (Ben) Added a couple of warnings (Ben) v5: Remove warnings (Daniel) Use more accurate time diff for default case (Daniel) Bikeshed for setting the return timespec in timeout case (Daniel) s/jiffies/time in one of the comments Signed-off-by: Ben Widawsky <ben@bwidawsk.net> Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c70
1 files changed, 58 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 6d2180cf3da..c8a5b04bc8d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1869,34 +1869,82 @@ i915_gem_check_olr(struct intel_ring_buffer *ring, u32 seqno)
1869 return ret; 1869 return ret;
1870} 1870}
1871 1871
1872/**
1873 * __wait_seqno - wait until execution of seqno has finished
1874 * @ring: the ring expected to report seqno
1875 * @seqno: duh!
1876 * @interruptible: do an interruptible wait (normally yes)
1877 * @timeout: in - how long to wait (NULL forever); out - how much time remaining
1878 *
1879 * Returns 0 if the seqno was found within the alloted time. Else returns the
1880 * errno with remaining time filled in timeout argument.
1881 */
1872static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, 1882static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno,
1873 bool interruptible) 1883 bool interruptible, struct timespec *timeout)
1874{ 1884{
1875 drm_i915_private_t *dev_priv = ring->dev->dev_private; 1885 drm_i915_private_t *dev_priv = ring->dev->dev_private;
1876 int ret = 0; 1886 struct timespec before, now, wait_time={1,0};
1887 unsigned long timeout_jiffies;
1888 long end;
1889 bool wait_forever = true;
1877 1890
1878 if (i915_seqno_passed(ring->get_seqno(ring), seqno)) 1891 if (i915_seqno_passed(ring->get_seqno(ring), seqno))
1879 return 0; 1892 return 0;
1880 1893
1881 trace_i915_gem_request_wait_begin(ring, seqno); 1894 trace_i915_gem_request_wait_begin(ring, seqno);
1895
1896 if (timeout != NULL) {
1897 wait_time = *timeout;
1898 wait_forever = false;
1899 }
1900
1901 timeout_jiffies = timespec_to_jiffies(&wait_time);
1902
1882 if (WARN_ON(!ring->irq_get(ring))) 1903 if (WARN_ON(!ring->irq_get(ring)))
1883 return -ENODEV; 1904 return -ENODEV;
1884 1905
1906 /* Record current time in case interrupted by signal, or wedged * */
1907 getrawmonotonic(&before);
1908
1885#define EXIT_COND \ 1909#define EXIT_COND \
1886 (i915_seqno_passed(ring->get_seqno(ring), seqno) || \ 1910 (i915_seqno_passed(ring->get_seqno(ring), seqno) || \
1887 atomic_read(&dev_priv->mm.wedged)) 1911 atomic_read(&dev_priv->mm.wedged))
1912 do {
1913 if (interruptible)
1914 end = wait_event_interruptible_timeout(ring->irq_queue,
1915 EXIT_COND,
1916 timeout_jiffies);
1917 else
1918 end = wait_event_timeout(ring->irq_queue, EXIT_COND,
1919 timeout_jiffies);
1888 1920
1889 if (interruptible) 1921 if (atomic_read(&dev_priv->mm.wedged))
1890 ret = wait_event_interruptible(ring->irq_queue, 1922 end = -EAGAIN;
1891 EXIT_COND); 1923 } while (end == 0 && wait_forever);
1892 else 1924
1893 wait_event(ring->irq_queue, EXIT_COND); 1925 getrawmonotonic(&now);
1894 1926
1895 ring->irq_put(ring); 1927 ring->irq_put(ring);
1896 trace_i915_gem_request_wait_end(ring, seqno); 1928 trace_i915_gem_request_wait_end(ring, seqno);
1897#undef EXIT_COND 1929#undef EXIT_COND
1898 1930
1899 return ret; 1931 if (timeout) {
1932 struct timespec sleep_time = timespec_sub(now, before);
1933 *timeout = timespec_sub(*timeout, sleep_time);
1934 }
1935
1936 switch (end) {
1937 case -EAGAIN: /* Wedged */
1938 case -ERESTARTSYS: /* Signal */
1939 return (int)end;
1940 case 0: /* Timeout */
1941 if (timeout)
1942 set_normalized_timespec(timeout, 0, 0);
1943 return -ETIME;
1944 default: /* Completed */
1945 WARN_ON(end < 0); /* We're not aware of other errors */
1946 return 0;
1947 }
1900} 1948}
1901 1949
1902/** 1950/**
@@ -1920,9 +1968,7 @@ i915_wait_request(struct intel_ring_buffer *ring,
1920 if (ret) 1968 if (ret)
1921 return ret; 1969 return ret;
1922 1970
1923 ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible); 1971 ret = __wait_seqno(ring, seqno, dev_priv->mm.interruptible, NULL);
1924 if (atomic_read(&dev_priv->mm.wedged))
1925 ret = -EAGAIN;
1926 1972
1927 return ret; 1973 return ret;
1928} 1974}
@@ -3002,7 +3048,7 @@ i915_gem_ring_throttle(struct drm_device *dev, struct drm_file *file)
3002 if (seqno == 0) 3048 if (seqno == 0)
3003 return 0; 3049 return 0;
3004 3050
3005 ret = __wait_seqno(ring, seqno, true); 3051 ret = __wait_seqno(ring, seqno, true, NULL);
3006 if (ret == 0) 3052 if (ret == 0)
3007 queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0); 3053 queue_delayed_work(dev_priv->wq, &dev_priv->mm.retire_work, 0);
3008 3054