lkml.org 
[lkml]   [2012]   [Jun]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH 2/2] CHROMIUM: tpm: tpm_i2c_infineon: Lock the I2C adapter for a sequence of requests.

    Signed-off-by: Marcel Selhorst <tpmdd@selhorst.net>

    Zitat von Peter Huewe <peter.huewe@infineon.com>:

    > From: Bryan Freed <bfreed@chromium.org>
    >
    > This is derived from Peter Huewe's recommended fix:
    >
    > On some ChromeOS systems, a TPM sharing the I2C bus with another device
    > gets confused when it sees I2C requests to that other device.
    > This change locks the I2C adapter for the duration of the full sequence
    > of I2C requests the TPM needs to complete.
    >
    > smbus_xfer is not supported, but SMBUS is not supported by the original
    > driver, either.
    >
    > Signed-off-by: Bryan Freed <bfreed@chromium.org>
    > Signed-off-by: Peter Huewe <peter.huewe@infineon.com>
    > ---
    > drivers/char/tpm/tpm_i2c_infineon.c | 45
    > +++++++++++++++++++++++++++++++---
    > 1 files changed, 41 insertions(+), 4 deletions(-)
    >
    > diff --git a/drivers/char/tpm/tpm_i2c_infineon.c
    > b/drivers/char/tpm/tpm_i2c_infineon.c
    > index 54b9a5e..1794a09 100644
    > --- a/drivers/char/tpm/tpm_i2c_infineon.c
    > +++ b/drivers/char/tpm/tpm_i2c_infineon.c
    > @@ -68,6 +68,31 @@ struct tpm_inf_dev {
    > static struct tpm_inf_dev tpm_dev;
    > static struct i2c_driver tpm_tis_i2c_driver;
    >
    > +
    > +/*
    > + * Copy i2c-core:i2c_transfer() as close as possible without the
    > adapter locks
    > + * and algorithm check. These are done by the caller for atomicity.
    > + * Unfortunately we have to use this as a workaround in multislave
    > environments
    > + * as no other suitable and working mechanism is available.
    > + */
    > +static int i2c_transfer_nolock(struct i2c_adapter *adap, struct
    > i2c_msg *msgs,
    > + int num)
    > +{
    > + unsigned long orig_jiffies;
    > + int ret, try;
    > +
    > + /* Retry automatically on arbitration loss */
    > + orig_jiffies = jiffies;
    > + for (ret = 0, try = 0; try <= adap->retries; try++) {
    > + ret = adap->algo->master_xfer(adap, msgs, num);
    > + if (ret != -EAGAIN)
    > + break;
    > + if (time_after(jiffies, orig_jiffies + adap->timeout))
    > + break;
    > + }
    > + return ret;
    > +}
    > +
    > /*
    > * iic_tpm_read() - read from TPM register
    > * @addr: register address to read from
    > @@ -96,8 +121,13 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len)
    > int rc;
    > int count;
    >
    > + /* Lock the adapter for the duration of the whole sequence. */
    > + if (!tpm_dev.client->adapter->algo->master_xfer)
    > + return -EOPNOTSUPP;
    > + i2c_lock_adapter(tpm_dev.client->adapter);
    > +
    > for (count = 0; count < MAX_COUNT; count++) {
    > - rc = i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
    > + rc = i2c_transfer_nolock(tpm_dev.client->adapter, &msg1, 1);
    > if (rc > 0)
    > break; /* break here to skip sleep */
    >
    > @@ -105,19 +135,21 @@ static int iic_tpm_read(u8 addr, u8 *buffer,
    > size_t len)
    > }
    >
    > if (rc <= 0)
    > - return -EIO;
    > + goto out;
    >
    > /* After the TPM has successfully received the register address it needs
    > * some time, thus we're sleeping here again, before retrieving the data
    > */
    > for (count = 0; count < MAX_COUNT; count++) {
    > usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI);
    > - rc = i2c_transfer(tpm_dev.client->adapter, &msg2, 1);
    > + rc = i2c_transfer_nolock(tpm_dev.client->adapter, &msg2, 1);
    > if (rc > 0)
    > break;
    >
    > }
    >
    > +out:
    > + i2c_unlock_adapter(tpm_dev.client->adapter);
    > if (rc <= 0)
    > return -EIO;
    >
    > @@ -136,6 +168,10 @@ static int iic_tpm_write_generic(u8 addr, u8
    > *buffer, size_t len,
    > if (len > TPM_BUFSIZE)
    > return -EINVAL;
    >
    > + if (!tpm_dev.client->adapter->algo->master_xfer)
    > + return -EOPNOTSUPP;
    > + i2c_lock_adapter(tpm_dev.client->adapter);
    > +
    > /* prepend the 'register address' to the buffer */
    > tpm_dev.buf[0] = addr;
    > memcpy(&(tpm_dev.buf[1]), buffer, len);
    > @@ -145,13 +181,14 @@ static int iic_tpm_write_generic(u8 addr, u8
    > *buffer, size_t len,
    > * cannot rely on the standard behavior of i2c_transfer.
    > */
    > for (count = 0; count < max_count; count++) {
    > - rc = i2c_transfer(tpm_dev.client->adapter, &msg1, 1);
    > + rc = i2c_transfer_nolock(tpm_dev.client->adapter, &msg1, 1);
    > if (rc > 0)
    > break;
    >
    > usleep_range(sleep_low, sleep_hi);
    > }
    >
    > + i2c_unlock_adapter(tpm_dev.client->adapter);
    > if (rc <= 0)
    > return -EIO;
    >
    > --
    > 1.7.6.msysgit.0





    \
     
     \ /
      Last update: 2012-06-13 10:22    [W:0.032 / U:63.904 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site