Re: [PATCH v3 2/3] i3c: master: dw: Map CCC hardware errors to I3C M0/M2
Frank Li <[email protected]>
| Newsgroups | org.infradead.lists.linux-i3c,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <ajWX3JExFZCqXj13@lizhi-Precision-Tower-5810> |
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 > 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