Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daein...
authorDave Airlie <airlied@redhat.com>
Sun, 16 Dec 2012 05:49:46 +0000 (05:49 +0000)
committerDave Airlie <airlied@redhat.com>
Sun, 16 Dec 2012 05:49:46 +0000 (05:49 +0000)
Inki writes:
"- add dmabuf attach/detach feature
  . This patch would resolve performance deterioration issue
    when v4l2-based driver is using the buffer imported from gem.
- drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
  . With gem allocation, kernel space mapping isn't allocated and
    also physical pages aren't mapped with the kernel space.
    The physical pages are mapped with kernel space though vmap
    function only for console framebuffer.
- add the below two patches I missed.
  drm: exynos: moved exynos drm device registration to drm driver
  drm: exynos: moved exynos drm hdmi device registration to drm driver
- add IPP subsystem framework and its-based device drivers.
  . This patch set includes fimc, rotator and gsc drivers to perform
    image scaling, rotation and color space conversion.
- add runtime pm support to hdmi driver.
- And fixups and cleanups."

* 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (30 commits)
  drm/exynos: add gsc ipp driver
  drm/exynos: add rotator ipp driver
  drm/exynos: add fimc ipp driver
  drm/exynos: add iommu support for ipp
  drm/exynos: add ipp subsystem
  drm/exynos: support device tree for fimd
  drm/exynos: support extended screen coordinate of fimd
  drm/exynos: fix x, y coordinates for right bottom pixel
  drm/exynos: fix fb offset calculation for plane
  drm/exynos: hdmi: Fix potential NULL pointer dereference error
  drm/exynos: hdmi: Add CONFIG_OF and use of_match_ptr() macro
  drm/exynos: add support for hdmiphy power control for exynos5
  drm/exynos: add runtime pm support for mixer
  drm/exynos: added runtime pm support for hdmi
  drm/exynos: fix allocation and cache mapping type
  drm/exynos: reorder framebuffer init sequence
  drm/exynos/iommu: fix return value check in drm_create_iommu_mapping()
  drm/exynos: remove unused vaddr member
  drm/exynos: use DMA_ATTR_NO_KERNEL_MAPPING attribute
  drm/exynos: add exception codes to exynos_drm_fbdev_create()
  ...

16 files changed:
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_cp.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_cursor.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_display.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_drv.h
drivers/gpu/drm/radeon/radeon_object.c
include/uapi/drm/radeon_drm.h

index 62c227104781fdde9afcea698303249eb2e7a06f..74c6b42d259788fab5f35fd3d10343b16b38f8f2 100644 (file)
@@ -34,6 +34,8 @@
 #define MAX(a,b)                   (((a)>(b))?(a):(b))
 #define MIN(a,b)                   (((a)<(b))?(a):(b))
 
+int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
+                          struct radeon_cs_reloc **cs_reloc);
 static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
                                          struct radeon_cs_reloc **cs_reloc);
 
@@ -507,20 +509,28 @@ static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
                /* height is npipes htiles aligned == npipes * 8 pixel aligned */
                nby = round_up(nby, track->npipes * 8);
        } else {
+               /* always assume 8x8 htile */
+               /* align is htile align * 8, htile align vary according to
+                * number of pipe and tile width and nby
+                */
                switch (track->npipes) {
                case 8:
+                       /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
                        nbx = round_up(nbx, 64 * 8);
                        nby = round_up(nby, 64 * 8);
                        break;
                case 4:
+                       /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
                        nbx = round_up(nbx, 64 * 8);
                        nby = round_up(nby, 32 * 8);
                        break;
                case 2:
+                       /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
                        nbx = round_up(nbx, 32 * 8);
                        nby = round_up(nby, 32 * 8);
                        break;
                case 1:
+                       /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
                        nbx = round_up(nbx, 32 * 8);
                        nby = round_up(nby, 16 * 8);
                        break;
@@ -531,9 +541,10 @@ static int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p,
                }
        }
        /* compute number of htile */
-       nbx = nbx / 8;
-       nby = nby / 8;
-       size = nbx * nby * 4;
+       nbx = nbx >> 3;
+       nby = nby >> 3;
+       /* size must be aligned on npipes * 2K boundary */
+       size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
        size += track->htile_offset;
 
        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)
        case DB_HTILE_SURFACE:
                /* 8x8 only */
                track->htile_surface = radeon_get_ib_value(p, idx);
+               /* force 8x8 htile width and height */
+               ib[idx] |= 3;
                track->db_dirty = true;
                break;
        case CB_IMMED0_BASE:
@@ -2243,6 +2256,18 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                command = radeon_get_ib_value(p, idx+4);
                size = command & 0x1fffff;
                info = radeon_get_ib_value(p, idx+1);
