* Re: [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs [not found] ` <20200415101138.26126-2-tvrtko.ursulin@linux.intel.com> @ 2020-08-26 1:11 ` Lucas De Marchi 2020-09-01 15:09 ` Tvrtko Ursulin 0 siblings, 1 reply; 7+ messages in thread From: Lucas De Marchi @ 2020-08-26 1:11 UTC (permalink / raw) To: Tvrtko Ursulin; +Cc: Intel Graphics, Chris Wilson Hi, Any update on this? It now conflicts in a few places so it needs a rebase. Lucas De Marchi On Wed, Apr 15, 2020 at 3:11 AM Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> wrote: > > From: Tvrtko Ursulin <tvrtko.ursulin@intel.com> > > Expose a list of clients with open file handles in sysfs. > > This will be a basis for a top-like utility showing per-client and per- > engine GPU load. > > Currently we only expose each client's pid and name under opaque numbered > directories in /sys/class/drm/card0/clients/. > > For instance: > > /sys/class/drm/card0/clients/3/name: Xorg > /sys/class/drm/card0/clients/3/pid: 5664 > > v2: > Chris Wilson: > * Enclose new members into dedicated structs. > * Protect against failed sysfs registration. > > v3: > * sysfs_attr_init. > > v4: > * Fix for internal clients. > > v5: > * Use cyclic ida for client id. (Chris) > * Do not leak pid reference. (Chris) > * Tidy code with some locals. > > v6: > * Use xa_alloc_cyclic to simplify locking. (Chris) > * No need to unregister individial sysfs files. (Chris) > * Rebase on top of fpriv kref. > * Track client closed status and reflect in sysfs. > > v7: > * Make drm_client more standalone concept. > > v8: > * Simplify sysfs show. (Chris) > * Always track name and pid. > > v9: > * Fix cyclic id assignment. > > v10: > * No need for a mutex around xa_alloc_cyclic. > * Refactor sysfs into own function. > * Unregister sysfs before freeing pid and name. > * Move clients setup into own function. > > v11: > * Call clients init directly from driver init. (Chris) > > Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> > Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> > --- > drivers/gpu/drm/i915/Makefile | 3 +- > drivers/gpu/drm/i915/i915_drm_client.c | 179 +++++++++++++++++++++++++ > drivers/gpu/drm/i915/i915_drm_client.h | 64 +++++++++ > drivers/gpu/drm/i915/i915_drv.c | 3 + > drivers/gpu/drm/i915/i915_drv.h | 5 + > drivers/gpu/drm/i915/i915_gem.c | 25 +++- > drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ > 7 files changed, 283 insertions(+), 4 deletions(-) > create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c > create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h > > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index 44c506b7e117..b30f3d51c66a 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -33,7 +33,8 @@ subdir-ccflags-y += -I$(srctree)/$(src) > # Please keep these build lists sorted! > > # core driver code > -i915-y += i915_drv.o \ > +i915-y += i915_drm_client.o \ > + i915_drv.o \ > i915_irq.o \ > i915_getparam.o \ > i915_params.o \ > diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c > new file mode 100644 > index 000000000000..2067fbcdb795 > --- /dev/null > +++ b/drivers/gpu/drm/i915/i915_drm_client.c > @@ -0,0 +1,179 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2020 Intel Corporation > + */ > + > +#include <linux/kernel.h> > +#include <linux/slab.h> > +#include <linux/types.h> > + > +#include "i915_drm_client.h" > +#include "i915_gem.h" > +#include "i915_utils.h" > + > +void i915_drm_clients_init(struct i915_drm_clients *clients) > +{ > + clients->next_id = 0; > + xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC); > +} > + > +static ssize_t > +show_client_name(struct device *kdev, struct device_attribute *attr, char *buf) > +{ > + struct i915_drm_client *client = > + container_of(attr, typeof(*client), attr.name); > + > + return snprintf(buf, PAGE_SIZE, > + READ_ONCE(client->closed) ? "<%s>" : "%s", > + client->name); > +} > + > +static ssize_t > +show_client_pid(struct device *kdev, struct device_attribute *attr, char *buf) > +{ > + struct i915_drm_client *client = > + container_of(attr, typeof(*client), attr.pid); > + > + return snprintf(buf, PAGE_SIZE, > + READ_ONCE(client->closed) ? "<%u>" : "%u", > + pid_nr(client->pid)); > +} > + > +static int > +__client_register_sysfs(struct i915_drm_client *client) > +{ > + const struct { > + const char *name; > + struct device_attribute *attr; > + ssize_t (*show)(struct device *dev, > + struct device_attribute *attr, > + char *buf); > + } files[] = { > + { "name", &client->attr.name, show_client_name }, > + { "pid", &client->attr.pid, show_client_pid }, > + }; > + unsigned int i; > + char buf[16]; > + int ret; > + > + ret = scnprintf(buf, sizeof(buf), "%u", client->id); > + if (ret == sizeof(buf)) > + return -EINVAL; > + > + client->root = kobject_create_and_add(buf, client->clients->root); > + if (!client->root) > + return -ENOMEM; > + > + for (i = 0; i < ARRAY_SIZE(files); i++) { > + struct device_attribute *attr = files[i].attr; > + > + sysfs_attr_init(&attr->attr); > + > + attr->attr.name = files[i].name; > + attr->attr.mode = 0444; > + attr->show = files[i].show; > + > + ret = sysfs_create_file(client->root, (struct attribute *)attr); > + if (ret) > + break; > + } > + > + if (ret) > + kobject_put(client->root); > + > + return ret; > +} > + > +static void __client_unregister_sysfs(struct i915_drm_client *client) > +{ > + kobject_put(fetch_and_zero(&client->root)); > +} > + > +static int > +__i915_drm_client_register(struct i915_drm_client *client, > + struct task_struct *task) > +{ > + struct i915_drm_clients *clients = client->clients; > + char *name; > + int ret; > + > + name = kstrdup(task->comm, GFP_KERNEL); > + if (!name) > + return -ENOMEM; > + > + client->pid = get_task_pid(task, PIDTYPE_PID); > + client->name = name; > + > + if (!clients->root) > + return 0; /* intel_fbdev_init registers a client before sysfs */ > + > + ret = __client_register_sysfs(client); > + if (ret) > + goto err_sysfs; > + > + return 0; > + > +err_sysfs: > + put_pid(client->pid); > + kfree(client->name); > + > + return ret; > +} > + > +static void > +__i915_drm_client_unregister(struct i915_drm_client *client) > +{ > + __client_unregister_sysfs(client); > + > + put_pid(fetch_and_zero(&client->pid)); > + kfree(fetch_and_zero(&client->name)); > +} > + > +struct i915_drm_client * > +i915_drm_client_add(struct i915_drm_clients *clients, struct task_struct *task) > +{ > + struct i915_drm_client *client; > + int ret; > + > + client = kzalloc(sizeof(*client), GFP_KERNEL); > + if (!client) > + return ERR_PTR(-ENOMEM); > + > + kref_init(&client->kref); > + client->clients = clients; > + > + ret = xa_alloc_cyclic(&clients->xarray, &client->id, client, > + xa_limit_32b, &clients->next_id, GFP_KERNEL); > + if (ret) > + goto err_id; > + > + ret = __i915_drm_client_register(client, task); > + if (ret) > + goto err_register; > + > + return client; > + > +err_register: > + xa_erase(&clients->xarray, client->id); > +err_id: > + kfree(client); > + > + return ERR_PTR(ret); > +} > + > +void __i915_drm_client_free(struct kref *kref) > +{ > + struct i915_drm_client *client = > + container_of(kref, typeof(*client), kref); > + > + __i915_drm_client_unregister(client); > + xa_erase(&client->clients->xarray, client->id); > + kfree_rcu(client, rcu); > +} > + > +void i915_drm_client_close(struct i915_drm_client *client) > +{ > + GEM_BUG_ON(READ_ONCE(client->closed)); > + WRITE_ONCE(client->closed, true); > + i915_drm_client_put(client); > +} > diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h > new file mode 100644 > index 000000000000..af6998c74d4c > --- /dev/null > +++ b/drivers/gpu/drm/i915/i915_drm_client.h > @@ -0,0 +1,64 @@ > +// SPDX-License-Identifier: MIT > +/* > + * Copyright © 2020 Intel Corporation > + */ > + > +#ifndef __I915_DRM_CLIENT_H__ > +#define __I915_DRM_CLIENT_H__ > + > +#include <linux/device.h> > +#include <linux/kobject.h> > +#include <linux/kref.h> > +#include <linux/pid.h> > +#include <linux/rcupdate.h> > +#include <linux/sched.h> > +#include <linux/xarray.h> > + > +struct i915_drm_clients { > + struct xarray xarray; > + u32 next_id; > + > + struct kobject *root; > +}; > + > +struct i915_drm_client { > + struct kref kref; > + > + struct rcu_head rcu; > + > + unsigned int id; > + struct pid *pid; > + char *name; > + bool closed; > + > + struct i915_drm_clients *clients; > + > + struct kobject *root; > + struct { > + struct device_attribute pid; > + struct device_attribute name; > + } attr; > +}; > + > +void i915_drm_clients_init(struct i915_drm_clients *clients); > + > +static inline struct i915_drm_client * > +i915_drm_client_get(struct i915_drm_client *client) > +{ > + kref_get(&client->kref); > + return client; > +} > + > +void __i915_drm_client_free(struct kref *kref); > + > +static inline void i915_drm_client_put(struct i915_drm_client *client) > +{ > + kref_put(&client->kref, __i915_drm_client_free); > +} > + > +void i915_drm_client_close(struct i915_drm_client *client); > + > +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients, > + struct task_struct *task); > + > +#endif /* !__I915_DRM_CLIENT_H__ */ > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c > index 641f5e03b661..dac84b17d23d 100644 > --- a/drivers/gpu/drm/i915/i915_drv.c > +++ b/drivers/gpu/drm/i915/i915_drv.c > @@ -70,6 +70,7 @@ > #include "gt/intel_rc6.h" > > #include "i915_debugfs.h" > +#include "i915_drm_client.h" > #include "i915_drv.h" > #include "i915_ioc32.h" > #include "i915_irq.h" > @@ -456,6 +457,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) > > i915_gem_init_early(dev_priv); > > + i915_drm_clients_init(&dev_priv->clients); > + > /* This must be called before any calls to HAS_PCH_* */ > intel_detect_pch(dev_priv); > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index e9ee4daa9320..f9f0c3ba6e4a 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -91,6 +91,7 @@ > #include "intel_wakeref.h" > #include "intel_wopcm.h" > > +#include "i915_drm_client.h" > #include "i915_gem.h" > #include "i915_gem_gtt.h" > #include "i915_gpu_error.h" > @@ -226,6 +227,8 @@ struct drm_i915_file_private { > /** ban_score: Accumulated score of all ctx bans and fast hangs. */ > atomic_t ban_score; > unsigned long hang_timestamp; > + > + struct i915_drm_client *client; > }; > > /* Interface history: > @@ -1201,6 +1204,8 @@ struct drm_i915_private { > > struct i915_pmu pmu; > > + struct i915_drm_clients clients; > + > struct i915_hdcp_comp_master *hdcp_master; > bool hdcp_comp_added; > > diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c > index 0cbcb9f54e7d..5a0b5fae8b92 100644 > --- a/drivers/gpu/drm/i915/i915_gem.c > +++ b/drivers/gpu/drm/i915/i915_gem.c > @@ -1234,6 +1234,8 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv) > GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); > GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); > drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count); > + drm_WARN_ON(&dev_priv->drm, !xa_empty(&dev_priv->clients.xarray)); > + xa_destroy(&dev_priv->clients.xarray); > } > > int i915_gem_freeze(struct drm_i915_private *dev_priv) > @@ -1288,6 +1290,8 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) > struct drm_i915_file_private *file_priv = file->driver_priv; > struct i915_request *request; > > + i915_drm_client_close(file_priv->client); > + > /* Clean up our request list when the client is going away, so that > * later retire_requests won't dereference our soon-to-be-gone > * file_priv. > @@ -1301,17 +1305,25 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) > int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) > { > struct drm_i915_file_private *file_priv; > - int ret; > + struct i915_drm_client *client; > + int ret = -ENOMEM; > > DRM_DEBUG("\n"); > > file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); > if (!file_priv) > - return -ENOMEM; > + goto err_alloc; > + > + client = i915_drm_client_add(&i915->clients, current); > + if (IS_ERR(client)) { > + ret = PTR_ERR(client); > + goto err_client; > + } > > file->driver_priv = file_priv; > file_priv->dev_priv = i915; > file_priv->file = file; > + file_priv->client = client; > > spin_lock_init(&file_priv->mm.lock); > INIT_LIST_HEAD(&file_priv->mm.request_list); > @@ -1321,8 +1333,15 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) > > ret = i915_gem_context_open(i915, file); > if (ret) > - kfree(file_priv); > + goto err_context; > + > + return 0; > > +err_context: > + i915_drm_client_close(client); > +err_client: > + kfree(file_priv); > +err_alloc: > return ret; > } > > diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c > index 45d32ef42787..b7d4a6d2dd5c 100644 > --- a/drivers/gpu/drm/i915/i915_sysfs.c > +++ b/drivers/gpu/drm/i915/i915_sysfs.c > @@ -560,6 +560,11 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) > struct device *kdev = dev_priv->drm.primary->kdev; > int ret; > > + dev_priv->clients.root = > + kobject_create_and_add("clients", &kdev->kobj); > + if (!dev_priv->clients.root) > + DRM_ERROR("Per-client sysfs setup failed\n"); > + > #ifdef CONFIG_PM > if (HAS_RC6(dev_priv)) { > ret = sysfs_merge_group(&kdev->kobj, > @@ -627,4 +632,7 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) > sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); > sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); > #endif > + > + if (dev_priv->clients.root) > + kobject_put(dev_priv->clients.root); > } > -- > 2.20.1 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs 2020-08-26 1:11 ` [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs Lucas De Marchi @ 2020-09-01 15:09 ` Tvrtko Ursulin 2020-09-01 15:25 ` Tvrtko Ursulin 0 siblings, 1 reply; 7+ messages in thread From: Tvrtko Ursulin @ 2020-09-01 15:09 UTC (permalink / raw) To: Lucas De Marchi; +Cc: Intel Graphics, Chris Wilson Hi, On 26/08/2020 02:11, Lucas De Marchi wrote: > Hi, > > Any update on this? It now conflicts in a few places so it needs a rebase. I don't see any previous email on the topic - what kind of update, where and how, are you looking for? Rebase against drm-tip so you pull it in? Rebase against some internal in progress branch? Regards, Tvrtko > Lucas De Marchi > > On Wed, Apr 15, 2020 at 3:11 AM Tvrtko Ursulin > <tvrtko.ursulin@linux.intel.com> wrote: >> >> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com> >> >> Expose a list of clients with open file handles in sysfs. >> >> This will be a basis for a top-like utility showing per-client and per- >> engine GPU load. >> >> Currently we only expose each client's pid and name under opaque numbered >> directories in /sys/class/drm/card0/clients/. >> >> For instance: >> >> /sys/class/drm/card0/clients/3/name: Xorg >> /sys/class/drm/card0/clients/3/pid: 5664 >> >> v2: >> Chris Wilson: >> * Enclose new members into dedicated structs. >> * Protect against failed sysfs registration. >> >> v3: >> * sysfs_attr_init. >> >> v4: >> * Fix for internal clients. >> >> v5: >> * Use cyclic ida for client id. (Chris) >> * Do not leak pid reference. (Chris) >> * Tidy code with some locals. >> >> v6: >> * Use xa_alloc_cyclic to simplify locking. (Chris) >> * No need to unregister individial sysfs files. (Chris) >> * Rebase on top of fpriv kref. >> * Track client closed status and reflect in sysfs. >> >> v7: >> * Make drm_client more standalone concept. >> >> v8: >> * Simplify sysfs show. (Chris) >> * Always track name and pid. >> >> v9: >> * Fix cyclic id assignment. >> >> v10: >> * No need for a mutex around xa_alloc_cyclic. >> * Refactor sysfs into own function. >> * Unregister sysfs before freeing pid and name. >> * Move clients setup into own function. >> >> v11: >> * Call clients init directly from driver init. (Chris) >> >> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> >> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> >> --- >> drivers/gpu/drm/i915/Makefile | 3 +- >> drivers/gpu/drm/i915/i915_drm_client.c | 179 +++++++++++++++++++++++++ >> drivers/gpu/drm/i915/i915_drm_client.h | 64 +++++++++ >> drivers/gpu/drm/i915/i915_drv.c | 3 + >> drivers/gpu/drm/i915/i915_drv.h | 5 + >> drivers/gpu/drm/i915/i915_gem.c | 25 +++- >> drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ >> 7 files changed, 283 insertions(+), 4 deletions(-) >> create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c >> create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h >> >> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile >> index 44c506b7e117..b30f3d51c66a 100644 >> --- a/drivers/gpu/drm/i915/Makefile >> +++ b/drivers/gpu/drm/i915/Makefile >> @@ -33,7 +33,8 @@ subdir-ccflags-y += -I$(srctree)/$(src) >> # Please keep these build lists sorted! >> >> # core driver code >> -i915-y += i915_drv.o \ >> +i915-y += i915_drm_client.o \ >> + i915_drv.o \ >> i915_irq.o \ >> i915_getparam.o \ >> i915_params.o \ >> diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c >> new file mode 100644 >> index 000000000000..2067fbcdb795 >> --- /dev/null >> +++ b/drivers/gpu/drm/i915/i915_drm_client.c >> @@ -0,0 +1,179 @@ >> +// SPDX-License-Identifier: MIT >> +/* >> + * Copyright © 2020 Intel Corporation >> + */ >> + >> +#include <linux/kernel.h> >> +#include <linux/slab.h> >> +#include <linux/types.h> >> + >> +#include "i915_drm_client.h" >> +#include "i915_gem.h" >> +#include "i915_utils.h" >> + >> +void i915_drm_clients_init(struct i915_drm_clients *clients) >> +{ >> + clients->next_id = 0; >> + xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC); >> +} >> + >> +static ssize_t >> +show_client_name(struct device *kdev, struct device_attribute *attr, char *buf) >> +{ >> + struct i915_drm_client *client = >> + container_of(attr, typeof(*client), attr.name); >> + >> + return snprintf(buf, PAGE_SIZE, >> + READ_ONCE(client->closed) ? "<%s>" : "%s", >> + client->name); >> +} >> + >> +static ssize_t >> +show_client_pid(struct device *kdev, struct device_attribute *attr, char *buf) >> +{ >> + struct i915_drm_client *client = >> + container_of(attr, typeof(*client), attr.pid); >> + >> + return snprintf(buf, PAGE_SIZE, >> + READ_ONCE(client->closed) ? "<%u>" : "%u", >> + pid_nr(client->pid)); >> +} >> + >> +static int >> +__client_register_sysfs(struct i915_drm_client *client) >> +{ >> + const struct { >> + const char *name; >> + struct device_attribute *attr; >> + ssize_t (*show)(struct device *dev, >> + struct device_attribute *attr, >> + char *buf); >> + } files[] = { >> + { "name", &client->attr.name, show_client_name }, >> + { "pid", &client->attr.pid, show_client_pid }, >> + }; >> + unsigned int i; >> + char buf[16]; >> + int ret; >> + >> + ret = scnprintf(buf, sizeof(buf), "%u", client->id); >> + if (ret == sizeof(buf)) >> + return -EINVAL; >> + >> + client->root = kobject_create_and_add(buf, client->clients->root); >> + if (!client->root) >> + return -ENOMEM; >> + >> + for (i = 0; i < ARRAY_SIZE(files); i++) { >> + struct device_attribute *attr = files[i].attr; >> + >> + sysfs_attr_init(&attr->attr); >> + >> + attr->attr.name = files[i].name; >> + attr->attr.mode = 0444; >> + attr->show = files[i].show; >> + >> + ret = sysfs_create_file(client->root, (struct attribute *)attr); >> + if (ret) >> + break; >> + } >> + >> + if (ret) >> + kobject_put(client->root); >> + >> + return ret; >> +} >> + >> +static void __client_unregister_sysfs(struct i915_drm_client *client) >> +{ >> + kobject_put(fetch_and_zero(&client->root)); >> +} >> + >> +static int >> +__i915_drm_client_register(struct i915_drm_client *client, >> + struct task_struct *task) >> +{ >> + struct i915_drm_clients *clients = client->clients; >> + char *name; >> + int ret; >> + >> + name = kstrdup(task->comm, GFP_KERNEL); >> + if (!name) >> + return -ENOMEM; >> + >> + client->pid = get_task_pid(task, PIDTYPE_PID); >> + client->name = name; >> + >> + if (!clients->root) >> + return 0; /* intel_fbdev_init registers a client before sysfs */ >> + >> + ret = __client_register_sysfs(client); >> + if (ret) >> + goto err_sysfs; >> + >> + return 0; >> + >> +err_sysfs: >> + put_pid(client->pid); >> + kfree(client->name); >> + >> + return ret; >> +} >> + >> +static void >> +__i915_drm_client_unregister(struct i915_drm_client *client) >> +{ >> + __client_unregister_sysfs(client); >> + >> + put_pid(fetch_and_zero(&client->pid)); >> + kfree(fetch_and_zero(&client->name)); >> +} >> + >> +struct i915_drm_client * >> +i915_drm_client_add(struct i915_drm_clients *clients, struct task_struct *task) >> +{ >> + struct i915_drm_client *client; >> + int ret; >> + >> + client = kzalloc(sizeof(*client), GFP_KERNEL); >> + if (!client) >> + return ERR_PTR(-ENOMEM); >> + >> + kref_init(&client->kref); >> + client->clients = clients; >> + >> + ret = xa_alloc_cyclic(&clients->xarray, &client->id, client, >> + xa_limit_32b, &clients->next_id, GFP_KERNEL); >> + if (ret) >> + goto err_id; >> + >> + ret = __i915_drm_client_register(client, task); >> + if (ret) >> + goto err_register; >> + >> + return client; >> + >> +err_register: >> + xa_erase(&clients->xarray, client->id); >> +err_id: >> + kfree(client); >> + >> + return ERR_PTR(ret); >> +} >> + >> +void __i915_drm_client_free(struct kref *kref) >> +{ >> + struct i915_drm_client *client = >> + container_of(kref, typeof(*client), kref); >> + >> + __i915_drm_client_unregister(client); >> + xa_erase(&client->clients->xarray, client->id); >> + kfree_rcu(client, rcu); >> +} >> + >> +void i915_drm_client_close(struct i915_drm_client *client) >> +{ >> + GEM_BUG_ON(READ_ONCE(client->closed)); >> + WRITE_ONCE(client->closed, true); >> + i915_drm_client_put(client); >> +} >> diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h >> new file mode 100644 >> index 000000000000..af6998c74d4c >> --- /dev/null >> +++ b/drivers/gpu/drm/i915/i915_drm_client.h >> @@ -0,0 +1,64 @@ >> +// SPDX-License-Identifier: MIT >> +/* >> + * Copyright © 2020 Intel Corporation >> + */ >> + >> +#ifndef __I915_DRM_CLIENT_H__ >> +#define __I915_DRM_CLIENT_H__ >> + >> +#include <linux/device.h> >> +#include <linux/kobject.h> >> +#include <linux/kref.h> >> +#include <linux/pid.h> >> +#include <linux/rcupdate.h> >> +#include <linux/sched.h> >> +#include <linux/xarray.h> >> + >> +struct i915_drm_clients { >> + struct xarray xarray; >> + u32 next_id; >> + >> + struct kobject *root; >> +}; >> + >> +struct i915_drm_client { >> + struct kref kref; >> + >> + struct rcu_head rcu; >> + >> + unsigned int id; >> + struct pid *pid; >> + char *name; >> + bool closed; >> + >> + struct i915_drm_clients *clients; >> + >> + struct kobject *root; >> + struct { >> + struct device_attribute pid; >> + struct device_attribute name; >> + } attr; >> +}; >> + >> +void i915_drm_clients_init(struct i915_drm_clients *clients); >> + >> +static inline struct i915_drm_client * >> +i915_drm_client_get(struct i915_drm_client *client) >> +{ >> + kref_get(&client->kref); >> + return client; >> +} >> + >> +void __i915_drm_client_free(struct kref *kref); >> + >> +static inline void i915_drm_client_put(struct i915_drm_client *client) >> +{ >> + kref_put(&client->kref, __i915_drm_client_free); >> +} >> + >> +void i915_drm_client_close(struct i915_drm_client *client); >> + >> +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients, >> + struct task_struct *task); >> + >> +#endif /* !__I915_DRM_CLIENT_H__ */ >> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c >> index 641f5e03b661..dac84b17d23d 100644 >> --- a/drivers/gpu/drm/i915/i915_drv.c >> +++ b/drivers/gpu/drm/i915/i915_drv.c >> @@ -70,6 +70,7 @@ >> #include "gt/intel_rc6.h" >> >> #include "i915_debugfs.h" >> +#include "i915_drm_client.h" >> #include "i915_drv.h" >> #include "i915_ioc32.h" >> #include "i915_irq.h" >> @@ -456,6 +457,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) >> >> i915_gem_init_early(dev_priv); >> >> + i915_drm_clients_init(&dev_priv->clients); >> + >> /* This must be called before any calls to HAS_PCH_* */ >> intel_detect_pch(dev_priv); >> >> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h >> index e9ee4daa9320..f9f0c3ba6e4a 100644 >> --- a/drivers/gpu/drm/i915/i915_drv.h >> +++ b/drivers/gpu/drm/i915/i915_drv.h >> @@ -91,6 +91,7 @@ >> #include "intel_wakeref.h" >> #include "intel_wopcm.h" >> >> +#include "i915_drm_client.h" >> #include "i915_gem.h" >> #include "i915_gem_gtt.h" >> #include "i915_gpu_error.h" >> @@ -226,6 +227,8 @@ struct drm_i915_file_private { >> /** ban_score: Accumulated score of all ctx bans and fast hangs. */ >> atomic_t ban_score; >> unsigned long hang_timestamp; >> + >> + struct i915_drm_client *client; >> }; >> >> /* Interface history: >> @@ -1201,6 +1204,8 @@ struct drm_i915_private { >> >> struct i915_pmu pmu; >> >> + struct i915_drm_clients clients; >> + >> struct i915_hdcp_comp_master *hdcp_master; >> bool hdcp_comp_added; >> >> diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c >> index 0cbcb9f54e7d..5a0b5fae8b92 100644 >> --- a/drivers/gpu/drm/i915/i915_gem.c >> +++ b/drivers/gpu/drm/i915/i915_gem.c >> @@ -1234,6 +1234,8 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv) >> GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); >> GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); >> drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count); >> + drm_WARN_ON(&dev_priv->drm, !xa_empty(&dev_priv->clients.xarray)); >> + xa_destroy(&dev_priv->clients.xarray); >> } >> >> int i915_gem_freeze(struct drm_i915_private *dev_priv) >> @@ -1288,6 +1290,8 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) >> struct drm_i915_file_private *file_priv = file->driver_priv; >> struct i915_request *request; >> >> + i915_drm_client_close(file_priv->client); >> + >> /* Clean up our request list when the client is going away, so that >> * later retire_requests won't dereference our soon-to-be-gone >> * file_priv. >> @@ -1301,17 +1305,25 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file) >> int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) >> { >> struct drm_i915_file_private *file_priv; >> - int ret; >> + struct i915_drm_client *client; >> + int ret = -ENOMEM; >> >> DRM_DEBUG("\n"); >> >> file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); >> if (!file_priv) >> - return -ENOMEM; >> + goto err_alloc; >> + >> + client = i915_drm_client_add(&i915->clients, current); >> + if (IS_ERR(client)) { >> + ret = PTR_ERR(client); >> + goto err_client; >> + } >> >> file->driver_priv = file_priv; >> file_priv->dev_priv = i915; >> file_priv->file = file; >> + file_priv->client = client; >> >> spin_lock_init(&file_priv->mm.lock); >> INIT_LIST_HEAD(&file_priv->mm.request_list); >> @@ -1321,8 +1333,15 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) >> >> ret = i915_gem_context_open(i915, file); >> if (ret) >> - kfree(file_priv); >> + goto err_context; >> + >> + return 0; >> >> +err_context: >> + i915_drm_client_close(client); >> +err_client: >> + kfree(file_priv); >> +err_alloc: >> return ret; >> } >> >> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c >> index 45d32ef42787..b7d4a6d2dd5c 100644 >> --- a/drivers/gpu/drm/i915/i915_sysfs.c >> +++ b/drivers/gpu/drm/i915/i915_sysfs.c >> @@ -560,6 +560,11 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) >> struct device *kdev = dev_priv->drm.primary->kdev; >> int ret; >> >> + dev_priv->clients.root = >> + kobject_create_and_add("clients", &kdev->kobj); >> + if (!dev_priv->clients.root) >> + DRM_ERROR("Per-client sysfs setup failed\n"); >> + >> #ifdef CONFIG_PM >> if (HAS_RC6(dev_priv)) { >> ret = sysfs_merge_group(&kdev->kobj, >> @@ -627,4 +632,7 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) >> sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); >> sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); >> #endif >> + >> + if (dev_priv->clients.root) >> + kobject_put(dev_priv->clients.root); >> } >> -- >> 2.20.1 >> >> _______________________________________________ >> Intel-gfx mailing list >> Intel-gfx@lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs 2020-09-01 15:09 ` Tvrtko Ursulin @ 2020-09-01 15:25 ` Tvrtko Ursulin 2020-09-04 6:26 ` Lucas De Marchi 0 siblings, 1 reply; 7+ messages in thread From: Tvrtko Ursulin @ 2020-09-01 15:25 UTC (permalink / raw) To: Lucas De Marchi; +Cc: Intel Graphics, Chris Wilson On 01/09/2020 16:09, Tvrtko Ursulin wrote: > > Hi, > > On 26/08/2020 02:11, Lucas De Marchi wrote: >> Hi, >> >> Any update on this? It now conflicts in a few places so it needs a >> rebase. > > I don't see any previous email on the topic - what kind of update, where > and how, are you looking for? Rebase against drm-tip so you pull it in? > Rebase against some internal in progress branch? Clearly you were after an update against drm-tip.. :) Problem here was no userspace but I can try to respin it. Regards, Tvrtko > > Regards, > > Tvrtko > >> Lucas De Marchi >> >> On Wed, Apr 15, 2020 at 3:11 AM Tvrtko Ursulin >> <tvrtko.ursulin@linux.intel.com> wrote: >>> >>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com> >>> >>> Expose a list of clients with open file handles in sysfs. >>> >>> This will be a basis for a top-like utility showing per-client and per- >>> engine GPU load. >>> >>> Currently we only expose each client's pid and name under opaque >>> numbered >>> directories in /sys/class/drm/card0/clients/. >>> >>> For instance: >>> >>> /sys/class/drm/card0/clients/3/name: Xorg >>> /sys/class/drm/card0/clients/3/pid: 5664 >>> >>> v2: >>> Chris Wilson: >>> * Enclose new members into dedicated structs. >>> * Protect against failed sysfs registration. >>> >>> v3: >>> * sysfs_attr_init. >>> >>> v4: >>> * Fix for internal clients. >>> >>> v5: >>> * Use cyclic ida for client id. (Chris) >>> * Do not leak pid reference. (Chris) >>> * Tidy code with some locals. >>> >>> v6: >>> * Use xa_alloc_cyclic to simplify locking. (Chris) >>> * No need to unregister individial sysfs files. (Chris) >>> * Rebase on top of fpriv kref. >>> * Track client closed status and reflect in sysfs. >>> >>> v7: >>> * Make drm_client more standalone concept. >>> >>> v8: >>> * Simplify sysfs show. (Chris) >>> * Always track name and pid. >>> >>> v9: >>> * Fix cyclic id assignment. >>> >>> v10: >>> * No need for a mutex around xa_alloc_cyclic. >>> * Refactor sysfs into own function. >>> * Unregister sysfs before freeing pid and name. >>> * Move clients setup into own function. >>> >>> v11: >>> * Call clients init directly from driver init. (Chris) >>> >>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> >>> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> >>> --- >>> drivers/gpu/drm/i915/Makefile | 3 +- >>> drivers/gpu/drm/i915/i915_drm_client.c | 179 +++++++++++++++++++++++++ >>> drivers/gpu/drm/i915/i915_drm_client.h | 64 +++++++++ >>> drivers/gpu/drm/i915/i915_drv.c | 3 + >>> drivers/gpu/drm/i915/i915_drv.h | 5 + >>> drivers/gpu/drm/i915/i915_gem.c | 25 +++- >>> drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ >>> 7 files changed, 283 insertions(+), 4 deletions(-) >>> create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c >>> create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h >>> >>> diff --git a/drivers/gpu/drm/i915/Makefile >>> b/drivers/gpu/drm/i915/Makefile >>> index 44c506b7e117..b30f3d51c66a 100644 >>> --- a/drivers/gpu/drm/i915/Makefile >>> +++ b/drivers/gpu/drm/i915/Makefile >>> @@ -33,7 +33,8 @@ subdir-ccflags-y += -I$(srctree)/$(src) >>> # Please keep these build lists sorted! >>> >>> # core driver code >>> -i915-y += i915_drv.o \ >>> +i915-y += i915_drm_client.o \ >>> + i915_drv.o \ >>> i915_irq.o \ >>> i915_getparam.o \ >>> i915_params.o \ >>> diff --git a/drivers/gpu/drm/i915/i915_drm_client.c >>> b/drivers/gpu/drm/i915/i915_drm_client.c >>> new file mode 100644 >>> index 000000000000..2067fbcdb795 >>> --- /dev/null >>> +++ b/drivers/gpu/drm/i915/i915_drm_client.c >>> @@ -0,0 +1,179 @@ >>> +// SPDX-License-Identifier: MIT >>> +/* >>> + * Copyright © 2020 Intel Corporation >>> + */ >>> + >>> +#include <linux/kernel.h> >>> +#include <linux/slab.h> >>> +#include <linux/types.h> >>> + >>> +#include "i915_drm_client.h" >>> +#include "i915_gem.h" >>> +#include "i915_utils.h" >>> + >>> +void i915_drm_clients_init(struct i915_drm_clients *clients) >>> +{ >>> + clients->next_id = 0; >>> + xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC); >>> +} >>> + >>> +static ssize_t >>> +show_client_name(struct device *kdev, struct device_attribute *attr, >>> char *buf) >>> +{ >>> + struct i915_drm_client *client = >>> + container_of(attr, typeof(*client), attr.name); >>> + >>> + return snprintf(buf, PAGE_SIZE, >>> + READ_ONCE(client->closed) ? "<%s>" : "%s", >>> + client->name); >>> +} >>> + >>> +static ssize_t >>> +show_client_pid(struct device *kdev, struct device_attribute *attr, >>> char *buf) >>> +{ >>> + struct i915_drm_client *client = >>> + container_of(attr, typeof(*client), attr.pid); >>> + >>> + return snprintf(buf, PAGE_SIZE, >>> + READ_ONCE(client->closed) ? "<%u>" : "%u", >>> + pid_nr(client->pid)); >>> +} >>> + >>> +static int >>> +__client_register_sysfs(struct i915_drm_client *client) >>> +{ >>> + const struct { >>> + const char *name; >>> + struct device_attribute *attr; >>> + ssize_t (*show)(struct device *dev, >>> + struct device_attribute *attr, >>> + char *buf); >>> + } files[] = { >>> + { "name", &client->attr.name, show_client_name }, >>> + { "pid", &client->attr.pid, show_client_pid }, >>> + }; >>> + unsigned int i; >>> + char buf[16]; >>> + int ret; >>> + >>> + ret = scnprintf(buf, sizeof(buf), "%u", client->id); >>> + if (ret == sizeof(buf)) >>> + return -EINVAL; >>> + >>> + client->root = kobject_create_and_add(buf, >>> client->clients->root); >>> + if (!client->root) >>> + return -ENOMEM; >>> + >>> + for (i = 0; i < ARRAY_SIZE(files); i++) { >>> + struct device_attribute *attr = files[i].attr; >>> + >>> + sysfs_attr_init(&attr->attr); >>> + >>> + attr->attr.name = files[i].name; >>> + attr->attr.mode = 0444; >>> + attr->show = files[i].show; >>> + >>> + ret = sysfs_create_file(client->root, (struct >>> attribute *)attr); >>> + if (ret) >>> + break; >>> + } >>> + >>> + if (ret) >>> + kobject_put(client->root); >>> + >>> + return ret; >>> +} >>> + >>> +static void __client_unregister_sysfs(struct i915_drm_client *client) >>> +{ >>> + kobject_put(fetch_and_zero(&client->root)); >>> +} >>> + >>> +static int >>> +__i915_drm_client_register(struct i915_drm_client *client, >>> + struct task_struct *task) >>> +{ >>> + struct i915_drm_clients *clients = client->clients; >>> + char *name; >>> + int ret; >>> + >>> + name = kstrdup(task->comm, GFP_KERNEL); >>> + if (!name) >>> + return -ENOMEM; >>> + >>> + client->pid = get_task_pid(task, PIDTYPE_PID); >>> + client->name = name; >>> + >>> + if (!clients->root) >>> + return 0; /* intel_fbdev_init registers a client >>> before sysfs */ >>> + >>> + ret = __client_register_sysfs(client); >>> + if (ret) >>> + goto err_sysfs; >>> + >>> + return 0; >>> + >>> +err_sysfs: >>> + put_pid(client->pid); >>> + kfree(client->name); >>> + >>> + return ret; >>> +} >>> + >>> +static void >>> +__i915_drm_client_unregister(struct i915_drm_client *client) >>> +{ >>> + __client_unregister_sysfs(client); >>> + >>> + put_pid(fetch_and_zero(&client->pid)); >>> + kfree(fetch_and_zero(&client->name)); >>> +} >>> + >>> +struct i915_drm_client * >>> +i915_drm_client_add(struct i915_drm_clients *clients, struct >>> task_struct *task) >>> +{ >>> + struct i915_drm_client *client; >>> + int ret; >>> + >>> + client = kzalloc(sizeof(*client), GFP_KERNEL); >>> + if (!client) >>> + return ERR_PTR(-ENOMEM); >>> + >>> + kref_init(&client->kref); >>> + client->clients = clients; >>> + >>> + ret = xa_alloc_cyclic(&clients->xarray, &client->id, client, >>> + xa_limit_32b, &clients->next_id, >>> GFP_KERNEL); >>> + if (ret) >>> + goto err_id; >>> + >>> + ret = __i915_drm_client_register(client, task); >>> + if (ret) >>> + goto err_register; >>> + >>> + return client; >>> + >>> +err_register: >>> + xa_erase(&clients->xarray, client->id); >>> +err_id: >>> + kfree(client); >>> + >>> + return ERR_PTR(ret); >>> +} >>> + >>> +void __i915_drm_client_free(struct kref *kref) >>> +{ >>> + struct i915_drm_client *client = >>> + container_of(kref, typeof(*client), kref); >>> + >>> + __i915_drm_client_unregister(client); >>> + xa_erase(&client->clients->xarray, client->id); >>> + kfree_rcu(client, rcu); >>> +} >>> + >>> +void i915_drm_client_close(struct i915_drm_client *client) >>> +{ >>> + GEM_BUG_ON(READ_ONCE(client->closed)); >>> + WRITE_ONCE(client->closed, true); >>> + i915_drm_client_put(client); >>> +} >>> diff --git a/drivers/gpu/drm/i915/i915_drm_client.h >>> b/drivers/gpu/drm/i915/i915_drm_client.h >>> new file mode 100644 >>> index 000000000000..af6998c74d4c >>> --- /dev/null >>> +++ b/drivers/gpu/drm/i915/i915_drm_client.h >>> @@ -0,0 +1,64 @@ >>> +// SPDX-License-Identifier: MIT >>> +/* >>> + * Copyright © 2020 Intel Corporation >>> + */ >>> + >>> +#ifndef __I915_DRM_CLIENT_H__ >>> +#define __I915_DRM_CLIENT_H__ >>> + >>> +#include <linux/device.h> >>> +#include <linux/kobject.h> >>> +#include <linux/kref.h> >>> +#include <linux/pid.h> >>> +#include <linux/rcupdate.h> >>> +#include <linux/sched.h> >>> +#include <linux/xarray.h> >>> + >>> +struct i915_drm_clients { >>> + struct xarray xarray; >>> + u32 next_id; >>> + >>> + struct kobject *root; >>> +}; >>> + >>> +struct i915_drm_client { >>> + struct kref kref; >>> + >>> + struct rcu_head rcu; >>> + >>> + unsigned int id; >>> + struct pid *pid; >>> + char *name; >>> + bool closed; >>> + >>> + struct i915_drm_clients *clients; >>> + >>> + struct kobject *root; >>> + struct { >>> + struct device_attribute pid; >>> + struct device_attribute name; >>> + } attr; >>> +}; >>> + >>> +void i915_drm_clients_init(struct i915_drm_clients *clients); >>> + >>> +static inline struct i915_drm_client * >>> +i915_drm_client_get(struct i915_drm_client *client) >>> +{ >>> + kref_get(&client->kref); >>> + return client; >>> +} >>> + >>> +void __i915_drm_client_free(struct kref *kref); >>> + >>> +static inline void i915_drm_client_put(struct i915_drm_client *client) >>> +{ >>> + kref_put(&client->kref, __i915_drm_client_free); >>> +} >>> + >>> +void i915_drm_client_close(struct i915_drm_client *client); >>> + >>> +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients >>> *clients, >>> + struct task_struct *task); >>> + >>> +#endif /* !__I915_DRM_CLIENT_H__ */ >>> diff --git a/drivers/gpu/drm/i915/i915_drv.c >>> b/drivers/gpu/drm/i915/i915_drv.c >>> index 641f5e03b661..dac84b17d23d 100644 >>> --- a/drivers/gpu/drm/i915/i915_drv.c >>> +++ b/drivers/gpu/drm/i915/i915_drv.c >>> @@ -70,6 +70,7 @@ >>> #include "gt/intel_rc6.h" >>> >>> #include "i915_debugfs.h" >>> +#include "i915_drm_client.h" >>> #include "i915_drv.h" >>> #include "i915_ioc32.h" >>> #include "i915_irq.h" >>> @@ -456,6 +457,8 @@ static int i915_driver_early_probe(struct >>> drm_i915_private *dev_priv) >>> >>> i915_gem_init_early(dev_priv); >>> >>> + i915_drm_clients_init(&dev_priv->clients); >>> + >>> /* This must be called before any calls to HAS_PCH_* */ >>> intel_detect_pch(dev_priv); >>> >>> diff --git a/drivers/gpu/drm/i915/i915_drv.h >>> b/drivers/gpu/drm/i915/i915_drv.h >>> index e9ee4daa9320..f9f0c3ba6e4a 100644 >>> --- a/drivers/gpu/drm/i915/i915_drv.h >>> +++ b/drivers/gpu/drm/i915/i915_drv.h >>> @@ -91,6 +91,7 @@ >>> #include "intel_wakeref.h" >>> #include "intel_wopcm.h" >>> >>> +#include "i915_drm_client.h" >>> #include "i915_gem.h" >>> #include "i915_gem_gtt.h" >>> #include "i915_gpu_error.h" >>> @@ -226,6 +227,8 @@ struct drm_i915_file_private { >>> /** ban_score: Accumulated score of all ctx bans and fast >>> hangs. */ >>> atomic_t ban_score; >>> unsigned long hang_timestamp; >>> + >>> + struct i915_drm_client *client; >>> }; >>> >>> /* Interface history: >>> @@ -1201,6 +1204,8 @@ struct drm_i915_private { >>> >>> struct i915_pmu pmu; >>> >>> + struct i915_drm_clients clients; >>> + >>> struct i915_hdcp_comp_master *hdcp_master; >>> bool hdcp_comp_added; >>> >>> diff --git a/drivers/gpu/drm/i915/i915_gem.c >>> b/drivers/gpu/drm/i915/i915_gem.c >>> index 0cbcb9f54e7d..5a0b5fae8b92 100644 >>> --- a/drivers/gpu/drm/i915/i915_gem.c >>> +++ b/drivers/gpu/drm/i915/i915_gem.c >>> @@ -1234,6 +1234,8 @@ void i915_gem_cleanup_early(struct >>> drm_i915_private *dev_priv) >>> GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); >>> GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); >>> drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count); >>> + drm_WARN_ON(&dev_priv->drm, >>> !xa_empty(&dev_priv->clients.xarray)); >>> + xa_destroy(&dev_priv->clients.xarray); >>> } >>> >>> int i915_gem_freeze(struct drm_i915_private *dev_priv) >>> @@ -1288,6 +1290,8 @@ void i915_gem_release(struct drm_device *dev, >>> struct drm_file *file) >>> struct drm_i915_file_private *file_priv = file->driver_priv; >>> struct i915_request *request; >>> >>> + i915_drm_client_close(file_priv->client); >>> + >>> /* Clean up our request list when the client is going away, >>> so that >>> * later retire_requests won't dereference our soon-to-be-gone >>> * file_priv. >>> @@ -1301,17 +1305,25 @@ void i915_gem_release(struct drm_device *dev, >>> struct drm_file *file) >>> int i915_gem_open(struct drm_i915_private *i915, struct drm_file >>> *file) >>> { >>> struct drm_i915_file_private *file_priv; >>> - int ret; >>> + struct i915_drm_client *client; >>> + int ret = -ENOMEM; >>> >>> DRM_DEBUG("\n"); >>> >>> file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); >>> if (!file_priv) >>> - return -ENOMEM; >>> + goto err_alloc; >>> + >>> + client = i915_drm_client_add(&i915->clients, current); >>> + if (IS_ERR(client)) { >>> + ret = PTR_ERR(client); >>> + goto err_client; >>> + } >>> >>> file->driver_priv = file_priv; >>> file_priv->dev_priv = i915; >>> file_priv->file = file; >>> + file_priv->client = client; >>> >>> spin_lock_init(&file_priv->mm.lock); >>> INIT_LIST_HEAD(&file_priv->mm.request_list); >>> @@ -1321,8 +1333,15 @@ int i915_gem_open(struct drm_i915_private >>> *i915, struct drm_file *file) >>> >>> ret = i915_gem_context_open(i915, file); >>> if (ret) >>> - kfree(file_priv); >>> + goto err_context; >>> + >>> + return 0; >>> >>> +err_context: >>> + i915_drm_client_close(client); >>> +err_client: >>> + kfree(file_priv); >>> +err_alloc: >>> return ret; >>> } >>> >>> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c >>> b/drivers/gpu/drm/i915/i915_sysfs.c >>> index 45d32ef42787..b7d4a6d2dd5c 100644 >>> --- a/drivers/gpu/drm/i915/i915_sysfs.c >>> +++ b/drivers/gpu/drm/i915/i915_sysfs.c >>> @@ -560,6 +560,11 @@ void i915_setup_sysfs(struct drm_i915_private >>> *dev_priv) >>> struct device *kdev = dev_priv->drm.primary->kdev; >>> int ret; >>> >>> + dev_priv->clients.root = >>> + kobject_create_and_add("clients", &kdev->kobj); >>> + if (!dev_priv->clients.root) >>> + DRM_ERROR("Per-client sysfs setup failed\n"); >>> + >>> #ifdef CONFIG_PM >>> if (HAS_RC6(dev_priv)) { >>> ret = sysfs_merge_group(&kdev->kobj, >>> @@ -627,4 +632,7 @@ void i915_teardown_sysfs(struct drm_i915_private >>> *dev_priv) >>> sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); >>> sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); >>> #endif >>> + >>> + if (dev_priv->clients.root) >>> + kobject_put(dev_priv->clients.root); >>> } >>> -- >>> 2.20.1 >>> >>> _______________________________________________ >>> Intel-gfx mailing list >>> Intel-gfx@lists.freedesktop.org >>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs 2020-09-01 15:25 ` Tvrtko Ursulin @ 2020-09-04 6:26 ` Lucas De Marchi 2020-09-04 13:03 ` Tvrtko Ursulin 0 siblings, 1 reply; 7+ messages in thread From: Lucas De Marchi @ 2020-09-04 6:26 UTC (permalink / raw) To: Tvrtko Ursulin; +Cc: Intel Graphics, Chris Wilson On Tue, Sep 1, 2020 at 8:25 AM Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> wrote: > > > On 01/09/2020 16:09, Tvrtko Ursulin wrote: > > > > Hi, > > > > On 26/08/2020 02:11, Lucas De Marchi wrote: > >> Hi, > >> > >> Any update on this? It now conflicts in a few places so it needs a > >> rebase. > > > > I don't see any previous email on the topic - what kind of update, where > > and how, are you looking for? Rebase against drm-tip so you pull it in? > > Rebase against some internal in progress branch? > > Clearly you were after an update against drm-tip.. :) Problem here was > no userspace but I can try to respin it. Yes, against drm-tip. I rebased it, but I think there is something wrong with it. If you can share your version I can do some tests. thanks Lucas De Marchi > > Regards, > > Tvrtko > > > > > Regards, > > > > Tvrtko > > > >> Lucas De Marchi > >> > >> On Wed, Apr 15, 2020 at 3:11 AM Tvrtko Ursulin > >> <tvrtko.ursulin@linux.intel.com> wrote: > >>> > >>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com> > >>> > >>> Expose a list of clients with open file handles in sysfs. > >>> > >>> This will be a basis for a top-like utility showing per-client and per- > >>> engine GPU load. > >>> > >>> Currently we only expose each client's pid and name under opaque > >>> numbered > >>> directories in /sys/class/drm/card0/clients/. > >>> > >>> For instance: > >>> > >>> /sys/class/drm/card0/clients/3/name: Xorg > >>> /sys/class/drm/card0/clients/3/pid: 5664 > >>> > >>> v2: > >>> Chris Wilson: > >>> * Enclose new members into dedicated structs. > >>> * Protect against failed sysfs registration. > >>> > >>> v3: > >>> * sysfs_attr_init. > >>> > >>> v4: > >>> * Fix for internal clients. > >>> > >>> v5: > >>> * Use cyclic ida for client id. (Chris) > >>> * Do not leak pid reference. (Chris) > >>> * Tidy code with some locals. > >>> > >>> v6: > >>> * Use xa_alloc_cyclic to simplify locking. (Chris) > >>> * No need to unregister individial sysfs files. (Chris) > >>> * Rebase on top of fpriv kref. > >>> * Track client closed status and reflect in sysfs. > >>> > >>> v7: > >>> * Make drm_client more standalone concept. > >>> > >>> v8: > >>> * Simplify sysfs show. (Chris) > >>> * Always track name and pid. > >>> > >>> v9: > >>> * Fix cyclic id assignment. > >>> > >>> v10: > >>> * No need for a mutex around xa_alloc_cyclic. > >>> * Refactor sysfs into own function. > >>> * Unregister sysfs before freeing pid and name. > >>> * Move clients setup into own function. > >>> > >>> v11: > >>> * Call clients init directly from driver init. (Chris) > >>> > >>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> > >>> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> > >>> --- > >>> drivers/gpu/drm/i915/Makefile | 3 +- > >>> drivers/gpu/drm/i915/i915_drm_client.c | 179 +++++++++++++++++++++++++ > >>> drivers/gpu/drm/i915/i915_drm_client.h | 64 +++++++++ > >>> drivers/gpu/drm/i915/i915_drv.c | 3 + > >>> drivers/gpu/drm/i915/i915_drv.h | 5 + > >>> drivers/gpu/drm/i915/i915_gem.c | 25 +++- > >>> drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ > >>> 7 files changed, 283 insertions(+), 4 deletions(-) > >>> create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c > >>> create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h > >>> > >>> diff --git a/drivers/gpu/drm/i915/Makefile > >>> b/drivers/gpu/drm/i915/Makefile > >>> index 44c506b7e117..b30f3d51c66a 100644 > >>> --- a/drivers/gpu/drm/i915/Makefile > >>> +++ b/drivers/gpu/drm/i915/Makefile > >>> @@ -33,7 +33,8 @@ subdir-ccflags-y += -I$(srctree)/$(src) > >>> # Please keep these build lists sorted! > >>> > >>> # core driver code > >>> -i915-y += i915_drv.o \ > >>> +i915-y += i915_drm_client.o \ > >>> + i915_drv.o \ > >>> i915_irq.o \ > >>> i915_getparam.o \ > >>> i915_params.o \ > >>> diff --git a/drivers/gpu/drm/i915/i915_drm_client.c > >>> b/drivers/gpu/drm/i915/i915_drm_client.c > >>> new file mode 100644 > >>> index 000000000000..2067fbcdb795 > >>> --- /dev/null > >>> +++ b/drivers/gpu/drm/i915/i915_drm_client.c > >>> @@ -0,0 +1,179 @@ > >>> +// SPDX-License-Identifier: MIT > >>> +/* > >>> + * Copyright © 2020 Intel Corporation > >>> + */ > >>> + > >>> +#include <linux/kernel.h> > >>> +#include <linux/slab.h> > >>> +#include <linux/types.h> > >>> + > >>> +#include "i915_drm_client.h" > >>> +#include "i915_gem.h" > >>> +#include "i915_utils.h" > >>> + > >>> +void i915_drm_clients_init(struct i915_drm_clients *clients) > >>> +{ > >>> + clients->next_id = 0; > >>> + xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC); > >>> +} > >>> + > >>> +static ssize_t > >>> +show_client_name(struct device *kdev, struct device_attribute *attr, > >>> char *buf) > >>> +{ > >>> + struct i915_drm_client *client = > >>> + container_of(attr, typeof(*client), attr.name); > >>> + > >>> + return snprintf(buf, PAGE_SIZE, > >>> + READ_ONCE(client->closed) ? "<%s>" : "%s", > >>> + client->name); > >>> +} > >>> + > >>> +static ssize_t > >>> +show_client_pid(struct device *kdev, struct device_attribute *attr, > >>> char *buf) > >>> +{ > >>> + struct i915_drm_client *client = > >>> + container_of(attr, typeof(*client), attr.pid); > >>> + > >>> + return snprintf(buf, PAGE_SIZE, > >>> + READ_ONCE(client->closed) ? "<%u>" : "%u", > >>> + pid_nr(client->pid)); > >>> +} > >>> + > >>> +static int > >>> +__client_register_sysfs(struct i915_drm_client *client) > >>> +{ > >>> + const struct { > >>> + const char *name; > >>> + struct device_attribute *attr; > >>> + ssize_t (*show)(struct device *dev, > >>> + struct device_attribute *attr, > >>> + char *buf); > >>> + } files[] = { > >>> + { "name", &client->attr.name, show_client_name }, > >>> + { "pid", &client->attr.pid, show_client_pid }, > >>> + }; > >>> + unsigned int i; > >>> + char buf[16]; > >>> + int ret; > >>> + > >>> + ret = scnprintf(buf, sizeof(buf), "%u", client->id); > >>> + if (ret == sizeof(buf)) > >>> + return -EINVAL; > >>> + > >>> + client->root = kobject_create_and_add(buf, > >>> client->clients->root); > >>> + if (!client->root) > >>> + return -ENOMEM; > >>> + > >>> + for (i = 0; i < ARRAY_SIZE(files); i++) { > >>> + struct device_attribute *attr = files[i].attr; > >>> + > >>> + sysfs_attr_init(&attr->attr); > >>> + > >>> + attr->attr.name = files[i].name; > >>> + attr->attr.mode = 0444; > >>> + attr->show = files[i].show; > >>> + > >>> + ret = sysfs_create_file(client->root, (struct > >>> attribute *)attr); > >>> + if (ret) > >>> + break; > >>> + } > >>> + > >>> + if (ret) > >>> + kobject_put(client->root); > >>> + > >>> + return ret; > >>> +} > >>> + > >>> +static void __client_unregister_sysfs(struct i915_drm_client *client) > >>> +{ > >>> + kobject_put(fetch_and_zero(&client->root)); > >>> +} > >>> + > >>> +static int > >>> +__i915_drm_client_register(struct i915_drm_client *client, > >>> + struct task_struct *task) > >>> +{ > >>> + struct i915_drm_clients *clients = client->clients; > >>> + char *name; > >>> + int ret; > >>> + > >>> + name = kstrdup(task->comm, GFP_KERNEL); > >>> + if (!name) > >>> + return -ENOMEM; > >>> + > >>> + client->pid = get_task_pid(task, PIDTYPE_PID); > >>> + client->name = name; > >>> + > >>> + if (!clients->root) > >>> + return 0; /* intel_fbdev_init registers a client > >>> before sysfs */ > >>> + > >>> + ret = __client_register_sysfs(client); > >>> + if (ret) > >>> + goto err_sysfs; > >>> + > >>> + return 0; > >>> + > >>> +err_sysfs: > >>> + put_pid(client->pid); > >>> + kfree(client->name); > >>> + > >>> + return ret; > >>> +} > >>> + > >>> +static void > >>> +__i915_drm_client_unregister(struct i915_drm_client *client) > >>> +{ > >>> + __client_unregister_sysfs(client); > >>> + > >>> + put_pid(fetch_and_zero(&client->pid)); > >>> + kfree(fetch_and_zero(&client->name)); > >>> +} > >>> + > >>> +struct i915_drm_client * > >>> +i915_drm_client_add(struct i915_drm_clients *clients, struct > >>> task_struct *task) > >>> +{ > >>> + struct i915_drm_client *client; > >>> + int ret; > >>> + > >>> + client = kzalloc(sizeof(*client), GFP_KERNEL); > >>> + if (!client) > >>> + return ERR_PTR(-ENOMEM); > >>> + > >>> + kref_init(&client->kref); > >>> + client->clients = clients; > >>> + > >>> + ret = xa_alloc_cyclic(&clients->xarray, &client->id, client, > >>> + xa_limit_32b, &clients->next_id, > >>> GFP_KERNEL); > >>> + if (ret) > >>> + goto err_id; > >>> + > >>> + ret = __i915_drm_client_register(client, task); > >>> + if (ret) > >>> + goto err_register; > >>> + > >>> + return client; > >>> + > >>> +err_register: > >>> + xa_erase(&clients->xarray, client->id); > >>> +err_id: > >>> + kfree(client); > >>> + > >>> + return ERR_PTR(ret); > >>> +} > >>> + > >>> +void __i915_drm_client_free(struct kref *kref) > >>> +{ > >>> + struct i915_drm_client *client = > >>> + container_of(kref, typeof(*client), kref); > >>> + > >>> + __i915_drm_client_unregister(client); > >>> + xa_erase(&client->clients->xarray, client->id); > >>> + kfree_rcu(client, rcu); > >>> +} > >>> + > >>> +void i915_drm_client_close(struct i915_drm_client *client) > >>> +{ > >>> + GEM_BUG_ON(READ_ONCE(client->closed)); > >>> + WRITE_ONCE(client->closed, true); > >>> + i915_drm_client_put(client); > >>> +} > >>> diff --git a/drivers/gpu/drm/i915/i915_drm_client.h > >>> b/drivers/gpu/drm/i915/i915_drm_client.h > >>> new file mode 100644 > >>> index 000000000000..af6998c74d4c > >>> --- /dev/null > >>> +++ b/drivers/gpu/drm/i915/i915_drm_client.h > >>> @@ -0,0 +1,64 @@ > >>> +// SPDX-License-Identifier: MIT > >>> +/* > >>> + * Copyright © 2020 Intel Corporation > >>> + */ > >>> + > >>> +#ifndef __I915_DRM_CLIENT_H__ > >>> +#define __I915_DRM_CLIENT_H__ > >>> + > >>> +#include <linux/device.h> > >>> +#include <linux/kobject.h> > >>> +#include <linux/kref.h> > >>> +#include <linux/pid.h> > >>> +#include <linux/rcupdate.h> > >>> +#include <linux/sched.h> > >>> +#include <linux/xarray.h> > >>> + > >>> +struct i915_drm_clients { > >>> + struct xarray xarray; > >>> + u32 next_id; > >>> + > >>> + struct kobject *root; > >>> +}; > >>> + > >>> +struct i915_drm_client { > >>> + struct kref kref; > >>> + > >>> + struct rcu_head rcu; > >>> + > >>> + unsigned int id; > >>> + struct pid *pid; > >>> + char *name; > >>> + bool closed; > >>> + > >>> + struct i915_drm_clients *clients; > >>> + > >>> + struct kobject *root; > >>> + struct { > >>> + struct device_attribute pid; > >>> + struct device_attribute name; > >>> + } attr; > >>> +}; > >>> + > >>> +void i915_drm_clients_init(struct i915_drm_clients *clients); > >>> + > >>> +static inline struct i915_drm_client * > >>> +i915_drm_client_get(struct i915_drm_client *client) > >>> +{ > >>> + kref_get(&client->kref); > >>> + return client; > >>> +} > >>> + > >>> +void __i915_drm_client_free(struct kref *kref); > >>> + > >>> +static inline void i915_drm_client_put(struct i915_drm_client *client) > >>> +{ > >>> + kref_put(&client->kref, __i915_drm_client_free); > >>> +} > >>> + > >>> +void i915_drm_client_close(struct i915_drm_client *client); > >>> + > >>> +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients > >>> *clients, > >>> + struct task_struct *task); > >>> + > >>> +#endif /* !__I915_DRM_CLIENT_H__ */ > >>> diff --git a/drivers/gpu/drm/i915/i915_drv.c > >>> b/drivers/gpu/drm/i915/i915_drv.c > >>> index 641f5e03b661..dac84b17d23d 100644 > >>> --- a/drivers/gpu/drm/i915/i915_drv.c > >>> +++ b/drivers/gpu/drm/i915/i915_drv.c > >>> @@ -70,6 +70,7 @@ > >>> #include "gt/intel_rc6.h" > >>> > >>> #include "i915_debugfs.h" > >>> +#include "i915_drm_client.h" > >>> #include "i915_drv.h" > >>> #include "i915_ioc32.h" > >>> #include "i915_irq.h" > >>> @@ -456,6 +457,8 @@ static int i915_driver_early_probe(struct > >>> drm_i915_private *dev_priv) > >>> > >>> i915_gem_init_early(dev_priv); > >>> > >>> + i915_drm_clients_init(&dev_priv->clients); > >>> + > >>> /* This must be called before any calls to HAS_PCH_* */ > >>> intel_detect_pch(dev_priv); > >>> > >>> diff --git a/drivers/gpu/drm/i915/i915_drv.h > >>> b/drivers/gpu/drm/i915/i915_drv.h > >>> index e9ee4daa9320..f9f0c3ba6e4a 100644 > >>> --- a/drivers/gpu/drm/i915/i915_drv.h > >>> +++ b/drivers/gpu/drm/i915/i915_drv.h > >>> @@ -91,6 +91,7 @@ > >>> #include "intel_wakeref.h" > >>> #include "intel_wopcm.h" > >>> > >>> +#include "i915_drm_client.h" > >>> #include "i915_gem.h" > >>> #include "i915_gem_gtt.h" > >>> #include "i915_gpu_error.h" > >>> @@ -226,6 +227,8 @@ struct drm_i915_file_private { > >>> /** ban_score: Accumulated score of all ctx bans and fast > >>> hangs. */ > >>> atomic_t ban_score; > >>> unsigned long hang_timestamp; > >>> + > >>> + struct i915_drm_client *client; > >>> }; > >>> > >>> /* Interface history: > >>> @@ -1201,6 +1204,8 @@ struct drm_i915_private { > >>> > >>> struct i915_pmu pmu; > >>> > >>> + struct i915_drm_clients clients; > >>> + > >>> struct i915_hdcp_comp_master *hdcp_master; > >>> bool hdcp_comp_added; > >>> > >>> diff --git a/drivers/gpu/drm/i915/i915_gem.c > >>> b/drivers/gpu/drm/i915/i915_gem.c > >>> index 0cbcb9f54e7d..5a0b5fae8b92 100644 > >>> --- a/drivers/gpu/drm/i915/i915_gem.c > >>> +++ b/drivers/gpu/drm/i915/i915_gem.c > >>> @@ -1234,6 +1234,8 @@ void i915_gem_cleanup_early(struct > >>> drm_i915_private *dev_priv) > >>> GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); > >>> GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); > >>> drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count); > >>> + drm_WARN_ON(&dev_priv->drm, > >>> !xa_empty(&dev_priv->clients.xarray)); > >>> + xa_destroy(&dev_priv->clients.xarray); > >>> } > >>> > >>> int i915_gem_freeze(struct drm_i915_private *dev_priv) > >>> @@ -1288,6 +1290,8 @@ void i915_gem_release(struct drm_device *dev, > >>> struct drm_file *file) > >>> struct drm_i915_file_private *file_priv = file->driver_priv; > >>> struct i915_request *request; > >>> > >>> + i915_drm_client_close(file_priv->client); > >>> + > >>> /* Clean up our request list when the client is going away, > >>> so that > >>> * later retire_requests won't dereference our soon-to-be-gone > >>> * file_priv. > >>> @@ -1301,17 +1305,25 @@ void i915_gem_release(struct drm_device *dev, > >>> struct drm_file *file) > >>> int i915_gem_open(struct drm_i915_private *i915, struct drm_file > >>> *file) > >>> { > >>> struct drm_i915_file_private *file_priv; > >>> - int ret; > >>> + struct i915_drm_client *client; > >>> + int ret = -ENOMEM; > >>> > >>> DRM_DEBUG("\n"); > >>> > >>> file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); > >>> if (!file_priv) > >>> - return -ENOMEM; > >>> + goto err_alloc; > >>> + > >>> + client = i915_drm_client_add(&i915->clients, current); > >>> + if (IS_ERR(client)) { > >>> + ret = PTR_ERR(client); > >>> + goto err_client; > >>> + } > >>> > >>> file->driver_priv = file_priv; > >>> file_priv->dev_priv = i915; > >>> file_priv->file = file; > >>> + file_priv->client = client; > >>> > >>> spin_lock_init(&file_priv->mm.lock); > >>> INIT_LIST_HEAD(&file_priv->mm.request_list); > >>> @@ -1321,8 +1333,15 @@ int i915_gem_open(struct drm_i915_private > >>> *i915, struct drm_file *file) > >>> > >>> ret = i915_gem_context_open(i915, file); > >>> if (ret) > >>> - kfree(file_priv); > >>> + goto err_context; > >>> + > >>> + return 0; > >>> > >>> +err_context: > >>> + i915_drm_client_close(client); > >>> +err_client: > >>> + kfree(file_priv); > >>> +err_alloc: > >>> return ret; > >>> } > >>> > >>> diff --git a/drivers/gpu/drm/i915/i915_sysfs.c > >>> b/drivers/gpu/drm/i915/i915_sysfs.c > >>> index 45d32ef42787..b7d4a6d2dd5c 100644 > >>> --- a/drivers/gpu/drm/i915/i915_sysfs.c > >>> +++ b/drivers/gpu/drm/i915/i915_sysfs.c > >>> @@ -560,6 +560,11 @@ void i915_setup_sysfs(struct drm_i915_private > >>> *dev_priv) > >>> struct device *kdev = dev_priv->drm.primary->kdev; > >>> int ret; > >>> > >>> + dev_priv->clients.root = > >>> + kobject_create_and_add("clients", &kdev->kobj); > >>> + if (!dev_priv->clients.root) > >>> + DRM_ERROR("Per-client sysfs setup failed\n"); > >>> + > >>> #ifdef CONFIG_PM > >>> if (HAS_RC6(dev_priv)) { > >>> ret = sysfs_merge_group(&kdev->kobj, > >>> @@ -627,4 +632,7 @@ void i915_teardown_sysfs(struct drm_i915_private > >>> *dev_priv) > >>> sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); > >>> sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); > >>> #endif > >>> + > >>> + if (dev_priv->clients.root) > >>> + kobject_put(dev_priv->clients.root); > >>> } > >>> -- > >>> 2.20.1 > >>> > >>> _______________________________________________ > >>> Intel-gfx mailing list > >>> Intel-gfx@lists.freedesktop.org > >>> https://lists.freedesktop.org/mailman/listinfo/intel-gfx _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs 2020-09-04 6:26 ` Lucas De Marchi @ 2020-09-04 13:03 ` Tvrtko Ursulin 0 siblings, 0 replies; 7+ messages in thread From: Tvrtko Ursulin @ 2020-09-04 13:03 UTC (permalink / raw) To: Lucas De Marchi; +Cc: Intel Graphics, Chris Wilson On 04/09/2020 07:26, Lucas De Marchi wrote: > On Tue, Sep 1, 2020 at 8:25 AM Tvrtko Ursulin > <tvrtko.ursulin@linux.intel.com> wrote: >> >> >> On 01/09/2020 16:09, Tvrtko Ursulin wrote: >>> >>> Hi, >>> >>> On 26/08/2020 02:11, Lucas De Marchi wrote: >>>> Hi, >>>> >>>> Any update on this? It now conflicts in a few places so it needs a >>>> rebase. >>> >>> I don't see any previous email on the topic - what kind of update, where >>> and how, are you looking for? Rebase against drm-tip so you pull it in? >>> Rebase against some internal in progress branch? >> >> Clearly you were after an update against drm-tip.. :) Problem here was >> no userspace but I can try to respin it. > > Yes, against drm-tip. I rebased it, but I think there is something > wrong with it. > If you can share your version I can do some tests. I've sent a series out just now. Tested it lightly (proper IGTs are still in progress) and it seems to work. Regards, Tvrtko _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply [flat|nested] 7+ messages in thread
* [Intel-gfx] [PATCH 0/9] Per client engine busyness
@ 2020-09-04 12:59 Tvrtko Ursulin
2020-09-04 12:59 ` [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs Tvrtko Ursulin
0 siblings, 1 reply; 7+ messages in thread
From: Tvrtko Ursulin @ 2020-09-04 12:59 UTC (permalink / raw)
To: Intel-gfx
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Another re-spin of the per-client engine busyness series. Highlights from this
version:
* Small fix for cyclic client id allocation.
* Otherwise just a rebase to catch up with drm-tip.
Internally we track time spent on engines for each struct intel_context. This
can serve as a building block for several features from the want list:
smarter scheduler decisions, getrusage(2)-like per-GEM-context functionality
wanted by some customers, cgroups controller, dynamic SSEU tuning,...
Externally, in sysfs, we expose time spent on GPU per client and per engine
class.
Sysfs interface enables us to implement a "top-like" tool for GPU tasks. Or with
a "screenshot":
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
intel-gpu-top - 906/ 955 MHz; 0% RC6; 5.30 Watts; 933 irqs/s
IMC reads: 4414 MiB/s
IMC writes: 3805 MiB/s
ENGINE BUSY MI_SEMA MI_WAIT
Render/3D/0 93.46% |████████████████████████████████▋ | 0% 0%
Blitter/0 0.00% | | 0% 0%
Video/0 0.00% | | 0% 0%
VideoEnhance/0 0.00% | | 0% 0%
PID NAME Render/3D Blitter Video VideoEnhance
2733 neverball |██████▌ || || || |
2047 Xorg |███▊ || || || |
2737 glxgears |█▍ || || || |
2128 xfwm4 | || || || |
2047 Xorg | || || || |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Implementation wise we add a a bunch of files in sysfs like:
# cd /sys/class/drm/card0/clients/
# tree
.
├── 7
│ ├── busy
│ │ ├── 0
│ │ ├── 1
│ │ ├── 2
│ │ └── 3
│ ├── name
│ └── pid
├── 8
│ ├── busy
│ │ ├── 0
│ │ ├── 1
│ │ ├── 2
│ │ └── 3
│ ├── name
│ └── pid
└── 9
├── busy
│ ├── 0
│ ├── 1
│ ├── 2
│ └── 3
├── name
└── pid
Files in 'busy' directories are numbered using the engine class ABI values and
they contain accumulated nanoseconds each client spent on engines of a
respective class.
Tvrtko Ursulin (9):
drm/i915: Expose list of clients in sysfs
drm/i915: Update client name on context create
drm/i915: Make GEM contexts track DRM clients
drm/i915: Track runtime spent in unreachable intel_contexts
drm/i915: Track runtime spent in closed GEM contexts
drm/i915: Track all user contexts per client
drm/i915: Expose per-engine client busyness
drm/i915: Track context current active time
drm/i915: Prefer software tracked context busyness
drivers/gpu/drm/i915/Makefile | 5 +-
drivers/gpu/drm/i915/gem/i915_gem_context.c | 56 ++-
.../gpu/drm/i915/gem/i915_gem_context_types.h | 21 +-
drivers/gpu/drm/i915/gt/intel_context.c | 11 +-
drivers/gpu/drm/i915/gt/intel_context.h | 6 +-
drivers/gpu/drm/i915/gt/intel_context_types.h | 24 +-
drivers/gpu/drm/i915/gt/intel_lrc.c | 57 ++-
drivers/gpu/drm/i915/gt/selftest_lrc.c | 10 +-
drivers/gpu/drm/i915/i915_debugfs.c | 29 +-
drivers/gpu/drm/i915/i915_drm_client.c | 432 ++++++++++++++++++
drivers/gpu/drm/i915/i915_drm_client.h | 94 ++++
drivers/gpu/drm/i915/i915_drv.c | 4 +
drivers/gpu/drm/i915/i915_drv.h | 5 +
drivers/gpu/drm/i915/i915_gem.c | 23 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 26 +-
drivers/gpu/drm/i915/i915_sysfs.c | 8 +
16 files changed, 732 insertions(+), 79 deletions(-)
create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c
create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h
--
2.25.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread* [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs 2020-09-04 12:59 [Intel-gfx] [PATCH 0/9] Per client engine busyness Tvrtko Ursulin @ 2020-09-04 12:59 ` Tvrtko Ursulin 0 siblings, 0 replies; 7+ messages in thread From: Tvrtko Ursulin @ 2020-09-04 12:59 UTC (permalink / raw) To: Intel-gfx; +Cc: Chris Wilson From: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Expose a list of clients with open file handles in sysfs. This will be a basis for a top-like utility showing per-client and per- engine GPU load. Currently we only expose each client's pid and name under opaque numbered directories in /sys/class/drm/card0/clients/. For instance: /sys/class/drm/card0/clients/3/name: Xorg /sys/class/drm/card0/clients/3/pid: 5664 v2: Chris Wilson: * Enclose new members into dedicated structs. * Protect against failed sysfs registration. v3: * sysfs_attr_init. v4: * Fix for internal clients. v5: * Use cyclic ida for client id. (Chris) * Do not leak pid reference. (Chris) * Tidy code with some locals. v6: * Use xa_alloc_cyclic to simplify locking. (Chris) * No need to unregister individial sysfs files. (Chris) * Rebase on top of fpriv kref. * Track client closed status and reflect in sysfs. v7: * Make drm_client more standalone concept. v8: * Simplify sysfs show. (Chris) * Always track name and pid. v9: * Fix cyclic id assignment. v10: * No need for a mutex around xa_alloc_cyclic. * Refactor sysfs into own function. * Unregister sysfs before freeing pid and name. * Move clients setup into own function. v11: * Call clients init directly from driver init. (Chris) v12: * Rebased after i915_gem_release removal. * Do not fail client add on id wrap. (Maciej) Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> # v11 --- drivers/gpu/drm/i915/Makefile | 5 +- drivers/gpu/drm/i915/i915_drm_client.c | 180 +++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drm_client.h | 65 +++++++++ drivers/gpu/drm/i915/i915_drv.c | 4 + drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 23 +++- drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ 7 files changed, 285 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index e5574e506a5c..250f004d92bb 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -34,8 +34,9 @@ subdir-ccflags-y += -I$(srctree)/$(src) # Please keep these build lists sorted! # core driver code -i915-y += i915_drv.o \ - i915_config.o \ +i915-y += i915_config.o \ + i915_drm_client.o \ + i915_drv.o \ i915_irq.o \ i915_getparam.o \ i915_params.o \ diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c new file mode 100644 index 000000000000..33f695c4596c --- /dev/null +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -0,0 +1,180 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2020 Intel Corporation + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/types.h> + +#include "i915_drm_client.h" +#include "i915_gem.h" +#include "i915_utils.h" + +void i915_drm_clients_init(struct i915_drm_clients *clients) +{ + clients->next_id = 0; + xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC); +} + +static ssize_t +show_client_name(struct device *kdev, struct device_attribute *attr, char *buf) +{ + struct i915_drm_client *client = + container_of(attr, typeof(*client), attr.name); + + return snprintf(buf, PAGE_SIZE, + READ_ONCE(client->closed) ? "<%s>" : "%s", + client->name); +} + +static ssize_t +show_client_pid(struct device *kdev, struct device_attribute *attr, char *buf) +{ + struct i915_drm_client *client = + container_of(attr, typeof(*client), attr.pid); + + return snprintf(buf, PAGE_SIZE, + READ_ONCE(client->closed) ? "<%u>" : "%u", + pid_nr(client->pid)); +} + +static int +__client_register_sysfs(struct i915_drm_client *client) +{ + const struct { + const char *name; + struct device_attribute *attr; + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf); + } files[] = { + { "name", &client->attr.name, show_client_name }, + { "pid", &client->attr.pid, show_client_pid }, + }; + unsigned int i; + char buf[16]; + int ret; + + ret = scnprintf(buf, sizeof(buf), "%u", client->id); + if (ret == sizeof(buf)) + return -EINVAL; + + client->root = kobject_create_and_add(buf, client->clients->root); + if (!client->root) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(files); i++) { + struct device_attribute *attr = files[i].attr; + + sysfs_attr_init(&attr->attr); + + attr->attr.name = files[i].name; + attr->attr.mode = 0444; + attr->show = files[i].show; + + ret = sysfs_create_file(client->root, (struct attribute *)attr); + if (ret) + break; + } + + if (ret) + kobject_put(client->root); + + return ret; +} + +static void __client_unregister_sysfs(struct i915_drm_client *client) +{ + kobject_put(fetch_and_zero(&client->root)); +} + +static int +__i915_drm_client_register(struct i915_drm_client *client, + struct task_struct *task) +{ + struct i915_drm_clients *clients = client->clients; + char *name; + int ret; + + name = kstrdup(task->comm, GFP_KERNEL); + if (!name) + return -ENOMEM; + + client->pid = get_task_pid(task, PIDTYPE_PID); + client->name = name; + + if (!clients->root) + return 0; /* intel_fbdev_init registers a client before sysfs */ + + ret = __client_register_sysfs(client); + if (ret) + goto err_sysfs; + + return 0; + +err_sysfs: + put_pid(client->pid); + kfree(client->name); + + return ret; +} + +static void +__i915_drm_client_unregister(struct i915_drm_client *client) +{ + __client_unregister_sysfs(client); + + put_pid(fetch_and_zero(&client->pid)); + kfree(fetch_and_zero(&client->name)); +} + +struct i915_drm_client * +i915_drm_client_add(struct i915_drm_clients *clients, struct task_struct *task) +{ + struct i915_drm_client *client; + int ret; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + kref_init(&client->kref); + client->clients = clients; + + ret = xa_alloc_cyclic(&clients->xarray, &client->id, client, + xa_limit_32b, &clients->next_id, GFP_KERNEL); + if (ret < 0) + goto err_id; + + ret = __i915_drm_client_register(client, task); + if (ret) + goto err_register; + + return client; + +err_register: + xa_erase(&clients->xarray, client->id); +err_id: + kfree(client); + + return ERR_PTR(ret); +} + +void __i915_drm_client_free(struct kref *kref) +{ + struct i915_drm_client *client = + container_of(kref, typeof(*client), kref); + + __i915_drm_client_unregister(client); + xa_erase(&client->clients->xarray, client->id); + kfree_rcu(client, rcu); +} + +void i915_drm_client_close(struct i915_drm_client *client) +{ + GEM_BUG_ON(READ_ONCE(client->closed)); + WRITE_ONCE(client->closed, true); + i915_drm_client_put(client); +} diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h new file mode 100644 index 000000000000..5009a2ae4b65 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright © 2020 Intel Corporation + */ + +#ifndef __I915_DRM_CLIENT_H__ +#define __I915_DRM_CLIENT_H__ + +#include <linux/device.h> +#include <linux/kobject.h> +#include <linux/kref.h> +#include <linux/pid.h> +#include <linux/rcupdate.h> +#include <linux/sched.h> +#include <linux/xarray.h> + +struct i915_drm_clients { + struct xarray xarray; + u32 next_id; + + struct kobject *root; +}; + +struct i915_drm_client { + struct kref kref; + + struct rcu_head rcu; + + unsigned int id; + struct pid *pid; + char *name; + bool closed; + + struct i915_drm_clients *clients; + + struct kobject *root; + struct { + struct device_attribute pid; + struct device_attribute name; + } attr; +}; + +void i915_drm_clients_init(struct i915_drm_clients *clients); + +static inline struct i915_drm_client * +i915_drm_client_get(struct i915_drm_client *client) +{ + kref_get(&client->kref); + return client; +} + +void __i915_drm_client_free(struct kref *kref); + +static inline void i915_drm_client_put(struct i915_drm_client *client) +{ + kref_put(&client->kref, __i915_drm_client_free); +} + +void i915_drm_client_close(struct i915_drm_client *client); + +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients, + struct task_struct *task); + +#endif /* !__I915_DRM_CLIENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 00292a849c34..28fcd3ab654b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -70,6 +70,7 @@ #include "gt/intel_rc6.h" #include "i915_debugfs.h" +#include "i915_drm_client.h" #include "i915_drv.h" #include "i915_ioc32.h" #include "i915_irq.h" @@ -459,6 +460,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) i915_gem_init_early(dev_priv); + i915_drm_clients_init(&dev_priv->clients); + /* This must be called before any calls to HAS_PCH_* */ intel_detect_pch(dev_priv); @@ -1120,6 +1123,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; i915_gem_context_close(file); + i915_drm_client_close(file_priv->client); kfree_rcu(file_priv, rcu); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a455752221cc..54fac8cab520 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -91,6 +91,7 @@ #include "intel_wakeref.h" #include "intel_wopcm.h" +#include "i915_drm_client.h" #include "i915_gem.h" #include "i915_gem_gtt.h" #include "i915_gpu_error.h" @@ -223,6 +224,8 @@ struct drm_i915_file_private { /** ban_score: Accumulated score of all ctx bans and fast hangs. */ atomic_t ban_score; unsigned long hang_timestamp; + + struct i915_drm_client *client; }; /* Interface history: @@ -1219,6 +1222,8 @@ struct drm_i915_private { struct i915_pmu pmu; + struct i915_drm_clients clients; + struct i915_hdcp_comp_master *hdcp_master; bool hdcp_comp_added; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bb0c12975f38..39182c85c5b7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1267,6 +1267,8 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv) GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count); + drm_WARN_ON(&dev_priv->drm, !xa_empty(&dev_priv->clients.xarray)); + xa_destroy(&dev_priv->clients.xarray); } int i915_gem_freeze(struct drm_i915_private *dev_priv) @@ -1319,25 +1321,40 @@ int i915_gem_freeze_late(struct drm_i915_private *i915) int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) { struct drm_i915_file_private *file_priv; - int ret; + struct i915_drm_client *client; + int ret = -ENOMEM; DRM_DEBUG("\n"); file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); if (!file_priv) - return -ENOMEM; + goto err_alloc; + + client = i915_drm_client_add(&i915->clients, current); + if (IS_ERR(client)) { + ret = PTR_ERR(client); + goto err_client; + } file->driver_priv = file_priv; file_priv->dev_priv = i915; file_priv->file = file; + file_priv->client = client; file_priv->bsd_engine = -1; file_priv->hang_timestamp = jiffies; ret = i915_gem_context_open(i915, file); if (ret) - kfree(file_priv); + goto err_context; + + return 0; +err_context: + i915_drm_client_close(client); +err_client: + kfree(file_priv); +err_alloc: return ret; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 45d32ef42787..b7d4a6d2dd5c 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -560,6 +560,11 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) struct device *kdev = dev_priv->drm.primary->kdev; int ret; + dev_priv->clients.root = + kobject_create_and_add("clients", &kdev->kobj); + if (!dev_priv->clients.root) + DRM_ERROR("Per-client sysfs setup failed\n"); + #ifdef CONFIG_PM if (HAS_RC6(dev_priv)) { ret = sysfs_merge_group(&kdev->kobj, @@ -627,4 +632,7 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); #endif + + if (dev_priv->clients.root) + kobject_put(dev_priv->clients.root); } -- 2.25.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply related [flat|nested] 7+ messages in thread
* [Intel-gfx] [PATCH 0/9] Per client engine busyness
@ 2020-09-14 13:12 Tvrtko Ursulin
2020-09-14 13:12 ` [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs Tvrtko Ursulin
0 siblings, 1 reply; 7+ messages in thread
From: Tvrtko Ursulin @ 2020-09-14 13:12 UTC (permalink / raw)
To: Intel-gfx
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Another re-spin of the per-client engine busyness series. Highlights from this
version:
* Make sure i915_gem_context is fully initialized before adding to
gem.contexts.list.
* A couple checkpatch warnings.
Internally we track time spent on engines for each struct intel_context. This
can serve as a building block for several features from the want list:
smarter scheduler decisions, getrusage(2)-like per-GEM-context functionality
wanted by some customers, cgroups controller, dynamic SSEU tuning,...
Externally, in sysfs, we expose time spent on GPU per client and per engine
class.
Sysfs interface enables us to implement a "top-like" tool for GPU tasks. Or with
a "screenshot":
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
intel-gpu-top - 906/ 955 MHz; 0% RC6; 5.30 Watts; 933 irqs/s
IMC reads: 4414 MiB/s
IMC writes: 3805 MiB/s
ENGINE BUSY MI_SEMA MI_WAIT
Render/3D/0 93.46% |████████████████████████████████▋ | 0% 0%
Blitter/0 0.00% | | 0% 0%
Video/0 0.00% | | 0% 0%
VideoEnhance/0 0.00% | | 0% 0%
PID NAME Render/3D Blitter Video VideoEnhance
2733 neverball |██████▌ || || || |
2047 Xorg |███▊ || || || |
2737 glxgears |█▍ || || || |
2128 xfwm4 | || || || |
2047 Xorg | || || || |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Implementation wise we add a a bunch of files in sysfs like:
# cd /sys/class/drm/card0/clients/
# tree
.
├── 7
│ ├── busy
│ │ ├── 0
│ │ ├── 1
│ │ ├── 2
│ │ └── 3
│ ├── name
│ └── pid
├── 8
│ ├── busy
│ │ ├── 0
│ │ ├── 1
│ │ ├── 2
│ │ └── 3
│ ├── name
│ └── pid
└── 9
├── busy
│ ├── 0
│ ├── 1
│ ├── 2
│ └── 3
├── name
└── pid
Files in 'busy' directories are numbered using the engine class ABI values and
they contain accumulated nanoseconds each client spent on engines of a
respective class.
Tvrtko Ursulin (9):
drm/i915: Expose list of clients in sysfs
drm/i915: Update client name on context create
drm/i915: Make GEM contexts track DRM clients
drm/i915: Track runtime spent in unreachable intel_contexts
drm/i915: Track runtime spent in closed GEM contexts
drm/i915: Track all user contexts per client
drm/i915: Expose per-engine client busyness
drm/i915: Track context current active time
drm/i915: Prefer software tracked context busyness
drivers/gpu/drm/i915/Makefile | 5 +-
drivers/gpu/drm/i915/gem/i915_gem_context.c | 56 ++-
.../gpu/drm/i915/gem/i915_gem_context_types.h | 21 +-
drivers/gpu/drm/i915/gt/intel_context.c | 11 +-
drivers/gpu/drm/i915/gt/intel_context.h | 6 +-
drivers/gpu/drm/i915/gt/intel_context_types.h | 24 +-
drivers/gpu/drm/i915/gt/intel_lrc.c | 57 ++-
drivers/gpu/drm/i915/gt/selftest_lrc.c | 10 +-
drivers/gpu/drm/i915/i915_debugfs.c | 29 +-
drivers/gpu/drm/i915/i915_drm_client.c | 434 ++++++++++++++++++
drivers/gpu/drm/i915/i915_drm_client.h | 93 ++++
drivers/gpu/drm/i915/i915_drv.c | 4 +
drivers/gpu/drm/i915/i915_drv.h | 5 +
drivers/gpu/drm/i915/i915_gem.c | 23 +-
drivers/gpu/drm/i915/i915_gpu_error.c | 26 +-
drivers/gpu/drm/i915/i915_sysfs.c | 8 +
16 files changed, 733 insertions(+), 79 deletions(-)
create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c
create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h
--
2.25.1
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply [flat|nested] 7+ messages in thread* [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs 2020-09-14 13:12 [Intel-gfx] [PATCH 0/9] Per client engine busyness Tvrtko Ursulin @ 2020-09-14 13:12 ` Tvrtko Ursulin 0 siblings, 0 replies; 7+ messages in thread From: Tvrtko Ursulin @ 2020-09-14 13:12 UTC (permalink / raw) To: Intel-gfx From: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Expose a list of clients with open file handles in sysfs. This will be a basis for a top-like utility showing per-client and per- engine GPU load. Currently we only expose each client's pid and name under opaque numbered directories in /sys/class/drm/card0/clients/. For instance: /sys/class/drm/card0/clients/3/name: Xorg /sys/class/drm/card0/clients/3/pid: 5664 v2: Chris Wilson: * Enclose new members into dedicated structs. * Protect against failed sysfs registration. v3: * sysfs_attr_init. v4: * Fix for internal clients. v5: * Use cyclic ida for client id. (Chris) * Do not leak pid reference. (Chris) * Tidy code with some locals. v6: * Use xa_alloc_cyclic to simplify locking. (Chris) * No need to unregister individial sysfs files. (Chris) * Rebase on top of fpriv kref. * Track client closed status and reflect in sysfs. v7: * Make drm_client more standalone concept. v8: * Simplify sysfs show. (Chris) * Always track name and pid. v9: * Fix cyclic id assignment. v10: * No need for a mutex around xa_alloc_cyclic. * Refactor sysfs into own function. * Unregister sysfs before freeing pid and name. * Move clients setup into own function. v11: * Call clients init directly from driver init. (Chris) v12: * Rebased after i915_gem_release removal. * Do not fail client add on id wrap. (Maciej) Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> # v11 --- drivers/gpu/drm/i915/Makefile | 5 +- drivers/gpu/drm/i915/i915_drm_client.c | 179 +++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drm_client.h | 64 +++++++++ drivers/gpu/drm/i915/i915_drv.c | 4 + drivers/gpu/drm/i915/i915_drv.h | 5 + drivers/gpu/drm/i915/i915_gem.c | 23 +++- drivers/gpu/drm/i915/i915_sysfs.c | 8 ++ 7 files changed, 283 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_drm_client.c create mode 100644 drivers/gpu/drm/i915/i915_drm_client.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index e5574e506a5c..250f004d92bb 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -34,8 +34,9 @@ subdir-ccflags-y += -I$(srctree)/$(src) # Please keep these build lists sorted! # core driver code -i915-y += i915_drv.o \ - i915_config.o \ +i915-y += i915_config.o \ + i915_drm_client.o \ + i915_drv.o \ i915_irq.o \ i915_getparam.o \ i915_params.o \ diff --git a/drivers/gpu/drm/i915/i915_drm_client.c b/drivers/gpu/drm/i915/i915_drm_client.c new file mode 100644 index 000000000000..137a5744f9c6 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_drm_client.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2020 Intel Corporation + */ + +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/types.h> + +#include "i915_drm_client.h" +#include "i915_gem.h" +#include "i915_utils.h" + +void i915_drm_clients_init(struct i915_drm_clients *clients) +{ + clients->next_id = 0; + xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC); +} + +static ssize_t +show_client_name(struct device *kdev, struct device_attribute *attr, char *buf) +{ + struct i915_drm_client *client = + container_of(attr, typeof(*client), attr.name); + + return snprintf(buf, PAGE_SIZE, + READ_ONCE(client->closed) ? "<%s>" : "%s", + client->name); +} + +static ssize_t +show_client_pid(struct device *kdev, struct device_attribute *attr, char *buf) +{ + struct i915_drm_client *client = + container_of(attr, typeof(*client), attr.pid); + + return snprintf(buf, PAGE_SIZE, + READ_ONCE(client->closed) ? "<%u>" : "%u", + pid_nr(client->pid)); +} + +static int +__client_register_sysfs(struct i915_drm_client *client) +{ + const struct { + const char *name; + struct device_attribute *attr; + ssize_t (*show)(struct device *dev, + struct device_attribute *attr, + char *buf); + } files[] = { + { "name", &client->attr.name, show_client_name }, + { "pid", &client->attr.pid, show_client_pid }, + }; + unsigned int i; + char buf[16]; + int ret; + + ret = scnprintf(buf, sizeof(buf), "%u", client->id); + if (ret == sizeof(buf)) + return -EINVAL; + + client->root = kobject_create_and_add(buf, client->clients->root); + if (!client->root) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(files); i++) { + struct device_attribute *attr = files[i].attr; + + sysfs_attr_init(&attr->attr); + + attr->attr.name = files[i].name; + attr->attr.mode = 0444; + attr->show = files[i].show; + + ret = sysfs_create_file(client->root, (struct attribute *)attr); + if (ret) + break; + } + + if (ret) + kobject_put(client->root); + + return ret; +} + +static void __client_unregister_sysfs(struct i915_drm_client *client) +{ + kobject_put(fetch_and_zero(&client->root)); +} + +static int +__i915_drm_client_register(struct i915_drm_client *client, + struct task_struct *task) +{ + struct i915_drm_clients *clients = client->clients; + char *name; + int ret; + + name = kstrdup(task->comm, GFP_KERNEL); + if (!name) + return -ENOMEM; + + client->pid = get_task_pid(task, PIDTYPE_PID); + client->name = name; + + if (!clients->root) + return 0; /* intel_fbdev_init registers a client before sysfs */ + + ret = __client_register_sysfs(client); + if (ret) + goto err_sysfs; + + return 0; + +err_sysfs: + put_pid(client->pid); + kfree(client->name); + + return ret; +} + +static void +__i915_drm_client_unregister(struct i915_drm_client *client) +{ + __client_unregister_sysfs(client); + + put_pid(fetch_and_zero(&client->pid)); + kfree(fetch_and_zero(&client->name)); +} + +struct i915_drm_client * +i915_drm_client_add(struct i915_drm_clients *clients, struct task_struct *task) +{ + struct i915_drm_client *client; + int ret; + + client = kzalloc(sizeof(*client), GFP_KERNEL); + if (!client) + return ERR_PTR(-ENOMEM); + + kref_init(&client->kref); + client->clients = clients; + + ret = xa_alloc_cyclic(&clients->xarray, &client->id, client, + xa_limit_32b, &clients->next_id, GFP_KERNEL); + if (ret < 0) + goto err_id; + + ret = __i915_drm_client_register(client, task); + if (ret) + goto err_register; + + return client; + +err_register: + xa_erase(&clients->xarray, client->id); +err_id: + kfree(client); + + return ERR_PTR(ret); +} + +void __i915_drm_client_free(struct kref *kref) +{ + struct i915_drm_client *client = + container_of(kref, typeof(*client), kref); + + __i915_drm_client_unregister(client); + xa_erase(&client->clients->xarray, client->id); + kfree_rcu(client, rcu); +} + +void i915_drm_client_close(struct i915_drm_client *client) +{ + GEM_BUG_ON(READ_ONCE(client->closed)); + WRITE_ONCE(client->closed, true); + i915_drm_client_put(client); +} diff --git a/drivers/gpu/drm/i915/i915_drm_client.h b/drivers/gpu/drm/i915/i915_drm_client.h new file mode 100644 index 000000000000..af6998c74d4c --- /dev/null +++ b/drivers/gpu/drm/i915/i915_drm_client.h @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2020 Intel Corporation + */ + +#ifndef __I915_DRM_CLIENT_H__ +#define __I915_DRM_CLIENT_H__ + +#include <linux/device.h> +#include <linux/kobject.h> +#include <linux/kref.h> +#include <linux/pid.h> +#include <linux/rcupdate.h> +#include <linux/sched.h> +#include <linux/xarray.h> + +struct i915_drm_clients { + struct xarray xarray; + u32 next_id; + + struct kobject *root; +}; + +struct i915_drm_client { + struct kref kref; + + struct rcu_head rcu; + + unsigned int id; + struct pid *pid; + char *name; + bool closed; + + struct i915_drm_clients *clients; + + struct kobject *root; + struct { + struct device_attribute pid; + struct device_attribute name; + } attr; +}; + +void i915_drm_clients_init(struct i915_drm_clients *clients); + +static inline struct i915_drm_client * +i915_drm_client_get(struct i915_drm_client *client) +{ + kref_get(&client->kref); + return client; +} + +void __i915_drm_client_free(struct kref *kref); + +static inline void i915_drm_client_put(struct i915_drm_client *client) +{ + kref_put(&client->kref, __i915_drm_client_free); +} + +void i915_drm_client_close(struct i915_drm_client *client); + +struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients, + struct task_struct *task); + +#endif /* !__I915_DRM_CLIENT_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 94e00e450683..4a16edfe5b6b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -69,6 +69,7 @@ #include "gt/intel_rc6.h" #include "i915_debugfs.h" +#include "i915_drm_client.h" #include "i915_drv.h" #include "i915_ioc32.h" #include "i915_irq.h" @@ -339,6 +340,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) i915_gem_init_early(dev_priv); + i915_drm_clients_init(&dev_priv->clients); + /* This must be called before any calls to HAS_PCH_* */ intel_detect_pch(dev_priv); @@ -1017,6 +1020,7 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) struct drm_i915_file_private *file_priv = file->driver_priv; i915_gem_context_close(file); + i915_drm_client_close(file_priv->client); kfree_rcu(file_priv, rcu); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ef75acda9bff..e548ff3b85f9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -91,6 +91,7 @@ #include "intel_wakeref.h" #include "intel_wopcm.h" +#include "i915_drm_client.h" #include "i915_gem.h" #include "i915_gem_gtt.h" #include "i915_gpu_error.h" @@ -223,6 +224,8 @@ struct drm_i915_file_private { /** ban_score: Accumulated score of all ctx bans and fast hangs. */ atomic_t ban_score; unsigned long hang_timestamp; + + struct i915_drm_client *client; }; /* Interface history: @@ -1217,6 +1220,8 @@ struct drm_i915_private { struct i915_pmu pmu; + struct i915_drm_clients clients; + struct i915_hdcp_comp_master *hdcp_master; bool hdcp_comp_added; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index bb0c12975f38..39182c85c5b7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1267,6 +1267,8 @@ void i915_gem_cleanup_early(struct drm_i915_private *dev_priv) GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list)); GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count)); drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count); + drm_WARN_ON(&dev_priv->drm, !xa_empty(&dev_priv->clients.xarray)); + xa_destroy(&dev_priv->clients.xarray); } int i915_gem_freeze(struct drm_i915_private *dev_priv) @@ -1319,25 +1321,40 @@ int i915_gem_freeze_late(struct drm_i915_private *i915) int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file) { struct drm_i915_file_private *file_priv; - int ret; + struct i915_drm_client *client; + int ret = -ENOMEM; DRM_DEBUG("\n"); file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL); if (!file_priv) - return -ENOMEM; + goto err_alloc; + + client = i915_drm_client_add(&i915->clients, current); + if (IS_ERR(client)) { + ret = PTR_ERR(client); + goto err_client; + } file->driver_priv = file_priv; file_priv->dev_priv = i915; file_priv->file = file; + file_priv->client = client; file_priv->bsd_engine = -1; file_priv->hang_timestamp = jiffies; ret = i915_gem_context_open(i915, file); if (ret) - kfree(file_priv); + goto err_context; + + return 0; +err_context: + i915_drm_client_close(client); +err_client: + kfree(file_priv); +err_alloc: return ret; } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 45d32ef42787..b7d4a6d2dd5c 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -560,6 +560,11 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) struct device *kdev = dev_priv->drm.primary->kdev; int ret; + dev_priv->clients.root = + kobject_create_and_add("clients", &kdev->kobj); + if (!dev_priv->clients.root) + DRM_ERROR("Per-client sysfs setup failed\n"); + #ifdef CONFIG_PM if (HAS_RC6(dev_priv)) { ret = sysfs_merge_group(&kdev->kobj, @@ -627,4 +632,7 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); #endif + + if (dev_priv->clients.root) + kobject_put(dev_priv->clients.root); } -- 2.25.1 _______________________________________________ Intel-gfx mailing list Intel-gfx@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-09-14 13:13 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20200415101138.26126-1-tvrtko.ursulin@linux.intel.com>
[not found] ` <20200415101138.26126-2-tvrtko.ursulin@linux.intel.com>
2020-08-26 1:11 ` [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs Lucas De Marchi
2020-09-01 15:09 ` Tvrtko Ursulin
2020-09-01 15:25 ` Tvrtko Ursulin
2020-09-04 6:26 ` Lucas De Marchi
2020-09-04 13:03 ` Tvrtko Ursulin
2020-09-04 12:59 [Intel-gfx] [PATCH 0/9] Per client engine busyness Tvrtko Ursulin
2020-09-04 12:59 ` [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs Tvrtko Ursulin
-- strict thread matches above, loose matches on Subject: below --
2020-09-14 13:12 [Intel-gfx] [PATCH 0/9] Per client engine busyness Tvrtko Ursulin
2020-09-14 13:12 ` [Intel-gfx] [PATCH 1/9] drm/i915: Expose list of clients in sysfs Tvrtko Ursulin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox