aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c66
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h5
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c12
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
1801static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc) 1808static 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
1811static ssize_t 1815static 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
1251struct intel_pipe_crc { 1251struct 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}