Skip to content

soundwire: Use get_device()/put_device() to protect callbacks#5799

Draft
rfvirgil wants to merge 1 commit into
thesofproject:topic/sof-devfrom
CirrusLogic:topic/soundwire-callback-lock
Draft

soundwire: Use get_device()/put_device() to protect callbacks#5799
rfvirgil wants to merge 1 commit into
thesofproject:topic/sof-devfrom
CirrusLogic:topic/soundwire-callback-lock

Conversation

@rfvirgil
Copy link
Copy Markdown

@rfvirgil rfvirgil commented Jun 2, 2026

Use get_device()/put_device() around calling driver callbacks instead of holding a mutex. This avoids mutex nesting and possible mutex inversion. Rename sdw_dev_lock to probe_remove_lock to make its purpose explicit.

When the core SoundWire code calls a driver callback it must be sure that the target driver is not unloaded while the callback is running. The code was using the sdw_dev_lock mutex to block driver remove() while the callback is executing.

This meant the callbacks were always called while holding that mutex, which could lead to mutex inversion. For example during enumeration:

  1. Take sdw_dev_lock
  2. Call update_status()
  3. Take regmap lock

But during BRA activity we could have:

  1. Take regmap lock
  2. Start BRA transaction
  3. Take sdw_dev_lock
  4. Call port_prep() and/or bus_config() callbacks

A better way to prevent the target driver being unloaded is to increment its reference count by calling get_device(). This pattern is seen in other drivers that need to call callbacks in another device. The mutex is only needed around the call to get_device() to prevent the driver being removed while its reference count is being incremented. After that, the mutex can be released becase the driver cannot be removed until its reference count is decremented.

Change-Id: I1f5cfd81d6204cf3aa92ddc2896af17307edd9c1

Use get_device()/put_device() around calling driver callbacks instead
of holding a mutex. This avoids mutex nesting and possible mutex
inversion. Rename sdw_dev_lock to probe_remove_lock to make its
purpose explicit.

When the core SoundWire code calls a driver callback it must be sure
that the target driver is not unloaded while the callback is running.
The code was using the sdw_dev_lock mutex to block driver remove()
while the callback is executing.

This meant the callbacks were always called while holding that mutex,
which could lead to mutex inversion. For example during enumeration:

1) Take sdw_dev_lock
2) Call update_status()
3) Take regmap lock

But during BRA activity we could have:

1) Take regmap lock
2) Start BRA transaction
3) Take sdw_dev_lock
4) Call port_prep() and/or bus_config() callbacks

A better way to prevent the target driver being unloaded is to
increment its reference count by calling get_device(). This pattern
is seen in other drivers that need to call callbacks in another device.
The mutex is only needed around the call to get_device() to prevent
the driver being removed while its reference count is being incremented.
After that, the mutex can be released becase the driver cannot be
removed until its reference count is decremented.

Change-Id: I1f5cfd81d6204cf3aa92ddc2896af17307edd9c1
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
@rfvirgil rfvirgil requested review from bardliao and plbossart June 2, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant