summaryrefslogtreecommitdiff
path: root/drivers/char/tpm/st33zp24/st33zp24.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 17:38:46 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-29 17:38:46 -0700
commit7a1e8b80fb1e8ead4cec15d1fc494ed290e4d2e9 (patch)
tree55a36d4256f1ae793b5c8e88c0f158737447193f /drivers/char/tpm/st33zp24/st33zp24.c
parenta867d7349e94b6409b08629886a819f802377e91 (diff)
parent7616ac70d1bb4f2e9d25c1a82d283f3368a7b632 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - TPM core and driver updates/fixes - IPv6 security labeling (CALIPSO) - Lots of Apparmor fixes - Seccomp: remove 2-phase API, close hole where ptrace can change syscall #" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (156 commits) apparmor: fix SECURITY_APPARMOR_HASH_DEFAULT parameter handling tpm: Add TPM 2.0 support to the Nuvoton i2c driver (NPCT6xx family) tpm: Factor out common startup code tpm: use devm_add_action_or_reset tpm2_i2c_nuvoton: add irq validity check tpm: read burstcount from TPM_STS in one 32-bit transaction tpm: fix byte-order for the value read by tpm2_get_tpm_pt tpm_tis_core: convert max timeouts from msec to jiffies apparmor: fix arg_size computation for when setprocattr is null terminated apparmor: fix oops, validate buffer size in apparmor_setprocattr() apparmor: do not expose kernel stack apparmor: fix module parameters can be changed after policy is locked apparmor: fix oops in profile_unpack() when policy_db is not present apparmor: don't check for vmalloc_addr if kvzalloc() failed apparmor: add missing id bounds check on dfa verification apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task apparmor: use list_next_entry instead of list_entry_next apparmor: fix refcount race when finding a child profile apparmor: fix ref count leak when profile sha1 hash is read apparmor: check that xindex is in trans_table bounds ...
Diffstat (limited to 'drivers/char/tpm/st33zp24/st33zp24.c')
-rw-r--r--drivers/char/tpm/st33zp24/st33zp24.c129
1 files changed, 49 insertions, 80 deletions
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index 8d626784cd8d..c2ee30451e41 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -1,6 +1,6 @@
/*
* STMicroelectronics TPM Linux driver for TPM ST33ZP24
- * Copyright (C) 2009 - 2015 STMicroelectronics
+ * Copyright (C) 2009 - 2016 STMicroelectronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -73,14 +73,6 @@ enum tis_defaults {
TIS_LONG_TIMEOUT = 2000,
};
-struct st33zp24_dev {
- struct tpm_chip *chip;
- void *phy_id;
- const struct st33zp24_phy_ops *ops;
- u32 intrs;
- int io_lpcpd;
-};
-
/*
* clear_interruption clear the pending interrupt.
* @param: tpm_dev, the tpm device device.
@@ -102,11 +94,9 @@ static u8 clear_interruption(struct st33zp24_dev *tpm_dev)
*/
static void st33zp24_cancel(struct tpm_chip *chip)
{
- struct st33zp24_dev *tpm_dev;
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data;
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
-
data = TPM_STS_COMMAND_READY;
tpm_dev->ops->send(tpm_dev->phy_id, TPM_STS, &data, 1);
} /* st33zp24_cancel() */
@@ -118,11 +108,9 @@ static void st33zp24_cancel(struct tpm_chip *chip)
*/
static u8 st33zp24_status(struct tpm_chip *chip)
{
- struct st33zp24_dev *tpm_dev;
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data;
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
-
tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1);
return data;
} /* st33zp24_status() */
@@ -134,17 +122,15 @@ static u8 st33zp24_status(struct tpm_chip *chip)
*/
static int check_locality(struct tpm_chip *chip)
{
- struct st33zp24_dev *tpm_dev;
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data;
u8 status;
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
-
status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
if (status && (data &
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
- return chip->vendor.locality;
+ return tpm_dev->locality;
return -EACCES;
} /* check_locality() */
@@ -156,27 +142,25 @@ static int check_locality(struct tpm_chip *chip)
*/
static int request_locality(struct tpm_chip *chip)
{
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
unsigned long stop;
long ret;
- struct st33zp24_dev *tpm_dev;
u8 data;
- if (check_locality(chip) == chip->vendor.locality)
- return chip->vendor.locality;
-
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+ if (check_locality(chip) == tpm_dev->locality)
+ return tpm_dev->locality;
data = TPM_ACCESS_REQUEST_USE;
ret = tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
if (ret < 0)
return ret;
- stop = jiffies + chip->vendor.timeout_a;
+ stop = jiffies + chip->timeout_a;
/* Request locality is usually effective after the request */
do {
if (check_locality(chip) >= 0)
- return chip->vendor.locality;
+ return tpm_dev->locality;
msleep(TPM_TIMEOUT);
} while (time_before(jiffies, stop));
@@ -190,10 +174,9 @@ static int request_locality(struct tpm_chip *chip)
*/
static void release_locality(struct tpm_chip *chip)
{
- struct st33zp24_dev *tpm_dev;
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u8 data;
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
data = TPM_ACCESS_ACTIVE_LOCALITY;
tpm_dev->ops->send(tpm_dev->phy_id, TPM_ACCESS, &data, 1);
@@ -206,23 +189,21 @@ static void release_locality(struct tpm_chip *chip)
*/
static int get_burstcount(struct tpm_chip *chip)
{
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
unsigned long stop;
int burstcnt, status;
- u8 tpm_reg, temp;
- struct st33zp24_dev *tpm_dev;
-
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+ u8 temp;
- stop = jiffies + chip->vendor.timeout_d;
+ stop = jiffies + chip->timeout_d;
do {
- tpm_reg = TPM_STS + 1;
- status = tpm_dev->ops->recv(tpm_dev->phy_id, tpm_reg, &temp, 1);
+ status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 1,
+ &temp, 1);
if (status < 0)
return -EBUSY;
- tpm_reg = TPM_STS + 2;
burstcnt = temp;
- status = tpm_dev->ops->recv(tpm_dev->phy_id, tpm_reg, &temp, 1);
+ status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS + 2,
+ &temp, 1);
if (status < 0)
return -EBUSY;
@@ -271,15 +252,13 @@ static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
wait_queue_head_t *queue, bool check_cancel)
{
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
unsigned long stop;
int ret = 0;
bool canceled = false;
bool condition;
u32 cur_intrs;
u8 status;
- struct st33zp24_dev *tpm_dev;
-
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
/* check current status */
status = st33zp24_status(chip);
@@ -288,10 +267,10 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
stop = jiffies + timeout;
- if (chip->vendor.irq) {
+ if (chip->flags & TPM_CHIP_FLAG_IRQ) {
cur_intrs = tpm_dev->intrs;
clear_interruption(tpm_dev);
- enable_irq(chip->vendor.irq);
+ enable_irq(tpm_dev->irq);
do {
if (ret == -ERESTARTSYS && freezing(current))
@@ -314,7 +293,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
}
} while (ret == -ERESTARTSYS && freezing(current));
- disable_irq_nosync(chip->vendor.irq);
+ disable_irq_nosync(tpm_dev->irq);
} else {
do {
@@ -337,16 +316,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
*/
static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
{
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
int size = 0, burstcnt, len, ret;
- struct st33zp24_dev *tpm_dev;
-
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
while (size < count &&
wait_for_stat(chip,
TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- chip->vendor.timeout_c,
- &chip->vendor.read_queue, true) == 0) {
+ chip->timeout_c,
+ &tpm_dev->read_queue, true) == 0) {
burstcnt = get_burstcount(chip);
if (burstcnt < 0)
return burstcnt;
@@ -370,13 +347,11 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
{
struct tpm_chip *chip = dev_id;
- struct st33zp24_dev *tpm_dev;
-
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
tpm_dev->intrs++;
- wake_up_interruptible(&chip->vendor.read_queue);
- disable_irq_nosync(chip->vendor.irq);
+ wake_up_interruptible(&tpm_dev->read_queue);
+ disable_irq_nosync(tpm_dev->irq);
return IRQ_HANDLED;
} /* tpm_ioserirq_handler() */
@@ -393,19 +368,17 @@ static irqreturn_t tpm_ioserirq_handler(int irq, void *dev_id)
static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
size_t len)
{
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
u32 status, i, size, ordinal;
int burstcnt = 0;
int ret;
u8 data;
- struct st33zp24_dev *tpm_dev;
if (!chip)
return -EBUSY;
if (len < TPM_HEADER_SIZE)
return -EBUSY;
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
-
ret = request_locality(chip);
if (ret < 0)
return ret;
@@ -414,8 +387,8 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
if ((status & TPM_STS_COMMAND_READY) == 0) {
st33zp24_cancel(chip);
if (wait_for_stat
- (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
- &chip->vendor.read_queue, false) < 0) {
+ (chip, TPM_STS_COMMAND_READY, chip->timeout_b,
+ &tpm_dev->read_queue, false) < 0) {
ret = -ETIME;
goto out_err;
}
@@ -456,12 +429,12 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
if (ret < 0)
goto out_err;
- if (chip->vendor.irq) {
+ if (chip->flags & TPM_CHIP_FLAG_IRQ) {
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
tpm_calc_ordinal_duration(chip, ordinal),
- &chip->vendor.read_queue, false);
+ &tpm_dev->read_queue, false);
if (ret < 0)
goto out_err;
}
@@ -532,6 +505,7 @@ static bool st33zp24_req_canceled(struct tpm_chip *chip, u8 status)
}
static const struct tpm_class_ops st33zp24_tpm = {
+ .flags = TPM_OPS_AUTO_STARTUP,
.send = st33zp24_send,
.recv = st33zp24_recv,
.cancel = st33zp24_cancel,
@@ -565,20 +539,20 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
if (!tpm_dev)
return -ENOMEM;
- TPM_VPRIV(chip) = tpm_dev;
tpm_dev->phy_id = phy_id;
tpm_dev->ops = ops;
+ dev_set_drvdata(&chip->dev, tpm_dev);
- chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
- chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
- chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
- chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT);
+ chip->timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
+ chip->timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
- chip->vendor.locality = LOCALITY0;
+ tpm_dev->locality = LOCALITY0;
if (irq) {
/* INTERRUPT Setup */
- init_waitqueue_head(&chip->vendor.read_queue);
+ init_waitqueue_head(&tpm_dev->read_queue);
tpm_dev->intrs = 0;
if (request_locality(chip) != LOCALITY0) {
@@ -611,16 +585,14 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
if (ret < 0)
goto _tpm_clean_answer;
- chip->vendor.irq = irq;
+ tpm_dev->irq = irq;
+ chip->flags |= TPM_CHIP_FLAG_IRQ;
- disable_irq_nosync(chip->vendor.irq);
+ disable_irq_nosync(tpm_dev->irq);
tpm_gen_interrupt(chip);
}
- tpm_get_timeouts(chip);
- tpm_do_selftest(chip);
-
return tpm_chip_register(chip);
_tpm_clean_answer:
dev_info(&chip->dev, "TPM initialization fail\n");
@@ -650,10 +622,9 @@ EXPORT_SYMBOL(st33zp24_remove);
int st33zp24_pm_suspend(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
- struct st33zp24_dev *tpm_dev;
- int ret = 0;
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
+ int ret = 0;
if (gpio_is_valid(tpm_dev->io_lpcpd))
gpio_set_value(tpm_dev->io_lpcpd, 0);
@@ -672,16 +643,14 @@ EXPORT_SYMBOL(st33zp24_pm_suspend);
int st33zp24_pm_resume(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
- struct st33zp24_dev *tpm_dev;
+ struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
int ret = 0;
- tpm_dev = (struct st33zp24_dev *)TPM_VPRIV(chip);
-
if (gpio_is_valid(tpm_dev->io_lpcpd)) {
gpio_set_value(tpm_dev->io_lpcpd, 1);
ret = wait_for_stat(chip,
- TPM_STS_VALID, chip->vendor.timeout_b,
- &chip->vendor.read_queue, false);
+ TPM_STS_VALID, chip->timeout_b,
+ &tpm_dev->read_queue, false);
} else {
ret = tpm_pm_resume(dev);
if (!ret)