All of lore.kernel.org
 help / color / mirror / Atom feed
From: Viresh Kumar <viresh.kumar@linaro.org>
To: Rob Clark <robdclark@gmail.com>
Cc: Daniel Vetter <daniel@ffwll.ch>,
	dri-devel <dri-devel@lists.freedesktop.org>,
	Rob Clark <robdclark@chromium.org>, Sean Paul <sean@poorly.run>,
	David Airlie <airlied@linux.ie>,
	"open list:DRM DRIVER FOR MSM ADRENO GPU" 
	<linux-arm-msm@vger.kernel.org>,
	"open list:DRM DRIVER FOR MSM ADRENO GPU" 
	<freedreno@lists.freedesktop.org>,
	open list <linux-kernel@vger.kernel.org>,
	"Menon, Nishanth" <nm@ti.com>
Subject: Re: [PATCH v2 07/22] drm/msm: Do rpm get sooner in the submit path
Date: Tue, 3 Nov 2020 11:17:15 +0530	[thread overview]
Message-ID: <20201103054715.4l5j57pyjz6zd6ed@vireshk-i7> (raw)
In-Reply-To: <20201027113532.nriqqws7gdcu5su6@vireshk-i7>

On 27-10-20, 17:05, Viresh Kumar wrote:
> It isn't that straight forward unfortunately, we need to make sure the
> table doesn't get allocated for the same device twice, so
> find+allocate needs to happen within a locked region.
> 
> I have taken, not so straight forward, approach to fixing this issue,
> lets see if this fixes it or not.
> 
> -------------------------8<-------------------------
> 
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 4ac4e7ce6b8b..6f4a73a6391f 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -29,6 +29,8 @@
>  LIST_HEAD(opp_tables);
>  /* Lock to allow exclusive modification to the device and opp lists */
>  DEFINE_MUTEX(opp_table_lock);
> +/* Flag indicating that opp_tables list is being updated at the moment */
> +static bool opp_tables_busy;
>  
>  static struct opp_device *_find_opp_dev(const struct device *dev,
>  					struct opp_table *opp_table)
> @@ -1036,8 +1038,8 @@ static void _remove_opp_dev(struct opp_device *opp_dev,
>  	kfree(opp_dev);
>  }
>  
> -static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
> -						struct opp_table *opp_table)
> +struct opp_device *_add_opp_dev(const struct device *dev,
> +				struct opp_table *opp_table)
>  {
>  	struct opp_device *opp_dev;
>  
> @@ -1048,7 +1050,9 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
>  	/* Initialize opp-dev */
>  	opp_dev->dev = dev;
>  
> +	mutex_lock(&opp_table->lock);
>  	list_add(&opp_dev->node, &opp_table->dev_list);
> +	mutex_unlock(&opp_table->lock);
>  
>  	/* Create debugfs entries for the opp_table */
>  	opp_debug_register(opp_dev, opp_table);
> @@ -1056,18 +1060,6 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
>  	return opp_dev;
>  }
>  
> -struct opp_device *_add_opp_dev(const struct device *dev,
> -				struct opp_table *opp_table)
> -{
> -	struct opp_device *opp_dev;
> -
> -	mutex_lock(&opp_table->lock);
> -	opp_dev = _add_opp_dev_unlocked(dev, opp_table);
> -	mutex_unlock(&opp_table->lock);
> -
> -	return opp_dev;
> -}
> -
>  static struct opp_table *_allocate_opp_table(struct device *dev, int index)
>  {
>  	struct opp_table *opp_table;
> @@ -1121,8 +1113,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
>  	INIT_LIST_HEAD(&opp_table->opp_list);
>  	kref_init(&opp_table->kref);
>  
> -	/* Secure the device table modification */
> -	list_add(&opp_table->node, &opp_tables);
>  	return opp_table;
>  
>  err:
> @@ -1135,27 +1125,64 @@ void _get_opp_table_kref(struct opp_table *opp_table)
>  	kref_get(&opp_table->kref);
>  }
>  
> +/*
> + * We need to make sure that the OPP table for a device doesn't get added twice,
> + * if this routine gets called in parallel with the same device pointer.
> + *
> + * The simplest way to enforce that is to perform everything (find existing
> + * table and if not found, create a new one) under the opp_table_lock, so only
> + * one creator gets access to the same. But that expands the critical section
> + * under the lock and may end up causing circular dependencies with frameworks
> + * like debugfs, interconnect or clock framework as they may be direct or
> + * indirect users of OPP core.
> + *
> + * And for that reason we have to go for a bit tricky implementation here, which
> + * uses the opp_tables_busy flag to indicate if another creator is in the middle
> + * of adding an OPP table and others should wait for it to finish.
> + */
>  static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
>  {
>  	struct opp_table *opp_table;
>  
> -	/* Hold our table modification lock here */
> +again:
>  	mutex_lock(&opp_table_lock);
>  
>  	opp_table = _find_opp_table_unlocked(dev);
>  	if (!IS_ERR(opp_table))
>  		goto unlock;
>  
> +	/*
> +	 * The opp_tables list or an OPP table's dev_list is getting updated by
> +	 * another user, wait for it to finish.
> +	 */
> +	if (unlikely(opp_tables_busy)) {
> +		mutex_unlock(&opp_table_lock);
> +		cpu_relax();
> +		goto again;
> +	}
> +
> +	opp_tables_busy = true;
>  	opp_table = _managed_opp(dev, index);
> +
> +	/* Drop the lock to reduce the size of critical section */
> +	mutex_unlock(&opp_table_lock);
> +
>  	if (opp_table) {
> -		if (!_add_opp_dev_unlocked(dev, opp_table)) {
> +		if (!_add_opp_dev(dev, opp_table)) {
>  			dev_pm_opp_put_opp_table(opp_table);
>  			opp_table = ERR_PTR(-ENOMEM);
>  		}
> -		goto unlock;
> +
> +		mutex_lock(&opp_table_lock);
> +	} else {
> +		opp_table = _allocate_opp_table(dev, index);
> +
> +		mutex_lock(&opp_table_lock);
> +		if (!IS_ERR(opp_table))
> +			list_add(&opp_table->node, &opp_tables);
>  	}
>  
> -	opp_table = _allocate_opp_table(dev, index);
> +	opp_tables_busy = false;
>  
>  unlock:
>  	mutex_unlock(&opp_table_lock);
> @@ -1181,6 +1208,10 @@ static void _opp_table_kref_release(struct kref *kref)
>  	struct opp_device *opp_dev, *temp;
>  	int i;
>  
> +	/* Drop the lock as soon as we can */
> +	list_del(&opp_table->node);
> +	mutex_unlock(&opp_table_lock);
> +
>  	_of_clear_opp_table(opp_table);
>  
>  	/* Release clk */
> @@ -1208,10 +1239,7 @@ static void _opp_table_kref_release(struct kref *kref)
>  
>  	mutex_destroy(&opp_table->genpd_virt_dev_lock);
>  	mutex_destroy(&opp_table->lock);
> -	list_del(&opp_table->node);
>  	kfree(opp_table);
> -
> -	mutex_unlock(&opp_table_lock);
>  }
>  
>  void dev_pm_opp_put_opp_table(struct opp_table *opp_table)

Rob, Ping.

-- 
viresh

WARNING: multiple messages have this Message-ID (diff)
From: Viresh Kumar <viresh.kumar@linaro.org>
To: Rob Clark <robdclark@gmail.com>
Cc: Rob Clark <robdclark@chromium.org>,
	"open list:DRM DRIVER FOR MSM ADRENO GPU"
	<freedreno@lists.freedesktop.org>, "Menon, Nishanth" <nm@ti.com>,
	David Airlie <airlied@linux.ie>,
	"open list:DRM DRIVER FOR MSM ADRENO GPU"
	<linux-arm-msm@vger.kernel.org>,
	open list <linux-kernel@vger.kernel.org>,
	dri-devel <dri-devel@lists.freedesktop.org>,
	Sean Paul <sean@poorly.run>
Subject: Re: [PATCH v2 07/22] drm/msm: Do rpm get sooner in the submit path
Date: Tue, 3 Nov 2020 11:17:15 +0530	[thread overview]
Message-ID: <20201103054715.4l5j57pyjz6zd6ed@vireshk-i7> (raw)
In-Reply-To: <20201027113532.nriqqws7gdcu5su6@vireshk-i7>

On 27-10-20, 17:05, Viresh Kumar wrote:
> It isn't that straight forward unfortunately, we need to make sure the
> table doesn't get allocated for the same device twice, so
> find+allocate needs to happen within a locked region.
> 
> I have taken, not so straight forward, approach to fixing this issue,
> lets see if this fixes it or not.
> 
> -------------------------8<-------------------------
> 
> diff --git a/drivers/opp/core.c b/drivers/opp/core.c
> index 4ac4e7ce6b8b..6f4a73a6391f 100644
> --- a/drivers/opp/core.c
> +++ b/drivers/opp/core.c
> @@ -29,6 +29,8 @@
>  LIST_HEAD(opp_tables);
>  /* Lock to allow exclusive modification to the device and opp lists */
>  DEFINE_MUTEX(opp_table_lock);
> +/* Flag indicating that opp_tables list is being updated at the moment */
> +static bool opp_tables_busy;
>  
>  static struct opp_device *_find_opp_dev(const struct device *dev,
>  					struct opp_table *opp_table)
> @@ -1036,8 +1038,8 @@ static void _remove_opp_dev(struct opp_device *opp_dev,
>  	kfree(opp_dev);
>  }
>  
> -static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
> -						struct opp_table *opp_table)
> +struct opp_device *_add_opp_dev(const struct device *dev,
> +				struct opp_table *opp_table)
>  {
>  	struct opp_device *opp_dev;
>  
> @@ -1048,7 +1050,9 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
>  	/* Initialize opp-dev */
>  	opp_dev->dev = dev;
>  
> +	mutex_lock(&opp_table->lock);
>  	list_add(&opp_dev->node, &opp_table->dev_list);
> +	mutex_unlock(&opp_table->lock);
>  
>  	/* Create debugfs entries for the opp_table */
>  	opp_debug_register(opp_dev, opp_table);
> @@ -1056,18 +1060,6 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
>  	return opp_dev;
>  }
>  
> -struct opp_device *_add_opp_dev(const struct device *dev,
> -				struct opp_table *opp_table)
> -{
> -	struct opp_device *opp_dev;
> -
> -	mutex_lock(&opp_table->lock);
> -	opp_dev = _add_opp_dev_unlocked(dev, opp_table);
> -	mutex_unlock(&opp_table->lock);
> -
> -	return opp_dev;
> -}
> -
>  static struct opp_table *_allocate_opp_table(struct device *dev, int index)
>  {
>  	struct opp_table *opp_table;
> @@ -1121,8 +1113,6 @@ static struct opp_table *_allocate_opp_table(struct device *dev, int index)
>  	INIT_LIST_HEAD(&opp_table->opp_list);
>  	kref_init(&opp_table->kref);
>  
> -	/* Secure the device table modification */
> -	list_add(&opp_table->node, &opp_tables);
>  	return opp_table;
>  
>  err:
> @@ -1135,27 +1125,64 @@ void _get_opp_table_kref(struct opp_table *opp_table)
>  	kref_get(&opp_table->kref);
>  }
>  
> +/*
> + * We need to make sure that the OPP table for a device doesn't get added twice,
> + * if this routine gets called in parallel with the same device pointer.
> + *
> + * The simplest way to enforce that is to perform everything (find existing
> + * table and if not found, create a new one) under the opp_table_lock, so only
> + * one creator gets access to the same. But that expands the critical section
> + * under the lock and may end up causing circular dependencies with frameworks
> + * like debugfs, interconnect or clock framework as they may be direct or
> + * indirect users of OPP core.
> + *
> + * And for that reason we have to go for a bit tricky implementation here, which
> + * uses the opp_tables_busy flag to indicate if another creator is in the middle
> + * of adding an OPP table and others should wait for it to finish.
> + */
>  static struct opp_table *_opp_get_opp_table(struct device *dev, int index)
>  {
>  	struct opp_table *opp_table;
>  
> -	/* Hold our table modification lock here */
> +again:
>  	mutex_lock(&opp_table_lock);
>  
>  	opp_table = _find_opp_table_unlocked(dev);
>  	if (!IS_ERR(opp_table))
>  		goto unlock;
>  
> +	/*
> +	 * The opp_tables list or an OPP table's dev_list is getting updated by
> +	 * another user, wait for it to finish.
> +	 */
> +	if (unlikely(opp_tables_busy)) {
> +		mutex_unlock(&opp_table_lock);
> +		cpu_relax();
> +		goto again;
> +	}
> +
> +	opp_tables_busy = true;
>  	opp_table = _managed_opp(dev, index);
> +
> +	/* Drop the lock to reduce the size of critical section */
> +	mutex_unlock(&opp_table_lock);
> +
>  	if (opp_table) {
> -		if (!_add_opp_dev_unlocked(dev, opp_table)) {
> +		if (!_add_opp_dev(dev, opp_table)) {
>  			dev_pm_opp_put_opp_table(opp_table);
>  			opp_table = ERR_PTR(-ENOMEM);
>  		}
> -		goto unlock;
> +
> +		mutex_lock(&opp_table_lock);
> +	} else {
> +		opp_table = _allocate_opp_table(dev, index);
> +
> +		mutex_lock(&opp_table_lock);
> +		if (!IS_ERR(opp_table))
> +			list_add(&opp_table->node, &opp_tables);
>  	}
>  
> -	opp_table = _allocate_opp_table(dev, index);
> +	opp_tables_busy = false;
>  
>  unlock:
>  	mutex_unlock(&opp_table_lock);
> @@ -1181,6 +1208,10 @@ static void _opp_table_kref_release(struct kref *kref)
>  	struct opp_device *opp_dev, *temp;
>  	int i;
>  
> +	/* Drop the lock as soon as we can */
> +	list_del(&opp_table->node);
> +	mutex_unlock(&opp_table_lock);
> +
>  	_of_clear_opp_table(opp_table);
>  
>  	/* Release clk */
> @@ -1208,10 +1239,7 @@ static void _opp_table_kref_release(struct kref *kref)
>  
>  	mutex_destroy(&opp_table->genpd_virt_dev_lock);
>  	mutex_destroy(&opp_table->lock);
> -	list_del(&opp_table->node);
>  	kfree(opp_table);
> -
> -	mutex_unlock(&opp_table_lock);
>  }
>  
>  void dev_pm_opp_put_opp_table(struct opp_table *opp_table)

Rob, Ping.

-- 
viresh
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2020-11-03  5:47 UTC|newest]

