Message ID | 20190613180931.65445-3-swboyd@chromium.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | tpm: Add driver for cr50 | expand |
On Thu, Jun 13, 2019 at 11:09:25AM -0700, Stephen Boyd wrote: > From: Andrey Pronin <apronin@chromium.org> > > If tpm reports a bigger burstcnt than allowed by the physical protocol, > set burstcnt to the max allowed value. > > In practice, seen in case of xfer issues (e.g. in spi interface case, > lost header causing flow control issues and wrong values returned on read > from TPM_STS). Without catching, causes the physical layer to reject xfer. > > Signed-off-by: Andrey Pronin <apronin@chromium.org> > Reviewed-by: Dmitry Torokhov <dtor@chromium.org> > Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > [swboyd@chromium.org: Drop extra parenthesis in if statement] > Signed-off-by: Stephen Boyd <swboyd@chromium.org> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> /Jarkko
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index b9f64684c3fb..ecf703802333 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -272,8 +272,15 @@ static int get_burstcount(struct tpm_chip *chip) return rc; burstcnt = (value >> 8) & 0xFFFF; - if (burstcnt) + if (burstcnt) { + if (priv->phy_ops->max_xfer_size && + burstcnt > priv->phy_ops->max_xfer_size) { + dev_warn(&chip->dev, + "Bad burstcnt read: %d\n", burstcnt); + burstcnt = priv->phy_ops->max_xfer_size; + } return burstcnt; + } usleep_range(TPM_TIMEOUT_USECS_MIN, TPM_TIMEOUT_USECS_MAX); } while (time_before(jiffies, stop)); return -EBUSY; diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index f48125f1e6e0..bb4979cf81ed 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -110,6 +110,7 @@ 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); + u16 max_xfer_size; }; static inline int tpm_tis_read_bytes(struct tpm_tis_data *data, u32 addr,