Commit 5f0d4d14 authored by Tvrtko Ursulin's avatar Tvrtko Ursulin
Browse files

drm/i915: Explicitly track DRM clients



Tracking DRM clients more explicitly will allow later patches to
accumulate past and current GPU usage in a centralised place and also
consolidate access to owning task pid/name.

Unique client id is also assigned for the purpose of distinguishing/
consolidating between multiple file descriptors owned by the same process.

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:
 * Do not fail client add on id wrap. (Maciej)

v13 (Lucas): Rebase.

v14:
 * Dropped sysfs bits.

v15:
 * Dropped tracking of pid/ and name.
 * Dropped RCU freeing of the client object.

Signed-off-by: default avatarTvrtko Ursulin <tvrtko.ursulin@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> # v11
Reviewed-by: Aravind Iddamsetty <aravind.iddamsetty@intel.com> # v11
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarUmesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220401142205.3123159-2-tvrtko.ursulin@linux.intel.com
parent 3f654e14
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ subdir-ccflags-y += -I$(srctree)/$(src)

# core driver code
i915-y += i915_driver.o \
	  i915_drm_client.o \
	  i915_config.o \
	  i915_getparam.o \
	  i915_ioctl.o \
+6 −0
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@
#include "i915_file_private.h"
#include "i915_debugfs.h"
#include "i915_driver.h"
#include "i915_drm_client.h"
#include "i915_drv.h"
#include "i915_getparam.h"
#include "i915_ioc32.h"
@@ -353,6 +354,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)

	intel_root_gt_init_early(dev_priv);

	i915_drm_clients_init(&dev_priv->clients, dev_priv);

	i915_gem_init_early(dev_priv);

	/* This must be called before any calls to HAS_PCH_* */
@@ -373,6 +376,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
err_gem:
	i915_gem_cleanup_early(dev_priv);
	intel_gt_driver_late_release_all(dev_priv);
	i915_drm_clients_fini(&dev_priv->clients);
	intel_region_ttm_device_fini(dev_priv);
err_ttm:
	vlv_suspend_cleanup(dev_priv);
@@ -392,6 +396,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv)
	intel_power_domains_cleanup(dev_priv);
	i915_gem_cleanup_early(dev_priv);
	intel_gt_driver_late_release_all(dev_priv);
	i915_drm_clients_fini(&dev_priv->clients);
	intel_region_ttm_device_fini(dev_priv);
	vlv_suspend_cleanup(dev_priv);
	i915_workqueues_cleanup(dev_priv);
@@ -1006,6 +1011,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_put(file_priv->client);

	kfree_rcu(file_priv, rcu);

+68 −0
Original line number Diff line number Diff line
// 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,
			   struct drm_i915_private *i915)
{
	clients->i915 = i915;
	clients->next_id = 0;

	xa_init_flags(&clients->xarray, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_IRQ);
}

struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients)
{
	struct i915_drm_client *client;
	struct xarray *xa = &clients->xarray;
	int ret;

	client = kzalloc(sizeof(*client), GFP_KERNEL);
	if (!client)
		return ERR_PTR(-ENOMEM);

	xa_lock_irq(xa);
	ret = __xa_alloc_cyclic(xa, &client->id, client, xa_limit_32b,
				&clients->next_id, GFP_KERNEL);
	xa_unlock_irq(xa);
	if (ret < 0)
		goto err;

	kref_init(&client->kref);
	client->clients = clients;

	return client;

err:
	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);
	struct xarray *xa = &client->clients->xarray;
	unsigned long flags;

	xa_lock_irqsave(xa, flags);
	__xa_erase(xa, client->id);
	xa_unlock_irqrestore(xa, flags);
	kfree(client);
}

void i915_drm_clients_fini(struct i915_drm_clients *clients)
{
	GEM_BUG_ON(!xa_empty(&clients->xarray));
	xa_destroy(&clients->xarray);
}
+50 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: MIT */
/*
 * Copyright © 2020 Intel Corporation
 */

#ifndef __I915_DRM_CLIENT_H__
#define __I915_DRM_CLIENT_H__

#include <linux/kref.h>
#include <linux/xarray.h>

struct drm_i915_private;

struct i915_drm_clients {
	struct drm_i915_private *i915;

	struct xarray xarray;
	u32 next_id;
};

struct i915_drm_client {
	struct kref kref;

	unsigned int id;

	struct i915_drm_clients *clients;
};

void i915_drm_clients_init(struct i915_drm_clients *clients,
			   struct drm_i915_private *i915);

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);
}

struct i915_drm_client *i915_drm_client_add(struct i915_drm_clients *clients);

void i915_drm_clients_fini(struct i915_drm_clients *clients);

#endif /* !__I915_DRM_CLIENT_H__ */
+3 −0
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@
#include "gt/intel_workarounds.h"
#include "gt/uc/intel_uc.h"

#include "i915_drm_client.h"
#include "i915_gem.h"
#include "i915_gpu_error.h"
#include "i915_params.h"
@@ -854,6 +855,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;

Loading