diff options
| author | Dave Airlie <airlied@redhat.com> | 2012-12-15 17:15:18 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-12-15 17:15:18 -0500 |
| commit | 652a187664902399d34f5b3a084fdbb51b2ca12f (patch) | |
| tree | a2ecda4e8167c94a31d22442360401418c2abab6 | |
| parent | 9add1ac3dd256ad12e266f8403daf928be19953f (diff) | |
| parent | dd54fee7d440c4a9756cce2c24a50c15e4c17ccb (diff) | |
Merge branch 'drm-next-3.8' of git://people.freedesktop.org/~agd5f/linux into drm-next
Fix regression, and some locking races, also as CS support
for the DMA engines.
* 'drm-next-3.8' of git://people.freedesktop.org/~agd5f/linux:
radeon: fix regression with eviction since evict caching changes
drm/radeon: add more pedantic checks in the CP DMA checker
drm/radeon: bump version for CS ioctl support for async DMA
drm/radeon: enable the async DMA rings in the CS ioctl
drm/radeon: add VM CS parser support for async DMA on cayman/TN/SI
drm/radeon/kms: add evergreen/cayman CS parser for async DMA (v2)
drm/radeon/kms: add 6xx/7xx CS parser for async DMA (v2)
drm/radeon: fix htile buffer size computation for command stream checker
drm/radeon: fix fence locking in the pageflip callback
drm/radeon: make indirect register access concurrency-safe
drm/radeon: add W|RREG32_IDX for MM_INDEX|DATA based mmio accesss
| -rw-r--r-- | drivers/gpu/drm/radeon/evergreen_cs.c | 603 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 23 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_cs.c | 285 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 19 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.c | 26 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_asic.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_combios.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cp.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cs.c | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_cursor.c | 17 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_device.c | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_object.c | 4 | ||||
| -rw-r--r-- | include/uapi/drm/radeon_drm.h | 1 |
16 files changed, 897 insertions, 127 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 62c227104781..74c6b42d2597 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #define MAX(a,b) (((a)>(b))?(a):(b)) | 34 | #define MAX(a,b) (((a)>(b))?(a):(b)) |
| 35 | #define MIN(a,b) (((a)<(b))?(a):(b)) | 35 | #define MIN(a,b) (((a)<(b))?(a):(b)) |
| 36 | 36 | ||
| 37 | int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, | ||
| 38 | struct radeon_cs_reloc **cs_reloc); | ||
| 37 | static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, | 39 | static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p, |
| 38 | struct radeon_cs_reloc **cs_reloc); | 40 | struct radeon_cs_reloc **cs_reloc); |
| 39 | 41 | ||
| @@ -507,20 +509,28 @@ static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, | |||
| 507 | /* height is npipes htiles aligned == npipes * 8 pixel aligned */ | 509 | /* height is npipes htiles aligned == npipes * 8 pixel aligned */ |
| 508 | nby = round_up(nby, track->npipes * 8); | 510 | nby = round_up(nby, track->npipes * 8); |
| 509 | } else { | 511 | } else { |
| 512 | /* always assume 8x8 htile */ | ||
| 513 | /* align is htile align * 8, htile align vary according to | ||
| 514 | * number of pipe and tile width and nby | ||
| 515 | */ | ||
| 510 | switch (track->npipes) { | 516 | switch (track->npipes) { |
| 511 | case 8: | 517 | case 8: |
| 518 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | ||
| 512 | nbx = round_up(nbx, 64 * 8); | 519 | nbx = round_up(nbx, 64 * 8); |
| 513 | nby = round_up(nby, 64 * 8); | 520 | nby = round_up(nby, 64 * 8); |
| 514 | break; | 521 | break; |
| 515 | case 4: | 522 | case 4: |
| 523 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | ||
| 516 | nbx = round_up(nbx, 64 * 8); | 524 | nbx = round_up(nbx, 64 * 8); |
| 517 | nby = round_up(nby, 32 * 8); | 525 | nby = round_up(nby, 32 * 8); |
| 518 | break; | 526 | break; |
| 519 | case 2: | 527 | case 2: |
| 528 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | ||
| 520 | nbx = round_up(nbx, 32 * 8); | 529 | nbx = round_up(nbx, 32 * 8); |
| 521 | nby = round_up(nby, 32 * 8); | 530 | nby = round_up(nby, 32 * 8); |
| 522 | break; | 531 | break; |
| 523 | case 1: | 532 | case 1: |
| 533 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | ||
| 524 | nbx = round_up(nbx, 32 * 8); | 534 | nbx = round_up(nbx, 32 * 8); |
| 525 | nby = round_up(nby, 16 * 8); | 535 | nby = round_up(nby, 16 * 8); |
| 526 | break; | 536 | break; |
| @@ -531,9 +541,10 @@ static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, | |||
| 531 | } | 541 | } |
| 532 | } | 542 | } |
| 533 | /* compute number of htile */ | 543 | /* compute number of htile */ |
| 534 | nbx = nbx / 8; | 544 | nbx = nbx >> 3; |
| 535 | nby = nby / 8; | 545 | nby = nby >> 3; |
| 536 | size = nbx * nby * 4; | 546 | /* size must be aligned on npipes * 2K boundary */ |
| 547 | size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); | ||
| 537 | size += track->htile_offset; | 548 | size += track->htile_offset; |
| 538 | 549 | ||
| 539 | if (size > radeon_bo_size(track->htile_bo)) { | 550 | if (size > radeon_bo_size(track->htile_bo)) { |
| @@ -1790,6 +1801,8 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) | |||
| 1790 | case DB_HTILE_SURFACE: | 1801 | case DB_HTILE_SURFACE: |
| 1791 | /* 8x8 only */ | 1802 | /* 8x8 only */ |
| 1792 | track->htile_surface = radeon_get_ib_value(p, idx); | 1803 | track->htile_surface = radeon_get_ib_value(p, idx); |
| 1804 | /* force 8x8 htile width and height */ | ||
| 1805 | ib[idx] |= 3; | ||
| 1793 | track->db_dirty = true; | 1806 | track->db_dirty = true; |
| 1794 | break; | 1807 | break; |
| 1795 | case CB_IMMED0_BASE: | 1808 | case CB_IMMED0_BASE: |
| @@ -2243,6 +2256,18 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p, | |||
| 2243 | command = radeon_get_ib_value(p, idx+4); | 2256 | command = radeon_get_ib_value(p, idx+4); |
| 2244 | size = command & 0x1fffff; | 2257 | size = command & 0x1fffff; |
| 2245 | info = radeon_get_ib_value(p, idx+1); | 2258 | info = radeon_get_ib_value(p, idx+1); |
| 2259 | if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ | ||
| 2260 | (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ | ||
| 2261 | ((((info & 0x00300000) >> 20) == 0) && | ||
| 2262 | (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ | ||
| 2263 | ((((info & 0x60000000) >> 29) == 0) && | ||
| 2264 | (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ | ||
| 2265 | /* non mem to mem copies requires dw aligned count */ | ||
| 2266 | if (size % 4) { | ||
| 2267 | DRM_ERROR("CP DMA command requires dw count alignment\n"); | ||
| 2268 | return -EINVAL; | ||
| 2269 | } | ||
| 2270 | } | ||
| 2246 | if (command & PACKET3_CP_DMA_CMD_SAS) { | 2271 | if (command & PACKET3_CP_DMA_CMD_SAS) { |
| 2247 | /* src address space is register */ | 2272 | /* src address space is register */ |
| 2248 | /* GDS is ok */ | 2273 | /* GDS is ok */ |
| @@ -2804,6 +2829,455 @@ int evergreen_cs_parse(struct radeon_cs_parser *p) | |||
| 2804 | return 0; | 2829 | return 0; |
| 2805 | } | 2830 | } |
| 2806 | 2831 | ||
| 2832 | /* | ||
| 2833 | * DMA | ||
| 2834 | */ | ||
| 2835 | |||
| 2836 | #define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28) | ||
| 2837 | #define GET_DMA_COUNT(h) ((h) & 0x000fffff) | ||
| 2838 | #define GET_DMA_T(h) (((h) & 0x00800000) >> 23) | ||
| 2839 | #define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26) | ||
| 2840 | #define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20) | ||
| 2841 | |||
| 2842 | /** | ||
| 2843 | * evergreen_dma_cs_parse() - parse the DMA IB | ||
| 2844 | * @p: parser structure holding parsing context. | ||
| 2845 | * | ||
| 2846 | * Parses the DMA IB from the CS ioctl and updates | ||
| 2847 | * the GPU addresses based on the reloc information and | ||
| 2848 | * checks for errors. (Evergreen-Cayman) | ||
| 2849 | * Returns 0 for success and an error on failure. | ||
| 2850 | **/ | ||
| 2851 | int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | ||
| 2852 | { | ||
| 2853 | struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 2854 | struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc; | ||
| 2855 | u32 header, cmd, count, tiled, new_cmd, misc; | ||
| 2856 | volatile u32 *ib = p->ib.ptr; | ||
| 2857 | u32 idx, idx_value; | ||
| 2858 | u64 src_offset, dst_offset, dst2_offset; | ||
| 2859 | int r; | ||
| 2860 | |||
| 2861 | do { | ||
| 2862 | if (p->idx >= ib_chunk->length_dw) { | ||
| 2863 | DRM_ERROR("Can not parse packet at %d after CS end %d !\n", | ||
| 2864 | p->idx, ib_chunk->length_dw); | ||
| 2865 | return -EINVAL; | ||
| 2866 | } | ||
| 2867 | idx = p->idx; | ||
| 2868 | header = radeon_get_ib_value(p, idx); | ||
| 2869 | cmd = GET_DMA_CMD(header); | ||
| 2870 | count = GET_DMA_COUNT(header); | ||
| 2871 | tiled = GET_DMA_T(header); | ||
| 2872 | new_cmd = GET_DMA_NEW(header); | ||
| 2873 | misc = GET_DMA_MISC(header); | ||
| 2874 | |||
| 2875 | switch (cmd) { | ||
| 2876 | case DMA_PACKET_WRITE: | ||
| 2877 | r = r600_dma_cs_next_reloc(p, &dst_reloc); | ||
| 2878 | if (r) { | ||
| 2879 | DRM_ERROR("bad DMA_PACKET_WRITE\n"); | ||
| 2880 | return -EINVAL; | ||
| 2881 | } | ||
| 2882 | if (tiled) { | ||
| 2883 | dst_offset = ib[idx+1]; | ||
| 2884 | dst_offset <<= 8; | ||
| 2885 | |||
| 2886 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 2887 | p->idx += count + 7; | ||
| 2888 | } else { | ||
| 2889 | dst_offset = ib[idx+1]; | ||
| 2890 | dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32; | ||
| 2891 | |||
| 2892 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2893 | ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 2894 | p->idx += count + 3; | ||
| 2895 | } | ||
| 2896 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 2897 | dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n", | ||
| 2898 | dst_offset, radeon_bo_size(dst_reloc->robj)); | ||
| 2899 | return -EINVAL; | ||
| 2900 | } | ||
| 2901 | break; | ||
| 2902 | case DMA_PACKET_COPY: | ||
| 2903 | r = r600_dma_cs_next_reloc(p, &src_reloc); | ||
| 2904 | if (r) { | ||
| 2905 | DRM_ERROR("bad DMA_PACKET_COPY\n"); | ||
| 2906 | return -EINVAL; | ||
| 2907 | } | ||
| 2908 | r = r600_dma_cs_next_reloc(p, &dst_reloc); | ||
| 2909 | if (r) { | ||
| 2910 | DRM_ERROR("bad DMA_PACKET_COPY\n"); | ||
| 2911 | return -EINVAL; | ||
| 2912 | } | ||
| 2913 | if (tiled) { | ||
| 2914 | idx_value = radeon_get_ib_value(p, idx + 2); | ||
| 2915 | if (new_cmd) { | ||
| 2916 | switch (misc) { | ||
| 2917 | case 0: | ||
| 2918 | /* L2T, frame to fields */ | ||
| 2919 | if (idx_value & (1 << 31)) { | ||
| 2920 | DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); | ||
| 2921 | return -EINVAL; | ||
| 2922 | } | ||
| 2923 | r = r600_dma_cs_next_reloc(p, &dst2_reloc); | ||
| 2924 | if (r) { | ||
| 2925 | DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); | ||
| 2926 | return -EINVAL; | ||
| 2927 | } | ||
| 2928 | dst_offset = ib[idx+1]; | ||
| 2929 | dst_offset <<= 8; | ||
| 2930 | dst2_offset = ib[idx+2]; | ||
| 2931 | dst2_offset <<= 8; | ||
| 2932 | src_offset = ib[idx+8]; | ||
| 2933 | src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32; | ||
| 2934 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 2935 | dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n", | ||
| 2936 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 2937 | return -EINVAL; | ||
| 2938 | } | ||
| 2939 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 2940 | dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n", | ||
| 2941 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 2942 | return -EINVAL; | ||
| 2943 | } | ||
| 2944 | if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { | ||
| 2945 | dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n", | ||
| 2946 | dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); | ||
| 2947 | return -EINVAL; | ||
| 2948 | } | ||
| 2949 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 2950 | ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); | ||
| 2951 | ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2952 | ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 2953 | p->idx += 10; | ||
| 2954 | break; | ||
| 2955 | case 1: | ||
| 2956 | /* L2T, T2L partial */ | ||
| 2957 | if (p->family < CHIP_CAYMAN) { | ||
| 2958 | DRM_ERROR("L2T, T2L Partial is cayman only !\n"); | ||
| 2959 | return -EINVAL; | ||
| 2960 | } | ||
| 2961 | /* detile bit */ | ||
| 2962 | if (idx_value & (1 << 31)) { | ||
| 2963 | /* tiled src, linear dst */ | ||
| 2964 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | ||
| 2965 | |||
| 2966 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2967 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 2968 | } else { | ||
| 2969 | /* linear src, tiled dst */ | ||
| 2970 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2971 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 2972 | |||
| 2973 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 2974 | } | ||
| 2975 | p->idx += 12; | ||
| 2976 | break; | ||
| 2977 | case 3: | ||
| 2978 | /* L2T, broadcast */ | ||
| 2979 | if (idx_value & (1 << 31)) { | ||
| 2980 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); | ||
| 2981 | return -EINVAL; | ||
| 2982 | } | ||
| 2983 | r = r600_dma_cs_next_reloc(p, &dst2_reloc); | ||
| 2984 | if (r) { | ||
| 2985 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); | ||
| 2986 | return -EINVAL; | ||
| 2987 | } | ||
| 2988 | dst_offset = ib[idx+1]; | ||
| 2989 | dst_offset <<= 8; | ||
| 2990 | dst2_offset = ib[idx+2]; | ||
| 2991 | dst2_offset <<= 8; | ||
| 2992 | src_offset = ib[idx+8]; | ||
| 2993 | src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32; | ||
| 2994 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 2995 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", | ||
| 2996 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 2997 | return -EINVAL; | ||
| 2998 | } | ||
| 2999 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3000 | dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", | ||
| 3001 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 3002 | return -EINVAL; | ||
| 3003 | } | ||
| 3004 | if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { | ||
| 3005 | dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n", | ||
| 3006 | dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); | ||
| 3007 | return -EINVAL; | ||
| 3008 | } | ||
| 3009 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 3010 | ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); | ||
| 3011 | ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3012 | ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3013 | p->idx += 10; | ||
| 3014 | break; | ||
| 3015 | case 4: | ||
| 3016 | /* L2T, T2L */ | ||
| 3017 | /* detile bit */ | ||
| 3018 | if (idx_value & (1 << 31)) { | ||
| 3019 | /* tiled src, linear dst */ | ||
| 3020 | src_offset = ib[idx+1]; | ||
| 3021 | src_offset <<= 8; | ||
| 3022 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | ||
| 3023 | |||
| 3024 | dst_offset = ib[idx+7]; | ||
| 3025 | dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | ||
| 3026 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3027 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 3028 | } else { | ||
| 3029 | /* linear src, tiled dst */ | ||
| 3030 | src_offset = ib[idx+7]; | ||
| 3031 | src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | ||
| 3032 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3033 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3034 | |||
| 3035 | dst_offset = ib[idx+1]; | ||
| 3036 | dst_offset <<= 8; | ||
| 3037 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 3038 | } | ||
| 3039 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 3040 | dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n", | ||
| 3041 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 3042 | return -EINVAL; | ||
| 3043 | } | ||
| 3044 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3045 | dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n", | ||
| 3046 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 3047 | return -EINVAL; | ||
| 3048 | } | ||
| 3049 | p->idx += 9; | ||
| 3050 | break; | ||
| 3051 | case 5: | ||
| 3052 | /* T2T partial */ | ||
| 3053 | if (p->family < CHIP_CAYMAN) { | ||
| 3054 | DRM_ERROR("L2T, T2L Partial is cayman only !\n"); | ||
| 3055 | return -EINVAL; | ||
| 3056 | } | ||
| 3057 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | ||
| 3058 | ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 3059 | p->idx += 13; | ||
| 3060 | break; | ||
| 3061 | case 7: | ||
| 3062 | /* L2T, broadcast */ | ||
| 3063 | if (idx_value & (1 << 31)) { | ||
| 3064 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); | ||
| 3065 | return -EINVAL; | ||
| 3066 | } | ||
| 3067 | r = r600_dma_cs_next_reloc(p, &dst2_reloc); | ||
| 3068 | if (r) { | ||
| 3069 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); | ||
| 3070 | return -EINVAL; | ||
| 3071 | } | ||
| 3072 | dst_offset = ib[idx+1]; | ||
| 3073 | dst_offset <<= 8; | ||
| 3074 | dst2_offset = ib[idx+2]; | ||
| 3075 | dst2_offset <<= 8; | ||
| 3076 | src_offset = ib[idx+8]; | ||
| 3077 | src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32; | ||
| 3078 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 3079 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", | ||
| 3080 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 3081 | return -EINVAL; | ||
| 3082 | } | ||
| 3083 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3084 | dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", | ||
| 3085 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 3086 | return -EINVAL; | ||
| 3087 | } | ||
| 3088 | if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { | ||
| 3089 | dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n", | ||
| 3090 | dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); | ||
| 3091 | return -EINVAL; | ||
| 3092 | } | ||
| 3093 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 3094 | ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8); | ||
| 3095 | ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3096 | ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3097 | p->idx += 10; | ||
| 3098 | break; | ||
| 3099 | default: | ||
| 3100 | DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); | ||
| 3101 | return -EINVAL; | ||
| 3102 | } | ||
| 3103 | } else { | ||
| 3104 | switch (misc) { | ||
| 3105 | case 0: | ||
| 3106 | /* detile bit */ | ||
| 3107 | if (idx_value & (1 << 31)) { | ||
| 3108 | /* tiled src, linear dst */ | ||
| 3109 | src_offset = ib[idx+1]; | ||
| 3110 | src_offset <<= 8; | ||
| 3111 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | ||
| 3112 | |||
| 3113 | dst_offset = ib[idx+7]; | ||
| 3114 | dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | ||
| 3115 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3116 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 3117 | } else { | ||
| 3118 | /* linear src, tiled dst */ | ||
| 3119 | src_offset = ib[idx+7]; | ||
| 3120 | src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | ||
| 3121 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3122 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3123 | |||
| 3124 | dst_offset = ib[idx+1]; | ||
| 3125 | dst_offset <<= 8; | ||
| 3126 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 3127 | } | ||
| 3128 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 3129 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", | ||
| 3130 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 3131 | return -EINVAL; | ||
| 3132 | } | ||
| 3133 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3134 | dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", | ||
| 3135 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 3136 | return -EINVAL; | ||
| 3137 | } | ||
| 3138 | p->idx += 9; | ||
| 3139 | break; | ||
| 3140 | default: | ||
| 3141 | DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); | ||
| 3142 | return -EINVAL; | ||
| 3143 | } | ||
| 3144 | } | ||
| 3145 | } else { | ||
| 3146 | if (new_cmd) { | ||
| 3147 | switch (misc) { | ||
| 3148 | case 0: | ||
| 3149 | /* L2L, byte */ | ||
| 3150 | src_offset = ib[idx+2]; | ||
| 3151 | src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | ||
| 3152 | dst_offset = ib[idx+1]; | ||
| 3153 | dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | ||
| 3154 | if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { | ||
| 3155 | dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n", | ||
| 3156 | src_offset + count, radeon_bo_size(src_reloc->robj)); | ||
| 3157 | return -EINVAL; | ||
| 3158 | } | ||
| 3159 | if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3160 | dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n", | ||
| 3161 | dst_offset + count, radeon_bo_size(dst_reloc->robj)); | ||
| 3162 | return -EINVAL; | ||
| 3163 | } | ||
| 3164 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff); | ||
| 3165 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff); | ||
| 3166 | ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 3167 | ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3168 | p->idx += 5; | ||
| 3169 | break; | ||
| 3170 | case 1: | ||
| 3171 | /* L2L, partial */ | ||
| 3172 | if (p->family < CHIP_CAYMAN) { | ||
| 3173 | DRM_ERROR("L2L Partial is cayman only !\n"); | ||
| 3174 | return -EINVAL; | ||
| 3175 | } | ||
| 3176 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff); | ||
| 3177 | ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3178 | ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff); | ||
| 3179 | ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 3180 | |||
| 3181 | p->idx += 9; | ||
| 3182 | break; | ||
| 3183 | case 4: | ||
| 3184 | /* L2L, dw, broadcast */ | ||
| 3185 | r = r600_dma_cs_next_reloc(p, &dst2_reloc); | ||
| 3186 | if (r) { | ||
| 3187 | DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); | ||
| 3188 | return -EINVAL; | ||
| 3189 | } | ||
| 3190 | dst_offset = ib[idx+1]; | ||
| 3191 | dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | ||
| 3192 | dst2_offset = ib[idx+2]; | ||
| 3193 | dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32; | ||
| 3194 | src_offset = ib[idx+3]; | ||
| 3195 | src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32; | ||
| 3196 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 3197 | dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n", | ||
| 3198 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 3199 | return -EINVAL; | ||
| 3200 | } | ||
| 3201 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3202 | dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n", | ||
| 3203 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 3204 | return -EINVAL; | ||
| 3205 | } | ||
| 3206 | if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { | ||
| 3207 | dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n", | ||
| 3208 | dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); | ||
| 3209 | return -EINVAL; | ||
| 3210 | } | ||
| 3211 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3212 | ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3213 | ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3214 | ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 3215 | ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff; | ||
| 3216 | ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3217 | p->idx += 7; | ||
| 3218 | break; | ||
| 3219 | default: | ||
| 3220 | DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); | ||
| 3221 | return -EINVAL; | ||
| 3222 | } | ||
| 3223 | } else { | ||
| 3224 | /* L2L, dw */ | ||
| 3225 | src_offset = ib[idx+2]; | ||
| 3226 | src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | ||
| 3227 | dst_offset = ib[idx+1]; | ||
| 3228 | dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | ||
| 3229 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 3230 | dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n", | ||
| 3231 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 3232 | return -EINVAL; | ||
| 3233 | } | ||
| 3234 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3235 | dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n", | ||
| 3236 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 3237 | return -EINVAL; | ||
| 3238 | } | ||
| 3239 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3240 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3241 | ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 3242 | ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 3243 | p->idx += 5; | ||
| 3244 | } | ||
| 3245 | } | ||
| 3246 | break; | ||
| 3247 | case DMA_PACKET_CONSTANT_FILL: | ||
| 3248 | r = r600_dma_cs_next_reloc(p, &dst_reloc); | ||
| 3249 | if (r) { | ||
| 3250 | DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); | ||
| 3251 | return -EINVAL; | ||
| 3252 | } | ||
| 3253 | dst_offset = ib[idx+1]; | ||
| 3254 | dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16; | ||
| 3255 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 3256 | dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", | ||
| 3257 | dst_offset, radeon_bo_size(dst_reloc->robj)); | ||
| 3258 | return -EINVAL; | ||
| 3259 | } | ||
| 3260 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 3261 | ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000; | ||
| 3262 | p->idx += 4; | ||
| 3263 | break; | ||
| 3264 | case DMA_PACKET_NOP: | ||
| 3265 | p->idx += 1; | ||
| 3266 | break; | ||
| 3267 | default: | ||
| 3268 | DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); | ||
| 3269 | return -EINVAL; | ||
| 3270 | } | ||
| 3271 | } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); | ||
| 3272 | #if 0 | ||
| 3273 | for (r = 0; r < p->ib->length_dw; r++) { | ||
| 3274 | printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]); | ||
| 3275 | mdelay(1); | ||
| 3276 | } | ||
| 3277 | #endif | ||
| 3278 | return 0; | ||
| 3279 | } | ||
| 3280 | |||
| 2807 | /* vm parser */ | 3281 | /* vm parser */ |
| 2808 | static bool evergreen_vm_reg_valid(u32 reg) | 3282 | static bool evergreen_vm_reg_valid(u32 reg) |
| 2809 | { | 3283 | { |
| @@ -3010,6 +3484,18 @@ static int evergreen_vm_packet3_check(struct radeon_device *rdev, | |||
| 3010 | case PACKET3_CP_DMA: | 3484 | case PACKET3_CP_DMA: |
| 3011 | command = ib[idx + 4]; | 3485 | command = ib[idx + 4]; |
| 3012 | info = ib[idx + 1]; | 3486 | info = ib[idx + 1]; |
| 3487 | if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ | ||
| 3488 | (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ | ||
| 3489 | ((((info & 0x00300000) >> 20) == 0) && | ||
| 3490 | (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ | ||
| 3491 | ((((info & 0x60000000) >> 29) == 0) && | ||
| 3492 | (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ | ||
| 3493 | /* non mem to mem copies requires dw aligned count */ | ||
| 3494 | if ((command & 0x1fffff) % 4) { | ||
| 3495 | DRM_ERROR("CP DMA command requires dw count alignment\n"); | ||
| 3496 | return -EINVAL; | ||
| 3497 | } | ||
| 3498 | } | ||
| 3013 | if (command & PACKET3_CP_DMA_CMD_SAS) { | 3499 | if (command & PACKET3_CP_DMA_CMD_SAS) { |
| 3014 | /* src address space is register */ | 3500 | /* src address space is register */ |
| 3015 | if (((info & 0x60000000) >> 29) == 0) { | 3501 | if (((info & 0x60000000) >> 29) == 0) { |
| @@ -3094,3 +3580,114 @@ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 3094 | 3580 | ||
| 3095 | return ret; | 3581 | return ret; |
| 3096 | } | 3582 | } |
| 3583 | |||
| 3584 | /** | ||
| 3585 | * evergreen_dma_ib_parse() - parse the DMA IB for VM | ||
| 3586 | * @rdev: radeon_device pointer | ||
| 3587 | * @ib: radeon_ib pointer | ||
| 3588 | * | ||
| 3589 | * Parses the DMA IB from the VM CS ioctl | ||
| 3590 | * checks for errors. (Cayman-SI) | ||
| 3591 | * Returns 0 for success and an error on failure. | ||
| 3592 | **/ | ||
| 3593 | int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) | ||
| 3594 | { | ||
| 3595 | u32 idx = 0; | ||
| 3596 | u32 header, cmd, count, tiled, new_cmd, misc; | ||
| 3597 | |||
| 3598 | do { | ||
| 3599 | header = ib->ptr[idx]; | ||
| 3600 | cmd = GET_DMA_CMD(header); | ||
| 3601 | count = GET_DMA_COUNT(header); | ||
| 3602 | tiled = GET_DMA_T(header); | ||
| 3603 | new_cmd = GET_DMA_NEW(header); | ||
| 3604 | misc = GET_DMA_MISC(header); | ||
| 3605 | |||
| 3606 | switch (cmd) { | ||
| 3607 | case DMA_PACKET_WRITE: | ||
| 3608 | if (tiled) | ||
| 3609 | idx += count + 7; | ||
| 3610 | else | ||
| 3611 | idx += count + 3; | ||
| 3612 | break; | ||
| 3613 | case DMA_PACKET_COPY: | ||
| 3614 | if (tiled) { | ||
| 3615 | if (new_cmd) { | ||
| 3616 | switch (misc) { | ||
| 3617 | case 0: | ||
| 3618 | /* L2T, frame to fields */ | ||
| 3619 | idx += 10; | ||
| 3620 | break; | ||
| 3621 | case 1: | ||
| 3622 | /* L2T, T2L partial */ | ||
| 3623 | idx += 12; | ||
| 3624 | break; | ||
| 3625 | case 3: | ||
| 3626 | /* L2T, broadcast */ | ||
| 3627 | idx += 10; | ||
| 3628 | break; | ||
| 3629 | case 4: | ||
| 3630 | /* L2T, T2L */ | ||
| 3631 | idx += 9; | ||
| 3632 | break; | ||
| 3633 | case 5: | ||
| 3634 | /* T2T partial */ | ||
| 3635 | idx += 13; | ||
| 3636 | break; | ||
| 3637 | case 7: | ||
| 3638 | /* L2T, broadcast */ | ||
| 3639 | idx += 10; | ||
| 3640 | break; | ||
| 3641 | default: | ||
| 3642 | DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); | ||
| 3643 | return -EINVAL; | ||
| 3644 | } | ||
| 3645 | } else { | ||
| 3646 | switch (misc) { | ||
| 3647 | case 0: | ||
| 3648 | idx += 9; | ||
| 3649 | break; | ||
| 3650 | default: | ||
| 3651 | DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); | ||
| 3652 | return -EINVAL; | ||
| 3653 | } | ||
| 3654 | } | ||
| 3655 | } else { | ||
| 3656 | if (new_cmd) { | ||
| 3657 | switch (misc) { | ||
| 3658 | case 0: | ||
| 3659 | /* L2L, byte */ | ||
| 3660 | idx += 5; | ||
| 3661 | break; | ||
| 3662 | case 1: | ||
| 3663 | /* L2L, partial */ | ||
| 3664 | idx += 9; | ||
| 3665 | break; | ||
| 3666 | case 4: | ||
| 3667 | /* L2L, dw, broadcast */ | ||
| 3668 | idx += 7; | ||
| 3669 | break; | ||
| 3670 | default: | ||
| 3671 | DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc); | ||
| 3672 | return -EINVAL; | ||
| 3673 | } | ||
| 3674 | } else { | ||
| 3675 | /* L2L, dw */ | ||
| 3676 | idx += 5; | ||
| 3677 | } | ||
| 3678 | } | ||
| 3679 | break; | ||
| 3680 | case DMA_PACKET_CONSTANT_FILL: | ||
| 3681 | idx += 4; | ||
| 3682 | break; | ||
| 3683 | case DMA_PACKET_NOP: | ||
| 3684 | idx += 1; | ||
| 3685 | break; | ||
| 3686 | default: | ||
| 3687 | DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); | ||
| 3688 | return -EINVAL; | ||
| 3689 | } | ||
| 3690 | } while (idx < ib->length_dw); | ||
| 3691 | |||
| 3692 | return 0; | ||
| 3693 | } | ||
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 376884f1bcd2..8ff7cac222dc 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
| @@ -4135,23 +4135,36 @@ int r100_init(struct radeon_device *rdev) | |||
| 4135 | return 0; | 4135 | return 0; |
| 4136 | } | 4136 | } |
| 4137 | 4137 | ||
| 4138 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | 4138 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg, |
| 4139 | bool always_indirect) | ||
| 4139 | { | 4140 | { |
| 4140 | if (reg < rdev->rmmio_size) | 4141 | if (reg < rdev->rmmio_size && !always_indirect) |
| 4141 | return readl(((void __iomem *)rdev->rmmio) + reg); | 4142 | return readl(((void __iomem *)rdev->rmmio) + reg); |
| 4142 | else { | 4143 | else { |
| 4144 | unsigned long flags; | ||
| 4145 | uint32_t ret; | ||
| 4146 | |||
| 4147 | spin_lock_irqsave(&rdev->mmio_idx_lock, flags); | ||
| 4143 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | 4148 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
| 4144 | return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); | 4149 | ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); |
| 4150 | spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags); | ||
| 4151 | |||
| 4152 | return ret; | ||
| 4145 | } | 4153 | } |
| 4146 | } | 4154 | } |
| 4147 | 4155 | ||
| 4148 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | 4156 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v, |
| 4157 | bool always_indirect) | ||
| 4149 | { | 4158 | { |
| 4150 | if (reg < rdev->rmmio_size) | 4159 | if (reg < rdev->rmmio_size && !always_indirect) |
| 4151 | writel(v, ((void __iomem *)rdev->rmmio) + reg); | 4160 | writel(v, ((void __iomem *)rdev->rmmio) + reg); |
| 4152 | else { | 4161 | else { |
| 4162 | unsigned long flags; | ||
| 4163 | |||
| 4164 | spin_lock_irqsave(&rdev->mmio_idx_lock, flags); | ||
| 4153 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | 4165 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
| 4154 | writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); | 4166 | writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA); |
| 4167 | spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags); | ||
| 4155 | } | 4168 | } |
| 4156 | } | 4169 | } |
| 4157 | 4170 | ||
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 5d6e7f959e75..0be768be530c 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
| @@ -657,87 +657,30 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p) | |||
| 657 | /* nby is npipes htiles aligned == npipes * 8 pixel aligned */ | 657 | /* nby is npipes htiles aligned == npipes * 8 pixel aligned */ |
| 658 | nby = round_up(nby, track->npipes * 8); | 658 | nby = round_up(nby, track->npipes * 8); |
| 659 | } else { | 659 | } else { |
| 660 | /* htile widht & nby (8 or 4) make 2 bits number */ | 660 | /* always assume 8x8 htile */ |
| 661 | tmp = track->htile_surface & 3; | ||
| 662 | /* align is htile align * 8, htile align vary according to | 661 | /* align is htile align * 8, htile align vary according to |
| 663 | * number of pipe and tile width and nby | 662 | * number of pipe and tile width and nby |
| 664 | */ | 663 | */ |
| 665 | switch (track->npipes) { | 664 | switch (track->npipes) { |
| 666 | case 8: | 665 | case 8: |
| 667 | switch (tmp) { | 666 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ |
| 668 | case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | 667 | nbx = round_up(nbx, 64 * 8); |
| 669 | nbx = round_up(nbx, 64 * 8); | 668 | nby = round_up(nby, 64 * 8); |
| 670 | nby = round_up(nby, 64 * 8); | ||
| 671 | break; | ||
| 672 | case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ | ||
| 673 | case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ | ||
| 674 | nbx = round_up(nbx, 64 * 8); | ||
| 675 | nby = round_up(nby, 32 * 8); | ||
| 676 | break; | ||
| 677 | case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ | ||
| 678 | nbx = round_up(nbx, 32 * 8); | ||
| 679 | nby = round_up(nby, 32 * 8); | ||
| 680 | break; | ||
| 681 | default: | ||
| 682 | return -EINVAL; | ||
| 683 | } | ||
| 684 | break; | 669 | break; |
| 685 | case 4: | 670 | case 4: |
| 686 | switch (tmp) { | 671 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ |
| 687 | case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | 672 | nbx = round_up(nbx, 64 * 8); |
| 688 | nbx = round_up(nbx, 64 * 8); | 673 | nby = round_up(nby, 32 * 8); |
| 689 | nby = round_up(nby, 32 * 8); | ||
| 690 | break; | ||
| 691 | case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ | ||
| 692 | case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ | ||
| 693 | nbx = round_up(nbx, 32 * 8); | ||
| 694 | nby = round_up(nby, 32 * 8); | ||
| 695 | break; | ||
| 696 | case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ | ||
| 697 | nbx = round_up(nbx, 32 * 8); | ||
| 698 | nby = round_up(nby, 16 * 8); | ||
| 699 | break; | ||
| 700 | default: | ||
| 701 | return -EINVAL; | ||
| 702 | } | ||
| 703 | break; | 674 | break; |
| 704 | case 2: | 675 | case 2: |
| 705 | switch (tmp) { | 676 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ |
| 706 | case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | 677 | nbx = round_up(nbx, 32 * 8); |
| 707 | nbx = round_up(nbx, 32 * 8); | 678 | nby = round_up(nby, 32 * 8); |
| 708 | nby = round_up(nby, 32 * 8); | ||
| 709 | break; | ||
| 710 | case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ | ||
| 711 | case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ | ||
| 712 | nbx = round_up(nbx, 32 * 8); | ||
| 713 | nby = round_up(nby, 16 * 8); | ||
| 714 | break; | ||
| 715 | case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ | ||
| 716 | nbx = round_up(nbx, 16 * 8); | ||
| 717 | nby = round_up(nby, 16 * 8); | ||
| 718 | break; | ||
| 719 | default: | ||
| 720 | return -EINVAL; | ||
| 721 | } | ||
| 722 | break; | 679 | break; |
| 723 | case 1: | 680 | case 1: |
| 724 | switch (tmp) { | 681 | /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ |
| 725 | case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ | 682 | nbx = round_up(nbx, 32 * 8); |
| 726 | nbx = round_up(nbx, 32 * 8); | 683 | nby = round_up(nby, 16 * 8); |
| 727 | nby = round_up(nby, 16 * 8); | ||
| 728 | break; | ||
| 729 | case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/ | ||
| 730 | case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/ | ||
| 731 | nbx = round_up(nbx, 16 * 8); | ||
| 732 | nby = round_up(nby, 16 * 8); | ||
| 733 | break; | ||
| 734 | case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/ | ||
| 735 | nbx = round_up(nbx, 16 * 8); | ||
| 736 | nby = round_up(nby, 8 * 8); | ||
| 737 | break; | ||
| 738 | default: | ||
| 739 | return -EINVAL; | ||
| 740 | } | ||
| 741 | break; | 684 | break; |
| 742 | default: | 685 | default: |
| 743 | dev_warn(p->dev, "%s:%d invalid num pipes %d\n", | 686 | dev_warn(p->dev, "%s:%d invalid num pipes %d\n", |
| @@ -746,9 +689,10 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p) | |||
| 746 | } | 689 | } |
| 747 | } | 690 | } |
| 748 | /* compute number of htile */ | 691 | /* compute number of htile */ |
| 749 | nbx = G_028D24_HTILE_WIDTH(track->htile_surface) ? nbx / 8 : nbx / 4; | 692 | nbx = nbx >> 3; |
| 750 | nby = G_028D24_HTILE_HEIGHT(track->htile_surface) ? nby / 8 : nby / 4; | 693 | nby = nby >> 3; |
| 751 | size = nbx * nby * 4; | 694 | /* size must be aligned on npipes * 2K boundary */ |
| 695 | size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); | ||
| 752 | size += track->htile_offset; | 696 | size += track->htile_offset; |
| 753 | 697 | ||
| 754 | if (size > radeon_bo_size(track->htile_bo)) { | 698 | if (size > radeon_bo_size(track->htile_bo)) { |
| @@ -1492,6 +1436,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) | |||
| 1492 | break; | 1436 | break; |
| 1493 | case DB_HTILE_SURFACE: | 1437 | case DB_HTILE_SURFACE: |
| 1494 | track->htile_surface = radeon_get_ib_value(p, idx); | 1438 | track->htile_surface = radeon_get_ib_value(p, idx); |
| 1439 | /* force 8x8 htile width and height */ | ||
| 1440 | ib[idx] |= 3; | ||
| 1495 | track->db_dirty = true; | 1441 | track->db_dirty = true; |
| 1496 | break; | 1442 | break; |
| 1497 | case SQ_PGM_START_FS: | 1443 | case SQ_PGM_START_FS: |
| @@ -2568,3 +2514,196 @@ void r600_cs_legacy_init(void) | |||
| 2568 | { | 2514 | { |
| 2569 | r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm; | 2515 | r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm; |
| 2570 | } | 2516 | } |
| 2517 | |||
| 2518 | /* | ||
| 2519 | * DMA | ||
| 2520 | */ | ||
| 2521 | /** | ||
| 2522 | * r600_dma_cs_next_reloc() - parse next reloc | ||
| 2523 | * @p: parser structure holding parsing context. | ||
| 2524 | * @cs_reloc: reloc informations | ||
| 2525 | * | ||
| 2526 | * Return the next reloc, do bo validation and compute | ||
| 2527 | * GPU offset using the provided start. | ||
| 2528 | **/ | ||
| 2529 | int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, | ||
| 2530 | struct radeon_cs_reloc **cs_reloc) | ||
| 2531 | { | ||
| 2532 | struct radeon_cs_chunk *relocs_chunk; | ||
| 2533 | unsigned idx; | ||
| 2534 | |||
| 2535 | if (p->chunk_relocs_idx == -1) { | ||
| 2536 | DRM_ERROR("No relocation chunk !\n"); | ||
| 2537 | return -EINVAL; | ||
| 2538 | } | ||
| 2539 | *cs_reloc = NULL; | ||
| 2540 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; | ||
| 2541 | idx = p->dma_reloc_idx; | ||
| 2542 | if (idx >= relocs_chunk->length_dw) { | ||
| 2543 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", | ||
| 2544 | idx, relocs_chunk->length_dw); | ||
| 2545 | return -EINVAL; | ||
| 2546 | } | ||
| 2547 | *cs_reloc = p->relocs_ptr[idx]; | ||
| 2548 | p->dma_reloc_idx++; | ||
| 2549 | return 0; | ||
| 2550 | } | ||
| 2551 | |||
| 2552 | #define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28) | ||
| 2553 | #define GET_DMA_COUNT(h) ((h) & 0x0000ffff) | ||
| 2554 | #define GET_DMA_T(h) (((h) & 0x00800000) >> 23) | ||
| 2555 | |||
| 2556 | /** | ||
| 2557 | * r600_dma_cs_parse() - parse the DMA IB | ||
| 2558 | * @p: parser structure holding parsing context. | ||
| 2559 | * | ||
| 2560 | * Parses the DMA IB from the CS ioctl and updates | ||
| 2561 | * the GPU addresses based on the reloc information and | ||
| 2562 | * checks for errors. (R6xx-R7xx) | ||
| 2563 | * Returns 0 for success and an error on failure. | ||
| 2564 | **/ | ||
| 2565 | int r600_dma_cs_parse(struct radeon_cs_parser *p) | ||
| 2566 | { | ||
| 2567 | struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; | ||
| 2568 | struct radeon_cs_reloc *src_reloc, *dst_reloc; | ||
| 2569 | u32 header, cmd, count, tiled; | ||
| 2570 | volatile u32 *ib = p->ib.ptr; | ||
| 2571 | u32 idx, idx_value; | ||
| 2572 | u64 src_offset, dst_offset; | ||
| 2573 | int r; | ||
| 2574 | |||
| 2575 | do { | ||
| 2576 | if (p->idx >= ib_chunk->length_dw) { | ||
| 2577 | DRM_ERROR("Can not parse packet at %d after CS end %d !\n", | ||
| 2578 | p->idx, ib_chunk->length_dw); | ||
| 2579 | return -EINVAL; | ||
| 2580 | } | ||
| 2581 | idx = p->idx; | ||
| 2582 | header = radeon_get_ib_value(p, idx); | ||
| 2583 | cmd = GET_DMA_CMD(header); | ||
| 2584 | count = GET_DMA_COUNT(header); | ||
| 2585 | tiled = GET_DMA_T(header); | ||
| 2586 | |||
| 2587 | switch (cmd) { | ||
| 2588 | case DMA_PACKET_WRITE: | ||
| 2589 | r = r600_dma_cs_next_reloc(p, &dst_reloc); | ||
| 2590 | if (r) { | ||
| 2591 | DRM_ERROR("bad DMA_PACKET_WRITE\n"); | ||
| 2592 | return -EINVAL; | ||
| 2593 | } | ||
| 2594 | if (tiled) { | ||
| 2595 | dst_offset = ib[idx+1]; | ||
| 2596 | dst_offset <<= 8; | ||
| 2597 | |||
| 2598 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 2599 | p->idx += count + 5; | ||
| 2600 | } else { | ||
| 2601 | dst_offset = ib[idx+1]; | ||
| 2602 | dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32; | ||
| 2603 | |||
| 2604 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2605 | ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 2606 | p->idx += count + 3; | ||
| 2607 | } | ||
| 2608 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 2609 | dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n", | ||
| 2610 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 2611 | return -EINVAL; | ||
| 2612 | } | ||
| 2613 | break; | ||
| 2614 | case DMA_PACKET_COPY: | ||
| 2615 | r = r600_dma_cs_next_reloc(p, &src_reloc); | ||
| 2616 | if (r) { | ||
| 2617 | DRM_ERROR("bad DMA_PACKET_COPY\n"); | ||
| 2618 | return -EINVAL; | ||
| 2619 | } | ||
| 2620 | r = r600_dma_cs_next_reloc(p, &dst_reloc); | ||
| 2621 | if (r) { | ||
| 2622 | DRM_ERROR("bad DMA_PACKET_COPY\n"); | ||
| 2623 | return -EINVAL; | ||
| 2624 | } | ||
| 2625 | if (tiled) { | ||
| 2626 | idx_value = radeon_get_ib_value(p, idx + 2); | ||
| 2627 | /* detile bit */ | ||
| 2628 | if (idx_value & (1 << 31)) { | ||
| 2629 | /* tiled src, linear dst */ | ||
| 2630 | src_offset = ib[idx+1]; | ||
| 2631 | src_offset <<= 8; | ||
| 2632 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | ||
| 2633 | |||
| 2634 | dst_offset = ib[idx+5]; | ||
| 2635 | dst_offset |= ((u64)(ib[idx+6] & 0xff)) << 32; | ||
| 2636 | ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2637 | ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 2638 | } else { | ||
| 2639 | /* linear src, tiled dst */ | ||
| 2640 | src_offset = ib[idx+5]; | ||
| 2641 | src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32; | ||
| 2642 | ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2643 | ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 2644 | |||
| 2645 | dst_offset = ib[idx+1]; | ||
| 2646 | dst_offset <<= 8; | ||
| 2647 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | ||
| 2648 | } | ||
| 2649 | p->idx += 7; | ||
| 2650 | } else { | ||
| 2651 | src_offset = ib[idx+2]; | ||
| 2652 | src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | ||
| 2653 | dst_offset = ib[idx+1]; | ||
| 2654 | dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | ||
| 2655 | |||
| 2656 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2657 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2658 | ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | ||
| 2659 | ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | ||
| 2660 | p->idx += 5; | ||
| 2661 | } | ||
| 2662 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | ||
| 2663 | dev_warn(p->dev, "DMA copy src buffer too small (%llu %lu)\n", | ||
| 2664 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | ||
| 2665 | return -EINVAL; | ||
| 2666 | } | ||
| 2667 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 2668 | dev_warn(p->dev, "DMA write dst buffer too small (%llu %lu)\n", | ||
| 2669 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 2670 | return -EINVAL; | ||
| 2671 | } | ||
| 2672 | break; | ||
| 2673 | case DMA_PACKET_CONSTANT_FILL: | ||
| 2674 | if (p->family < CHIP_RV770) { | ||
| 2675 | DRM_ERROR("Constant Fill is 7xx only !\n"); | ||
| 2676 | return -EINVAL; | ||
| 2677 | } | ||
| 2678 | r = r600_dma_cs_next_reloc(p, &dst_reloc); | ||
| 2679 | if (r) { | ||
| 2680 | DRM_ERROR("bad DMA_PACKET_WRITE\n"); | ||
| 2681 | return -EINVAL; | ||
| 2682 | } | ||
| 2683 | dst_offset = ib[idx+1]; | ||
| 2684 | dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16; | ||
| 2685 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | ||
| 2686 | dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", | ||
| 2687 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | ||
| 2688 | return -EINVAL; | ||
| 2689 | } | ||
| 2690 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | ||
| 2691 | ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000; | ||
| 2692 | p->idx += 4; | ||
| 2693 | break; | ||
| 2694 | case DMA_PACKET_NOP: | ||
| 2695 | p->idx += 1; | ||
| 2696 | break; | ||
| 2697 | default: | ||
| 2698 | DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); | ||
| 2699 | return -EINVAL; | ||
| 2700 | } | ||
| 2701 | } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); | ||
| 2702 | #if 0 | ||
| 2703 | for (r = 0; r < p->ib->length_dw; r++) { | ||
| 2704 | printk(KERN_INFO "%05d 0x%08X\n", r, p->ib.ptr[r]); | ||
| 2705 | mdelay(1); | ||
| 2706 | } | ||
| 2707 | #endif | ||
| 2708 | return 0; | ||
| 2709 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 1b9120a875ef..5dc744d43d12 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -839,6 +839,7 @@ struct radeon_cs_parser { | |||
| 839 | struct radeon_cs_reloc *relocs; | 839 | struct radeon_cs_reloc *relocs; |
| 840 | struct radeon_cs_reloc **relocs_ptr; | 840 | struct radeon_cs_reloc **relocs_ptr; |
| 841 | struct list_head validated; | 841 | struct list_head validated; |
| 842 | unsigned dma_reloc_idx; | ||
| 842 | /* indices of various chunks */ | 843 | /* indices of various chunks */ |
| 843 | int chunk_ib_idx; | 844 | int chunk_ib_idx; |
| 844 | int chunk_relocs_idx; | 845 | int chunk_relocs_idx; |
| @@ -1556,6 +1557,8 @@ struct radeon_device { | |||
| 1556 | /* Register mmio */ | 1557 | /* Register mmio */ |
| 1557 | resource_size_t rmmio_base; | 1558 | resource_size_t rmmio_base; |
| 1558 | resource_size_t rmmio_size; | 1559 | resource_size_t rmmio_size; |
| 1560 | /* protects concurrent MM_INDEX/DATA based register access */ | ||
| 1561 | spinlock_t mmio_idx_lock; | ||
| 1559 | void __iomem *rmmio; | 1562 | void __iomem *rmmio; |
| 1560 | radeon_rreg_t mc_rreg; | 1563 | radeon_rreg_t mc_rreg; |
| 1561 | radeon_wreg_t mc_wreg; | 1564 | radeon_wreg_t mc_wreg; |
| @@ -1631,8 +1634,10 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 1631 | void radeon_device_fini(struct radeon_device *rdev); | 1634 | void radeon_device_fini(struct radeon_device *rdev); |
| 1632 | int radeon_gpu_wait_for_idle(struct radeon_device *rdev); | 1635 | int radeon_gpu_wait_for_idle(struct radeon_device *rdev); |
| 1633 | 1636 | ||
| 1634 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg); | 1637 | uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg, |
| 1635 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 1638 | bool always_indirect); |
| 1639 | void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v, | ||
| 1640 | bool always_indirect); | ||
| 1636 | u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); | 1641 | u32 r100_io_rreg(struct radeon_device *rdev, u32 reg); |
| 1637 | void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); | 1642 | void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); |
| 1638 | 1643 | ||
| @@ -1648,9 +1653,11 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); | |||
| 1648 | #define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg)) | 1653 | #define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg)) |
| 1649 | #define RREG16(reg) readw((rdev->rmmio) + (reg)) | 1654 | #define RREG16(reg) readw((rdev->rmmio) + (reg)) |
| 1650 | #define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg)) | 1655 | #define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg)) |
| 1651 | #define RREG32(reg) r100_mm_rreg(rdev, (reg)) | 1656 | #define RREG32(reg) r100_mm_rreg(rdev, (reg), false) |
| 1652 | #define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg))) | 1657 | #define RREG32_IDX(reg) r100_mm_rreg(rdev, (reg), true) |
| 1653 | #define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v)) | 1658 | #define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg), false)) |
| 1659 | #define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v), false) | ||
| 1660 | #define WREG32_IDX(reg, v) r100_mm_wreg(rdev, (reg), (v), true) | ||
| 1654 | #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) | 1661 | #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) |
| 1655 | #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) | 1662 | #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK) |
| 1656 | #define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg)) | 1663 | #define RREG32_PLL(reg) rdev->pll_rreg(rdev, (reg)) |
| @@ -1675,7 +1682,7 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v); | |||
| 1675 | tmp_ |= ((val) & ~(mask)); \ | 1682 | tmp_ |= ((val) & ~(mask)); \ |
| 1676 | WREG32_PLL(reg, tmp_); \ | 1683 | WREG32_PLL(reg, tmp_); \ |
| 1677 | } while (0) | 1684 | } while (0) |
| 1678 | #define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg))) | 1685 | #define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg), false)) |
| 1679 | #define RREG32_IO(reg) r100_io_rreg(rdev, (reg)) | 1686 | #define RREG32_IO(reg) r100_io_rreg(rdev, (reg)) |
| 1680 | #define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v)) | 1687 | #define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v)) |
| 1681 | 1688 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 3ea0475f9a95..596bcbe80ed0 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
| @@ -952,7 +952,7 @@ static struct radeon_asic r600_asic = { | |||
| 952 | .ib_execute = &r600_dma_ring_ib_execute, | 952 | .ib_execute = &r600_dma_ring_ib_execute, |
| 953 | .emit_fence = &r600_dma_fence_ring_emit, | 953 | .emit_fence = &r600_dma_fence_ring_emit, |
| 954 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 954 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 955 | .cs_parse = NULL, | 955 | .cs_parse = &r600_dma_cs_parse, |
| 956 | .ring_test = &r600_dma_ring_test, | 956 | .ring_test = &r600_dma_ring_test, |
| 957 | .ib_test = &r600_dma_ib_test, | 957 | .ib_test = &r600_dma_ib_test, |
| 958 | .is_lockup = &r600_dma_is_lockup, | 958 | .is_lockup = &r600_dma_is_lockup, |
| @@ -1036,7 +1036,7 @@ static struct radeon_asic rs780_asic = { | |||
| 1036 | .ib_execute = &r600_dma_ring_ib_execute, | 1036 | .ib_execute = &r600_dma_ring_ib_execute, |
| 1037 | .emit_fence = &r600_dma_fence_ring_emit, | 1037 | .emit_fence = &r600_dma_fence_ring_emit, |
| 1038 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1038 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1039 | .cs_parse = NULL, | 1039 | .cs_parse = &r600_dma_cs_parse, |
| 1040 | .ring_test = &r600_dma_ring_test, | 1040 | .ring_test = &r600_dma_ring_test, |
| 1041 | .ib_test = &r600_dma_ib_test, | 1041 | .ib_test = &r600_dma_ib_test, |
| 1042 | .is_lockup = &r600_dma_is_lockup, | 1042 | .is_lockup = &r600_dma_is_lockup, |
| @@ -1120,7 +1120,7 @@ static struct radeon_asic rv770_asic = { | |||
| 1120 | .ib_execute = &r600_dma_ring_ib_execute, | 1120 | .ib_execute = &r600_dma_ring_ib_execute, |
| 1121 | .emit_fence = &r600_dma_fence_ring_emit, | 1121 | .emit_fence = &r600_dma_fence_ring_emit, |
| 1122 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1122 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1123 | .cs_parse = NULL, | 1123 | .cs_parse = &r600_dma_cs_parse, |
| 1124 | .ring_test = &r600_dma_ring_test, | 1124 | .ring_test = &r600_dma_ring_test, |
| 1125 | .ib_test = &r600_dma_ib_test, | 1125 | .ib_test = &r600_dma_ib_test, |
| 1126 | .is_lockup = &r600_dma_is_lockup, | 1126 | .is_lockup = &r600_dma_is_lockup, |
| @@ -1204,7 +1204,7 @@ static struct radeon_asic evergreen_asic = { | |||
| 1204 | .ib_execute = &evergreen_dma_ring_ib_execute, | 1204 | .ib_execute = &evergreen_dma_ring_ib_execute, |
| 1205 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1205 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1206 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1206 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1207 | .cs_parse = NULL, | 1207 | .cs_parse = &evergreen_dma_cs_parse, |
| 1208 | .ring_test = &r600_dma_ring_test, | 1208 | .ring_test = &r600_dma_ring_test, |
| 1209 | .ib_test = &r600_dma_ib_test, | 1209 | .ib_test = &r600_dma_ib_test, |
| 1210 | .is_lockup = &r600_dma_is_lockup, | 1210 | .is_lockup = &r600_dma_is_lockup, |
| @@ -1288,7 +1288,7 @@ static struct radeon_asic sumo_asic = { | |||
| 1288 | .ib_execute = &evergreen_dma_ring_ib_execute, | 1288 | .ib_execute = &evergreen_dma_ring_ib_execute, |
| 1289 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1289 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1290 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1290 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1291 | .cs_parse = NULL, | 1291 | .cs_parse = &evergreen_dma_cs_parse, |
| 1292 | .ring_test = &r600_dma_ring_test, | 1292 | .ring_test = &r600_dma_ring_test, |
| 1293 | .ib_test = &r600_dma_ib_test, | 1293 | .ib_test = &r600_dma_ib_test, |
| 1294 | .is_lockup = &r600_dma_is_lockup, | 1294 | .is_lockup = &r600_dma_is_lockup, |
| @@ -1372,7 +1372,7 @@ static struct radeon_asic btc_asic = { | |||
| 1372 | .ib_execute = &evergreen_dma_ring_ib_execute, | 1372 | .ib_execute = &evergreen_dma_ring_ib_execute, |
| 1373 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1373 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1374 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1374 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1375 | .cs_parse = NULL, | 1375 | .cs_parse = &evergreen_dma_cs_parse, |
| 1376 | .ring_test = &r600_dma_ring_test, | 1376 | .ring_test = &r600_dma_ring_test, |
| 1377 | .ib_test = &r600_dma_ib_test, | 1377 | .ib_test = &r600_dma_ib_test, |
| 1378 | .is_lockup = &r600_dma_is_lockup, | 1378 | .is_lockup = &r600_dma_is_lockup, |
| @@ -1484,9 +1484,10 @@ static struct radeon_asic cayman_asic = { | |||
| 1484 | }, | 1484 | }, |
| 1485 | [R600_RING_TYPE_DMA_INDEX] = { | 1485 | [R600_RING_TYPE_DMA_INDEX] = { |
| 1486 | .ib_execute = &cayman_dma_ring_ib_execute, | 1486 | .ib_execute = &cayman_dma_ring_ib_execute, |
| 1487 | .ib_parse = &evergreen_dma_ib_parse, | ||
| 1487 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1488 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1488 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1489 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1489 | .cs_parse = NULL, | 1490 | .cs_parse = &evergreen_dma_cs_parse, |
| 1490 | .ring_test = &r600_dma_ring_test, | 1491 | .ring_test = &r600_dma_ring_test, |
| 1491 | .ib_test = &r600_dma_ib_test, | 1492 | .ib_test = &r600_dma_ib_test, |
| 1492 | .is_lockup = &cayman_dma_is_lockup, | 1493 | .is_lockup = &cayman_dma_is_lockup, |
| @@ -1494,9 +1495,10 @@ static struct radeon_asic cayman_asic = { | |||
| 1494 | }, | 1495 | }, |
| 1495 | [CAYMAN_RING_TYPE_DMA1_INDEX] = { | 1496 | [CAYMAN_RING_TYPE_DMA1_INDEX] = { |
| 1496 | .ib_execute = &cayman_dma_ring_ib_execute, | 1497 | .ib_execute = &cayman_dma_ring_ib_execute, |
| 1498 | .ib_parse = &evergreen_dma_ib_parse, | ||
| 1497 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1499 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1498 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1500 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1499 | .cs_parse = NULL, | 1501 | .cs_parse = &evergreen_dma_cs_parse, |
| 1500 | .ring_test = &r600_dma_ring_test, | 1502 | .ring_test = &r600_dma_ring_test, |
| 1501 | .ib_test = &r600_dma_ib_test, | 1503 | .ib_test = &r600_dma_ib_test, |
| 1502 | .is_lockup = &cayman_dma_is_lockup, | 1504 | .is_lockup = &cayman_dma_is_lockup, |
| @@ -1609,9 +1611,10 @@ static struct radeon_asic trinity_asic = { | |||
| 1609 | }, | 1611 | }, |
| 1610 | [R600_RING_TYPE_DMA_INDEX] = { | 1612 | [R600_RING_TYPE_DMA_INDEX] = { |
| 1611 | .ib_execute = &cayman_dma_ring_ib_execute, | 1613 | .ib_execute = &cayman_dma_ring_ib_execute, |
| 1614 | .ib_parse = &evergreen_dma_ib_parse, | ||
| 1612 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1615 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1613 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1616 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1614 | .cs_parse = NULL, | 1617 | .cs_parse = &evergreen_dma_cs_parse, |
| 1615 | .ring_test = &r600_dma_ring_test, | 1618 | .ring_test = &r600_dma_ring_test, |
| 1616 | .ib_test = &r600_dma_ib_test, | 1619 | .ib_test = &r600_dma_ib_test, |
| 1617 | .is_lockup = &cayman_dma_is_lockup, | 1620 | .is_lockup = &cayman_dma_is_lockup, |
| @@ -1619,9 +1622,10 @@ static struct radeon_asic trinity_asic = { | |||
| 1619 | }, | 1622 | }, |
| 1620 | [CAYMAN_RING_TYPE_DMA1_INDEX] = { | 1623 | [CAYMAN_RING_TYPE_DMA1_INDEX] = { |
| 1621 | .ib_execute = &cayman_dma_ring_ib_execute, | 1624 | .ib_execute = &cayman_dma_ring_ib_execute, |
| 1625 | .ib_parse = &evergreen_dma_ib_parse, | ||
| 1622 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1626 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1623 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1627 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1624 | .cs_parse = NULL, | 1628 | .cs_parse = &evergreen_dma_cs_parse, |
| 1625 | .ring_test = &r600_dma_ring_test, | 1629 | .ring_test = &r600_dma_ring_test, |
| 1626 | .ib_test = &r600_dma_ib_test, | 1630 | .ib_test = &r600_dma_ib_test, |
| 1627 | .is_lockup = &cayman_dma_is_lockup, | 1631 | .is_lockup = &cayman_dma_is_lockup, |
| @@ -1734,6 +1738,7 @@ static struct radeon_asic si_asic = { | |||
| 1734 | }, | 1738 | }, |
| 1735 | [R600_RING_TYPE_DMA_INDEX] = { | 1739 | [R600_RING_TYPE_DMA_INDEX] = { |
| 1736 | .ib_execute = &cayman_dma_ring_ib_execute, | 1740 | .ib_execute = &cayman_dma_ring_ib_execute, |
| 1741 | .ib_parse = &evergreen_dma_ib_parse, | ||
| 1737 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1742 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1738 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1743 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1739 | .cs_parse = NULL, | 1744 | .cs_parse = NULL, |
| @@ -1744,6 +1749,7 @@ static struct radeon_asic si_asic = { | |||
| 1744 | }, | 1749 | }, |
| 1745 | [CAYMAN_RING_TYPE_DMA1_INDEX] = { | 1750 | [CAYMAN_RING_TYPE_DMA1_INDEX] = { |
| 1746 | .ib_execute = &cayman_dma_ring_ib_execute, | 1751 | .ib_execute = &cayman_dma_ring_ib_execute, |
| 1752 | .ib_parse = &evergreen_dma_ib_parse, | ||
| 1747 | .emit_fence = &evergreen_dma_fence_ring_emit, | 1753 | .emit_fence = &evergreen_dma_fence_ring_emit, |
| 1748 | .emit_semaphore = &r600_dma_semaphore_ring_emit, | 1754 | .emit_semaphore = &r600_dma_semaphore_ring_emit, |
| 1749 | .cs_parse = NULL, | 1755 | .cs_parse = NULL, |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index c338931190a5..5f4882cc2152 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h | |||
| @@ -304,6 +304,7 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev); | |||
| 304 | uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg); | 304 | uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg); |
| 305 | void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); | 305 | void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); |
| 306 | int r600_cs_parse(struct radeon_cs_parser *p); | 306 | int r600_cs_parse(struct radeon_cs_parser *p); |
| 307 | int r600_dma_cs_parse(struct radeon_cs_parser *p); | ||
| 307 | void r600_fence_ring_emit(struct radeon_device *rdev, | 308 | void r600_fence_ring_emit(struct radeon_device *rdev, |
| 308 | struct radeon_fence *fence); | 309 | struct radeon_fence *fence); |
| 309 | void r600_semaphore_ring_emit(struct radeon_device *rdev, | 310 | void r600_semaphore_ring_emit(struct radeon_device *rdev, |
| @@ -430,6 +431,7 @@ u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc); | |||
| 430 | int evergreen_irq_set(struct radeon_device *rdev); | 431 | int evergreen_irq_set(struct radeon_device *rdev); |
| 431 | int evergreen_irq_process(struct radeon_device *rdev); | 432 | int evergreen_irq_process(struct radeon_device *rdev); |
| 432 | extern int evergreen_cs_parse(struct radeon_cs_parser *p); | 433 | extern int evergreen_cs_parse(struct radeon_cs_parser *p); |
| 434 | extern int evergreen_dma_cs_parse(struct radeon_cs_parser *p); | ||
| 433 | extern void evergreen_pm_misc(struct radeon_device *rdev); | 435 | extern void evergreen_pm_misc(struct radeon_device *rdev); |
| 434 | extern void evergreen_pm_prepare(struct radeon_device *rdev); | 436 | extern void evergreen_pm_prepare(struct radeon_device *rdev); |
| 435 | extern void evergreen_pm_finish(struct radeon_device *rdev); | 437 | extern void evergreen_pm_finish(struct radeon_device *rdev); |
| @@ -471,6 +473,7 @@ void cayman_vm_set_page(struct radeon_device *rdev, uint64_t pe, | |||
| 471 | uint64_t addr, unsigned count, | 473 | uint64_t addr, unsigned count, |
| 472 | uint32_t incr, uint32_t flags); | 474 | uint32_t incr, uint32_t flags); |
| 473 | int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); | 475 | int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); |
| 476 | int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); | ||
| 474 | void cayman_dma_ring_ib_execute(struct radeon_device *rdev, | 477 | void cayman_dma_ring_ib_execute(struct radeon_device *rdev, |
| 475 | struct radeon_ib *ib); | 478 | struct radeon_ib *ib); |
| 476 | bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring); | 479 | bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring); |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 45b660b27cfc..4af89126e223 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
| @@ -3246,11 +3246,9 @@ static uint32_t combios_detect_ram(struct drm_device *dev, int ram, | |||
| 3246 | while (ram--) { | 3246 | while (ram--) { |
| 3247 | addr = ram * 1024 * 1024; | 3247 | addr = ram * 1024 * 1024; |
| 3248 | /* write to each page */ | 3248 | /* write to each page */ |
| 3249 | WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER); | 3249 | WREG32_IDX((addr) | RADEON_MM_APER, 0xdeadbeef); |
| 3250 | WREG32(RADEON_MM_DATA, 0xdeadbeef); | ||
| 3251 | /* read back and verify */ | 3250 | /* read back and verify */ |
| 3252 | WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER); | 3251 | if (RREG32_IDX((addr) | RADEON_MM_APER) != 0xdeadbeef) |
| 3253 | if (RREG32(RADEON_MM_DATA) != 0xdeadbeef) | ||
| 3254 | return 0; | 3252 | return 0; |
| 3255 | } | 3253 | } |
| 3256 | 3254 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 8b2797dc7b64..9143fc45e35b 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
| @@ -116,20 +116,6 @@ u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index) | |||
| 116 | } | 116 | } |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | u32 RADEON_READ_MM(drm_radeon_private_t *dev_priv, int addr) | ||
| 120 | { | ||
| 121 | u32 ret; | ||
| 122 | |||
| 123 | if (addr < 0x10000) | ||
| 124 | ret = DRM_READ32(dev_priv->mmio, addr); | ||
| 125 | else { | ||
| 126 | DRM_WRITE32(dev_priv->mmio, RADEON_MM_INDEX, addr); | ||
| 127 | ret = DRM_READ32(dev_priv->mmio, RADEON_MM_DATA); | ||
| 128 | } | ||
| 129 | |||
| 130 | return ret; | ||
| 131 | } | ||
| 132 | |||
| 133 | static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) | 119 | static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) |
| 134 | { | 120 | { |
| 135 | u32 ret; | 121 | u32 ret; |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 41672cc563fb..396baba0141a 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
| @@ -43,6 +43,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p) | |||
| 43 | return 0; | 43 | return 0; |
| 44 | } | 44 | } |
| 45 | chunk = &p->chunks[p->chunk_relocs_idx]; | 45 | chunk = &p->chunks[p->chunk_relocs_idx]; |
| 46 | p->dma_reloc_idx = 0; | ||
| 46 | /* FIXME: we assume that each relocs use 4 dwords */ | 47 | /* FIXME: we assume that each relocs use 4 dwords */ |
| 47 | p->nrelocs = chunk->length_dw / 4; | 48 | p->nrelocs = chunk->length_dw / 4; |
| 48 | p->relocs_ptr = kcalloc(p->nrelocs, sizeof(void *), GFP_KERNEL); | 49 | p->relocs_ptr = kcalloc(p->nrelocs, sizeof(void *), GFP_KERNEL); |
| @@ -111,6 +112,18 @@ static int radeon_cs_get_ring(struct radeon_cs_parser *p, u32 ring, s32 priority | |||
| 111 | } else | 112 | } else |
| 112 | p->ring = RADEON_RING_TYPE_GFX_INDEX; | 113 | p->ring = RADEON_RING_TYPE_GFX_INDEX; |
| 113 | break; | 114 | break; |
| 115 | case RADEON_CS_RING_DMA: | ||
| 116 | if (p->rdev->family >= CHIP_CAYMAN) { | ||
| 117 | if (p->priority > 0) | ||
| 118 | p->ring = R600_RING_TYPE_DMA_INDEX; | ||
| 119 | else | ||
| 120 | p->ring = CAYMAN_RING_TYPE_DMA1_INDEX; | ||
| 121 | } else if (p->rdev->family >= CHIP_R600) { | ||
| 122 | p->ring = R600_RING_TYPE_DMA_INDEX; | ||
| 123 | } else { | ||
| 124 | return -EINVAL; | ||
| 125 | } | ||
| 126 | break; | ||
| 114 | } | 127 | } |
| 115 | return 0; | 128 | return 0; |
| 116 | } | 129 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 0fe56c9f64bd..ad6df625e8b8 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
| @@ -66,24 +66,25 @@ static void radeon_hide_cursor(struct drm_crtc *crtc) | |||
| 66 | struct radeon_device *rdev = crtc->dev->dev_private; | 66 | struct radeon_device *rdev = crtc->dev->dev_private; |
| 67 | 67 | ||
| 68 | if (ASIC_IS_DCE4(rdev)) { | 68 | if (ASIC_IS_DCE4(rdev)) { |
| 69 | WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset); | 69 | WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset, |
| 70 | WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | | 70 | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) | |
| 71 | EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); | 71 | EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2)); |
| 72 | } else if (ASIC_IS_AVIVO(rdev)) { | 72 | } else if (ASIC_IS_AVIVO(rdev)) { |
| 73 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset); | 73 | WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, |
| 74 | WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); | 74 | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); |
| 75 | } else { | 75 | } else { |
| 76 | u32 reg; | ||
| 76 | switch (radeon_crtc->crtc_id) { | 77 | switch (radeon_crtc->crtc_id) { |
| 77 | case 0: | 78 | case 0: |
| 78 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); | 79 | reg = RADEON_CRTC_GEN_CNTL; |
| 79 | break; | 80 | break; |
| 80 | case 1: | 81 | case 1: |
| 81 | WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL); | 82 | reg = RADEON_CRTC2_GEN_CNTL; |
| 82 | break; | 83 | break; |
| 83 | default: | 84 | default: |
| 84 | return; | 85 | return; |
| 85 | } | 86 | } |
| 86 | WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN); | 87 | WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN); |
| 87 | } | 88 | } |
| 88 | } | 89 | } |
| 89 | 90 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e2f5f888c374..49b06590001e 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -1059,6 +1059,7 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 1059 | 1059 | ||
| 1060 | /* Registers mapping */ | 1060 | /* Registers mapping */ |
| 1061 | /* TODO: block userspace mapping of io register */ | 1061 | /* TODO: block userspace mapping of io register */ |
| 1062 | spin_lock_init(&rdev->mmio_idx_lock); | ||
| 1062 | rdev->rmmio_base = pci_resource_start(rdev->pdev, 2); | 1063 | rdev->rmmio_base = pci_resource_start(rdev->pdev, 2); |
| 1063 | rdev->rmmio_size = pci_resource_len(rdev->pdev, 2); | 1064 | rdev->rmmio_size = pci_resource_len(rdev->pdev, 2); |
| 1064 | rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size); | 1065 | rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size); |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index bfa2a6015727..310c0e5254ba 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -378,8 +378,12 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, | |||
| 378 | work->old_rbo = rbo; | 378 | work->old_rbo = rbo; |
| 379 | obj = new_radeon_fb->obj; | 379 | obj = new_radeon_fb->obj; |
| 380 | rbo = gem_to_radeon_bo(obj); | 380 | rbo = gem_to_radeon_bo(obj); |
| 381 | |||
| 382 | spin_lock(&rbo->tbo.bdev->fence_lock); | ||
| 381 | if (rbo->tbo.sync_obj) | 383 | if (rbo->tbo.sync_obj) |
| 382 | work->fence = radeon_fence_ref(rbo->tbo.sync_obj); | 384 | work->fence = radeon_fence_ref(rbo->tbo.sync_obj); |
| 385 | spin_unlock(&rbo->tbo.bdev->fence_lock); | ||
| 386 | |||
| 383 | INIT_WORK(&work->work, radeon_unpin_work_func); | 387 | INIT_WORK(&work->work, radeon_unpin_work_func); |
| 384 | 388 | ||
| 385 | /* We borrow the event spin lock for protecting unpin_work */ | 389 | /* We borrow the event spin lock for protecting unpin_work */ |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 91b64278c4ff..9b1a727d3c9e 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -66,9 +66,11 @@ | |||
| 66 | * 2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880 | 66 | * 2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880 |
| 67 | * 2.24.0 - eg only: allow MIP_ADDRESS=0 for MSAA textures | 67 | * 2.24.0 - eg only: allow MIP_ADDRESS=0 for MSAA textures |
| 68 | * 2.25.0 - eg+: new info request for num SE and num SH | 68 | * 2.25.0 - eg+: new info request for num SE and num SH |
| 69 | * 2.26.0 - r600-eg: fix htile size computation | ||
| 70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA | ||
| 69 | */ | 71 | */ |
| 70 | #define KMS_DRIVER_MAJOR 2 | 72 | #define KMS_DRIVER_MAJOR 2 |
| 71 | #define KMS_DRIVER_MINOR 25 | 73 | #define KMS_DRIVER_MINOR 27 |
| 72 | #define KMS_DRIVER_PATCHLEVEL 0 | 74 | #define KMS_DRIVER_PATCHLEVEL 0 |
| 73 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 75 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
| 74 | int radeon_driver_unload_kms(struct drm_device *dev); | 76 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index a1b59ca96d01..e7fdf163a8ca 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
| @@ -366,7 +366,6 @@ extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file | |||
| 366 | extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv); | 366 | extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv); |
| 367 | extern void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc); | 367 | extern void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc); |
| 368 | extern void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base); | 368 | extern void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base); |
| 369 | extern u32 RADEON_READ_MM(drm_radeon_private_t *dev_priv, int addr); | ||
| 370 | 369 | ||
| 371 | extern void radeon_freelist_reset(struct drm_device * dev); | 370 | extern void radeon_freelist_reset(struct drm_device * dev); |
| 372 | extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); | 371 | extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 93d3445477be..883c95d8d90f 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -96,9 +96,9 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
| 96 | } | 96 | } |
| 97 | if (domain & RADEON_GEM_DOMAIN_CPU) { | 97 | if (domain & RADEON_GEM_DOMAIN_CPU) { |
| 98 | if (rbo->rdev->flags & RADEON_IS_AGP) { | 98 | if (rbo->rdev->flags & RADEON_IS_AGP) { |
| 99 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; | 99 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM; |
| 100 | } else { | 100 | } else { |
| 101 | rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; | 101 | rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM; |
| 102 | } | 102 | } |
| 103 | } | 103 | } |
| 104 | if (!c) | 104 | if (!c) |
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h index 5645a878faec..eeda91774c8a 100644 --- a/include/uapi/drm/radeon_drm.h +++ b/include/uapi/drm/radeon_drm.h | |||
| @@ -917,6 +917,7 @@ struct drm_radeon_gem_va { | |||
| 917 | /* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */ | 917 | /* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */ |
| 918 | #define RADEON_CS_RING_GFX 0 | 918 | #define RADEON_CS_RING_GFX 0 |
| 919 | #define RADEON_CS_RING_COMPUTE 1 | 919 | #define RADEON_CS_RING_COMPUTE 1 |
| 920 | #define RADEON_CS_RING_DMA 2 | ||
| 920 | /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ | 921 | /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */ |
| 921 | /* 0 = normal, + = higher priority, - = lower priority */ | 922 | /* 0 = normal, + = higher priority, - = lower priority */ |
| 922 | 923 | ||