+               if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
+                   (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
+                   ((((info & 0x00300000) >> 20) == 0) &&
+                    (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
+                   ((((info & 0x60000000) >> 29) == 0) &&
+                    (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
+                       /* non mem to mem copies requires dw aligned count */
+                       if (size % 4) {
+                               DRM_ERROR("CP DMA command requires dw count alignment\n");
+                               return -EINVAL;
+                       }
+               }
                if (command & PACKET3_CP_DMA_CMD_SAS) {
                        /* src address space is register */
                        /* GDS is ok */
@@ -2804,6 +2829,455 @@ int evergreen_cs_parse(struct radeon_cs_parser *p)
        return 0;
 }
 
+/*
+ *  DMA
+ */
+
+#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
+#define GET_DMA_COUNT(h) ((h) & 0x000fffff)
+#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
+#define GET_DMA_NEW(h) (((h) & 0x04000000) >> 26)
+#define GET_DMA_MISC(h) (((h) & 0x0700000) >> 20)
+
+/**
+ * evergreen_dma_cs_parse() - parse the DMA IB
+ * @p:         parser structure holding parsing context.
+ *
+ * Parses the DMA IB from the CS ioctl and updates
+ * the GPU addresses based on the reloc information and
+ * checks for errors. (Evergreen-Cayman)
+ * Returns 0 for success and an error on failure.
+ **/
+int evergreen_dma_cs_parse(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+       struct radeon_cs_reloc *src_reloc, *dst_reloc, *dst2_reloc;
+       u32 header, cmd, count, tiled, new_cmd, misc;
+       volatile u32 *ib = p->ib.ptr;
+       u32 idx, idx_value;
+       u64 src_offset, dst_offset, dst2_offset;
+       int r;
+
+       do {
+               if (p->idx >= ib_chunk->length_dw) {
+                       DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+                                 p->idx, ib_chunk->length_dw);
+                       return -EINVAL;
+               }
+               idx = p->idx;
+               header = radeon_get_ib_value(p, idx);
+               cmd = GET_DMA_CMD(header);
+               count = GET_DMA_COUNT(header);
+               tiled = GET_DMA_T(header);
+               new_cmd = GET_DMA_NEW(header);
+               misc = GET_DMA_MISC(header);
+
+               switch (cmd) {
+               case DMA_PACKET_WRITE:
+                       r = r600_dma_cs_next_reloc(p, &dst_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_WRITE\n");
+                               return -EINVAL;
+                       }
+                       if (tiled) {
+                               dst_offset = ib[idx+1];
+                               dst_offset <<= 8;
+
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               p->idx += count + 7;
+                       } else {
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
+
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += count + 3;
+                       }
+                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                               dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
+                                        dst_offset, radeon_bo_size(dst_reloc->robj));
+                               return -EINVAL;
+                       }
+                       break;
+               case DMA_PACKET_COPY:
+                       r = r600_dma_cs_next_reloc(p, &src_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_COPY\n");
+                               return -EINVAL;
+                       }
+                       r = r600_dma_cs_next_reloc(p, &dst_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_COPY\n");
+                               return -EINVAL;
+                       }
+                       if (tiled) {
+                               idx_value = radeon_get_ib_value(p, idx + 2);
+                               if (new_cmd) {
+                                       switch (misc) {
+                                       case 0:
+                                               /* L2T, frame to fields */
+                                               if (idx_value & (1 << 31)) {
+                                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                                               if (r) {
+                                                       DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               dst_offset = ib[idx+1];
+                                               dst_offset <<= 8;
+                                               dst2_offset = ib[idx+2];
+                                               dst2_offset <<= 8;
+                                               src_offset = ib[idx+8];
+                                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n",
+                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
+                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n",
+                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                               p->idx += 10;
+                                               break;
+                                       case 1:
+                                               /* L2T, T2L partial */
+                                               if (p->family < CHIP_CAYMAN) {
+                                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
+                                                       return -EINVAL;
+                                               }
+                                               /* detile bit */
+                                               if (idx_value & (1 << 31)) {
+                                                       /* tiled src, linear dst */
+                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                               } else {
+                                                       /* linear src, tiled dst */
+                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               }
+                                               p->idx += 12;
+                                               break;
+                                       case 3:
+                                               /* L2T, broadcast */
+                                               if (idx_value & (1 << 31)) {
+                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                                               if (r) {
+                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               dst_offset = ib[idx+1];
+                                               dst_offset <<= 8;
+                                               dst2_offset = ib[idx+2];
+                                               dst2_offset <<= 8;
+                                               src_offset = ib[idx+8];
+                                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
+                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
+                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
+                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                               p->idx += 10;
+                                               break;
+                                       case 4:
+                                               /* L2T, T2L */
+                                               /* detile bit */
+                                               if (idx_value & (1 << 31)) {
+                                                       /* tiled src, linear dst */
+                                                       src_offset = ib[idx+1];
+                                                       src_offset <<= 8;
+                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                                       dst_offset = ib[idx+7];
+                                                       dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                               } else {
+                                                       /* linear src, tiled dst */
+                                                       src_offset = ib[idx+7];
+                                                       src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                                       dst_offset = ib[idx+1];
+                                                       dst_offset <<= 8;
+                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               }
+                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n",
+                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n",
+                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               p->idx += 9;
+                                               break;
+                                       case 5:
+                                               /* T2T partial */
+                                               if (p->family < CHIP_CAYMAN) {
+                                                       DRM_ERROR("L2T, T2L Partial is cayman only !\n");
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               p->idx += 13;
+                                               break;
+                                       case 7:
+                                               /* L2T, broadcast */
+                                               if (idx_value & (1 << 31)) {
+                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                                               if (r) {
+                                                       DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               dst_offset = ib[idx+1];
+                                               dst_offset <<= 8;
+                                               dst2_offset = ib[idx+2];
+                                               dst2_offset <<= 8;
+                                               src_offset = ib[idx+8];
+                                               src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32;
+                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
+                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
+                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n",
+                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset >> 8);
+                                               ib[idx+8] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                               ib[idx+9] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                               p->idx += 10;
+                                               break;
+                                       default:
+                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
+                                               return -EINVAL;
+                                       }
+                               } else {
+                                       switch (misc) {
+                                       case 0:
+                                               /* detile bit */
+                                               if (idx_value & (1 << 31)) {
+                                                       /* tiled src, linear dst */
+                                                       src_offset = ib[idx+1];
+                                                       src_offset <<= 8;
+                                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                                       dst_offset = ib[idx+7];
+                                                       dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                                       ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                               } else {
+                                                       /* linear src, tiled dst */
+                                                       src_offset = ib[idx+7];
+                                                       src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32;
+                                                       ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                                       ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                                       dst_offset = ib[idx+1];
+                                                       dst_offset <<= 8;
+                                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                                               }
+                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n",
+                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n",
+                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               p->idx += 9;
+                                               break;
+                                       default:
+                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
+                                               return -EINVAL;
+                                       }
+                               }
+                       } else {
+                               if (new_cmd) {
+                                       switch (misc) {
+                                       case 0:
+                                               /* L2L, byte */
+                                               src_offset = ib[idx+2];
+                                               src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                                               dst_offset = ib[idx+1];
+                                               dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                                               if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n",
+                                                                src_offset + count, radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n",
+                                                                dst_offset + count, radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
+                                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
+                                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                               p->idx += 5;
+                                               break;
+                                       case 1:
+                                               /* L2L, partial */
+                                               if (p->family < CHIP_CAYMAN) {
+                                                       DRM_ERROR("L2L Partial is cayman only !\n");
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset & 0xffffffff);
+                                               ib[idx+2] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                               ib[idx+4] += (u32)(dst_reloc->lobj.gpu_offset & 0xffffffff);
+                                               ib[idx+5] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+
+                                               p->idx += 9;
+                                               break;
+                                       case 4:
+                                               /* L2L, dw, broadcast */
+                                               r = r600_dma_cs_next_reloc(p, &dst2_reloc);
+                                               if (r) {
+                                                       DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n");
+                                                       return -EINVAL;
+                                               }
+                                               dst_offset = ib[idx+1];
+                                               dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                                               dst2_offset = ib[idx+2];
+                                               dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32;
+                                               src_offset = ib[idx+3];
+                                               src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                               if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n",
+                                                                src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n",
+                                                                dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) {
+                                                       dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n",
+                                                                dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj));
+                                                       return -EINVAL;
+                                               }
+                                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                               ib[idx+2] += (u32)(dst2_reloc->lobj.gpu_offset & 0xfffffffc);
+                                               ib[idx+3] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                               ib[idx+4] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                               ib[idx+5] += upper_32_bits(dst2_reloc->lobj.gpu_offset) & 0xff;
+                                               ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                               p->idx += 7;
+                                               break;
+                                       default:
+                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
+                                               return -EINVAL;
+                                       }
+                               } else {
+                                       /* L2L, dw */
+                                       src_offset = ib[idx+2];
+                                       src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                                       dst_offset = ib[idx+1];
+                                       dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+                                       if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                                               dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n",
+                                                        src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                                               return -EINVAL;
+                                       }
+                                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                                               dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n",
+                                                        dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                                               return -EINVAL;
+                                       }
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                                       ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                                       p->idx += 5;
+                               }
+                       }
+                       break;
+               case DMA_PACKET_CONSTANT_FILL:
+                       r = r600_dma_cs_next_reloc(p, &dst_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n");
+                               return -EINVAL;
+                       }
+                       dst_offset = ib[idx+1];
+                       dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
+                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                               dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
+                                        dst_offset, radeon_bo_size(dst_reloc->robj));
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                       ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000;
+                       p->idx += 4;
+                       break;
+               case DMA_PACKET_NOP:
+                       p->idx += 1;
+                       break;
+               default:
+                       DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
+                       return -EINVAL;
+               }
+       } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+#if 0
+       for (r = 0; r < p->ib->length_dw; r++) {
+               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib.ptr[r]);
+               mdelay(1);
+       }
+#endif
+       return 0;
+}
+
 /* vm parser */
 static bool evergreen_vm_reg_valid(u32 reg)
 {
@@ -3010,6 +3484,18 @@ static int evergreen_vm_packet3_check(struct radeon_device *rdev,
        case PACKET3_CP_DMA:
                command = ib[idx + 4];
                info = ib[idx + 1];
+               if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */
+                   (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */
+                   ((((info & 0x00300000) >> 20) == 0) &&
+                    (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */
+                   ((((info & 0x60000000) >> 29) == 0) &&
+                    (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */
+                       /* non mem to mem copies requires dw aligned count */
+                       if ((command & 0x1fffff) % 4) {
+                               DRM_ERROR("CP DMA command requires dw count alignment\n");
+                               return -EINVAL;
+                       }
+               }
                if (command & PACKET3_CP_DMA_CMD_SAS) {
                        /* src address space is register */
                        if (((info & 0x60000000) >> 29) == 0) {
@@ -3094,3 +3580,114 @@ int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
 
        return ret;
 }
+
+/**
+ * evergreen_dma_ib_parse() - parse the DMA IB for VM
+ * @rdev: radeon_device pointer
+ * @ib:        radeon_ib pointer
+ *
+ * Parses the DMA IB from the VM CS ioctl
+ * checks for errors. (Cayman-SI)
+ * Returns 0 for success and an error on failure.
+ **/
+int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib)
+{
+       u32 idx = 0;
+       u32 header, cmd, count, tiled, new_cmd, misc;
+
+       do {
+               header = ib->ptr[idx];
+               cmd = GET_DMA_CMD(header);
+               count = GET_DMA_COUNT(header);
+               tiled = GET_DMA_T(header);
+               new_cmd = GET_DMA_NEW(header);
+               misc = GET_DMA_MISC(header);
+
+               switch (cmd) {
+               case DMA_PACKET_WRITE:
+                       if (tiled)
+                               idx += count + 7;
+                       else
+                               idx += count + 3;
+                       break;
+               case DMA_PACKET_COPY:
+                       if (tiled) {
+                               if (new_cmd) {
+                                       switch (misc) {
+                                       case 0:
+                                               /* L2T, frame to fields */
+                                               idx += 10;
+                                               break;
+                                       case 1:
+                                               /* L2T, T2L partial */
+                                               idx += 12;
+                                               break;
+                                       case 3:
+                                               /* L2T, broadcast */
+                                               idx += 10;
+                                               break;
+                                       case 4:
+                                               /* L2T, T2L */
+                                               idx += 9;
+                                               break;
+                                       case 5:
+                                               /* T2T partial */
+                                               idx += 13;
+                                               break;
+                                       case 7:
+                                               /* L2T, broadcast */
+                                               idx += 10;
+                                               break;
+                                       default:
+                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
+                                               return -EINVAL;
+                                       }
+                               } else {
+                                       switch (misc) {
+                                       case 0:
+                                               idx += 9;
+                                               break;
+                                       default:
+                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
+                                               return -EINVAL;
+                                       }
+                               }
+                       } else {
+                               if (new_cmd) {
+                                       switch (misc) {
+                                       case 0:
+                                               /* L2L, byte */
+                                               idx += 5;
+                                               break;
+                                       case 1:
+                                               /* L2L, partial */
+                                               idx += 9;
+                                               break;
+                                       case 4:
+                                               /* L2L, dw, broadcast */
+                                               idx += 7;
+                                               break;
+                                       default:
+                                               DRM_ERROR("bad DMA_PACKET_COPY misc %u\n", misc);
+                                               return -EINVAL;
+                                       }
+                               } else {
+                                       /* L2L, dw */
+                                       idx += 5;
+                               }
+                       }
+                       break;
+               case DMA_PACKET_CONSTANT_FILL:
+                       idx += 4;
+                       break;
+               case DMA_PACKET_NOP:
+                       idx += 1;
+                       break;
+               default:
+                       DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
+                       return -EINVAL;
+               }
+       } while (idx < ib->length_dw);
+
+       return 0;
+}
index 376884f1bcd29fc503c4a52fc29c95765b719a61..8ff7cac222dce7ccba37e5318adea5773571cd6f 100644 (file)
@@ -4135,23 +4135,36 @@ int r100_init(struct radeon_device *rdev)
        return 0;
 }
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
+                     bool always_indirect)
 {
-       if (reg < rdev->rmmio_size)
+       if (reg < rdev->rmmio_size && !always_indirect)
                return readl(((void __iomem *)rdev->rmmio) + reg);
        else {
+               unsigned long flags;
+               uint32_t ret;
+
+               spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
                writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
-               return readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+               ret = readl(((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+               spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
+
+               return ret;
        }
 }
 
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
+                 bool always_indirect)
 {
-       if (reg < rdev->rmmio_size)
+       if (reg < rdev->rmmio_size && !always_indirect)
                writel(v, ((void __iomem *)rdev->rmmio) + reg);
        else {
+               unsigned long flags;
+
+               spin_lock_irqsave(&rdev->mmio_idx_lock, flags);
                writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX);
                writel(v, ((void __iomem *)rdev->rmmio) + RADEON_MM_DATA);
+               spin_unlock_irqrestore(&rdev->mmio_idx_lock, flags);
        }
 }
 
index 5d6e7f959e756e999082736a4b736feef7609c3b..0be768be530c7ceea8e0b4125a3932ed4e696c35 100644 (file)
@@ -657,87 +657,30 @@ static int r600_cs_track_validate_db(struct radeon_cs_parser *p)
                        /* nby is npipes htiles aligned == npipes * 8 pixel aligned */
                        nby = round_up(nby, track->npipes * 8);
                } else {
-                       /* htile widht & nby (8 or 4) make 2 bits number */
-                       tmp = track->htile_surface & 3;
+                       /* always assume 8x8 htile */
                        /* align is htile align * 8, htile align vary according to
                         * number of pipe and tile width and nby
                         */
                        switch (track->npipes) {
                        case 8:
-                               switch (tmp) {
-                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
-                                       nbx = round_up(nbx, 64 * 8);
-                                       nby = round_up(nby, 64 * 8);
-                                       break;
-                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
-                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 64 * 8);
-                                       nby = round_up(nby, 32 * 8);
-                                       break;
-                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 32 * 8);
-                                       nby = round_up(nby, 32 * 8);
-                                       break;
-                               default:
-                                       return -EINVAL;
-                               }
+                               /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                               nbx = round_up(nbx, 64 * 8);
+                               nby = round_up(nby, 64 * 8);
                                break;
                        case 4:
-                               switch (tmp) {
-                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
-                                       nbx = round_up(nbx, 64 * 8);
-                                       nby = round_up(nby, 32 * 8);
-                                       break;
-                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
-                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 32 * 8);
-                                       nby = round_up(nby, 32 * 8);
-                                       break;
-                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 32 * 8);
-                                       nby = round_up(nby, 16 * 8);
-                                       break;
-                               default:
-                                       return -EINVAL;
-                               }
+                               /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                               nbx = round_up(nbx, 64 * 8);
+                               nby = round_up(nby, 32 * 8);
                                break;
                        case 2:
-                               switch (tmp) {
-                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
-                                       nbx = round_up(nbx, 32 * 8);
-                                       nby = round_up(nby, 32 * 8);
-                                       break;
-                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
-                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 32 * 8);
-                                       nby = round_up(nby, 16 * 8);
-                                       break;
-                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 16 * 8);
-                                       nby = round_up(nby, 16 * 8);
-                                       break;
-                               default:
-                                       return -EINVAL;
-                               }
+                               /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                               nbx = round_up(nbx, 32 * 8);
+                               nby = round_up(nby, 32 * 8);
                                break;
                        case 1:
-                               switch (tmp) {
-                               case 3: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
-                                       nbx = round_up(nbx, 32 * 8);
-                                       nby = round_up(nby, 16 * 8);
-                                       break;
-                               case 2: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 8*/
-                               case 1: /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 16 * 8);
-                                       nby = round_up(nby, 16 * 8);
-                                       break;
-                               case 0: /* HTILE_WIDTH = 4 & HTILE_HEIGHT = 4*/
-                                       nbx = round_up(nbx, 16 * 8);
-                                       nby = round_up(nby, 8 * 8);
-                                       break;
-                               default:
-                                       return -EINVAL;
-                               }
+                               /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
+                               nbx = round_up(nbx, 32 * 8);
+                               nby = round_up(nby, 16 * 8);
                                break;
                        default:
                                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)
                        }
                }
                /* compute number of htile */
-               nbx = G_028D24_HTILE_WIDTH(track->htile_surface) ? nbx / 8 : nbx / 4;
-               nby = G_028D24_HTILE_HEIGHT(track->htile_surface) ? nby / 8 : nby / 4;
-               size = nbx * nby * 4;
+               nbx = nbx >> 3;
+               nby = nby >> 3;
+               /* size must be aligned on npipes * 2K boundary */
+               size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
                size += track->htile_offset;
 
                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)
                break;
        case DB_HTILE_SURFACE:
                track->htile_surface = radeon_get_ib_value(p, idx);
