Commit 43686598 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull tpm updates from Jarkko Sakkinen:
 "A random collection of TPM fixes and one bug fix for trusted keys"

* tag 'tpmdd-next-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
  tpm: st33zp24: remove pointless checks on probe
  tpm/tpm_crb: Fix error message in __crb_relinquish_locality()
  tpm/tpm_ftpm_tee: Fix error handling in ftpm_mod_init()
  tpm: tpm_tis: Add the missed acpi_put_table() to fix memory leak
  tpm: tpm_crb: Add the missed acpi_put_table() to fix memory leak
  tpm: acpi: Call acpi_put_table() to fix memory leak
  tpm: Add flag to use default cancellation policy
  tpm: tis_i2c: Fix sanity check interrupt enable mask
  KEYS: trusted: tee: Make registered shm dependency explicit
  tpm: Avoid function type cast of put_device()
  tpm: st33zp24: switch to using gpiod API
  tpm: st33zp24: drop support for platform data
parents 893660b0 eaabc245
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -90,16 +90,21 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
			return -ENODEV;

		if (tbl->header.length <
				sizeof(*tbl) + sizeof(struct acpi_tpm2_phy))
				sizeof(*tbl) + sizeof(struct acpi_tpm2_phy)) {
			acpi_put_table((struct acpi_table_header *)tbl);
			return -ENODEV;
		}

		tpm2_phy = (void *)tbl + sizeof(*tbl);
		len = tpm2_phy->log_area_minimum_length;

		start = tpm2_phy->log_area_start_address;
		if (!start || !len)
		if (!start || !len) {
			acpi_put_table((struct acpi_table_header *)tbl);
			return -ENODEV;
		}

		acpi_put_table((struct acpi_table_header *)tbl);
		format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
	} else {
		/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
@@ -120,8 +125,10 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
			break;
		}

		acpi_put_table((struct acpi_table_header *)buff);
		format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
	}

	if (!len) {
		dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
		return -EIO;
@@ -156,5 +163,4 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
	kfree(log->bios_event_log);
	log->bios_event_log = NULL;
	return ret;

}
+2 −140
Original line number Diff line number Diff line
@@ -6,13 +6,9 @@

#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/of.h>
#include <linux/acpi.h>
#include <linux/tpm.h>
#include <linux/platform_data/st33zp24.h>

#include "../tpm.h"
#include "st33zp24.h"
@@ -22,7 +18,6 @@
struct st33zp24_i2c_phy {
	struct i2c_client *client;
	u8 buf[ST33ZP24_BUFSIZE + 1];
	int io_lpcpd;
};

/*
@@ -99,115 +94,6 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
	.recv = st33zp24_i2c_recv,
};

static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };

static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
	{ "lpcpd-gpios", &lpcpd_gpios, 1 },
	{},
};

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;
	int ret;

	ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
	if (ret)
		return ret;

	/* Get LPCPD GPIO from ACPI */
	gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", 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;
	int gpio;
	int ret;

	pp = client->dev.of_node;
	if (!pp) {
		dev_err(&client->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(&client->dev,
			"Failed to retrieve lpcpd-gpios from dts.\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;
	}
	/* GPIO request and configuration */
	ret = devm_gpio_request_one(&client->dev, gpio,
			GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
	if (ret) {
		dev_err(&client->dev, "Failed to request lpcpd pin\n");
		return -ENODEV;
	}
	phy->io_lpcpd = gpio;

	return 0;
}

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;

	pdata = client->dev.platform_data;
	if (!pdata) {
		dev_err(&client->dev, "No platform data\n");
		return -ENODEV;
	}

	/* store for late use */
	phy->io_lpcpd = pdata->io_lpcpd;

	if (gpio_is_valid(pdata->io_lpcpd)) {
		ret = devm_gpio_request_one(&client->dev,
				pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
				"TPM IO_LPCPD");
		if (ret) {
			dev_err(&client->dev, "Failed to request lpcpd pin\n");
			return ret;
		}
	}

	return 0;
}

/*
 * st33zp24_i2c_probe initialize the TPM device
 * @param: client, the i2c_client description (TPM I2C description).
@@ -218,16 +104,8 @@ static int st33zp24_i2c_request_resources(struct i2c_client *client)
static int st33zp24_i2c_probe(struct i2c_client *client,
			      const struct i2c_device_id *id)
{
	int ret;
	struct st33zp24_platform_data *pdata;
	struct st33zp24_i2c_phy *phy;

	if (!client) {
		pr_info("%s: i2c client is NULL. Device not accessible.\n",
			__func__);
		return -ENODEV;
	}

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		dev_info(&client->dev, "client not i2c capable\n");
		return -ENODEV;
@@ -240,23 +118,7 @@ static int st33zp24_i2c_probe(struct i2c_client *client,

	phy->client = client;

	pdata = client->dev.platform_data;
	if (!pdata && client->dev.of_node) {
		ret = st33zp24_i2c_of_request_resources(client);
		if (ret)
			return ret;
	} else if (pdata) {
		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;
	}

	return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq,
			      phy->io_lpcpd);
	return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq);
}

/*
+3 −142
Original line number Diff line number Diff line
@@ -6,13 +6,9 @@

#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/of.h>
#include <linux/acpi.h>
#include <linux/tpm.h>
#include <linux/platform_data/st33zp24.h>

#include "../tpm.h"
#include "st33zp24.h"
@@ -61,7 +57,6 @@ struct st33zp24_spi_phy {
	u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE];
	u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE];

	int io_lpcpd;
	int latency;
};

@@ -218,115 +213,6 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
	.recv = st33zp24_spi_recv,
};

static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };

static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
	{ "lpcpd-gpios", &lpcpd_gpios, 1 },
	{},
};

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;
	int ret;

	ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
	if (ret)
		return ret;

	/* Get LPCPD GPIO from ACPI */
	gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", 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;
	int gpio;
	int ret;

	pp = spi_dev->dev.of_node;
	if (!pp) {
		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(&spi_dev->dev,
			"Failed to retrieve lpcpd-gpios from dts.\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;
	}
	/* GPIO request and configuration */
	ret = devm_gpio_request_one(&spi_dev->dev, gpio,
			GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
	if (ret) {
		dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n");
		return -ENODEV;
	}
	phy->io_lpcpd = gpio;

	return 0;
}

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;

	pdata = dev->dev.platform_data;
	if (!pdata) {
		dev_err(&dev->dev, "No platform data\n");
		return -ENODEV;
	}

	/* store for late use */
	phy->io_lpcpd = pdata->io_lpcpd;

	if (gpio_is_valid(pdata->io_lpcpd)) {
		ret = devm_gpio_request_one(&dev->dev,
				pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
				"TPM IO_LPCPD");
		if (ret) {
			dev_err(&dev->dev, "%s : reset gpio_request failed\n",
				__FILE__);
			return ret;
		}
	}

	return 0;
}

/*
 * st33zp24_spi_probe initialize the TPM device
 * @param: dev, the spi_device description (TPM SPI description).
@@ -335,17 +221,8 @@ static int st33zp24_spi_request_resources(struct spi_device *dev)
 */
static int st33zp24_spi_probe(struct spi_device *dev)
{
	int ret;
	struct st33zp24_platform_data *pdata;
	struct st33zp24_spi_phy *phy;

	/* Check SPI platform functionnalities */
	if (!dev) {
		pr_info("%s: dev is NULL. Device is not accessible.\n",
			__func__);
		return -ENODEV;
	}

	phy = devm_kzalloc(&dev->dev, sizeof(struct st33zp24_spi_phy),
			   GFP_KERNEL);
	if (!phy)
@@ -353,27 +230,11 @@ static int st33zp24_spi_probe(struct spi_device *dev)

	phy->spi_device = dev;

	pdata = dev->dev.platform_data;
	if (!pdata && dev->dev.of_node) {
		ret = st33zp24_spi_of_request_resources(dev);
		if (ret)
			return ret;
	} else if (pdata) {
		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->latency = st33zp24_spi_evaluate_latency(phy);
	if (phy->latency <= 0)
		return -ENODEV;

	return st33zp24_probe(phy, &spi_phy_ops, &dev->dev, dev->irq,
			      phy->io_lpcpd);
	return st33zp24_probe(phy, &spi_phy_ops, &dev->dev, dev->irq);
}

/*
@@ -411,7 +272,7 @@ static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,

static struct spi_driver st33zp24_spi_driver = {
	.driver = {
		.name = TPM_ST33_SPI,
		.name = "st33zp24-spi",
		.pm = &st33zp24_spi_ops,
		.of_match_table = of_match_ptr(of_st33zp24_spi_match),
		.acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
+33 −6
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 * Copyright (C) 2009 - 2016 STMicroelectronics
 */

#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
@@ -12,7 +13,7 @@
#include <linux/freezer.h>
#include <linux/string.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/io.h>
@@ -432,11 +433,18 @@ static const struct tpm_class_ops st33zp24_tpm = {
	.req_canceled = st33zp24_req_canceled,
};

static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };

static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
	{ "lpcpd-gpios", &lpcpd_gpios, 1 },
	{ },
};

