diff options
author | Minchan Kim <minchan@google.com> | 2022-01-24 22:19:47 -0800 |
---|---|---|
committer | Will McVicker <willmcvicker@google.com> | 2022-05-20 15:04:40 -0700 |
commit | e2e4d3226d155e0bbbeb7b74d63491efcfa264e2 (patch) | |
tree | 60869e4291dbefa5985f719b3ce9573c93d68da3 | |
parent | a5932e5ab949cd9159233db4e8d529987a95403a (diff) | |
download | raviole-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.h | 3 | ||||
-rw-r--r-- | drivers/soc/google/eh/eh_main.c | 52 |
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; } |