diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/evergreen_cs.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index c042e497e450..5435879ad535 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
| @@ -2232,6 +2232,95 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
| 2232 | ib[idx+2] = upper_32_bits(offset) & 0xff; | 2232 | ib[idx+2] = upper_32_bits(offset) & 0xff; |
| 2233 | } | 2233 | } |
| 2234 | break; | 2234 | break; |
| 2235 | case PACKET3_CP_DMA: | ||
| 2236 | { | ||
| 2237 | u32 command, size, info; | ||
| 2238 | u64 offset, tmp; | ||
| 2239 | if (pkt->count != 4) { | ||
| 2240 | DRM_ERROR("bad CP DMA\n"); | ||
| 2241 | return -EINVAL; | ||
| 2242 | } | ||
| 2243 | command = radeon_get_ib_value(p, idx+4); | ||
| 2244 | size = command & 0x1fffff; | ||
| 2245 | info = radeon_get_ib_value(p, idx+1); | ||
| 2246 | if (command & PACKET3_CP_DMA_CMD_SAS) { | ||
| 2247 | /* src address space is register */ | ||
| 2248 | /* GDS is ok */ | ||
| 2249 | if (((info & 0x60000000) >> 29) != 1) { | ||
| 2250 | DRM_ERROR("CP DMA SAS not supported\n"); | ||
| 2251 | return -EINVAL; | ||
| 2252 | } | ||
| 2253 | } else { | ||
| 2254 | if (command & PACKET3_CP_DMA_CMD_SAIC) { | ||
| 2255 | DRM_ERROR("CP DMA SAIC only supported for registers\n"); | ||
| 2256 | return -EINVAL; | ||
| 2257 | } | ||
| 2258 | /* src address space is memory */ | ||
| 2259 | if (((info & 0x60000000) >> 29) == 0) { | ||
| 2260 | r = evergreen_cs_packet_next_reloc(p, &reloc); | ||
| 2261 | if (r) { | ||
| 2262 | DRM_ERROR("bad CP DMA SRC\n"); | ||
| 2263 | return -EINVAL; | ||
| 2264 | } | ||
| 2265 | |||
| 2266 | tmp = radeon_get_ib_value(p, idx) + | ||
| 2267 | ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); | ||
| 2268 | |||
| 2269 | offset = reloc->lobj.gpu_offset + tmp; | ||
| 2270 | |||
| 2271 | if ((tmp + size) > radeon_bo_size(reloc->robj)) { | ||
| 2272 | dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n", | ||
| 2273 | tmp + size, radeon_bo_size(reloc->robj)); | ||
| 2274 | return -EINVAL; | ||
| 2275 | } | ||
| 2276 | |||
| 2277 | ib[idx] = offset; | ||
| 2278 | ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff); | ||
| 2279 | } else if (((info & 0x60000000) >> 29) != 2) { | ||
| 2280 | DRM_ERROR("bad CP DMA SRC_SEL\n"); | ||
| 2281 | return -EINVAL; | ||
| 2282 | } | ||
| 2283 | } | ||
| 2284 | if (command & PACKET3_CP_DMA_CMD_DAS) { | ||
| 2285 | /* dst address space is register */ | ||
| 2286 | /* GDS is ok */ | ||
| 2287 | if (((info & 0x00300000) >> 20) != 1) { | ||
| 2288 | DRM_ERROR("CP DMA DAS not supported\n"); | ||
| 2289 | return -EINVAL; | ||
| 2290 | } | ||
| 2291 | } else { | ||
| 2292 | /* dst address space is memory */ | ||
| 2293 | if (command & PACKET3_CP_DMA_CMD_DAIC) { | ||
| 2294 | DRM_ERROR("CP DMA DAIC only supported for registers\n"); | ||
| 2295 | return -EINVAL; | ||
| 2296 | } | ||
| 2297 | if (((info & 0x00300000) >> 20) == 0) { | ||
| 2298 | r = evergreen_cs_packet_next_reloc(p, &reloc); | ||
| 2299 | if (r) { | ||
| 2300 | DRM_ERROR("bad CP DMA DST\n"); | ||
| 2301 | return -EINVAL; | ||
| 2302 | } | ||
| 2303 | |||
| 2304 | tmp = radeon_get_ib_value(p, idx+2) + | ||
| 2305 | ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32); | ||
| 2306 | |||
| 2307 | offset = reloc->lobj.gpu_offset + tmp; | ||
| 2308 | |||
| 2309 | if ((tmp + size) > radeon_bo_size(reloc->robj)) { | ||
| 2310 | dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n", | ||
| 2311 | tmp + size, radeon_bo_size(reloc->robj)); | ||
| 2312 | return -EINVAL; | ||
| 2313 | } | ||
| 2314 | |||
| 2315 | ib[idx+2] = offset; | ||
| 2316 | ib[idx+3] = upper_32_bits(offset) & 0xff; | ||
| 2317 | } else { | ||
| 2318 | DRM_ERROR("bad CP DMA DST_SEL\n"); | ||
| 2319 | return -EINVAL; | ||
| 2320 | } | ||
| 2321 | } | ||
| 2322 | break; | ||
| 2323 | } | ||
| 2235 | case PACKET3_SURFACE_SYNC: | 2324 | case PACKET3_SURFACE_SYNC: |
| 2236 | if (pkt->count != 3) { | 2325 | if (pkt->count != 3) { |
| 2237 | DRM_ERROR("bad SURFACE_SYNC\n"); | 2326 | DRM_ERROR("bad SURFACE_SYNC\n"); |
