msm: kgsl: Add sysfs node to control legacy snapshot

Sometimes the crashdumper fails and we fall back to the legacy
path, which means we fall back to reading the registers through
host cpu. This leads to access violation because some register offset
might be protected in the TZ. To avoid this, set the default
behaviour to never do the legacy path in snapshot for register
offsets that are protected in the TZ. Enable the legacy path through
following sysfs node if and when needed.

/sys/class/kgsl/kgsl-3d0/snapshot/snapshot_legacy

Change-Id: I7475042ac1271605d32c486fa0b86fd0bacb1046
Signed-off-by: Harshdeep Dhatt <hdhatt@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 63dbde0..17ee6e6 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -640,6 +640,9 @@
 	unsigned int *data = (unsigned int *)(buf + sizeof(*header));
 	int i, j;
 
+	if (!device->snapshot_legacy)
+		return 0;
+
 	if (remain < sizeof(*header)) {
 		SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
 		return 0;
@@ -748,6 +751,9 @@
 	unsigned int read_sel;
 	int i, j;
 
+	if (!device->snapshot_legacy)
+		return 0;
+
 	/* Figure out how many registers we are going to dump */
 	for (i = 0; i < regs->num_sets; i++) {
 		int start = regs->regs[i * 2];
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 876b668..be379e3 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -291,6 +291,8 @@
 
 	/* Use CP Crash dumper to get GPU snapshot*/
 	bool snapshot_crashdumper;
+	/* Use HOST side register reads to get GPU snapshot*/
+	bool snapshot_legacy;
 
 	struct kobject snapshot_kobj;
 
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 40d239c..7cbda72 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -875,6 +875,25 @@
 	return snprintf(buf, PAGE_SIZE, "%lu\n", timestamp);
 }
 
+static ssize_t snapshot_legacy_show(struct kgsl_device *device, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_legacy);
+}
+
+static ssize_t snapshot_legacy_store(struct kgsl_device *device,
+	const char *buf, size_t count)
+{
+	unsigned int val = 0;
+	int ret;
+
+	ret = kgsl_sysfs_store(buf, &val);
+
+	if (!ret && device)
+		device->snapshot_legacy = (bool)val;
+
+	return (ssize_t) ret < 0 ? ret : count;
+}
+
 static struct bin_attribute snapshot_attr = {
 	.attr.name = "dump",
 	.attr.mode = 0444,
@@ -894,6 +913,8 @@
 static SNAPSHOT_ATTR(force_panic, 0644, force_panic_show, force_panic_store);
 static SNAPSHOT_ATTR(snapshot_crashdumper, 0644, snapshot_crashdumper_show,
 	snapshot_crashdumper_store);
+static SNAPSHOT_ATTR(snapshot_legacy, 0644, snapshot_legacy_show,
+	snapshot_legacy_store);
 
 static ssize_t snapshot_sysfs_show(struct kobject *kobj,
 	struct attribute *attr, char *buf)
@@ -975,6 +996,7 @@
 	device->snapshot_faultcount = 0;
 	device->force_panic = 0;
 	device->snapshot_crashdumper = 1;
+	device->snapshot_legacy = 0;
 
 	ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
 		&device->dev->kobj, "snapshot");
@@ -1000,6 +1022,12 @@
 
 	ret  = sysfs_create_file(&device->snapshot_kobj,
 			&attr_snapshot_crashdumper.attr);
+	if (ret)
+		goto done;
+
+	ret  = sysfs_create_file(&device->snapshot_kobj,
+			&attr_snapshot_legacy.attr);
+
 done:
 	return ret;
 }