Commit 7a1e8b80 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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
  ...
parents a867d734 7616ac70
/*
* STMicroelectronics TPM I2C 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
......@@ -19,11 +19,14 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/tpm.h>
#include <linux/platform_data/st33zp24.h>
#include "../tpm.h"
#include "st33zp24.h"
#define TPM_DUMMY_BYTE 0xAA
......@@ -108,11 +111,40 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
.recv = st33zp24_i2c_recv,
};
#ifdef CONFIG_OF
static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
{
struct tpm_chip *chip = i2c_get_clientdata(client);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
struct gpio_desc *gpiod_lpcpd;
struct device *dev = &client->dev;
/* Get LPCPD GPIO from ACPI */
gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod_lpcpd)) {
dev_err(&client->dev,
"Failed to retrieve lpcpd-gpios from acpi.\n");
phy->io_lpcpd = -1;
/*
* lpcpd pin is not specified. This is not an issue as
* power management can be also managed by TPM specific
* commands. So leave with a success status code.
*/
return 0;
}
phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
return 0;
}
static int st33zp24_i2c_of_request_resources(struct i2c_client *client)
{
struct tpm_chip *chip = i2c_get_clientdata(client);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
struct device_node *pp;
struct i2c_client *client = phy->client;
int gpio;
int ret;
......@@ -146,16 +178,12 @@ static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
return 0;
}
#else
static int st33zp24_i2c_of_request_resources(struct st33zp24_i2c_phy *phy)
{
return -ENODEV;
}
#endif
static int st33zp24_i2c_request_resources(struct i2c_client *client,
struct st33zp24_i2c_phy *phy)
static int st33zp24_i2c_request_resources(struct i2c_client *client)
{
struct tpm_chip *chip = i2c_get_clientdata(client);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
struct st33zp24_platform_data *pdata;
int ret;
......@@ -212,13 +240,18 @@ static int st33zp24_i2c_probe(struct i2c_client *client,
return -ENOMEM;
phy->client = client;
pdata = client->dev.platform_data;
if (!pdata && client->dev.of_node) {
ret = st33zp24_i2c_of_request_resources(phy);
ret = st33zp24_i2c_of_request_resources(client);
if (ret)
return ret;
} else if (pdata) {
ret = st33zp24_i2c_request_resources(client, phy);
ret = st33zp24_i2c_request_resources(client);
if (ret)
return ret;
} else if (ACPI_HANDLE(&client->dev)) {
ret = st33zp24_i2c_acpi_request_resources(client);
if (ret)
return ret;
}
......@@ -245,13 +278,17 @@ static const struct i2c_device_id st33zp24_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, st33zp24_i2c_id);
#ifdef CONFIG_OF
static const struct of_device_id of_st33zp24_i2c_match[] = {
{ .compatible = "st,st33zp24-i2c", },
{}
};
MODULE_DEVICE_TABLE(of, of_st33zp24_i2c_match);
#endif
static const struct acpi_device_id st33zp24_i2c_acpi_match[] = {
{"SMO3324"},
{}
};
MODULE_DEVICE_TABLE(acpi, st33zp24_i2c_acpi_match);
static SIMPLE_DEV_PM_OPS(st33zp24_i2c_ops, st33zp24_pm_suspend,
st33zp24_pm_resume);
......@@ -261,6 +298,7 @@ static struct i2c_driver st33zp24_i2c_driver = {
.name = TPM_ST33_I2C,
.pm = &st33zp24_i2c_ops,
.of_match_table = of_match_ptr(of_st33zp24_i2c_match),
.acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
},
.probe = st33zp24_i2c_probe,
.remove = st33zp24_i2c_remove,
......
/*
* STMicroelectronics TPM SPI 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
......@@ -19,11 +19,14 @@
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/acpi.h>
#include <linux/tpm.h>
#include <linux/platform_data/st33zp24.h>
#include "../tpm.h"
#include "st33zp24.h"
#define TPM_DATA_FIFO 0x24
......@@ -66,7 +69,7 @@
struct st33zp24_spi_phy {
struct spi_device *spi_device;
struct spi_transfer spi_xfer;
u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE];
u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE];
......@@ -110,43 +113,39 @@ static int st33zp24_status_to_errno(u8 code)
static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
int tpm_size)
{
u8 data = 0;
int total_length = 0, nbr_dummy_bytes = 0, ret = 0;
int total_length = 0, ret = 0;
struct st33zp24_spi_phy *phy = phy_id;
struct spi_device *dev = phy->spi_device;
u8 *tx_buf = (u8 *)phy->spi_xfer.tx_buf;
u8 *rx_buf = phy->spi_xfer.rx_buf;
struct spi_transfer spi_xfer = {
.tx_buf = phy->tx_buf,
.rx_buf = phy->rx_buf,
};
/* Pre-Header */
data = TPM_WRITE_DIRECTION | LOCALITY0;
memcpy(tx_buf + total_length, &data, sizeof(data));
total_length++;
data = tpm_register;
memcpy(tx_buf + total_length, &data, sizeof(data));
total_length++;
phy->tx_buf[total_length++] = TPM_WRITE_DIRECTION | LOCALITY0;
phy->tx_buf[total_length++] = tpm_register;
if (tpm_size > 0 && tpm_register == TPM_DATA_FIFO) {
tx_buf[total_length++] = tpm_size >> 8;
tx_buf[total_length++] = tpm_size;
phy->tx_buf[total_length++] = tpm_size >> 8;
phy->tx_buf[total_length++] = tpm_size;
}
memcpy(&tx_buf[total_length], tpm_data, tpm_size);
memcpy(&phy->tx_buf[total_length], tpm_data, tpm_size);
total_length += tpm_size;
nbr_dummy_bytes = phy->latency;
memset(&tx_buf[total_length], TPM_DUMMY_BYTE, nbr_dummy_bytes);
memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE, phy->latency);
phy->spi_xfer.len = total_length + nbr_dummy_bytes;
spi_xfer.len = total_length + phy->latency;
ret = spi_sync_transfer(dev, &phy->spi_xfer, 1);
ret = spi_sync_transfer(dev, &spi_xfer, 1);
if (ret == 0)
ret = rx_buf[total_length + nbr_dummy_bytes - 1];
ret = phy->rx_buf[total_length + phy->latency - 1];
return st33zp24_status_to_errno(ret);
} /* st33zp24_spi_send() */
/*
* read8_recv
* st33zp24_spi_read8_recv
* Recv byte from the TIS register according to the ST33ZP24 SPI protocol.
* @param: phy_id, the phy description
* @param: tpm_register, the tpm tis register where the data should be read
......@@ -154,40 +153,37 @@ static int st33zp24_spi_send(void *phy_id, u8 tpm_register, u8 *tpm_data,
* @param: tpm_size, tpm TPM response size to read.
* @return: should be zero if success else a negative error code.
*/
static int read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size)
static int st33zp24_spi_read8_reg(void *phy_id, u8 tpm_register, u8 *tpm_data,
int tpm_size)
{
u8 data = 0;
int total_length = 0, nbr_dummy_bytes, ret;
int total_length = 0, ret;
struct st33zp24_spi_phy *phy = phy_id;
struct spi_device *dev = phy->spi_device;
u8 *tx_buf = (u8 *)phy->spi_xfer.tx_buf;
u8 *rx_buf = phy->spi_xfer.rx_buf;
struct spi_transfer spi_xfer = {
.tx_buf = phy->tx_buf,
.rx_buf = phy->rx_buf,
};
/* Pre-Header */
data = LOCALITY0;
memcpy(tx_buf + total_length, &data, sizeof(data));
total_length++;
data = tpm_register;
memcpy(tx_buf + total_length, &data, sizeof(data));
total_length++;
phy->tx_buf[total_length++] = LOCALITY0;
phy->tx_buf[total_length++] = tpm_register;
nbr_dummy_bytes = phy->latency;
memset(&tx_buf[total_length], TPM_DUMMY_BYTE,
nbr_dummy_bytes + tpm_size);
memset(&phy->tx_buf[total_length], TPM_DUMMY_BYTE,
phy->latency + tpm_size);
phy->spi_xfer.len = total_length + nbr_dummy_bytes + tpm_size;
spi_xfer.len = total_length + phy->latency + tpm_size;
/* header + status byte + size of the data + status byte */
ret = spi_sync_transfer(dev, &phy->spi_xfer, 1);
ret = spi_sync_transfer(dev, &spi_xfer, 1);
if (tpm_size > 0 && ret == 0) {
ret = rx_buf[total_length + nbr_dummy_bytes - 1];
ret = phy->rx_buf[total_length + phy->latency - 1];
memcpy(tpm_data, rx_buf + total_length + nbr_dummy_bytes,
memcpy(tpm_data, phy->rx_buf + total_length + phy->latency,
tpm_size);
}
return ret;
} /* read8_reg() */
} /* st33zp24_spi_read8_reg() */
/*
* st33zp24_spi_recv
......@@ -203,13 +199,13 @@ static int st33zp24_spi_recv(void *phy_id, u8 tpm_register, u8 *tpm_data,
{
int ret;
ret = read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
ret = st33zp24_spi_read8_reg(phy_id, tpm_register, tpm_data, tpm_size);
if (!st33zp24_status_to_errno(ret))
return tpm_size;
return ret;
} /* st33zp24_spi_recv() */
static int evaluate_latency(void *phy_id)
static int st33zp24_spi_evaluate_latency(void *phy_id)
{
struct st33zp24_spi_phy *phy = phy_id;
int latency = 1, status = 0;
......@@ -217,9 +213,15 @@ static int evaluate_latency(void *phy_id)
while (!status && latency < MAX_SPI_LATENCY) {
phy->latency = latency;
status = read8_reg(phy_id, TPM_INTF_CAPABILITY, &data, 1);
status = st33zp24_spi_read8_reg(phy_id, TPM_INTF_CAPABILITY,
&data, 1);
latency++;
}
if (status < 0)
return status;
if (latency == MAX_SPI_LATENCY)
return -ENODEV;
return latency - 1;
} /* evaluate_latency() */
......@@ -228,24 +230,52 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
.recv = st33zp24_spi_recv,
};
#ifdef CONFIG_OF
static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy)
static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
{
struct tpm_chip *chip = spi_get_drvdata(spi_dev);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
struct gpio_desc *gpiod_lpcpd;
struct device *dev = &spi_dev->dev;
/* Get LPCPD GPIO from ACPI */
gpiod_lpcpd = devm_gpiod_get_index(dev, "TPM IO LPCPD", 1,
GPIOD_OUT_HIGH);
if (IS_ERR(gpiod_lpcpd)) {
dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n");
phy->io_lpcpd = -1;
/*
* lpcpd pin is not specified. This is not an issue as
* power management can be also managed by TPM specific
* commands. So leave with a success status code.
*/
return 0;
}
phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
return 0;
}
static int st33zp24_spi_of_request_resources(struct spi_device *spi_dev)
{
struct tpm_chip *chip = spi_get_drvdata(spi_dev);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
struct device_node *pp;
struct spi_device *dev = phy->spi_device;
int gpio;
int ret;
pp = dev->dev.of_node;
pp = spi_dev->dev.of_node;
if (!pp) {
dev_err(&dev->dev, "No platform data\n");
dev_err(&spi_dev->dev, "No platform data\n");
return -ENODEV;
}
/* Get GPIO from device tree */
gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
if (gpio < 0) {
dev_err(&dev->dev,
dev_err(&spi_dev->dev,
"Failed to retrieve lpcpd-gpios from dts.\n");
phy->io_lpcpd = -1;
/*
......@@ -256,26 +286,22 @@ static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy)
return 0;
}
/* GPIO request and configuration */
ret = devm_gpio_request_one(&dev->dev, gpio,
ret = devm_gpio_request_one(&spi_dev->dev, gpio,
GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
if (ret) {
dev_err(&dev->dev, "Failed to request lpcpd pin\n");
dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n");
return -ENODEV;
}
phy->io_lpcpd = gpio;
return 0;
}
#else
static int tpm_stm_spi_of_request_resources(struct st33zp24_spi_phy *phy)
{
return -ENODEV;
}
#endif
static int tpm_stm_spi_request_resources(struct spi_device *dev,
struct st33zp24_spi_phy *phy)
static int st33zp24_spi_request_resources(struct spi_device *dev)
{
struct tpm_chip *chip = spi_get_drvdata(dev);
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
struct st33zp24_platform_data *pdata;
int ret;
......@@ -303,13 +329,12 @@ static int tpm_stm_spi_request_resources(struct spi_device *dev,
}
/*
* tpm_st33_spi_probe initialize the TPM device
* st33zp24_spi_probe initialize the TPM device
* @param: dev, the spi_device drescription (TPM SPI description).
* @return: 0 in case of success.
* or a negative value describing the error.
*/
static int
tpm_st33_spi_probe(struct spi_device *dev)
static int st33zp24_spi_probe(struct spi_device *dev)
{
int ret;
struct st33zp24_platform_data *pdata;
......@@ -328,21 +353,23 @@ tpm_st33_spi_probe(struct spi_device *dev)
return -ENOMEM;
phy->spi_device = dev;
pdata = dev->dev.platform_data;
if (!pdata && dev->dev.of_node) {
ret = tpm_stm_spi_of_request_resources(phy);
ret = st33zp24_spi_of_request_resources(dev);
if (ret)
return ret;
} else if (pdata) {
ret = tpm_stm_spi_request_resources(dev, phy);
ret = st33zp24_spi_request_resources(dev);
if (ret)
return ret;
} else if (ACPI_HANDLE(&dev->dev)) {
ret = st33zp24_spi_acpi_request_resources(dev);
if (ret)
return ret;
}
phy->spi_xfer.tx_buf = phy->tx_buf;
phy->spi_xfer.rx_buf = phy->rx_buf;
phy->latency = evaluate_latency(phy);
phy->latency = st33zp24_spi_evaluate_latency(phy);
if (phy->latency <= 0)
return -ENODEV;
......@@ -351,11 +378,11 @@ tpm_st33_spi_probe(struct spi_device *dev)
}
/*
* tpm_st33_spi_remove remove the TPM device
* st33zp24_spi_remove remove the TPM device
* @param: client, the spi_device drescription (TPM SPI description).
* @return: 0 in case of success.
*/
static int tpm_st33_spi_remove(struct spi_device *dev)
static int st33zp24_spi_remove(struct spi_device *dev)
{
struct tpm_chip *chip = spi_get_drvdata(dev);
......@@ -368,29 +395,34 @@ static const struct spi_device_id st33zp24_spi_id[] = {
};
MODULE_DEVICE_TABLE(spi, st33zp24_spi_id);
#ifdef CONFIG_OF
static const struct of_device_id of_st33zp24_spi_match[] = {
{ .compatible = "st,st33zp24-spi", },
{}
};
MODULE_DEVICE_TABLE(of, of_st33zp24_spi_match);
#endif
static const struct acpi_device_id st33zp24_spi_acpi_match[] = {
{"SMO3324"},
{}
};
MODULE_DEVICE_TABLE(acpi, st33zp24_spi_acpi_match);
static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
st33zp24_pm_resume);
static struct spi_driver tpm_st33_spi_driver = {
static struct spi_driver st33zp24_spi_driver = {
.driver = {
.name = TPM_ST33_SPI,
.pm = &st33zp24_spi_ops,
.of_match_table = of_match_ptr(of_st33zp24_spi_match),
.acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
},
.probe = tpm_st33_spi_probe,
.remove = tpm_st33_spi_remove,
.probe = st33zp24_spi_probe,
.remove = st33zp24_spi_remove,
.id_table = st33zp24_spi_id,
};
module_spi_driver(tpm_st33_spi_driver);
module_spi_driver(st33zp24_spi_driver);
MODULE_AUTHOR("TPM support (TPMsupport@list.st.com)");
MODULE_DESCRIPTION("STM TPM 1.2 SPI ST33 Driver");
......
/*
* 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)
......
/*
* 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 and conditions of the GNU General Public License,
......@@ -21,6 +21,18 @@
#define TPM_WRITE_DIRECTION 0x80
#define TPM_BUFSIZE 2048
struct st33zp24_dev {
struct tpm_chip *chip;
void *phy_id;
const struct st33zp24_phy_ops *ops;
int locality;
int irq;
u32 intrs;
int io_lpcpd;
wait_queue_head_t read_queue;
};
struct st33zp24_phy_ops {
int (*send)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size);
int (*recv)(void *phy_id, u8 tpm_register, u8 *tpm_data, int tpm_size);
......
......@@ -29,33 +29,88 @@
#include "tpm.h"
#include "tpm_eventlog.h"
static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
DEFINE_IDR(dev_nums_idr);
static DEFINE_MUTEX(idr_lock);
struct class *tpm_class;
dev_t tpm_devt;
/*
* tpm_chip_find_get - return tpm_chip for a given chip number
* @chip_num the device number for the chip
/**
* tpm_try_get_ops() - Get a ref to the tpm_chip
* @chip: Chip to ref
*
* The caller must already have some kind of locking to ensure that chip is
* valid. This function will lock the chip so that the ops member can be
* accessed safely. The locking prevents tpm_chip_unregister from
* completing, so it should not be held for long periods.
*
* Returns -ERRNO if the chip could not be got.
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
int tpm_try_get_ops(struct tpm_chip *chip)
{
struct tpm_chip *pos, *chip = NULL;
int rc = -EIO;
rcu_read_lock();
list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
continue;
get_device(&chip->dev);
if (try_module_get(pos->pdev->driver->owner)) {
chip = pos;
break;
}
down_read(&chip->ops_sem);
if (!chip->ops)
goto out_lock;
return 0;
out_lock:
up_read(&chip->ops_sem);
put_device(&chip->dev);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_try_get_ops);
/**
* tpm_put_ops() - Release a ref to the tpm_chip
* @chip: Chip to put
*
* This is the opposite pair to tpm_try_get_ops(). After this returns chip may
* be kfree'd.
*/
void tpm_put_ops(struct tpm_chip *chip)
{
up_read(&chip->ops_sem);
put_device(&chip->dev);
}
EXPORT_SYMBOL_GPL(tpm_put_ops);
/**
* tpm_chip_find_get() - return tpm_chip for a given chip number
* @chip_num: id to find
*
* The return'd chip has been tpm_try_get_ops'd and must be released via
* tpm_put_ops
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
{
struct tpm_chip *chip, *res = NULL;
int chip_prev;
mutex_lock(&idr_lock);
if (chip_num == TPM_ANY_NUM) {
chip_num = 0;
do {
chip_prev = chip_num;
chip = idr_get_next(&dev_nums_idr, &chip_num);
if (chip && !tpm_try_get_ops(chip)) {
res = chip;
break;
}
} while (chip_prev != chip_num);
} else {
chip = idr_find_slowpath(&dev_nums_idr, chip_num);
if (chip && !tpm_try_get_ops(chip))
res = chip;
}
rcu_read_unlock();
return chip;
mutex_unlock(&idr_lock);
return res;
}
/**
......@@ -68,24 +123,25 @@ static void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
spin_lock(&driver_lock);
clear_bit(chip->dev_num, dev_mask);
spin_unlock(&driver_lock);
mutex_lock(&idr_lock);
idr_remove(&dev_nums_idr, chip->dev_num);
mutex_unlock(&idr_lock);
kfree(chip);
}
/**
* tpmm_chip_alloc() - allocate a new struct tpm_chip instance
* @dev: device to which the chip is associated
* tpm_chip_alloc() - allocate a new struct tpm_chip instance
* @pdev: device to which the chip is associated
* At this point pdev mst be initialized, but does not have to
* be registered
* @ops: struct tpm_class_ops instance
*
* Allocates a new struct tpm_chip instance and assigns a free
* device number for it. Caller does not have to worry about
* freeing the allocated resources. When the devices is removed
* devres calls tpmm_chip_remove() to do the job.
* device number for it. Must be paired with put_device(&chip->dev).
*/
struct tpm_chip *tpmm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops)
struct tpm_chip *tpm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
int rc;
......@@ -95,53 +151,75 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
return ERR_PTR(-ENOMEM);
mutex_init(&chip->tpm_mutex);
INIT_LIST_HEAD(&chip->list);
init_rwsem(&chip->ops_sem);
chip->ops = ops;
spin_lock(&driver_lock);
chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
spin_unlock(&driver_lock);
if (chip->dev_num >= TPM_NUM_DEVICES) {
mutex_lock(&idr_lock);
rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
mutex_unlock(&idr_lock);
if (rc < 0) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
return ERR_PTR(-ENOMEM);
return ERR_PTR(rc);
}
chip->dev_num = rc;
set_bit(chip->dev_num, dev_mask);
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
chip->pdev = dev;
dev_set_drvdata(dev, chip);
device_initialize(&chip->dev);
chip->dev.class = tpm_class;
chip->dev.release = tpm_dev_release;
chip->dev.parent = chip->pdev;
#ifdef CONFIG_ACPI
chip->dev.parent = dev;
chip->dev.groups = chip->groups;
#endif
if (chip->dev_num == 0)
chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
else
chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
dev_set_name(&chip->dev, "%s", chip->devname);
rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
if (rc)
goto out;
device_initialize(&chip->dev);
if (!dev)
chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
cdev_init(&chip->cdev, &tpm_fops);
chip->cdev.owner = chip->pdev->driver->owner;
chip->cdev.owner = THIS_MODULE;
chip->cdev.kobj.parent = &chip->dev.kobj;
rc = devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
if (rc) {
put_device(&chip->dev);
return chip;
out:
put_device(&chip->dev);
return ERR_PTR(rc);
}
EXPORT_SYMBOL_GPL(tpm_chip_alloc);
/**
* tpmm_chip_alloc() - allocate a new struct tpm_chip instance
* @pdev: parent device to which the chip is associated
* @ops: struct tpm_class_ops instance
*
* Same as tpm_chip_alloc except devm is used to do the put_device
*/
struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_alloc(pdev, ops);
if (IS_ERR(chip))
return chip;
rc = devm_add_action_or_reset(pdev,
(void (*)(void *)) put_device,
&chip->dev);
if (rc)
return ERR_PTR(rc);
}
dev_set_drvdata(pdev, chip);
return chip;
}
......@@ -155,7 +233,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
if (rc) {
dev_err(&chip->dev,
"unable to cdev_add() %s, major %d, minor %d, err=%d\n",
chip->devname, MAJOR(chip->dev.devt),
dev_name(&chip->dev), MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc);
return rc;
......@@ -165,13 +243,18 @@ static int tpm_add_char_device(struct tpm_chip *chip)
if (rc) {
dev_err(&chip->dev,
"unable to device_register() %s, major %d, minor %d, err=%d\n",
chip->devname, MAJOR(chip->dev.devt),
dev_name(&chip->dev), MAJOR(chip->dev.devt),
MINOR(chip->dev.devt), rc);
cdev_del(&chip->cdev);
return rc;
}
/* Make the chip available. */
mutex_lock(&idr_lock);
idr_replace(&dev_nums_idr, chip, chip->dev_num);
mutex_unlock(&idr_lock);
return rc;
}
......@@ -179,20 +262,28 @@ static void tpm_del_char_device(struct tpm_chip *chip)
{
cdev_del(&chip->cdev);
device_del(&chip->dev);
/* Make the chip unavailable. */
mutex_lock(&idr_lock);
idr_replace(&dev_nums_idr, NULL, chip->dev_num);
mutex_unlock(&idr_lock);
/* Make the driver uncallable. */
down_write(&chip->ops_sem);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
chip->ops = NULL;
up_write(&chip->ops_sem);
}
static int tpm1_chip_register(struct tpm_chip *chip)
{
int rc;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return 0;
rc = tpm_sysfs_add_device(chip);
if (rc)
return rc;
tpm_sysfs_add_device(chip);
chip->bios_dir = tpm_bios_log_setup(chip->devname);
chip->bios_dir = tpm_bios_log_setup(dev_name(&chip->dev));
return 0;
}
......@@ -204,10 +295,50 @@ static void tpm1_chip_unregister(struct tpm_chip *chip)
if (chip->bios_dir)
tpm_bios_log_teardown(chip->bios_dir);
}
static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
{
struct attribute **i;
if (chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL))
return;
sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
tpm_sysfs_del_device(chip);
for (i = chip->groups[0]->attrs; *i != NULL; ++i)
sysfs_remove_link(&chip->dev.parent->kobj, (*i)->name);
}
/* For compatibility with legacy sysfs paths we provide symlinks from the
* parent dev directory to selected names within the tpm chip directory. Old
* kernel versions created these files directly under the parent.
*/
static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
{
struct attribute **i;
int rc;
if (chip->flags & (TPM_CHIP_FLAG_TPM2 | TPM_CHIP_FLAG_VIRTUAL))
return 0;
rc = __compat_only_sysfs_link_entry_to_kobj(
&chip->dev.parent->kobj, &chip->dev.kobj, "ppi");
if (rc && rc != -ENOENT)
return rc;
/* All the names from tpm-sysfs */
for (i = chip->groups[0]->attrs; *i != NULL; ++i) {
rc = __compat_only_sysfs_link_entry_to_kobj(
&chip->dev.parent->kobj, &chip->dev.kobj, (*i)->name);
if (rc) {
tpm_del_legacy_sysfs(chip);
return rc;
}
}
return 0;
}
/*
* tpm_chip_register() - create a character device for the TPM chip
* @chip: TPM chip to use.
......@@ -223,6 +354,15 @@ int tpm_chip_register(struct tpm_chip *chip)
{
int rc;
if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_auto_startup(chip);
else
rc = tpm1_auto_startup(chip);
if (rc)
return rc;
}
rc = tpm1_chip_register(chip);
if (rc)
return rc;
......@@ -230,30 +370,20 @@ int tpm_chip_register(struct tpm_chip *chip)
tpm_add_ppi(chip);
rc = tpm_add_char_device(chip);
if (rc)
goto out_err;
/* Make the chip available. */
spin_lock(&driver_lock);
list_add_tail_rcu(&chip->list, &tpm_chip_list);
spin_unlock(&driver_lock);
if (rc) {
tpm1_chip_unregister(chip);
return rc;
}
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
rc = __compat_only_sysfs_link_entry_to_kobj(&chip->pdev->kobj,
&chip->dev.kobj,
"ppi");
if (rc && rc != -ENOENT) {
tpm_chip_unregister(chip);
return rc;
}
rc = tpm_add_legacy_sysfs(chip);
if (rc) {
tpm_chip_unregister(chip);
return rc;
}
return 0;
out_err:
tpm1_chip_unregister(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_chip_register);
......@@ -264,6 +394,9 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
* Takes the chip first away from the list of available TPM chips and then
* cleans up all the resources reserved by tpm_chip_register().
*
* Once this function returns the driver call backs in 'op's will not be
* running and will no longer start.
*
* NOTE: This function should be only called before deinitializing chip
* resources.
*/
......@@ -272,13 +405,7 @@ void tpm_chip_unregister(struct tpm_chip *chip)
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
return;
spin_lock(&driver_lock);
list_del_rcu(&chip->list);
spin_unlock(&driver_lock);
synchronize_rcu();
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
sysfs_remove_link(&chip->pdev->kobj, "ppi");
tpm_del_legacy_sysfs(chip);
tpm1_chip_unregister(chip);
tpm_del_char_device(chip);
......
......@@ -61,7 +61,7 @@ static int tpm_open(struct inode *inode, struct file *file)
* by the check of is_open variable, which is protected
* by driver_lock. */
if (test_and_set_bit(0, &chip->is_open)) {
dev_dbg(chip->pdev, "Another process owns this TPM\n");
dev_dbg(&chip->dev, "Another process owns this TPM\n");
return -EBUSY;
}
......@@ -79,7 +79,6 @@ static int tpm_open(struct inode *inode, struct file *file)
INIT_WORK(&priv->work, timeout_work);
file->private_data = priv;
get_device(chip->pdev);
return 0;
}
......@@ -137,9 +136,18 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
return -EFAULT;
}
/* atomic tpm command send and result receive */
/* atomic tpm command send and result receive. We only hold the ops
* lock during this period so that the tpm can be unregistered even if
* the char dev is held open.
*/
if (tpm_try_get_ops(priv->chip)) {
mutex_unlock(&priv->buffer_mutex);
return -EPIPE;
}
out_size = tpm_transmit(priv->chip, priv->data_buffer,
sizeof(priv->data_buffer));
tpm_put_ops(priv->chip);
if (out_size < 0) {
mutex_unlock(&priv->buffer_mutex);
return out_size;
......@@ -166,7 +174,6 @@ static int tpm_release(struct inode *inode, struct file *file)
file->private_data = NULL;
atomic_set(&priv->data_pending, 0);
clear_bit(0, &priv->chip->is_open);
put_device(priv->chip->pdev);
kfree(priv);
return 0;
}
......
......@@ -319,7 +319,7 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
duration_idx = tpm_ordinal_duration[ordinal];
if (duration_idx != TPM_UNDEFINED)
duration = chip->vendor.duration[duration_idx];
duration = chip->duration[duration_idx];
if (duration <= 0)
return 2 * 60 * HZ;
else
......@@ -345,7 +345,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"invalid count value %x %zx\n", count, bufsiz);
return -E2BIG;
}
......@@ -354,12 +354,12 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
rc = chip->ops->send(chip, (u8 *) buf, count);
if (rc < 0) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
if (chip->vendor.irq)
if (chip->flags & TPM_CHIP_FLAG_IRQ)
goto out_recv;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
......@@ -373,7 +373,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
goto out_recv;
if (chip->ops->req_canceled(chip, status)) {
dev_err(chip->pdev, "Operation Canceled\n");
dev_err(&chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
}
......@@ -383,14 +383,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
} while (time_before(jiffies, stop));
chip->ops->cancel(chip);
dev_err(chip->pdev, "Operation Timed out\n");
dev_err(&chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
dev_err(chip->pdev,
dev_err(&chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
out:
mutex_unlock(&chip->tpm_mutex);
......@@ -416,7 +416,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd,
err = be32_to_cpu(header->return_code);
if (err != 0 && desc)
dev_err(chip->pdev, "A TPM error (%d) occurred %s\n", err,
dev_err(&chip->dev, "A TPM error (%d) occurred %s\n", err,
desc);
return err;
......@@ -432,12 +432,11 @@ static const struct tpm_input_header tpm_getcap_header = {
.ordinal = TPM_ORD_GET_CAP
};
ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap,
ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
const char *desc)
{
struct tpm_cmd_t tpm_cmd;
int rc;
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_cmd.header.in = tpm_getcap_header;
if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) {
......@@ -505,15 +504,15 @@ int tpm_get_timeouts(struct tpm_chip *chip)
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
/* Fixed timeouts for TPM2 */
chip->vendor.timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->vendor.timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->vendor.timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->vendor.timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
chip->vendor.duration[TPM_SHORT] =
chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
chip->duration[TPM_SHORT] =
msecs_to_jiffies(TPM2_DURATION_SHORT);
chip->vendor.duration[TPM_MEDIUM] =
chip->duration[TPM_MEDIUM] =
msecs_to_jiffies(TPM2_DURATION_MEDIUM);
chip->vendor.duration[TPM_LONG] =
chip->duration[TPM_LONG] =
msecs_to_jiffies(TPM2_DURATION_LONG);
return 0;
}
......@@ -527,7 +526,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
if (rc == TPM_ERR_INVALID_POSTINIT) {
/* The TPM is not started, we are the first to talk to it.
Execute a startup command. */
dev_info(chip->pdev, "Issuing TPM_STARTUP");
dev_info(&chip->dev, "Issuing TPM_STARTUP");
if (tpm_startup(chip, TPM_ST_CLEAR))
return rc;
......@@ -539,7 +538,7 @@ int tpm_get_timeouts(struct tpm_chip *chip)
NULL);
}
if (rc) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"A TPM error (%zd) occurred attempting to determine the timeouts\n",
rc);
goto duration;
......@@ -561,10 +560,10 @@ int tpm_get_timeouts(struct tpm_chip *chip)
* of misreporting.
*/
if (chip->ops->update_timeouts != NULL)
chip->vendor.timeout_adjusted =
chip->timeout_adjusted =
chip->ops->update_timeouts(chip, new_timeout);
if (!chip->vendor.timeout_adjusted) {
if (!chip->timeout_adjusted) {
/* Don't overwrite default if value is 0 */
if (new_timeout[0] != 0 && new_timeout[0] < 1000) {
int i;
......@@ -572,13 +571,13 @@ int tpm_get_timeouts(struct tpm_chip *chip)
/* timeouts in msec rather usec */
for (i = 0; i != ARRAY_SIZE(new_timeout); i++)
new_timeout[i] *= 1000;
chip->vendor.timeout_adjusted = true;
chip->timeout_adjusted = true;
}
}
/* Report adjusted timeouts */
if (chip->vendor.timeout_adjusted) {
dev_info(chip->pdev,
if (chip->timeout_adjusted) {
dev_info(&chip->dev,
HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
old_timeout[0], new_timeout[0],
old_timeout[1], new_timeout[1],
......@@ -586,10 +585,10 @@ int tpm_get_timeouts(struct tpm_chip *chip)
old_timeout[3], new_timeout[3]);
}
chip->vendor.timeout_a = usecs_to_jiffies(new_timeout[0]);
chip->vendor.timeout_b = usecs_to_jiffies(new_timeout[1]);
chip->vendor.timeout_c = usecs_to_jiffies(new_timeout[2]);
chip->vendor.timeout_d = usecs_to_jiffies(new_timeout[3]);
chip->timeout_a = usecs_to_jiffies(new_timeout[0]);
chip->timeout_b = usecs_to_jiffies(new_timeout[1]);
chip->timeout_c = usecs_to_jiffies(new_timeout[2]);
chip->timeout_d = usecs_to_jiffies(new_timeout[3]);
duration:
tpm_cmd.header.in = tpm_getcap_header;
......@@ -608,11 +607,11 @@ int tpm_get_timeouts(struct tpm_chip *chip)
return -EINVAL;
duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
chip->vendor.duration[TPM_SHORT] =
chip->duration[TPM_SHORT] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short));
chip->vendor.duration[TPM_MEDIUM] =
chip->duration[TPM_MEDIUM] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium));
chip->vendor.duration[TPM_LONG] =
chip->duration[TPM_LONG] =
usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long));
/* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
......@@ -620,12 +619,12 @@ int tpm_get_timeouts(struct tpm_chip *chip)
* fix up the resulting too-small TPM_SHORT value to make things work.
* We also scale the TPM_MEDIUM and -_LONG values by 1000.
*/
if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) {
chip->vendor.duration[TPM_SHORT] = HZ;
chip->vendor.duration[TPM_MEDIUM] *= 1000;
chip->vendor.duration[TPM_LONG] *= 1000;
chip->vendor.duration_adjusted = true;
dev_info(chip->pdev, "Adjusting TPM timeout parameters.");
if (chip->duration[TPM_SHORT] < (HZ / 100)) {
chip->duration[TPM_SHORT] = HZ;
chip->duration[TPM_MEDIUM] *= 1000;
chip->duration[TPM_LONG] *= 1000;
chip->duration_adjusted = true;
dev_info(&chip->dev, "Adjusting TPM timeout parameters.");
}
return 0;
}
......@@ -700,7 +699,7 @@ int tpm_is_tpm2(u32 chip_num)
rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
......@@ -729,7 +728,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
else
rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf);
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_pcr_read);
......@@ -764,7 +763,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
rc = tpm2_pcr_extend(chip, pcr_idx, hash);
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
......@@ -774,7 +773,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
"attempting extend a PCR value");
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_pcr_extend);
......@@ -815,7 +814,9 @@ int tpm_do_selftest(struct tpm_chip *chip)
* around 300ms while the self test is ongoing, keep trying
* until the self test duration expires. */
if (rc == -ETIME) {
dev_info(chip->pdev, HW_ERR "TPM command timed out during continue self test");
dev_info(
&chip->dev, HW_ERR
"TPM command timed out during continue self test");
msleep(delay_msec);
continue;
}
......@@ -825,7 +826,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
rc = be32_to_cpu(cmd.header.out.return_code);
if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
dev_info(chip->pdev,
dev_info(&chip->dev,
"TPM is disabled/deactivated (0x%X)\n", rc);
/* TPM is disabled and/or deactivated; driver can
* proceed and TPM does handle commands for
......@@ -842,6 +843,33 @@ int tpm_do_selftest(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_do_selftest);
/**
* tpm1_auto_startup - Perform the standard automatic TPM initialization
* sequence
* @chip: TPM chip to use
*
* Returns 0 on success, < 0 in case of fatal error.
*/
int tpm1_auto_startup(struct tpm_chip *chip)
{
int rc;
rc = tpm_get_timeouts(chip);
if (rc)
goto out;
rc = tpm_do_selftest(chip);
if (rc) {
dev_err(&chip->dev, "TPM self test failed\n");
goto out;
}
return rc;
out:
if (rc > 0)
rc = -ENODEV;
return rc;
}
int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{
struct tpm_chip *chip;
......@@ -853,7 +881,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd");
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_send);
......@@ -888,7 +916,7 @@ int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
stop = jiffies + timeout;
if (chip->vendor.irq) {
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
......@@ -978,10 +1006,10 @@ int tpm_pm_suspend(struct device *dev)
}
if (rc)
dev_err(chip->pdev,
dev_err(&chip->dev,
"Error (%d) sending savestate before suspend\n", rc);
else if (try > 0)
dev_warn(chip->pdev, "TPM savestate took %dms\n",
dev_warn(&chip->dev, "TPM savestate took %dms\n",
try * TPM_TIMEOUT_RETRY);
return rc;
......@@ -1035,7 +1063,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
err = tpm2_get_random(chip, out, max);
tpm_chip_put(chip);
tpm_put_ops(chip);
return err;
}
......@@ -1057,7 +1085,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
num_bytes -= recd;
} while (retries-- && total < max);
tpm_chip_put(chip);
tpm_put_ops(chip);
return total ? total : -EIO;
}
EXPORT_SYMBOL_GPL(tpm_get_random);
......@@ -1083,7 +1111,7 @@ int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
rc = tpm2_seal_trusted(chip, payload, options);
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_seal_trusted);
......@@ -1109,7 +1137,8 @@ int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
rc = tpm2_unseal_trusted(chip, payload, options);
tpm_chip_put(chip);
tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_unseal_trusted);
......@@ -1136,6 +1165,7 @@ static int __init tpm_init(void)
static void __exit tpm_exit(void)
{
idr_destroy(&dev_nums_idr);
class_destroy(tpm_class);
unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
}
......
......@@ -36,7 +36,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
int i, rc;
char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_chip *chip = to_tpm_chip(dev);
tpm_cmd.header.in = tpm_readpubek_header;
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
......@@ -92,9 +92,9 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
ssize_t rc;
int i, j, num_pcrs;
char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_chip *chip = to_tpm_chip(dev);
rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap,
rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap,
"attempting to determine the number of PCRS");
if (rc)
return 0;
......@@ -119,8 +119,8 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent enabled state");
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent enabled state");
if (rc)
return 0;
......@@ -135,8 +135,8 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent active state");
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
"attempting to determine the permanent active state");
if (rc)
return 0;
......@@ -151,8 +151,8 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap,
"attempting to determine the owner state");
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
"attempting to determine the owner state");
if (rc)
return 0;
......@@ -167,8 +167,8 @@ static ssize_t temp_deactivated_show(struct device *dev,
cap_t cap;
ssize_t rc;
rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap,
"attempting to determine the temporary state");
rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
"attempting to determine the temporary state");
if (rc)
return 0;
......@@ -180,11 +180,12 @@ static DEVICE_ATTR_RO(temp_deactivated);
static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = to_tpm_chip(dev);
cap_t cap;
ssize_t rc;
char *str = buf;
rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
"attempting to determine the manufacturer");
if (rc)
return 0;
......@@ -192,8 +193,8 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
be32_to_cpu(cap.manufacturer_id));
/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap,
"attempting to determine the 1.2 version");
rc = tpm_getcap(chip, CAP_VERSION_1_2, &cap,
"attempting to determine the 1.2 version");
if (!rc) {
str += sprintf(str,
"TCG version: %d.%d\nFirmware version: %d.%d\n",
......@@ -203,7 +204,7 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
cap.tpm_version_1_2.revMinor);
} else {
/* Otherwise just use TPM_STRUCT_VER */
rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
rc = tpm_getcap(chip, CAP_VERSION_1_1, &cap,
"attempting to determine the 1.1 version");
if (rc)
return 0;
......@@ -222,7 +223,7 @@ static DEVICE_ATTR_RO(caps);
static ssize_t cancel_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_chip *chip = to_tpm_chip(dev);
if (chip == NULL)
return 0;
......@@ -234,16 +235,16 @@ static DEVICE_ATTR_WO(cancel);
static ssize_t durations_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_chip *chip = to_tpm_chip(dev);
if (chip->vendor.duration[TPM_LONG] == 0)
if (chip->duration[TPM_LONG] == 0)
return 0;
return sprintf(buf, "%d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]),
jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]),
jiffies_to_usecs(chip->vendor.duration[TPM_LONG]),
chip->vendor.duration_adjusted
jiffies_to_usecs(chip->duration[TPM_SHORT]),
jiffies_to_usecs(chip->duration[TPM_MEDIUM]),
jiffies_to_usecs(chip->duration[TPM_LONG]),
chip->duration_adjusted
? "adjusted" : "original");
}
static DEVICE_ATTR_RO(durations);
......@@ -251,14 +252,14 @@ static DEVICE_ATTR_RO(durations);
static ssize_t timeouts_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_chip *chip = to_tpm_chip(dev);
return sprintf(buf, "%d %d %d %d [%s]\n",
jiffies_to_usecs(chip->vendor.timeout_a),
jiffies_to_usecs(chip->vendor.timeout_b),
jiffies_to_usecs(chip->vendor.timeout_c),
jiffies_to_usecs(chip->vendor.timeout_d),
chip->vendor.timeout_adjusted
jiffies_to_usecs(chip->timeout_a),
jiffies_to_usecs(chip->timeout_b),
jiffies_to_usecs(chip->timeout_c),
jiffies_to_usecs(chip->timeout_d),
chip->timeout_adjusted
? "adjusted" : "original");
}
static DEVICE_ATTR_RO(timeouts);
......@@ -281,19 +282,12 @@ static const struct attribute_group tpm_dev_group = {
.attrs = tpm_dev_attrs,
};
int tpm_sysfs_add_device(struct tpm_chip *chip)
void tpm_sysfs_add_device(struct tpm_chip *chip)
{
int err;
err = sysfs_create_group(&chip->pdev->kobj,
&tpm_dev_group);
if (err)
dev_err(chip->pdev,
"failed to create sysfs attributes, %d\n", err);
return err;
}
void tpm_sysfs_del_device(struct tpm_chip *chip)
{
sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group);
/* The sysfs routines rely on an implicit tpm_try_get_ops, device_del
* is called before ops is null'd and the sysfs core synchronizes this
* removal so that no callbacks are running or can run again
*/
WARN_ON(chip->groups_cnt != 0);
chip->groups[chip->groups_cnt++] = &tpm_dev_group;
}
......@@ -19,6 +19,10 @@
* License.
*
*/
#ifndef __TPM_H__
#define __TPM_H__
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/fs.h>
......@@ -34,7 +38,7 @@
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 4096,
TPM_NUM_DEVICES = 256,
TPM_NUM_DEVICES = 65536,
TPM_RETRY = 50, /* 5 seconds */
};
......@@ -128,33 +132,6 @@ enum tpm2_startup_types {
TPM2_SU_STATE = 0x0001,
};
struct tpm_chip;
struct tpm_vendor_specific {
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
int irq;
int region_size;
int have_region;
struct list_head list;
int locality;
unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */
bool timeout_adjusted;
unsigned long duration[3]; /* jiffies */
bool duration_adjusted;
void *priv;
wait_queue_head_t read_queue;
wait_queue_head_t int_queue;
u16 manufacturer_id;
};
#define TPM_VPRIV(c) ((c)->vendor.priv)
#define TPM_VID_INTEL 0x8086
#define TPM_VID_WINBOND 0x1050
#define TPM_VID_STM 0x104A
......@@ -164,44 +141,48 @@ struct tpm_vendor_specific {
enum tpm_chip_flags {
TPM_CHIP_FLAG_REGISTERED = BIT(0),
TPM_CHIP_FLAG_TPM2 = BIT(1),
TPM_CHIP_FLAG_IRQ = BIT(2),
TPM_CHIP_FLAG_VIRTUAL = BIT(3),
};
struct tpm_chip {
struct device *pdev; /* Device stuff */
struct device dev;
struct cdev cdev;
/* A driver callback under ops cannot be run unless ops_sem is held
* (sometimes implicitly, eg for the sysfs code). ops becomes null
* when the driver is unregistered, see tpm_try_get_ops.
*/
struct rw_semaphore ops_sem;
const struct tpm_class_ops *ops;
unsigned int flags;
int dev_num; /* /dev/tpm# */
char devname[7];
unsigned long is_open; /* only one allowed */
int time_expired;
struct mutex tpm_mutex; /* tpm is processing */
struct tpm_vendor_specific vendor;
unsigned long timeout_a; /* jiffies */
unsigned long timeout_b; /* jiffies */
unsigned long timeout_c; /* jiffies */
unsigned long timeout_d; /* jiffies */
bool timeout_adjusted;
unsigned long duration[3]; /* jiffies */
bool duration_adjusted;
struct dentry **bios_dir;
#ifdef CONFIG_ACPI
const struct attribute_group *groups[2];
const struct attribute_group *groups[3];
unsigned int groups_cnt;
#ifdef CONFIG_ACPI
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
struct list_head list;
};
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
static inline void tpm_chip_put(struct tpm_chip *chip)
{
module_put(chip->pdev->driver->owner);
}
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
......@@ -493,14 +474,17 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
extern struct class *tpm_class;
extern dev_t tpm_devt;
extern const struct file_operations tpm_fops;
extern struct idr dev_nums_idr;
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap,
const char *desc);
ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz);
ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len,
const char *desc);
extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm_pm_suspend(struct device *);
......@@ -509,13 +493,17 @@ extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
wait_queue_head_t *, bool);
struct tpm_chip *tpm_chip_find_get(int chip_num);
extern struct tpm_chip *tpmm_chip_alloc(struct device *dev,
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);
extern struct tpm_chip *tpm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops);
extern struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
const struct tpm_class_ops *ops);
extern int tpm_chip_register(struct tpm_chip *chip);
extern void tpm_chip_unregister(struct tpm_chip *chip);
int tpm_sysfs_add_device(struct tpm_chip *chip);
void tpm_sysfs_del_device(struct tpm_chip *chip);
void tpm_sysfs_add_device(struct tpm_chip *chip);
int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
......@@ -539,9 +527,9 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
u32 *value, const char *desc);
extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
int tpm2_auto_startup(struct tpm_chip *chip);
extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
extern int tpm2_do_selftest(struct tpm_chip *chip);
extern int tpm2_gen_interrupt(struct tpm_chip *chip);
extern int tpm2_probe(struct tpm_chip *chip);
#endif
......@@ -597,7 +597,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT);
if (rc) {
dev_warn(chip->pdev, "0x%08x was not flushed, out of memory\n",
dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n",
handle);
return;
}
......@@ -606,7 +606,7 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context");
if (rc)
dev_warn(chip->pdev, "0x%08x was not flushed, rc=%d\n", handle,
dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle,
rc);
tpm_buf_destroy(&buf);
......@@ -703,7 +703,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc);
if (!rc)
*value = cmd.params.get_tpm_pt_out.value;
*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
return rc;
}
......@@ -728,7 +728,7 @@ static const struct tpm_input_header tpm2_startup_header = {
* returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error.
*/
int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
{
struct tpm2_cmd cmd;
......@@ -738,7 +738,6 @@ int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
return tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
"attempting to start the TPM");
}
EXPORT_SYMBOL_GPL(tpm2_startup);
#define TPM2_SHUTDOWN_IN_SIZE \
(sizeof(struct tpm_input_header) + \
......@@ -770,10 +769,9 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
* except print the error code on a system failure.
*/
if (rc < 0)
dev_warn(chip->pdev, "transmit returned %d while stopping the TPM",
dev_warn(&chip->dev, "transmit returned %d while stopping the TPM",
rc);
}
EXPORT_SYMBOL_GPL(tpm2_shutdown);
/*
* tpm2_calc_ordinal_duration() - maximum duration for a command
......@@ -793,7 +791,7 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST];
if (index != TPM_UNDEFINED)
duration = chip->vendor.duration[index];
duration = chip->duration[index];
if (duration <= 0)
duration = 2 * 60 * HZ;
......@@ -837,7 +835,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
* immediately. This is a workaround for that.
*/
if (rc == TPM2_RC_TESTING) {
dev_warn(chip->pdev, "Got RC_TESTING, ignoring\n");
dev_warn(&chip->dev, "Got RC_TESTING, ignoring\n");
rc = 0;
}
......@@ -855,7 +853,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
* returned it remarks a POSIX error code. If a positive number is returned
* it remarks a TPM error.
*/
int tpm2_do_selftest(struct tpm_chip *chip)
static int tpm2_do_selftest(struct tpm_chip *chip)
{
int rc;
unsigned int loops;
......@@ -895,7 +893,6 @@ int tpm2_do_selftest(struct tpm_chip *chip)
return rc;
}
EXPORT_SYMBOL_GPL(tpm2_do_selftest);
/**
* tpm2_gen_interrupt() - generate an interrupt
......@@ -943,3 +940,43 @@ int tpm2_probe(struct tpm_chip *chip)
return 0;
}
EXPORT_SYMBOL_GPL(tpm2_probe);
/**
* tpm2_auto_startup - Perform the standard automatic TPM initialization
* sequence
* @chip: TPM chip to use
*
* Returns 0 on success, < 0 in case of fatal error.
*/
int tpm2_auto_startup(struct tpm_chip *chip)
{
int rc;
rc = tpm_get_timeouts(chip);
if (rc)
goto out;
rc = tpm2_do_selftest(chip);
if (rc != TPM2_RC_INITIALIZE) {
dev_err(&chip->dev, "TPM self test failed\n");
goto out;
}
if (rc == TPM2_RC_INITIALIZE) {
rc = tpm2_startup(chip, TPM2_SU_CLEAR);
if (rc)
goto out;
rc = tpm2_do_selftest(chip);
if (rc) {
dev_err(&chip->dev, "TPM self test failed\n");
goto out;
}
}
return rc;
out:
if (rc > 0)
rc = -ENODEV;
return rc;
}
......@@ -37,6 +37,7 @@ enum tpm_atmel_read_status {
static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
u8 status, *hdr = buf;
u32 size;
int i;
......@@ -47,12 +48,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -EIO;
for (i = 0; i < 6; i++) {
status = ioread8(chip->vendor.iobase + 1);
status = ioread8(priv->iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->pdev, "error reading header\n");
dev_err(&chip->dev, "error reading header\n");
return -EIO;
}
*buf++ = ioread8(chip->vendor.iobase);
*buf++ = ioread8(priv->iobase);
}
/* size of the data received */
......@@ -60,12 +61,12 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size = be32_to_cpu(*native_size);
if (count < size) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */
status = ioread8(chip->vendor.iobase + 1);
status = ioread8(priv->iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->pdev, "error reading data\n");
dev_err(&chip->dev, "error reading data\n");
return -EIO;
}
}
......@@ -74,19 +75,19 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read all the data available */
for (; i < size; i++) {
status = ioread8(chip->vendor.iobase + 1);
status = ioread8(priv->iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->pdev, "error reading data\n");
dev_err(&chip->dev, "error reading data\n");
return -EIO;
}
*buf++ = ioread8(chip->vendor.iobase);
*buf++ = ioread8(priv->iobase);
}
/* make sure data available is gone */
status = ioread8(chip->vendor.iobase + 1);
status = ioread8(priv->iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) {
dev_err(chip->pdev, "data available is stuck\n");
dev_err(&chip->dev, "data available is stuck\n");
return -EIO;
}
......@@ -95,12 +96,13 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
int i;
dev_dbg(chip->pdev, "tpm_atml_send:\n");
dev_dbg(&chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) {
dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
iowrite8(buf[i], chip->vendor.iobase);
dev_dbg(&chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
iowrite8(buf[i], priv->iobase);
}
return count;
......@@ -108,12 +110,16 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count)
static void tpm_atml_cancel(struct tpm_chip *chip)
{
iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
iowrite8(ATML_STATUS_ABORT, priv->iobase + 1);
}
static u8 tpm_atml_status(struct tpm_chip *chip)
{
return ioread8(chip->vendor.iobase + 1);
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
return ioread8(priv->iobase + 1);
}
static bool tpm_atml_req_canceled(struct tpm_chip *chip, u8 status)
......@@ -136,13 +142,13 @@ static struct platform_device *pdev;
static void atml_plat_remove(void)
{
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
struct tpm_atmel_priv *priv = dev_get_drvdata(&chip->dev);
if (chip) {
tpm_chip_unregister(chip);
if (chip->vendor.have_region)
atmel_release_region(chip->vendor.base,
chip->vendor.region_size);
atmel_put_base_addr(chip->vendor.iobase);
if (priv->have_region)
atmel_release_region(priv->base, priv->region_size);
atmel_put_base_addr(priv->iobase);
platform_device_unregister(pdev);
}
}
......@@ -163,6 +169,7 @@ static int __init init_atmel(void)
int have_region, region_size;
unsigned long base;
struct tpm_chip *chip;
struct tpm_atmel_priv *priv;
rc = platform_driver_register(&atml_drv);
if (rc)
......@@ -183,16 +190,24 @@ static int __init init_atmel(void)
goto err_rel_reg;
}
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
rc = -ENOMEM;
goto err_unreg_dev;
}
priv->iobase = iobase;
priv->base = base;
priv->have_region = have_region;
priv->region_size = region_size;
chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel);
if (IS_ERR(chip)) {
rc = PTR_ERR(chip);
goto err_unreg_dev;
}
chip->vendor.iobase = iobase;
chip->vendor.base = base;
chip->vendor.have_region = have_region;
chip->vendor.region_size = region_size;
dev_set_drvdata(&chip->dev, priv);
rc = tpm_chip_register(chip);
if (rc)
......
......@@ -22,12 +22,19 @@
*
*/
struct tpm_atmel_priv {
int region_size;
int have_region;
unsigned long base;
void __iomem *iobase;
};
#ifdef CONFIG_PPC64
#include <asm/prom.h>
#define atmel_getb(chip, offset) readb(chip->vendor->iobase + offset);
#define atmel_putb(val, chip, offset) writeb(val, chip->vendor->iobase + offset)
#define atmel_getb(priv, offset) readb(priv->iobase + offset)
#define atmel_putb(val, priv, offset) writeb(val, priv->iobase + offset)
#define atmel_request_region request_mem_region
#define atmel_release_region release_mem_region
......@@ -78,8 +85,9 @@ static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
return ioremap(*base, *region_size);
}
#else
#define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
#define atmel_putb(val, chip, offset) outb(val, chip->vendor->base + offset)
#define atmel_getb(chip, offset) inb(atmel_get_priv(chip)->base + offset)
#define atmel_putb(val, chip, offset) \
outb(val, atmel_get_priv(chip)->base + offset)
#define atmel_request_region request_region
#define atmel_release_region release_region
/* Atmel definitions */
......
......@@ -77,7 +77,6 @@ enum crb_flags {
struct crb_priv {
unsigned int flags;
struct resource res;
void __iomem *iobase;
struct crb_control_area __iomem *cca;
u8 __iomem *cmd;
......@@ -88,7 +87,7 @@ static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume);
static u8 crb_status(struct tpm_chip *chip)
{
struct crb_priv *priv = chip->vendor.priv;
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
u8 sts = 0;
if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) !=
......@@ -100,7 +99,7 @@ static u8 crb_status(struct tpm_chip *chip)
static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct crb_priv *priv = chip->vendor.priv;
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
unsigned int expected;
/* sanity check */
......@@ -140,7 +139,7 @@ static int crb_do_acpi_start(struct tpm_chip *chip)
static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct crb_priv *priv = chip->vendor.priv;
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
int rc = 0;
if (len > ioread32(&priv->cca->cmd_size)) {
......@@ -167,7 +166,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len)
static void crb_cancel(struct tpm_chip *chip)
{
struct crb_priv *priv = chip->vendor.priv;
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
iowrite32(cpu_to_le32(CRB_CANCEL_INVOKE), &priv->cca->cancel);
......@@ -182,13 +181,14 @@ static void crb_cancel(struct tpm_chip *chip)
static bool crb_req_canceled(struct tpm_chip *chip, u8 status)
{
struct crb_priv *priv = chip->vendor.priv;
struct crb_priv *priv = dev_get_drvdata(&chip->dev);
u32 cancel = ioread32(&priv->cca->cancel);
return (cancel & CRB_CANCEL_INVOKE) == CRB_CANCEL_INVOKE;
}
static const struct tpm_class_ops tpm_crb = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = crb_status,
.recv = crb_recv,
.send = crb_send,
......@@ -201,42 +201,33 @@ static const struct tpm_class_ops tpm_crb = {
static int crb_init(struct acpi_device *device, struct crb_priv *priv)
{
struct tpm_chip *chip;
int rc;
chip = tpmm_chip_alloc(&device->dev, &tpm_crb);
if (IS_ERR(chip))
return PTR_ERR(chip);
chip->vendor.priv = priv;
dev_set_drvdata(&chip->dev, priv);
chip->acpi_dev_handle = device->handle;
chip->flags = TPM_CHIP_FLAG_TPM2;
rc = tpm_get_timeouts(chip);
if (rc)
return rc;
rc = tpm2_do_selftest(chip);
if (rc)
return rc;
return tpm_chip_register(chip);
}
static int crb_check_resource(struct acpi_resource *ares, void *data)
{
struct crb_priv *priv = data;
struct resource *io_res = data;
struct resource res;
if (acpi_dev_resource_memory(ares, &res)) {
priv->res = res;
priv->res.name = NULL;
*io_res = res;
io_res->name = NULL;
}
return 1;
}
static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
u64 start, u32 size)
struct resource *io_res, u64 start, u32 size)
{
struct resource new_res = {
.start = start,
......@@ -246,53 +237,74 @@ static void __iomem *crb_map_res(struct device *dev, struct crb_priv *priv,
/* Detect a 64 bit address on a 32 bit system */
if (start != new_res.start)
return ERR_PTR(-EINVAL);
return (void __iomem *) ERR_PTR(-EINVAL);
if (!resource_contains(&priv->res, &new_res))
if (!resource_contains(io_res, &new_res))
return devm_ioremap_resource(dev, &new_res);
return priv->iobase + (new_res.start - priv->res.start);
return priv->iobase + (new_res.start - io_res->start);
}
static int crb_map_io(struct acpi_device *device, struct crb_priv *priv,
struct acpi_table_tpm2 *buf)
{
struct list_head resources;
struct resource io_res;
struct device *dev = &device->dev;
u64 pa;
u64 cmd_pa;
u32 cmd_size;
u64 rsp_pa;
u32 rsp_size;
int ret;
INIT_LIST_HEAD(&resources);
ret = acpi_dev_get_resources(device, &resources, crb_check_resource,
priv);
&io_res);
if (ret < 0)
return ret;
acpi_dev_free_resource_list(&resources);
if (resource_type(&priv->res) != IORESOURCE_MEM) {
if (resource_type(&io_res) != IORESOURCE_MEM) {
dev_err(dev,
FW_BUG "TPM2 ACPI table does not define a memory resource\n");
return -EINVAL;
}
priv->iobase = devm_ioremap_resource(dev, &priv->res);
priv->iobase = devm_ioremap_resource(dev, &io_res);
if (IS_ERR(priv->iobase))
return PTR_ERR(priv->iobase);
priv->cca = crb_map_res(dev, priv, buf->control_address, 0x1000);
priv->cca = crb_map_res(dev, priv, &io_res, buf->control_address,
sizeof(struct crb_control_area));
if (IS_ERR(priv->cca))
return PTR_ERR(priv->cca);
pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
(u64) ioread32(&priv->cca->cmd_pa_low);
priv->cmd = crb_map_res(dev, priv, pa, ioread32(&priv->cca->cmd_size));
cmd_pa = ((u64) ioread32(&priv->cca->cmd_pa_high) << 32) |
(u64) ioread32(&priv->cca->cmd_pa_low);
cmd_size = ioread32(&priv->cca->cmd_size);
priv->cmd = crb_map_res(dev, priv, &io_res, cmd_pa, cmd_size);
if (IS_ERR(priv->cmd))
return PTR_ERR(priv->cmd);
memcpy_fromio(&pa, &priv->cca->rsp_pa, 8);
pa = le64_to_cpu(pa);
priv->rsp = crb_map_res(dev, priv, pa, ioread32(&priv->cca->rsp_size));
return PTR_ERR_OR_ZERO(priv->rsp);
memcpy_fromio(&rsp_pa, &priv->cca->rsp_pa, 8);
rsp_pa = le64_to_cpu(rsp_pa);
rsp_size = ioread32(&priv->cca->rsp_size);
if (cmd_pa != rsp_pa) {
priv->rsp = crb_map_res(dev, priv, &io_res, rsp_pa, rsp_size);
return PTR_ERR_OR_ZERO(priv->rsp);
}
/* According to the PTP specification, overlapping command and response
* buffer sizes must be identical.
*/
if (cmd_size != rsp_size) {
dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical");
return -EINVAL;
}
priv->rsp = priv->cmd;
return 0;
}
static int crb_acpi_add(struct acpi_device *device)
......@@ -344,9 +356,6 @@ static int crb_acpi_remove(struct acpi_device *device)
struct device *dev = &device->dev;
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_unregister(chip);
return 0;
......
......@@ -403,7 +403,7 @@ static int is_bad(void *p)
return 0;
}
struct dentry **tpm_bios_log_setup(char *name)
struct dentry **tpm_bios_log_setup(const char *name)
{
struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file;
......
......@@ -77,10 +77,10 @@ int read_log(struct tpm_bios_log *log);
#if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \
defined(CONFIG_ACPI)
extern struct dentry **tpm_bios_log_setup(char *);
extern struct dentry **tpm_bios_log_setup(const char *);
extern void tpm_bios_log_teardown(struct dentry **);
#else
static inline struct dentry **tpm_bios_log_setup(char *name)
static inline struct dentry **tpm_bios_log_setup(const char *name)
{
return NULL;
}
......
......@@ -51,8 +51,8 @@ struct priv_data {
static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct priv_data *priv = chip->vendor.priv;
struct i2c_client *client = to_i2c_client(chip->pdev);
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
priv->len = 0;
......@@ -62,7 +62,7 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
status = i2c_master_send(client, buf, len);
dev_dbg(chip->pdev,
dev_dbg(&chip->dev,
"%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
(int)min_t(size_t, 64, len), buf, len, status);
return status;
......@@ -70,8 +70,8 @@ static int i2c_atmel_send(struct tpm_chip *chip, u8 *buf, size_t len)
static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct priv_data *priv = chip->vendor.priv;
struct i2c_client *client = to_i2c_client(chip->pdev);
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
struct tpm_output_header *hdr =
(struct tpm_output_header *)priv->buffer;
u32 expected_len;
......@@ -88,7 +88,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
return -ENOMEM;
if (priv->len >= expected_len) {
dev_dbg(chip->pdev,
dev_dbg(&chip->dev,
"%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count,
expected_len);
......@@ -97,7 +97,7 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
}
rc = i2c_master_recv(client, buf, expected_len);
dev_dbg(chip->pdev,
dev_dbg(&chip->dev,
"%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
(int)min_t(size_t, 64, expected_len), buf, count,
expected_len);
......@@ -106,13 +106,13 @@ static int i2c_atmel_recv(struct tpm_chip *chip, u8 *buf, size_t count)
static void i2c_atmel_cancel(struct tpm_chip *chip)
{
dev_err(chip->pdev, "TPM operation cancellation was requested, but is not supported");
dev_err(&chip->dev, "TPM operation cancellation was requested, but is not supported");
}
static u8 i2c_atmel_read_status(struct tpm_chip *chip)
{
struct priv_data *priv = chip->vendor.priv;
struct i2c_client *client = to_i2c_client(chip->pdev);
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
int rc;
/* The TPM fails the I2C read until it is ready, so we do the entire
......@@ -125,7 +125,7 @@ static u8 i2c_atmel_read_status(struct tpm_chip *chip)
/* Once the TPM has completed the command the command remains readable
* until another command is issued. */
rc = i2c_master_recv(client, priv->buffer, sizeof(priv->buffer));
dev_dbg(chip->pdev,
dev_dbg(&chip->dev,
"%s: sts=%d", __func__, rc);
if (rc <= 0)
return 0;
......@@ -141,6 +141,7 @@ static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status)
}
static const struct tpm_class_ops i2c_atmel = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = i2c_atmel_read_status,
.recv = i2c_atmel_recv,
.send = i2c_atmel_send,
......@@ -155,6 +156,7 @@ static int i2c_atmel_probe(struct i2c_client *client,
{
struct tpm_chip *chip;
struct device *dev = &client->dev;
struct priv_data *priv;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
......@@ -163,26 +165,21 @@ static int i2c_atmel_probe(struct i2c_client *client,
if (IS_ERR(chip))
return PTR_ERR(chip);
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
GFP_KERNEL);
if (!chip->vendor.priv)
priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
if (!priv)
return -ENOMEM;
/* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.irq = 0;
chip->timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
chip->timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
dev_set_drvdata(&chip->dev, priv);
/* There is no known way to probe for this device, and all version
* information seems to be read via TPM commands. Thus we rely on the
* TPM startup process in the common code to detect the device. */
if (tpm_get_timeouts(chip))
return -ENODEV;
if (tpm_do_selftest(chip))
return -ENODEV;
return tpm_chip_register(chip);
}
......
......@@ -66,6 +66,7 @@ enum i2c_chip_type {
/* Structure to store I2C TPM specific stuff */
struct tpm_inf_dev {
struct i2c_client *client;
int locality;
u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */
struct tpm_chip *chip;
enum i2c_chip_type chip_type;
......@@ -288,7 +289,7 @@ static int check_locality(struct tpm_chip *chip, int loc)
if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
(TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) {
chip->vendor.locality = loc;
tpm_dev.locality = loc;
return loc;
}
......@@ -320,7 +321,7 @@ static int request_locality(struct tpm_chip *chip, int loc)
iic_tpm_write(TPM_ACCESS(loc), &buf, 1);
/* wait for burstcount */
stop = jiffies + chip->vendor.timeout_a;
stop = jiffies + chip->timeout_a;
do {
if (check_locality(chip, loc) >= 0)
return loc;
......@@ -337,7 +338,7 @@ static u8 tpm_tis_i2c_status(struct tpm_chip *chip)
u8 i = 0;
do {
if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0)
if (iic_tpm_read(TPM_STS(tpm_dev.locality), &buf, 1) < 0)
return 0;
i++;
......@@ -351,7 +352,7 @@ static void tpm_tis_i2c_ready(struct tpm_chip *chip)
{
/* this causes the current command to be aborted */
u8 buf = TPM_STS_COMMAND_READY;
iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1);
iic_tpm_write_long(TPM_STS(tpm_dev.locality), &buf, 1);
}
static ssize_t get_burstcount(struct tpm_chip *chip)
......@@ -362,10 +363,10 @@ static ssize_t get_burstcount(struct tpm_chip *chip)
/* wait for burstcount */
/* which timeout value, spec has 2 answers (c & d) */
stop = jiffies + chip->vendor.timeout_d;
stop = jiffies + chip->timeout_d;
do {
/* Note: STS is little endian */
if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0)
if (iic_tpm_read(TPM_STS(tpm_dev.locality)+1, buf, 3) < 0)
burstcnt = 0;
else
burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0];
......@@ -419,7 +420,7 @@ static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
if (burstcnt > (count - size))
burstcnt = count - size;
rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality),
rc = iic_tpm_read(TPM_DATA_FIFO(tpm_dev.locality),
&(buf[size]), burstcnt);
if (rc == 0)
size += burstcnt;
......@@ -446,7 +447,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
/* read first 10 bytes, including tag, paramsize, and result */
size = recv_data(chip, buf, TPM_HEADER_SIZE);
if (size < TPM_HEADER_SIZE) {
dev_err(chip->pdev, "Unable to read header\n");
dev_err(&chip->dev, "Unable to read header\n");
goto out;
}
......@@ -459,14 +460,14 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
size += recv_data(chip, &buf[TPM_HEADER_SIZE],
expected - TPM_HEADER_SIZE);
if (size < expected) {
dev_err(chip->pdev, "Unable to read remainder of result\n");
dev_err(&chip->dev, "Unable to read remainder of result\n");
size = -ETIME;
goto out;
}
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
dev_err(chip->pdev, "Error left over data\n");
dev_err(&chip->dev, "Error left over data\n");
size = -EIO;
goto out;
}
......@@ -477,7 +478,7 @@ static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count)
* so we sleep rather than keeping the bus busy
*/
usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
release_locality(chip, chip->vendor.locality, 0);
release_locality(chip, tpm_dev.locality, 0);
return size;
}
......@@ -500,7 +501,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
tpm_tis_i2c_ready(chip);
if (wait_for_stat
(chip, TPM_STS_COMMAND_READY,
chip->vendor.timeout_b, &status) < 0) {
chip->timeout_b, &status) < 0) {
rc = -ETIME;
goto out_err;
}
......@@ -516,7 +517,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
if (burstcnt > (len - 1 - count))
burstcnt = len - 1 - count;
rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality),
rc = iic_tpm_write(TPM_DATA_FIFO(tpm_dev.locality),
&(buf[count]), burstcnt);
if (rc == 0)
count += burstcnt;
......@@ -530,7 +531,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
}
wait_for_stat(chip, TPM_STS_VALID,
chip->vendor.timeout_c, &status);
chip->timeout_c, &status);
if ((status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO;
......@@ -539,15 +540,15 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
}
/* write last byte */
iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1);
wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status);
iic_tpm_write(TPM_DATA_FIFO(tpm_dev.locality), &(buf[count]), 1);
wait_for_stat(chip, TPM_STS_VALID, chip->timeout_c, &status);
if ((status & TPM_STS_DATA_EXPECT) != 0) {
rc = -EIO;
goto out_err;
}
/* go and do it */
iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1);
iic_tpm_write(TPM_STS(tpm_dev.locality), &sts, 1);
return len;
out_err:
......@@ -556,7 +557,7 @@ static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len)
* so we sleep rather than keeping the bus busy
*/
usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI);
release_locality(chip, chip->vendor.locality, 0);
release_locality(chip, tpm_dev.locality, 0);
return rc;
}
......@@ -566,6 +567,7 @@ static bool tpm_tis_i2c_req_canceled(struct tpm_chip *chip, u8 status)
}
static const struct tpm_class_ops tpm_tis_i2c = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = tpm_tis_i2c_status,
.recv = tpm_tis_i2c_recv,
.send = tpm_tis_i2c_send,
......@@ -585,14 +587,11 @@ static int tpm_tis_i2c_init(struct device *dev)
if (IS_ERR(chip))
return PTR_ERR(chip);
/* Disable interrupts */
chip->vendor.irq = 0;
/* Default timeouts */
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);
if (request_locality(chip, 0) != 0) {
dev_err(dev, "could not request locality\n");
......@@ -619,15 +618,11 @@ static int tpm_tis_i2c_init(struct device *dev)
dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16);
INIT_LIST_HEAD(&chip->vendor.list);
tpm_dev.chip = chip;
tpm_get_timeouts(chip);
tpm_do_selftest(chip);
return tpm_chip_register(chip);
out_release:
release_locality(chip, chip->vendor.locality, 1);
release_locality(chip, tpm_dev.locality, 1);
tpm_dev.client = NULL;
out_err:
return rc;
......@@ -699,7 +694,7 @@ static int tpm_tis_i2c_remove(struct i2c_client *client)
struct tpm_chip *chip = tpm_dev.chip;
tpm_chip_unregister(chip);
release_locality(chip, chip->vendor.locality, 1);
release_locality(chip, tpm_dev.locality, 1);
tpm_dev.client = NULL;
return 0;
......
/******************************************************************************
* Nuvoton TPM I2C Device Driver Interface for WPCT301/NPCT501,
/******************************************************************************
* Nuvoton TPM I2C Device Driver Interface for WPCT301/NPCT501/NPCT6XX,
* based on the TCG TPM Interface Spec version 1.2.
* Specifications at www.trustedcomputinggroup.org
*
......@@ -31,6 +31,7 @@
#include <linux/interrupt.h>
#include <linux/wait.h>
#include <linux/i2c.h>
#include <linux/of_device.h>
#include "tpm.h"
/* I2C interface offsets */
......@@ -52,10 +53,13 @@
#define TPM_I2C_RETRY_DELAY_SHORT 2 /* msec */
#define TPM_I2C_RETRY_DELAY_LONG 10 /* msec */
#define I2C_DRIVER_NAME "tpm_i2c_nuvoton"
#define OF_IS_TPM2 ((void *)1)
#define I2C_IS_TPM2 1
struct priv_data {
int irq;
unsigned int intrs;
wait_queue_head_t read_queue;
};
static s32 i2c_nuvoton_read_buf(struct i2c_client *client, u8 offset, u8 size,
......@@ -96,13 +100,13 @@ static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size,
/* read TPM_STS register */
static u8 i2c_nuvoton_read_status(struct tpm_chip *chip)
{
struct i2c_client *client = to_i2c_client(chip->pdev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
u8 data;
status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data);
if (status <= 0) {
dev_err(chip->pdev, "%s() error return %d\n", __func__,
dev_err(&chip->dev, "%s() error return %d\n", __func__,
status);
data = TPM_STS_ERR_VAL;
}
......@@ -127,13 +131,13 @@ static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data)
/* write commandReady to TPM_STS register */
static void i2c_nuvoton_ready(struct tpm_chip *chip)
{
struct i2c_client *client = to_i2c_client(chip->pdev);
struct i2c_client *client = to_i2c_client(chip->dev.parent);
s32 status;
/* this causes the current command to be aborted */
status = i2c_nuvoton_write_status(client, TPM_STS_COMMAND_READY);
if (status < 0)
dev_err(chip->pdev,
dev_err(&chip->dev,
"%s() fail to write TPM_STS.commandReady\n", __func__);
}
......@@ -142,7 +146,7 @@ static void i2c_nuvoton_ready(struct tpm_chip *chip)
static int i2c_nuvoton_get_burstcount(struct i2c_client *client,
struct tpm_chip *chip)
{
unsigned long stop = jiffies + chip->vendor.timeout_d;
unsigned long stop = jiffies + chip->timeout_d;
s32 status;
int burst_count = -1;
u8 data;
......@@ -163,7 +167,7 @@ static int i2c_nuvoton_get_burstcount(struct i2c_client *client,
}
/*
* WPCT301/NPCT501 SINT# supports only dataAvail
* WPCT301/NPCT501/NPCT6XX SINT# supports only dataAvail
* any call to this function which is not waiting for dataAvail will
* set queue to NULL to avoid waiting for interrupt
*/
......@@ -176,12 +180,12 @@ static bool i2c_nuvoton_check_status(struct tpm_chip *chip, u8 mask, u8 value)
static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
u32 timeout, wait_queue_head_t *queue)
{
if (chip->vendor.irq && queue) {
if ((chip->flags & TPM_CHIP_FLAG_IRQ) && queue) {
s32 rc;
struct priv_data *priv = chip->vendor.priv;
struct priv_data *priv = dev_get_drvdata(&chip->dev);
unsigned int cur_intrs = priv->intrs;
enable_irq(chip->vendor.irq);
enable_irq(priv->irq);
rc = wait_event_interruptible_timeout(*queue,
cur_intrs != priv->intrs,
timeout);
......@@ -212,7 +216,7 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
return 0;
} while (time_before(jiffies, stop));
}
dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
dev_err(&chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
value);
return -ETIMEDOUT;
}
......@@ -231,16 +235,17 @@ static int i2c_nuvoton_wait_for_data_avail(struct tpm_chip *chip, u32 timeout,
static int i2c_nuvoton_recv_data(struct i2c_client *client,
struct tpm_chip *chip, u8 *buf, size_t count)
{
struct priv_data *priv = dev_get_drvdata(&chip->dev);
s32 rc;
int burst_count, bytes2read, size = 0;
while (size < count &&
i2c_nuvoton_wait_for_data_avail(chip,
chip->vendor.timeout_c,
&chip->vendor.read_queue) == 0) {
chip->timeout_c,
&priv->read_queue) == 0) {
burst_count = i2c_nuvoton_get_burstcount(client, chip);
if (burst_count < 0) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"%s() fail to read burstCount=%d\n", __func__,
burst_count);
return -EIO;
......@@ -249,12 +254,12 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R,
bytes2read, &buf[size]);
if (rc < 0) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"%s() fail on i2c_nuvoton_read_buf()=%d\n",
__func__, rc);
return -EIO;
}
dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read);
dev_dbg(&chip->dev, "%s(%d):", __func__, bytes2read);
size += bytes2read;
}
......@@ -264,7 +269,8 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client,
/* Read TPM command results */
static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct device *dev = chip->pdev;
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
s32 rc;
int expected, status, burst_count, retries, size = 0;
......@@ -285,7 +291,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
* tag, paramsize, and result
*/
status = i2c_nuvoton_wait_for_data_avail(
chip, chip->vendor.timeout_c, &chip->vendor.read_queue);
chip, chip->timeout_c, &priv->read_queue);
if (status != 0) {
dev_err(dev, "%s() timeout on dataAvail\n", __func__);
size = -ETIMEDOUT;
......@@ -325,7 +331,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
}
if (i2c_nuvoton_wait_for_stat(
chip, TPM_STS_VALID | TPM_STS_DATA_AVAIL,
TPM_STS_VALID, chip->vendor.timeout_c,
TPM_STS_VALID, chip->timeout_c,
NULL)) {
dev_err(dev, "%s() error left over data\n", __func__);
size = -ETIMEDOUT;
......@@ -334,7 +340,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
break;
}
i2c_nuvoton_ready(chip);
dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size);
dev_dbg(&chip->dev, "%s() -> %d\n", __func__, size);
return size;
}
......@@ -347,7 +353,8 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
*/
static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
{
struct device *dev = chip->pdev;
struct priv_data *priv = dev_get_drvdata(&chip->dev);
struct device *dev = chip->dev.parent;
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
......@@ -357,7 +364,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
i2c_nuvoton_ready(chip);
if (i2c_nuvoton_wait_for_stat(chip, TPM_STS_COMMAND_READY,
TPM_STS_COMMAND_READY,
chip->vendor.timeout_b, NULL)) {
chip->timeout_b, NULL)) {
dev_err(dev, "%s() timeout on commandReady\n",
__func__);
rc = -EIO;
......@@ -389,7 +396,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
TPM_STS_EXPECT,
TPM_STS_VALID |
TPM_STS_EXPECT,
chip->vendor.timeout_c,
chip->timeout_c,
NULL);
if (rc < 0) {
dev_err(dev, "%s() timeout on Expect\n",
......@@ -414,7 +421,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
rc = i2c_nuvoton_wait_for_stat(chip,
TPM_STS_VALID | TPM_STS_EXPECT,
TPM_STS_VALID,
chip->vendor.timeout_c, NULL);
chip->timeout_c, NULL);
if (rc) {
dev_err(dev, "%s() timeout on Expect to clear\n",
__func__);
......@@ -439,7 +446,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
rc = i2c_nuvoton_wait_for_data_avail(chip,
tpm_calc_ordinal_duration(chip,
ordinal),
&chip->vendor.read_queue);
&priv->read_queue);
if (rc) {
dev_err(dev, "%s() timeout command duration\n", __func__);
i2c_nuvoton_ready(chip);
......@@ -456,6 +463,7 @@ static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status)
}
static const struct tpm_class_ops tpm_i2c = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = i2c_nuvoton_read_status,
.recv = i2c_nuvoton_recv,
.send = i2c_nuvoton_send,
......@@ -473,11 +481,11 @@ static const struct tpm_class_ops tpm_i2c = {
static irqreturn_t i2c_nuvoton_int_handler(int dummy, void *dev_id)
{
struct tpm_chip *chip = dev_id;
struct priv_data *priv = chip->vendor.priv;
struct priv_data *priv = dev_get_drvdata(&chip->dev);
priv->intrs++;
wake_up(&chip->vendor.read_queue);
disable_irq_nosync(chip->vendor.irq);
wake_up(&priv->read_queue);
disable_irq_nosync(priv->irq);
return IRQ_HANDLED;
}
......@@ -521,6 +529,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
int rc;
struct tpm_chip *chip;
struct device *dev = &client->dev;
struct priv_data *priv;
u32 vid = 0;
rc = get_vid(client, &vid);
......@@ -534,46 +543,56 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
if (IS_ERR(chip))
return PTR_ERR(chip);
chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
GFP_KERNEL);
if (!chip->vendor.priv)
priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
if (!priv)
return -ENOMEM;
init_waitqueue_head(&chip->vendor.read_queue);
init_waitqueue_head(&chip->vendor.int_queue);
if (dev->of_node) {
const struct of_device_id *of_id;
of_id = of_match_device(dev->driver->of_match_table, dev);
if (of_id && of_id->data == OF_IS_TPM2)
chip->flags |= TPM_CHIP_FLAG_TPM2;
} else
if (id->driver_data == I2C_IS_TPM2)
chip->flags |= TPM_CHIP_FLAG_TPM2;
init_waitqueue_head(&priv->read_queue);
/* Default timeouts */
chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
chip->timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
chip->timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
dev_set_drvdata(&chip->dev, priv);
/*
* I2C intfcaps (interrupt capabilitieis) in the chip are hard coded to:
* TPM_INTF_INT_LEVEL_LOW | TPM_INTF_DATA_AVAIL_INT
* The IRQ should be set in the i2c_board_info (which is done
* automatically in of_i2c_register_devices, for device tree users */
chip->vendor.irq = client->irq;
if (chip->vendor.irq) {
dev_dbg(dev, "%s() chip-vendor.irq\n", __func__);
rc = devm_request_irq(dev, chip->vendor.irq,
priv->irq = client->irq;
if (client->irq) {
dev_dbg(dev, "%s() priv->irq\n", __func__);
rc = devm_request_irq(dev, client->irq,
i2c_nuvoton_int_handler,
IRQF_TRIGGER_LOW,
chip->devname,
dev_name(&chip->dev),
chip);
if (rc) {
dev_err(dev, "%s() Unable to request irq: %d for use\n",
__func__, chip->vendor.irq);
chip->vendor.irq = 0;
__func__, priv->irq);
priv->irq = 0;
} else {
chip->flags |= TPM_CHIP_FLAG_IRQ;
/* Clear any pending interrupt */
i2c_nuvoton_ready(chip);
/* - wait for TPM_STS==0xA0 (stsValid, commandReady) */
rc = i2c_nuvoton_wait_for_stat(chip,
TPM_STS_COMMAND_READY,
TPM_STS_COMMAND_READY,
chip->vendor.timeout_b,
chip->timeout_b,
NULL);
if (rc == 0) {
/*
......@@ -601,25 +620,20 @@ static int i2c_nuvoton_probe(struct i2c_client *client,
}
}
if (tpm_get_timeouts(chip))
return -ENODEV;
if (tpm_do_selftest(chip))
return -ENODEV;
return tpm_chip_register(chip);
}
static int i2c_nuvoton_remove(struct i2c_client *client)
{
struct device *dev = &(client->dev);
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_chip *chip = i2c_get_clientdata(client);
tpm_chip_unregister(chip);
return 0;
}
static const struct i2c_device_id i2c_nuvoton_id[] = {
{I2C_DRIVER_NAME, 0},
{"tpm_i2c_nuvoton"},
{"tpm2_i2c_nuvoton", .driver_data = I2C_IS_TPM2},
{}
};
MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id);
......@@ -628,6 +642,7 @@ MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id);
static const struct of_device_id i2c_nuvoton_of_match[] = {
{.compatible = "nuvoton,npct501"},
{.compatible = "winbond,wpct301"},
{.compatible = "nuvoton,npct601", .data = OF_IS_TPM2},
{},
};
MODULE_DEVICE_TABLE(of, i2c_nuvoton_of_match);
......@@ -640,7 +655,7 @@ static struct i2c_driver i2c_nuvoton_driver = {
.probe = i2c_nuvoton_probe,
.remove = i2c_nuvoton_remove,
.driver = {
.name = I2C_DRIVER_NAME,
.name = "tpm_i2c_nuvoton",
.pm = &i2c_nuvoton_pm_ops,
.of_match_table = of_match_ptr(i2c_nuvoton_of_match),
},
......
......@@ -53,21 +53,6 @@ static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2)
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2);
}
/**
* ibmvtpm_get_data - Retrieve ibm vtpm data
* @dev: device struct
*
* Return value:
* vtpm device struct
*/
static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip)
return (struct ibmvtpm_dev *)TPM_VPRIV(chip);
return NULL;
}
/**
* tpm_ibmvtpm_recv - Receive data after send
* @chip: tpm chip struct
......@@ -79,12 +64,10 @@ static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev)
*/
static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct ibmvtpm_dev *ibmvtpm;
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
u16 len;
int sig;
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
if (!ibmvtpm->rtce_buf) {
dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
return 0;
......@@ -122,13 +105,11 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
*/
static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
{
struct ibmvtpm_dev *ibmvtpm;
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
struct ibmvtpm_crq crq;
__be64 *word = (__be64 *)&crq;
int rc, sig;
ibmvtpm = (struct ibmvtpm_dev *)TPM_VPRIV(chip);
if (!ibmvtpm->rtce_buf) {
dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n");
return 0;
......@@ -289,8 +270,8 @@ static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm)
*/
static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
{
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
struct tpm_chip *chip = dev_get_drvdata(ibmvtpm->dev);
struct tpm_chip *chip = dev_get_drvdata(&vdev->dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
int rc = 0;
tpm_chip_unregister(chip);
......@@ -327,7 +308,8 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev)
*/
static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
{
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev);
struct tpm_chip *chip = dev_get_drvdata(&vdev->dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
/* ibmvtpm initializes at probe time, so the data we are
* asking for may not be set yet. Estimate that 4K required
......@@ -348,7 +330,8 @@ static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev)
*/
static int tpm_ibmvtpm_suspend(struct device *dev)
{
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
struct tpm_chip *chip = dev_get_drvdata(dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
struct ibmvtpm_crq crq;
u64 *buf = (u64 *) &crq;
int rc = 0;
......@@ -400,7 +383,8 @@ static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm)
*/
static int tpm_ibmvtpm_resume(struct device *dev)
{
struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev);
struct tpm_chip *chip = dev_get_drvdata(dev);
struct ibmvtpm_dev *ibmvtpm = dev_get_drvdata(&chip->dev);
int rc = 0;
do {
......@@ -643,7 +627,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev,
crq_q->index = 0;
TPM_VPRIV(chip) = (void *)ibmvtpm;
dev_set_drvdata(&chip->dev, ibmvtpm);
spin_lock_init(&ibmvtpm->rtce_lock);
......
......@@ -195,9 +195,9 @@ static int wait(struct tpm_chip *chip, int wait_for_bit)
}
if (i == TPM_MAX_TRIES) { /* timeout occurs */
if (wait_for_bit == STAT_XFE)
dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n");
dev_err(&chip->dev, "Timeout in wait(STAT_XFE)\n");
if (wait_for_bit == STAT_RDA)
dev_err(chip->pdev, "Timeout in wait(STAT_RDA)\n");
dev_err(&chip->dev, "Timeout in wait(STAT_RDA)\n");
return -EIO;
}
return 0;
......@@ -220,7 +220,7 @@ static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
static void tpm_wtx(struct tpm_chip *chip)
{
number_of_wtx++;
dev_info(chip->pdev, "Granting WTX (%02d / %02d)\n",
dev_info(&chip->dev, "Granting WTX (%02d / %02d)\n",
number_of_wtx, TPM_MAX_WTX_PACKAGES);
wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX);
......@@ -231,7 +231,7 @@ static void tpm_wtx(struct tpm_chip *chip)
static void tpm_wtx_abort(struct tpm_chip *chip)
{
dev_info(chip->pdev, "Aborting WTX\n");
dev_info(&chip->dev, "Aborting WTX\n");
wait_and_send(chip, TPM_VL_VER);
wait_and_send(chip, TPM_CTRL_WTX_ABORT);
wait_and_send(chip, 0x00);
......@@ -257,7 +257,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (buf[0] != TPM_VL_VER) {
dev_err(chip->pdev,
dev_err(&chip->dev,
"Wrong transport protocol implementation!\n");
return -EIO;
}
......@@ -272,7 +272,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if ((size == 0x6D00) && (buf[1] == 0x80)) {
dev_err(chip->pdev, "Error handling on vendor layer!\n");
dev_err(&chip->dev, "Error handling on vendor layer!\n");
return -EIO;
}
......@@ -284,7 +284,7 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (buf[1] == TPM_CTRL_WTX) {
dev_info(chip->pdev, "WTX-package received\n");
dev_info(&chip->dev, "WTX-package received\n");
if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
tpm_wtx(chip);
goto recv_begin;
......@@ -295,14 +295,14 @@ static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
}
if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
dev_info(chip->pdev, "WTX-abort acknowledged\n");
dev_info(&chip->dev, "WTX-abort acknowledged\n");
return size;
}
if (buf[1] == TPM_CTRL_ERROR) {
dev_err(chip->pdev, "ERROR-package received:\n");
dev_err(&chip->dev, "ERROR-package received:\n");
if (buf[4] == TPM_INF_NAK)
dev_err(chip->pdev,
dev_err(&chip->dev,
"-> Negative acknowledgement"
" - retransmit command!\n");
return -EIO;
......@@ -321,7 +321,7 @@ static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
ret = empty_fifo(chip, 1);
if (ret) {
dev_err(chip->pdev, "Timeout while clearing FIFO\n");
dev_err(&chip->dev, "Timeout while clearing FIFO\n");
return -EIO;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment