Re: [PATCH v3 2/3] i3c: master: dw: Map CCC hardware errors to I3C M0/M2

"NG, TZE YEE" <[email protected]>
Newsgroups org.infradead.lists.linux-i3c,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 20/6/2026 3:26 am, Frank Li wrote:
> On Wed, Jun 10, 2026 at 06:54:07PM -0700, [email protected] wrote:
>> From: Adrian Ng Ho Yin <[email protected]>
>>
>> Map DesignWare response-queue status to standard I3C error codes in
>> ccc->err:
>>
>> - RESPONSE_ERROR_IBA_NACK and RESPONSE_ERROR_ADDRESS_NACK -> I3C_ERROR_M2
>> - RESPONSE_ERROR_CRC, RESPONSE_ERROR_PARITY, RESPONSE_ERROR_FRAME and
>>    RESPONSE_ERROR_TRANSF_ABORT -> I3C_ERROR_M0
>>
>> Return -EIO for RESPONSE_ERROR_ADDRESS_NACK so bus NACKs are not reported
>> as -EINVAL alongside I3C_ERROR_M2, consistent with IBA_NACK handling and
>> other I3C master drivers.
>>
>> The M0 mappings match the generic I/O failures already reported by
>> dw_i3c_master_end_xfer_locked() so the core can retry transient bus
>> integrity errors on CCC transfers.
>>
>> Reset ccc->err to I3C_ERROR_UNKNOWN before each transfer.
>>
>> Signed-off-by: Adrian Ng Ho Yin <[email protected]>
>> Signed-off-by: Tze Yee Ng <[email protected]>
>> ---
>>   drivers/i3c/master/dw-i3c-master.c | 31 +++++++++++++++++++++++++-----
>>   1 file changed, 26 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
>> index 06fdf8857b9c..45bde92d0342 100644
>> --- a/drivers/i3c/master/dw-i3c-master.c
>> +++ b/drivers/i3c/master/dw-i3c-master.c
>> @@ -493,6 +493,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
>>   			break;
>>   		case RESPONSE_ERROR_PARITY:
>>   		case RESPONSE_ERROR_IBA_NACK:
>> +		case RESPONSE_ERROR_ADDRESS_NACK:
>>   		case RESPONSE_ERROR_TRANSF_ABORT:
>>   		case RESPONSE_ERROR_CRC:
>>   		case RESPONSE_ERROR_FRAME:
>> @@ -502,7 +503,6 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
>>   			ret = -ENOSPC;
>>   			break;
>>   		case RESPONSE_ERROR_I2C_W_NACK_ERR:
>> -		case RESPONSE_ERROR_ADDRESS_NACK:
>>   		default:
>>   			ret = -EINVAL;
>>   			break;
>> @@ -708,12 +708,32 @@ static void dw_i3c_master_bus_cleanup(struct i3c_master_controller *m)
>>   	dw_i3c_master_disable(master);
>>   }
>>
>> +static void dw_i3c_ccc_map_err(struct i3c_ccc_cmd *ccc, struct dw_i3c_cmd *cmd)
>> +{
>> +	switch (cmd->error) {
>> +	case RESPONSE_ERROR_IBA_NACK:
>> +	case RESPONSE_ERROR_ADDRESS_NACK:
>> +		ccc->err = I3C_ERROR_M2;
>> +		break;
>> +	case RESPONSE_ERROR_CRC:
>> +	case RESPONSE_ERROR_PARITY:
>> +	case RESPONSE_ERROR_FRAME:
>> +	case RESPONSE_ERROR_TRANSF_ABORT:
>> +		ccc->err = I3C_ERROR_M0;
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +}
>> +
> 
> generaly this type map function like
> 
> enum i3c_error_code dw_i3c_ccc_map_err(int dw_err)
> {
> 	....
> }
> 
> ccc->err = dw_i3c_ccc_map_err(cmd->error);
> 
> Frank
Agree, in v4, we will change it to return enum i3c_error_code from the 
DW error code.>>   static int dw_i3c_ccc_set(struct dw_i3c_master *master,
>>   			  struct i3c_ccc_cmd *ccc)
>>   {
>>   	struct dw_i3c_cmd *cmd;
>>   	int ret, pos = 0;
>>
>> +	ccc->err = I3C_ERROR_UNKNOWN;
>> +
>>   	if (ccc->id & I3C_CCC_DIRECT) {
>>   		pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr);
>>   		if (pos < 0)
>> @@ -742,8 +762,8 @@ static int dw_i3c_ccc_set(struct dw_i3c_master *master,
>>   		dw_i3c_master_dequeue_xfer(master, xfer);
>>
>>   	ret = xfer->ret;
>> -	if (xfer->cmds[0].error == RESPONSE_ERROR_IBA_NACK)
>> -		ccc->err = I3C_ERROR_M2;
>> +	cmd = &xfer->cmds[0];
>> +	dw_i3c_ccc_map_err(ccc, cmd);
>>
>>   	return ret;
>>   }
>> @@ -754,6 +774,8 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
>>   	u16 req_len;
>>   	int ret, pos;
>>
>> +	ccc->err = I3C_ERROR_UNKNOWN;
>> +
>>   	pos = dw_i3c_master_get_addr_pos(master, ccc->dests[0].addr);
>>   	if (pos < 0)
>>   		return pos;
>> @@ -784,10 +806,9 @@ static int dw_i3c_ccc_get(struct dw_i3c_master *master, struct i3c_ccc_cmd *ccc)
>>
>>   	ret = xfer->ret;
>>   	cmd = &xfer->cmds[0];
>> +	dw_i3c_ccc_map_err(ccc, cmd);
>>   	if (!ret)
>>   		ccc->dests[0].payload.len = cmd->rx_len;
>> -	if (cmd->error == RESPONSE_ERROR_IBA_NACK)
>> -		ccc->err = I3C_ERROR_M2;
>>
>>   	return ret;
>>   }
>> --
>> 2.43.7
>>

-- 
linux-i3c mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-i3c
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.