On Tue, Apr 07, 2020 at 07:20:39PM +0300, amirmizi6@xxxxxxxxx wrote: > From: Amir Mizinski <amirmizi6@xxxxxxxxx> > > In order to validate data integrity we need to compute the crc over the data > sent in lower layer (I2C for instance). s/crc/CRC/ > To do that tpm_tis_check_data() calls a "check_data" operation (if available). "check_data" does not exist. > If data integrity check fails, a retry to save the sent/received > data is implemented in tpm_tis_send_main()/tpm_tis_recv() functions. > > Considering this commit, the following steps are done when sending a command: > 1. Host writes to TPM_STS.commandReady. > 2. Host writes command. > 3. Host checks that TPM received data is valid. > 4. If data is currupted go to step 1. > > When receiving data: > 1. Host checks that TPM_STS.dataAvail is set. > 2. Host saves received data. > 3. Host checks that received data is correct. > 4. If data is currupted Host writes to TPM_STS.responseRetry and go to > step 1. These sequences in the commit message look somewhat uselss. Maybe just remove them. > > Co-developed-by: Christophe Ricard <christophe-h.ricard@xxxxxx> > Signed-off-by: Christophe Ricard <christophe-h.ricard@xxxxxx> > Signed-off-by: Amir Mizinski <amirmizi6@xxxxxxxxx> > --- > drivers/char/tpm/tpm_tis_core.c | 102 +++++++++++++++++++++++++--------------- > drivers/char/tpm/tpm_tis_core.h | 3 ++ > 2 files changed, 67 insertions(+), 38 deletions(-) > > diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c > index 27c6ca0..6c4f232 100644 > --- a/drivers/char/tpm/tpm_tis_core.c > +++ b/drivers/char/tpm/tpm_tis_core.c > @@ -242,6 +242,15 @@ static u8 tpm_tis_status(struct tpm_chip *chip) > return status; > } > > +static bool tpm_tis_check_data(struct tpm_chip *chip, const u8 *buf, size_t len) Not sure if this is the best possible function name, "check" can mean almost anything. > +{ > + struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > + > + if (priv->phy_ops->check_data) > + return priv->phy_ops->check_data(priv, buf, len); New line here before the return statement. > + return true; > +} > + > static void tpm_tis_ready(struct tpm_chip *chip) > { > struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > @@ -308,47 +317,59 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) > { > struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > int size = 0; > - int status; > + int status, i; > u32 expected; > + bool check_data = false; > > - if (count < TPM_HEADER_SIZE) { > - size = -EIO; > - goto out; > - } > + for (i = 0; i < TPM_RETRY; i++) { > + if (count < TPM_HEADER_SIZE) { > + size = -EIO; > + goto out; > + } > > - size = recv_data(chip, buf, TPM_HEADER_SIZE); > - /* read first 10 bytes, including tag, paramsize, and result */ > - if (size < TPM_HEADER_SIZE) { > - dev_err(&chip->dev, "Unable to read header\n"); > - goto out; > - } > + size = recv_data(chip, buf, TPM_HEADER_SIZE); > + /* read first 10 bytes, including tag, paramsize, and result */ > + if (size < TPM_HEADER_SIZE) { > + dev_err(&chip->dev, "Unable to read header\n"); > + goto out; > + } > > - expected = be32_to_cpu(*(__be32 *) (buf + 2)); > - if (expected > count || expected < TPM_HEADER_SIZE) { > - size = -EIO; > - goto out; > - } > + expected = be32_to_cpu(*(__be32 *) (buf + 2)); > + if (expected > count || expected < TPM_HEADER_SIZE) { > + size = -EIO; > + goto out; > + } > > - size += recv_data(chip, &buf[TPM_HEADER_SIZE], > - expected - TPM_HEADER_SIZE); > - if (size < expected) { > - dev_err(&chip->dev, "Unable to read remainder of result\n"); > - size = -ETIME; > - goto out; > - } > + size += recv_data(chip, &buf[TPM_HEADER_SIZE], > + expected - TPM_HEADER_SIZE); > + if (size < expected) { > + dev_err(&chip->dev, "Unable to read remainder of result\n"); > + size = -ETIME; > + goto out; > + } > > - if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, > - &priv->int_queue, false) < 0) { > - size = -ETIME; > - goto out; > + if (wait_for_tpm_stat(chip, TPM_STS_VALID, chip->timeout_c, > + &priv->int_queue, false) < 0) { > + size = -ETIME; > + goto out; > + } > + > + status = tpm_tis_status(chip); > + if (status & TPM_STS_DATA_AVAIL) { /* retry? */ > + dev_err(&chip->dev, "Error left over data\n"); > + size = -EIO; > + goto out; > + } > + > + check_data = tpm_tis_check_data(chip, buf, size); > + if (!check_data) > + tpm_tis_write8(priv, TPM_STS(priv->locality), > + TPM_STS_RESPONSE_RETRY); > + else > + break; > } > - status = tpm_tis_status(chip); > - if (status & TPM_STS_DATA_AVAIL) { /* retry? */ > - dev_err(&chip->dev, "Error left over data\n"); > + if (!check_data) > size = -EIO; > - goto out; > - } > - > out: > tpm_tis_ready(chip); > return size; > @@ -453,14 +474,19 @@ static void disable_interrupts(struct tpm_chip *chip) > static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len) > { > struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev); > - int rc; > + int rc, i; > u32 ordinal; > unsigned long dur; > + bool data_valid = false; > > - rc = tpm_tis_send_data(chip, buf, len); > - if (rc < 0) > - return rc; > - > + for (i = 0; i < TPM_RETRY && !data_valid; i++) { > + rc = tpm_tis_send_data(chip, buf, len); > + if (rc < 0) > + return rc; > + data_valid = tpm_tis_check_data(chip, buf, len); > + } > + if (!data_valid) > + return -EIO; > /* go and do it */ > rc = tpm_tis_write8(priv, TPM_STS(priv->locality), TPM_STS_GO); > if (rc < 0) > diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h > index d06c65b..486c2e9 100644 > --- a/drivers/char/tpm/tpm_tis_core.h > +++ b/drivers/char/tpm/tpm_tis_core.h > @@ -34,6 +34,7 @@ enum tis_status { > TPM_STS_GO = 0x20, > TPM_STS_DATA_AVAIL = 0x10, > TPM_STS_DATA_EXPECT = 0x08, > + TPM_STS_RESPONSE_RETRY = 0x02, > }; > > enum tis_int_flags { > @@ -106,6 +107,8 @@ struct tpm_tis_phy_ops { > int (*read16)(struct tpm_tis_data *data, u32 addr, u16 *result); > int (*read32)(struct tpm_tis_data *data, u32 addr, u32 *result); > int (*write32)(struct tpm_tis_data *data, u32 addr, u32 src); > + bool (*check_data)(struct tpm_tis_data *data, const u8 *buf, > + size_t len); Aren't you validating the contents of the buf? /Jarkko