+               /* force 8x8 htile width and height */
+               ib[idx] |= 3;
                track->db_dirty = true;
                break;
        case SQ_PGM_START_FS:
@@ -2568,3 +2514,196 @@ void r600_cs_legacy_init(void)
 {
        r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_nomm;
 }
+
+/*
+ *  DMA
+ */
+/**
+ * r600_dma_cs_next_reloc() - parse next reloc
+ * @p:         parser structure holding parsing context.
+ * @cs_reloc:          reloc informations
+ *
+ * Return the next reloc, do bo validation and compute
+ * GPU offset using the provided start.
+ **/
+int r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
+                          struct radeon_cs_reloc **cs_reloc)
+{
+       struct radeon_cs_chunk *relocs_chunk;
+       unsigned idx;
+
+       if (p->chunk_relocs_idx == -1) {
+               DRM_ERROR("No relocation chunk !\n");
+               return -EINVAL;
+       }
+       *cs_reloc = NULL;
+       relocs_chunk = &p->chunks[p->chunk_relocs_idx];
+       idx = p->dma_reloc_idx;
+       if (idx >= relocs_chunk->length_dw) {
+               DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
+                         idx, relocs_chunk->length_dw);
+               return -EINVAL;
+       }
+       *cs_reloc = p->relocs_ptr[idx];
+       p->dma_reloc_idx++;
+       return 0;
+}
+
+#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
+#define GET_DMA_COUNT(h) ((h) & 0x0000ffff)
+#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
+
+/**
+ * r600_dma_cs_parse() - parse the DMA IB
+ * @p:         parser structure holding parsing context.
+ *
+ * Parses the DMA IB from the CS ioctl and updates
+ * the GPU addresses based on the reloc information and
+ * checks for errors. (R6xx-R7xx)
+ * Returns 0 for success and an error on failure.
+ **/
+int r600_dma_cs_parse(struct radeon_cs_parser *p)
+{
+       struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx];
+       struct radeon_cs_reloc *src_reloc, *dst_reloc;
+       u32 header, cmd, count, tiled;
+       volatile u32 *ib = p->ib.ptr;
+       u32 idx, idx_value;
+       u64 src_offset, dst_offset;
+       int r;
+
+       do {
+               if (p->idx >= ib_chunk->length_dw) {
+                       DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
+                                 p->idx, ib_chunk->length_dw);
+                       return -EINVAL;
+               }
+               idx = p->idx;
+               header = radeon_get_ib_value(p, idx);
+               cmd = GET_DMA_CMD(header);
+               count = GET_DMA_COUNT(header);
+               tiled = GET_DMA_T(header);
+
+               switch (cmd) {
+               case DMA_PACKET_WRITE:
+                       r = r600_dma_cs_next_reloc(p, &dst_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_WRITE\n");
+                               return -EINVAL;
+                       }
+                       if (tiled) {
+                               dst_offset = ib[idx+1];
+                               dst_offset <<= 8;
+
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               p->idx += count + 5;
+                       } else {
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32;
+
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += count + 3;
+                       }
+                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                               dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
+                                        dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                               return -EINVAL;
+                       }
+                       break;
+               case DMA_PACKET_COPY:
+                       r = r600_dma_cs_next_reloc(p, &src_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_COPY\n");
+                               return -EINVAL;
+                       }
+                       r = r600_dma_cs_next_reloc(p, &dst_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_COPY\n");
+                               return -EINVAL;
+                       }
+                       if (tiled) {
+                               idx_value = radeon_get_ib_value(p, idx + 2);
+                               /* detile bit */
+                               if (idx_value & (1 << 31)) {
+                                       /* tiled src, linear dst */
+                                       src_offset = ib[idx+1];
+                                       src_offset <<= 8;
+                                       ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8);
+
+                                       dst_offset = ib[idx+5];
+                                       dst_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                       ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               } else {
+                                       /* linear src, tiled dst */
+                                       src_offset = ib[idx+5];
+                                       src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32;
+                                       ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                                       ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+
+                                       dst_offset = ib[idx+1];
+                                       dst_offset <<= 8;
+                                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8);
+                               }
+                               p->idx += 7;
+                       } else {
+                               src_offset = ib[idx+2];
+                               src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32;
+                               dst_offset = ib[idx+1];
+                               dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32;
+
+                               ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc);
+                               ib[idx+3] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff;
+                               ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff;
+                               p->idx += 5;
+                       }
+                       if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
+                               dev_warn(p->dev, "DMA copy src buffer too small (%llu %lu)\n",
+                                        src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
+                               return -EINVAL;
+                       }
+                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                               dev_warn(p->dev, "DMA write dst buffer too small (%llu %lu)\n",
+                                        dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                               return -EINVAL;
+                       }
+                       break;
+               case DMA_PACKET_CONSTANT_FILL:
+                       if (p->family < CHIP_RV770) {
+                               DRM_ERROR("Constant Fill is 7xx only !\n");
+                               return -EINVAL;
+                       }
+                       r = r600_dma_cs_next_reloc(p, &dst_reloc);
+                       if (r) {
+                               DRM_ERROR("bad DMA_PACKET_WRITE\n");
+                               return -EINVAL;
+                       }
+                       dst_offset = ib[idx+1];
+                       dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16;
+                       if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
+                               dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
+                                        dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
+                               return -EINVAL;
+                       }
+                       ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc);
+                       ib[idx+3] += (upper_32_bits(dst_reloc->lobj.gpu_offset) << 16) & 0x00ff0000;
+                       p->idx += 4;
+                       break;
+               case DMA_PACKET_NOP:
+                       p->idx += 1;
+                       break;
+               default:
+                       DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
+                       return -EINVAL;
+               }
+       } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw);
+#if 0
+       for (r = 0; r < p->ib->length_dw; r++) {
+               printk(KERN_INFO "%05d  0x%08X\n", r, p->ib.ptr[r]);
+               mdelay(1);
+       }
+#endif
+       return 0;
+}
index 1b9120a875efaf23f4b8ad86ad2aace00168a1e9..5dc744d43d128a537078153a5cf94803a4906101 100644 (file)
@@ -839,6 +839,7 @@ struct radeon_cs_parser {
        struct radeon_cs_reloc  *relocs;
        struct radeon_cs_reloc  **relocs_ptr;
        struct list_head        validated;
+       unsigned                dma_reloc_idx;
        /* indices of various chunks */
        int                     chunk_ib_idx;
        int                     chunk_relocs_idx;
@@ -1556,6 +1557,8 @@ struct radeon_device {
        /* Register mmio */
        resource_size_t                 rmmio_base;
        resource_size_t                 rmmio_size;
+       /* protects concurrent MM_INDEX/DATA based register access */
+       spinlock_t mmio_idx_lock;
        void __iomem                    *rmmio;
        radeon_rreg_t                   mc_rreg;
        radeon_wreg_t                   mc_wreg;
@@ -1631,8 +1634,10 @@ int radeon_device_init(struct radeon_device *rdev,
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg);
-void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
+uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg,
+                     bool always_indirect);
+void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v,
+                 bool always_indirect);
 u32 r100_io_rreg(struct radeon_device *rdev, u32 reg);
 void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 
