drm/radeon: add support for SET_APPEND_CNT packet3 (v2)
authorDave Airlie <airlied@redhat.com>
Wed, 6 Apr 2016 20:50:25 +0000 (06:50 +1000)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 5 May 2016 00:19:49 +0000 (20:19 -0400)
This adds support to the command parser for the set append counter
packet3, this is required to support atomic counters on
evergreen/cayman GPUs.

v2: fixup some of the hardcoded numbers with real register names
(Christian)

Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/radeon_drv.c

index 9e93205..18ddd75 100644 (file)
@@ -2608,6 +2608,51 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                        }
                }
                break;
+       case PACKET3_SET_APPEND_CNT:
+       {
+               uint32_t areg;
+               uint32_t allowed_reg_base;
+               uint32_t source_sel;
+               if (pkt->count != 2) {
+                       DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n");
+                       return -EINVAL;
+               }
+
+               allowed_reg_base = GDS_APPEND_COUNT_0;
+               allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START;
+               allowed_reg_base >>= 2;
+
+               areg = idx_value >> 16;
+               if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) {
+                       dev_warn(p->dev, "forbidden register for append cnt 0x%08x at %d\n",
+                                areg, idx);
+                       return -EINVAL;
+               }
+
+               source_sel = G_PACKET3_SET_APPEND_CNT_SRC_SELECT(idx_value);
+               if (source_sel == PACKET3_SAC_SRC_SEL_MEM) {
+                       uint64_t offset;
+                       uint32_t swap;
+                       r = radeon_cs_packet_next_reloc(p, &reloc, 0);
+                       if (r) {
+                               DRM_ERROR("bad SET_APPEND_CNT (missing reloc)\n");
+                               return -EINVAL;
+                       }
+                       offset = radeon_get_ib_value(p, idx + 1);
+                       swap = offset & 0x3;
+                       offset &= ~0x3;
+
+                       offset += ((u64)(radeon_get_ib_value(p, idx + 2) & 0xff)) << 32;
+
+                       offset += reloc->gpu_offset;
+                       ib[idx+1] = (offset & 0xfffffffc) | swap;
+                       ib[idx+2] = upper_32_bits(offset) & 0xff;
+               } else {
+                       DRM_ERROR("bad SET_APPEND_CNT (unsupported operation)\n");
+                       return -EINVAL;
+               }
+               break;
+       }
        case PACKET3_NOP:
                break;
        default:
index 13b6029..0b174e1 100644 (file)
 #define        PACKET3_SET_CONTEXT_REG_INDIRECT                0x73
 #define        PACKET3_SET_RESOURCE_INDIRECT                   0x74
 #define        PACKET3_SET_APPEND_CNT                          0x75
+/* SET_APPEND_CNT - documentation
+ * 1. header
+ * 2. COMMAND
+ *  1:0 - SOURCE SEL
+ *  15:2 - Reserved
+ *  31:16 - WR_REG_OFFSET - context register to write source data to.
+ *          (one of R_02872C_GDS_APPEND_COUNT_0-11)
+ * 3. CONTROL
+ *  (for source == mem)
+ *  31:2 SRC_ADDRESS_LO
+ *  0:1 SWAP
+ *  (for source == GDS)
+ *  31:0 GDS offset
+ *  (for source == DATA)
+ *  31:0 DATA
+ *  (for source == REG)
+ *  31:0 REG
+ * 4. SRC_ADDRESS_HI[7:0]
+ * kernel driver 2.44 only supports SRC == MEM.
+ */
+#define PACKET3_SET_APPEND_CNT_SRC_SELECT(x) ((x) << 0)
+#define G_PACKET3_SET_APPEND_CNT_SRC_SELECT(x) ((x & 0x3) >> 0)
+/* source is from the data in CONTROL */
+#define PACKET3_SAC_SRC_SEL_DATA 0x0
+/* source is from register */
+#define PACKET3_SAC_SRC_SEL_REG  0x1
+/* source is from GDS offset in CONTROL */
+#define PACKET3_SAC_SRC_SEL_GDS  0x2
+/* source is from memory address */
+#define PACKET3_SAC_SRC_SEL_MEM  0x3
 
 #define        SQ_RESOURCE_CONSTANT_WORD7_0                            0x3001c
 #define                S__SQ_CONSTANT_TYPE(x)                  (((x) & 3) << 30)
 
 #define GDS_ADDR_BASE                                  0x28720
 
+#define GDS_APPEND_COUNT_0                             0x2872C
+#define GDS_APPEND_COUNT_1                             0x28730
+#define GDS_APPEND_COUNT_2                             0x28734
+#define GDS_APPEND_COUNT_3                             0x28738
+#define GDS_APPEND_COUNT_4                             0x2873C
+#define GDS_APPEND_COUNT_5                             0x28740
+#define GDS_APPEND_COUNT_6                             0x28744
+#define GDS_APPEND_COUNT_7                             0x28748
+#define GDS_APPEND_COUNT_8                             0x2874c
+#define GDS_APPEND_COUNT_9                             0x28750
+#define GDS_APPEND_COUNT_10                            0x28754
+#define GDS_APPEND_COUNT_11                            0x28758
+
 #define        CB_IMMED0_BASE                                  0x28b9c
 #define        CB_IMMED1_BASE                                  0x28ba0
 #define        CB_IMMED2_BASE                                  0x28ba4
index d2a925e..1ff77ce 100644 (file)
  *   2.41.0 - evergreen/cayman: Add SET_BASE/DRAW_INDIRECT command parsing support
  *   2.42.0 - Add VCE/VUI (Video Usability Information) support
  *   2.43.0 - RADEON_INFO_GPU_RESET_COUNTER
+ *   2.44.0 - SET_APPEND_CNT packet3 support
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       43
+#define KMS_DRIVER_MINOR       44
 #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);