aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_debugfs.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-16 07:30:34 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-10-16 07:32:04 -0400
commit926321d503406d1fefb2fae9651beca14160529a (patch)
tree593caafe1fbc7df1427190df3e0cc8d990de4287 /drivers/gpu/drm/i915/i915_debugfs.c
parent8bf1e9f1d2aa1fafd2b262683a13cbb7f934c6d0 (diff)
drm/i915: Add a control file for pipe CRCs
Note the "return -ENODEV;" in pipe_crc_set_source(). The ctl file is disabled until the end of the series to be able to do incremental improvements. Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_debugfs.c')
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c217
1 files changed, 215 insertions, 2 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index e1d45aaf6881..0d8a9a397a24 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -27,6 +27,7 @@
27 */ 27 */
28 28
29#include <linux/seq_file.h> 29#include <linux/seq_file.h>
30#include <linux/ctype.h>
30#include <linux/debugfs.h> 31#include <linux/debugfs.h>
31#include <linux/slab.h> 32#include <linux/slab.h>
32#include <linux/export.h> 33#include <linux/export.h>
@@ -1742,8 +1743,8 @@ static int i915_pipe_crc(struct seq_file *m, void *data)
1742 int i; 1743 int i;
1743 int start; 1744 int start;
1744 1745
1745 if (!IS_IVYBRIDGE(dev)) { 1746 if (dev_priv->pipe_crc[pipe].source == INTEL_PIPE_CRC_SOURCE_NONE) {
1746 seq_puts(m, "unsupported\n"); 1747 seq_puts(m, "none\n");
1747 return 0; 1748 return 0;
1748 } 1749 }
1749 1750
@@ -1762,6 +1763,217 @@ static int i915_pipe_crc(struct seq_file *m, void *data)
1762 return 0; 1763 return 0;
1763} 1764}
1764 1765
1766static const char *pipe_crc_sources[] = {
1767 "none",
1768 "plane1",
1769 "plane2",
1770 "pf",
1771};
1772
1773static const char *pipe_crc_source_name(enum intel_pipe_crc_source source)
1774{
1775 BUILD_BUG_ON(ARRAY_SIZE(pipe_crc_sources) != INTEL_PIPE_CRC_SOURCE_MAX);
1776 return pipe_crc_sources[source];
1777}
1778
1779static int pipe_crc_ctl_show(struct seq_file *m, void *data)
1780{
1781 struct drm_device *dev = m->private;
1782 struct drm_i915_private *dev_priv = dev->dev_private;
1783 int i;
1784
1785 for (i = 0; i < I915_MAX_PIPES; i++)
1786 seq_printf(m, "%c %s\n", pipe_name(i),
1787 pipe_crc_source_name(dev_priv->pipe_crc[i].source));
1788
1789 return 0;
1790}
1791
1792static int pipe_crc_ctl_open(struct inode *inode, struct file *file)
1793{
1794 struct drm_device *dev = inode->i_private;
1795
1796 return single_open(file, pipe_crc_ctl_show, dev);
1797}
1798
1799static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
1800 enum intel_pipe_crc_source source)
1801{
1802 struct drm_i915_private *dev_priv = dev->dev_private;
1803 u32 val;
1804
1805
1806 return -ENODEV;
1807
1808 if (!IS_IVYBRIDGE(dev))
1809 return -ENODEV;
1810
1811 dev_priv->pipe_crc[pipe].source = source;
1812
1813 switch (source) {
1814 case INTEL_PIPE_CRC_SOURCE_PLANE1:
1815 val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB;
1816 break;
1817 case INTEL_PIPE_CRC_SOURCE_PLANE2:
1818 val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB;
1819 break;
1820 case INTEL_PIPE_CRC_SOURCE_PF:
1821 val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB;
1822 break;
1823 case INTEL_PIPE_CRC_SOURCE_NONE:
1824 default:
1825 val = 0;
1826 break;
1827 }
1828
1829 I915_WRITE(PIPE_CRC_CTL(pipe), val);
1830 POSTING_READ(PIPE_CRC_CTL(pipe));
1831
1832 return 0;
1833}
1834
1835/*
1836 * Parse pipe CRC command strings:
1837 * command: wsp* pipe wsp+ source wsp*
1838 * pipe: (A | B | C)
1839 * source: (none | plane1 | plane2 | pf)
1840 * wsp: (#0x20 | #0x9 | #0xA)+
1841 *
1842 * eg.:
1843 * "A plane1" -> Start CRC computations on plane1 of pipe A
1844 * "A none" -> Stop CRC
1845 */
1846static int pipe_crc_ctl_tokenize(char *buf, char *words[], int max_words)
1847{
1848 int n_words = 0;
1849
1850 while (*buf) {
1851 char *end;
1852
1853 /* skip leading white space */
1854 buf = skip_spaces(buf);
1855 if (!*buf)
1856 break; /* end of buffer */
1857
1858 /* find end of word */
1859 for (end = buf; *end && !isspace(*end); end++)
1860 ;
1861
1862 if (n_words == max_words) {
1863 DRM_DEBUG_DRIVER("too many words, allowed <= %d\n",
1864 max_words);
1865 return -EINVAL; /* ran out of words[] before bytes */
1866 }
1867
1868 if (*end)
1869 *end++ = '\0';
1870 words[n_words++] = buf;
1871 buf = end;
1872 }
1873
1874 return n_words;
1875}
1876
1877static int pipe_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe)
1878{
1879 const char name = buf[0];
1880
1881 if (name < 'A' || name >= pipe_name(I915_MAX_PIPES))
1882 return -EINVAL;
1883
1884 *pipe = name - 'A';
1885
1886 return 0;
1887}
1888
1889static int
1890pipe_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *source)
1891{
1892 int i;
1893
1894 for (i = 0; i < ARRAY_SIZE(pipe_crc_sources); i++)
1895 if (!strcmp(buf, pipe_crc_sources[i])) {
1896 *source = i;
1897 return 0;
1898 }
1899
1900 return -EINVAL;
1901}
1902
1903static int pipe_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len)
1904{
1905#define MAX_WORDS 2
1906 int n_words;
1907 char *words[MAX_WORDS];
1908 enum pipe pipe;
1909 enum intel_pipe_crc_source source;
1910
1911 n_words = pipe_crc_ctl_tokenize(buf, words, MAX_WORDS);
1912 if (n_words != 2) {
1913 DRM_DEBUG_DRIVER("tokenize failed, a command is 2 words\n");
1914 return -EINVAL;
1915 }
1916
1917 if (pipe_crc_ctl_parse_pipe(words[0], &pipe) < 0) {
1918 DRM_DEBUG_DRIVER("unknown pipe %s\n", words[0]);
1919 return -EINVAL;
1920 }
1921
1922 if (pipe_crc_ctl_parse_source(words[1], &source) < 0) {
1923 DRM_DEBUG_DRIVER("unknown source %s\n", words[1]);
1924 return -EINVAL;
1925 }
1926
1927 return pipe_crc_set_source(dev, pipe, source);
1928}
1929
1930static ssize_t pipe_crc_ctl_write(struct file *file, const char __user *ubuf,
1931 size_t len, loff_t *offp)
1932{
1933 struct seq_file *m = file->private_data;
1934 struct drm_device *dev = m->private;
1935 char *tmpbuf;
1936 int ret;
1937
1938 if (len == 0)
1939 return 0;
1940
1941 if (len > PAGE_SIZE - 1) {
1942 DRM_DEBUG_DRIVER("expected <%lu bytes into pipe crc control\n",
1943 PAGE_SIZE);
1944 return -E2BIG;
1945 }
1946
1947 tmpbuf = kmalloc(len + 1, GFP_KERNEL);
1948 if (!tmpbuf)
1949 return -ENOMEM;
1950
1951 if (copy_from_user(tmpbuf, ubuf, len)) {
1952 ret = -EFAULT;
1953 goto out;
1954 }
1955 tmpbuf[len] = '\0';
1956
1957 ret = pipe_crc_ctl_parse(dev, tmpbuf, len);
1958
1959out:
1960 kfree(tmpbuf);
1961 if (ret < 0)
1962 return ret;
1963
1964 *offp += len;
1965 return len;
1966}
1967
1968static const struct file_operations i915_pipe_crc_ctl_fops = {
1969 .owner = THIS_MODULE,
1970 .open = pipe_crc_ctl_open,
1971 .read = seq_read,
1972 .llseek = seq_lseek,
1973 .release = single_release,
1974 .write = pipe_crc_ctl_write
1975};
1976
1765static int 1977static int
1766i915_wedged_get(void *data, u64 *val) 1978i915_wedged_get(void *data, u64 *val)
1767{ 1979{
@@ -2297,6 +2509,7 @@ static struct i915_debugfs_files {
2297 {"i915_gem_drop_caches", &i915_drop_caches_fops}, 2509 {"i915_gem_drop_caches", &i915_drop_caches_fops},
2298 {"i915_error_state", &i915_error_state_fops}, 2510 {"i915_error_state", &i915_error_state_fops},
2299 {"i915_next_seqno", &i915_next_seqno_fops}, 2511 {"i915_next_seqno", &i915_next_seqno_fops},
2512 {"i915_pipe_crc_ctl", &i915_pipe_crc_ctl_fops},
2300}; 2513};
2301 2514
2302int i915_debugfs_init(struct drm_minor *minor) 2515int i915_debugfs_init(struct drm_minor *minor)