/*
 * initialize the TPM device
 */
int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
		   struct device *dev, int irq, int io_lpcpd)
		   struct device *dev, int irq)
{
	int ret;
	u8 intmask = 0;
@@ -463,6 +471,25 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,

	tpm_dev->locality = LOCALITY0;

	if (ACPI_COMPANION(dev)) {
		ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
		if (ret)
			return ret;
	}

	/*
	 * Get LPCPD GPIO. If lpcpd pin is not specified. This is not an
	 * issue as power management can be also managed by TPM specific
	 * commands.
	 */
	tpm_dev->io_lpcpd = devm_gpiod_get_optional(dev, "lpcpd",
						    GPIOD_OUT_HIGH);
	ret = PTR_ERR_OR_ZERO(tpm_dev->io_lpcpd);
	if (ret) {
		dev_err(dev, "failed to request lpcpd gpio: %d\n", ret);
		return ret;
	}

	if (irq) {
		/* INTERRUPT Setup */
		init_waitqueue_head(&tpm_dev->read_queue);
@@ -525,8 +552,8 @@ int st33zp24_pm_suspend(struct device *dev)

	int ret = 0;

	if (gpio_is_valid(tpm_dev->io_lpcpd))
		gpio_set_value(tpm_dev->io_lpcpd, 0);
	if (tpm_dev->io_lpcpd)
		gpiod_set_value_cansleep(tpm_dev->io_lpcpd, 0);
	else
		ret = tpm_pm_suspend(dev);

@@ -540,8 +567,8 @@ int st33zp24_pm_resume(struct device *dev)
	struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
	int ret = 0;

	if (gpio_is_valid(tpm_dev->io_lpcpd)) {
		gpio_set_value(tpm_dev->io_lpcpd, 1);
	if (tpm_dev->io_lpcpd) {
		gpiod_set_value_cansleep(tpm_dev->io_lpcpd, 1);
		ret = wait_for_stat(chip,
				TPM_STS_VALID, chip->timeout_b,
				&tpm_dev->read_queue, false);
+5 −2
Original line number Diff line number Diff line
@@ -7,6 +7,9 @@
#ifndef __LOCAL_ST33ZP24_H__
#define __LOCAL_ST33ZP24_H__

#define TPM_ST33_I2C		"st33zp24-i2c"
#define TPM_ST33_SPI		"st33zp24-spi"

#define TPM_WRITE_DIRECTION	0x80
#define ST33ZP24_BUFSIZE	2048

@@ -17,7 +20,7 @@ struct st33zp24_dev {
	int locality;
	int irq;
	u32 intrs;
	int io_lpcpd;
	struct gpio_desc *io_lpcpd;
	wait_queue_head_t read_queue;
};

@@ -33,6 +36,6 @@ int st33zp24_pm_resume(struct device *dev);
#endif

int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
		   struct device *dev, int irq, int io_lpcpd);
		   struct device *dev, int irq);
void st33zp24_remove(struct tpm_chip *chip);
#endif /* __LOCAL_ST33ZP24_H__ */
Loading