Skip to content

Commit

Permalink
fixup! soundwire: cadence: re-check Peripheral status with delayed_work
Browse files Browse the repository at this point in the history
Add mutual exclusion so that the interrupt and delayed work cannot
update the status concurrently.

Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
  • Loading branch information
plbossart committed Jul 15, 2024
1 parent 0c7d09a commit 6a4c468
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 13 deletions.
26 changes: 13 additions & 13 deletions drivers/soundwire/cadence_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -891,8 +891,14 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
}
}

if (is_slave)
return sdw_handle_slave_status(&cdns->bus, status);
if (is_slave) {
int ret;

mutex_lock(&cdns->status_update_lock);
ret = sdw_handle_slave_status(&cdns->bus, status);
mutex_unlock(&cdns->status_update_lock);
return ret;
}

return 0;
}
Expand Down Expand Up @@ -998,14 +1004,6 @@ static void cdns_check_attached_status_dwork(struct work_struct *work)
int ret;
int i;

/*
* Mask the Slave interrupt while we try to update the status.
* This will prevent concurrent execution of this delayed_work
* and the regular update_status_work as a result of programming
* the device number to a non-zero value.
*/
cdns_updatel(cdns, CDNS_MCP_INTMASK, CDNS_MCP_INT_SLAVE_MASK, 0);

val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);

for (i = 0; i <= SDW_MAX_DEVICES; i++) {
Expand All @@ -1015,13 +1013,13 @@ static void cdns_check_attached_status_dwork(struct work_struct *work)
val >>= 2;
}

mutex_lock(&cdns->status_update_lock);
ret = sdw_handle_slave_status(&cdns->bus, status);
mutex_unlock(&cdns->status_update_lock);
if (ret < 0)
dev_err(cdns->dev, "%s: sdw_handle_slave_status failed: %d\n", __func__, ret);

/* unmask Slave interrupt now */
cdns_updatel(cdns, CDNS_MCP_INTMASK, CDNS_MCP_INT_SLAVE_MASK, CDNS_MCP_INT_SLAVE_MASK);
}

/**
* cdns_update_slave_status_work - update slave status in a work since we will need to handle
* other interrupts eg. CDNS_MCP_INT_RX_WL during the update slave
Expand Down Expand Up @@ -1774,6 +1772,8 @@ int sdw_cdns_probe(struct sdw_cdns *cdns)
init_completion(&cdns->tx_complete);
cdns->bus.port_ops = &cdns_port_ops;

mutex_init(&cdns->status_update_lock);

INIT_WORK(&cdns->work, cdns_update_slave_status_work);
INIT_DELAYED_WORK(&cdns->attach_dwork, cdns_check_attached_status_dwork);

Expand Down
4 changes: 4 additions & 0 deletions drivers/soundwire/cadence_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ struct sdw_cdns_dai_runtime {
* @link_up: Link status
* @msg_count: Messages sent on bus
* @dai_runtime_array: runtime context for each allocated DAI.
* @status_update_lock: protect concurrency between interrupt-based and delayed work
* status update
*/
struct sdw_cdns {
struct device *dev;
Expand Down Expand Up @@ -153,6 +155,8 @@ struct sdw_cdns {
struct list_head list;

struct sdw_cdns_dai_runtime **dai_runtime_array;

struct mutex status_update_lock; /* add mutual exclusion to sdw_handle_slave_status() */
};

#define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus)
Expand Down

0 comments on commit 6a4c468

Please sign in to comment.