diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 12 |
3 files changed, 58 insertions, 25 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 25fc3841a2b1..5c45e9e598de 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -1772,13 +1772,18 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep) | |||
1772 | struct drm_i915_private *dev_priv = info->dev->dev_private; | 1772 | struct drm_i915_private *dev_priv = info->dev->dev_private; |
1773 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; | 1773 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; |
1774 | 1774 | ||
1775 | if (!atomic_dec_and_test(&pipe_crc->available)) { | 1775 | spin_lock_irq(&pipe_crc->lock); |
1776 | atomic_inc(&pipe_crc->available); | 1776 | |
1777 | if (pipe_crc->opened) { | ||
1778 | spin_unlock_irq(&pipe_crc->lock); | ||
1777 | return -EBUSY; /* already open */ | 1779 | return -EBUSY; /* already open */ |
1778 | } | 1780 | } |
1779 | 1781 | ||
1782 | pipe_crc->opened = true; | ||
1780 | filep->private_data = inode->i_private; | 1783 | filep->private_data = inode->i_private; |
1781 | 1784 | ||
1785 | spin_unlock_irq(&pipe_crc->lock); | ||
1786 | |||
1782 | return 0; | 1787 | return 0; |
1783 | } | 1788 | } |
1784 | 1789 | ||
@@ -1788,7 +1793,9 @@ static int i915_pipe_crc_release(struct inode *inode, struct file *filep) | |||
1788 | struct drm_i915_private *dev_priv = info->dev->dev_private; | 1793 | struct drm_i915_private *dev_priv = info->dev->dev_private; |
1789 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; | 1794 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; |
1790 | 1795 | ||
1791 | atomic_inc(&pipe_crc->available); /* release the device */ | 1796 | spin_lock_irq(&pipe_crc->lock); |
1797 | pipe_crc->opened = false; | ||
1798 | spin_unlock_irq(&pipe_crc->lock); | ||
1792 | 1799 | ||
1793 | return 0; | 1800 | return 0; |
1794 | } | 1801 | } |
@@ -1800,12 +1807,9 @@ static int i915_pipe_crc_release(struct inode *inode, struct file *filep) | |||
1800 | 1807 | ||
1801 | static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc) | 1808 | static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc) |
1802 | { | 1809 | { |
1803 | int head, tail; | 1810 | assert_spin_locked(&pipe_crc->lock); |
1804 | 1811 | return CIRC_CNT(pipe_crc->head, pipe_crc->tail, | |
1805 | head = atomic_read(&pipe_crc->head); | 1812 | INTEL_PIPE_CRC_ENTRIES_NR); |
1806 | tail = atomic_read(&pipe_crc->tail); | ||
1807 | |||
1808 | return CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR); | ||
1809 | } | 1813 | } |
1810 | 1814 | ||
1811 | static ssize_t | 1815 | static ssize_t |
@@ -1831,20 +1835,30 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, | |||
1831 | return 0; | 1835 | return 0; |
1832 | 1836 | ||
1833 | /* nothing to read */ | 1837 | /* nothing to read */ |
1838 | spin_lock_irq(&pipe_crc->lock); | ||
1834 | while (pipe_crc_data_count(pipe_crc) == 0) { | 1839 | while (pipe_crc_data_count(pipe_crc) == 0) { |
1835 | if (filep->f_flags & O_NONBLOCK) | 1840 | int ret; |
1841 | |||
1842 | if (filep->f_flags & O_NONBLOCK) { | ||
1843 | spin_unlock_irq(&pipe_crc->lock); | ||
1836 | return -EAGAIN; | 1844 | return -EAGAIN; |
1845 | } | ||
1837 | 1846 | ||
1838 | if (wait_event_interruptible(pipe_crc->wq, | 1847 | ret = wait_event_interruptible_lock_irq(pipe_crc->wq, |
1839 | pipe_crc_data_count(pipe_crc))) | 1848 | pipe_crc_data_count(pipe_crc), pipe_crc->lock); |
1840 | return -ERESTARTSYS; | 1849 | if (ret) { |
1850 | spin_unlock_irq(&pipe_crc->lock); | ||
1851 | return ret; | ||
1852 | } | ||
1841 | } | 1853 | } |
1842 | 1854 | ||
1843 | /* We now have one or more entries to read */ | 1855 | /* We now have one or more entries to read */ |
1844 | head = atomic_read(&pipe_crc->head); | 1856 | head = pipe_crc->head; |
1845 | tail = atomic_read(&pipe_crc->tail); | 1857 | tail = pipe_crc->tail; |
1846 | n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR), | 1858 | n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR), |
1847 | count / PIPE_CRC_LINE_LEN); | 1859 | count / PIPE_CRC_LINE_LEN); |
1860 | spin_unlock_irq(&pipe_crc->lock); | ||
1861 | |||
1848 | bytes_read = 0; | 1862 | bytes_read = 0; |
1849 | n = 0; | 1863 | n = 0; |
1850 | do { | 1864 | do { |
@@ -1864,10 +1878,13 @@ i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, | |||
1864 | 1878 | ||
1865 | BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); | 1879 | BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); |
1866 | tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); | 1880 | tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); |
1867 | atomic_set(&pipe_crc->tail, tail); | ||
1868 | n++; | 1881 | n++; |
1869 | } while (--n_entries); | 1882 | } while (--n_entries); |
1870 | 1883 | ||
1884 | spin_lock_irq(&pipe_crc->lock); | ||
1885 | pipe_crc->tail = tail; | ||
1886 | spin_unlock_irq(&pipe_crc->lock); | ||
1887 | |||
1871 | return bytes_read; | 1888 | return bytes_read; |
1872 | } | 1889 | } |
1873 | 1890 | ||
@@ -2111,8 +2128,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, | |||
2111 | if (!pipe_crc->entries) | 2128 | if (!pipe_crc->entries) |
2112 | return -ENOMEM; | 2129 | return -ENOMEM; |
2113 | 2130 | ||
2114 | atomic_set(&pipe_crc->head, 0); | 2131 | spin_lock_irq(&pipe_crc->lock); |
2115 | atomic_set(&pipe_crc->tail, 0); | 2132 | pipe_crc->head = 0; |
2133 | pipe_crc->tail = 0; | ||
2134 | spin_unlock_irq(&pipe_crc->lock); | ||
2116 | } | 2135 | } |
2117 | 2136 | ||
2118 | pipe_crc->source = source; | 2137 | pipe_crc->source = source; |
@@ -2122,13 +2141,19 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, | |||
2122 | 2141 | ||
2123 | /* real source -> none transition */ | 2142 | /* real source -> none transition */ |
2124 | if (source == INTEL_PIPE_CRC_SOURCE_NONE) { | 2143 | if (source == INTEL_PIPE_CRC_SOURCE_NONE) { |
2144 | struct intel_pipe_crc_entry *entries; | ||
2145 | |||
2125 | DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", | 2146 | DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", |
2126 | pipe_name(pipe)); | 2147 | pipe_name(pipe)); |
2127 | 2148 | ||
2128 | intel_wait_for_vblank(dev, pipe); | 2149 | intel_wait_for_vblank(dev, pipe); |
2129 | 2150 | ||
2130 | kfree(pipe_crc->entries); | 2151 | spin_lock_irq(&pipe_crc->lock); |
2152 | entries = pipe_crc->entries; | ||
2131 | pipe_crc->entries = NULL; | 2153 | pipe_crc->entries = NULL; |
2154 | spin_unlock_irq(&pipe_crc->lock); | ||
2155 | |||
2156 | kfree(entries); | ||
2132 | } | 2157 | } |
2133 | 2158 | ||
2134 | return 0; | 2159 | return 0; |
@@ -2823,7 +2848,8 @@ void intel_display_crc_init(struct drm_device *dev) | |||
2823 | for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { | 2848 | for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { |
2824 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; | 2849 | struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; |
2825 | 2850 | ||
2826 | atomic_set(&pipe_crc->available, 1); | 2851 | pipe_crc->opened = false; |
2852 | spin_lock_init(&pipe_crc->lock); | ||
2827 | init_waitqueue_head(&pipe_crc->wq); | 2853 | init_waitqueue_head(&pipe_crc->wq); |
2828 | } | 2854 | } |
2829 | } | 2855 | } |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 2e1e884ac86c..5bfcf0f91a51 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1249,10 +1249,11 @@ struct intel_pipe_crc_entry { | |||
1249 | 1249 | ||
1250 | #define INTEL_PIPE_CRC_ENTRIES_NR 128 | 1250 | #define INTEL_PIPE_CRC_ENTRIES_NR 128 |
1251 | struct intel_pipe_crc { | 1251 | struct intel_pipe_crc { |
1252 | atomic_t available; /* exclusive access to the device */ | 1252 | spinlock_t lock; |
1253 | bool opened; /* exclusive access to the result file */ | ||
1253 | struct intel_pipe_crc_entry *entries; | 1254 | struct intel_pipe_crc_entry *entries; |
1254 | enum intel_pipe_crc_source source; | 1255 | enum intel_pipe_crc_source source; |
1255 | atomic_t head, tail; | 1256 | int head, tail; |
1256 | wait_queue_head_t wq; | 1257 | wait_queue_head_t wq; |
1257 | }; | 1258 | }; |
1258 | 1259 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8f7baad72316..1a7dc7754e2f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1200,15 +1200,19 @@ static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, | |||
1200 | struct intel_pipe_crc_entry *entry; | 1200 | struct intel_pipe_crc_entry *entry; |
1201 | int head, tail; | 1201 | int head, tail; |
1202 | 1202 | ||
1203 | spin_lock(&pipe_crc->lock); | ||
1204 | |||
1203 | if (!pipe_crc->entries) { | 1205 | if (!pipe_crc->entries) { |
1206 | spin_unlock(&pipe_crc->lock); | ||
1204 | DRM_ERROR("spurious interrupt\n"); | 1207 | DRM_ERROR("spurious interrupt\n"); |
1205 | return; | 1208 | return; |
1206 | } | 1209 | } |
1207 | 1210 | ||
1208 | head = atomic_read(&pipe_crc->head); | 1211 | head = pipe_crc->head; |
1209 | tail = atomic_read(&pipe_crc->tail); | 1212 | tail = pipe_crc->tail; |
1210 | 1213 | ||
1211 | if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { | 1214 | if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { |
1215 | spin_unlock(&pipe_crc->lock); | ||
1212 | DRM_ERROR("CRC buffer overflowing\n"); | 1216 | DRM_ERROR("CRC buffer overflowing\n"); |
1213 | return; | 1217 | return; |
1214 | } | 1218 | } |
@@ -1223,7 +1227,9 @@ static void display_pipe_crc_irq_handler(struct drm_device *dev, enum pipe pipe, | |||
1223 | entry->crc[4] = crc4; | 1227 | entry->crc[4] = crc4; |
1224 | 1228 | ||
1225 | head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); | 1229 | head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); |
1226 | atomic_set(&pipe_crc->head, head); | 1230 | pipe_crc->head = head; |
1231 | |||
1232 | spin_unlock(&pipe_crc->lock); | ||
1227 | 1233 | ||
1228 | wake_up_interruptible(&pipe_crc->wq); | 1234 | wake_up_interruptible(&pipe_crc->wq); |
1229 | } | 1235 | } |