diff options
author | Marek Olšák <maraeo@gmail.com> | 2012-03-18 22:09:33 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2012-03-20 04:44:29 -0400 |
commit | 788571313870610bd7eb444e0fdc86f7e5541ee2 (patch) | |
tree | d793645cdc98918ca5323d8a555b0a45f11f4f79 /drivers | |
parent | 7df7c547c5aada8c6b9ee5ce14139e0ff5c66369 (diff) |
drm/radeon/kms: compute GPU addresses correctly on evergreen
There are also two fixes:
- In DRAW_INDEX_2, we read idx_value, but should have read idx+1.
- When correcting SQ_VTX_CONSTANT_WORD1_0.SIZE, we should subtract
the offset.
Signed-off-by: Marek Olšák <maraeo@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/evergreen_cs.c | 130 |
1 files changed, 103 insertions, 27 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 4674a688ad40..b39a089a15c3 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
@@ -1811,6 +1811,8 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
1811 | { | 1811 | { |
1812 | int pred_op; | 1812 | int pred_op; |
1813 | int tmp; | 1813 | int tmp; |
1814 | uint64_t offset; | ||
1815 | |||
1814 | if (pkt->count != 1) { | 1816 | if (pkt->count != 1) { |
1815 | DRM_ERROR("bad SET PREDICATION\n"); | 1817 | DRM_ERROR("bad SET PREDICATION\n"); |
1816 | return -EINVAL; | 1818 | return -EINVAL; |
@@ -1834,8 +1836,12 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
1834 | return -EINVAL; | 1836 | return -EINVAL; |
1835 | } | 1837 | } |
1836 | 1838 | ||
1837 | ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 1839 | offset = reloc->lobj.gpu_offset + |
1838 | ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff); | 1840 | (idx_value & 0xfffffff0) + |
1841 | ((u64)(tmp & 0xff) << 32); | ||
1842 | |||
1843 | ib[idx + 0] = offset; | ||
1844 | ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); | ||
1839 | } | 1845 | } |
1840 | break; | 1846 | break; |
1841 | case PACKET3_CONTEXT_CONTROL: | 1847 | case PACKET3_CONTEXT_CONTROL: |
@@ -1863,6 +1869,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
1863 | } | 1869 | } |
1864 | break; | 1870 | break; |
1865 | case PACKET3_INDEX_BASE: | 1871 | case PACKET3_INDEX_BASE: |
1872 | { | ||
1873 | uint64_t offset; | ||
1874 | |||
1866 | if (pkt->count != 1) { | 1875 | if (pkt->count != 1) { |
1867 | DRM_ERROR("bad INDEX_BASE\n"); | 1876 | DRM_ERROR("bad INDEX_BASE\n"); |
1868 | return -EINVAL; | 1877 | return -EINVAL; |
@@ -1872,15 +1881,24 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
1872 | DRM_ERROR("bad INDEX_BASE\n"); | 1881 | DRM_ERROR("bad INDEX_BASE\n"); |
1873 | return -EINVAL; | 1882 | return -EINVAL; |
1874 | } | 1883 | } |
1875 | ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 1884 | |
1876 | ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 1885 | offset = reloc->lobj.gpu_offset + |
1886 | idx_value + | ||
1887 | ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); | ||
1888 | |||
1889 | ib[idx+0] = offset; | ||
1890 | ib[idx+1] = upper_32_bits(offset) & 0xff; | ||
1891 | |||
1877 | r = evergreen_cs_track_check(p); | 1892 | r = evergreen_cs_track_check(p); |
1878 | if (r) { | 1893 | if (r) { |
1879 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); | 1894 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); |
1880 | return r; | 1895 | return r; |
1881 | } | 1896 | } |
1882 | break; | 1897 | break; |
1898 | } | ||
1883 | case PACKET3_DRAW_INDEX: | 1899 | case PACKET3_DRAW_INDEX: |
1900 | { | ||
1901 | uint64_t offset; | ||
1884 | if (pkt->count != 3) { | 1902 | if (pkt->count != 3) { |
1885 | DRM_ERROR("bad DRAW_INDEX\n"); | 1903 | DRM_ERROR("bad DRAW_INDEX\n"); |
1886 | return -EINVAL; | 1904 | return -EINVAL; |
@@ -1890,15 +1908,25 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
1890 | DRM_ERROR("bad DRAW_INDEX\n"); | 1908 | DRM_ERROR("bad DRAW_INDEX\n"); |
1891 | return -EINVAL; | 1909 | return -EINVAL; |
1892 | } | 1910 | } |
1893 | ib[idx+0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 1911 | |
1894 | ib[idx+1] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 1912 | offset = reloc->lobj.gpu_offset + |
1913 | idx_value + | ||
1914 | ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); | ||
1915 | |||
1916 | ib[idx+0] = offset; | ||
1917 | ib[idx+1] = upper_32_bits(offset) & 0xff; | ||
1918 | |||
1895 | r = evergreen_cs_track_check(p); | 1919 | r = evergreen_cs_track_check(p); |
1896 | if (r) { | 1920 | if (r) { |
1897 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); | 1921 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); |
1898 | return r; | 1922 | return r; |
1899 | } | 1923 | } |
1900 | break; | 1924 | break; |
1925 | } | ||
1901 | case PACKET3_DRAW_INDEX_2: | 1926 | case PACKET3_DRAW_INDEX_2: |
1927 | { | ||
1928 | uint64_t offset; | ||
1929 | |||
1902 | if (pkt->count != 4) { | 1930 | if (pkt->count != 4) { |
1903 | DRM_ERROR("bad DRAW_INDEX_2\n"); | 1931 | DRM_ERROR("bad DRAW_INDEX_2\n"); |
1904 | return -EINVAL; | 1932 | return -EINVAL; |
@@ -1908,14 +1936,21 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
1908 | DRM_ERROR("bad DRAW_INDEX_2\n"); | 1936 | DRM_ERROR("bad DRAW_INDEX_2\n"); |
1909 | return -EINVAL; | 1937 | return -EINVAL; |
1910 | } | 1938 | } |
1911 | ib[idx+1] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 1939 | |
1912 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 1940 | offset = reloc->lobj.gpu_offset + |
1941 | radeon_get_ib_value(p, idx+1) + | ||
1942 | ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); | ||
1943 | |||
1944 | ib[idx+1] = offset; | ||
1945 | ib[idx+2] = upper_32_bits(offset) & 0xff; | ||
1946 | |||
1913 | r = evergreen_cs_track_check(p); | 1947 | r = evergreen_cs_track_check(p); |
1914 | if (r) { | 1948 | if (r) { |
1915 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); | 1949 | dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); |
1916 | return r; | 1950 | return r; |
1917 | } | 1951 | } |
1918 | break; | 1952 | break; |
1953 | } | ||
1919 | case PACKET3_DRAW_INDEX_AUTO: | 1954 | case PACKET3_DRAW_INDEX_AUTO: |
1920 | if (pkt->count != 1) { | 1955 | if (pkt->count != 1) { |
1921 | DRM_ERROR("bad DRAW_INDEX_AUTO\n"); | 1956 | DRM_ERROR("bad DRAW_INDEX_AUTO\n"); |
@@ -2006,13 +2041,20 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2006 | } | 2041 | } |
2007 | /* bit 4 is reg (0) or mem (1) */ | 2042 | /* bit 4 is reg (0) or mem (1) */ |
2008 | if (idx_value & 0x10) { | 2043 | if (idx_value & 0x10) { |
2044 | uint64_t offset; | ||
2045 | |||
2009 | r = evergreen_cs_packet_next_reloc(p, &reloc); | 2046 | r = evergreen_cs_packet_next_reloc(p, &reloc); |
2010 | if (r) { | 2047 | if (r) { |
2011 | DRM_ERROR("bad WAIT_REG_MEM\n"); | 2048 | DRM_ERROR("bad WAIT_REG_MEM\n"); |
2012 | return -EINVAL; | 2049 | return -EINVAL; |
2013 | } | 2050 | } |
2014 | ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2051 | |
2015 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2052 | offset = reloc->lobj.gpu_offset + |
2053 | (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + | ||
2054 | ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); | ||
2055 | |||
2056 | ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc); | ||
2057 | ib[idx+2] = upper_32_bits(offset) & 0xff; | ||
2016 | } | 2058 | } |
2017 | break; | 2059 | break; |
2018 | case PACKET3_SURFACE_SYNC: | 2060 | case PACKET3_SURFACE_SYNC: |
@@ -2037,16 +2079,25 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2037 | return -EINVAL; | 2079 | return -EINVAL; |
2038 | } | 2080 | } |
2039 | if (pkt->count) { | 2081 | if (pkt->count) { |
2082 | uint64_t offset; | ||
2083 | |||
2040 | r = evergreen_cs_packet_next_reloc(p, &reloc); | 2084 | r = evergreen_cs_packet_next_reloc(p, &reloc); |
2041 | if (r) { | 2085 | if (r) { |
2042 | DRM_ERROR("bad EVENT_WRITE\n"); | 2086 | DRM_ERROR("bad EVENT_WRITE\n"); |
2043 | return -EINVAL; | 2087 | return -EINVAL; |
2044 | } | 2088 | } |
2045 | ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2089 | offset = reloc->lobj.gpu_offset + |
2046 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2090 | (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + |
2091 | ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); | ||
2092 | |||
2093 | ib[idx+1] = offset & 0xfffffff8; | ||
2094 | ib[idx+2] = upper_32_bits(offset) & 0xff; | ||
2047 | } | 2095 | } |
2048 | break; | 2096 | break; |
2049 | case PACKET3_EVENT_WRITE_EOP: | 2097 | case PACKET3_EVENT_WRITE_EOP: |
2098 | { | ||
2099 | uint64_t offset; | ||
2100 | |||
2050 | if (pkt->count != 4) { | 2101 | if (pkt->count != 4) { |
2051 | DRM_ERROR("bad EVENT_WRITE_EOP\n"); | 2102 | DRM_ERROR("bad EVENT_WRITE_EOP\n"); |
2052 | return -EINVAL; | 2103 | return -EINVAL; |
@@ -2056,10 +2107,19 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2056 | DRM_ERROR("bad EVENT_WRITE_EOP\n"); | 2107 | DRM_ERROR("bad EVENT_WRITE_EOP\n"); |
2057 | return -EINVAL; | 2108 | return -EINVAL; |
2058 | } | 2109 | } |
2059 | ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2110 | |
2060 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2111 | offset = reloc->lobj.gpu_offset + |
2112 | (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + | ||
2113 | ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); | ||
2114 | |||
2115 | ib[idx+1] = offset & 0xfffffffc; | ||
2116 | ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); | ||
2061 | break; | 2117 | break; |
2118 | } | ||
2062 | case PACKET3_EVENT_WRITE_EOS: | 2119 | case PACKET3_EVENT_WRITE_EOS: |
2120 | { | ||
2121 | uint64_t offset; | ||
2122 | |||
2063 | if (pkt->count != 3) { | 2123 | if (pkt->count != 3) { |
2064 | DRM_ERROR("bad EVENT_WRITE_EOS\n"); | 2124 | DRM_ERROR("bad EVENT_WRITE_EOS\n"); |
2065 | return -EINVAL; | 2125 | return -EINVAL; |
@@ -2069,9 +2129,15 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2069 | DRM_ERROR("bad EVENT_WRITE_EOS\n"); | 2129 | DRM_ERROR("bad EVENT_WRITE_EOS\n"); |
2070 | return -EINVAL; | 2130 | return -EINVAL; |
2071 | } | 2131 | } |
2072 | ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2132 | |
2073 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2133 | offset = reloc->lobj.gpu_offset + |
2134 | (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + | ||
2135 | ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); | ||
2136 | |||
2137 | ib[idx+1] = offset & 0xfffffffc; | ||
2138 | ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); | ||
2074 | break; | 2139 | break; |
2140 | } | ||
2075 | case PACKET3_SET_CONFIG_REG: | 2141 | case PACKET3_SET_CONFIG_REG: |
2076 | start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; | 2142 | start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; |
2077 | end_reg = 4 * pkt->count + start_reg - 4; | 2143 | end_reg = 4 * pkt->count + start_reg - 4; |
@@ -2164,6 +2230,8 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2164 | ib[idx+1+(i*8)+3] += moffset; | 2230 | ib[idx+1+(i*8)+3] += moffset; |
2165 | break; | 2231 | break; |
2166 | case SQ_TEX_VTX_VALID_BUFFER: | 2232 | case SQ_TEX_VTX_VALID_BUFFER: |
2233 | { | ||
2234 | uint64_t offset64; | ||
2167 | /* vtx base */ | 2235 | /* vtx base */ |
2168 | r = evergreen_cs_packet_next_reloc(p, &reloc); | 2236 | r = evergreen_cs_packet_next_reloc(p, &reloc); |
2169 | if (r) { | 2237 | if (r) { |
@@ -2175,11 +2243,15 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2175 | if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { | 2243 | if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { |
2176 | /* force size to size of the buffer */ | 2244 | /* force size to size of the buffer */ |
2177 | dev_warn(p->dev, "vbo resource seems too big for the bo\n"); | 2245 | dev_warn(p->dev, "vbo resource seems too big for the bo\n"); |
2178 | ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj); | 2246 | ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset; |
2179 | } | 2247 | } |
2180 | ib[idx+1+(i*8)+0] += (u32)((reloc->lobj.gpu_offset) & 0xffffffff); | 2248 | |
2181 | ib[idx+1+(i*8)+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2249 | offset64 = reloc->lobj.gpu_offset + offset; |
2250 | ib[idx+1+(i*8)+0] = offset64; | ||
2251 | ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | | ||
2252 | (upper_32_bits(offset64) & 0xff); | ||
2182 | break; | 2253 | break; |
2254 | } | ||
2183 | case SQ_TEX_VTX_INVALID_TEXTURE: | 2255 | case SQ_TEX_VTX_INVALID_TEXTURE: |
2184 | case SQ_TEX_VTX_INVALID_BUFFER: | 2256 | case SQ_TEX_VTX_INVALID_BUFFER: |
2185 | default: | 2257 | default: |
@@ -2255,8 +2327,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2255 | offset + 4, radeon_bo_size(reloc->robj)); | 2327 | offset + 4, radeon_bo_size(reloc->robj)); |
2256 | return -EINVAL; | 2328 | return -EINVAL; |
2257 | } | 2329 | } |
2258 | ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2330 | offset += reloc->lobj.gpu_offset; |
2259 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2331 | ib[idx+1] = offset; |
2332 | ib[idx+2] = upper_32_bits(offset) & 0xff; | ||
2260 | } | 2333 | } |
2261 | /* Reading data from SRC_ADDRESS. */ | 2334 | /* Reading data from SRC_ADDRESS. */ |
2262 | if (((idx_value >> 1) & 0x3) == 2) { | 2335 | if (((idx_value >> 1) & 0x3) == 2) { |
@@ -2273,8 +2346,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2273 | offset + 4, radeon_bo_size(reloc->robj)); | 2346 | offset + 4, radeon_bo_size(reloc->robj)); |
2274 | return -EINVAL; | 2347 | return -EINVAL; |
2275 | } | 2348 | } |
2276 | ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2349 | offset += reloc->lobj.gpu_offset; |
2277 | ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2350 | ib[idx+3] = offset; |
2351 | ib[idx+4] = upper_32_bits(offset) & 0xff; | ||
2278 | } | 2352 | } |
2279 | break; | 2353 | break; |
2280 | case PACKET3_COPY_DW: | 2354 | case PACKET3_COPY_DW: |
@@ -2297,8 +2371,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2297 | offset + 4, radeon_bo_size(reloc->robj)); | 2371 | offset + 4, radeon_bo_size(reloc->robj)); |
2298 | return -EINVAL; | 2372 | return -EINVAL; |
2299 | } | 2373 | } |
2300 | ib[idx+1] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2374 | offset += reloc->lobj.gpu_offset; |
2301 | ib[idx+2] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2375 | ib[idx+1] = offset; |
2376 | ib[idx+2] = upper_32_bits(offset) & 0xff; | ||
2302 | } else { | 2377 | } else { |
2303 | /* SRC is a reg. */ | 2378 | /* SRC is a reg. */ |
2304 | reg = radeon_get_ib_value(p, idx+1) << 2; | 2379 | reg = radeon_get_ib_value(p, idx+1) << 2; |
@@ -2320,8 +2395,9 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
2320 | offset + 4, radeon_bo_size(reloc->robj)); | 2395 | offset + 4, radeon_bo_size(reloc->robj)); |
2321 | return -EINVAL; | 2396 | return -EINVAL; |
2322 | } | 2397 | } |
2323 | ib[idx+3] += (u32)(reloc->lobj.gpu_offset & 0xffffffff); | 2398 | offset += reloc->lobj.gpu_offset; |
2324 | ib[idx+4] += upper_32_bits(reloc->lobj.gpu_offset) & 0xff; | 2399 | ib[idx+3] = offset; |
2400 | ib[idx+4] = upper_32_bits(offset) & 0xff; | ||
2325 | } else { | 2401 | } else { |
2326 | /* DST is a reg. */ | 2402 | /* DST is a reg. */ |
2327 | reg = radeon_get_ib_value(p, idx+3) << 2; | 2403 | reg = radeon_get_ib_value(p, idx+3) << 2; |