diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 70 |
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 | */ | ||
1872 | static int __wait_seqno(struct intel_ring_buffer *ring, u32 seqno, | 1882 | static 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 | ||