aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Lespiau <damien.lespiau@intel.com>2013-10-15 13:55:40 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-16 07:32:16 -0400
commit071444280bcbb96ec38a1fb1ee3924ca7860844a (patch)
tree49171943b164c5f1c00fc3418e43500834e9e681
parent497666d80587933fc65dbe40d8fe6b6cc89ac9ad (diff)
drm/i915: Implement blocking read for pipe CRC files
seq_file is not quite the right interface for these ones. We have a circular buffer with a new entry per vblank on one side and a process wanting to dequeue the CRC with a read(). It's quite racy to wait for vblank in user land and then try to read a pipe_crc file, sometimes the CRC interrupt hasn't been fired and we end up with an EOF. So, let's have the read on the pipe_crc file block until the interrupt gives us a new entry. At that point we can wake the reading process. Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c164
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h6
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c2
4 files changed, 155 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index baa2e430bd5b..5137f8f97b8a 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1760,37 +1760,138 @@ static int i915_pc8_status(struct seq_file *m, void *unused)
1760 return 0; 1760 return 0;
1761} 1761}
1762 1762
1763static int i915_pipe_crc(struct seq_file *m, void *data) 1763struct pipe_crc_info {
1764 const char *name;
1765 struct drm_device *dev;
1766 enum pipe pipe;
1767};
1768
1769static int i915_pipe_crc_open(struct inode *inode, struct file *filep)
1770{
1771 filep->private_data = inode->i_private;
1772
1773 return 0;
1774}
1775
1776static int i915_pipe_crc_release(struct inode *inode, struct file *filep)
1777{
1778 return 0;
1779}
1780
1781/* (6 fields, 8 chars each, space separated (5) + '\n') */
1782#define PIPE_CRC_LINE_LEN (6 * 8 + 5 + 1)
1783/* account for \'0' */
1784#define PIPE_CRC_BUFFER_LEN (PIPE_CRC_LINE_LEN + 1)
1785
1786static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc)
1764{ 1787{
1765 struct drm_info_node *node = (struct drm_info_node *) m->private;
1766 struct drm_device *dev = node->minor->dev;
1767 struct drm_i915_private *dev_priv = dev->dev_private;
1768 enum pipe pipe = (enum pipe)node->info_ent->data;
1769 struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe];
1770 int head, tail; 1788 int head, tail;
1771 1789
1772 if (dev_priv->pipe_crc[pipe].source == INTEL_PIPE_CRC_SOURCE_NONE) { 1790 head = atomic_read(&pipe_crc->head);
1773 seq_puts(m, "none\n"); 1791 tail = atomic_read(&pipe_crc->tail);
1792
1793 return CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR);
1794}
1795
1796static ssize_t
1797i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count,
1798 loff_t *pos)
1799{
1800 struct pipe_crc_info *info = filep->private_data;
1801 struct drm_device *dev = info->dev;
1802 struct drm_i915_private *dev_priv = dev->dev_private;
1803 struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe];
1804 char buf[PIPE_CRC_BUFFER_LEN];
1805 int head, tail, n_entries, n;
1806 ssize_t bytes_read;
1807
1808 /*
1809 * Don't allow user space to provide buffers not big enough to hold
1810 * a line of data.
1811 */
1812 if (count < PIPE_CRC_LINE_LEN)
1813 return -EINVAL;
1814
1815 if (pipe_crc->source == INTEL_PIPE_CRC_SOURCE_NONE)
1774 return 0; 1816 return 0;
1817
1818 /* nothing to read */
1819 while (pipe_crc_data_count(pipe_crc) == 0) {
1820 if (filep->f_flags & O_NONBLOCK)
1821 return -EAGAIN;
1822
1823 if (wait_event_interruptible(pipe_crc->wq,
1824 pipe_crc_data_count(pipe_crc)))
1825 return -ERESTARTSYS;
1775 } 1826 }
1776 1827
1777 seq_puts(m, " frame CRC1 CRC2 CRC3 CRC4 CRC5\n"); 1828 /* We now have one or more entries to read */
1778 head = atomic_read(&pipe_crc->head); 1829 head = atomic_read(&pipe_crc->head);
1779 tail = atomic_read(&pipe_crc->tail); 1830 tail = atomic_read(&pipe_crc->tail);
1780 1831 n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR),
1781 while (CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) >= 1) { 1832 count / PIPE_CRC_LINE_LEN);
1833 bytes_read = 0;
1834 n = 0;
1835 do {
1782 struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail]; 1836 struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail];
1837 int ret;
1783 1838
1784 seq_printf(m, "%8u %8x %8x %8x %8x %8x\n", entry->frame, 1839 bytes_read += snprintf(buf, PIPE_CRC_BUFFER_LEN,
1785 entry->crc[0], entry->crc[1], entry->crc[2], 1840 "%8u %8x %8x %8x %8x %8x\n",
1786 entry->crc[3], entry->crc[4]); 1841 entry->frame, entry->crc[0],
1842 entry->crc[1], entry->crc[2],
1843 entry->crc[3], entry->crc[4]);
1844
1845 ret = copy_to_user(user_buf + n * PIPE_CRC_LINE_LEN,
1846 buf, PIPE_CRC_LINE_LEN);
1847 if (ret == PIPE_CRC_LINE_LEN)
1848 return -EFAULT;
1787 1849
1788 BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); 1850 BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR);
1789 tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); 1851 tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1);
1790 atomic_set(&pipe_crc->tail, tail); 1852 atomic_set(&pipe_crc->tail, tail);
1791 } 1853 n++;
1854 } while (--n_entries);
1792 1855
1793 return 0; 1856 return bytes_read;
1857}
1858
1859static const struct file_operations i915_pipe_crc_fops = {
1860 .owner = THIS_MODULE,
1861 .open = i915_pipe_crc_open,
1862 .read = i915_pipe_crc_read,
1863 .release = i915_pipe_crc_release,
1864};
1865
1866static struct pipe_crc_info i915_pipe_crc_data[I915_MAX_PIPES] = {
1867 {
1868 .name = "i915_pipe_A_crc",
1869 .pipe = PIPE_A,
1870 },
1871 {
1872 .name = "i915_pipe_B_crc",
1873 .pipe = PIPE_B,
1874 },
1875 {
1876 .name = "i915_pipe_C_crc",
1877 .pipe = PIPE_C,
1878 },
1879};
1880
1881static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor,
1882 enum pipe pipe)
1883{
1884 struct drm_device *dev = minor->dev;
1885 struct dentry *ent;
1886 struct pipe_crc_info *info = &i915_pipe_crc_data[pipe];
1887
1888 info->dev = dev;
1889 ent = debugfs_create_file(info->name, S_IRUGO, root, info,
1890 &i915_pipe_crc_fops);
1891 if (IS_ERR(ent))
1892 return PTR_ERR(ent);
1893
1894 return drm_add_fake_info_node(minor, ent, info);
1794} 1895}
1795 1896
1796static const char *pipe_crc_sources[] = { 1897static const char *pipe_crc_sources[] = {
@@ -2555,9 +2656,6 @@ static struct drm_info_list i915_debugfs_list[] = {
2555 {"i915_edp_psr_status", i915_edp_psr_status, 0}, 2656 {"i915_edp_psr_status", i915_edp_psr_status, 0},
2556 {"i915_energy_uJ", i915_energy_uJ, 0}, 2657 {"i915_energy_uJ", i915_energy_uJ, 0},
2557 {"i915_pc8_status", i915_pc8_status, 0}, 2658 {"i915_pc8_status", i915_pc8_status, 0},
2558 {"i915_pipe_A_crc", i915_pipe_crc, 0, (void *)PIPE_A},
2559 {"i915_pipe_B_crc", i915_pipe_crc, 0, (void *)PIPE_B},
2560 {"i915_pipe_C_crc", i915_pipe_crc, 0, (void *)PIPE_C},
2561}; 2659};
2562#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) 2660#define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
2563 2661
@@ -2578,6 +2676,18 @@ static struct i915_debugfs_files {
2578 {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, 2676 {"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
2579}; 2677};
2580 2678
2679void intel_display_crc_init(struct drm_device *dev)
2680{
2681 struct drm_i915_private *dev_priv = dev->dev_private;
2682 int i;
2683
2684 for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
2685 struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i];
2686
2687 init_waitqueue_head(&pipe_crc->wq);
2688 }
2689}
2690
2581int i915_debugfs_init(struct drm_minor *minor) 2691int i915_debugfs_init(struct drm_minor *minor)
2582{ 2692{
2583 int ret, i; 2693 int ret, i;
@@ -2586,6 +2696,12 @@ int i915_debugfs_init(struct drm_minor *minor)
2586 if (ret) 2696 if (ret)
2587 return ret; 2697 return ret;
2588 2698
2699 for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) {
2700 ret = i915_pipe_crc_create(minor->debugfs_root, minor, i);
2701 if (ret)
2702 return ret;
2703 }
2704
2589 for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { 2705 for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
2590 ret = i915_debugfs_create(minor->debugfs_root, minor, 2706 ret = i915_debugfs_create(minor->debugfs_root, minor,
2591 i915_debugfs_files[i].name, 2707 i915_debugfs_files[i].name,
@@ -2601,12 +2717,22 @@ int i915_debugfs_init(struct drm_minor *minor)
2601 2717
2602void i915_debugfs_cleanup(struct drm_minor *minor) 2718void i915_debugfs_cleanup(struct drm_minor *minor)
2603{ 2719{
2720 struct drm_device *dev = minor->dev;
2604 int i; 2721 int i;
2605 2722
2606 drm_debugfs_remove_files(i915_debugfs_list, 2723 drm_debugfs_remove_files(i915_debugfs_list,
2607 I915_DEBUGFS_ENTRIES, minor); 2724 I915_DEBUGFS_ENTRIES, minor);
2725
2608 drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, 2726 drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops,
2609 1, minor); 2727 1, minor);
2728
2729 for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) {
2730 struct drm_info_list *info_list =
2731 (struct drm_info_list *)&i915_pipe_crc_data[i];
2732
2733 drm_debugfs_remove_files(info_list, 1, minor);
2734 }
2735
2610 for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { 2736 for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) {
2611 struct drm_info_list *info_list = 2737 struct drm_info_list *info_list =
2612 (struct drm_info_list *) i915_debugfs_files[i].fops; 2738 (struct drm_info_list *) i915_debugfs_files[i].fops;
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 42cddc11c23c..9f71bc204e38 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -1514,6 +1514,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
1514 dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ 1514 dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */
1515 INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); 1515 INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work);
1516 1516
1517 intel_display_crc_init(dev);
1518
1517 i915_dump_device_info(dev_priv); 1519 i915_dump_device_info(dev_priv);
1518 1520
1519 /* Not all pre-production machines fall into this category, only the 1521 /* Not all pre-production machines fall into this category, only the
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1faeaac5f9f3..7408f1184347 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1235,6 +1235,7 @@ struct intel_pipe_crc {
1235 struct intel_pipe_crc_entry *entries; 1235 struct intel_pipe_crc_entry *entries;
1236 enum intel_pipe_crc_source source; 1236 enum intel_pipe_crc_source source;
1237 atomic_t head, tail; 1237 atomic_t head, tail;
1238 wait_queue_head_t wq;
1238}; 1239};
1239 1240
1240typedef struct drm_i915_private { 1241typedef struct drm_i915_private {
@@ -2233,6 +2234,11 @@ int i915_verify_lists(struct drm_device *dev);
2233/* i915_debugfs.c */ 2234/* i915_debugfs.c */
2234int i915_debugfs_init(struct drm_minor *minor); 2235int i915_debugfs_init(struct drm_minor *minor);
2235void i915_debugfs_cleanup(struct drm_minor *minor); 2236void i915_debugfs_cleanup(struct drm_minor *minor);
2237#if defined(CONFIG_DEBUG_FS)
2238void intel_display_crc_init(struct drm_device *dev);
2239#else
2240void intel_display_crc_init(struct drm_device *dev) {}
2241#endif
2236 2242
2237/* i915_gpu_error.c */ 2243/* i915_gpu_error.c */
2238__printf(2, 3) 2244__printf(2, 3)
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index b201a214279e..b2be05791b2f 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1221,6 +1221,8 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe)
1221 1221
1222 head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); 1222 head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1);
1223 atomic_set(&pipe_crc->head, head); 1223 atomic_set(&pipe_crc->head, head);
1224
1225 wake_up_interruptible(&pipe_crc->wq);
1224} 1226}
1225#else 1227#else
1226static void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} 1228static void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {}