@@ -41,7 +41,6 @@
#include <linux/freezer.h>
#include <linux/string.h>
#include <linux/interrupt.h>
-#include <linux/spinlock.h>
#include <linux/sysfs.h>
#include <linux/gpio.h>
#include <linux/sched.h>
@@ -106,7 +105,7 @@ enum tis_defaults {
struct tpm_stm_dev {
struct i2c_client *client;
- struct mutex lock;
+ struct mutex tpm_lock;
struct tpm_chip *chip;
u8 buf[TPM_BUFSIZE + 1];
int io_serirq;
@@ -147,6 +146,7 @@ static int read8_reg(struct tpm_stm_dev *tpm_dev, u8 tpm_register,
status = write8_reg(tpm_dev, tpm_register, &data, 1);
if (status == 2)
status = i2c_master_recv(tpm_dev->client, tpm_data, tpm_size);
+
return status;
} /* read8_reg() */
@@ -163,6 +163,18 @@ static int read8_reg(struct tpm_stm_dev *tpm_dev, u8 tpm_register,
(write8_reg(tpm_dev, tpm_register | \
TPM_WRITE_DIRECTION, tpm_data, tpm_size))
+
+static int i2c_write_data(struct tpm_stm_dev *tpm_dev, u8 tpm_register,
+ u8 *tpm_data, u16 tpm_size)
+{
+ u8 status;
+
+ mutex_lock(&tpm_dev->tpm_lock);
+ status = I2C_WRITE_DATA(tpm_dev, tpm_register, tpm_data, tpm_size);
+ mutex_unlock(&tpm_dev->tpm_lock);
+
+ return status;
+} /* i2c_write_data() */
/*
* I2C_READ_DATA
* Recv byte from the TIS register according to the ST33ZP24 I2C protocol.
@@ -175,6 +187,18 @@ static int read8_reg(struct tpm_stm_dev *tpm_dev, u8 tpm_register,
#define I2C_READ_DATA(tpm_dev, tpm_register, tpm_data, tpm_size) \
(read8_reg(tpm_dev, tpm_register, tpm_data, tpm_size))
+static int i2c_read_data(struct tpm_stm_dev *tpm_dev, u8 tpm_register,
+ u8 *tpm_data, u16 tpm_size)
+{
+ u8 status;
+
+ mutex_lock(&tpm_dev->tpm_lock);
+ status = I2C_READ_DATA(tpm_dev, tpm_register, tpm_data, tpm_size);
+ mutex_unlock(&tpm_dev->tpm_lock);
+
+ return status;
+} /* i2c_read_data() */
+
/*
* clear_interruption
* clear the TPM interrupt register.
@@ -184,8 +208,8 @@ static u8 clear_interruption(struct tpm_stm_dev *tpm_dev)
{
u8 interrupt;
- I2C_READ_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1);
- I2C_WRITE_DATA(tpm_dev, TPM_INT_STATUS, &interrupt, 1);
+ i2c_read_data(tpm_dev, TPM_INT_STATUS, &interrupt, 1);
+ i2c_write_data(tpm_dev, TPM_INT_STATUS, &interrupt, 1);
return interrupt;
} /* clear_interruption() */
@@ -202,7 +226,7 @@ static void tpm_stm_i2c_cancel(struct tpm_chip *chip)
tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
data = TPM_STS_COMMAND_READY;
- I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1);
+ i2c_write_data(tpm_dev, TPM_STS, &data, 1);
} /* tpm_stm_i2c_cancel() */
/*
@@ -217,7 +241,7 @@ static u8 tpm_stm_i2c_status(struct tpm_chip *chip)
tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
- I2C_READ_DATA(tpm_dev, TPM_STS, &data, 1);
+ i2c_read_data(tpm_dev, TPM_STS, &data, 1);
return data;
} /* tpm_stm_i2c_status() */
@@ -235,7 +259,7 @@ static int check_locality(struct tpm_chip *chip)
tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
- status = I2C_READ_DATA(tpm_dev, TPM_ACCESS, &data, 1);
+ status = i2c_read_data(tpm_dev, TPM_ACCESS, &data, 1);
if (status && (data &
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
@@ -263,7 +287,7 @@ static int request_locality(struct tpm_chip *chip)
tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
data = TPM_ACCESS_REQUEST_USE;
- r = I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1);
+ r = i2c_write_data(tpm_dev, TPM_ACCESS, &data, 1);
if (r < 0)
goto end;
@@ -308,7 +332,7 @@ static void release_locality(struct tpm_chip *chip)
tpm_dev = (struct tpm_stm_dev *)TPM_VPRIV(chip);
data = TPM_ACCESS_ACTIVE_LOCALITY;
- I2C_WRITE_DATA(tpm_dev, TPM_ACCESS, &data, 1);
+ i2c_write_data(tpm_dev, TPM_ACCESS, &data, 1);
}
/*
@@ -328,13 +352,13 @@ static int get_burstcount(struct tpm_chip *chip)
stop = jiffies + chip->vendor.timeout_d;
do {
tpm_reg = TPM_STS + 1;
- status = I2C_READ_DATA(tpm_dev, tpm_reg, &temp, 1);
+ status = i2c_read_data(tpm_dev, tpm_reg, &temp, 1);
if (status < 0)
goto end;
tpm_reg = tpm_reg + 1;
burstcnt = temp;
- status = I2C_READ_DATA(tpm_dev, tpm_reg, &temp, 1);
+ status = i2c_read_data(tpm_dev, tpm_reg, &temp, 1);
if (status < 0)
goto end;
@@ -366,12 +390,12 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
wait_for_tpm_stat(chip,
TPM_STS_DATA_AVAIL | TPM_STS_VALID,
chip->vendor.timeout_c,
- &chip->vendor.read_queue, true) == 0) {
+ &chip->vendor.read_queue, false) == 0) {
burstcnt = get_burstcount(chip);
if (burstcnt < 0)
return burstcnt;
len = min_t(int, burstcnt, count - size);
- I2C_READ_DATA(tpm_dev, TPM_DATA_FIFO, buf + size, len);
+ i2c_read_data(tpm_dev, TPM_DATA_FIFO, buf + size, len);
size += len;
}
return size;
@@ -456,7 +480,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
if (burstcnt < 0)
return burstcnt;
size = min_t(int, len - i - 1, burstcnt);
- r = I2C_WRITE_DATA(tpm_dev, TPM_DATA_FIFO, buf, size);
+ r = i2c_write_data(tpm_dev, TPM_DATA_FIFO, buf, size);
if (r < 0)
goto out_err;
@@ -469,7 +493,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
goto out_err;
}
- r = I2C_WRITE_DATA(tpm_dev, TPM_DATA_FIFO, buf + len - 1, 1);
+ r = i2c_write_data(tpm_dev, TPM_DATA_FIFO, buf + len - 1, 1);
if (r < 0)
goto out_err;
@@ -480,7 +504,7 @@ static int tpm_stm_i2c_send(struct tpm_chip *chip, unsigned char *buf,
}
data = TPM_STS_GO;
- I2C_WRITE_DATA(tpm_dev, TPM_STS, &data, 1);
+ i2c_write_data(tpm_dev, TPM_STS, &data, 1);
return len;
out_err:
@@ -730,6 +754,7 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
chip->vendor.locality = LOCALITY0;
+ mutex_init(&tpm_dev->tpm_lock);
if (interrupts) {
/* INTERRUPT Setup */
@@ -758,12 +783,12 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
| TPM_INTF_STS_VALID_INT
| TPM_INTF_DATA_AVAIL_INT;
- r = I2C_WRITE_DATA(tpm_dev, TPM_INT_ENABLE, &intmask, 1);
+ r = i2c_write_data(tpm_dev, TPM_INT_ENABLE, &intmask, 1);
if (r < 0)
goto _tpm_clean_answer;
intmask = TPM_GLOBAL_INT_ENABLE;
- r = I2C_WRITE_DATA(tpm_dev, (TPM_INT_ENABLE + 3), &intmask, 1);
+ r = i2c_write_data(tpm_dev, (TPM_INT_ENABLE + 3), &intmask, 1);
if (r < 0)
goto _tpm_clean_answer;
Adding tpm_lock mutex in order to guarantee that a i2c_read_data or a i2c_write_data will not get interrupted by a threaded interrupt. Signed-off-by: Christophe Ricard <christophe-h.ricard@st.com> --- drivers/char/tpm/tpm_i2c_stm_st33.c | 61 ++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 18 deletions(-)