diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 14 | ||||
-rw-r--r-- | drivers/char/agp/alpha-agp.c | 2 | ||||
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 4 | ||||
-rw-r--r-- | drivers/char/hw_random/Kconfig | 13 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/msm-rng.c | 183 | ||||
-rw-r--r-- | drivers/char/mem.c | 1 | ||||
-rw-r--r-- | drivers/char/random.c | 59 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-chip.c | 68 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 72 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 31 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 258 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-space.c | 12 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 101 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_i2c_infineon.c | 8 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.h | 1 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_spi.c | 9 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_vtpm_proxy.c | 2 |
19 files changed, 334 insertions, 507 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 212f447938ae..ce277ee0a28a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -554,3 +554,17 @@ config ADI endmenu +config RANDOM_TRUST_CPU + bool "Trust the CPU manufacturer to initialize Linux's CRNG" + depends on X86 || S390 || PPC + default n + help + Assume that CPU manufacturer (e.g., Intel or AMD for RDSEED or + RDRAND, IBM for the S390 and Power PC architectures) is trustworthy + for the purposes of initializing Linux's CRNG. Since this is not + something that can be independently audited, this amounts to trusting + that CPU manufacturer (perhaps with the insistence or mandate + of a Nation State's intelligence or law enforcement agencies) + has not installed a hidden back door to compromise the CPU's + random number generation facilities. + diff --git a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c index 53fe633df1e8..c9bf2c219841 100644 --- a/drivers/char/agp/alpha-agp.c +++ b/drivers/char/agp/alpha-agp.c @@ -11,7 +11,7 @@ #include "agp.h" -static int alpha_core_agp_vm_fault(struct vm_fault *vmf) +static vm_fault_t alpha_core_agp_vm_fault(struct vm_fault *vmf) { alpha_agp_info *agp = agp_bridge->dev_private_data; dma_addr_t dma_addr; diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index e50c29c97ca7..c69e39fdd02b 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -156,7 +156,7 @@ static u64 amd64_configure(struct pci_dev *hammer, u64 gatt_table) /* Address to map to */ pci_read_config_dword(hammer, AMD64_GARTAPERTUREBASE, &tmp); - aperturebase = tmp << 25; + aperturebase = (u64)tmp << 25; aper_base = (aperturebase & PCI_BASE_ADDRESS_MEM_MASK); enable_gart_translation(hammer, gatt_table); @@ -277,7 +277,7 @@ static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap) pci_read_config_dword(nb, AMD64_GARTAPERTURECTL, &nb_order); nb_order = (nb_order >> 1) & 7; pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base); - nb_aper = nb_base << 25; + nb_aper = (u64)nb_base << 25; /* Northbridge seems to contain crap. Try the AGP bridge. */ diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index c34b257d852d..dac895dc01b9 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -307,19 +307,6 @@ config HW_RANDOM_HISI If unsure, say Y. -config HW_RANDOM_MSM - tristate "Qualcomm SoCs Random Number Generator support" - depends on HW_RANDOM && ARCH_QCOM - default HW_RANDOM - ---help--- - This driver provides kernel-side support for the Random Number - Generator hardware found on Qualcomm SoCs. - - To compile this driver as a module, choose M here. the - module will be called msm-rng. - - If unsure, say Y. - config HW_RANDOM_ST tristate "ST Microelectronics HW Random Number Generator support" depends on HW_RANDOM && ARCH_STI diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 533e913c93d1..e35ec3ce3a20 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -29,7 +29,6 @@ obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o -obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o obj-$(CONFIG_HW_RANDOM_ST) += st-rng.o obj-$(CONFIG_HW_RANDOM_XGENE) += xgene-rng.o obj-$(CONFIG_HW_RANDOM_STM32) += stm32-rng.o diff --git a/drivers/char/hw_random/msm-rng.c b/drivers/char/hw_random/msm-rng.c deleted file mode 100644 index 841fee845ec9..000000000000 --- a/drivers/char/hw_random/msm-rng.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/hw_random.h> -#include <linux/io.h> -#include <linux/module.h> -#include <linux/of.h> -#include <linux/platform_device.h> - -/* Device specific register offsets */ -#define PRNG_DATA_OUT 0x0000 -#define PRNG_STATUS 0x0004 -#define PRNG_LFSR_CFG 0x0100 -#define PRNG_CONFIG 0x0104 - -/* Device specific register masks and config values */ -#define PRNG_LFSR_CFG_MASK 0x0000ffff -#define PRNG_LFSR_CFG_CLOCKS 0x0000dddd -#define PRNG_CONFIG_HW_ENABLE BIT(1) -#define PRNG_STATUS_DATA_AVAIL BIT(0) - -#define MAX_HW_FIFO_DEPTH 16 -#define MAX_HW_FIFO_SIZE (MAX_HW_FIFO_DEPTH * 4) -#define WORD_SZ 4 - -struct msm_rng { - void __iomem *base; - struct clk *clk; - struct hwrng hwrng; -}; - -#define to_msm_rng(p) container_of(p, struct msm_rng, hwrng) - -static int msm_rng_enable(struct hwrng *hwrng, int enable) -{ - struct msm_rng *rng = to_msm_rng(hwrng); - u32 val; - int ret; - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - if (enable) { - /* Enable PRNG only if it is not already enabled */ - val = readl_relaxed(rng->base + PRNG_CONFIG); - if (val & PRNG_CONFIG_HW_ENABLE) - goto already_enabled; - - val = readl_relaxed(rng->base + PRNG_LFSR_CFG); - val &= ~PRNG_LFSR_CFG_MASK; - val |= PRNG_LFSR_CFG_CLOCKS; - writel(val, rng->base + PRNG_LFSR_CFG); - - val = readl_relaxed(rng->base + PRNG_CONFIG); - val |= PRNG_CONFIG_HW_ENABLE; - writel(val, rng->base + PRNG_CONFIG); - } else { - val = readl_relaxed(rng->base + PRNG_CONFIG); - val &= ~PRNG_CONFIG_HW_ENABLE; - writel(val, rng->base + PRNG_CONFIG); - } - -already_enabled: - clk_disable_unprepare(rng->clk); - return 0; -} - -static int msm_rng_read(struct hwrng *hwrng, void *data, size_t max, bool wait) -{ - struct msm_rng *rng = to_msm_rng(hwrng); - size_t currsize = 0; - u32 *retdata = data; - size_t maxsize; - int ret; - u32 val; - - /* calculate max size bytes to transfer back to caller */ - maxsize = min_t(size_t, MAX_HW_FIFO_SIZE, max); - - ret = clk_prepare_enable(rng->clk); - if (ret) - return ret; - - /* read random data from hardware */ - do { - val = readl_relaxed(rng->base + PRNG_STATUS); - if (!(val & PRNG_STATUS_DATA_AVAIL)) - break; - - val = readl_relaxed(rng->base + PRNG_DATA_OUT); - if (!val) - break; - - *retdata++ = val; - currsize += WORD_SZ; - - /* make sure we stay on 32bit boundary */ - if ((maxsize - currsize) < WORD_SZ) - break; - } while (currsize < maxsize); - - clk_disable_unprepare(rng->clk); - - return currsize; -} - -static int msm_rng_init(struct hwrng *hwrng) -{ - return msm_rng_enable(hwrng, 1); -} - -static void msm_rng_cleanup(struct hwrng *hwrng) -{ - msm_rng_enable(hwrng, 0); -} - -static int msm_rng_probe(struct platform_device *pdev) -{ - struct resource *res; - struct msm_rng *rng; - int ret; - - rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL); - if (!rng) - return -ENOMEM; - - platform_set_drvdata(pdev, rng); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - rng->base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(rng->base)) - return PTR_ERR(rng->base); - - rng->clk = devm_clk_get(&pdev->dev, "core"); - if (IS_ERR(rng->clk)) - return PTR_ERR(rng->clk); - - rng->hwrng.name = KBUILD_MODNAME, - rng->hwrng.init = msm_rng_init, - rng->hwrng.cleanup = msm_rng_cleanup, - rng->hwrng.read = msm_rng_read, - - ret = devm_hwrng_register(&pdev->dev, &rng->hwrng); - if (ret) { - dev_err(&pdev->dev, "failed to register hwrng\n"); - return ret; - } - - return 0; -} - -static const struct of_device_id msm_rng_of_match[] = { - { .compatible = "qcom,prng", }, - {} -}; -MODULE_DEVICE_TABLE(of, msm_rng_of_match); - -static struct platform_driver msm_rng_driver = { - .probe = msm_rng_probe, - .driver = { - .name = KBUILD_MODNAME, - .of_match_table = of_match_ptr(msm_rng_of_match), - } -}; -module_platform_driver(msm_rng_driver); - -MODULE_ALIAS("platform:" KBUILD_MODNAME); -MODULE_AUTHOR("The Linux Foundation"); -MODULE_DESCRIPTION("Qualcomm MSM random number generator driver"); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 4b00d6adcccf..7b4e4de778e4 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -708,6 +708,7 @@ static int mmap_zero(struct file *file, struct vm_area_struct *vma) #endif if (vma->vm_flags & VM_SHARED) return shmem_zero_setup(vma); + vma_set_anonymous(vma); return 0; } diff --git a/drivers/char/random.c b/drivers/char/random.c index cd888d4ee605..bf5f99fc36f1 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -782,6 +782,7 @@ static void invalidate_batched_entropy(void); static void crng_initialize(struct crng_state *crng) { int i; + int arch_init = 1; unsigned long rv; memcpy(&crng->state[0], "expand 32-byte k", 16); @@ -792,10 +793,18 @@ static void crng_initialize(struct crng_state *crng) _get_random_bytes(&crng->state[4], sizeof(__u32) * 12); for (i = 4; i < 16; i++) { if (!arch_get_random_seed_long(&rv) && - !arch_get_random_long(&rv)) + !arch_get_random_long(&rv)) { rv = random_get_entropy(); + arch_init = 0; + } crng->state[i] ^= rv; } +#ifdef CONFIG_RANDOM_TRUST_CPU + if (arch_init) { + crng_init = 2; + pr_notice("random: crng done (trusting CPU's manufacturer)\n"); + } +#endif crng->init_time = jiffies - CRNG_RESEED_INTERVAL - 1; } @@ -1122,8 +1131,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) } sample; long delta, delta2, delta3; - preempt_disable(); - sample.jiffies = jiffies; sample.cycles = random_get_entropy(); sample.num = num; @@ -1161,8 +1168,6 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) * and limit entropy entimate to 12 bits. */ credit_entropy_bits(r, min_t(int, fls(delta>>1), 11)); - - preempt_enable(); } void add_input_randomness(unsigned int type, unsigned int code, @@ -1659,6 +1664,21 @@ int wait_for_random_bytes(void) EXPORT_SYMBOL(wait_for_random_bytes); /* + * Returns whether or not the urandom pool has been seeded and thus guaranteed + * to supply cryptographically secure random numbers. This applies to: the + * /dev/urandom device, the get_random_bytes function, and the get_random_{u32, + * ,u64,int,long} family of functions. + * + * Returns: true if the urandom pool has been seeded. + * false if the urandom pool has not been seeded. + */ +bool rng_is_initialized(void) +{ + return crng_ready(); +} +EXPORT_SYMBOL(rng_is_initialized); + +/* * Add a callback function that will be invoked when the nonblocking * pool is initialised. * @@ -1725,30 +1745,31 @@ EXPORT_SYMBOL(del_random_ready_callback); * key known by the NSA). So it's useful if we need the speed, but * only if we're willing to trust the hardware manufacturer not to * have put in a back door. + * + * Return number of bytes filled in. */ -void get_random_bytes_arch(void *buf, int nbytes) +int __must_check get_random_bytes_arch(void *buf, int nbytes) { + int left = nbytes; char *p = buf; - trace_get_random_bytes_arch(nbytes, _RET_IP_); - while (nbytes) { + trace_get_random_bytes_arch(left, _RET_IP_); + while (left) { unsigned long v; - int chunk = min(nbytes, (int)sizeof(unsigned long)); + int chunk = min_t(int, left, sizeof(unsigned long)); if (!arch_get_random_long(&v)) break; - + memcpy(p, &v, chunk); p += chunk; - nbytes -= chunk; + left -= chunk; } - if (nbytes) - get_random_bytes(p, nbytes); + return nbytes - left; } EXPORT_SYMBOL(get_random_bytes_arch); - /* * init_std_data - initialize pool with system data * @@ -1895,14 +1916,22 @@ static int write_pool(struct entropy_store *r, const char __user *buffer, size_t count) { size_t bytes; - __u32 buf[16]; + __u32 t, buf[16]; const char __user *p = buffer; while (count > 0) { + int b, i = 0; + bytes = min(count, sizeof(buf)); if (copy_from_user(&buf, p, bytes)) return -EFAULT; + for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) { + if (!arch_get_random_int(&t)) + break; + buf[i] ^= t; + } + count -= bytes; p += bytes; diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 0a62c19937b6..46caadca916a 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c @@ -81,42 +81,66 @@ void tpm_put_ops(struct tpm_chip *chip) EXPORT_SYMBOL_GPL(tpm_put_ops); /** - * tpm_chip_find_get() - find and reserve a TPM chip + * tpm_default_chip() - find a TPM chip and get a reference to it + */ +struct tpm_chip *tpm_default_chip(void) +{ + struct tpm_chip *chip, *res = NULL; + int chip_num = 0; + int chip_prev; + + mutex_lock(&idr_lock); + + do { + chip_prev = chip_num; + chip = idr_get_next(&dev_nums_idr, &chip_num); + if (chip) { + get_device(&chip->dev); + res = chip; + break; + } + } while (chip_prev != chip_num); + + mutex_unlock(&idr_lock); + + return res; +} +EXPORT_SYMBOL_GPL(tpm_default_chip); + +/** + * tpm_find_get_ops() - find and reserve a TPM chip * @chip: a &struct tpm_chip instance, %NULL for the default chip * * Finds a TPM chip and reserves its class device and operations. The chip must - * be released with tpm_chip_put_ops() after use. + * be released with tpm_put_ops() after use. + * This function is for internal use only. It supports existing TPM callers + * by accepting NULL, but those callers should be converted to pass in a chip + * directly. * * Return: * A reserved &struct tpm_chip instance. * %NULL if a chip is not found. * %NULL if the chip is not available. */ -struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip) +struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip) { - struct tpm_chip *res = NULL; - int chip_num = 0; - int chip_prev; - - mutex_lock(&idr_lock); + int rc; - if (!chip) { - do { - chip_prev = chip_num; - chip = idr_get_next(&dev_nums_idr, &chip_num); - if (chip && !tpm_try_get_ops(chip)) { - res = chip; - break; - } - } while (chip_prev != chip_num); - } else { + if (chip) { if (!tpm_try_get_ops(chip)) - res = chip; + return chip; + return NULL; } - mutex_unlock(&idr_lock); - - return res; + chip = tpm_default_chip(); + if (!chip) + return NULL; + rc = tpm_try_get_ops(chip); + /* release additional reference we got from tpm_default_chip() */ + put_device(&chip->dev); + if (rc) + return NULL; + return chip; } /** diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index e32f6e85dc6d..1a803b0cf980 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -29,7 +29,6 @@ #include <linux/mutex.h> #include <linux/spinlock.h> #include <linux/freezer.h> -#include <linux/pm_runtime.h> #include <linux/tpm_eventlog.h> #include "tpm.h" @@ -369,10 +368,13 @@ err_len: return -EINVAL; } -static int tpm_request_locality(struct tpm_chip *chip) +static int tpm_request_locality(struct tpm_chip *chip, unsigned int flags) { int rc; + if (flags & TPM_TRANSMIT_NESTED) + return 0; + if (!chip->ops->request_locality) return 0; @@ -385,10 +387,13 @@ static int tpm_request_locality(struct tpm_chip *chip) return 0; } -static void tpm_relinquish_locality(struct tpm_chip *chip) +static void tpm_relinquish_locality(struct tpm_chip *chip, unsigned int flags) { int rc; + if (flags & TPM_TRANSMIT_NESTED) + return; + if (!chip->ops->relinquish_locality) return; @@ -399,6 +404,28 @@ static void tpm_relinquish_locality(struct tpm_chip *chip) chip->locality = -1; } +static int tpm_cmd_ready(struct tpm_chip *chip, unsigned int flags) +{ + if (flags & TPM_TRANSMIT_NESTED) + return 0; + + if (!chip->ops->cmd_ready) + return 0; + + return chip->ops->cmd_ready(chip); +} + +static int tpm_go_idle(struct tpm_chip *chip, unsigned int flags) +{ + if (flags & TPM_TRANSMIT_NESTED) + return 0; + + if (!chip->ops->go_idle) + return 0; + + return chip->ops->go_idle(chip); +} + static ssize_t tpm_try_transmit(struct tpm_chip *chip, struct tpm_space *space, u8 *buf, size_t bufsiz, @@ -423,7 +450,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | TSS2_RESMGR_TPM_RC_LAYER); - return bufsiz; + return sizeof(*header); } if (bufsiz > TPM_BUFSIZE) @@ -439,24 +466,24 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, return -E2BIG; } - if (!(flags & TPM_TRANSMIT_UNLOCKED)) + if (!(flags & TPM_TRANSMIT_UNLOCKED) && !(flags & TPM_TRANSMIT_NESTED)) mutex_lock(&chip->tpm_mutex); - if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, true); /* Store the decision as chip->locality will be changed. */ need_locality = chip->locality == -1; - if (!(flags & TPM_TRANSMIT_RAW) && need_locality) { - rc = tpm_request_locality(chip); + if (need_locality) { + rc = tpm_request_locality(chip, flags); if (rc < 0) goto out_no_locality; } - if (chip->dev.parent) - pm_runtime_get_sync(chip->dev.parent); + rc = tpm_cmd_ready(chip, flags); + if (rc) + goto out; rc = tpm2_prepare_space(chip, space, ordinal, buf); if (rc) @@ -516,19 +543,22 @@ out_recv: } rc = tpm2_commit_space(chip, space, ordinal, buf, &len); + if (rc) + dev_err(&chip->dev, "tpm2_commit_space: error %d\n", rc); out: - if (chip->dev.parent) - pm_runtime_put_sync(chip->dev.parent); + rc = tpm_go_idle(chip, flags); + if (rc) + goto out; if (need_locality) - tpm_relinquish_locality(chip); + tpm_relinquish_locality(chip, flags); out_no_locality: if (chip->ops->clk_enable != NULL) chip->ops->clk_enable(chip, false); - if (!(flags & TPM_TRANSMIT_UNLOCKED)) + if (!(flags & TPM_TRANSMIT_UNLOCKED) && !(flags & TPM_TRANSMIT_NESTED)) mutex_unlock(&chip->tpm_mutex); return rc ? rc : len; } @@ -930,7 +960,7 @@ int tpm_is_tpm2(struct tpm_chip *chip) { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -954,7 +984,7 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; if (chip->flags & TPM_CHIP_FLAG_TPM2) @@ -1013,7 +1043,7 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) u32 count = 0; int i; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -1142,7 +1172,7 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -1262,7 +1292,7 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) return -EINVAL; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip) return -ENODEV; @@ -1324,7 +1354,7 @@ int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) return -ENODEV; @@ -1352,7 +1382,7 @@ int tpm_unseal_trusted(struct tpm_chip *chip, { int rc; - chip = tpm_chip_find_get(chip); + chip = tpm_find_get_ops(chip); if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) return -ENODEV; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 4426649e431c..f3501d05264f 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -424,23 +424,24 @@ struct tpm_buf { u8 *data; }; -static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +static inline void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) { struct tpm_input_header *head; + head = (struct tpm_input_header *)buf->data; + head->tag = cpu_to_be16(tag); + head->length = cpu_to_be32(sizeof(*head)); + head->ordinal = cpu_to_be32(ordinal); +} +static inline int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +{ buf->data_page = alloc_page(GFP_HIGHUSER); if (!buf->data_page) return -ENOMEM; buf->flags = 0; buf->data = kmap(buf->data_page); - - head = (struct tpm_input_header *) buf->data; - - head->tag = cpu_to_be16(tag); - head->length = cpu_to_be32(sizeof(*head)); - head->ordinal = cpu_to_be32(ordinal); - + tpm_buf_reset(buf, tag, ordinal); return 0; } @@ -511,9 +512,17 @@ extern const struct file_operations tpm_fops; extern const struct file_operations tpmrm_fops; extern struct idr dev_nums_idr; +/** + * enum tpm_transmit_flags - flags for tpm_transmit() + * + * @TPM_TRANSMIT_UNLOCKED: do not lock the chip + * @TPM_TRANSMIT_NESTED: discard setup steps (power management, + * locality) including locking (i.e. implicit + * UNLOCKED) + */ enum tpm_transmit_flags { TPM_TRANSMIT_UNLOCKED = BIT(0), - TPM_TRANSMIT_RAW = BIT(1), + TPM_TRANSMIT_NESTED = BIT(1), }; ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, @@ -538,7 +547,7 @@ static inline void tpm_msleep(unsigned int delay_msec) delay_msec * 1000); }; -struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip); +struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip); __must_check int tpm_try_get_ops(struct tpm_chip *chip); void tpm_put_ops(struct tpm_chip *chip); @@ -569,7 +578,7 @@ static inline u32 tpm2_rc_value(u32 rc) int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, struct tpm2_digest *digests); -int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max); +int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max); void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, unsigned int flags); int tpm2_seal_trusted(struct tpm_chip *chip, diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index d31b09099216..c31b490bd41d 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -27,46 +27,6 @@ enum tpm2_session_attributes { TPM2_SA_CONTINUE_SESSION = BIT(0), }; -struct tpm2_startup_in { - __be16 startup_type; -} __packed; - -struct tpm2_get_tpm_pt_in { - __be32 cap_id; - __be32 property_id; - __be32 property_cnt; -} __packed; - -struct tpm2_get_tpm_pt_out { - u8 more_data; - __be32 subcap_id; - __be32 property_cnt; - __be32 property_id; - __be32 value; -} __packed; - -struct tpm2_get_random_in { - __be16 size; -} __packed; - -struct tpm2_get_random_out { - __be16 size; - u8 buffer[TPM_MAX_RNG_DATA]; -} __packed; - -union tpm2_cmd_params { - struct tpm2_startup_in startup_in; - struct tpm2_get_tpm_pt_in get_tpm_pt_in; - struct tpm2_get_tpm_pt_out get_tpm_pt_out; - struct tpm2_get_random_in getrandom_in; - struct tpm2_get_random_out getrandom_out; -}; - -struct tpm2_cmd { - tpm_cmd_header header; - union tpm2_cmd_params params; -} __packed; - struct tpm2_hash { unsigned int crypto_id; unsigned int tpm_id; @@ -321,82 +281,72 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count, } -#define TPM2_GETRANDOM_IN_SIZE \ - (sizeof(struct tpm_input_header) + \ - sizeof(struct tpm2_get_random_in)) - -static const struct tpm_input_header tpm2_getrandom_header = { - .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), - .length = cpu_to_be32(TPM2_GETRANDOM_IN_SIZE), - .ordinal = cpu_to_be32(TPM2_CC_GET_RANDOM) -}; +struct tpm2_get_random_out { + __be16 size; + u8 buffer[TPM_MAX_RNG_DATA]; +} __packed; /** * tpm2_get_random() - get random bytes from the TPM RNG * - * @chip: TPM chip to use - * @out: destination buffer for the random bytes - * @max: the max number of bytes to write to @out + * @chip: a &tpm_chip instance + * @dest: destination buffer + * @max: the max number of random bytes to pull * * Return: - * Size of the output buffer, or -EIO on error. + * size of the buffer on success, + * -errno otherwise */ -int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max) +int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { - struct tpm2_cmd cmd; - u32 recd, rlength; - u32 num_bytes; + struct tpm2_get_random_out *out; + struct tpm_buf buf; + u32 recd; + u32 num_bytes = max; int err; int total = 0; int retries = 5; - u8 *dest = out; + u8 *dest_ptr = dest; - num_bytes = min_t(u32, max, sizeof(cmd.params.getrandom_out.buffer)); - - if (!out || !num_bytes || - max > sizeof(cmd.params.getrandom_out.buffer)) + if (!num_bytes || max > TPM_MAX_RNG_DATA) return -EINVAL; - do { - cmd.header.in = tpm2_getrandom_header; - cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); + err = tpm_buf_init(&buf, 0, 0); + if (err) + return err; - err = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), + do { + tpm_buf_reset(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_RANDOM); + tpm_buf_append_u16(&buf, num_bytes); + err = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, offsetof(struct tpm2_get_random_out, buffer), 0, "attempting get random"); if (err) - break; + goto out; - recd = min_t(u32, be16_to_cpu(cmd.params.getrandom_out.size), - num_bytes); - rlength = be32_to_cpu(cmd.header.out.length); - if (rlength < offsetof(struct tpm2_get_random_out, buffer) + - recd) - return -EFAULT; - memcpy(dest, cmd.params.getrandom_out.buffer, recd); + out = (struct tpm2_get_random_out *) + &buf.data[TPM_HEADER_SIZE]; + recd = min_t(u32, be16_to_cpu(out->size), num_bytes); + if (tpm_buf_length(&buf) < + offsetof(struct tpm2_get_random_out, buffer) + recd) { + err = -EFAULT; + goto out; + } + memcpy(dest_ptr, out->buffer, recd); - dest += recd; + dest_ptr += recd; total += recd; num_bytes -= recd; } while (retries-- && total < max); + tpm_buf_destroy(&buf); return total ? total : -EIO; +out: + tpm_buf_destroy(&buf); + return err; } -#define TPM2_GET_TPM_PT_IN_SIZE \ - (sizeof(struct tpm_input_header) + \ - sizeof(struct tpm2_get_tpm_pt_in)) - -#define TPM2_GET_TPM_PT_OUT_BODY_SIZE \ - sizeof(struct tpm2_get_tpm_pt_out) - -static const struct tpm_input_header tpm2_get_tpm_pt_header = { - .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), - .length = cpu_to_be32(TPM2_GET_TPM_PT_IN_SIZE), - .ordinal = cpu_to_be32(TPM2_CC_GET_CAPABILITY) -}; - /** * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command * @chip: TPM chip to use @@ -471,7 +421,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, { unsigned int blob_len; struct tpm_buf buf; - u32 hash, rlength; + u32 hash; int i; int rc; @@ -546,8 +496,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, rc = -E2BIG; goto out; } - rlength = be32_to_cpu(((struct tpm2_cmd *)&buf)->header.out.length); - if (rlength < TPM_HEADER_SIZE + 4 + blob_len) { + if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 4 + blob_len) { rc = -EFAULT; goto out; } @@ -657,7 +606,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, u16 data_len; u8 *data; int rc; - u32 rlength; rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); if (rc) @@ -685,9 +633,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, goto out; } - rlength = be32_to_cpu(((struct tpm2_cmd *)&buf) - ->header.out.length); - if (rlength < TPM_HEADER_SIZE + 6 + data_len) { + if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) { rc = -EFAULT; goto out; } @@ -733,69 +679,71 @@ out: return rc; } +struct tpm2_get_cap_out { + u8 more_data; + __be32 subcap_id; + __be32 property_cnt; + __be32 property_id; + __be32 value; +} __packed; + /** * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property - * @chip: TPM chip to use. + * @chip: a &tpm_chip instance * @property_id: property ID. * @value: output variable. * @desc: passed to tpm_transmit_cmd() * - * Return: Same as with tpm_transmit_cmd. + * Return: + * 0 on success, + * -errno or a TPM return code otherwise */ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc) { - struct tpm2_cmd cmd; + struct tpm2_get_cap_out *out; + struct tpm_buf buf; int rc; - cmd.header.in = tpm2_get_tpm_pt_header; - cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES); - cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); - cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); - - rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), - TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc); - if (!rc) - *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value); - + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + if (rc) + return rc; + tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); + tpm_buf_append_u32(&buf, property_id); + tpm_buf_append_u32(&buf, 1); + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL); + if (!rc) { + out = (struct tpm2_get_cap_out *) + &buf.data[TPM_HEADER_SIZE]; + *value = be32_to_cpu(out->value); + } + tpm_buf_destroy(&buf); return rc; } EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); -#define TPM2_SHUTDOWN_IN_SIZE \ - (sizeof(struct tpm_input_header) + \ - sizeof(struct tpm2_startup_in)) - -static const struct tpm_input_header tpm2_shutdown_header = { - .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), - .length = cpu_to_be32(TPM2_SHUTDOWN_IN_SIZE), - .ordinal = cpu_to_be32(TPM2_CC_SHUTDOWN) -}; - /** - * tpm2_shutdown() - send shutdown command to the TPM chip + * tpm2_shutdown() - send a TPM shutdown command + * + * Sends a TPM shutdown command. The shutdown command is used in call + * sites where the system is going down. If it fails, there is not much + * that can be done except print an error message. * - * @chip: TPM chip to use. - * @shutdown_type: shutdown type. The value is either - * TPM_SU_CLEAR or TPM_SU_STATE. + * @chip: a &tpm_chip instance + * @shutdown_type: TPM_SU_CLEAR or TPM_SU_STATE. */ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) { - struct tpm2_cmd cmd; + struct tpm_buf buf; int rc; - cmd.header.in = tpm2_shutdown_header; - cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); - - rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, - "stopping the TPM"); - - /* In places where shutdown command is sent there's no much we can do - * except print the error code on a system failure. - */ - if (rc < 0 && rc != -EPIPE) - dev_warn(&chip->dev, "transmit returned %d while stopping the TPM", - rc); + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN); + if (rc) + return; + tpm_buf_append_u16(&buf, shutdown_type); + tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, + "stopping the TPM"); + tpm_buf_destroy(&buf); } /* @@ -863,31 +811,37 @@ static int tpm2_do_selftest(struct tpm_chip *chip) } /** - * tpm2_probe() - probe TPM 2.0 - * @chip: TPM chip to use + * tpm2_probe() - probe for the TPM 2.0 protocol + * @chip: a &tpm_chip instance * - * Return: < 0 error and 0 on success. + * Send an idempotent TPM 2.0 command and see whether there is TPM2 chip in the + * other end based on the response tag. The flag TPM_CHIP_FLAG_TPM2 is set by + * this function if this is the case. * - * Send idempotent TPM 2.0 command and see whether TPM 2.0 chip replied based on - * the reply tag. + * Return: + * 0 on success, + * -errno otherwise */ int tpm2_probe(struct tpm_chip *chip) { - struct tpm2_cmd cmd; + struct tpm_output_header *out; + struct tpm_buf buf; int rc; - cmd.header.in = tpm2_get_tpm_pt_header; - cmd.params.get_tpm_pt_in.cap_id = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES); - cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); - cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); - - rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, NULL); - if (rc < 0) + rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + if (rc) return rc; - - if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS) - chip->flags |= TPM_CHIP_FLAG_TPM2; - + tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); + tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS); + tpm_buf_append_u32(&buf, 1); + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0, NULL); + /* We ignore TPM return codes on purpose. */ + if (rc >= 0) { + out = (struct tpm_output_header *)buf.data; + if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS) + chip->flags |= TPM_CHIP_FLAG_TPM2; + } + tpm_buf_destroy(&buf); return 0; } EXPORT_SYMBOL_GPL(tpm2_probe); diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index 6122d3276f72..d2e101b32482 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -39,7 +39,7 @@ static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space) for (i = 0; i < ARRAY_SIZE(space->session_tbl); i++) { if (space->session_tbl[i]) tpm2_flush_context_cmd(chip, space->session_tbl[i], - TPM_TRANSMIT_UNLOCKED); + TPM_TRANSMIT_NESTED); } } @@ -84,7 +84,7 @@ static int tpm2_load_context(struct tpm_chip *chip, u8 *buf, tpm_buf_append(&tbuf, &buf[*offset], body_size); rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4, - TPM_TRANSMIT_UNLOCKED, NULL); + TPM_TRANSMIT_NESTED, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); @@ -133,7 +133,7 @@ static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, tpm_buf_append_u32(&tbuf, handle); rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0, - TPM_TRANSMIT_UNLOCKED, NULL); + TPM_TRANSMIT_NESTED, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); @@ -170,7 +170,7 @@ static void tpm2_flush_space(struct tpm_chip *chip) for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) if (space->context_tbl[i] && ~space->context_tbl[i]) tpm2_flush_context_cmd(chip, space->context_tbl[i], - TPM_TRANSMIT_UNLOCKED); + TPM_TRANSMIT_NESTED); tpm2_flush_sessions(chip, space); } @@ -377,7 +377,7 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp, return 0; out_no_slots: - tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED); + tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_NESTED); dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__, phandle); return -ENOMEM; @@ -465,7 +465,7 @@ static int tpm2_save_space(struct tpm_chip *chip) return rc; tpm2_flush_context_cmd(chip, space->context_tbl[i], - TPM_TRANSMIT_UNLOCKED); + TPM_TRANSMIT_NESTED); space->context_tbl[i] = ~0; } diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 34fbc6cb097b..36952ef98f90 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -132,7 +132,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, } /** - * crb_go_idle - request tpm crb device to go the idle state + * __crb_go_idle - request tpm crb device to go the idle state * * @dev: crb device * @priv: crb private data @@ -147,7 +147,7 @@ static bool crb_wait_for_reg_32(u32 __iomem *reg, u32 mask, u32 value, * * Return: 0 always */ -static int crb_go_idle(struct device *dev, struct crb_priv *priv) +static int __crb_go_idle(struct device *dev, struct crb_priv *priv) { if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || @@ -163,11 +163,20 @@ static int crb_go_idle(struct device *dev, struct crb_priv *priv) dev_warn(dev, "goIdle timed out\n"); return -ETIME; } + return 0; } +static int crb_go_idle(struct tpm_chip *chip) +{ + struct device *dev = &chip->dev; + struct crb_priv *priv = dev_get_drvdata(dev); + + return __crb_go_idle(dev, priv); +} + /** - * crb_cmd_ready - request tpm crb device to enter ready state + * __crb_cmd_ready - request tpm crb device to enter ready state * * @dev: crb device * @priv: crb private data @@ -181,7 +190,7 @@ static int crb_go_idle(struct device *dev, struct crb_priv *priv) * * Return: 0 on success -ETIME on timeout; */ -static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) +static int __crb_cmd_ready(struct device *dev, struct crb_priv *priv) { if ((priv->sm == ACPI_TPM2_START_METHOD) || (priv->sm == ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD) || @@ -200,6 +209,14 @@ static int crb_cmd_ready(struct device *dev, struct crb_priv *priv) return 0; } +static int crb_cmd_ready(struct tpm_chip *chip) +{ + struct device *dev = &chip->dev; + struct crb_priv *priv = dev_get_drvdata(dev); + + return __crb_cmd_ready(dev, priv); +} + static int __crb_request_locality(struct device *dev, struct crb_priv *priv, int loc) { @@ -401,6 +418,8 @@ static const struct tpm_class_ops tpm_crb = { .send = crb_send, .cancel = crb_cancel, .req_canceled = crb_req_canceled, + .go_idle = crb_go_idle, + .cmd_ready = crb_cmd_ready, .request_locality = crb_request_locality, .relinquish_locality = crb_relinquish_locality, .req_complete_mask = CRB_DRV_STS_COMPLETE, @@ -520,7 +539,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, * PTT HW bug w/a: wake up the device to access * possibly not retained registers. */ - ret = crb_cmd_ready(dev, priv); + ret = __crb_cmd_ready(dev, priv); if (ret) goto out_relinquish_locality; @@ -565,7 +584,7 @@ out: if (!ret) priv->cmd_size = cmd_size; - crb_go_idle(dev, priv); + __crb_go_idle(dev, priv); out_relinquish_locality: @@ -628,32 +647,7 @@ static int crb_acpi_add(struct acpi_device *device) chip->acpi_dev_handle = device->handle; chip->flags = TPM_CHIP_FLAG_TPM2; - rc = __crb_request_locality(dev, priv, 0); - if (rc) - return rc; - - rc = crb_cmd_ready(dev, priv); - if (rc) - goto out; - - pm_runtime_get_noresume(dev); - pm_runtime_set_active(dev); - pm_runtime_enable(dev); - - rc = tpm_chip_register(chip); - if (rc) { - crb_go_idle(dev, priv); - pm_runtime_put_noidle(dev); - pm_runtime_disable(dev); - goto out; - } - - pm_runtime_put_sync(dev); - -out: - __crb_relinquish_locality(dev, priv, 0); - - return rc; + return tpm_chip_register(chip); } static int crb_acpi_remove(struct acpi_device *device) @@ -663,52 +657,11 @@ static int crb_acpi_remove(struct acpi_device *device) tpm_chip_unregister(chip); - pm_runtime_disable(dev); - return 0; } -static int __maybe_unused crb_pm_runtime_suspend(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - struct crb_priv *priv = dev_get_drvdata(&chip->dev); - - return crb_go_idle(dev, priv); -} - -static int __maybe_unused crb_pm_runtime_resume(struct device *dev) -{ - struct tpm_chip *chip = dev_get_drvdata(dev); - struct crb_priv *priv = dev_get_drvdata(&chip->dev); - - return crb_cmd_ready(dev, priv); -} - -static int __maybe_unused crb_pm_suspend(struct device *dev) -{ - int ret; - - ret = tpm_pm_suspend(dev); - if (ret) - return ret; - - return crb_pm_runtime_suspend(dev); -} - -static int __maybe_unused crb_pm_resume(struct device *dev) -{ - int ret; - - ret = crb_pm_runtime_resume(dev); - if (ret) - return ret; - - return tpm_pm_resume(dev); -} - static const struct dev_pm_ops crb_pm = { - SET_SYSTEM_SLEEP_PM_OPS(crb_pm_suspend, crb_pm_resume) - SET_RUNTIME_PM_OPS(crb_pm_runtime_suspend, crb_pm_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(tpm_pm_suspend, tpm_pm_resume) }; static const struct acpi_device_id crb_device_ids[] = { diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 6116cd05e228..9086edc9066b 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c @@ -117,7 +117,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) /* Lock the adapter for the duration of the whole sequence. */ if (!tpm_dev.client->adapter->algo->master_xfer) return -EOPNOTSUPP; - i2c_lock_adapter(tpm_dev.client->adapter); + i2c_lock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); if (tpm_dev.chip_type == SLB9645) { /* use a combined read for newer chips @@ -192,7 +192,7 @@ static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) } out: - i2c_unlock_adapter(tpm_dev.client->adapter); + i2c_unlock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); /* take care of 'guard time' */ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); @@ -224,7 +224,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, if (!tpm_dev.client->adapter->algo->master_xfer) return -EOPNOTSUPP; - i2c_lock_adapter(tpm_dev.client->adapter); + i2c_lock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); /* prepend the 'register address' to the buffer */ tpm_dev.buf[0] = addr; @@ -243,7 +243,7 @@ static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, usleep_range(sleep_low, sleep_hi); } - i2c_unlock_adapter(tpm_dev.client->adapter); + i2c_unlock_bus(tpm_dev.client->adapter, I2C_LOCK_SEGMENT); /* take care of 'guard time' */ usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 8b46aaa9e049..d2345d9fd7b5 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -875,6 +875,8 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, chip->acpi_dev_handle = acpi_dev_handle; #endif + chip->hwrng.quality = priv->rng_quality; + /* Maximum timeouts */ chip->timeout_a = msecs_to_jiffies(TIS_TIMEOUT_A_MAX); chip->timeout_b = msecs_to_jiffies(TIS_TIMEOUT_B_MAX); diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index f6e1dbe212a7..f48125f1e6e0 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -99,6 +99,7 @@ struct tpm_tis_data { wait_queue_head_t int_queue; wait_queue_head_t read_queue; const struct tpm_tis_phy_ops *phy_ops; + unsigned short rng_quality; }; struct tpm_tis_phy_ops { diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c index 424ff2fde1f2..9914f6973463 100644 --- a/drivers/char/tpm/tpm_tis_spi.c +++ b/drivers/char/tpm/tpm_tis_spi.c @@ -199,6 +199,7 @@ static const struct tpm_tis_phy_ops tpm_spi_phy_ops = { static int tpm_tis_spi_probe(struct spi_device *dev) { struct tpm_tis_spi_phy *phy; + int irq; phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy), GFP_KERNEL); @@ -211,7 +212,13 @@ static int tpm_tis_spi_probe(struct spi_device *dev) if (!phy->iobuf) return -ENOMEM; - return tpm_tis_core_init(&dev->dev, &phy->priv, -1, &tpm_spi_phy_ops, + /* If the SPI device has an IRQ then use that */ + if (dev->irq > 0) + irq = dev->irq; + else + irq = -1; + + return tpm_tis_core_init(&dev->dev, &phy->priv, irq, &tpm_spi_phy_ops, NULL); } diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index e4f79f920450..87a0ce47f201 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -418,7 +418,7 @@ static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) proxy_dev->state |= STATE_DRIVER_COMMAND; rc = tpm_transmit_cmd(chip, NULL, buf.data, tpm_buf_length(&buf), 0, - TPM_TRANSMIT_UNLOCKED | TPM_TRANSMIT_RAW, + TPM_TRANSMIT_NESTED, "attempting to set locality"); proxy_dev->state &= ~STATE_DRIVER_COMMAND; |