Skip to content

Commit 0c5a1f9

Browse files
committed
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 <pierre-louis.bossart@linux.intel.com>
1 parent c7ad7fa commit 0c5a1f9

1 file changed

Lines changed: 13 additions & 10 deletions

File tree

drivers/soundwire/intel.c

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

465465
mutex_lock(sdw->link_res->shim_lock);
466466

467-
intel_shim_master_ip_to_glue(sdw);
468-
469467
if (!(*shim_mask & BIT(link_id)))
470468
dev_err(sdw->cdns.dev,
471469
"%s: Unbalanced power-up/down calls\n", __func__);
472470

471+
sdw->cdns.link_up = false;
472+
473+
intel_shim_master_ip_to_glue(sdw);
474+
473475
*shim_mask &= ~BIT(link_id);
474476

475477
if (!*shim_mask) {
@@ -486,18 +488,19 @@ static int intel_link_power_down(struct sdw_intel *sdw)
486488
link_control &= spa_mask;
487489

488490
ret = intel_clear_bit(shim, SDW_SHIM_LCTL, link_control, cpa_mask);
491+
if (ret < 0) {
492+
dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
493+
494+
/*
495+
* we leave the sdw->cdns.link_up flag as false since we've disabled
496+
* the link at this point and cannot handle interrupts any longer.
497+
*/
498+
}
489499
}
490500

491501
mutex_unlock(sdw->link_res->shim_lock);
492502

493-
if (ret < 0) {
494-
dev_err(sdw->cdns.dev, "%s: could not power down link\n", __func__);
495-
496-
return ret;
497-
}
498-
499-
sdw->cdns.link_up = false;
500-
return 0;
503+
return ret;
501504
}
502505

503506
static void intel_shim_sync_arm(struct sdw_intel *sdw)

0 commit comments

Comments
 (0)