summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinchan Kim <minchan@google.com>2022-01-24 22:19:47 -0800
committerWill McVicker <willmcvicker@google.com>2022-05-20 15:04:40 -0700
commite2e4d3226d155e0bbbeb7b74d63491efcfa264e2 (patch)
tree60869e4291dbefa5985f719b3ce9573c93d68da3
parenta5932e5ab949cd9159233db4e8d529987a95403a (diff)
downloadraviole-device-e2e4d3226d155e0bbbeb7b74d63491efcfa264e2.tar.gz
eh: introduce eh sysfs and add nr_stall
With stall information, we could know how often the reclaimer got stuck on EH. We could get the metric from telemetry in future. cat /sys/kernel/eh/nr_stall Bug: 215573980 Signed-off-by: Minchan Kim <minchan@google.com> Change-Id: Ic354eeaac2de225c1e48ff91755ce00a2a67c9ae (cherry picked from commit b4f6a0bfa02b67c585b02b65c7c17f8ad8b2190c) Signed-off-by: Will McVicker <willmcvicker@google.com>
-rw-r--r--drivers/soc/google/eh/eh_internal.h3
-rw-r--r--drivers/soc/google/eh/eh_main.c52
2 files changed, 43 insertions, 12 deletions
diff --git a/drivers/soc/google/eh/eh_internal.h b/drivers/soc/google/eh/eh_internal.h
index f7dea1351..890c625e0 100644
--- a/drivers/soc/google/eh/eh_internal.h
+++ b/drivers/soc/google/eh/eh_internal.h
@@ -12,6 +12,7 @@
#include "eh_regs.h"
#include <linux/spinlock_types.h>
#include <linux/wait.h>
+#include <linux/kobject.h>
struct eh_completion {
void *priv;
@@ -40,6 +41,7 @@ struct eh_sw_fifo {
};
struct eh_device {
+ struct kobject kobj;
struct list_head eh_dev_list;
/* hardware characteristics */
@@ -109,5 +111,6 @@ struct eh_device {
struct eh_request_pool pool;
/* keep pending request */
struct eh_sw_fifo sw_fifo;
+ atomic64_t nr_stall;
};
#endif
diff --git a/drivers/soc/google/eh/eh_main.c b/drivers/soc/google/eh/eh_main.c
index 4b7c96a65..5ec50ba93 100644
--- a/drivers/soc/google/eh/eh_main.c
+++ b/drivers/soc/google/eh/eh_main.c
@@ -393,12 +393,14 @@ static void init_compression_descriptor(struct eh_device *eh_dev)
/*
* - Primitive functions for Emerald Hill SW
*/
-static long eh_congestion_wait(long timeout)
+static long eh_congestion_wait(struct eh_device *eh_dev, unsigned long timeout)
{
long ret;
DEFINE_WAIT(wait);
wait_queue_head_t *wqh = &eh_compress_wait;
+ atomic64_inc(&eh_dev->nr_stall);
+
prepare_to_wait(wqh, &wait, TASK_UNINTERRUPTIBLE);
ret = io_schedule_timeout(timeout);
finish_wait(wqh, &wait);
@@ -419,7 +421,7 @@ static void request_to_sw_fifo(struct eh_device *eh_dev,
struct eh_sw_fifo *fifo = &eh_dev->sw_fifo;
while ((req = pool_alloc(&eh_dev->pool)) == NULL)
- eh_congestion_wait(HZ/10);
+ eh_congestion_wait(eh_dev, HZ/10);
req->page = page;
req->priv = priv;
@@ -961,12 +963,39 @@ iounmap:
return ret;
}
-static void eh_deinit(struct eh_device *eh_dev)
+#define EH_ATTR_RO(_name) \
+ static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+
+static ssize_t nr_stall_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
{
- eh_hw_deinit(eh_dev);
+ struct eh_device *eh_dev = container_of(kobj, struct eh_device, kobj);
+
+ return sysfs_emit(buf, "%lu\n", atomic64_read(&eh_dev->nr_stall));
+}
+EH_ATTR_RO(nr_stall);
+
+static struct attribute *eh_attrs[] = {
+ &nr_stall_attr.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(eh);
+
+static void eh_kobj_release(struct kobject *kobj)
+{
+ struct eh_device *eh_dev = container_of(kobj, struct eh_device, kobj);
+
eh_sw_deinit(eh_dev);
+ eh_hw_deinit(eh_dev);
+ kfree(eh_dev);
}
+static struct kobj_type eh_ktype = {
+ .release = eh_kobj_release,
+ .sysfs_ops = &kobj_sysfs_ops,
+ .default_groups = eh_groups,
+};
+
/* EmeraldHill initialization entry */
static int eh_init(struct device *device, struct eh_device *eh_dev,
unsigned short fifo_size, phys_addr_t regs, int error_irq,
@@ -991,7 +1020,12 @@ static int eh_init(struct device *device, struct eh_device *eh_dev,
return ret;
}
- return 0;
+ ret = kobject_init_and_add(&eh_dev->kobj, &eh_ktype,
+ kernel_kobj, "%s", "eh");
+ if (ret)
+ kobject_put(&eh_dev->kobj);
+
+ return ret;
}
static void eh_setup_dcmd(struct eh_device *eh_dev, unsigned int index,
@@ -1226,12 +1260,6 @@ disable_pm_runtime:
return ret;
}
-void eh_remove(struct eh_device *eh_dev)
-{
- eh_deinit(eh_dev);
- kfree(eh_dev);
-}
-
static int eh_of_remove(struct platform_device *pdev)
{
struct eh_device *eh_dev = platform_get_drvdata(pdev);
@@ -1241,7 +1269,7 @@ static int eh_of_remove(struct platform_device *pdev)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- eh_remove(eh_dev);
+ kobject_put(&eh_dev->kobj);
return 0;
}