On Tue, Jan 03, 2023 at 04:15:31PM +0800, Haotien Hsu wrote: > From: Sing-Han Chen <singhanc@xxxxxxxxxx> > > For the CCGx, when the OPM field in the INTR_REG is cleared, then the > CCI data in the PPM is reset. > > To align with the CCGx UCSI interface guide, this patch updates the > driver to copy CCI and MESSAGE_IN before clearing UCSI interrupt. > When a new command is sent, the driver will clear the old CCI and > MESSAGE_IN copy. > > Finally, clear UCSI_READ_INT before calling complete() to ensure that > the ucsi_ccg_sync_write() would wait for the interrupt handling to > complete. > It prevents the driver from resetting CCI prematurely. > > Signed-off-by: Sing-Han Chen <singhanc@xxxxxxxxxx> > Signed-off-by: Haotien Hsu <haotienh@xxxxxxxxxx> > --- > V1->V2 > - Fix uninitialized symbol 'cci' > v2->v3 > - Remove wrong Reported-by tags > --- > drivers/usb/typec/ucsi/ucsi_ccg.c | 86 ++++++++++++++++++++++++++++--- > 1 file changed, 79 insertions(+), 7 deletions(-) > > diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c > index eab3012e1b01..b35a3a97c9fb 100644 > --- a/drivers/usb/typec/ucsi/ucsi_ccg.c > +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c > @@ -192,6 +192,12 @@ struct ucsi_ccg_altmode { > bool checked; > } __packed; > > +#define CCGX_MESSAGE_IN_MAX 4 > +struct op_region { > + u32 cci; > + u32 message_in[CCGX_MESSAGE_IN_MAX]; > +}; > + > struct ucsi_ccg { > struct device *dev; > struct ucsi *ucsi; > @@ -222,6 +228,9 @@ struct ucsi_ccg { > bool has_multiple_dp; > struct ucsi_ccg_altmode orig[UCSI_MAX_ALTMODES]; > struct ucsi_ccg_altmode updated[UCSI_MAX_ALTMODES]; > + > + spinlock_t op_lock; What does this lock protect? Please document that so that we can verify if this really is a correct change _AND_ so we know what future changes need to take the lock or not. > + struct op_region op_data; > }; > > static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) > @@ -305,12 +314,57 @@ static int ccg_write(struct ucsi_ccg *uc, u16 rab, const u8 *data, u32 len) > return 0; > } > > +static void ccg_op_region_read(struct ucsi_ccg *uc, unsigned int offset, > + void *val, size_t val_len) > +{ > + struct op_region *data = &uc->op_data; > + > + spin_lock(&uc->op_lock); > + if (offset == UCSI_CCI) > + memcpy(val, &data->cci, val_len); > + else if (offset == UCSI_MESSAGE_IN) > + memcpy(val, &data->message_in, val_len); > + spin_unlock(&uc->op_lock); > +} > + > +static void ccg_op_region_update(struct ucsi_ccg *uc, u32 cci) > +{ > + u16 reg = CCGX_RAB_UCSI_DATA_BLOCK(UCSI_MESSAGE_IN); > + struct op_region *data = &uc->op_data; > + u32 message_in[CCGX_MESSAGE_IN_MAX]; > + > + if (UCSI_CCI_LENGTH(cci)) > + if (ccg_read(uc, reg, (void *)&message_in, > + sizeof(message_in))) { > + dev_err(uc->dev, "failed to read MESSAGE_IN\n"); What can userspace do with this error? Will it be repeated a lot? thanks, greg k-h