Skip to content

Commit ea6942d

Browse files
plbossartvinodkoul
authored andcommitted
soundwire: intel: fix potential race condition during power down
The power down sequence sets the link_up flag as false outside of the mutex_lock. This is potentially unsafe. In additional the flow in that sequence can be improved by first testing if the link was powered, setting the link_up flag as false and proceeding with the power down. In case the CPA bits cannot be cleared, we only flag an error since we cannot deal with interrupts any longer. Signed-off-by: Pierre-Louis Bossart <[email protected]> Reviewed-by: Ranjani Sridharan <[email protected]> Signed-off-by: Bard Liao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent dd81e7c commit ea6942d

File tree

1 file changed

+13
-10
lines changed

1 file changed

+13
-10
lines changed

drivers/soundwire/intel.c

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -538,12 +538,14 @@ static int intel_link_power_down(struct sdw_intel *sdw)
538538

539539
mutex_lock(sdw->link_res->shim_lock);
540540

541-
intel_shim_master_ip_to_glue(sdw);
542-
543541
if (!(*shim_mask & BIT(link_id)))
544542
dev_err(sdw->cdns.dev,
545543
"%s: Unbalanced power-up/down calls\n", __func__);
546544

545+
sdw->cdns.link_up = false;
546+
547+
intel_shim_master_ip_to_glue(sdw);
548+
547549
*shim_mask &= ~BIT(link_id);
548550

549551
if (!*shim_mask) {
@@ -560,18 +562,19 @@ static int intel_link_power_down(struct sdw_intel *sdw)
560562
link_control &= spa_mask;
561563

562564
ret = intel_clear_bit(shim, SDW_SHIM_LCTL, link_control, cpa_mask);
565+
if (ret < 0) {
566+
dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
567+
568+
/*
569+
* we leave the sdw->cdns.link_up flag as false since we've disabled
570+
* the link at this point and cannot handle interrupts any longer.
571+
*/
572+
}
563573
}
564574

565575
mutex_unlock(sdw->link_res->shim_lock);
566576

567-
if (ret < 0) {
568-
dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
569-
570-
return ret;
571-
}
572-
573-
sdw->cdns.link_up = false;
574-
return 0;
577+
return ret;
575578
}
576579

577580
static void intel_shim_sync_arm(struct sdw_intel *sdw)

0 commit comments

Comments
 (0)