From: Chris Wilson <chris@chris-wilson.co.uk> To: Daniel Vetter <daniel.vetter@ffwll.ch>, "Intel Graphics Development" <intel-gfx@lists.freedesktop.org> Cc: "DRI Development" <dri-devel@lists.freedesktop.org>, "Daniel Vetter" <daniel.vetter@ffwll.ch>, "Ben Widawsky" <ben@bwidawsk.net>, "Dave Airlie" <airlied@gmail.com>, "Sean Paul" <seanpaul@chromium.org>, stable@vger.kernel.org, "Daniel Vetter" <daniel.vetter@intel.com>, "Jani Nikula" <jani.nikula@linux.intel.com>, "Gustavo Padovan" <gustavo@padovan.org>, "David Airlie" <airlied@linux.ie>, "Javier Martinez Canillas" <javier@dowhile0.org>, "Shuah Khan" <shuahkh@osg.samsung.com>, "Guillaume Tucker" <guillaume.tucker@collabora.com>, "Mark Brown" <broonie@kernel.org>, "Kevin Hilman" <khilman@baylibre.com>, "Matt Hart" <matthew.hart@linaro.org>, "Thierry Escande" <thierry.escande@collabora.co.uk>, "Tomeu Vizoso" <tomeu.vizoso@collabora.com>, "Enric Balletbo i Serra" <enric.balletbo@collabora.com> Subject: Re: [PATCH] drm: rework delayed connector cleanup in connector_iter Date: Wed, 13 Dec 2017 13:05:49 +0000 [thread overview] Message-ID: <151317034976.11713.13410850976946373368@mail.alporthouse.com> (raw) In-Reply-To: <20171213124936.17914-1-daniel.vetter@ffwll.ch> Quoting Daniel Vetter (2017-12-13 12:49:36) > PROBE_DEFER also uses system_wq to reprobe drivers, which means when > that again fails, and we try to flush the overall system_wq (to get > all the delayed connectore cleanup work_struct completed), we > deadlock. > > Fix this by using just a single cleanup work, so that we can only > flush that one and don't block on anything else. That means a free > list plus locking, a standard pattern. > > v2: > - Correctly free connectors only on last ref. Oops (Chris). > - use llist_head/node (Chris). > > Fixes: a703c55004e1 ("drm: safely free connectors from connector_iter") > Fixes: 613051dac40d ("drm: locking&new iterators for connector_list") > Cc: Ben Widawsky <ben@bwidawsk.net> > Cc: Dave Airlie <airlied@gmail.com> > Cc: Chris Wilson <chris@chris-wilson.co.uk> > Cc: Sean Paul <seanpaul@chromium.org> > Cc: <stable@vger.kernel.org> # v4.11+: 613051dac40d ("drm: locking&new iterators for connector_list" > Cc: <stable@vger.kernel.org> # v4.11+ > Cc: Daniel Vetter <daniel.vetter@intel.com> > Cc: Jani Nikula <jani.nikula@linux.intel.com> > Cc: Gustavo Padovan <gustavo@padovan.org> > Cc: David Airlie <airlied@linux.ie> > Cc: Javier Martinez Canillas <javier@dowhile0.org> > Cc: Shuah Khan <shuahkh@osg.samsung.com> > Cc: Guillaume Tucker <guillaume.tucker@collabora.com> > Cc: Mark Brown <broonie@kernel.org> > Cc: Kevin Hilman <khilman@baylibre.com> > Cc: Matt Hart <matthew.hart@linaro.org> > Cc: Thierry Escande <thierry.escande@collabora.co.uk> > Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com> > Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> > --- > drivers/gpu/drm/drm_connector.c | 50 ++++++++++++++++++++++++++----------- > drivers/gpu/drm/drm_crtc_internal.h | 1 + > drivers/gpu/drm/drm_mode_config.c | 4 ++- > include/drm/drm_connector.h | 10 +++++--- > include/drm/drm_mode_config.h | 18 ++++++++++++- > 5 files changed, 62 insertions(+), 21 deletions(-) > > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c > index 0b7e0974e6da..3f53f127e1f2 100644 > --- a/drivers/gpu/drm/drm_connector.c > +++ b/drivers/gpu/drm/drm_connector.c > @@ -153,14 +153,23 @@ static void drm_connector_free(struct kref *kref) > connector->funcs->destroy(connector); > } > > -static void drm_connector_free_work_fn(struct work_struct *work) > +void drm_connector_free_work_fn(struct work_struct *work) > { > - struct drm_connector *connector = > - container_of(work, struct drm_connector, free_work); > - struct drm_device *dev = connector->dev; > + struct drm_connector *connector, *n; > + struct drm_device *dev = > + container_of(work, struct drm_device, mode_config.connector_free_work); > + struct drm_mode_config *config = &dev->mode_config; > + unsigned long flags; > + struct llist_node *freed; > > - drm_mode_object_unregister(dev, &connector->base); > - connector->funcs->destroy(connector); > + spin_lock_irqsave(&config->connector_list_lock, flags); > + freed = llist_del_all(&config->connector_free_list); > + spin_unlock_irqrestore(&config->connector_list_lock, flags); My understanding is that the spinlock here is only used to guard the free_list. (It's not protecting the final refcount.) In which case it is redundant as llist_del_all/llist_add are a safe lockless combination. That just makes the patch bigger than has to be, but it looks correct. > +__drm_connector_put_safe(struct drm_connector *conn) > { > - if (refcount_dec_and_test(&conn->base.refcount.refcount)) > - schedule_work(&conn->free_work); > + struct drm_mode_config *config = &conn->dev->mode_config; > + > + lockdep_assert_held(&config->connector_list_lock); > + > + if (!refcount_dec_and_test(&conn->base.refcount.refcount)) > + return; > + > + llist_add(&conn->free_node, &config->connector_free_list); > + schedule_work(&config->connector_free_work); (Didn't like the if (llist_add) nano-optimisation? :) > diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h > index 9ebb8841778c..af00f42ba269 100644 > --- a/drivers/gpu/drm/drm_crtc_internal.h > +++ b/drivers/gpu/drm/drm_crtc_internal.h > @@ -142,6 +142,7 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, > uint64_t value); > int drm_connector_create_standard_properties(struct drm_device *dev); > const char *drm_get_connector_force_name(enum drm_connector_force force); > +void drm_connector_free_work_fn(struct work_struct *work); > > /* IOCTL */ > int drm_mode_connector_property_set_ioctl(struct drm_device *dev, > diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c > index 6ffe952142e6..7681269abe41 100644 > --- a/drivers/gpu/drm/drm_mode_config.c > +++ b/drivers/gpu/drm/drm_mode_config.c > @@ -382,6 +382,8 @@ void drm_mode_config_init(struct drm_device *dev) > ida_init(&dev->mode_config.connector_ida); > spin_lock_init(&dev->mode_config.connector_list_lock); > > + INIT_WORK(&dev->mode_config.connector_free_work, drm_connector_free_work_fn); A init_llist_head(&dev->mode_config.connector_free_list) wouldn't go amiss here. So perhaps push the connectors init into its own exported function from drm_connector.c as opposed to exposing the free_fn. Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> -Chris
WARNING: multiple messages have this Message-ID (diff)
From: Chris Wilson <chris@chris-wilson.co.uk> To: Intel Graphics Development <intel-gfx@lists.freedesktop.org> Cc: DRI Development <dri-devel@lists.freedesktop.org>, Daniel Vetter <daniel.vetter@ffwll.ch>, Ben Widawsky <ben@bwidawsk.net>, Dave Airlie <airlied@gmail.com>, Sean Paul <seanpaul@chromium.org>, stable@vger.kernel.org, Daniel Vetter <daniel.vetter@intel.com>, Jani Nikula <jani.nikula@linux.intel.com>, Gustavo Padovan <gustavo@padovan.org>, David Airlie <airlied@linux.ie>, Javier Martinez Canillas <javier@dowhile0.org>, Shuah Khan <shuahkh@osg.samsung.com>, Guillaume Tucker <guillaume.tucker@collabora.com>, Mark Brown <broonie@kernel.org>, Kevin Hilman <khilman@baylibre.com>, Matt Hart <matthew.hart@linaro.org>, Thierry Escande <thierry.escande@collabora.co.uk>, Tomeu Vizoso <tomeu.vizoso@collabora.com>, Enric Balletbo Subject: Re: [PATCH] drm: rework delayed connector cleanup in connector_iter Date: Wed, 13 Dec 2017 13:05:49 +0000 [thread overview] Message-ID: <151317034976.11713.13410850976946373368@mail.alporthouse.com> (raw) In-Reply-To: <20171213124936.17914-1-daniel.vetter@ffwll.ch> Quoting Daniel Vetter (2017-12-13 12:49:36) > PROBE_DEFER also uses system_wq to reprobe drivers, which means when > that again fails, and we try to flush the overall system_wq (to get > all the delayed connectore cleanup work_struct completed), we > deadlock. > > Fix this by using just a single cleanup work, so that we can only > flush that one and don't block on anything else. That means a free > list plus locking, a standard pattern. > > v2: > - Correctly free connectors only on last ref. Oops (Chris). > - use llist_head/node (Chris). > > Fixes: a703c55004e1 ("drm: safely free connectors from connector_iter") > Fixes: 613051dac40d ("drm: locking&new iterators for connector_list") > Cc: Ben Widawsky <ben@bwidawsk.net> > Cc: Dave Airlie <airlied@gmail.com> > Cc: Chris Wilson <chris@chris-wilson.co.uk> > Cc: Sean Paul <seanpaul@chromium.org> > Cc: <stable@vger.kernel.org> # v4.11+: 613051dac40d ("drm: locking&new iterators for connector_list" > Cc: <stable@vger.kernel.org> # v4.11+ > Cc: Daniel Vetter <daniel.vetter@intel.com> > Cc: Jani Nikula <jani.nikula@linux.intel.com> > Cc: Gustavo Padovan <gustavo@padovan.org> > Cc: David Airlie <airlied@linux.ie> > Cc: Javier Martinez Canillas <javier@dowhile0.org> > Cc: Shuah Khan <shuahkh@osg.samsung.com> > Cc: Guillaume Tucker <guillaume.tucker@collabora.com> > Cc: Mark Brown <broonie@kernel.org> > Cc: Kevin Hilman <khilman@baylibre.com> > Cc: Matt Hart <matthew.hart@linaro.org> > Cc: Thierry Escande <thierry.escande@collabora.co.uk> > Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com> > Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com> > Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> > --- > drivers/gpu/drm/drm_connector.c | 50 ++++++++++++++++++++++++++----------- > drivers/gpu/drm/drm_crtc_internal.h | 1 + > drivers/gpu/drm/drm_mode_config.c | 4 ++- > include/drm/drm_connector.h | 10 +++++--- > include/drm/drm_mode_config.h | 18 ++++++++++++- > 5 files changed, 62 insertions(+), 21 deletions(-) > > diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c > index 0b7e0974e6da..3f53f127e1f2 100644 > --- a/drivers/gpu/drm/drm_connector.c > +++ b/drivers/gpu/drm/drm_connector.c > @@ -153,14 +153,23 @@ static void drm_connector_free(struct kref *kref) > connector->funcs->destroy(connector); > } > > -static void drm_connector_free_work_fn(struct work_struct *work) > +void drm_connector_free_work_fn(struct work_struct *work) > { > - struct drm_connector *connector = > - container_of(work, struct drm_connector, free_work); > - struct drm_device *dev = connector->dev; > + struct drm_connector *connector, *n; > + struct drm_device *dev = > + container_of(work, struct drm_device, mode_config.connector_free_work); > + struct drm_mode_config *config = &dev->mode_config; > + unsigned long flags; > + struct llist_node *freed; > > - drm_mode_object_unregister(dev, &connector->base); > - connector->funcs->destroy(connector); > + spin_lock_irqsave(&config->connector_list_lock, flags); > + freed = llist_del_all(&config->connector_free_list); > + spin_unlock_irqrestore(&config->connector_list_lock, flags); My understanding is that the spinlock here is only used to guard the free_list. (It's not protecting the final refcount.) In which case it is redundant as llist_del_all/llist_add are a safe lockless combination. That just makes the patch bigger than has to be, but it looks correct. > +__drm_connector_put_safe(struct drm_connector *conn) > { > - if (refcount_dec_and_test(&conn->base.refcount.refcount)) > - schedule_work(&conn->free_work); > + struct drm_mode_config *config = &conn->dev->mode_config; > + > + lockdep_assert_held(&config->connector_list_lock); > + > + if (!refcount_dec_and_test(&conn->base.refcount.refcount)) > + return; > + > + llist_add(&conn->free_node, &config->connector_free_list); > + schedule_work(&config->connector_free_work); (Didn't like the if (llist_add) nano-optimisation? :) > diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h > index 9ebb8841778c..af00f42ba269 100644 > --- a/drivers/gpu/drm/drm_crtc_internal.h > +++ b/drivers/gpu/drm/drm_crtc_internal.h > @@ -142,6 +142,7 @@ int drm_mode_connector_set_obj_prop(struct drm_mode_object *obj, > uint64_t value); > int drm_connector_create_standard_properties(struct drm_device *dev); > const char *drm_get_connector_force_name(enum drm_connector_force force); > +void drm_connector_free_work_fn(struct work_struct *work); > > /* IOCTL */ > int drm_mode_connector_property_set_ioctl(struct drm_device *dev, > diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c > index 6ffe952142e6..7681269abe41 100644 > --- a/drivers/gpu/drm/drm_mode_config.c > +++ b/drivers/gpu/drm/drm_mode_config.c > @@ -382,6 +382,8 @@ void drm_mode_config_init(struct drm_device *dev) > ida_init(&dev->mode_config.connector_ida); > spin_lock_init(&dev->mode_config.connector_list_lock); > > + INIT_WORK(&dev->mode_config.connector_free_work, drm_connector_free_work_fn); A init_llist_head(&dev->mode_config.connector_free_list) wouldn't go amiss here. So perhaps push the connectors init into its own exported function from drm_connector.c as opposed to exposing the free_fn. Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> -Chris
next prev parent reply other threads:[~2017-12-13 13:06 UTC|newest] Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top [not found] <CGME20171213104607epcas4p420c1a7a83a19c1924318207c0bb2e8e2@epcas4p4.samsung.com> 2017-12-13 10:45 ` [PATCH] drm: rework delayed connector cleanup in connector_iter Daniel Vetter 2017-12-13 10:45 ` Daniel Vetter 2017-12-13 11:04 ` Chris Wilson 2017-12-13 11:04 ` Chris Wilson 2017-12-13 11:48 ` ✗ Fi.CI.BAT: failure for " Patchwork 2017-12-13 12:27 ` [PATCH] " Marek Szyprowski 2017-12-13 12:49 ` Daniel Vetter 2017-12-13 12:49 ` Daniel Vetter 2017-12-13 13:01 ` Marek Szyprowski 2017-12-13 13:05 ` Chris Wilson [this message] 2017-12-13 13:05 ` Chris Wilson 2017-12-13 13:35 ` Daniel Vetter 2017-12-13 13:35 ` Daniel Vetter 2017-12-13 21:59 ` Daniel Vetter 2017-12-13 21:59 ` Daniel Vetter 2017-12-13 14:48 ` ✓ Fi.CI.BAT: success for drm: rework delayed connector cleanup in connector_iter (rev2) Patchwork 2017-12-13 17:30 ` ✗ Fi.CI.IGT: warning " Patchwork
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=151317034976.11713.13410850976946373368@mail.alporthouse.com \ --to=chris@chris-wilson.co.uk \ --cc=airlied@gmail.com \ --cc=airlied@linux.ie \ --cc=ben@bwidawsk.net \ --cc=broonie@kernel.org \ --cc=daniel.vetter@ffwll.ch \ --cc=daniel.vetter@intel.com \ --cc=dri-devel@lists.freedesktop.org \ --cc=enric.balletbo@collabora.com \ --cc=guillaume.tucker@collabora.com \ --cc=gustavo@padovan.org \ --cc=intel-gfx@lists.freedesktop.org \ --cc=jani.nikula@linux.intel.com \ --cc=javier@dowhile0.org \ --cc=khilman@baylibre.com \ --cc=matthew.hart@linaro.org \ --cc=seanpaul@chromium.org \ --cc=shuahkh@osg.samsung.com \ --cc=stable@vger.kernel.org \ --cc=thierry.escande@collabora.co.uk \ --cc=tomeu.vizoso@collabora.com \ /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: linkBe 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.