[PATCH 0/5] soundwire: fix ACK/NAK handling and improve log
The existing code reports a NAK only when ACK=0 This is not aligned with the SoundWire 1.x specifications.
Table 32 in the SoundWire 1.2 specification shows that a Device shall not set NAK=1 if ACK=1. But Table 33 shows the Combined Response may very well be NAK=1/ACK=1, e.g. if another Device than the one addressed reports a parity error.
NAK=1 signals a 'Command_Aborted', regardless of the ACK bit value.
Move the tests for NAK so that the NAK=1/ACK=1 combination is properly detected according to the specification.
Also, improve the demesg log to get more information for debugging.
Bard Liao (1): soundwire: bus: add more details to track failed transfers
Pierre-Louis Bossart (4): soundwire: use consistent format for Slave devID logs soundwire: cadence: add status in dev_dbg 'State change' log soundwire: cadence: fix ACK/NAK handling soundwire: cadence: adjust verbosity in response handling
drivers/soundwire/bus.c | 11 ++++++----- drivers/soundwire/cadence_master.c | 29 +++++++++++++++-------------- drivers/soundwire/slave.c | 10 ++++------ 3 files changed, 25 insertions(+), 25 deletions(-)
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
We mix decimal and hexadecimal values, this leads to confusions in dmesg logs and bug reports. Let's add a 0x prefix for all hexadecimal values and a format when more than 4 bits are used.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Reviewed-by: Rander Wang rander.wang@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 5 ++--- drivers/soundwire/slave.c | 10 ++++------ 2 files changed, 6 insertions(+), 9 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index d1e8c3a54976..3cc006bfae71 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -679,9 +679,8 @@ void sdw_extract_slave_id(struct sdw_bus *bus, id->class_id = SDW_CLASS_ID(addr);
dev_dbg(bus->dev, - "SDW Slave class_id %x, part_id %x, mfg_id %x, unique_id %x, version %x\n", - id->class_id, id->part_id, id->mfg_id, - id->unique_id, id->sdw_version); + "SDW Slave class_id 0x%02x, mfg_id 0x%04x, part_id 0x%04x, unique_id 0x%x, version 0x%x\n", + id->class_id, id->mfg_id, id->part_id, id->unique_id, id->sdw_version); }
static int sdw_program_device_num(struct sdw_bus *bus) diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c index a08f4081c1c4..180f38bd003b 100644 --- a/drivers/soundwire/slave.c +++ b/drivers/soundwire/slave.c @@ -163,15 +163,13 @@ int sdw_acpi_find_slaves(struct sdw_bus *bus)
if (id.unique_id != id2.unique_id) { dev_dbg(bus->dev, - "Valid unique IDs %x %x for Slave mfg %x part %d\n", - id.unique_id, id2.unique_id, - id.mfg_id, id.part_id); + "Valid unique IDs 0x%x 0x%x for Slave mfg_id 0x%04x, part_id 0x%04x\n", + id.unique_id, id2.unique_id, id.mfg_id, id.part_id); ignore_unique_id = false; } else { dev_err(bus->dev, - "Invalid unique IDs %x %x for Slave mfg %x part %d\n", - id.unique_id, id2.unique_id, - id.mfg_id, id.part_id); + "Invalid unique IDs 0x%x 0x%x for Slave mfg_id 0x%04x, part_id 0x%04x\n", + id.unique_id, id2.unique_id, id.mfg_id, id.part_id); return -ENODEV; } }
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
The existing debug log only mentions a state change, without providing any details. For integration and stress-tests, it's helpful to see in the dmesg log the reason for the state change.
The value is intended for power users and isn't converted as human-readable values. But for the record each device has a 4-bit status:
BIT(0): Unattached BIT(1): Attached BIT(2): Alert BIT(3): Reserved (should not happen)
Example:
[ 121.891288] intel-sdw intel-sdw.0: Slave status change: 0x2
<< this shows a Device0 Attached
[ 121.891295] soundwire sdw-master-0: Slave attached, programming device number [ 121.891629] soundwire sdw-master-0: SDW Slave Addr: 30025d071101 [ 121.891632] soundwire sdw-master-0: SDW Slave class_id 1, part_id 711, mfg_id 25d, unique_id 0, version 3 [ 121.892011] intel-sdw intel-sdw.0: Msg ignored for Slave 0 [ 121.892013] soundwire sdw-master-0: No more devices to enumerate [ 121.892200] intel-sdw intel-sdw.0: Slave status change: 0x21
<< this shows the device now Attached as Device1 and Unattached as Device0, i.e. a successful enumeration.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/cadence_master.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 9fa55164354a..801e1fef59d8 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -734,21 +734,18 @@ static void cdns_read_response(struct sdw_cdns *cdns) }
static int cdns_update_slave_status(struct sdw_cdns *cdns, - u32 slave0, u32 slave1) + u64 slave_intstat) { enum sdw_slave_status status[SDW_MAX_DEVICES + 1]; bool is_slave = false; - u64 slave; u32 mask; int i, set_status;
- /* combine the two status */ - slave = ((u64)slave1 << 32) | slave0; memset(status, 0, sizeof(status));
for (i = 0; i <= SDW_MAX_DEVICES; i++) { - mask = (slave >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) & - CDNS_MCP_SLAVE_STATUS_BITS; + mask = (slave_intstat >> (i * CDNS_MCP_SLAVE_STATUS_NUM)) & + CDNS_MCP_SLAVE_STATUS_BITS; if (!mask) continue;
@@ -918,13 +915,17 @@ static void cdns_update_slave_status_work(struct work_struct *work) struct sdw_cdns *cdns = container_of(work, struct sdw_cdns, work); u32 slave0, slave1; - - dev_dbg_ratelimited(cdns->dev, "Slave status change\n"); + u64 slave_intstat;
slave0 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT0); slave1 = cdns_readl(cdns, CDNS_MCP_SLAVE_INTSTAT1);
- cdns_update_slave_status(cdns, slave0, slave1); + /* combine the two status */ + slave_intstat = ((u64)slave1 << 32) | slave0; + + dev_dbg_ratelimited(cdns->dev, "Slave status change: 0x%llx\n", slave_intstat); + + cdns_update_slave_status(cdns, slave_intstat); cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT0, slave0); cdns_writel(cdns, CDNS_MCP_SLAVE_INTSTAT1, slave1);
The current error log does not provide details on the type of transfers and which address/count was requested. All this information can help locate in which parts of the configuration process an error occurred.
Co-developed-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/bus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 3cc006bfae71..6e1c988f3845 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -267,8 +267,10 @@ static int sdw_transfer_unlocked(struct sdw_bus *bus, struct sdw_msg *msg)
ret = do_transfer(bus, msg); if (ret != 0 && ret != -ENODATA) - dev_err(bus->dev, "trf on Slave %d failed:%d\n", - msg->dev_num, ret); + dev_err(bus->dev, "trf on Slave %d failed:%d %s addr %x count %d\n", + msg->dev_num, ret, + (msg->flags & SDW_MSG_FLAG_WRITE) ? "write" : "read", + msg->addr, msg->len);
if (msg->page) sdw_reset_page(bus, msg->dev_num);
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
The existing code reports a NAK only when ACK=0 This is not aligned with the SoundWire 1.x specifications.
Table 32 in the SoundWire 1.2 specification shows that a Device shall not set NAK=1 if ACK=1. But Table 33 shows the Combined Response may very well be NAK=1/ACK=1, e.g. if another Device than the one addressed reports a parity error.
NAK=1 signals a 'Command_Aborted', regardless of the ACK bit value.
Move the tests for NAK so that the NAK=1/ACK=1 combination is properly detected according to the specification.
Fixes: 956baa1992f9a ('soundwire: cdns: Add sdw_master_ops and IO transfer support') Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/cadence_master.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 801e1fef59d8..d3c9cf920cbd 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -484,10 +484,10 @@ cdns_fill_msg_resp(struct sdw_cdns *cdns, if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) { no_ack = 1; dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n"); - if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { - nack = 1; - dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); - } + } + if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { + nack = 1; + dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); } }
From: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com
There are too many logs on startup, e.g.
[ 8811.851497] cdns_fill_msg_resp: 2 callbacks suppressed [ 8811.851497] intel-sdw intel-sdw.0: Msg Ack not received [ 8811.851498] intel-sdw intel-sdw.0: Msg Ack not received [ 8811.851499] intel-sdw intel-sdw.0: Msg Ack not received [ 8811.851499] intel-sdw intel-sdw.0: Msg Ack not received [ 8811.851500] intel-sdw intel-sdw.0: Msg Ack not received [ 8811.851500] intel-sdw intel-sdw.0: Msg Ack not received [ 8811.851502] intel-sdw intel-sdw.0: Msg ignored for Slave 0 [ 8811.851503] soundwire sdw-master-0: No more devices to enumerate
We can skip the 'Msg Ack not received' since it's typical of the enumeration end, and conversely add the information on which command fails.
Signed-off-by: Pierre-Louis Bossart pierre-louis.bossart@linux.intel.com Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com --- drivers/soundwire/cadence_master.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index d3c9cf920cbd..8d7166ffd4ad 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -483,11 +483,11 @@ cdns_fill_msg_resp(struct sdw_cdns *cdns, for (i = 0; i < count; i++) { if (!(cdns->response_buf[i] & CDNS_MCP_RESP_ACK)) { no_ack = 1; - dev_dbg_ratelimited(cdns->dev, "Msg Ack not received\n"); + dev_vdbg(cdns->dev, "Msg Ack not received, cmd %d\n", i); } if (cdns->response_buf[i] & CDNS_MCP_RESP_NACK) { nack = 1; - dev_err_ratelimited(cdns->dev, "Msg NACK received\n"); + dev_err_ratelimited(cdns->dev, "Msg NACK received, cmd %d\n", i); } }
On 15-01-21, 13:37, Bard Liao wrote:
The existing code reports a NAK only when ACK=0 This is not aligned with the SoundWire 1.x specifications.
Table 32 in the SoundWire 1.2 specification shows that a Device shall not set NAK=1 if ACK=1. But Table 33 shows the Combined Response may very well be NAK=1/ACK=1, e.g. if another Device than the one addressed reports a parity error.
NAK=1 signals a 'Command_Aborted', regardless of the ACK bit value.
Move the tests for NAK so that the NAK=1/ACK=1 combination is properly detected according to the specification.
Also, improve the demesg log to get more information for debugging.
Applied, thanks
participants (2)
-
Bard Liao
-
Vinod Koul