Thread overview: 100+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-10-12  2:09 [PATCH 00/14] drm/msm: de-struct_mutex-ification Rob Clark
2020-10-12  2:09 ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 01/22] drm/msm/gem: Add obj->lock wrappers Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 02/22] drm/msm/gem: Rename internal get_iova_locked helper Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 03/22] drm/msm/gem: Move prototypes to msm_gem.h Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 04/22] drm/msm/gem: Add some _locked() helpers Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 05/22] drm/msm/gem: Move locking in shrinker path Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 06/22] drm/msm/submit: Move copy_from_user ahead of locking bos Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 07/22] drm/msm: Do rpm get sooner in the submit path Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12 14:35   ` Daniel Vetter
2020-10-12 14:35     ` Daniel Vetter
2020-10-12 15:43     ` Rob Clark
2020-10-12 15:43       ` Rob Clark
2020-10-20  9:07       ` Viresh Kumar
2020-10-20  9:07         ` Viresh Kumar
2020-10-20 10:56         ` Daniel Vetter
2020-10-20 10:56           ` Daniel Vetter
2020-10-20 11:24           ` Viresh Kumar
2020-10-20 11:24             ` Viresh Kumar
2020-10-20 11:42             ` Daniel Vetter
2020-10-20 11:42               ` Daniel Vetter
2020-10-20 14:13             ` Rob Clark
2020-10-20 14:13               ` Rob Clark
2020-10-22  8:06               ` Viresh Kumar
2020-10-22  8:06                 ` Viresh Kumar
2020-10-25 17:39                 ` Rob Clark
2020-10-25 17:39                   ` Rob Clark
2020-10-27 11:35                   ` Viresh Kumar
2020-10-27 11:35                     ` Viresh Kumar
2020-11-03  5:47                     ` Viresh Kumar [this message]
2020-11-03  5:47                       ` Viresh Kumar
2020-11-03 16:50                       ` Rob Clark
2020-11-03 16:50                         ` Rob Clark
2020-11-04  3:03                         ` Viresh Kumar
2020-11-04  3:03                           ` Viresh Kumar
2020-11-05 19:24                           ` Rob Clark
2020-11-05 19:24                             ` Rob Clark
2020-11-06  7:16                             ` Viresh Kumar
2020-11-06  7:16                               ` Viresh Kumar
2020-11-17 10:03                               ` Viresh Kumar
2020-11-17 10:03                                 ` Viresh Kumar
2020-11-17 17:02                               ` Rob Clark
2020-11-17 17:02                                 ` Rob Clark
2020-11-18  5:28                                 ` Viresh Kumar
2020-11-18  5:28                                   ` Viresh Kumar
2020-11-18 16:53                                   ` Rob Clark
2020-11-18 16:53                                     ` Rob Clark
2020-11-19  6:05                                     ` Viresh Kumar
2020-11-19  6:05                                       ` Viresh Kumar
2020-12-07  6:16                                       ` Viresh Kumar
2020-12-07  6:16                                         ` Viresh Kumar
2020-12-16  5:22                                         ` Viresh Kumar
2020-12-16  5:22                                           ` Viresh Kumar
2020-10-12  2:09 ` [PATCH v2 08/22] drm/msm/gem: Switch over to obj->resv for locking Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 09/22] drm/msm: Use correct drm_gem_object_put() in fail case Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 10/22] drm/msm: Drop chatty trace Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 11/22] drm/msm: Move update_fences() Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 12/22] drm/msm: Add priv->mm_lock to protect active/inactive lists Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 13/22] drm/msm: Document and rename preempt_lock Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 14/22] drm/msm: Protect ring->submits with it's own lock Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 15/22] drm/msm: Refcount submits Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 16/22] drm/msm: Remove obj->gpu Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 17/22] drm/msm: Drop struct_mutex from the retire path Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 18/22] drm/msm: Drop struct_mutex in free_object() path Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 19/22] drm/msm: remove msm_gem_free_work Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 20/22] drm/msm: drop struct_mutex in madvise path Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 21/22] drm/msm: Drop struct_mutex in shrinker path Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12  2:09 ` [PATCH v2 22/22] drm/msm: Don't implicit-sync if only a single ring Rob Clark
2020-10-12  2:09   ` Rob Clark
2020-10-12 14:40   ` Daniel Vetter
2020-10-12 14:40     ` Daniel Vetter
2020-10-12 15:07     ` Rob Clark
2020-10-12 15:07       ` Rob Clark
2020-10-13 11:08       ` Daniel Vetter
2020-10-13 11:08         ` Daniel Vetter
2020-10-13 16:15         ` [Freedreno] " Rob Clark
2020-10-13 16:15           ` Rob Clark
2020-10-15  8:22           ` Daniel Vetter
2020-10-15  8:22             ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201103054715.4l5j57pyjz6zd6ed@vireshk-i7 \
    --to=viresh.kumar@linaro.org \
    --cc=airlied@linux.ie \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=freedreno@lists.freedesktop.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nm@ti.com \
    --cc=robdclark@chromium.org \
    --cc=robdclark@gmail.com \
    --cc=sean@poorly.run \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.