@@ -1648,9 +1653,11 @@ void r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v);
 #define WREG8(reg, v) writeb(v, (rdev->rmmio) + (reg))
 #define RREG16(reg) readw((rdev->rmmio) + (reg))
 #define WREG16(reg, v) writew(v, (rdev->rmmio) + (reg))
-#define RREG32(reg) r100_mm_rreg(rdev, (reg))
-#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg)))
-#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v))
+#define RREG32(reg) r100_mm_rreg(rdev, (reg), false)
+#define RREG32_IDX(reg) r100_mm_rreg(rdev, (reg), true)
+#define DREG32(reg) printk(KERN_INFO "REGISTER: " #reg " : 0x%08X\n", r100_mm_rreg(rdev, (reg), false))
+#define WREG32(reg, v) r100_mm_wreg(rdev, (reg), (v), false)
+#define WREG32_IDX(reg, v) r100_mm_wreg(rdev, (reg), (v), true)
 #define REG_SET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
 #define REG_GET(FIELD, v) (((v) << FIELD##_SHIFT) & FIELD##_MASK)
 #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);
                tmp_ |= ((val) & ~(mask));                      \
                WREG32_PLL(reg, tmp_);                          \
        } while (0)
-#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg)))
+#define DREG32_SYS(sqf, rdev, reg) seq_printf((sqf), #reg " : 0x%08X\n", r100_mm_rreg((rdev), (reg), false))
 #define RREG32_IO(reg) r100_io_rreg(rdev, (reg))
 #define WREG32_IO(reg, v) r100_io_wreg(rdev, (reg), (v))
 
index 3ea0475f9a95f23fc41a8b2a2667ea86da63791d..596bcbe80ed06d5a8e50c271ded50d0a9003afaf 100644 (file)
@@ -952,7 +952,7 @@ static struct radeon_asic r600_asic = {
                        .ib_execute = &r600_dma_ring_ib_execute,
                        .emit_fence = &r600_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &r600_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &r600_dma_is_lockup,
@@ -1036,7 +1036,7 @@ static struct radeon_asic rs780_asic = {
                        .ib_execute = &r600_dma_ring_ib_execute,
                        .emit_fence = &r600_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &r600_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &r600_dma_is_lockup,
@@ -1120,7 +1120,7 @@ static struct radeon_asic rv770_asic = {
                        .ib_execute = &r600_dma_ring_ib_execute,
                        .emit_fence = &r600_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &r600_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &r600_dma_is_lockup,
@@ -1204,7 +1204,7 @@ static struct radeon_asic evergreen_asic = {
                        .ib_execute = &evergreen_dma_ring_ib_execute,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &r600_dma_is_lockup,
@@ -1288,7 +1288,7 @@ static struct radeon_asic sumo_asic = {
                        .ib_execute = &evergreen_dma_ring_ib_execute,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &r600_dma_is_lockup,
@@ -1372,7 +1372,7 @@ static struct radeon_asic btc_asic = {
                        .ib_execute = &evergreen_dma_ring_ib_execute,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &r600_dma_is_lockup,
@@ -1484,9 +1484,10 @@ static struct radeon_asic cayman_asic = {
                },
                [R600_RING_TYPE_DMA_INDEX] = {
                        .ib_execute = &cayman_dma_ring_ib_execute,
+                       .ib_parse = &evergreen_dma_ib_parse,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &cayman_dma_is_lockup,
@@ -1494,9 +1495,10 @@ static struct radeon_asic cayman_asic = {
                },
                [CAYMAN_RING_TYPE_DMA1_INDEX] = {
                        .ib_execute = &cayman_dma_ring_ib_execute,
+                       .ib_parse = &evergreen_dma_ib_parse,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &cayman_dma_is_lockup,
@@ -1609,9 +1611,10 @@ static struct radeon_asic trinity_asic = {
                },
                [R600_RING_TYPE_DMA_INDEX] = {
                        .ib_execute = &cayman_dma_ring_ib_execute,
+                       .ib_parse = &evergreen_dma_ib_parse,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &cayman_dma_is_lockup,
@@ -1619,9 +1622,10 @@ static struct radeon_asic trinity_asic = {
                },
                [CAYMAN_RING_TYPE_DMA1_INDEX] = {
                        .ib_execute = &cayman_dma_ring_ib_execute,
+                       .ib_parse = &evergreen_dma_ib_parse,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
-                       .cs_parse = NULL,
+                       .cs_parse = &evergreen_dma_cs_parse,
                        .ring_test = &r600_dma_ring_test,
                        .ib_test = &r600_dma_ib_test,
                        .is_lockup = &cayman_dma_is_lockup,
@@ -1734,6 +1738,7 @@ static struct radeon_asic si_asic = {
                },
                [R600_RING_TYPE_DMA_INDEX] = {
                        .ib_execute = &cayman_dma_ring_ib_execute,
+                       .ib_parse = &evergreen_dma_ib_parse,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
                        .cs_parse = NULL,
@@ -1744,6 +1749,7 @@ static struct radeon_asic si_asic = {
                },
                [CAYMAN_RING_TYPE_DMA1_INDEX] = {
                        .ib_execute = &cayman_dma_ring_ib_execute,
+                       .ib_parse = &evergreen_dma_ib_parse,
                        .emit_fence = &evergreen_dma_fence_ring_emit,
                        .emit_semaphore = &r600_dma_semaphore_ring_emit,
                        .cs_parse = NULL,
index c338931190a5d4c22a26ff4c4c24ce9d5ae2273b..5f4882cc2152eda52e3bf25bf3bd9573bf4e610a 100644 (file)
@@ -304,6 +304,7 @@ void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
 uint32_t r600_pciep_rreg(struct radeon_device *rdev, uint32_t reg);
 void r600_pciep_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 int r600_cs_parse(struct radeon_cs_parser *p);
+int r600_dma_cs_parse(struct radeon_cs_parser *p);
 void r600_fence_ring_emit(struct radeon_device *rdev,
                          struct radeon_fence *fence);
 void r600_semaphore_ring_emit(struct radeon_device *rdev,
@@ -430,6 +431,7 @@ u32 evergreen_get_vblank_counter(struct radeon_device *rdev, int crtc);
 int evergreen_irq_set(struct radeon_device *rdev);
 int evergreen_irq_process(struct radeon_device *rdev);
 extern int evergreen_cs_parse(struct radeon_cs_parser *p);
+extern int evergreen_dma_cs_parse(struct radeon_cs_parser *p);
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 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,
                        uint64_t addr, unsigned count,
                        uint32_t incr, uint32_t flags);
 int evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
+int evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib);
 void cayman_dma_ring_ib_execute(struct radeon_device *rdev,
                                struct radeon_ib *ib);
 bool cayman_dma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring);
index 45b660b27cfca6e163230f83b8fee0bf89956fca..4af89126e223c4fd2b8dc85c86ef377544b30ee9 100644 (file)
@@ -3246,11 +3246,9 @@ static uint32_t combios_detect_ram(struct drm_device *dev, int ram,
        while (ram--) {
                addr = ram * 1024 * 1024;
                /* write to each page */
-               WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER);
-               WREG32(RADEON_MM_DATA, 0xdeadbeef);
+               WREG32_IDX((addr) | RADEON_MM_APER, 0xdeadbeef);
                /* read back and verify */
-               WREG32(RADEON_MM_INDEX, (addr) | RADEON_MM_APER);
-               if (RREG32(RADEON_MM_DATA) != 0xdeadbeef)
+               if (RREG32_IDX((addr) | RADEON_MM_APER) != 0xdeadbeef)
                        return 0;
        }
 
index 8b2797dc7b6408833170a655d9e608204b929af1..9143fc45e35b2cef5f5185ce7cbb01efa9d63d56 100644 (file)
@@ -116,20 +116,6 @@ u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index)
        }
 }
 
-u32 RADEON_READ_MM(drm_radeon_private_t *dev_priv, int addr)
-{
-       u32 ret;
-
-       if (addr < 0x10000)
-               ret = DRM_READ32(dev_priv->mmio, addr);
-       else {
-               DRM_WRITE32(dev_priv->mmio, RADEON_MM_INDEX, addr);
-               ret = DRM_READ32(dev_priv->mmio, RADEON_MM_DATA);
-       }
-
-       return ret;
-}
-
 static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
 {
        u32 ret;
index 41672cc563fb13005bc732d581844d9811473047..396baba0141a9c2abefbd5e8782a83e5634c4c96 100644 (file)
@@ -43,6 +43,7 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
                return 0;
        }
        chunk = &p->chunks[p->chunk_relocs_idx];
+       p->dma_reloc_idx = 0;
        /* FIXME: we assume that each relocs use 4 dwords */
        p->nrelocs = chunk->length_dw / 4;
        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
                } else
                        p->ring = RADEON_RING_TYPE_GFX_INDEX;
                break;
+       case RADEON_CS_RING_DMA:
+               if (p->rdev->family >= CHIP_CAYMAN) {
+                       if (p->priority > 0)
+                               p->ring = R600_RING_TYPE_DMA_INDEX;
+                       else
+                               p->ring = CAYMAN_RING_TYPE_DMA1_INDEX;
+               } else if (p->rdev->family >= CHIP_R600) {
+                       p->ring = R600_RING_TYPE_DMA_INDEX;
+               } else {
+                       return -EINVAL;
+               }
+               break;
        }
        return 0;
 }
index 0fe56c9f64bd006788af30a3543efacf32ccf84c..ad6df625e8b8a1cf869ac06bb898503022406a6b 100644 (file)
@@ -66,24 +66,25 @@ static void radeon_hide_cursor(struct drm_crtc *crtc)
        struct radeon_device *rdev = crtc->dev->dev_private;
 
        if (ASIC_IS_DCE4(rdev)) {
-               WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset);
-               WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
-                      EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
+               WREG32_IDX(EVERGREEN_CUR_CONTROL + radeon_crtc->crtc_offset,
+                          EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT) |
+                          EVERGREEN_CURSOR_URGENT_CONTROL(EVERGREEN_CURSOR_URGENT_1_2));
        } else if (ASIC_IS_AVIVO(rdev)) {
-               WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset);
-               WREG32(RADEON_MM_DATA, (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
+               WREG32_IDX(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset,
+                          (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT));
        } else {
+               u32 reg;
                switch (radeon_crtc->crtc_id) {
                case 0:
-                       WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL);
+                       reg = RADEON_CRTC_GEN_CNTL;
                        break;
                case 1:
-                       WREG32(RADEON_MM_INDEX, RADEON_CRTC2_GEN_CNTL);
+                       reg = RADEON_CRTC2_GEN_CNTL;
                        break;
                default:
                        return;
                }
-               WREG32_P(RADEON_MM_DATA, 0, ~RADEON_CRTC_CUR_EN);
+               WREG32_IDX(reg, RREG32_IDX(reg) & ~RADEON_CRTC_CUR_EN);
        }
 }
 
index e2f5f888c374cc29b2f8658a5e0ba9d91325827d..49b06590001e1a30ca65761cfab2e20d901bc215 100644 (file)
@@ -1059,6 +1059,7 @@ int radeon_device_init(struct radeon_device *rdev,
 
        /* Registers mapping */
        /* TODO: block userspace mapping of io register */
+       spin_lock_init(&rdev->mmio_idx_lock);
        rdev->rmmio_base = pci_resource_start(rdev->pdev, 2);
        rdev->rmmio_size = pci_resource_len(rdev->pdev, 2);
        rdev->rmmio = ioremap(rdev->rmmio_base, rdev->rmmio_size);
index bfa2a6015727284c485d97cceeab1c18a2d7f64c..310c0e5254babc770ec620b9f1735390ffb8ce78 100644 (file)
@@ -378,8 +378,12 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
        work->old_rbo = rbo;
        obj = new_radeon_fb->obj;
        rbo = gem_to_radeon_bo(obj);
+
+       spin_lock(&rbo->tbo.bdev->fence_lock);
        if (rbo->tbo.sync_obj)
                work->fence = radeon_fence_ref(rbo->tbo.sync_obj);
+       spin_unlock(&rbo->tbo.bdev->fence_lock);
+
        INIT_WORK(&work->work, radeon_unpin_work_func);
 
        /* We borrow the event spin lock for protecting unpin_work */
index 91b64278c4ff4d679c799019068681522e160b4c..9b1a727d3c9e450b926cae872735fd7c05d3456a 100644 (file)
  *   2.23.0 - allow STRMOUT_BASE_UPDATE on RS780 and RS880
  *   2.24.0 - eg only: allow MIP_ADDRESS=0 for MSAA textures
  *   2.25.0 - eg+: new info request for num SE and num SH
+ *   2.26.0 - r600-eg: fix htile size computation
+ *   2.27.0 - r600-SI: Add CS ioctl support for async DMA
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       25
+#define KMS_DRIVER_MINOR       27
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index a1b59ca96d01ab7d774b6370656c5825b567131b..e7fdf163a8ca74939c3dee6797f64e7299a7cec4 100644 (file)
@@ -366,7 +366,6 @@ extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file
 extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv);
 extern void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc);
 extern void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base);
