[PATCH 2/2] drm/i915: l3 parity sysfs interface

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dumb binary interfaces which allow root-only updates of our cache
remapping registers.  See intel-gpu-tools for how this can/should be
used.

Signed-off-by: Ben Widawsky <benjamin.widawsky at intel.com>
---
 drivers/gpu/drm/i915/i915_reg.h   |   10 ++++
 drivers/gpu/drm/i915/i915_sysfs.c |  103 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 111 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index de1685e..1a93395 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -4007,6 +4007,16 @@
 #define GEN7_PARITY_ERROR_SUBBANK(reg) \
 		((reg & GEN7_L3CDERRST1_SUBBANK_MASK) >> 8)
 
+#define GEN7_L3LOG_BASE				0xB070
+#define GEN7_L3LOG_SIZE				0x80
+#if 0
+#define   GEN7_L3LOG_ROW1(reg)         ((reg>>21) & IVYBRDIGE_L3_ROW_MASK)
+#define   GEN7_L3LOG_VLDERR1           (1<<16)
+#define   GEN7_L3LOG_ROW0(reg)         ((reg>>5) & IVYBRDIGE_L3_ROW_MASK)
+#define   GEN7_L3LOG_VLDERR0           (1<<0)
+#endif
+
+
 #define G4X_AUD_VID_DID			0x62020
 #define INTEL_AUDIO_DEVCL		0x808629FB
 #define INTEL_AUDIO_DEVBLC		0x80862801
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index f1b5108..fe37960 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -92,20 +92,119 @@ static struct attribute_group rc6_attr_group = {
 	.attrs =  rc6_attrs
 };
 
+static bool is_l3_access_valid(struct drm_device *dev, loff_t offset)
+{
+	if (!IS_IVYBRIDGE(dev))
+		return false;
+
+	if (offset >= GEN7_L3LOG_SIZE)
+		return false;
+
+	if (offset % 4 != 0)
+		return false;
+
+	return true;
+}
+
+static ssize_t
+i915_l3_read(struct file *filp, struct kobject *kobj,
+	     struct bin_attribute *attr, char *buf,
+	     loff_t offset, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+	struct drm_device *drm_dev = dminor->dev;
+	struct drm_i915_private *dev_priv = drm_dev->dev_private;
+	int i;
+
+	if (is_l3_access_valid(drm_dev, offset))
+		return 0;
+
+	if (i915_mutex_lock_interruptible(drm_dev))
+		return 0;
+
+	I915_WRITE(GEN7_MISCCPCTL,
+		   I915_READ(GEN7_MISCCPCTL) & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+	POSTING_READ(GEN7_MISCCPCTL);
+
+	for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4)
+		buf[i] = I915_READ(GEN7_L3LOG_BASE + i);
+
+	I915_WRITE(GEN7_MISCCPCTL,
+		   I915_READ(GEN7_MISCCPCTL) | GEN7_DOP_CLOCK_GATE_ENABLE);
+	POSTING_READ(GEN7_MISCCPCTL);
+
+	mutex_unlock(&drm_dev->struct_mutex);
+
+	return i - offset;
+}
+
+static ssize_t
+i915_l3_write(struct file *filp, struct kobject *kobj,
+	      struct bin_attribute *attr, char *buf,
+	      loff_t offset, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct drm_minor *dminor = container_of(dev, struct drm_minor, kdev);
+	struct drm_device *drm_dev = dminor->dev;
+	struct drm_i915_private *dev_priv = drm_dev->dev_private;
+	int i;
+
+	if (is_l3_access_valid(drm_dev, offset))
+		return 0;
+
+	if (i915_mutex_lock_interruptible(drm_dev))
+		return 0;
+
+	I915_WRITE(GEN7_MISCCPCTL,
+		   I915_READ(GEN7_MISCCPCTL) & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+	POSTING_READ(GEN7_MISCCPCTL);
+
+
+	for (i = offset; count >= 4 && i < GEN7_L3LOG_SIZE; i += 4, count -= 4) {
+		uint32_t data = *(uint32_t *)(&buf[i]);
+		I915_WRITE(GEN7_L3LOG_BASE + i, data);
+	}
+
+	I915_WRITE(GEN7_MISCCPCTL,
+		   I915_READ(GEN7_MISCCPCTL) | GEN7_DOP_CLOCK_GATE_ENABLE);
+	POSTING_READ(GEN7_MISCCPCTL);
+
+	mutex_unlock(&drm_dev->struct_mutex);
+
+	return 0;
+}
+
+static struct bin_attribute dpf_attrs = {
+	.attr = {.name = "l3_parity", .mode = (S_IRWXU)},
+	.size = GEN7_L3LOG_SIZE,
+	.read = i915_l3_read,
+	.write = i915_l3_write,
+	.mmap = NULL
+};
+
 void i915_setup_sysfs(struct drm_device *dev)
 {
 	int ret;
 
-	/* ILK doesn't have any residency information */
+	/* ILK and below don't yet have relevant sysfs files */
 	if (INTEL_INFO(dev)->gen < 6)
 		return;
 
 	ret = sysfs_merge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
 	if (ret)
-		DRM_ERROR("sysfs setup failed\n");
+		DRM_ERROR("RC6 residency sysfs setup failed\n");
+
+	if (!IS_IVYBRIDGE(dev))
+		return;
+
+	ret = device_create_bin_file(&dev->primary->kdev, &dpf_attrs);
+	if (ret)
+		DRM_ERROR("l3 parity sysfs setup failed\n");
 }
 
 void i915_teardown_sysfs(struct drm_device *dev)
 {
+	device_remove_bin_file(&dev->primary->kdev,  &dpf_attrs);
 	sysfs_unmerge_group(&dev->primary->kdev.kobj, &rc6_attr_group);
 }
-- 
1.7.10



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux