/linux/drivers/gpu/drm/ |
H A D | drm_mode_config.c | diff a703c55004e1c5076d57e43771b3e11117796ea0 Mon Dec 04 21:48:18 CET 2017 Daniel Vetter <daniel.vetter@ffwll.ch> drm: safely free connectors from connector_iter
In
commit 613051dac40da1751ab269572766d3348d45a197 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed Dec 14 00:08:06 2016 +0100
drm: locking&new iterators for connector_list
we've went to extreme lengths to make sure connector iterations works in any context, without introducing any additional locking context. This worked, except for a small fumble in the implementation:
When we actually race with a concurrent connector unplug event, and our temporary connector reference turns out to be the final one, then everything breaks: We call the connector release function from whatever context we happen to be in, which can be an irq/atomic context. And connector freeing grabs all kinds of locks and stuff.
Fix this by creating a specially safe put function for connetor_iter, which (in this rare case) punts the cleanup to a worker.
Reported-by: Ben Widawsky <ben@bwidawsk.net> Cc: Ben Widawsky <ben@bwidawsk.net> Fixes: 613051dac40d ("drm: locking&new iterators for connector_list") 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+ Reviewed-by: Dave Airlie <airlied@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171204204818.24745-1-daniel.vetter@ffwll.ch diff 613051dac40da1751ab269572766d3348d45a197 Wed Dec 14 00:08:06 CET 2016 Daniel Vetter <daniel.vetter@ffwll.ch> drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky: - We need to be able to jump over zombie conectors (i.e. with refcount == 0, but not yet removed from the list). If instead we require that there's no zombies on the list then the final kref_put must happen under the list protection lock, which means that locking context leaks all over the place. Not pretty - better to deal with zombies and wrap the locking just around the list_del in the destructor.
- When we walk the list we must _not_ hold the connector list lock. We walk the connector list at an absolutely massive amounts of places, if all those places can't ever call drm_connector_unreference the code would get unecessarily complicated.
- connector_list needs it own lock, again too many places that walk it that we could reuse e.g. mode_config.mutex without resulting in inversions.
- Lots of code uses these loops to look-up a connector, i.e. they want to be able to call drm_connector_reference. But on the other hand we want connectors to stay on that list until they're dead (i.e. connector_list can't hold a full reference), which means despite the "can't hold lock for the loop body" rule we need to make sure a connector doesn't suddenly become a zombie.
At first Dave&I discussed various horror-show approaches using srcu, but turns out it's fairly easy:
- For the loop body we always hold an additional reference to the current connector. That means it can't zombify, and it also means it'll stay on the list, which means we can use it as our iterator to find the next connector.
- When we try to find the next connector we only have to jump over zombies. To make sure we don't chase bad pointers that entire loop is protected with the new connect_list_lock spinlock. And because we know that we're starting out with a non-zombie (need to drop our reference for the old connector only after we have our new one), we're guranteed to still be on the connector_list and either find the next non-zombie or complete the iteration.
- Only downside is that we need to make sure that the temporary reference for the loop body doesn't leak. iter_get/put() functions + lockdep make sure that's the case.
- To avoid a flag day the new iterator macro has an _iter postfix. We can rename it back once all the users of the unsafe version are gone (there's about 100 list walkers for the connector_list).
For now this patch only converts all the list walking in the core, leaving helpers and drivers for later patches. The nice thing is that we can now finally remove 2 FIXME comments from the register/unregister functions.
v2: - use irqsafe spinlocks, so that we can use this in drm_state_dump too. - nuke drm_modeset_lock_all from drm_connector_init, now entirely cargo-culted nonsense.
v3: - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). - pretty kerneldoc - add EXPORT_SYMBOL, helpers&drivers are supposed to use this.
v4: Change lockdep annotations to only check whether we release the iter fake lock again (i.e. make sure that iter_put is called), but not check any locking dependecies itself. That seams to require a recursive read lock in trylock mode.
Cc: Dave Airlie <airlied@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
|
H A D | drm_encoder.c | diff 613051dac40da1751ab269572766d3348d45a197 Wed Dec 14 00:08:06 CET 2016 Daniel Vetter <daniel.vetter@ffwll.ch> drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky: - We need to be able to jump over zombie conectors (i.e. with refcount == 0, but not yet removed from the list). If instead we require that there's no zombies on the list then the final kref_put must happen under the list protection lock, which means that locking context leaks all over the place. Not pretty - better to deal with zombies and wrap the locking just around the list_del in the destructor.
- When we walk the list we must _not_ hold the connector list lock. We walk the connector list at an absolutely massive amounts of places, if all those places can't ever call drm_connector_unreference the code would get unecessarily complicated.
- connector_list needs it own lock, again too many places that walk it that we could reuse e.g. mode_config.mutex without resulting in inversions.
- Lots of code uses these loops to look-up a connector, i.e. they want to be able to call drm_connector_reference. But on the other hand we want connectors to stay on that list until they're dead (i.e. connector_list can't hold a full reference), which means despite the "can't hold lock for the loop body" rule we need to make sure a connector doesn't suddenly become a zombie.
At first Dave&I discussed various horror-show approaches using srcu, but turns out it's fairly easy:
- For the loop body we always hold an additional reference to the current connector. That means it can't zombify, and it also means it'll stay on the list, which means we can use it as our iterator to find the next connector.
- When we try to find the next connector we only have to jump over zombies. To make sure we don't chase bad pointers that entire loop is protected with the new connect_list_lock spinlock. And because we know that we're starting out with a non-zombie (need to drop our reference for the old connector only after we have our new one), we're guranteed to still be on the connector_list and either find the next non-zombie or complete the iteration.
- Only downside is that we need to make sure that the temporary reference for the loop body doesn't leak. iter_get/put() functions + lockdep make sure that's the case.
- To avoid a flag day the new iterator macro has an _iter postfix. We can rename it back once all the users of the unsafe version are gone (there's about 100 list walkers for the connector_list).
For now this patch only converts all the list walking in the core, leaving helpers and drivers for later patches. The nice thing is that we can now finally remove 2 FIXME comments from the register/unregister functions.
v2: - use irqsafe spinlocks, so that we can use this in drm_state_dump too. - nuke drm_modeset_lock_all from drm_connector_init, now entirely cargo-culted nonsense.
v3: - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). - pretty kerneldoc - add EXPORT_SYMBOL, helpers&drivers are supposed to use this.
v4: Change lockdep annotations to only check whether we release the iter fake lock again (i.e. make sure that iter_put is called), but not check any locking dependecies itself. That seams to require a recursive read lock in trylock mode.
Cc: Dave Airlie <airlied@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
|
H A D | drm_connector.c | diff a703c55004e1c5076d57e43771b3e11117796ea0 Mon Dec 04 21:48:18 CET 2017 Daniel Vetter <daniel.vetter@ffwll.ch> drm: safely free connectors from connector_iter
In
commit 613051dac40da1751ab269572766d3348d45a197 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed Dec 14 00:08:06 2016 +0100
drm: locking&new iterators for connector_list
we've went to extreme lengths to make sure connector iterations works in any context, without introducing any additional locking context. This worked, except for a small fumble in the implementation:
When we actually race with a concurrent connector unplug event, and our temporary connector reference turns out to be the final one, then everything breaks: We call the connector release function from whatever context we happen to be in, which can be an irq/atomic context. And connector freeing grabs all kinds of locks and stuff.
Fix this by creating a specially safe put function for connetor_iter, which (in this rare case) punts the cleanup to a worker.
Reported-by: Ben Widawsky <ben@bwidawsk.net> Cc: Ben Widawsky <ben@bwidawsk.net> Fixes: 613051dac40d ("drm: locking&new iterators for connector_list") 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+ Reviewed-by: Dave Airlie <airlied@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171204204818.24745-1-daniel.vetter@ffwll.ch diff 613051dac40da1751ab269572766d3348d45a197 Wed Dec 14 00:08:06 CET 2016 Daniel Vetter <daniel.vetter@ffwll.ch> drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky: - We need to be able to jump over zombie conectors (i.e. with refcount == 0, but not yet removed from the list). If instead we require that there's no zombies on the list then the final kref_put must happen under the list protection lock, which means that locking context leaks all over the place. Not pretty - better to deal with zombies and wrap the locking just around the list_del in the destructor.
- When we walk the list we must _not_ hold the connector list lock. We walk the connector list at an absolutely massive amounts of places, if all those places can't ever call drm_connector_unreference the code would get unecessarily complicated.
- connector_list needs it own lock, again too many places that walk it that we could reuse e.g. mode_config.mutex without resulting in inversions.
- Lots of code uses these loops to look-up a connector, i.e. they want to be able to call drm_connector_reference. But on the other hand we want connectors to stay on that list until they're dead (i.e. connector_list can't hold a full reference), which means despite the "can't hold lock for the loop body" rule we need to make sure a connector doesn't suddenly become a zombie.
At first Dave&I discussed various horror-show approaches using srcu, but turns out it's fairly easy:
- For the loop body we always hold an additional reference to the current connector. That means it can't zombify, and it also means it'll stay on the list, which means we can use it as our iterator to find the next connector.
- When we try to find the next connector we only have to jump over zombies. To make sure we don't chase bad pointers that entire loop is protected with the new connect_list_lock spinlock. And because we know that we're starting out with a non-zombie (need to drop our reference for the old connector only after we have our new one), we're guranteed to still be on the connector_list and either find the next non-zombie or complete the iteration.
- Only downside is that we need to make sure that the temporary reference for the loop body doesn't leak. iter_get/put() functions + lockdep make sure that's the case.
- To avoid a flag day the new iterator macro has an _iter postfix. We can rename it back once all the users of the unsafe version are gone (there's about 100 list walkers for the connector_list).
For now this patch only converts all the list walking in the core, leaving helpers and drivers for later patches. The nice thing is that we can now finally remove 2 FIXME comments from the register/unregister functions.
v2: - use irqsafe spinlocks, so that we can use this in drm_state_dump too. - nuke drm_modeset_lock_all from drm_connector_init, now entirely cargo-culted nonsense.
v3: - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). - pretty kerneldoc - add EXPORT_SYMBOL, helpers&drivers are supposed to use this.
v4: Change lockdep annotations to only check whether we release the iter fake lock again (i.e. make sure that iter_put is called), but not check any locking dependecies itself. That seams to require a recursive read lock in trylock mode.
Cc: Dave Airlie <airlied@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
|
H A D | drm_atomic.c | diff 613051dac40da1751ab269572766d3348d45a197 Wed Dec 14 00:08:06 CET 2016 Daniel Vetter <daniel.vetter@ffwll.ch> drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky: - We need to be able to jump over zombie conectors (i.e. with refcount == 0, but not yet removed from the list). If instead we require that there's no zombies on the list then the final kref_put must happen under the list protection lock, which means that locking context leaks all over the place. Not pretty - better to deal with zombies and wrap the locking just around the list_del in the destructor.
- When we walk the list we must _not_ hold the connector list lock. We walk the connector list at an absolutely massive amounts of places, if all those places can't ever call drm_connector_unreference the code would get unecessarily complicated.
- connector_list needs it own lock, again too many places that walk it that we could reuse e.g. mode_config.mutex without resulting in inversions.
- Lots of code uses these loops to look-up a connector, i.e. they want to be able to call drm_connector_reference. But on the other hand we want connectors to stay on that list until they're dead (i.e. connector_list can't hold a full reference), which means despite the "can't hold lock for the loop body" rule we need to make sure a connector doesn't suddenly become a zombie.
At first Dave&I discussed various horror-show approaches using srcu, but turns out it's fairly easy:
- For the loop body we always hold an additional reference to the current connector. That means it can't zombify, and it also means it'll stay on the list, which means we can use it as our iterator to find the next connector.
- When we try to find the next connector we only have to jump over zombies. To make sure we don't chase bad pointers that entire loop is protected with the new connect_list_lock spinlock. And because we know that we're starting out with a non-zombie (need to drop our reference for the old connector only after we have our new one), we're guranteed to still be on the connector_list and either find the next non-zombie or complete the iteration.
- Only downside is that we need to make sure that the temporary reference for the loop body doesn't leak. iter_get/put() functions + lockdep make sure that's the case.
- To avoid a flag day the new iterator macro has an _iter postfix. We can rename it back once all the users of the unsafe version are gone (there's about 100 list walkers for the connector_list).
For now this patch only converts all the list walking in the core, leaving helpers and drivers for later patches. The nice thing is that we can now finally remove 2 FIXME comments from the register/unregister functions.
v2: - use irqsafe spinlocks, so that we can use this in drm_state_dump too. - nuke drm_modeset_lock_all from drm_connector_init, now entirely cargo-culted nonsense.
v3: - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). - pretty kerneldoc - add EXPORT_SYMBOL, helpers&drivers are supposed to use this.
v4: Change lockdep annotations to only check whether we release the iter fake lock again (i.e. make sure that iter_put is called), but not check any locking dependecies itself. That seams to require a recursive read lock in trylock mode.
Cc: Dave Airlie <airlied@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
|
/linux/include/drm/ |
H A D | drm_connector.h | diff a703c55004e1c5076d57e43771b3e11117796ea0 Mon Dec 04 21:48:18 CET 2017 Daniel Vetter <daniel.vetter@ffwll.ch> drm: safely free connectors from connector_iter
In
commit 613051dac40da1751ab269572766d3348d45a197 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Wed Dec 14 00:08:06 2016 +0100
drm: locking&new iterators for connector_list
we've went to extreme lengths to make sure connector iterations works in any context, without introducing any additional locking context. This worked, except for a small fumble in the implementation:
When we actually race with a concurrent connector unplug event, and our temporary connector reference turns out to be the final one, then everything breaks: We call the connector release function from whatever context we happen to be in, which can be an irq/atomic context. And connector freeing grabs all kinds of locks and stuff.
Fix this by creating a specially safe put function for connetor_iter, which (in this rare case) punts the cleanup to a worker.
Reported-by: Ben Widawsky <ben@bwidawsk.net> Cc: Ben Widawsky <ben@bwidawsk.net> Fixes: 613051dac40d ("drm: locking&new iterators for connector_list") 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+ Reviewed-by: Dave Airlie <airlied@gmail.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20171204204818.24745-1-daniel.vetter@ffwll.ch diff 613051dac40da1751ab269572766d3348d45a197 Wed Dec 14 00:08:06 CET 2016 Daniel Vetter <daniel.vetter@ffwll.ch> drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky: - We need to be able to jump over zombie conectors (i.e. with refcount == 0, but not yet removed from the list). If instead we require that there's no zombies on the list then the final kref_put must happen under the list protection lock, which means that locking context leaks all over the place. Not pretty - better to deal with zombies and wrap the locking just around the list_del in the destructor.
- When we walk the list we must _not_ hold the connector list lock. We walk the connector list at an absolutely massive amounts of places, if all those places can't ever call drm_connector_unreference the code would get unecessarily complicated.
- connector_list needs it own lock, again too many places that walk it that we could reuse e.g. mode_config.mutex without resulting in inversions.
- Lots of code uses these loops to look-up a connector, i.e. they want to be able to call drm_connector_reference. But on the other hand we want connectors to stay on that list until they're dead (i.e. connector_list can't hold a full reference), which means despite the "can't hold lock for the loop body" rule we need to make sure a connector doesn't suddenly become a zombie.
At first Dave&I discussed various horror-show approaches using srcu, but turns out it's fairly easy:
- For the loop body we always hold an additional reference to the current connector. That means it can't zombify, and it also means it'll stay on the list, which means we can use it as our iterator to find the next connector.
- When we try to find the next connector we only have to jump over zombies. To make sure we don't chase bad pointers that entire loop is protected with the new connect_list_lock spinlock. And because we know that we're starting out with a non-zombie (need to drop our reference for the old connector only after we have our new one), we're guranteed to still be on the connector_list and either find the next non-zombie or complete the iteration.
- Only downside is that we need to make sure that the temporary reference for the loop body doesn't leak. iter_get/put() functions + lockdep make sure that's the case.
- To avoid a flag day the new iterator macro has an _iter postfix. We can rename it back once all the users of the unsafe version are gone (there's about 100 list walkers for the connector_list).
For now this patch only converts all the list walking in the core, leaving helpers and drivers for later patches. The nice thing is that we can now finally remove 2 FIXME comments from the register/unregister functions.
v2: - use irqsafe spinlocks, so that we can use this in drm_state_dump too. - nuke drm_modeset_lock_all from drm_connector_init, now entirely cargo-culted nonsense.
v3: - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). - pretty kerneldoc - add EXPORT_SYMBOL, helpers&drivers are supposed to use this.
v4: Change lockdep annotations to only check whether we release the iter fake lock again (i.e. make sure that iter_put is called), but not check any locking dependecies itself. That seams to require a recursive read lock in trylock mode.
Cc: Dave Airlie <airlied@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
|
H A D | drm_mode_config.h | diff 613051dac40da1751ab269572766d3348d45a197 Wed Dec 14 00:08:06 CET 2016 Daniel Vetter <daniel.vetter@ffwll.ch> drm: locking&new iterators for connector_list
The requirements for connector_list locking are a bit tricky: - We need to be able to jump over zombie conectors (i.e. with refcount == 0, but not yet removed from the list). If instead we require that there's no zombies on the list then the final kref_put must happen under the list protection lock, which means that locking context leaks all over the place. Not pretty - better to deal with zombies and wrap the locking just around the list_del in the destructor.
- When we walk the list we must _not_ hold the connector list lock. We walk the connector list at an absolutely massive amounts of places, if all those places can't ever call drm_connector_unreference the code would get unecessarily complicated.
- connector_list needs it own lock, again too many places that walk it that we could reuse e.g. mode_config.mutex without resulting in inversions.
- Lots of code uses these loops to look-up a connector, i.e. they want to be able to call drm_connector_reference. But on the other hand we want connectors to stay on that list until they're dead (i.e. connector_list can't hold a full reference), which means despite the "can't hold lock for the loop body" rule we need to make sure a connector doesn't suddenly become a zombie.
At first Dave&I discussed various horror-show approaches using srcu, but turns out it's fairly easy:
- For the loop body we always hold an additional reference to the current connector. That means it can't zombify, and it also means it'll stay on the list, which means we can use it as our iterator to find the next connector.
- When we try to find the next connector we only have to jump over zombies. To make sure we don't chase bad pointers that entire loop is protected with the new connect_list_lock spinlock. And because we know that we're starting out with a non-zombie (need to drop our reference for the old connector only after we have our new one), we're guranteed to still be on the connector_list and either find the next non-zombie or complete the iteration.
- Only downside is that we need to make sure that the temporary reference for the loop body doesn't leak. iter_get/put() functions + lockdep make sure that's the case.
- To avoid a flag day the new iterator macro has an _iter postfix. We can rename it back once all the users of the unsafe version are gone (there's about 100 list walkers for the connector_list).
For now this patch only converts all the list walking in the core, leaving helpers and drivers for later patches. The nice thing is that we can now finally remove 2 FIXME comments from the register/unregister functions.
v2: - use irqsafe spinlocks, so that we can use this in drm_state_dump too. - nuke drm_modeset_lock_all from drm_connector_init, now entirely cargo-culted nonsense.
v3: - do {} while (!kref_get_unless_zero), makes for a tidier loop (Dave). - pretty kerneldoc - add EXPORT_SYMBOL, helpers&drivers are supposed to use this.
v4: Change lockdep annotations to only check whether we release the iter fake lock again (i.e. make sure that iter_put is called), but not check any locking dependecies itself. That seams to require a recursive read lock in trylock mode.
Cc: Dave Airlie <airlied@gmail.com> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161213230814.19598-6-daniel.vetter@ffwll.ch
|