-extern u32 RADEON_READ_MM(drm_radeon_private_t *dev_priv, int addr);
 
 extern void radeon_freelist_reset(struct drm_device * dev);
 extern struct drm_buf *radeon_freelist_get(struct drm_device * dev);
index 93d3445477be11c45e730071c284feca9700fafa..883c95d8d90f4559b04b8a6e4ca319a896629681 100644 (file)
@@ -96,9 +96,9 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain)
        }
        if (domain & RADEON_GEM_DOMAIN_CPU) {
                if (rbo->rdev->flags & RADEON_IS_AGP) {
-                       rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
+                       rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_SYSTEM;
                } else {
-                       rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
+                       rbo->placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_SYSTEM;
                }
        }
        if (!c)
index 5645a878faec7c8df393276d237b7420b126eb79..eeda91774c8ac24f9dd95b0d2a45e61ab0da622a 100644 (file)
@@ -917,6 +917,7 @@ struct drm_radeon_gem_va {
 /* The second dword of RADEON_CHUNK_ID_FLAGS is a uint32 that sets the ring type */
 #define RADEON_CS_RING_GFX          0
 #define RADEON_CS_RING_COMPUTE      1
+#define RADEON_CS_RING_DMA          2
 /* The third dword of RADEON_CHUNK_ID_FLAGS is a sint32 that sets the priority */
 /* 0 = normal, + = higher priority, - = lower priority */