Commit fbbc73a2 authored by Simon Trimmer's avatar Simon Trimmer Committed by Vinod Koul

soundwire: cadence: fix updating slave status when a bus has multiple peripherals

The cadence IP explicitly reports slave status changes with bits for
each possible change. The function cdns_update_slave_status() attempts
to translate this into the current status of each of the slaves.

However when there are multiple peripherals on a bus any slave that did
not have a status change when the work function ran would not have it's
status updated - the array is initialised to a value that equates to
UNATTACHED and this can cause spurious reports that slaves had dropped
off the bus.

In the case where a slave has no status change or has multiple status
changes the value from the last PING command is used.
Signed-off-by: default avatarSimon Trimmer <simont@opensource.cirrus.com>
Signed-off-by: default avatarRichard Fitzgerald <rf@opensource.cirrus.com>
Reviewed-by: default avatarPierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Link: https://lore.kernel.org/r/20220914160248.1047627-2-rf@opensource.cirrus.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 279e46bc
...@@ -782,6 +782,7 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, ...@@ -782,6 +782,7 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
bool is_slave = false; bool is_slave = false;
u32 mask; u32 mask;
u32 val;
int i, set_status; int i, set_status;
memset(status, 0, sizeof(status)); memset(status, 0, sizeof(status));
...@@ -789,12 +790,12 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, ...@@ -789,12 +790,12 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
for (i = 0; i <= SDW_MAX_DEVICES; i++) { for (i = 0; i <= SDW_MAX_DEVICES; i++) {
mask = (slave_intstat >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) & mask = (slave_intstat >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) &
CDNS_MCP_SLAVE_STATUS_BITS; CDNS_MCP_SLAVE_STATUS_BITS;
if (!mask)
continue;
is_slave = true;
set_status = 0; set_status = 0;
if (mask) {
is_slave = true;
if (mask & CDNS_MCP_SLAVE_INTSTAT_RESERVED) { if (mask & CDNS_MCP_SLAVE_INTSTAT_RESERVED) {
status[i] = SDW_SLAVE_RESERVED; status[i] = SDW_SLAVE_RESERVED;
set_status++; set_status++;
...@@ -814,16 +815,13 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, ...@@ -814,16 +815,13 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
status[i] = SDW_SLAVE_UNATTACHED; status[i] = SDW_SLAVE_UNATTACHED;
set_status++; set_status++;
} }
}
/* first check if Slave reported multiple status */ /*
if (set_status > 1) { * check that there was a single reported Slave status and when
u32 val; * there is not use the latest status extracted from PING commands
*/
dev_warn_ratelimited(cdns->dev, if (set_status != 1) {
"Slave %d reported multiple Status: %d\n",
i, mask);
/* check latest status extracted from PING commands */
val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT); val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
val >>= (i * 2); val >>= (i * 2);
...@@ -842,11 +840,6 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns, ...@@ -842,11 +840,6 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
status[i] = SDW_SLAVE_RESERVED; status[i] = SDW_SLAVE_RESERVED;
break; break;
} }
dev_warn_ratelimited(cdns->dev,
"Slave %d status updated to %d\n",
i, status[i]);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment