From 448e9c55c12d6bd4fa90a7e31d802e045666d7c8 Mon Sep 17 00:00:00 2001 From: Scot Doyle Date: Wed, 24 Sep 2014 22:41:10 +0000 Subject: tpm_tis: verify interrupt during init Some machines, such as the Acer C720 and Toshiba CB35, have TPMs that do not send IRQs while also having an ACPI TPM entry indicating that they will be sent. These machines freeze on resume while the tpm_tis module waits for an IRQ, eventually timing out. When in interrupt mode, the tpm_tis module should receive an IRQ during module init. Fall back to polling mode if none is received when expected. Cc: Signed-off-by: Scot Doyle Tested-by: Michael Mullin Reviewed-by: Jason Gunthorpe [phuewe: minor checkpatch fixed] Signed-off-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 76 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 14 deletions(-) (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 6f1985496112..ccb140d60532 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -75,6 +75,10 @@ enum tis_defaults { #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) #define TPM_RID(l) (0x0F04 | ((l) << 12)) +struct priv_data { + bool irq_tested; +}; + static LIST_HEAD(tis_chips); static DEFINE_MUTEX(tis_lock); @@ -338,12 +342,27 @@ out_err: return rc; } +static void disable_interrupts(struct tpm_chip *chip) +{ + u32 intmask; + + intmask = + ioread32(chip->vendor.iobase + + TPM_INT_ENABLE(chip->vendor.locality)); + intmask &= ~TPM_GLOBAL_INT_ENABLE; + iowrite32(intmask, + chip->vendor.iobase + + TPM_INT_ENABLE(chip->vendor.locality)); + free_irq(chip->vendor.irq, chip); + chip->vendor.irq = 0; +} + /* * If interrupts are used (signaled by an irq set in the vendor structure) * tpm.c can skip polling for the data to be available as the interrupt is * waited for here */ -static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) +static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) { int rc; u32 ordinal; @@ -373,6 +392,30 @@ out_err: return rc; } +static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) +{ + int rc, irq; + struct priv_data *priv = chip->vendor.priv; + + if (!chip->vendor.irq || priv->irq_tested) + return tpm_tis_send_main(chip, buf, len); + + /* Verify receipt of the expected IRQ */ + irq = chip->vendor.irq; + chip->vendor.irq = 0; + rc = tpm_tis_send_main(chip, buf, len); + chip->vendor.irq = irq; + if (!priv->irq_tested) + msleep(1); + if (!priv->irq_tested) { + disable_interrupts(chip); + dev_err(chip->dev, + FW_BUG "TPM interrupt not working, polling instead\n"); + } + priv->irq_tested = true; + return rc; +} + struct tis_vendor_timeout_override { u32 did_vid; unsigned long timeout_us[4]; @@ -505,6 +548,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) if (interrupt == 0) return IRQ_NONE; + ((struct priv_data *)chip->vendor.priv)->irq_tested = true; if (interrupt & TPM_INTF_DATA_AVAIL_INT) wake_up_interruptible(&chip->vendor.read_queue); if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT) @@ -534,9 +578,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, u32 vendor, intfcaps, intmask; int rc, i, irq_s, irq_e, probe; struct tpm_chip *chip; + struct priv_data *priv; + priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; if (!(chip = tpm_register_hardware(dev, &tpm_tis))) return -ENODEV; + chip->vendor.priv = priv; chip->vendor.iobase = ioremap(start, len); if (!chip->vendor.iobase) { @@ -605,19 +654,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, if (intfcaps & TPM_INTF_DATA_AVAIL_INT) dev_dbg(dev, "\tData Avail Int Support\n"); - /* get the timeouts before testing for irqs */ - if (tpm_get_timeouts(chip)) { - dev_err(dev, "Could not get TPM timeouts and durations\n"); - rc = -ENODEV; - goto out_err; - } - - if (tpm_do_selftest(chip)) { - dev_err(dev, "TPM self test failed\n"); - rc = -ENODEV; - goto out_err; - } - /* INTERRUPT Setup */ init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); @@ -719,6 +755,18 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, } } + if (tpm_get_timeouts(chip)) { + dev_err(dev, "Could not get TPM timeouts and durations\n"); + rc = -ENODEV; + goto out_err; + } + + if (tpm_do_selftest(chip)) { + dev_err(dev, "TPM self test failed\n"); + rc = -ENODEV; + goto out_err; + } + INIT_LIST_HEAD(&chip->vendor.list); mutex_lock(&tis_lock); list_add(&chip->vendor.list, &tis_chips); -- cgit v1.2.3 From afb5abc262e962089ef2d7c2bbf71bb6f53a2a78 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 12 Dec 2014 11:46:34 -0800 Subject: tpm: two-phase chip management functions tpm_register_hardware() and tpm_remove_hardware() are called often before initializing the device. The problem is that the device might not be fully initialized when it comes visible to the user space. This patch resolves the issue by diving initialization into two parts: - tpmm_chip_alloc() creates struct tpm_chip. - tpm_chip_register() sets up the character device and sysfs attributes. The framework takes care of freeing struct tpm_chip by using the devres API. The broken release callback has been wiped. ACPI drivers do not ever get this callback. Regards to Jason Gunthorpe for carefully reviewing this part of the code. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jasob Gunthorpe Reviewed-by: Stefan Berger Tested-by: Scot Doyle Tested-by: Peter Huewe [phuewe: update to upstream changes] Signed-off-by: Peter Huewe --- drivers/char/tpm/Makefile | 2 +- drivers/char/tpm/tpm-chip.c | 199 ++++++++++++++++++++++++++++++++++++ drivers/char/tpm/tpm-interface.c | 148 +-------------------------- drivers/char/tpm/tpm.h | 16 ++- drivers/char/tpm/tpm_atmel.c | 11 +- drivers/char/tpm/tpm_i2c_atmel.c | 39 ++----- drivers/char/tpm/tpm_i2c_infineon.c | 37 ++----- drivers/char/tpm/tpm_i2c_nuvoton.c | 47 +++------ drivers/char/tpm/tpm_i2c_stm_st33.c | 14 +-- drivers/char/tpm/tpm_ibmvtpm.c | 17 ++- drivers/char/tpm/tpm_infineon.c | 29 +++--- drivers/char/tpm/tpm_nsc.c | 14 ++- drivers/char/tpm/tpm_tis.c | 80 ++++++--------- drivers/char/tpm/xen-tpmfront.c | 14 +-- 14 files changed, 329 insertions(+), 338 deletions(-) create mode 100644 drivers/char/tpm/tpm-chip.c (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 7f54dae847e4..c715596acb7c 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile @@ -2,7 +2,7 @@ # Makefile for the kernel tpm device drivers. # obj-$(CONFIG_TCG_TPM) += tpm.o -tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o +tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm-$(CONFIG_ACPI) += tpm_ppi.o ifdef CONFIG_ACPI diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c new file mode 100644 index 000000000000..7dc9999e2d54 --- /dev/null +++ b/drivers/char/tpm/tpm-chip.c @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2014 Intel Corporation + * + * Authors: + * Jarkko Sakkinen + * Leendert van Doorn + * Dave Safford + * Reiner Sailer + * Kylene Hall + * + * Maintained by: + * + * TPM chip management routines. + * + * 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 the Free Software Foundation, version 2 of the + * License. + * + */ + +#include +#include +#include +#include +#include +#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); + +/* + * tpm_chip_find_get - return tpm_chip for a given chip number + * @chip_num the device number for the chip + */ +struct tpm_chip *tpm_chip_find_get(int chip_num) +{ + struct tpm_chip *pos, *chip = NULL; + + 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; + + if (try_module_get(pos->dev->driver->owner)) { + chip = pos; + break; + } + } + rcu_read_unlock(); + return chip; +} + +/** + * tpmm_chip_remove() - free chip memory and device number + * @data: points to struct tpm_chip instance + * + * This is used internally by tpmm_chip_alloc() and called by devres + * when the device is released. This function does the opposite of + * tpmm_chip_alloc() freeing memory and the device number. + */ +static void tpmm_chip_remove(void *data) +{ + struct tpm_chip *chip = (struct tpm_chip *) data; + + spin_lock(&driver_lock); + clear_bit(chip->dev_num, dev_mask); + spin_unlock(&driver_lock); + kfree(chip); +} + +/** + * tpmm_chip_alloc() - allocate a new struct tpm_chip instance + * @dev: device to which the chip is associated + * @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. + */ +struct tpm_chip *tpmm_chip_alloc(struct device *dev, + const struct tpm_class_ops *ops) +{ + struct tpm_chip *chip; + + chip = kzalloc(sizeof(*chip), GFP_KERNEL); + if (chip == NULL) + return ERR_PTR(-ENOMEM); + + mutex_init(&chip->tpm_mutex); + INIT_LIST_HEAD(&chip->list); + + 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) { + dev_err(dev, "No available tpm device numbers\n"); + kfree(chip); + return ERR_PTR(-ENOMEM); + } + + set_bit(chip->dev_num, dev_mask); + + scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); + + chip->dev = dev; + devm_add_action(dev, tpmm_chip_remove, chip); + dev_set_drvdata(dev, chip); + + return chip; +} +EXPORT_SYMBOL_GPL(tpmm_chip_alloc); + +/* + * tpm_chip_register() - create a misc driver for the TPM chip + * @chip: TPM chip to use. + * + * Creates a misc driver for the TPM chip and adds sysfs interfaces for + * the device, PPI and TCPA. As the last step this function adds the + * chip to the list of TPM chips available for use. + * + * NOTE: This function should be only called after the chip initialization + * is complete. + * + * Called from tpm_.c probe function only for devices + * the driver has determined it should claim. Prior to calling + * this function the specific probe function has called pci_enable_device + * upon errant exit from this function specific probe function should call + * pci_disable_device + */ +int tpm_chip_register(struct tpm_chip *chip) +{ + int rc; + + rc = tpm_dev_add_device(chip); + if (rc) + return rc; + + rc = tpm_sysfs_add_device(chip); + if (rc) + goto del_misc; + + rc = tpm_add_ppi(&chip->dev->kobj); + if (rc) + goto del_sysfs; + + chip->bios_dir = tpm_bios_log_setup(chip->devname); + + /* Make the chip available. */ + spin_lock(&driver_lock); + list_add_rcu(&chip->list, &tpm_chip_list); + spin_unlock(&driver_lock); + + chip->flags |= TPM_CHIP_FLAG_REGISTERED; + + return 0; +del_sysfs: + tpm_sysfs_del_device(chip); +del_misc: + tpm_dev_del_device(chip); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_chip_register); + +/* + * tpm_chip_unregister() - release the TPM driver + * @chip: TPM chip to use. + * + * Takes the chip first away from the list of available TPM chips and then + * cleans up all the resources reserved by tpm_chip_register(). + * + * NOTE: This function should be only called before deinitializing chip + * resources. + */ +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->bios_dir) + tpm_bios_log_teardown(chip->bios_dir); + tpm_remove_ppi(&chip->dev->kobj); + tpm_sysfs_del_device(chip); + + tpm_dev_del_device(chip); +} +EXPORT_SYMBOL_GPL(tpm_chip_unregister); diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index c17aa45024aa..4dbed1e45abd 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2004 IBM Corporation + * Copyright (C) 2014 Intel Corporation * * Authors: * Leendert van Doorn @@ -47,10 +48,6 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644); MODULE_PARM_DESC(suspend_pcr, "PCR to use for dummy writes to faciltate flush on suspend."); -static LIST_HEAD(tpm_chip_list); -static DEFINE_SPINLOCK(driver_lock); -static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); - /* * Array with one entry per ordinal defining the maximum amount * of time the chip could take to return the result. The ordinal @@ -639,27 +636,6 @@ static int tpm_continue_selftest(struct tpm_chip *chip) return rc; } -/* - * tpm_chip_find_get - return tpm_chip for given chip number - */ -static struct tpm_chip *tpm_chip_find_get(int chip_num) -{ - struct tpm_chip *pos, *chip = NULL; - - 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; - - if (try_module_get(pos->dev->driver->owner)) { - chip = pos; - break; - } - } - rcu_read_unlock(); - return chip; -} - #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) #define READ_PCR_RESULT_SIZE 30 static struct tpm_input_header pcrread_header = { @@ -887,30 +863,6 @@ again: } EXPORT_SYMBOL_GPL(wait_for_tpm_stat); -void tpm_remove_hardware(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - - if (chip == NULL) { - dev_err(dev, "No device data found\n"); - return; - } - - spin_lock(&driver_lock); - list_del_rcu(&chip->list); - spin_unlock(&driver_lock); - synchronize_rcu(); - - tpm_dev_del_device(chip); - tpm_sysfs_del_device(chip); - tpm_remove_ppi(&dev->kobj); - tpm_bios_log_teardown(chip->bios_dir); - - /* write it this way to be explicit (chip->dev == dev) */ - put_device(chip->dev); -} -EXPORT_SYMBOL_GPL(tpm_remove_hardware); - #define TPM_ORD_SAVESTATE cpu_to_be32(152) #define SAVESTATE_RESULT_SIZE 10 @@ -1044,104 +996,6 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) } EXPORT_SYMBOL_GPL(tpm_get_random); -/* In case vendor provided release function, call it too.*/ - -void tpm_dev_vendor_release(struct tpm_chip *chip) -{ - if (!chip) - return; - - clear_bit(chip->dev_num, dev_mask); -} -EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); - - -/* - * Once all references to platform device are down to 0, - * release all allocated structures. - */ -static void tpm_dev_release(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - - if (!chip) - return; - - tpm_dev_vendor_release(chip); - - chip->release(dev); - kfree(chip); -} - -/* - * Called from tpm_.c probe function only for devices - * the driver has determined it should claim. Prior to calling - * this function the specific probe function has called pci_enable_device - * upon errant exit from this function specific probe function should call - * pci_disable_device - */ -struct tpm_chip *tpm_register_hardware(struct device *dev, - const struct tpm_class_ops *ops) -{ - struct tpm_chip *chip; - - /* Driver specific per-device data */ - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - - if (chip == NULL) - return NULL; - - mutex_init(&chip->tpm_mutex); - INIT_LIST_HEAD(&chip->list); - - chip->ops = ops; - chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES); - - if (chip->dev_num >= TPM_NUM_DEVICES) { - dev_err(dev, "No available tpm device numbers\n"); - goto out_free; - } - - set_bit(chip->dev_num, dev_mask); - - scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm", - chip->dev_num); - - chip->dev = get_device(dev); - chip->release = dev->release; - dev->release = tpm_dev_release; - dev_set_drvdata(dev, chip); - - if (tpm_dev_add_device(chip)) - goto put_device; - - if (tpm_sysfs_add_device(chip)) - goto del_misc; - - if (tpm_add_ppi(&dev->kobj)) - goto del_sysfs; - - chip->bios_dir = tpm_bios_log_setup(chip->devname); - - /* Make chip available */ - spin_lock(&driver_lock); - list_add_tail_rcu(&chip->list, &tpm_chip_list); - spin_unlock(&driver_lock); - - return chip; - -del_sysfs: - tpm_sysfs_del_device(chip); -del_misc: - tpm_dev_del_device(chip); -put_device: - put_device(chip->dev); -out_free: - kfree(chip); - return NULL; -} -EXPORT_SYMBOL_GPL(tpm_register_hardware); - MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); MODULE_DESCRIPTION("TPM Driver"); MODULE_VERSION("2.0"); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index e638eb016b90..72ff18c872d3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -94,9 +94,14 @@ struct tpm_vendor_specific { #define TPM_VID_WINBOND 0x1050 #define TPM_VID_STM 0x104A +enum tpm_chip_flags { + TPM_CHIP_FLAG_REGISTERED = BIT(0), +}; + struct tpm_chip { struct device *dev; /* Device stuff */ const struct tpm_class_ops *ops; + unsigned int flags; int dev_num; /* /dev/tpm# */ char devname[7]; @@ -110,7 +115,6 @@ struct tpm_chip { struct dentry **bios_dir; struct list_head list; - void (*release) (struct device *); }; #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor) @@ -322,15 +326,17 @@ extern int tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); extern int tpm_do_selftest(struct tpm_chip *); extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); -extern struct tpm_chip* tpm_register_hardware(struct device *, - const struct tpm_class_ops *ops); -extern void tpm_dev_vendor_release(struct tpm_chip *); -extern void tpm_remove_hardware(struct device *); extern int tpm_pm_suspend(struct device *); extern int tpm_pm_resume(struct device *); 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, + 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_dev_add_device(struct tpm_chip *chip); void tpm_dev_del_device(struct tpm_chip *chip); int tpm_sysfs_add_device(struct tpm_chip *chip); diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 435c8b9dd2f8..3d4c6c3b0433 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -138,11 +138,11 @@ static void atml_plat_remove(void) struct tpm_chip *chip = dev_get_drvdata(&pdev->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); - tpm_remove_hardware(chip->dev); platform_device_unregister(pdev); } } @@ -183,8 +183,9 @@ static int __init init_atmel(void) goto err_rel_reg; } - if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) { - rc = -ENODEV; + chip = tpmm_chip_alloc(&pdev->dev, &tpm_atmel); + if (IS_ERR(chip)) { + rc = PTR_ERR(chip); goto err_unreg_dev; } @@ -193,6 +194,10 @@ static int __init init_atmel(void) chip->vendor.have_region = have_region; chip->vendor.region_size = region_size; + rc = tpm_chip_register(chip); + if (rc) + goto err_unreg_dev; + return 0; err_unreg_dev: diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c index 5f448886417f..643a9402e911 100644 --- a/drivers/char/tpm/tpm_i2c_atmel.c +++ b/drivers/char/tpm/tpm_i2c_atmel.c @@ -153,25 +153,20 @@ static const struct tpm_class_ops i2c_atmel = { static int i2c_atmel_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int rc; struct tpm_chip *chip; struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - chip = tpm_register_hardware(dev, &i2c_atmel); - if (!chip) { - dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); - return -ENODEV; - } + chip = tpmm_chip_alloc(dev, &i2c_atmel); + if (IS_ERR(chip)) + return PTR_ERR(chip); chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); - if (!chip->vendor.priv) { - rc = -ENOMEM; - goto out_err; - } + if (!chip->vendor.priv) + return -ENOMEM; /* Default timeouts */ chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT); @@ -183,32 +178,20 @@ static int i2c_atmel_probe(struct i2c_client *client, /* 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)) { - rc = -ENODEV; - goto out_err; - } - - if (tpm_do_selftest(chip)) { - rc = -ENODEV; - goto out_err; - } + if (tpm_get_timeouts(chip)) + return -ENODEV; - return 0; + if (tpm_do_selftest(chip)) + return -ENODEV; -out_err: - tpm_dev_vendor_release(chip); - tpm_remove_hardware(chip->dev); - return rc; + return tpm_chip_register(chip); } static int i2c_atmel_remove(struct i2c_client *client) { struct device *dev = &(client->dev); struct tpm_chip *chip = dev_get_drvdata(dev); - - tpm_dev_vendor_release(chip); - tpm_remove_hardware(dev); - kfree(chip); + tpm_chip_unregister(chip); return 0; } diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 472af4bb1b61..03708e6b309a 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -581,12 +581,9 @@ static int tpm_tis_i2c_init(struct device *dev) int rc = 0; struct tpm_chip *chip; - chip = tpm_register_hardware(dev, &tpm_tis_i2c); - if (!chip) { - dev_err(dev, "could not register hardware\n"); - rc = -ENODEV; - goto out_err; - } + chip = tpmm_chip_alloc(dev, &tpm_tis_i2c); + if (IS_ERR(chip)) + return PTR_ERR(chip); /* Disable interrupts */ chip->vendor.irq = 0; @@ -600,7 +597,7 @@ static int tpm_tis_i2c_init(struct device *dev) if (request_locality(chip, 0) != 0) { dev_err(dev, "could not request locality\n"); rc = -ENODEV; - goto out_vendor; + goto out_err; } /* read four bytes from DID_VID register */ @@ -628,21 +625,9 @@ static int tpm_tis_i2c_init(struct device *dev) tpm_get_timeouts(chip); tpm_do_selftest(chip); - return 0; - + return tpm_chip_register(chip); out_release: release_locality(chip, chip->vendor.locality, 1); - -out_vendor: - /* close file handles */ - tpm_dev_vendor_release(chip); - - /* remove hardware */ - tpm_remove_hardware(chip->dev); - - /* reset these pointers, otherwise we oops */ - chip->dev->release = NULL; - chip->release = NULL; tpm_dev.client = NULL; out_err: return rc; @@ -712,17 +697,9 @@ static int tpm_tis_i2c_probe(struct i2c_client *client, static int tpm_tis_i2c_remove(struct i2c_client *client) { struct tpm_chip *chip = tpm_dev.chip; - release_locality(chip, chip->vendor.locality, 1); - /* close file handles */ - tpm_dev_vendor_release(chip); - - /* remove hardware */ - tpm_remove_hardware(chip->dev); - - /* reset these pointers, otherwise we oops */ - chip->dev->release = NULL; - chip->release = NULL; + tpm_chip_unregister(chip); + release_locality(chip, chip->vendor.locality, 1); tpm_dev.client = NULL; return 0; diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index bbb4997438c3..8c23088d99ef 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -530,18 +530,14 @@ static int i2c_nuvoton_probe(struct i2c_client *client, dev_info(dev, "VID: %04X DID: %02X RID: %02X\n", (u16) vid, (u8) (vid >> 16), (u8) (vid >> 24)); - chip = tpm_register_hardware(dev, &tpm_i2c); - if (!chip) { - dev_err(dev, "%s() error in tpm_register_hardware\n", __func__); - return -ENODEV; - } + chip = tpmm_chip_alloc(dev, &tpm_i2c); + if (IS_ERR(chip)) + return PTR_ERR(chip); chip->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); - if (!chip->vendor.priv) { - rc = -ENOMEM; - goto out_err; - } + if (!chip->vendor.priv) + return -ENOMEM; init_waitqueue_head(&chip->vendor.read_queue); init_waitqueue_head(&chip->vendor.int_queue); @@ -589,7 +585,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client, TPM_DATA_FIFO_W, 1, (u8 *) (&rc)); if (rc < 0) - goto out_err; + return rc; /* TPM_STS <- 0x40 (commandReady) */ i2c_nuvoton_ready(chip); } else { @@ -599,44 +595,29 @@ static int i2c_nuvoton_probe(struct i2c_client *client, * only TPM_STS_VALID should be set */ if (i2c_nuvoton_read_status(chip) != - TPM_STS_VALID) { - rc = -EIO; - goto out_err; - } + TPM_STS_VALID) + return -EIO; } } } - if (tpm_get_timeouts(chip)) { - rc = -ENODEV; - goto out_err; - } - - if (tpm_do_selftest(chip)) { - rc = -ENODEV; - goto out_err; - } + if (tpm_get_timeouts(chip)) + return -ENODEV; - return 0; + if (tpm_do_selftest(chip)) + return -ENODEV; -out_err: - tpm_dev_vendor_release(chip); - tpm_remove_hardware(chip->dev); - return rc; + 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); - - tpm_dev_vendor_release(chip); - tpm_remove_hardware(dev); - kfree(chip); + tpm_chip_unregister(chip); return 0; } - static const struct i2c_device_id i2c_nuvoton_id[] = { {I2C_DRIVER_NAME, 0}, {} diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c index 86203b022d13..9a96d3704fe5 100644 --- a/drivers/char/tpm/tpm_i2c_stm_st33.c +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c @@ -735,11 +735,9 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!tpm_dev) return -ENOMEM; - chip = tpm_register_hardware(&client->dev, &st_i2c_tpm); - if (!chip) { - dev_info(&client->dev, "fail chip\n"); - return -ENODEV; - } + chip = tpmm_chip_alloc(&client->dev, &st_i2c_tpm); + if (IS_ERR(chip)) + return PTR_ERR(chip); TPM_VPRIV(chip) = tpm_dev; tpm_dev->client = client; @@ -807,10 +805,8 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) tpm_get_timeouts(chip); tpm_do_selftest(chip); - dev_info(chip->dev, "TPM I2C Initialized\n"); - return 0; + return tpm_chip_register(chip); _tpm_clean_answer: - tpm_remove_hardware(chip->dev); dev_info(chip->dev, "TPM I2C initialisation fail\n"); return ret; } @@ -827,7 +823,7 @@ static int tpm_stm_i2c_remove(struct i2c_client *client) (struct tpm_chip *) i2c_get_clientdata(client); if (chip) - tpm_remove_hardware(chip->dev); + tpm_chip_unregister(chip); return 0; } diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c index 96f5d448b84c..0840347e251c 100644 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ b/drivers/char/tpm/tpm_ibmvtpm.c @@ -270,8 +270,11 @@ 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); int rc = 0; + tpm_chip_unregister(chip); + free_irq(vdev->irq, ibmvtpm); do { @@ -290,8 +293,6 @@ static int tpm_ibmvtpm_remove(struct vio_dev *vdev) kfree(ibmvtpm->rtce_buf); } - tpm_remove_hardware(ibmvtpm->dev); - kfree(ibmvtpm); return 0; @@ -563,11 +564,9 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, struct tpm_chip *chip; int rc = -ENOMEM, rc1; - chip = tpm_register_hardware(dev, &tpm_ibmvtpm); - if (!chip) { - dev_err(dev, "tpm_register_hardware failed\n"); - return -ENODEV; - } + chip = tpmm_chip_alloc(dev, &tpm_ibmvtpm); + if (IS_ERR(chip)) + return PTR_ERR(chip); ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL); if (!ibmvtpm) { @@ -637,7 +636,7 @@ static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, if (rc) goto init_irq_cleanup; - return rc; + return tpm_chip_register(chip); init_irq_cleanup: do { rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); @@ -652,8 +651,6 @@ cleanup: kfree(ibmvtpm); } - tpm_remove_hardware(dev); - return rc; } diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index dc0a2554034e..dcdb671b2a5d 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -546,7 +546,14 @@ static int tpm_inf_pnp_probe(struct pnp_dev *dev, vendorid[0], vendorid[1], productid[0], productid[1], chipname); - if (!(chip = tpm_register_hardware(&dev->dev, &tpm_inf))) + chip = tpmm_chip_alloc(&dev->dev, &tpm_inf); + if (IS_ERR(chip)) { + rc = PTR_ERR(chip); + goto err_release_region; + } + + rc = tpm_chip_register(chip); + if (rc) goto err_release_region; return 0; @@ -572,17 +579,15 @@ static void tpm_inf_pnp_remove(struct pnp_dev *dev) { struct tpm_chip *chip = pnp_get_drvdata(dev); - if (chip) { - if (tpm_dev.iotype == TPM_INF_IO_PORT) { - release_region(tpm_dev.data_regs, tpm_dev.data_size); - release_region(tpm_dev.config_port, - tpm_dev.config_size); - } else { - iounmap(tpm_dev.mem_base); - release_mem_region(tpm_dev.map_base, tpm_dev.map_size); - } - tpm_dev_vendor_release(chip); - tpm_remove_hardware(chip->dev); + tpm_chip_unregister(chip); + + if (tpm_dev.iotype == TPM_INF_IO_PORT) { + release_region(tpm_dev.data_regs, tpm_dev.data_size); + release_region(tpm_dev.config_port, + tpm_dev.config_size); + } else { + iounmap(tpm_dev.mem_base); + release_mem_region(tpm_dev.map_base, tpm_dev.map_size); } } diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 4d0a17ea8cde..6e2c2e64b292 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c @@ -247,10 +247,9 @@ static struct platform_device *pdev = NULL; static void tpm_nsc_remove(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - if ( chip ) { - release_region(chip->vendor.base, 2); - tpm_remove_hardware(chip->dev); - } + + tpm_chip_unregister(chip); + release_region(chip->vendor.base, 2); } static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume); @@ -307,11 +306,16 @@ static int __init init_nsc(void) goto err_del_dev; } - if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { + chip = tpmm_chip_alloc(&pdev->dev, &tpm_nsc); + if (IS_ERR(chip)) { rc = -ENODEV; goto err_rel_reg; } + rc = tpm_chip_register(chip); + if (rc) + goto err_rel_reg; + dev_dbg(&pdev->dev, "NSC TPM detected\n"); dev_dbg(&pdev->dev, "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index ccb140d60532..36f4fec11c2a 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -79,9 +79,6 @@ struct priv_data { bool irq_tested; }; -static LIST_HEAD(tis_chips); -static DEFINE_MUTEX(tis_lock); - #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) static int is_itpm(struct pnp_dev *dev) { @@ -572,6 +569,17 @@ static bool interrupts = true; module_param(interrupts, bool, 0444); MODULE_PARM_DESC(interrupts, "Enable interrupts"); +static void tpm_tis_remove(struct tpm_chip *chip) +{ + iowrite32(~TPM_GLOBAL_INT_ENABLE & + ioread32(chip->vendor.iobase + + TPM_INT_ENABLE(chip->vendor. + locality)), + chip->vendor.iobase + + TPM_INT_ENABLE(chip->vendor.locality)); + release_locality(chip, chip->vendor.locality, 1); +} + static int tpm_tis_init(struct device *dev, resource_size_t start, resource_size_t len, unsigned int irq) { @@ -583,15 +591,16 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); if (priv == NULL) return -ENOMEM; - if (!(chip = tpm_register_hardware(dev, &tpm_tis))) - return -ENODEV; + + chip = tpmm_chip_alloc(dev, &tpm_tis); + if (IS_ERR(chip)) + return PTR_ERR(chip); + chip->vendor.priv = priv; - chip->vendor.iobase = ioremap(start, len); - if (!chip->vendor.iobase) { - rc = -EIO; - goto out_err; - } + chip->vendor.iobase = devm_ioremap(dev, start, len); + if (!chip->vendor.iobase) + return -EIO; /* Default timeouts */ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); @@ -685,8 +694,8 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) { iowrite8(i, chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality)); - if (request_irq - (i, tis_int_probe, IRQF_SHARED, + if (devm_request_irq + (dev, i, tis_int_probe, IRQF_SHARED, chip->vendor.miscdev.name, chip) != 0) { dev_info(chip->dev, "Unable to request irq: %d for probe\n", @@ -726,15 +735,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, iowrite32(intmask, chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); - free_irq(i, chip); } } if (chip->vendor.irq) { iowrite8(chip->vendor.irq, chip->vendor.iobase + TPM_INT_VECTOR(chip->vendor.locality)); - if (request_irq - (chip->vendor.irq, tis_int_handler, IRQF_SHARED, + if (devm_request_irq + (dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED, chip->vendor.miscdev.name, chip) != 0) { dev_info(chip->dev, "Unable to request irq: %d for use\n", @@ -767,17 +775,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, goto out_err; } - INIT_LIST_HEAD(&chip->vendor.list); - mutex_lock(&tis_lock); - list_add(&chip->vendor.list, &tis_chips); - mutex_unlock(&tis_lock); - - - return 0; + return tpm_chip_register(chip); out_err: - if (chip->vendor.iobase) - iounmap(chip->vendor.iobase); - tpm_remove_hardware(chip->dev); + tpm_tis_remove(chip); return rc; } @@ -859,13 +859,10 @@ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); static void tpm_tis_pnp_remove(struct pnp_dev *dev) { struct tpm_chip *chip = pnp_get_drvdata(dev); - - tpm_dev_vendor_release(chip); - - kfree(chip); + tpm_chip_unregister(chip); + tpm_tis_remove(chip); } - static struct pnp_driver tis_pnp_driver = { .name = "tpm_tis", .id_table = tpm_pnp_tbl, @@ -884,7 +881,7 @@ MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); static struct platform_driver tis_drv = { .driver = { - .name = "tpm_tis", + .name = "tpm_tis", .pm = &tpm_tis_pm, }, }; @@ -923,31 +920,16 @@ err_dev: static void __exit cleanup_tis(void) { - struct tpm_vendor_specific *i, *j; struct tpm_chip *chip; - mutex_lock(&tis_lock); - list_for_each_entry_safe(i, j, &tis_chips, list) { - chip = to_tpm_chip(i); - tpm_remove_hardware(chip->dev); - iowrite32(~TPM_GLOBAL_INT_ENABLE & - ioread32(chip->vendor.iobase + - TPM_INT_ENABLE(chip->vendor. - locality)), - chip->vendor.iobase + - TPM_INT_ENABLE(chip->vendor.locality)); - release_locality(chip, chip->vendor.locality, 1); - if (chip->vendor.irq) - free_irq(chip->vendor.irq, chip); - iounmap(i->iobase); - list_del(&i->list); - } - mutex_unlock(&tis_lock); #ifdef CONFIG_PNP if (!force) { pnp_unregister_driver(&tis_pnp_driver); return; } #endif + chip = dev_get_drvdata(&pdev->dev); + tpm_chip_unregister(chip); + tpm_tis_remove(chip); platform_device_unregister(pdev); platform_driver_unregister(&tis_drv); } diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c index 441b44e54226..c3b4f5a5ac10 100644 --- a/drivers/char/tpm/xen-tpmfront.c +++ b/drivers/char/tpm/xen-tpmfront.c @@ -175,9 +175,9 @@ static int setup_chip(struct device *dev, struct tpm_private *priv) { struct tpm_chip *chip; - chip = tpm_register_hardware(dev, &tpm_vtpm); - if (!chip) - return -ENODEV; + chip = tpmm_chip_alloc(dev, &tpm_vtpm); + if (IS_ERR(chip)) + return PTR_ERR(chip); init_waitqueue_head(&chip->vendor.read_queue); @@ -286,6 +286,7 @@ static int tpmfront_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { struct tpm_private *priv; + struct tpm_chip *chip; int rv; priv = kzalloc(sizeof(*priv), GFP_KERNEL); @@ -302,21 +303,22 @@ static int tpmfront_probe(struct xenbus_device *dev, rv = setup_ring(dev, priv); if (rv) { - tpm_remove_hardware(&dev->dev); + chip = dev_get_drvdata(&dev->dev); + tpm_chip_unregister(chip); ring_free(priv); return rv; } tpm_get_timeouts(priv->chip); - return rv; + return tpm_chip_register(priv->chip); } static int tpmfront_remove(struct xenbus_device *dev) { struct tpm_chip *chip = dev_get_drvdata(&dev->dev); struct tpm_private *priv = TPM_VPRIV(chip); - tpm_remove_hardware(&dev->dev); + tpm_chip_unregister(chip); ring_free(priv); TPM_VPRIV(chip) = NULL; return 0; -- cgit v1.2.3 From 0dc553652102c55a43eb1ab52e2049e478469f53 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 12 Dec 2014 11:46:35 -0800 Subject: tpm: fix raciness of PPI interface lookup Traversal of the ACPI device tree was not done right. PPI interface should be looked up only from the ACPI device that is the platform device for the TPM. This could cause problems with systems with two TPM chips such as 4th gen Intel systems. In addition, added the missing license and copyright platter to the tpm_ppi.c. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jasob Gunthorpe Reviewed-by: Stefan Berger Tested-by: Scot Doyle Signed-off-by: Peter Huewe --- drivers/char/tpm/tpm-chip.c | 4 +- drivers/char/tpm/tpm.h | 17 ++++-- drivers/char/tpm/tpm_ppi.c | 141 +++++++++++++++++++++++++++----------------- drivers/char/tpm/tpm_tis.c | 14 +++-- 4 files changed, 112 insertions(+), 64 deletions(-) (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 7dc9999e2d54..64102de91ca3 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -147,7 +147,7 @@ int tpm_chip_register(struct tpm_chip *chip) if (rc) goto del_misc; - rc = tpm_add_ppi(&chip->dev->kobj); + rc = tpm_add_ppi(chip); if (rc) goto del_sysfs; @@ -191,7 +191,7 @@ void tpm_chip_unregister(struct tpm_chip *chip) if (chip->bios_dir) tpm_bios_log_teardown(chip->bios_dir); - tpm_remove_ppi(&chip->dev->kobj); + tpm_remove_ppi(chip); tpm_sysfs_del_device(chip); tpm_dev_del_device(chip); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 72ff18c872d3..3409acf953f3 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -27,6 +27,7 @@ #include #include #include +#include enum tpm_const { TPM_MINOR = 224, /* officially assigned */ @@ -94,8 +95,11 @@ struct tpm_vendor_specific { #define TPM_VID_WINBOND 0x1050 #define TPM_VID_STM 0x104A +#define TPM_PPI_VERSION_LEN 3 + enum tpm_chip_flags { TPM_CHIP_FLAG_REGISTERED = BIT(0), + TPM_CHIP_FLAG_PPI = BIT(1), }; struct tpm_chip { @@ -114,6 +118,11 @@ struct tpm_chip { struct dentry **bios_dir; +#ifdef CONFIG_ACPI + acpi_handle acpi_dev_handle; + char ppi_version[TPM_PPI_VERSION_LEN + 1]; +#endif /* CONFIG_ACPI */ + struct list_head list; }; @@ -345,15 +354,15 @@ void tpm_sysfs_del_device(struct tpm_chip *chip); int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); #ifdef CONFIG_ACPI -extern int tpm_add_ppi(struct kobject *); -extern void tpm_remove_ppi(struct kobject *); +extern int tpm_add_ppi(struct tpm_chip *chip); +extern void tpm_remove_ppi(struct tpm_chip *chip); #else -static inline int tpm_add_ppi(struct kobject *parent) +static inline int tpm_add_ppi(struct tpm_chip *chip) { return 0; } -static inline void tpm_remove_ppi(struct kobject *parent) +static inline void tpm_remove_ppi(struct tpm_chip *chip) { } #endif diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index 61dcc8011ec7..af48c56f642f 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c @@ -1,3 +1,22 @@ +/* + * Copyright (C) 2012-2014 Intel Corporation + * + * Authors: + * Xiaoyan Zhang + * Jiang Liu + * Jarkko Sakkinen + * + * Maintained by: + * + * This file contains implementation of the sysfs interface for PPI. + * + * 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 the Free Software Foundation; version 2 + * of the License. + */ + + #include #include "tpm.h" @@ -12,7 +31,6 @@ #define PPI_TPM_REQ_MAX 22 #define PPI_VS_REQ_START 128 #define PPI_VS_REQ_END 255 -#define PPI_VERSION_LEN 3 static const u8 tpm_ppi_uuid[] = { 0xA6, 0xFA, 0xDD, 0x3D, @@ -22,45 +40,22 @@ static const u8 tpm_ppi_uuid[] = { 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53 }; -static char tpm_ppi_version[PPI_VERSION_LEN + 1]; -static acpi_handle tpm_ppi_handle; - -static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context, - void **return_value) -{ - union acpi_object *obj; - - if (!acpi_check_dsm(handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, - 1 << TPM_PPI_FN_VERSION)) - return AE_OK; - - /* Cache version string */ - obj = acpi_evaluate_dsm_typed(handle, tpm_ppi_uuid, - TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION, - NULL, ACPI_TYPE_STRING); - if (obj) { - strlcpy(tpm_ppi_version, obj->string.pointer, - PPI_VERSION_LEN + 1); - ACPI_FREE(obj); - } - - *return_value = handle; - - return AE_CTRL_TERMINATE; -} - static inline union acpi_object * -tpm_eval_dsm(int func, acpi_object_type type, union acpi_object *argv4) +tpm_eval_dsm(acpi_handle ppi_handle, int func, acpi_object_type type, + union acpi_object *argv4) { - BUG_ON(!tpm_ppi_handle); - return acpi_evaluate_dsm_typed(tpm_ppi_handle, tpm_ppi_uuid, - TPM_PPI_REVISION_ID, func, argv4, type); + BUG_ON(!ppi_handle); + return acpi_evaluate_dsm_typed(ppi_handle, tpm_ppi_uuid, + TPM_PPI_REVISION_ID, + func, argv4, type); } static ssize_t tpm_show_ppi_version(struct device *dev, struct device_attribute *attr, char *buf) { - return scnprintf(buf, PAGE_SIZE, "%s\n", tpm_ppi_version); + struct tpm_chip *chip = dev_get_drvdata(dev); + + return scnprintf(buf, PAGE_SIZE, "%s\n", chip->ppi_version); } static ssize_t tpm_show_ppi_request(struct device *dev, @@ -68,8 +63,10 @@ static ssize_t tpm_show_ppi_request(struct device *dev, { ssize_t size = -EINVAL; union acpi_object *obj; + struct tpm_chip *chip = dev_get_drvdata(dev); - obj = tpm_eval_dsm(TPM_PPI_FN_GETREQ, ACPI_TYPE_PACKAGE, NULL); + obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETREQ, + ACPI_TYPE_PACKAGE, NULL); if (!obj) return -ENXIO; @@ -103,14 +100,15 @@ static ssize_t tpm_store_ppi_request(struct device *dev, int func = TPM_PPI_FN_SUBREQ; union acpi_object *obj, tmp; union acpi_object argv4 = ACPI_INIT_DSM_ARGV4(1, &tmp); + struct tpm_chip *chip = dev_get_drvdata(dev); /* * the function to submit TPM operation request to pre-os environment * is updated with function index from SUBREQ to SUBREQ2 since PPI * version 1.1 */ - if (acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, - 1 << TPM_PPI_FN_SUBREQ2)) + if (acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid, + TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_SUBREQ2)) func = TPM_PPI_FN_SUBREQ2; /* @@ -119,7 +117,7 @@ static ssize_t tpm_store_ppi_request(struct device *dev, * string/package type. For PPI version 1.0 and 1.1, use buffer type * for compatibility, and use package type since 1.2 according to spec. */ - if (strcmp(tpm_ppi_version, "1.2") < 0) { + if (strcmp(chip->ppi_version, "1.2") < 0) { if (sscanf(buf, "%d", &req) != 1) return -EINVAL; argv4.type = ACPI_TYPE_BUFFER; @@ -131,7 +129,8 @@ static ssize_t tpm_store_ppi_request(struct device *dev, return -EINVAL; } - obj = tpm_eval_dsm(func, ACPI_TYPE_INTEGER, &argv4); + obj = tpm_eval_dsm(chip->acpi_dev_handle, func, ACPI_TYPE_INTEGER, + &argv4); if (!obj) { return -ENXIO; } else { @@ -157,6 +156,7 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, .buffer.length = 0, .buffer.pointer = NULL }; + struct tpm_chip *chip = dev_get_drvdata(dev); static char *info[] = { "None", @@ -171,9 +171,10 @@ static ssize_t tpm_show_ppi_transition_action(struct device *dev, * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for * compatibility, define params[3].type as buffer, if PPI version < 1.2 */ - if (strcmp(tpm_ppi_version, "1.2") < 0) + if (strcmp(chip->ppi_version, "1.2") < 0) obj = &tmp; - obj = tpm_eval_dsm(TPM_PPI_FN_GETACT, ACPI_TYPE_INTEGER, obj); + obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETACT, + ACPI_TYPE_INTEGER, obj); if (!obj) { return -ENXIO; } else { @@ -196,8 +197,10 @@ static ssize_t tpm_show_ppi_response(struct device *dev, acpi_status status = -EINVAL; union acpi_object *obj, *ret_obj; u64 req, res; + struct tpm_chip *chip = dev_get_drvdata(dev); - obj = tpm_eval_dsm(TPM_PPI_FN_GETRSP, ACPI_TYPE_PACKAGE, NULL); + obj = tpm_eval_dsm(chip->acpi_dev_handle, TPM_PPI_FN_GETRSP, + ACPI_TYPE_PACKAGE, NULL); if (!obj) return -ENXIO; @@ -248,7 +251,8 @@ cleanup: return status; } -static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) +static ssize_t show_ppi_operations(acpi_handle dev_handle, char *buf, u32 start, + u32 end) { int i; u32 ret; @@ -264,14 +268,15 @@ static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) "User not required", }; - if (!acpi_check_dsm(tpm_ppi_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, + if (!acpi_check_dsm(dev_handle, tpm_ppi_uuid, TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_GETOPR)) return -EPERM; tmp.integer.type = ACPI_TYPE_INTEGER; for (i = start; i <= end; i++) { tmp.integer.value = i; - obj = tpm_eval_dsm(TPM_PPI_FN_GETOPR, ACPI_TYPE_INTEGER, &argv); + obj = tpm_eval_dsm(dev_handle, TPM_PPI_FN_GETOPR, + ACPI_TYPE_INTEGER, &argv); if (!obj) { return -ENOMEM; } else { @@ -291,14 +296,20 @@ static ssize_t tpm_show_ppi_tcg_operations(struct device *dev, struct device_attribute *attr, char *buf) { - return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX); + struct tpm_chip *chip = dev_get_drvdata(dev); + + return show_ppi_operations(chip->acpi_dev_handle, buf, 0, + PPI_TPM_REQ_MAX); } static ssize_t tpm_show_ppi_vs_operations(struct device *dev, struct device_attribute *attr, char *buf) { - return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END); + struct tpm_chip *chip = dev_get_drvdata(dev); + + return show_ppi_operations(chip->acpi_dev_handle, buf, PPI_VS_REQ_START, + PPI_VS_REQ_END); } static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL); @@ -323,16 +334,38 @@ static struct attribute_group ppi_attr_grp = { .attrs = ppi_attrs }; -int tpm_add_ppi(struct kobject *parent) +int tpm_add_ppi(struct tpm_chip *chip) { - /* Cache TPM ACPI handle and version string */ - acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, - ppi_callback, NULL, NULL, &tpm_ppi_handle); - return tpm_ppi_handle ? sysfs_create_group(parent, &ppi_attr_grp) : 0; + union acpi_object *obj; + int rc; + + if (!chip->acpi_dev_handle) + return 0; + + if (!acpi_check_dsm(chip->acpi_dev_handle, tpm_ppi_uuid, + TPM_PPI_REVISION_ID, 1 << TPM_PPI_FN_VERSION)) + return 0; + + /* Cache PPI version string. */ + obj = acpi_evaluate_dsm_typed(chip->acpi_dev_handle, tpm_ppi_uuid, + TPM_PPI_REVISION_ID, TPM_PPI_FN_VERSION, + NULL, ACPI_TYPE_STRING); + if (obj) { + strlcpy(chip->ppi_version, obj->string.pointer, + sizeof(chip->ppi_version)); + ACPI_FREE(obj); + } + + rc = sysfs_create_group(&chip->dev->kobj, &ppi_attr_grp); + + if (!rc) + chip->flags |= TPM_CHIP_FLAG_PPI; + + return rc; } -void tpm_remove_ppi(struct kobject *parent) +void tpm_remove_ppi(struct tpm_chip *chip) { - if (tpm_ppi_handle) - sysfs_remove_group(parent, &ppi_attr_grp); + if (chip->flags & TPM_CHIP_FLAG_PPI) + sysfs_remove_group(&chip->dev->kobj, &ppi_attr_grp); } diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 36f4fec11c2a..9695850d2afa 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -580,8 +580,9 @@ static void tpm_tis_remove(struct tpm_chip *chip) release_locality(chip, chip->vendor.locality, 1); } -static int tpm_tis_init(struct device *dev, resource_size_t start, - resource_size_t len, unsigned int irq) +static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, + resource_size_t start, resource_size_t len, + unsigned int irq) { u32 vendor, intfcaps, intmask; int rc, i, irq_s, irq_e, probe; @@ -597,6 +598,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, return PTR_ERR(chip); chip->vendor.priv = priv; + chip->acpi_dev_handle = acpi_dev_handle; chip->vendor.iobase = devm_ioremap(dev, start, len); if (!chip->vendor.iobase) @@ -827,6 +829,7 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, { resource_size_t start, len; unsigned int irq = 0; + acpi_handle acpi_dev_handle = NULL; start = pnp_mem_start(pnp_dev, 0); len = pnp_mem_len(pnp_dev, 0); @@ -839,7 +842,10 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, if (is_itpm(pnp_dev)) itpm = true; - return tpm_tis_init(&pnp_dev->dev, start, len, irq); + if (pnp_acpi_device(pnp_dev)) + acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; + + return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq); } static struct pnp_device_id tpm_pnp_tbl[] = { @@ -907,7 +913,7 @@ static int __init init_tis(void) rc = PTR_ERR(pdev); goto err_dev; } - rc = tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0); + rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0); if (rc) goto err_init; return 0; -- cgit v1.2.3 From 71ed848fd791bc0b53a1b7a04f29eb9e994c7cbb Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 12 Dec 2014 11:46:36 -0800 Subject: tpm: rename chip->dev to chip->pdev Rename chip->dev to chip->pdev to make it explicit that this not the character device but actually represents the platform device. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jasob Gunthorpe Reviewed-by: Stefan Berger Reviewed-by: Peter Huewe Tested-by: Scot Doyle Tested-by: Peter Huewe Signed-off-by: Peter Huewe --- drivers/char/tpm/tpm-chip.c | 4 ++-- drivers/char/tpm/tpm-dev.c | 10 +++++----- drivers/char/tpm/tpm-interface.c | 29 +++++++++++++++-------------- drivers/char/tpm/tpm-sysfs.c | 6 +++--- drivers/char/tpm/tpm.h | 4 ++-- drivers/char/tpm/tpm_atmel.c | 14 +++++++------- drivers/char/tpm/tpm_i2c_atmel.c | 16 ++++++++-------- drivers/char/tpm/tpm_i2c_infineon.c | 6 +++--- drivers/char/tpm/tpm_i2c_nuvoton.c | 22 +++++++++++----------- drivers/char/tpm/tpm_i2c_stm_st33.c | 18 +++++++++--------- drivers/char/tpm/tpm_infineon.c | 22 +++++++++++----------- drivers/char/tpm/tpm_nsc.c | 20 ++++++++++---------- drivers/char/tpm/tpm_ppi.c | 4 ++-- drivers/char/tpm/tpm_tis.c | 14 +++++++------- 14 files changed, 95 insertions(+), 94 deletions(-) (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 64102de91ca3..e72b042aa867 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -45,7 +45,7 @@ struct tpm_chip *tpm_chip_find_get(int chip_num) if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) continue; - if (try_module_get(pos->dev->driver->owner)) { + if (try_module_get(pos->pdev->driver->owner)) { chip = pos; break; } @@ -110,7 +110,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); - chip->dev = dev; + chip->pdev = dev; devm_add_action(dev, tpmm_chip_remove, chip); dev_set_drvdata(dev, chip); diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index d9b774e02a1f..356832146788 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c @@ -63,7 +63,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->dev, "Another process owns this TPM\n"); + dev_dbg(chip->pdev, "Another process owns this TPM\n"); return -EBUSY; } @@ -81,7 +81,7 @@ static int tpm_open(struct inode *inode, struct file *file) INIT_WORK(&priv->work, timeout_work); file->private_data = priv; - get_device(chip->dev); + get_device(chip->pdev); return 0; } @@ -168,7 +168,7 @@ 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->dev); + put_device(priv->chip->pdev); kfree(priv); return 0; } @@ -193,12 +193,12 @@ int tpm_dev_add_device(struct tpm_chip *chip) chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; chip->vendor.miscdev.name = chip->devname; - chip->vendor.miscdev.parent = chip->dev; + chip->vendor.miscdev.parent = chip->pdev; rc = misc_register(&chip->vendor.miscdev); if (rc) { chip->vendor.miscdev.name = NULL; - dev_err(chip->dev, + dev_err(chip->pdev, "unable to misc_register %s, minor %d err=%d\n", chip->vendor.miscdev.name, chip->vendor.miscdev.minor, rc); diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 4dbed1e45abd..e2af28fd63cb 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -343,7 +343,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, if (count == 0) return -ENODATA; if (count > bufsiz) { - dev_err(chip->dev, + dev_err(chip->pdev, "invalid count value %x %zx\n", count, bufsiz); return -E2BIG; } @@ -352,7 +352,7 @@ 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->dev, + dev_err(chip->pdev, "tpm_transmit: tpm_send: error %zd\n", rc); goto out; } @@ -368,7 +368,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->dev, "Operation Canceled\n"); + dev_err(chip->pdev, "Operation Canceled\n"); rc = -ECANCELED; goto out; } @@ -378,14 +378,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, } while (time_before(jiffies, stop)); chip->ops->cancel(chip); - dev_err(chip->dev, "Operation Timed out\n"); + dev_err(chip->pdev, "Operation Timed out\n"); rc = -ETIME; goto out; out_recv: rc = chip->ops->recv(chip, (u8 *) buf, bufsiz); if (rc < 0) - dev_err(chip->dev, + dev_err(chip->pdev, "tpm_transmit: tpm_recv: error %zd\n", rc); out: mutex_unlock(&chip->tpm_mutex); @@ -411,7 +411,8 @@ 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->dev, "A TPM error (%d) occurred %s\n", err, desc); + dev_err(chip->pdev, "A TPM error (%d) occurred %s\n", err, + desc); return err; } @@ -505,7 +506,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->dev, "Issuing TPM_STARTUP"); + dev_info(chip->pdev, "Issuing TPM_STARTUP"); if (tpm_startup(chip, TPM_ST_CLEAR)) return rc; @@ -517,7 +518,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) NULL); } if (rc) { - dev_err(chip->dev, + dev_err(chip->pdev, "A TPM error (%zd) occurred attempting to determine the timeouts\n", rc); goto duration; @@ -556,7 +557,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) /* Report adjusted timeouts */ if (chip->vendor.timeout_adjusted) { - dev_info(chip->dev, + dev_info(chip->pdev, 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], @@ -603,7 +604,7 @@ duration: chip->vendor.duration[TPM_MEDIUM] *= 1000; chip->vendor.duration[TPM_LONG] *= 1000; chip->vendor.duration_adjusted = true; - dev_info(chip->dev, "Adjusting TPM timeout parameters."); + dev_info(chip->pdev, "Adjusting TPM timeout parameters."); } return 0; } @@ -760,7 +761,7 @@ 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->dev, HW_ERR "TPM command timed out during continue self test"); + dev_info(chip->pdev, HW_ERR "TPM command timed out during continue self test"); msleep(delay_msec); continue; } @@ -770,7 +771,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->dev, + dev_info(chip->pdev, "TPM is disabled/deactivated (0x%X)\n", rc); /* TPM is disabled and/or deactivated; driver can * proceed and TPM does handle commands for @@ -918,10 +919,10 @@ int tpm_pm_suspend(struct device *dev) } if (rc) - dev_err(chip->dev, + dev_err(chip->pdev, "Error (%d) sending savestate before suspend\n", rc); else if (try > 0) - dev_warn(chip->dev, "TPM savestate took %dms\n", + dev_warn(chip->pdev, "TPM savestate took %dms\n", try * TPM_TIMEOUT_RETRY); return rc; diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 8ecb052e290d..ee66fd4673f3 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -284,16 +284,16 @@ static const struct attribute_group tpm_dev_group = { int tpm_sysfs_add_device(struct tpm_chip *chip) { int err; - err = sysfs_create_group(&chip->dev->kobj, + err = sysfs_create_group(&chip->pdev->kobj, &tpm_dev_group); if (err) - dev_err(chip->dev, + 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->dev->kobj, &tpm_dev_group); + sysfs_remove_group(&chip->pdev->kobj, &tpm_dev_group); } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 3409acf953f3..adf6af835329 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -103,7 +103,7 @@ enum tpm_chip_flags { }; struct tpm_chip { - struct device *dev; /* Device stuff */ + struct device *pdev; /* Device stuff */ const struct tpm_class_ops *ops; unsigned int flags; @@ -130,7 +130,7 @@ struct tpm_chip { static inline void tpm_chip_put(struct tpm_chip *chip) { - module_put(chip->dev->driver->owner); + module_put(chip->pdev->driver->owner); } static inline int tpm_read_index(int base, int index) diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 3d4c6c3b0433..dfadad0916a1 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -49,7 +49,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) for (i = 0; i < 6; i++) { status = ioread8(chip->vendor.iobase + 1); if ((status & ATML_STATUS_DATA_AVAIL) == 0) { - dev_err(chip->dev, "error reading header\n"); + dev_err(chip->pdev, "error reading header\n"); return -EIO; } *buf++ = ioread8(chip->vendor.iobase); @@ -60,12 +60,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->dev, + dev_err(chip->pdev, "Recv size(%d) less than available space\n", size); for (; i < size; i++) { /* clear the waiting data anyway */ status = ioread8(chip->vendor.iobase + 1); if ((status & ATML_STATUS_DATA_AVAIL) == 0) { - dev_err(chip->dev, "error reading data\n"); + dev_err(chip->pdev, "error reading data\n"); return -EIO; } } @@ -76,7 +76,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) for (; i < size; i++) { status = ioread8(chip->vendor.iobase + 1); if ((status & ATML_STATUS_DATA_AVAIL) == 0) { - dev_err(chip->dev, "error reading data\n"); + dev_err(chip->pdev, "error reading data\n"); return -EIO; } *buf++ = ioread8(chip->vendor.iobase); @@ -86,7 +86,7 @@ static int tpm_atml_recv(struct tpm_chip *chip, u8 *buf, size_t count) status = ioread8(chip->vendor.iobase + 1); if (status & ATML_STATUS_DATA_AVAIL) { - dev_err(chip->dev, "data available is stuck\n"); + dev_err(chip->pdev, "data available is stuck\n"); return -EIO; } @@ -97,9 +97,9 @@ static int tpm_atml_send(struct tpm_chip *chip, u8 *buf, size_t count) { int i; - dev_dbg(chip->dev, "tpm_atml_send:\n"); + dev_dbg(chip->pdev, "tpm_atml_send:\n"); for (i = 0; i < count; i++) { - dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); + dev_dbg(chip->pdev, "%d 0x%x(%d)\n", i, buf[i], buf[i]); iowrite8(buf[i], chip->vendor.iobase); } diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c index 643a9402e911..7a0ca78ad3c6 100644 --- a/drivers/char/tpm/tpm_i2c_atmel.c +++ b/drivers/char/tpm/tpm_i2c_atmel.c @@ -52,7 +52,7 @@ 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->dev); + struct i2c_client *client = to_i2c_client(chip->pdev); 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->dev, + dev_dbg(chip->pdev, "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__, (int)min_t(size_t, 64, len), buf, len, status); return status; @@ -71,7 +71,7 @@ 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->dev); + struct i2c_client *client = to_i2c_client(chip->pdev); 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->dev, + dev_dbg(chip->pdev, "%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->dev, + dev_dbg(chip->pdev, "%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->dev, "TPM operation cancellation was requested, but is not supported"); + dev_err(chip->pdev, "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->dev); + struct i2c_client *client = to_i2c_client(chip->pdev); 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->dev, + dev_dbg(chip->pdev, "%s: sts=%d", __func__, rc); if (rc <= 0) return 0; diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 03708e6b309a..33c5f360ab01 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -446,7 +446,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->dev, "Unable to read header\n"); + dev_err(chip->pdev, "Unable to read header\n"); goto out; } @@ -459,14 +459,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->dev, "Unable to read remainder of result\n"); + dev_err(chip->pdev, "Unable to read remainder of result\n"); size = -ETIME; goto out; } wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); if (status & TPM_STS_DATA_AVAIL) { /* retry? */ - dev_err(chip->dev, "Error left over data\n"); + dev_err(chip->pdev, "Error left over data\n"); size = -EIO; goto out; } diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index 8c23088d99ef..e1eadb0c1568 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -96,13 +96,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->dev); + struct i2c_client *client = to_i2c_client(chip->pdev); s32 status; u8 data; status = i2c_nuvoton_read_buf(client, TPM_STS, 1, &data); if (status <= 0) { - dev_err(chip->dev, "%s() error return %d\n", __func__, + dev_err(chip->pdev, "%s() error return %d\n", __func__, status); data = TPM_STS_ERR_VAL; } @@ -127,13 +127,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->dev); + struct i2c_client *client = to_i2c_client(chip->pdev); 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->dev, + dev_err(chip->pdev, "%s() fail to write TPM_STS.commandReady\n", __func__); } @@ -212,7 +212,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->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask, + dev_err(chip->pdev, "%s(%02x, %02x) -> timeout\n", __func__, mask, value); return -ETIMEDOUT; } @@ -240,7 +240,7 @@ static int i2c_nuvoton_recv_data(struct i2c_client *client, &chip->vendor.read_queue) == 0) { burst_count = i2c_nuvoton_get_burstcount(client, chip); if (burst_count < 0) { - dev_err(chip->dev, + dev_err(chip->pdev, "%s() fail to read burstCount=%d\n", __func__, burst_count); return -EIO; @@ -249,12 +249,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->dev, + dev_err(chip->pdev, "%s() fail on i2c_nuvoton_read_buf()=%d\n", __func__, rc); return -EIO; } - dev_dbg(chip->dev, "%s(%d):", __func__, bytes2read); + dev_dbg(chip->pdev, "%s(%d):", __func__, bytes2read); size += bytes2read; } @@ -264,7 +264,7 @@ 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->dev; + struct device *dev = chip->pdev; struct i2c_client *client = to_i2c_client(dev); s32 rc; int expected, status, burst_count, retries, size = 0; @@ -334,7 +334,7 @@ static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count) break; } i2c_nuvoton_ready(chip); - dev_dbg(chip->dev, "%s() -> %d\n", __func__, size); + dev_dbg(chip->pdev, "%s() -> %d\n", __func__, size); return size; } @@ -347,7 +347,7 @@ 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->dev; + struct device *dev = chip->pdev; struct i2c_client *client = to_i2c_client(dev); u32 ordinal; size_t count = 0; diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c index 9a96d3704fe5..48c4808d5a7a 100644 --- a/drivers/char/tpm/tpm_i2c_stm_st33.c +++ b/drivers/char/tpm/tpm_i2c_stm_st33.c @@ -588,7 +588,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, size = recv_data(chip, buf, TPM_HEADER_SIZE); if (size < TPM_HEADER_SIZE) { - dev_err(chip->dev, "Unable to read header\n"); + dev_err(chip->pdev, "Unable to read header\n"); goto out; } @@ -601,7 +601,7 @@ static int tpm_stm_i2c_recv(struct tpm_chip *chip, unsigned char *buf, size += recv_data(chip, &buf[TPM_HEADER_SIZE], expected - TPM_HEADER_SIZE); if (size < expected) { - dev_err(chip->dev, "Unable to read remainder of result\n"); + dev_err(chip->pdev, "Unable to read remainder of result\n"); size = -ETIME; goto out; } @@ -639,14 +639,14 @@ static int tpm_stm_i2c_of_request_resources(struct tpm_chip *chip) pp = client->dev.of_node; if (!pp) { - dev_err(chip->dev, "No platform data\n"); + dev_err(chip->pdev, "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(chip->dev, "Failed to retrieve lpcpd-gpios from dts.\n"); + dev_err(chip->pdev, "Failed to retrieve lpcpd-gpios from dts.\n"); tpm_dev->io_lpcpd = -1; /* * lpcpd pin is not specified. This is not an issue as @@ -659,7 +659,7 @@ static int tpm_stm_i2c_of_request_resources(struct tpm_chip *chip) ret = devm_gpio_request_one(&client->dev, gpio, GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD"); if (ret) { - dev_err(chip->dev, "Failed to request lpcpd pin\n"); + dev_err(chip->pdev, "Failed to request lpcpd pin\n"); return -ENODEV; } tpm_dev->io_lpcpd = gpio; @@ -682,7 +682,7 @@ static int tpm_stm_i2c_request_resources(struct i2c_client *client, pdata = client->dev.platform_data; if (!pdata) { - dev_err(chip->dev, "No platform data\n"); + dev_err(chip->pdev, "No platform data\n"); return -ENODEV; } @@ -694,7 +694,7 @@ static int tpm_stm_i2c_request_resources(struct i2c_client *client, pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH, "TPM IO_LPCPD"); if (ret) { - dev_err(chip->dev, "%s : reset gpio_request failed\n", + dev_err(chip->pdev, "%s : reset gpio_request failed\n", __FILE__); return ret; } @@ -776,7 +776,7 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) IRQF_TRIGGER_HIGH, "TPM SERIRQ management", chip); if (ret < 0) { - dev_err(chip->dev , "TPM SERIRQ signals %d not available\n", + dev_err(chip->pdev , "TPM SERIRQ signals %d not available\n", client->irq); goto _tpm_clean_answer; } @@ -807,7 +807,7 @@ tpm_stm_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) return tpm_chip_register(chip); _tpm_clean_answer: - dev_info(chip->dev, "TPM I2C initialisation fail\n"); + dev_info(chip->pdev, "TPM I2C initialisation fail\n"); return ret; } diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index dcdb671b2a5d..6d492132ad2b 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c @@ -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->dev, "Timeout in wait(STAT_XFE)\n"); + dev_err(chip->pdev, "Timeout in wait(STAT_XFE)\n"); if (wait_for_bit == STAT_RDA) - dev_err(chip->dev, "Timeout in wait(STAT_RDA)\n"); + dev_err(chip->pdev, "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->dev, "Granting WTX (%02d / %02d)\n", + dev_info(chip->pdev, "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->dev, "Aborting WTX\n"); + dev_info(chip->pdev, "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 @@ recv_begin: } if (buf[0] != TPM_VL_VER) { - dev_err(chip->dev, + dev_err(chip->pdev, "Wrong transport protocol implementation!\n"); return -EIO; } @@ -272,7 +272,7 @@ recv_begin: } if ((size == 0x6D00) && (buf[1] == 0x80)) { - dev_err(chip->dev, "Error handling on vendor layer!\n"); + dev_err(chip->pdev, "Error handling on vendor layer!\n"); return -EIO; } @@ -284,7 +284,7 @@ recv_begin: } if (buf[1] == TPM_CTRL_WTX) { - dev_info(chip->dev, "WTX-package received\n"); + dev_info(chip->pdev, "WTX-package received\n"); if (number_of_wtx < TPM_MAX_WTX_PACKAGES) { tpm_wtx(chip); goto recv_begin; @@ -295,14 +295,14 @@ recv_begin: } if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) { - dev_info(chip->dev, "WTX-abort acknowledged\n"); + dev_info(chip->pdev, "WTX-abort acknowledged\n"); return size; } if (buf[1] == TPM_CTRL_ERROR) { - dev_err(chip->dev, "ERROR-package received:\n"); + dev_err(chip->pdev, "ERROR-package received:\n"); if (buf[4] == TPM_INF_NAK) - dev_err(chip->dev, + dev_err(chip->pdev, "-> 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->dev, "Timeout while clearing FIFO\n"); + dev_err(chip->pdev, "Timeout while clearing FIFO\n"); return -EIO; } diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 6e2c2e64b292..289389ecef84 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c @@ -113,7 +113,7 @@ static int nsc_wait_for_ready(struct tpm_chip *chip) } while (time_before(jiffies, stop)); - dev_info(chip->dev, "wait for ready failed\n"); + dev_info(chip->pdev, "wait for ready failed\n"); return -EBUSY; } @@ -129,12 +129,12 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) return -EIO; if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) { - dev_err(chip->dev, "F0 timeout\n"); + dev_err(chip->pdev, "F0 timeout\n"); return -EIO; } if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) { - dev_err(chip->dev, "not in normal mode (0x%x)\n", + dev_err(chip->pdev, "not in normal mode (0x%x)\n", data); return -EIO; } @@ -143,7 +143,7 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) for (p = buffer; p < &buffer[count]; p++) { if (wait_for_stat (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) { - dev_err(chip->dev, + dev_err(chip->pdev, "OBF timeout (while reading data)\n"); return -EIO; } @@ -154,11 +154,11 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count) if ((data & NSC_STATUS_F0) == 0 && (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) { - dev_err(chip->dev, "F0 not set\n"); + dev_err(chip->pdev, "F0 not set\n"); return -EIO; } if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) { - dev_err(chip->dev, + dev_err(chip->pdev, "expected end of command(0x%x)\n", data); return -EIO; } @@ -189,19 +189,19 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) return -EIO; if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(chip->dev, "IBF timeout\n"); + dev_err(chip->pdev, "IBF timeout\n"); return -EIO; } outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND); if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) { - dev_err(chip->dev, "IBR timeout\n"); + dev_err(chip->pdev, "IBR timeout\n"); return -EIO; } for (i = 0; i < count; i++) { if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(chip->dev, + dev_err(chip->pdev, "IBF timeout (while writing data)\n"); return -EIO; } @@ -209,7 +209,7 @@ static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count) } if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) { - dev_err(chip->dev, "IBF timeout\n"); + dev_err(chip->pdev, "IBF timeout\n"); return -EIO; } outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND); diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c index af48c56f642f..6ca9b5d78144 100644 --- a/drivers/char/tpm/tpm_ppi.c +++ b/drivers/char/tpm/tpm_ppi.c @@ -356,7 +356,7 @@ int tpm_add_ppi(struct tpm_chip *chip) ACPI_FREE(obj); } - rc = sysfs_create_group(&chip->dev->kobj, &ppi_attr_grp); + rc = sysfs_create_group(&chip->pdev->kobj, &ppi_attr_grp); if (!rc) chip->flags |= TPM_CHIP_FLAG_PPI; @@ -367,5 +367,5 @@ int tpm_add_ppi(struct tpm_chip *chip) void tpm_remove_ppi(struct tpm_chip *chip) { if (chip->flags & TPM_CHIP_FLAG_PPI) - sysfs_remove_group(&chip->dev->kobj, &ppi_attr_grp); + sysfs_remove_group(&chip->pdev->kobj, &ppi_attr_grp); } diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 9695850d2afa..9e02489a94f3 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -242,7 +242,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) /* read first 10 bytes, including tag, paramsize, and result */ if ((size = recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) { - dev_err(chip->dev, "Unable to read header\n"); + dev_err(chip->pdev, "Unable to read header\n"); goto out; } @@ -255,7 +255,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) if ((size += recv_data(chip, &buf[TPM_HEADER_SIZE], expected - TPM_HEADER_SIZE)) < expected) { - dev_err(chip->dev, "Unable to read remainder of result\n"); + dev_err(chip->pdev, "Unable to read remainder of result\n"); size = -ETIME; goto out; } @@ -264,7 +264,7 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) &chip->vendor.int_queue, false); status = tpm_tis_status(chip); if (status & TPM_STS_DATA_AVAIL) { /* retry? */ - dev_err(chip->dev, "Error left over data\n"); + dev_err(chip->pdev, "Error left over data\n"); size = -EIO; goto out; } @@ -406,7 +406,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) msleep(1); if (!priv->irq_tested) { disable_interrupts(chip); - dev_err(chip->dev, + dev_err(chip->pdev, FW_BUG "TPM interrupt not working, polling instead\n"); } priv->irq_tested = true; @@ -476,7 +476,7 @@ static int probe_itpm(struct tpm_chip *chip) rc = tpm_tis_send_data(chip, cmd_getticks, len); if (rc == 0) { - dev_info(chip->dev, "Detected an iTPM.\n"); + dev_info(chip->pdev, "Detected an iTPM.\n"); rc = 1; } else rc = -EFAULT; @@ -699,7 +699,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, if (devm_request_irq (dev, i, tis_int_probe, IRQF_SHARED, chip->vendor.miscdev.name, chip) != 0) { - dev_info(chip->dev, + dev_info(chip->pdev, "Unable to request irq: %d for probe\n", i); continue; @@ -746,7 +746,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, if (devm_request_irq (dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED, chip->vendor.miscdev.name, chip) != 0) { - dev_info(chip->dev, + dev_info(chip->pdev, "Unable to request irq: %d for use\n", chip->vendor.irq); chip->vendor.irq = 0; -- cgit v1.2.3 From 313d21eeab9282e01fdcecd40e9ca87e0953627f Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 12 Dec 2014 11:46:37 -0800 Subject: tpm: device class for tpm Added own device class for TPM. Uses MISC_MAJOR:TPM_MINOR for the first character device in order to retain backwards compatibility. Added tpm_dev_release() back attached to the character device. I've been running this code now for a while on my laptop (Lenovo T430S) TrouSerS works perfectly without modifications. I don't believe it breaks anything significantly. The sysfs attributes that have been placed under the wrong place and are against sysfs-rules.txt should be probably left to stagnate under platform device directory and start defining new sysfs attributes to the char device directory. Guidelines for future TPM sysfs attributes should be probably along the lines of - Single flat set of mandatory sysfs attributes. For example, current PPI interface is way way too rich when you only want to use it to clear and activate the TPM. - Define sysfs attribute if and only if there's no way to get the value from ring-3. No attributes for TPM properties. It's just unnecessary maintenance hurdle that we don't want. Signed-off-by: Jarkko Sakkinen Reviewed-by: Jasob Gunthorpe Reviewed-by: Stefan Berger Tested-by: Scot Doyle Tested-by: Peter Huewe Signed-off-by: Peter Huewe --- Documentation/ABI/stable/sysfs-class-tpm | 22 +++++----- drivers/char/tpm/tpm-chip.c | 72 +++++++++++++++++++++++++++----- drivers/char/tpm/tpm-dev.c | 36 ++-------------- drivers/char/tpm/tpm-interface.c | 29 +++++++++++++ drivers/char/tpm/tpm.h | 12 ++++-- drivers/char/tpm/tpm_i2c_nuvoton.c | 2 +- drivers/char/tpm/tpm_tis.c | 4 +- 7 files changed, 116 insertions(+), 61 deletions(-) (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/Documentation/ABI/stable/sysfs-class-tpm b/Documentation/ABI/stable/sysfs-class-tpm index a60b45e2493b..9f790eebb5d2 100644 --- a/Documentation/ABI/stable/sysfs-class-tpm +++ b/Documentation/ABI/stable/sysfs-class-tpm @@ -1,4 +1,4 @@ -What: /sys/class/misc/tpmX/device/ +What: /sys/class/tpm/tpmX/device/ Date: April 2005 KernelVersion: 2.6.12 Contact: tpmdd-devel@lists.sf.net @@ -6,7 +6,7 @@ Description: The device/ directory under a specific TPM instance exposes the properties of that TPM chip -What: /sys/class/misc/tpmX/device/active +What: /sys/class/tpm/tpmX/device/active Date: April 2006 KernelVersion: 2.6.17 Contact: tpmdd-devel@lists.sf.net @@ -18,7 +18,7 @@ Description: The "active" property prints a '1' if the TPM chip is accepting section 17 for more information on which commands are available. -What: /sys/class/misc/tpmX/device/cancel +What: /sys/class/tpm/tpmX/device/cancel Date: June 2005 KernelVersion: 2.6.13 Contact: tpmdd-devel@lists.sf.net @@ -26,7 +26,7 @@ Description: The "cancel" property allows you to cancel the currently pending TPM command. Writing any value to cancel will call the TPM vendor specific cancel operation. -What: /sys/class/misc/tpmX/device/caps +What: /sys/class/tpm/tpmX/device/caps Date: April 2005 KernelVersion: 2.6.12 Contact: tpmdd-devel@lists.sf.net @@ -43,7 +43,7 @@ Description: The "caps" property contains TPM manufacturer and version info. the chip supports. Firmware version is that of the chip and is manufacturer specific. -What: /sys/class/misc/tpmX/device/durations +What: /sys/class/tpm/tpmX/device/durations Date: March 2011 KernelVersion: 3.1 Contact: tpmdd-devel@lists.sf.net @@ -66,7 +66,7 @@ Description: The "durations" property shows the 3 vendor-specific values scaled to be displayed in usecs. In this case "[adjusted]" will be displayed in place of "[original]". -What: /sys/class/misc/tpmX/device/enabled +What: /sys/class/tpm/tpmX/device/enabled Date: April 2006 KernelVersion: 2.6.17 Contact: tpmdd-devel@lists.sf.net @@ -75,7 +75,7 @@ Description: The "enabled" property prints a '1' if the TPM chip is enabled, may be visible but produce a '0' after some operation that disables the TPM. -What: /sys/class/misc/tpmX/device/owned +What: /sys/class/tpm/tpmX/device/owned Date: April 2006 KernelVersion: 2.6.17 Contact: tpmdd-devel@lists.sf.net @@ -83,7 +83,7 @@ Description: The "owned" property produces a '1' if the TPM_TakeOwnership ordinal has been executed successfully in the chip. A '0' indicates that ownership hasn't been taken. -What: /sys/class/misc/tpmX/device/pcrs +What: /sys/class/tpm/tpmX/device/pcrs Date: April 2005 KernelVersion: 2.6.12 Contact: tpmdd-devel@lists.sf.net @@ -106,7 +106,7 @@ Description: The "pcrs" property will dump the current value of all Platform 1.2 chips, PCRs represent SHA-1 hashes, which are 20 bytes long. Use the "caps" property to determine TPM version. -What: /sys/class/misc/tpmX/device/pubek +What: /sys/class/tpm/tpmX/device/pubek Date: April 2005 KernelVersion: 2.6.12 Contact: tpmdd-devel@lists.sf.net @@ -158,7 +158,7 @@ Description: The "pubek" property will return the TPM's public endorsement Modulus Length: 256 (bytes) Modulus: The 256 byte Endorsement Key modulus -What: /sys/class/misc/tpmX/device/temp_deactivated +What: /sys/class/tpm/tpmX/device/temp_deactivated Date: April 2006 KernelVersion: 2.6.17 Contact: tpmdd-devel@lists.sf.net @@ -167,7 +167,7 @@ Description: The "temp_deactivated" property returns a '1' if the chip has cycle. Whether a warm boot (reboot) will clear a TPM chip from a temp_deactivated state is platform specific. -What: /sys/class/misc/tpmX/device/timeouts +What: /sys/class/tpm/tpmX/device/timeouts Date: March 2011 KernelVersion: 3.1 Contact: tpmdd-devel@lists.sf.net diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index e72b042aa867..7596eef3bff9 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "tpm.h" #include "tpm_eventlog.h" @@ -32,6 +33,9 @@ static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES); static LIST_HEAD(tpm_chip_list); static DEFINE_SPINLOCK(driver_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 @@ -55,16 +59,14 @@ struct tpm_chip *tpm_chip_find_get(int chip_num) } /** - * tpmm_chip_remove() - free chip memory and device number - * @data: points to struct tpm_chip instance + * tpm_dev_release() - free chip memory and the device number + * @dev: the character device for the TPM chip * - * This is used internally by tpmm_chip_alloc() and called by devres - * when the device is released. This function does the opposite of - * tpmm_chip_alloc() freeing memory and the device number. + * This is used as the release function for the character device. */ -static void tpmm_chip_remove(void *data) +static void tpm_dev_release(struct device *dev) { - struct tpm_chip *chip = (struct tpm_chip *) data; + struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev); spin_lock(&driver_lock); clear_bit(chip->dev_num, dev_mask); @@ -111,18 +113,68 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev, scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num); chip->pdev = dev; - devm_add_action(dev, tpmm_chip_remove, chip); + dev_set_drvdata(dev, chip); + chip->dev.class = tpm_class; + chip->dev.release = tpm_dev_release; + chip->dev.parent = chip->pdev; + + 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, chip->devname); + + device_initialize(&chip->dev); + + chip->cdev.owner = chip->pdev->driver->owner; + cdev_init(&chip->cdev, &tpm_fops); + return chip; } EXPORT_SYMBOL_GPL(tpmm_chip_alloc); +static int tpm_dev_add_device(struct tpm_chip *chip) +{ + int rc; + + rc = device_add(&chip->dev); + if (rc) { + dev_err(&chip->dev, + "unable to device_register() %s, major %d, minor %d, err=%d\n", + chip->devname, MAJOR(chip->dev.devt), + MINOR(chip->dev.devt), rc); + + return rc; + } + + rc = cdev_add(&chip->cdev, chip->dev.devt, 1); + if (rc) { + dev_err(&chip->dev, + "unable to cdev_add() %s, major %d, minor %d, err=%d\n", + chip->devname, MAJOR(chip->dev.devt), + MINOR(chip->dev.devt), rc); + + device_unregister(&chip->dev); + return rc; + } + + return rc; +} + +static void tpm_dev_del_device(struct tpm_chip *chip) +{ + cdev_del(&chip->cdev); + device_unregister(&chip->dev); +} + /* - * tpm_chip_register() - create a misc driver for the TPM chip + * tpm_chip_register() - create a character device for the TPM chip * @chip: TPM chip to use. * - * Creates a misc driver for the TPM chip and adds sysfs interfaces for + * Creates a character device for the TPM chip and adds sysfs interfaces for * the device, PPI and TCPA. As the last step this function adds the * chip to the list of TPM chips available for use. * diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index 356832146788..de0337ebd658 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c @@ -17,7 +17,6 @@ * License. * */ -#include #include #include #include "tpm.h" @@ -54,9 +53,8 @@ static void timeout_work(struct work_struct *work) static int tpm_open(struct inode *inode, struct file *file) { - struct miscdevice *misc = file->private_data; - struct tpm_chip *chip = container_of(misc, struct tpm_chip, - vendor.miscdev); + struct tpm_chip *chip = + container_of(inode->i_cdev, struct tpm_chip, cdev); struct file_priv *priv; /* It's assured that the chip will be opened just once, @@ -173,7 +171,7 @@ static int tpm_release(struct inode *inode, struct file *file) return 0; } -static const struct file_operations tpm_fops = { +const struct file_operations tpm_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .open = tpm_open, @@ -182,32 +180,4 @@ static const struct file_operations tpm_fops = { .release = tpm_release, }; -int tpm_dev_add_device(struct tpm_chip *chip) -{ - int rc; - chip->vendor.miscdev.fops = &tpm_fops; - if (chip->dev_num == 0) - chip->vendor.miscdev.minor = TPM_MINOR; - else - chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR; - - chip->vendor.miscdev.name = chip->devname; - chip->vendor.miscdev.parent = chip->pdev; - - rc = misc_register(&chip->vendor.miscdev); - if (rc) { - chip->vendor.miscdev.name = NULL; - dev_err(chip->pdev, - "unable to misc_register %s, minor %d err=%d\n", - chip->vendor.miscdev.name, - chip->vendor.miscdev.minor, rc); - } - return rc; -} - -void tpm_dev_del_device(struct tpm_chip *chip) -{ - if (chip->vendor.miscdev.name) - misc_deregister(&chip->vendor.miscdev); -} diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index e2af28fd63cb..b6f6b17392fd 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -997,6 +997,35 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) } EXPORT_SYMBOL_GPL(tpm_get_random); +static int __init tpm_init(void) +{ + int rc; + + tpm_class = class_create(THIS_MODULE, "tpm"); + if (IS_ERR(tpm_class)) { + pr_err("couldn't create tpm class\n"); + return PTR_ERR(tpm_class); + } + + rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm"); + if (rc < 0) { + pr_err("tpm: failed to allocate char dev region\n"); + class_destroy(tpm_class); + return rc; + } + + return 0; +} + +static void __exit tpm_exit(void) +{ + class_destroy(tpm_class); + unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES); +} + +subsys_initcall(tpm_init); +module_exit(tpm_exit); + MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); MODULE_DESCRIPTION("TPM Driver"); MODULE_VERSION("2.0"); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index adf6af835329..d46765b4c97e 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -23,11 +23,11 @@ #include #include #include -#include #include #include #include #include +#include enum tpm_const { TPM_MINOR = 224, /* officially assigned */ @@ -74,7 +74,6 @@ struct tpm_vendor_specific { int region_size; int have_region; - struct miscdevice miscdev; struct list_head list; int locality; unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ @@ -104,6 +103,9 @@ enum tpm_chip_flags { struct tpm_chip { struct device *pdev; /* Device stuff */ + struct device dev; + struct cdev cdev; + const struct tpm_class_ops *ops; unsigned int flags; @@ -326,6 +328,10 @@ struct tpm_cmd_t { tpm_cmd_params params; } __packed; +extern struct class *tpm_class; +extern dev_t tpm_devt; +extern const struct file_operations tpm_fops; + ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, size_t bufsiz); @@ -346,8 +352,6 @@ extern struct tpm_chip *tpmm_chip_alloc(struct device *dev, extern int tpm_chip_register(struct tpm_chip *chip); extern void tpm_chip_unregister(struct tpm_chip *chip); -int tpm_dev_add_device(struct tpm_chip *chip); -void tpm_dev_del_device(struct tpm_chip *chip); int tpm_sysfs_add_device(struct tpm_chip *chip); void tpm_sysfs_del_device(struct tpm_chip *chip); diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index e1eadb0c1568..9d42b7d78e50 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -560,7 +560,7 @@ static int i2c_nuvoton_probe(struct i2c_client *client, rc = devm_request_irq(dev, chip->vendor.irq, i2c_nuvoton_int_handler, IRQF_TRIGGER_LOW, - chip->vendor.miscdev.name, + chip->devname, chip); if (rc) { dev_err(dev, "%s() Unable to request irq: %d for use\n", diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 9e02489a94f3..239cf0bbc1a1 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -698,7 +698,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, TPM_INT_VECTOR(chip->vendor.locality)); if (devm_request_irq (dev, i, tis_int_probe, IRQF_SHARED, - chip->vendor.miscdev.name, chip) != 0) { + chip->devname, chip) != 0) { dev_info(chip->pdev, "Unable to request irq: %d for probe\n", i); @@ -745,7 +745,7 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, TPM_INT_VECTOR(chip->vendor.locality)); if (devm_request_irq (dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED, - chip->vendor.miscdev.name, chip) != 0) { + chip->devname, chip) != 0) { dev_info(chip->pdev, "Unable to request irq: %d for use\n", chip->vendor.irq); -- cgit v1.2.3 From aec04cbdf7231c1b0da76172de82dfa2388a80d7 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Fri, 12 Dec 2014 11:46:40 -0800 Subject: tpm: TPM 2.0 FIFO Interface Detect TPM 2.0 by sending idempotent TPM 2.x command. Ordinals for TPM 2.0 are higher than TPM 1.x commands so this should be fail-safe. Using STS3 is unreliable because some chips just report 0xff and not what the spec says. Before TPM family is detected, timeouts are set to the maximum values for both TPM 1.x and TPM 2.x. In addition to this, suspend/resume functionality is implemented for TPM 2.x. Signed-off-by: Jarkko Sakkinen Signed-off-by: Will Arthur Reviewed-by: Jasob Gunthorpe Reviewed-by: Stefan Berger Reviewed-by: Peter Huewe Tested-by: Peter Huewe Signed-off-by: Peter Huewe --- drivers/char/tpm/tpm_tis.c | 112 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 89 insertions(+), 23 deletions(-) (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 239cf0bbc1a1..20a61bc98db8 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2005, 2006 IBM Corporation + * Copyright (C) 2014 Intel Corporation * * Authors: * Leendert van Doorn @@ -64,12 +65,22 @@ enum tis_defaults { TIS_LONG_TIMEOUT = 2000, /* 2 sec */ }; + +/* Some timeout values are needed before it is known whether the chip is + * TPM 1.0 or TPM 2.0. + */ +#define TIS_TIMEOUT_A_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) +#define TIS_TIMEOUT_B_MAX max(TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) +#define TIS_TIMEOUT_C_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) +#define TIS_TIMEOUT_D_MAX max(TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) + #define TPM_ACCESS(l) (0x0000 | ((l) << 12)) #define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) #define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) #define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) #define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) #define TPM_STS(l) (0x0018 | ((l) << 12)) +#define TPM_STS3(l) (0x001b | ((l) << 12)) #define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) @@ -363,6 +374,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) { int rc; u32 ordinal; + unsigned long dur; rc = tpm_tis_send_data(chip, buf, len); if (rc < 0) @@ -374,9 +386,14 @@ static int tpm_tis_send_main(struct tpm_chip *chip, u8 *buf, size_t len) if (chip->vendor.irq) { ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + dur = tpm2_calc_ordinal_duration(chip, ordinal); + else + dur = tpm_calc_ordinal_duration(chip, ordinal); + if (wait_for_tpm_stat - (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, - tpm_calc_ordinal_duration(chip, ordinal), + (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur, &chip->vendor.read_queue, false) < 0) { rc = -ETIME; goto out_err; @@ -598,17 +615,19 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, return PTR_ERR(chip); chip->vendor.priv = priv; +#ifdef CONFIG_ACPI chip->acpi_dev_handle = acpi_dev_handle; +#endif chip->vendor.iobase = devm_ioremap(dev, start, len); if (!chip->vendor.iobase) return -EIO; - /* 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); + /* Maximum timeouts */ + chip->vendor.timeout_a = TIS_TIMEOUT_A_MAX; + chip->vendor.timeout_b = TIS_TIMEOUT_B_MAX; + chip->vendor.timeout_c = TIS_TIMEOUT_C_MAX; + chip->vendor.timeout_d = TIS_TIMEOUT_D_MAX; if (wait_startup(chip, 0) != 0) { rc = -ENODEV; @@ -620,11 +639,18 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, goto out_err; } + /* Every TPM 2.x command has a higher ordinal than TPM 1.x commands. + * Therefore, we can use an idempotent TPM 2.x command to probe TPM 2.x. + */ + rc = tpm2_gen_interrupt(chip, true); + if (rc == 0 || rc == TPM2_RC_INITIALIZE) + chip->flags |= TPM_CHIP_FLAG_TPM2; + vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); chip->vendor.manufacturer_id = vendor; - dev_info(dev, - "1.2 TPM (device-id 0x%X, rev-id %d)\n", + dev_info(dev, "%s TPM (device-id 0x%X, rev-id %d)\n", + (chip->flags & TPM_CHIP_FLAG_TPM2) ? "2.0" : "1.2", vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); if (!itpm) { @@ -720,7 +746,10 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, chip->vendor.probed_irq = 0; /* Generate Interrupts */ - tpm_gen_interrupt(chip); + if (chip->flags & TPM_CHIP_FLAG_TPM2) + tpm2_gen_interrupt(chip, false); + else + tpm_gen_interrupt(chip); chip->vendor.irq = chip->vendor.probed_irq; @@ -765,16 +794,44 @@ static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle, } } - if (tpm_get_timeouts(chip)) { - dev_err(dev, "Could not get TPM timeouts and durations\n"); - rc = -ENODEV; - goto out_err; - } + if (chip->flags & TPM_CHIP_FLAG_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] = + msecs_to_jiffies(TPM2_DURATION_SHORT); + chip->vendor.duration[TPM_MEDIUM] = + msecs_to_jiffies(TPM2_DURATION_MEDIUM); + chip->vendor.duration[TPM_LONG] = + msecs_to_jiffies(TPM2_DURATION_LONG); + + rc = tpm2_do_selftest(chip); + if (rc == TPM2_RC_INITIALIZE) { + dev_warn(dev, "Firmware has not started TPM\n"); + rc = tpm2_startup(chip, TPM2_SU_CLEAR); + if (!rc) + rc = tpm2_do_selftest(chip); + } - if (tpm_do_selftest(chip)) { - dev_err(dev, "TPM self test failed\n"); - rc = -ENODEV; - goto out_err; + if (rc) { + dev_err(dev, "TPM self test failed\n"); + if (rc > 0) + rc = -ENODEV; + goto out_err; + } + } else { + if (tpm_get_timeouts(chip)) { + dev_err(dev, "Could not get TPM timeouts and durations\n"); + rc = -ENODEV; + goto out_err; + } + + if (tpm_do_selftest(chip)) { + dev_err(dev, "TPM self test failed\n"); + rc = -ENODEV; + goto out_err; + } } return tpm_chip_register(chip); @@ -808,14 +865,23 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) static int tpm_tis_resume(struct device *dev) { struct tpm_chip *chip = dev_get_drvdata(dev); - int ret; + int ret = 0; if (chip->vendor.irq) tpm_tis_reenable_interrupts(chip); - ret = tpm_pm_resume(dev); - if (!ret) - tpm_do_selftest(chip); + if (chip->flags & TPM_CHIP_FLAG_TPM2) { + /* NOP if firmware properly does this. */ + tpm2_startup(chip, TPM2_SU_STATE); + + ret = tpm2_shutdown(chip, TPM2_SU_STATE); + if (!ret) + ret = tpm2_do_selftest(chip); + } else { + ret = tpm_pm_resume(dev); + if (!ret) + tpm_do_selftest(chip); + } return ret; } -- cgit v1.2.3 From 961be7ef6963806cb978ccd6acf6bf84b0c63346 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Thu, 22 Jan 2015 00:42:50 +0100 Subject: tpm/tpm_tis: Add missing ifdef CONFIG_ACPI for pnp_acpi_device This fixes a build failure if CONFIG_PNP is set but CONFIG_ACPI is not: drivers/char/tpm/tpm_tis.c: In function ?tpm_tis_pnp_init?: drivers/char/tpm/tpm_tis.c:912:45: error: invalid type argument of ?->? (have ?int?) acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; If CONFIG_PNPACPI is not set pnp_acpi_device is defined as 0 and thus accesing the handle is not possible. Fixes: 0dc553652102 ("tpm: fix raciness of PPI interface lookup") Reported-by: Jim Davis Signed-off-by: Peter Huewe Signed-off-by: James Morris --- drivers/char/tpm/tpm_tis.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/char/tpm/tpm_tis.c') diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 20a61bc98db8..6725bef7cb96 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -908,8 +908,10 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, if (is_itpm(pnp_dev)) itpm = true; +#ifdef CONFIG_ACPI if (pnp_acpi_device(pnp_dev)) acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; +#endif return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq); } -- cgit v1.2.3