summaryrefslogtreecommitdiff
path: root/drivers/char
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/char
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig10
-rw-r--r--drivers/char/bsr.c1
-rw-r--r--drivers/char/hpet.c29
-rw-r--r--drivers/char/hw_random/Kconfig38
-rw-r--r--drivers/char/hw_random/Makefile3
-rw-r--r--drivers/char/hw_random/msm-rng.c197
-rw-r--r--drivers/char/hw_random/omap3-rom-rng.c141
-rw-r--r--drivers/char/hw_random/pasemi-rng.c1
-rw-r--r--drivers/char/hw_random/powernv-rng.c81
-rw-r--r--drivers/char/hw_random/ppc4xx-rng.c1
-rw-r--r--drivers/char/hw_random/pseries-rng.c19
-rw-r--r--drivers/char/hw_random/timeriomem-rng.c2
-rw-r--r--drivers/char/hw_random/via-rng.c2
-rw-r--r--drivers/char/hw_random/virtio-rng.c4
-rw-r--r--drivers/char/i8k.c7
-rw-r--r--drivers/char/misc.c20
-rw-r--r--drivers/char/nwbutton.c2
-rw-r--r--drivers/char/random.c646
-rw-r--r--drivers/char/rtc.c5
-rw-r--r--drivers/char/snsc.c3
-rw-r--r--drivers/char/snsc_event.c3
-rw-r--r--drivers/char/tlclk.c2
-rw-r--r--drivers/char/tpm/Kconfig37
-rw-r--r--drivers/char/tpm/Makefile11
-rw-r--r--drivers/char/tpm/tpm.c (renamed from drivers/char/tpm/tpm-interface.c)138
-rw-r--r--drivers/char/tpm/tpm.h3
-rw-r--r--drivers/char/tpm/tpm_atmel.c2
-rw-r--r--drivers/char/tpm/tpm_eventlog.c3
-rw-r--r--drivers/char/tpm/tpm_i2c_atmel.c284
-rw-r--r--drivers/char/tpm/tpm_i2c_infineon.c4
-rw-r--r--drivers/char/tpm/tpm_i2c_nuvoton.c710
-rw-r--r--drivers/char/tpm/tpm_i2c_stm_st33.c12
-rw-r--r--drivers/char/tpm/tpm_ibmvtpm.c6
-rw-r--r--drivers/char/tpm/tpm_ppi.c4
-rw-r--r--drivers/char/tpm/tpm_tis.c2
-rw-r--r--drivers/char/tpm/xen-tpmfront.c2
-rw-r--r--drivers/char/virtio_console.c25
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c3
38 files changed, 422 insertions, 2041 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index fa3243d..1421997 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -522,16 +522,10 @@ config HPET_MMAP
If you say Y here, user applications will be able to mmap
the HPET registers.
-config HPET_MMAP_DEFAULT
- bool "Enable HPET MMAP access by default"
- default y
- depends on HPET_MMAP
- help
In some hardware implementations, the page containing HPET
registers may also contain other things that shouldn't be
- exposed to the user. This option selects the default (if
- kernel parameter hpet_mmap is not set) user access to the
- registers for applications that require it.
+ exposed to the user. If this applies to your hardware,
+ say N here.
config HANGCHECK_TIMER
tristate "Hangcheck timer"
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 8fedbc2..0671e45 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -21,7 +21,6 @@
#include <linux/kernel.h>
#include <linux/of.h>
-#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/of_platform.h>
#include <linux/fs.h>
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5d9c31d..448ce5e 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -367,29 +367,12 @@ static unsigned int hpet_poll(struct file *file, poll_table * wait)
return 0;
}
-#ifdef CONFIG_HPET_MMAP
-#ifdef CONFIG_HPET_MMAP_DEFAULT
-static int hpet_mmap_enabled = 1;
-#else
-static int hpet_mmap_enabled = 0;
-#endif
-
-static __init int hpet_mmap_enable(char *str)
-{
- get_option(&str, &hpet_mmap_enabled);
- pr_info("HPET mmap %s\n", hpet_mmap_enabled ? "enabled" : "disabled");
- return 1;
-}
-__setup("hpet_mmap", hpet_mmap_enable);
-
static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
{
+#ifdef CONFIG_HPET_MMAP
struct hpet_dev *devp;
unsigned long addr;
- if (!hpet_mmap_enabled)
- return -EACCES;
-
devp = file->private_data;
addr = devp->hd_hpets->hp_hpet_phys;
@@ -398,13 +381,10 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
return vm_iomap_memory(vma, addr, PAGE_SIZE);
-}
#else
-static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
-{
return -ENOSYS;
-}
#endif
+}
static int hpet_fasync(int fd, struct file *file, int on)
{
@@ -506,7 +486,8 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp)
}
sprintf(devp->hd_name, "hpet%d", (int)(devp - hpetp->hp_dev));
- irq_flags = devp->hd_flags & HPET_SHARED_IRQ ? IRQF_SHARED : 0;
+ irq_flags = devp->hd_flags & HPET_SHARED_IRQ
+ ? IRQF_SHARED : IRQF_DISABLED;
if (request_irq(irq, hpet_interrupt, irq_flags,
devp->hd_name, (void *)devp)) {
printk(KERN_ERR "hpet: IRQ %d is not free\n", irq);
@@ -990,6 +971,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
struct acpi_resource_fixed_memory32 *fixmem32;
fixmem32 = &res->data.fixed_memory32;
+ if (!fixmem32)
+ return AE_NO_MEMORY;
hdp->hd_phys_address = fixmem32->address;
hdp->hd_address = ioremap(fixmem32->address,
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 2f2b084..0aa9d91 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -165,19 +165,6 @@ config HW_RANDOM_OMAP
If unsure, say Y.
-config HW_RANDOM_OMAP3_ROM
- tristate "OMAP3 ROM Random Number Generator support"
- depends on HW_RANDOM && ARCH_OMAP3
- default HW_RANDOM
- ---help---
- This driver provides kernel-side support for the Random Number
- Generator hardware found on OMAP34xx processors.
-
- To compile this driver as a module, choose M here: the
- module will be called omap3-rom-rng.
-
- If unsure, say Y.
-
config HW_RANDOM_OCTEON
tristate "Octeon Random Number Generator support"
depends on HW_RANDOM && CAVIUM_OCTEON_SOC
@@ -303,19 +290,6 @@ config HW_RANDOM_PSERIES
If unsure, say Y.
-config HW_RANDOM_POWERNV
- tristate "PowerNV Random Number Generator support"
- depends on HW_RANDOM && PPC_POWERNV
- default HW_RANDOM
- ---help---
- This is the driver for Random Number Generator hardware found
- in POWER7+ and above machines for PowerNV platform.
-
- To compile this driver as a module, choose M here: the
- module will be called powernv-rng.
-
- If unsure, say Y.
-
config HW_RANDOM_EXYNOS
tristate "EXYNOS HW random number generator support"
depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK
@@ -340,15 +314,3 @@ config HW_RANDOM_TPM
module will be called tpm-rng.
If unsure, say Y.
-
-config HW_RANDOM_MSM
- tristate "Qualcomm MSM Random Number Generator support"
- depends on HW_RANDOM && ARCH_MSM
- ---help---
- This driver provides kernel-side support for the Random Number
- Generator hardware found on Qualcomm MSM SoCs.
-
- To compile this driver as a module, choose M here. the
- module will be called msm-rng.
-
- If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 3ae7755..bed467c 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -15,7 +15,6 @@ n2-rng-y := n2-drv.o n2-asm.o
obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
-obj-$(CONFIG_HW_RANDOM_OMAP3_ROM) += omap3-rom-rng.o
obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
@@ -25,8 +24,6 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
-obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
-obj-$(CONFIG_HW_RANDOM_MSM) += msm-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 148521e..0000000
--- a/drivers/char/hw_random/msm-rng.c
+++ /dev/null
@@ -1,197 +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);
-
- /* no room for word data */
- if (maxsize < WORD_SZ)
- return 0;
-
- 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 = hwrng_register(&rng->hwrng);
- if (ret) {
- dev_err(&pdev->dev, "failed to register hwrng\n");
- return ret;
- }
-
- return 0;
-}
-
-static int msm_rng_remove(struct platform_device *pdev)
-{
- struct msm_rng *rng = platform_get_drvdata(pdev);
-
- hwrng_unregister(&rng->hwrng);
- 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,
- .remove = msm_rng_remove,
- .driver = {
- .name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
- .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/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c
deleted file mode 100644
index c853e9e..0000000
--- a/drivers/char/hw_random/omap3-rom-rng.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * omap3-rom-rng.c - RNG driver for TI OMAP3 CPU family
- *
- * Copyright (C) 2009 Nokia Corporation
- * Author: Juha Yrjola <juha.yrjola@solidboot.com>
- *
- * Copyright (C) 2013 Pali Rohár <pali.rohar@gmail.com>
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/random.h>
-#include <linux/hw_random.h>
-#include <linux/timer.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-
-#define RNG_RESET 0x01
-#define RNG_GEN_PRNG_HW_INIT 0x02
-#define RNG_GEN_HW 0x08
-
-/* param1: ptr, param2: count, param3: flag */
-static u32 (*omap3_rom_rng_call)(u32, u32, u32);
-
-static struct timer_list idle_timer;
-static int rng_idle;
-static struct clk *rng_clk;
-
-static void omap3_rom_rng_idle(unsigned long data)
-{
- int r;
-
- r = omap3_rom_rng_call(0, 0, RNG_RESET);
- if (r != 0) {
- pr_err("reset failed: %d\n", r);
- return;
- }
- clk_disable_unprepare(rng_clk);
- rng_idle = 1;
-}
-
-static int omap3_rom_rng_get_random(void *buf, unsigned int count)
-{
- u32 r;
- u32 ptr;
-
- del_timer_sync(&idle_timer);
- if (rng_idle) {
- clk_prepare_enable(rng_clk);
- r = omap3_rom_rng_call(0, 0, RNG_GEN_PRNG_HW_INIT);
- if (r != 0) {
- clk_disable_unprepare(rng_clk);
- pr_err("HW init failed: %d\n", r);
- return -EIO;
- }
- rng_idle = 0;
- }
-
- ptr = virt_to_phys(buf);
- r = omap3_rom_rng_call(ptr, count, RNG_GEN_HW);
- mod_timer(&idle_timer, jiffies + msecs_to_jiffies(500));
- if (r != 0)
- return -EINVAL;
- return 0;
-}
-
-static int omap3_rom_rng_data_present(struct hwrng *rng, int wait)
-{
- return 1;
-}
-
-static int omap3_rom_rng_data_read(struct hwrng *rng, u32 *data)
-{
- int r;
-
- r = omap3_rom_rng_get_random(data, 4);
- if (r < 0)
- return r;
- return 4;
-}
-
-static struct hwrng omap3_rom_rng_ops = {
- .name = "omap3-rom",
- .data_present = omap3_rom_rng_data_present,
- .data_read = omap3_rom_rng_data_read,
-};
-
-static int omap3_rom_rng_probe(struct platform_device *pdev)
-{
- pr_info("initializing\n");
-
- omap3_rom_rng_call = pdev->dev.platform_data;
- if (!omap3_rom_rng_call) {
- pr_err("omap3_rom_rng_call is NULL\n");
- return -EINVAL;
- }
-
- setup_timer(&idle_timer, omap3_rom_rng_idle, 0);
- rng_clk = clk_get(&pdev->dev, "ick");
- if (IS_ERR(rng_clk)) {
- pr_err("unable to get RNG clock\n");
- return PTR_ERR(rng_clk);
- }
-
- /* Leave the RNG in reset state. */
- clk_prepare_enable(rng_clk);
- omap3_rom_rng_idle(0);
-
- return hwrng_register(&omap3_rom_rng_ops);
-}
-
-static int omap3_rom_rng_remove(struct platform_device *pdev)
-{
- hwrng_unregister(&omap3_rom_rng_ops);
- clk_disable_unprepare(rng_clk);
- clk_put(rng_clk);
- return 0;
-}
-
-static struct platform_driver omap3_rom_rng_driver = {
- .driver = {
- .name = "omap3-rom-rng",
- .owner = THIS_MODULE,
- },
- .probe = omap3_rom_rng_probe,
- .remove = omap3_rom_rng_remove,
-};
-
-module_platform_driver(omap3_rom_rng_driver);
-
-MODULE_ALIAS("platform:omap3-rom-rng");
-MODULE_AUTHOR("Juha Yrjola");
-MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index c66279b..c6df5b2 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -24,7 +24,6 @@
#include <linux/platform_device.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
-#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/io.h>
diff --git a/drivers/char/hw_random/powernv-rng.c b/drivers/char/hw_random/powernv-rng.c
deleted file mode 100644
index 3f4f632..0000000
--- a/drivers/char/hw_random/powernv-rng.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2013 Michael Ellerman, Guo Chao, IBM Corp.
- *
- * 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; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/hw_random.h>
-
-static int powernv_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
-{
- unsigned long *buf;
- int i, len;
-
- /* We rely on rng_buffer_size() being >= sizeof(unsigned long) */
- len = max / sizeof(unsigned long);
-
- buf = (unsigned long *)data;
-
- for (i = 0; i < len; i++)
- powernv_get_random_long(buf++);
-
- return len * sizeof(unsigned long);
-}
-
-static struct hwrng powernv_hwrng = {
- .name = "powernv-rng",
- .read = powernv_rng_read,
-};
-
-static int powernv_rng_remove(struct platform_device *pdev)
-{
- hwrng_unregister(&powernv_hwrng);
-
- return 0;
-}
-
-static int powernv_rng_probe(struct platform_device *pdev)
-{
- int rc;
-
- rc = hwrng_register(&powernv_hwrng);
- if (rc) {
- /* We only register one device, ignore any others */
- if (rc == -EEXIST)
- rc = -ENODEV;
-
- return rc;
- }
-
- pr_info("Registered powernv hwrng.\n");
-
- return 0;
-}
-
-static struct of_device_id powernv_rng_match[] = {
- { .compatible = "ibm,power-rng",},
- {},
-};
-MODULE_DEVICE_TABLE(of, powernv_rng_match);
-
-static struct platform_driver powernv_rng_driver = {
- .driver = {
- .name = "powernv_rng",
- .of_match_table = powernv_rng_match,
- },
- .probe = powernv_rng_probe,
- .remove = powernv_rng_remove,
-};
-module_platform_driver(powernv_rng_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Bare metal HWRNG driver for POWER7+ and above");
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index 521f76b..732c330 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -13,7 +13,6 @@
#include <linux/platform_device.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
-#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <asm/io.h>
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c
index ab7ffde..5f11979 100644
--- a/drivers/char/hw_random/pseries-rng.c
+++ b/drivers/char/hw_random/pseries-rng.c
@@ -17,25 +17,18 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hw_random.h>
#include <asm/vio.h>
+#define MODULE_NAME "pseries-rng"
static int pseries_rng_data_read(struct hwrng *rng, u32 *data)
{
- int rc;
-
- rc = plpar_hcall(H_RANDOM, (unsigned long *)data);
- if (rc != H_SUCCESS) {
- pr_err_ratelimited("H_RANDOM call failed %d\n", rc);
- return -EIO;
+ if (plpar_hcall(H_RANDOM, (unsigned long *)data) != H_SUCCESS) {
+ printk(KERN_ERR "pseries rng hcall error\n");
+ return 0;
}
-
- /* The hypervisor interface returns 64 bits */
return 8;
}
@@ -54,7 +47,7 @@ static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev)
};
static struct hwrng pseries_rng = {
- .name = KBUILD_MODNAME,
+ .name = MODULE_NAME,
.data_read = pseries_rng_data_read,
};
@@ -77,7 +70,7 @@ static struct vio_device_id pseries_rng_driver_ids[] = {
MODULE_DEVICE_TABLE(vio, pseries_rng_driver_ids);
static struct vio_driver pseries_rng_driver = {
- .name = KBUILD_MODNAME,
+ .name = MODULE_NAME,
.probe = pseries_rng_probe,
.remove = pseries_rng_remove,
.get_desired_dma = pseries_rng_get_desired_dma,
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index 73ce739..d2120ba 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -79,7 +79,7 @@ static int timeriomem_rng_data_read(struct hwrng *rng, u32 *data)
priv->expires = cur + delay;
priv->present = 0;
- reinit_completion(&priv->completion);
+ INIT_COMPLETION(priv->completion);
mod_timer(&priv->timer, priv->expires);
return 4;
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index de5a6dc..e737772 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -221,7 +221,7 @@ static void __exit mod_exit(void)
module_init(mod_init);
module_exit(mod_exit);
-static struct x86_cpu_id __maybe_unused via_rng_cpu_id[] = {
+static struct x86_cpu_id via_rng_cpu_id[] = {
X86_FEATURE_MATCH(X86_FEATURE_XSTORE),
{}
};
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index c12398d..ef46a9c 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -133,7 +133,7 @@ static void virtrng_remove(struct virtio_device *vdev)
remove_common(vdev);
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
static int virtrng_freeze(struct virtio_device *vdev)
{
remove_common(vdev);
@@ -157,7 +157,7 @@ static struct virtio_driver virtio_rng_driver = {
.id_table = id_table,
.probe = virtrng_probe,
.remove = virtrng_remove,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
.freeze = virtrng_freeze,
.restore = virtrng_restore,
#endif
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index e6939e1..40cc0cf2 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -664,13 +664,6 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"),
},
},
- {
- .ident = "Dell XPS421",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
- },
- },
{ }
};
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index ffa97d2..190d442 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -114,7 +114,7 @@ static int misc_open(struct inode * inode, struct file * file)
int minor = iminor(inode);
struct miscdevice *c;
int err = -ENODEV;
- const struct file_operations *new_fops = NULL;
+ const struct file_operations *old_fops, *new_fops = NULL;
mutex_lock(&misc_mtx);
@@ -141,11 +141,17 @@ static int misc_open(struct inode * inode, struct file * file)
}
err = 0;
- replace_fops(file, new_fops);
+ old_fops = file->f_op;
+ file->f_op = new_fops;
if (file->f_op->open) {
file->private_data = c;
- err = file->f_op->open(inode,file);
+ err=file->f_op->open(inode,file);
+ if (err) {
+ fops_put(file->f_op);
+ file->f_op = fops_get(old_fops);
+ }
}
+ fops_put(old_fops);
fail:
mutex_unlock(&misc_mtx);
return err;
@@ -187,8 +193,8 @@ int misc_register(struct miscdevice * misc)
if (misc->minor == MISC_DYNAMIC_MINOR) {
int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
if (i >= DYNAMIC_MINORS) {
- err = -EBUSY;
- goto out;
+ mutex_unlock(&misc_mtx);
+ return -EBUSY;
}
misc->minor = DYNAMIC_MINORS - i - 1;
set_bit(i, misc_minors);
@@ -197,8 +203,8 @@ int misc_register(struct miscdevice * misc)
list_for_each_entry(c, &misc_list, list) {
if (c->minor == misc->minor) {
- err = -EBUSY;
- goto out;
+ mutex_unlock(&misc_mtx);
+ return -EBUSY;
}
}
}
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c
index 1fd00dc..cfdfe49 100644
--- a/drivers/char/nwbutton.c
+++ b/drivers/char/nwbutton.c
@@ -220,7 +220,7 @@ static int __init nwbutton_init(void)
return -EBUSY;
}
- if (request_irq (IRQ_NETWINDER_BUTTON, button_handler, 0,
+ if (request_irq (IRQ_NETWINDER_BUTTON, button_handler, IRQF_DISABLED,
"nwbutton", NULL)) {
printk (KERN_WARNING "nwbutton: IRQ %d is not free.\n",
IRQ_NETWINDER_BUTTON);
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 429b75b..7a744d3 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -255,7 +255,6 @@
#include <linux/fips.h>
#include <linux/ptrace.h>
#include <linux/kmemcheck.h>
-#include <linux/workqueue.h>
#include <linux/irq.h>
#include <asm/processor.h>
@@ -270,28 +269,14 @@
/*
* Configuration information
*/
-#define INPUT_POOL_SHIFT 12
-#define INPUT_POOL_WORDS (1 << (INPUT_POOL_SHIFT-5))
-#define OUTPUT_POOL_SHIFT 10
-#define OUTPUT_POOL_WORDS (1 << (OUTPUT_POOL_SHIFT-5))
-#define SEC_XFER_SIZE 512
-#define EXTRACT_SIZE 10
-
-#define DEBUG_RANDOM_BOOT 0
+#define INPUT_POOL_WORDS 128
+#define OUTPUT_POOL_WORDS 32
+#define SEC_XFER_SIZE 512
+#define EXTRACT_SIZE 10
#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long))
/*
- * To allow fractional bits to be tracked, the entropy_count field is
- * denominated in units of 1/8th bits.
- *
- * 2*(ENTROPY_SHIFT + log2(poolbits)) must <= 31, or the multiply in
- * credit_entropy_bits() needs to be 64 bits wide.
- */
-#define ENTROPY_SHIFT 3
-#define ENTROPY_BITS(r) ((r)->entropy_count >> ENTROPY_SHIFT)
-
-/*
* The minimum number of bits of entropy before we wake up a read on
* /dev/random. Should be enough to do a significant reseed.
*/
@@ -302,100 +287,108 @@ static int random_read_wakeup_thresh = 64;
* should wake up processes which are selecting or polling on write
* access to /dev/random.
*/
-static int random_write_wakeup_thresh = 28 * OUTPUT_POOL_WORDS;
+static int random_write_wakeup_thresh = 128;
/*
- * The minimum number of seconds between urandom pool resending. We
- * do this to limit the amount of entropy that can be drained from the
- * input pool even if there are heavy demands on /dev/urandom.
+ * When the input pool goes over trickle_thresh, start dropping most
+ * samples to avoid wasting CPU time and reduce lock contention.
*/
-static int random_min_urandom_seed = 60;
+
+static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
+
+static DEFINE_PER_CPU(int, trickle_count);
/*
- * Originally, we used a primitive polynomial of degree .poolwords
- * over GF(2). The taps for various sizes are defined below. They
- * were chosen to be evenly spaced except for the last tap, which is 1
- * to get the twisting happening as fast as possible.
- *
- * For the purposes of better mixing, we use the CRC-32 polynomial as
- * well to make a (modified) twisted Generalized Feedback Shift
- * Register. (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR
- * generators. ACM Transactions on Modeling and Computer Simulation
- * 2(3):179-194. Also see M. Matsumoto & Y. Kurita, 1994. Twisted
- * GFSR generators II. ACM Transactions on Mdeling and Computer
- * Simulation 4:254-266)
- *
- * Thanks to Colin Plumb for suggesting this.
- *
- * The mixing operation is much less sensitive than the output hash,
- * where we use SHA-1. All that we want of mixing operation is that
- * it be a good non-cryptographic hash; i.e. it not produce collisions
- * when fed "random" data of the sort we expect to see. As long as
- * the pool state differs for different inputs, we have preserved the
- * input entropy and done a good job. The fact that an intelligent
- * attacker can construct inputs that will produce controlled
- * alterations to the pool's state is not important because we don't
- * consider such inputs to contribute any randomness. The only
- * property we need with respect to them is that the attacker can't
- * increase his/her knowledge of the pool's state. Since all
- * additions are reversible (knowing the final state and the input,
- * you can reconstruct the initial state), if an attacker has any
- * uncertainty about the initial state, he/she can only shuffle that
- * uncertainty about, but never cause any collisions (which would
- * decrease the uncertainty).
- *
- * Our mixing functions were analyzed by Lacharme, Roeck, Strubel, and
- * Videau in their paper, "The Linux Pseudorandom Number Generator
- * Revisited" (see: http://eprint.iacr.org/2012/251.pdf). In their
- * paper, they point out that we are not using a true Twisted GFSR,
- * since Matsumoto & Kurita used a trinomial feedback polynomial (that
- * is, with only three taps, instead of the six that we are using).
- * As a result, the resulting polynomial is neither primitive nor
- * irreducible, and hence does not have a maximal period over
- * GF(2**32). They suggest a slight change to the generator
- * polynomial which improves the resulting TGFSR polynomial to be
- * irreducible, which we have made here.
+ * A pool of size .poolwords is stirred with a primitive polynomial
+ * of degree .poolwords over GF(2). The taps for various sizes are
+ * defined below. They are chosen to be evenly spaced (minimum RMS
+ * distance from evenly spaced; the numbers in the comments are a
+ * scaled squared error sum) except for the last tap, which is 1 to
+ * get the twisting happening as fast as possible.
*/
static struct poolinfo {
- int poolbitshift, poolwords, poolbytes, poolbits, poolfracbits;
-#define S(x) ilog2(x)+5, (x), (x)*4, (x)*32, (x) << (ENTROPY_SHIFT+5)
+ int poolwords;
int tap1, tap2, tap3, tap4, tap5;
} poolinfo_table[] = {
- /* was: x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 */
- /* x^128 + x^104 + x^76 + x^51 +x^25 + x + 1 */
- { S(128), 104, 76, 51, 25, 1 },
- /* was: x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 */
- /* x^32 + x^26 + x^19 + x^14 + x^7 + x + 1 */
- { S(32), 26, 19, 14, 7, 1 },
+ /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
+ { 128, 103, 76, 51, 25, 1 },
+ /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
+ { 32, 26, 20, 14, 7, 1 },
#if 0
/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
- { S(2048), 1638, 1231, 819, 411, 1 },
+ { 2048, 1638, 1231, 819, 411, 1 },
/* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
- { S(1024), 817, 615, 412, 204, 1 },
+ { 1024, 817, 615, 412, 204, 1 },
/* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
- { S(1024), 819, 616, 410, 207, 2 },
+ { 1024, 819, 616, 410, 207, 2 },
/* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
- { S(512), 411, 308, 208, 104, 1 },
+ { 512, 411, 308, 208, 104, 1 },
/* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
- { S(512), 409, 307, 206, 102, 2 },
+ { 512, 409, 307, 206, 102, 2 },
/* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
- { S(512), 409, 309, 205, 103, 2 },
+ { 512, 409, 309, 205, 103, 2 },
/* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
- { S(256), 205, 155, 101, 52, 1 },
+ { 256, 205, 155, 101, 52, 1 },
/* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
- { S(128), 103, 78, 51, 27, 2 },
+ { 128, 103, 78, 51, 27, 2 },
/* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
- { S(64), 52, 39, 26, 14, 1 },
+ { 64, 52, 39, 26, 14, 1 },
#endif
};
+#define POOLBITS poolwords*32
+#define POOLBYTES poolwords*4
+
+/*
+ * For the purposes of better mixing, we use the CRC-32 polynomial as
+ * well to make a twisted Generalized Feedback Shift Reigster
+ *
+ * (See M. Matsumoto & Y. Kurita, 1992. Twisted GFSR generators. ACM
+ * Transactions on Modeling and Computer Simulation 2(3):179-194.
+ * Also see M. Matsumoto & Y. Kurita, 1994. Twisted GFSR generators
+ * II. ACM Transactions on Mdeling and Computer Simulation 4:254-266)
+ *
+ * Thanks to Colin Plumb for suggesting this.
+ *
+ * We have not analyzed the resultant polynomial to prove it primitive;
+ * in fact it almost certainly isn't. Nonetheless, the irreducible factors
+ * of a random large-degree polynomial over GF(2) are more than large enough
+ * that periodicity is not a concern.
+ *
+ * The input hash is much less sensitive than the output hash. All
+ * that we want of it is that it be a good non-cryptographic hash;
+ * i.e. it not produce collisions when fed "random" data of the sort
+ * we expect to see. As long as the pool state differs for different
+ * inputs, we have preserved the input entropy and done a good job.
+ * The fact that an intelligent attacker can construct inputs that
+ * will produce controlled alterations to the pool's state is not
+ * important because we don't consider such inputs to contribute any
+ * randomness. The only property we need with respect to them is that
+ * the attacker can't increase his/her knowledge of the pool's state.
+ * Since all additions are reversible (knowing the final state and the
+ * input, you can reconstruct the initial state), if an attacker has
+ * any uncertainty about the initial state, he/she can only shuffle
+ * that uncertainty about, but never cause any collisions (which would
+ * decrease the uncertainty).
+ *
+ * The chosen system lets the state of the pool be (essentially) the input
+ * modulo the generator polymnomial. Now, for random primitive polynomials,
+ * this is a universal class of hash functions, meaning that the chance
+ * of a collision is limited by the attacker's knowledge of the generator
+ * polynomail, so if it is chosen at random, an attacker can never force
+ * a collision. Here, we use a fixed polynomial, but we *can* assume that
+ * ###--> it is unknown to the processes generating the input entropy. <-###
+ * Because of this important property, this is a good, collision-resistant
+ * hash; hash collisions will occur no more often than chance.
+ */
+
/*
* Static global variables
*/
@@ -403,6 +396,17 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
static struct fasync_struct *fasync;
+static bool debug;
+module_param(debug, bool, 0644);
+#define DEBUG_ENT(fmt, arg...) do { \
+ if (debug) \
+ printk(KERN_DEBUG "random %04d %04d %04d: " \
+ fmt,\
+ input_pool.entropy_count,\
+ blocking_pool.entropy_count,\
+ nonblocking_pool.entropy_count,\
+ ## arg); } while (0)
+
/**********************************************************************
*
* OS independent entropy store. Here are the functions which handle
@@ -413,26 +417,23 @@ static struct fasync_struct *fasync;
struct entropy_store;
struct entropy_store {
/* read-only data: */
- const struct poolinfo *poolinfo;
+ struct poolinfo *poolinfo;
__u32 *pool;
const char *name;
struct entropy_store *pull;
- struct work_struct push_work;
+ int limit;
/* read-write data: */
- unsigned long last_pulled;
spinlock_t lock;
- unsigned short add_ptr;
- unsigned short input_rotate;
+ unsigned add_ptr;
+ unsigned input_rotate;
int entropy_count;
int entropy_total;
unsigned int initialized:1;
- unsigned int limit:1;
- unsigned int last_data_init:1;
+ bool last_data_init;
__u8 last_data[EXTRACT_SIZE];
};
-static void push_to_pool(struct work_struct *work);
static __u32 input_pool_data[INPUT_POOL_WORDS];
static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
@@ -451,9 +452,7 @@ static struct entropy_store blocking_pool = {
.limit = 1,
.pull = &input_pool,
.lock = __SPIN_LOCK_UNLOCKED(blocking_pool.lock),
- .pool = blocking_pool_data,
- .push_work = __WORK_INITIALIZER(blocking_pool.push_work,
- push_to_pool),
+ .pool = blocking_pool_data
};
static struct entropy_store nonblocking_pool = {
@@ -461,9 +460,7 @@ static struct entropy_store nonblocking_pool = {
.name = "nonblocking",
.pull = &input_pool,
.lock = __SPIN_LOCK_UNLOCKED(nonblocking_pool.lock),
- .pool = nonblocking_pool_data,
- .push_work = __WORK_INITIALIZER(nonblocking_pool.push_work,
- push_to_pool),
+ .pool = nonblocking_pool_data
};
static __u32 const twist_table[8] = {
@@ -501,7 +498,7 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
/* mix one byte at a time to simplify size handling and churn faster */
while (nbytes--) {
- w = rol32(*bytes++, input_rotate);
+ w = rol32(*bytes++, input_rotate & 31);
i = (i - 1) & wordmask;
/* XOR in the various taps */
@@ -521,7 +518,7 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in,
* rotation, so that successive passes spread the
* input bits across the pool evenly.
*/
- input_rotate = (input_rotate + (i ? 7 : 14)) & 31;
+ input_rotate += i ? 7 : 14;
}
ACCESS_ONCE(r->input_rotate) = input_rotate;
@@ -564,151 +561,62 @@ struct fast_pool {
* collector. It's hardcoded for an 128 bit pool and assumes that any
* locks that might be needed are taken by the caller.
*/
-static void fast_mix(struct fast_pool *f, __u32 input[4])
+static void fast_mix(struct fast_pool *f, const void *in, int nbytes)
{
+ const char *bytes = in;
__u32 w;
+ unsigned i = f->count;
unsigned input_rotate = f->rotate;
- w = rol32(input[0], input_rotate) ^ f->pool[0] ^ f->pool[3];
- f->pool[0] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 14) & 31;
- w = rol32(input[1], input_rotate) ^ f->pool[1] ^ f->pool[0];
- f->pool[1] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 7) & 31;
- w = rol32(input[2], input_rotate) ^ f->pool[2] ^ f->pool[1];
- f->pool[2] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 7) & 31;
- w = rol32(input[3], input_rotate) ^ f->pool[3] ^ f->pool[2];
- f->pool[3] = (w >> 3) ^ twist_table[w & 7];
- input_rotate = (input_rotate + 7) & 31;
-
+ while (nbytes--) {
+ w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^
+ f->pool[(i + 1) & 3];
+ f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7];
+ input_rotate += (i++ & 3) ? 7 : 14;
+ }
+ f->count = i;
f->rotate = input_rotate;
- f->count++;
}
/*
- * Credit (or debit) the entropy store with n bits of entropy.
- * Use credit_entropy_bits_safe() if the value comes from userspace
- * or otherwise should be checked for extreme values.
+ * Credit (or debit) the entropy store with n bits of entropy
*/
static void credit_entropy_bits(struct entropy_store *r, int nbits)
{
int entropy_count, orig;
- const int pool_size = r->poolinfo->poolfracbits;
- int nfrac = nbits << ENTROPY_SHIFT;
if (!nbits)
return;
+ DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name);
retry:
entropy_count = orig = ACCESS_ONCE(r->entropy_count);
- if (nfrac < 0) {
- /* Debit */
- entropy_count += nfrac;
- } else {
- /*
- * Credit: we have to account for the possibility of
- * overwriting already present entropy. Even in the
- * ideal case of pure Shannon entropy, new contributions
- * approach the full value asymptotically:
- *
- * entropy <- entropy + (pool_size - entropy) *
- * (1 - exp(-add_entropy/pool_size))
- *
- * For add_entropy <= pool_size/2 then
- * (1 - exp(-add_entropy/pool_size)) >=
- * (add_entropy/pool_size)*0.7869...
- * so we can approximate the exponential with
- * 3/4*add_entropy/pool_size and still be on the
- * safe side by adding at most pool_size/2 at a time.
- *
- * The use of pool_size-2 in the while statement is to
- * prevent rounding artifacts from making the loop
- * arbitrarily long; this limits the loop to log2(pool_size)*2
- * turns no matter how large nbits is.
- */
- int pnfrac = nfrac;
- const int s = r->poolinfo->poolbitshift + ENTROPY_SHIFT + 2;
- /* The +2 corresponds to the /4 in the denominator */
-
- do {
- unsigned int anfrac = min(pnfrac, pool_size/2);
- unsigned int add =
- ((pool_size - entropy_count)*anfrac*3) >> s;
-
- entropy_count += add;
- pnfrac -= anfrac;
- } while (unlikely(entropy_count < pool_size-2 && pnfrac));
- }
+ entropy_count += nbits;
if (entropy_count < 0) {
- pr_warn("random: negative entropy/overflow: pool %s count %d\n",
- r->name, entropy_count);
- WARN_ON(1);
+ DEBUG_ENT("negative entropy/overflow\n");
entropy_count = 0;
- } else if (entropy_count > pool_size)
- entropy_count = pool_size;
+ } else if (entropy_count > r->poolinfo->POOLBITS)
+ entropy_count = r->poolinfo->POOLBITS;
if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
goto retry;
- r->entropy_total += nbits;
- if (!r->initialized && r->entropy_total > 128) {
- r->initialized = 1;
- r->entropy_total = 0;
- if (r == &nonblocking_pool) {
- prandom_reseed_late();
- pr_notice("random: %s pool is initialized\n", r->name);
- }
+ if (!r->initialized && nbits > 0) {
+ r->entropy_total += nbits;
+ if (r->entropy_total > 128)
+ r->initialized = 1;
}
- trace_credit_entropy_bits(r->name, nbits,
- entropy_count >> ENTROPY_SHIFT,
+ trace_credit_entropy_bits(r->name, nbits, entropy_count,
r->entropy_total, _RET_IP_);
- if (r == &input_pool) {
- int entropy_bytes = entropy_count >> ENTROPY_SHIFT;
-
- /* should we wake readers? */
- if (entropy_bytes >= random_read_wakeup_thresh) {
- wake_up_interruptible(&random_read_wait);
- kill_fasync(&fasync, SIGIO, POLL_IN);
- }
- /* If the input pool is getting full, send some
- * entropy to the two output pools, flipping back and
- * forth between them, until the output pools are 75%
- * full.
- */
- if (entropy_bytes > random_write_wakeup_thresh &&
- r->initialized &&
- r->entropy_total >= 2*random_read_wakeup_thresh) {
- static struct entropy_store *last = &blocking_pool;
- struct entropy_store *other = &blocking_pool;
-
- if (last == &blocking_pool)
- other = &nonblocking_pool;
- if (other->entropy_count <=
- 3 * other->poolinfo->poolfracbits / 4)
- last = other;
- if (last->entropy_count <=
- 3 * last->poolinfo->poolfracbits / 4) {
- schedule_work(&last->push_work);
- r->entropy_total = 0;
- }
- }
+ /* should we wake readers? */
+ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) {
+ wake_up_interruptible(&random_read_wait);
+ kill_fasync(&fasync, SIGIO, POLL_IN);
}
}
-static void credit_entropy_bits_safe(struct entropy_store *r, int nbits)
-{
- const int nbits_max = (int)(~0U >> (ENTROPY_SHIFT + 1));
-
- /* Cap the value to avoid overflows */
- nbits = min(nbits, nbits_max);
- nbits = max(nbits, -nbits_max);
-
- credit_entropy_bits(r, nbits);
-}
-
/*********************************************************************
*
* Entropy input management
@@ -722,8 +630,6 @@ struct timer_rand_state {
unsigned dont_count_entropy:1;
};
-#define INIT_TIMER_RAND_STATE { INITIAL_JIFFIES, };
-
/*
* Add device- or boot-specific data to the input and nonblocking
* pools to help initialize them to unique values.
@@ -735,22 +641,15 @@ struct timer_rand_state {
void add_device_randomness(const void *buf, unsigned int size)
{
unsigned long time = random_get_entropy() ^ jiffies;
- unsigned long flags;
- trace_add_device_randomness(size, _RET_IP_);
- spin_lock_irqsave(&input_pool.lock, flags);
- _mix_pool_bytes(&input_pool, buf, size, NULL);
- _mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
- spin_unlock_irqrestore(&input_pool.lock, flags);
-
- spin_lock_irqsave(&nonblocking_pool.lock, flags);
- _mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
- _mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
- spin_unlock_irqrestore(&nonblocking_pool.lock, flags);
+ mix_pool_bytes(&input_pool, buf, size, NULL);
+ mix_pool_bytes(&input_pool, &time, sizeof(time), NULL);
+ mix_pool_bytes(&nonblocking_pool, buf, size, NULL);
+ mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL);
}
EXPORT_SYMBOL(add_device_randomness);
-static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE;
+static struct timer_rand_state input_timer_state;
/*
* This function adds entropy to the entropy "pool" by using timing
@@ -764,7 +663,6 @@ static struct timer_rand_state input_timer_state = INIT_TIMER_RAND_STATE;
*/
static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
{
- struct entropy_store *r;
struct {
long jiffies;
unsigned cycles;
@@ -773,12 +671,15 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
long delta, delta2, delta3;
preempt_disable();
+ /* if over the trickle threshold, use only 1 in 4096 samples */
+ if (input_pool.entropy_count > trickle_thresh &&
+ ((__this_cpu_inc_return(trickle_count) - 1) & 0xfff))
+ goto out;
sample.jiffies = jiffies;
sample.cycles = random_get_entropy();
sample.num = num;
- r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
- mix_pool_bytes(r, &sample, sizeof(sample), NULL);
+ mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL);
/*
* Calculate number of bits of randomness we probably added.
@@ -812,8 +713,10 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
* Round down by 1 bit on general principles,
* and limit entropy entimate to 12 bits.
*/
- credit_entropy_bits(r, min_t(int, fls(delta>>1), 11));
+ credit_entropy_bits(&input_pool,
+ min_t(int, fls(delta>>1), 11));
}
+out:
preempt_enable();
}
@@ -826,10 +729,10 @@ void add_input_randomness(unsigned int type, unsigned int code,
if (value == last_value)
return;
+ DEBUG_ENT("input event\n");
last_value = value;
add_timer_randomness(&input_timer_state,
(type << 4) ^ code ^ (code >> 4) ^ value);
- trace_add_input_randomness(ENTROPY_BITS(&input_pool));
}
EXPORT_SYMBOL_GPL(add_input_randomness);
@@ -841,21 +744,20 @@ void add_interrupt_randomness(int irq, int irq_flags)
struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness);
struct pt_regs *regs = get_irq_regs();
unsigned long now = jiffies;
- cycles_t cycles = random_get_entropy();
- __u32 input[4], c_high, j_high;
- __u64 ip;
-
- c_high = (sizeof(cycles) > 4) ? cycles >> 32 : 0;
- j_high = (sizeof(now) > 4) ? now >> 32 : 0;
- input[0] = cycles ^ j_high ^ irq;
- input[1] = now ^ c_high;
- ip = regs ? instruction_pointer(regs) : _RET_IP_;
- input[2] = ip;
- input[3] = ip >> 32;
+ __u32 input[4], cycles = random_get_entropy();
+
+ input[0] = cycles ^ jiffies;
+ input[1] = irq;
+ if (regs) {
+ __u64 ip = instruction_pointer(regs);
+ input[2] = ip;
+ input[3] = ip >> 32;
+ }
- fast_mix(fast_pool, input);
+ fast_mix(fast_pool, input, sizeof(input));
- if ((fast_pool->count & 63) && !time_after(now, fast_pool->last + HZ))
+ if ((fast_pool->count & 1023) &&
+ !time_after(now, fast_pool->last + HZ))
return;
fast_pool->last = now;
@@ -884,8 +786,10 @@ void add_disk_randomness(struct gendisk *disk)
if (!disk || !disk->random)
return;
/* first major is 1, so we get >= 0x200 here */
+ DEBUG_ENT("disk event %d:%d\n",
+ MAJOR(disk_devt(disk)), MINOR(disk_devt(disk)));
+
add_timer_randomness(disk->random, 0x100 + disk_devt(disk));
- trace_add_disk_randomness(disk_devt(disk), ENTROPY_BITS(&input_pool));
}
#endif
@@ -903,58 +807,30 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
* from the primary pool to the secondary extraction pool. We make
* sure we pull enough for a 'catastrophic reseed'.
*/
-static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes);
static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
{
- if (r->limit == 0 && random_min_urandom_seed) {
- unsigned long now = jiffies;
-
- if (time_before(now,
- r->last_pulled + random_min_urandom_seed * HZ))
- return;
- r->last_pulled = now;
- }
- if (r->pull &&
- r->entropy_count < (nbytes << (ENTROPY_SHIFT + 3)) &&
- r->entropy_count < r->poolinfo->poolfracbits)
- _xfer_secondary_pool(r, nbytes);
-}
-
-static void _xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
-{
__u32 tmp[OUTPUT_POOL_WORDS];
- /* For /dev/random's pool, always leave two wakeup worth's BITS */
- int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
- int bytes = nbytes;
-
- /* pull at least as many as BYTES as wakeup BITS */
- bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
- /* but never more than the buffer size */
- bytes = min_t(int, bytes, sizeof(tmp));
-
- trace_xfer_secondary_pool(r->name, bytes * 8, nbytes * 8,
- ENTROPY_BITS(r), ENTROPY_BITS(r->pull));
- bytes = extract_entropy(r->pull, tmp, bytes,
- random_read_wakeup_thresh / 8, rsvd);
- mix_pool_bytes(r, tmp, bytes, NULL);
- credit_entropy_bits(r, bytes*8);
-}
-
-/*
- * Used as a workqueue function so that when the input pool is getting
- * full, we can "spill over" some entropy to the output pools. That
- * way the output pools can store some of the excess entropy instead
- * of letting it go to waste.
- */
-static void push_to_pool(struct work_struct *work)
-{
- struct entropy_store *r = container_of(work, struct entropy_store,
- push_work);
- BUG_ON(!r);
- _xfer_secondary_pool(r, random_read_wakeup_thresh/8);
- trace_push_to_pool(r->name, r->entropy_count >> ENTROPY_SHIFT,
- r->pull->entropy_count >> ENTROPY_SHIFT);
+ if (r->pull && r->entropy_count < nbytes * 8 &&
+ r->entropy_count < r->poolinfo->POOLBITS) {
+ /* If we're limited, always leave two wakeup worth's BITS */
+ int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
+ int bytes = nbytes;
+
+ /* pull at least as many as BYTES as wakeup BITS */
+ bytes = max_t(int, bytes, random_read_wakeup_thresh / 8);
+ /* but never more than the buffer size */
+ bytes = min_t(int, bytes, sizeof(tmp));
+
+ DEBUG_ENT("going to reseed %s with %d bits "
+ "(%zu of %d requested)\n",
+ r->name, bytes * 8, nbytes * 8, r->entropy_count);
+
+ bytes = extract_entropy(r->pull, tmp, bytes,
+ random_read_wakeup_thresh / 8, rsvd);
+ mix_pool_bytes(r, tmp, bytes, NULL);
+ credit_entropy_bits(r, bytes*8);
+ }
}
/*
@@ -974,48 +850,50 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min,
{
unsigned long flags;
int wakeup_write = 0;
- int have_bytes;
- int entropy_count, orig;
- size_t ibytes;
/* Hold lock while accounting */
spin_lock_irqsave(&r->lock, flags);
- BUG_ON(r->entropy_count > r->poolinfo->poolfracbits);
+ BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
+ DEBUG_ENT("trying to extract %zu bits from %s\n",
+ nbytes * 8, r->name);
/* Can we pull enough? */
-retry:
- entropy_count = orig = ACCESS_ONCE(r->entropy_count);
- have_bytes = entropy_count >> (ENTROPY_SHIFT + 3);
- ibytes = nbytes;
- if (have_bytes < min + reserved) {
- ibytes = 0;
+ if (r->entropy_count / 8 < min + reserved) {
+ nbytes = 0;
} else {
+ int entropy_count, orig;
+retry:
+ entropy_count = orig = ACCESS_ONCE(r->entropy_count);
/* If limited, never pull more than available */
- if (r->limit && ibytes + reserved >= have_bytes)
- ibytes = have_bytes - reserved;
-
- if (have_bytes >= ibytes + reserved)
- entropy_count -= ibytes << (ENTROPY_SHIFT + 3);
- else
- entropy_count = reserved << (ENTROPY_SHIFT + 3);
-
- if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
- goto retry;
+ if (r->limit && nbytes + reserved >= entropy_count / 8)
+ nbytes = entropy_count/8 - reserved;
+
+ if (entropy_count / 8 >= nbytes + reserved) {
+ entropy_count -= nbytes*8;
+ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ goto retry;
+ } else {
+ entropy_count = reserved;
+ if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig)
+ goto retry;
+ }
- if ((r->entropy_count >> ENTROPY_SHIFT)
- < random_write_wakeup_thresh)
+ if (entropy_count < random_write_wakeup_thresh)
wakeup_write = 1;
}
+
+ DEBUG_ENT("debiting %zu entropy credits from %s%s\n",
+ nbytes * 8, r->name, r->limit ? "" : " (unlimited)");
+
spin_unlock_irqrestore(&r->lock, flags);
- trace_debit_entropy(r->name, 8 * ibytes);
if (wakeup_write) {
wake_up_interruptible(&random_write_wait);
kill_fasync(&fasync, SIGIO, POLL_OUT);
}
- return ibytes;
+ return nbytes;
}
static void extract_buf(struct entropy_store *r, __u8 *out)
@@ -1023,7 +901,7 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
int i;
union {
__u32 w[5];
- unsigned long l[LONGS(20)];
+ unsigned long l[LONGS(EXTRACT_SIZE)];
} hash;
__u32 workspace[SHA_WORKSPACE_WORDS];
__u8 extract[64];
@@ -1036,17 +914,6 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
sha_transform(hash.w, (__u8 *)(r->pool + i), workspace);
/*
- * If we have a architectural hardware random number
- * generator, mix that in, too.
- */
- for (i = 0; i < LONGS(20); i++) {
- unsigned long v;
- if (!arch_get_random_long(&v))
- break;
- hash.l[i] ^= v;
- }
-
- /*
* We mix the hash back into the pool to prevent backtracking
* attacks (where the attacker knows the state of the pool
* plus the current outputs, and attempts to find previous
@@ -1075,6 +942,17 @@ static void extract_buf(struct entropy_store *r, __u8 *out)
hash.w[1] ^= hash.w[4];
hash.w[2] ^= rol32(hash.w[2], 16);
+ /*
+ * If we have a architectural hardware random number
+ * generator, mix that in, too.
+ */
+ for (i = 0; i < LONGS(EXTRACT_SIZE); i++) {
+ unsigned long v;
+ if (!arch_get_random_long(&v))
+ break;
+ hash.l[i] ^= v;
+ }
+
memcpy(out, &hash, EXTRACT_SIZE);
memset(&hash, 0, sizeof(hash));
}
@@ -1090,10 +968,10 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
if (fips_enabled) {
spin_lock_irqsave(&r->lock, flags);
if (!r->last_data_init) {
- r->last_data_init = 1;
+ r->last_data_init = true;
spin_unlock_irqrestore(&r->lock, flags);
trace_extract_entropy(r->name, EXTRACT_SIZE,
- ENTROPY_BITS(r), _RET_IP_);
+ r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, EXTRACT_SIZE);
extract_buf(r, tmp);
spin_lock_irqsave(&r->lock, flags);
@@ -1102,7 +980,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf,
spin_unlock_irqrestore(&r->lock, flags);
}
- trace_extract_entropy(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
+ trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, min, reserved);
@@ -1135,7 +1013,7 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
ssize_t ret = 0, i;
__u8 tmp[EXTRACT_SIZE];
- trace_extract_entropy_user(r->name, nbytes, ENTROPY_BITS(r), _RET_IP_);
+ trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_);
xfer_secondary_pool(r, nbytes);
nbytes = account(r, nbytes, 0, 0);
@@ -1175,14 +1053,6 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
*/
void get_random_bytes(void *buf, int nbytes)
{
-#if DEBUG_RANDOM_BOOT > 0
- if (unlikely(nonblocking_pool.initialized == 0))
- printk(KERN_NOTICE "random: %pF get_random_bytes called "
- "with %d bits of entropy available\n",
- (void *) _RET_IP_,
- nonblocking_pool.entropy_total);
-#endif
- trace_get_random_bytes(nbytes, _RET_IP_);
extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
}
EXPORT_SYMBOL(get_random_bytes);
@@ -1201,7 +1071,7 @@ void get_random_bytes_arch(void *buf, int nbytes)
{
char *p = buf;
- trace_get_random_bytes_arch(nbytes, _RET_IP_);
+ trace_get_random_bytes(nbytes, _RET_IP_);
while (nbytes) {
unsigned long v;
int chunk = min(nbytes, (int)sizeof(unsigned long));
@@ -1235,11 +1105,13 @@ static void init_std_data(struct entropy_store *r)
ktime_t now = ktime_get_real();
unsigned long rv;
- r->last_pulled = jiffies;
+ r->entropy_count = 0;
+ r->entropy_total = 0;
+ r->last_data_init = false;
mix_pool_bytes(r, &now, sizeof(now), NULL);
- for (i = r->poolinfo->poolbytes; i > 0; i -= sizeof(rv)) {
+ for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) {
if (!arch_get_random_long(&rv))
- rv = random_get_entropy();
+ break;
mix_pool_bytes(r, &rv, sizeof(rv), NULL);
}
mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL);
@@ -1262,7 +1134,7 @@ static int rand_initialize(void)
init_std_data(&nonblocking_pool);
return 0;
}
-early_initcall(rand_initialize);
+module_init(rand_initialize);
#ifdef CONFIG_BLOCK
void rand_initialize_disk(struct gendisk *disk)
@@ -1274,10 +1146,8 @@ void rand_initialize_disk(struct gendisk *disk)
* source.
*/
state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL);
- if (state) {
- state->last_time = INITIAL_JIFFIES;
+ if (state)
disk->random = state;
- }
}
#endif
@@ -1294,6 +1164,8 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
if (n > SEC_XFER_SIZE)
n = SEC_XFER_SIZE;
+ DEBUG_ENT("reading %zu bits\n", n*8);
+
n = extract_entropy_user(&blocking_pool, buf, n);
if (n < 0) {
@@ -1301,9 +1173,8 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
break;
}
- trace_random_read(n*8, (nbytes-n)*8,
- ENTROPY_BITS(&blocking_pool),
- ENTROPY_BITS(&input_pool));
+ DEBUG_ENT("read got %zd bits (%zd still needed)\n",
+ n*8, (nbytes-n)*8);
if (n == 0) {
if (file->f_flags & O_NONBLOCK) {
@@ -1311,9 +1182,13 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
break;
}
+ DEBUG_ENT("sleeping?\n");
+
wait_event_interruptible(random_read_wait,
- ENTROPY_BITS(&input_pool) >=
- random_read_wakeup_thresh);
+ input_pool.entropy_count >=
+ random_read_wakeup_thresh);
+
+ DEBUG_ENT("awake\n");
if (signal_pending(current)) {
retval = -ERESTARTSYS;
@@ -1336,18 +1211,7 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
static ssize_t
urandom_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
- int ret;
-
- if (unlikely(nonblocking_pool.initialized == 0))
- printk_once(KERN_NOTICE "random: %s urandom read "
- "with %d bits of entropy available\n",
- current->comm, nonblocking_pool.entropy_total);
-
- ret = extract_entropy_user(&nonblocking_pool, buf, nbytes);
-
- trace_urandom_read(8 * nbytes, ENTROPY_BITS(&nonblocking_pool),
- ENTROPY_BITS(&input_pool));
- return ret;
+ return extract_entropy_user(&nonblocking_pool, buf, nbytes);
}
static unsigned int
@@ -1358,9 +1222,9 @@ random_poll(struct file *file, poll_table * wait)
poll_wait(file, &random_read_wait, wait);
poll_wait(file, &random_write_wait, wait);
mask = 0;
- if (ENTROPY_BITS(&input_pool) >= random_read_wakeup_thresh)
+ if (input_pool.entropy_count >= random_read_wakeup_thresh)
mask |= POLLIN | POLLRDNORM;
- if (ENTROPY_BITS(&input_pool) < random_write_wakeup_thresh)
+ if (input_pool.entropy_count < random_write_wakeup_thresh)
mask |= POLLOUT | POLLWRNORM;
return mask;
}
@@ -1411,8 +1275,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
switch (cmd) {
case RNDGETENTCNT:
/* inherently racy, no point locking */
- ent_count = ENTROPY_BITS(&input_pool);
- if (put_user(ent_count, p))
+ if (put_user(input_pool.entropy_count, p))
return -EFAULT;
return 0;
case RNDADDTOENTCNT:
@@ -1420,7 +1283,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return -EPERM;
if (get_user(ent_count, p))
return -EFAULT;
- credit_entropy_bits_safe(&input_pool, ent_count);
+ credit_entropy_bits(&input_pool, ent_count);
return 0;
case RNDADDENTROPY:
if (!capable(CAP_SYS_ADMIN))
@@ -1435,19 +1298,14 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
size);
if (retval < 0)
return retval;
- credit_entropy_bits_safe(&input_pool, ent_count);
+ credit_entropy_bits(&input_pool, ent_count);
return 0;
case RNDZAPENTCNT:
case RNDCLEARPOOL:
- /*
- * Clear the entropy pool counters. We no longer clear
- * the entropy pool, as that's silly.
- */
+ /* Clear the entropy pool counters. */
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- input_pool.entropy_count = 0;
- nonblocking_pool.entropy_count = 0;
- blocking_pool.entropy_count = 0;
+ rand_initialize();
return 0;
default:
return -EINVAL;
@@ -1547,23 +1405,6 @@ static int proc_do_uuid(struct ctl_table *table, int write,
return proc_dostring(&fake_table, write, buffer, lenp, ppos);
}
-/*
- * Return entropy available scaled to integral bits
- */
-static int proc_do_entropy(ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- ctl_table fake_table;
- int entropy_count;
-
- entropy_count = *(int *)table->data >> ENTROPY_SHIFT;
-
- fake_table.data = &entropy_count;
- fake_table.maxlen = sizeof(entropy_count);
-
- return proc_dointvec(&fake_table, write, buffer, lenp, ppos);
-}
-
static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
extern struct ctl_table random_table[];
struct ctl_table random_table[] = {
@@ -1578,7 +1419,7 @@ struct ctl_table random_table[] = {
.procname = "entropy_avail",
.maxlen = sizeof(int),
.mode = 0444,
- .proc_handler = proc_do_entropy,
+ .proc_handler = proc_dointvec,
.data = &input_pool.entropy_count,
},
{
@@ -1600,13 +1441,6 @@ struct ctl_table random_table[] = {
.extra2 = &max_write_thresh,
},
{
- .procname = "urandom_min_reseed_secs",
- .data = &random_min_urandom_seed,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
.procname = "boot_id",
.data = &sysctl_bootid,
.maxlen = 16,
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 3525996..c0cbbd4 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -227,7 +227,7 @@ static inline unsigned char rtc_is_updating(void)
#ifdef RTC_IRQ
/*
- * A very tiny interrupt handler. It runs with interrupts disabled,
+ * A very tiny interrupt handler. It runs with IRQF_DISABLED set,
* but there is possibility of conflicting with the set_rtc_mmss()
* call (the rtc irq and the timer irq can easily run at the same
* time in two different CPUs). So we need to serialize
@@ -1040,7 +1040,8 @@ no_irq:
rtc_int_handler_ptr = rtc_interrupt;
}
- if (request_irq(RTC_IRQ, rtc_int_handler_ptr, 0, "rtc", NULL)) {
+ if (request_irq(RTC_IRQ, rtc_int_handler_ptr, IRQF_DISABLED,
+ "rtc", NULL)) {
/* Yeah right, seeing as irq 8 doesn't even hit the bus. */
rtc_has_irq = 0;
printk(KERN_ERR "rtc: IRQ %d is not free.\n", RTC_IRQ);
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index 8bab592..5816b39 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -108,7 +108,8 @@ scdrv_open(struct inode *inode, struct file *file)
/* hook this subchannel up to the system controller interrupt */
mutex_lock(&scdrv_mutex);
rv = request_irq(SGI_UART_VECTOR, scdrv_interrupt,
- IRQF_SHARED, SYSCTL_BASENAME, sd);
+ IRQF_SHARED | IRQF_DISABLED,
+ SYSCTL_BASENAME, sd);
if (rv) {
ia64_sn_irtr_close(sd->sd_nasid, sd->sd_subch);
kfree(sd);
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index 59bcefd..ee15694 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -292,7 +292,8 @@ scdrv_event_init(struct sysctl_data_s *scd)
/* hook event subchannel up to the system controller interrupt */
rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt,
- IRQF_SHARED, "system controller events", event_sd);
+ IRQF_SHARED | IRQF_DISABLED,
+ "system controller events", event_sd);
if (rv) {
printk(KERN_WARNING "%s: irq request failed (%d)\n",
__func__, rv);
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c
index 100cd1d..e95e0ab 100644
--- a/drivers/char/tlclk.c
+++ b/drivers/char/tlclk.c
@@ -222,7 +222,7 @@ static int tlclk_open(struct inode *inode, struct file *filp)
/* This device is wired through the FPGA IO space of the ATCA blade
* we can't share this IRQ */
result = request_irq(telclk_interrupt, &tlclk_interrupt,
- 0, "telco_clock", tlclk_interrupt);
+ IRQF_DISABLED, "telco_clock", tlclk_interrupt);
if (result == -EBUSY)
printk(KERN_ERR "tlclk: Interrupt can't be reserved.\n");
else
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 1a65838..94c0c74 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -33,15 +33,6 @@ config TCG_TIS
from within Linux. To compile this driver as a module, choose
M here; the module will be called tpm_tis.
-config TCG_TIS_I2C_ATMEL
- tristate "TPM Interface Specification 1.2 Interface (I2C - Atmel)"
- depends on I2C
- ---help---
- If you have an Atmel I2C TPM security chip say Yes and it will be
- accessible from within Linux.
- To compile this driver as a module, choose M here; the module will
- be called tpm_tis_i2c_atmel.
-
config TCG_TIS_I2C_INFINEON
tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)"
depends on I2C
@@ -51,17 +42,7 @@ config TCG_TIS_I2C_INFINEON
Specification 0.20 say Yes and it will be accessible from within
Linux.
To compile this driver as a module, choose M here; the module
- will be called tpm_i2c_infineon.
-
-config TCG_TIS_I2C_NUVOTON
- tristate "TPM Interface Specification 1.2 Interface (I2C - Nuvoton)"
- depends on I2C
- ---help---
- If you have a TPM security chip with an I2C interface from
- Nuvoton Technology Corp. say Yes and it will be accessible
- from within Linux.
- To compile this driver as a module, choose M here; the module
- will be called tpm_i2c_nuvoton.
+ will be called tpm_tis_i2c_infineon.
config TCG_NSC
tristate "National Semiconductor TPM Interface"
@@ -101,14 +82,14 @@ config TCG_IBMVTPM
as a module, choose M here; the module will be called tpm_ibmvtpm.
config TCG_ST33_I2C
- tristate "STMicroelectronics ST33 I2C TPM"
- depends on I2C
- depends on GPIOLIB
- ---help---
- If you have a TPM security chip from STMicroelectronics working with
- an I2C bus say Yes and it will be accessible from within Linux.
- To compile this driver as a module, choose M here; the module will be
- called tpm_stm_st33_i2c.
+ tristate "STMicroelectronics ST33 I2C TPM"
+ depends on I2C
+ depends on GPIOLIB
+ ---help---
+ If you have a TPM security chip from STMicroelectronics working with
+ an I2C bus say Yes and it will be accessible from within Linux.
+ To compile this driver as a module, choose M here; the module will be
+ called tpm_stm_st33_i2c.
config TCG_XEN
tristate "XEN TPM Interface"
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index b80a400..eb41ff9 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -2,20 +2,17 @@
# Makefile for the kernel tpm device drivers.
#
obj-$(CONFIG_TCG_TPM) += tpm.o
-tpm-y := tpm-interface.o
-tpm-$(CONFIG_ACPI) += tpm_ppi.o
-
ifdef CONFIG_ACPI
- tpm-y += tpm_eventlog.o tpm_acpi.o
+ obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+ tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o
else
ifdef CONFIG_TCG_IBMVTPM
- tpm-y += tpm_eventlog.o tpm_of.o
+ obj-$(CONFIG_TCG_TPM) += tpm_bios.o
+ tpm_bios-objs += tpm_eventlog.o tpm_of.o
endif
endif
obj-$(CONFIG_TCG_TIS) += tpm_tis.o
-obj-$(CONFIG_TCG_TIS_I2C_ATMEL) += tpm_i2c_atmel.o
obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o
-obj-$(CONFIG_TCG_TIS_I2C_NUVOTON) += tpm_i2c_nuvoton.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm.c
index 6ae41d3..e3c974a 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm.c
@@ -10,13 +10,13 @@
* Maintained by: <tpmdd-devel@lists.sourceforge.net>
*
* Device driver for TCG/TCPA TPM (trusted platform module).
- * Specifications at www.trustedcomputinggroup.org
+ * Specifications at www.trustedcomputinggroup.org
*
* 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.
- *
+ *
* Note, the TPM chip is not interrupt driven (only polling)
* and can have very long timeouts (minutes!). Hence the unusual
* calls to msleep.
@@ -371,14 +371,13 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
return -ENODATA;
if (count > bufsiz) {
dev_err(chip->dev,
- "invalid count value %x %zx\n", count, bufsiz);
+ "invalid count value %x %zx \n", count, bufsiz);
return -E2BIG;
}
mutex_lock(&chip->tpm_mutex);
- rc = chip->vendor.send(chip, (u8 *) buf, count);
- if (rc < 0) {
+ if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
dev_err(chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
@@ -445,7 +444,7 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
{
int err;
- len = tpm_transmit(chip, (u8 *) cmd, len);
+ len = tpm_transmit(chip,(u8 *) cmd, len);
if (len < 0)
return len;
else if (len < TPM_HEADER_SIZE)
@@ -659,7 +658,7 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
return rc;
}
-ssize_t tpm_show_enabled(struct device *dev, struct device_attribute *attr,
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
char *buf)
{
cap_t cap;
@@ -675,7 +674,7 @@ ssize_t tpm_show_enabled(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_show_enabled);
-ssize_t tpm_show_active(struct device *dev, struct device_attribute *attr,
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
char *buf)
{
cap_t cap;
@@ -691,7 +690,7 @@ ssize_t tpm_show_active(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_show_active);
-ssize_t tpm_show_owned(struct device *dev, struct device_attribute *attr,
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
char *buf)
{
cap_t cap;
@@ -707,8 +706,8 @@ ssize_t tpm_show_owned(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_show_owned);
-ssize_t tpm_show_temp_deactivated(struct device *dev,
- struct device_attribute *attr, char *buf)
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+ struct device_attribute * attr, char *buf)
{
cap_t cap;
ssize_t rc;
@@ -770,10 +769,10 @@ static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
/**
* tpm_pcr_read - read a pcr value
- * @chip_num: tpm idx # or ANY
+ * @chip_num: tpm idx # or ANY
* @pcr_idx: pcr idx to retrieve
- * @res_buf: TPM_PCR value
- * size of res_buf is 20 bytes (or NULL if you don't care)
+ * @res_buf: TPM_PCR value
+ * size of res_buf is 20 bytes (or NULL if you don't care)
*
* The TPM driver should be built-in, but for whatever reason it
* isn't, protect against the chip disappearing, by incrementing
@@ -795,9 +794,9 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
/**
* tpm_pcr_extend - extend pcr value with hash
- * @chip_num: tpm idx # or AN&
+ * @chip_num: tpm idx # or AN&
* @pcr_idx: pcr idx to extend
- * @hash: hash value used to extend pcr value
+ * @hash: hash value used to extend pcr value
*
* The TPM driver should be built-in, but for whatever reason it
* isn't, protect against the chip disappearing, by incrementing
@@ -848,7 +847,8 @@ int tpm_do_selftest(struct tpm_chip *chip)
unsigned long duration;
struct tpm_cmd_t cmd;
- duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);
+ duration = tpm_calc_ordinal_duration(chip,
+ TPM_ORD_CONTINUE_SELFTEST);
loops = jiffies_to_msecs(duration) / delay_msec;
@@ -965,12 +965,12 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
if (err)
goto out;
- /*
+ /*
ignore header 10 bytes
algorithm 32 bits (1 == RSA )
encscheme 16 bits
sigscheme 16 bits
- parameters (RSA 12->bytes: keybit, #primes, expbit)
+ parameters (RSA 12->bytes: keybit, #primes, expbit)
keylenbytes 32 bits
256 byte modulus
ignore checksum 20 bytes
@@ -1020,33 +1020,43 @@ ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
str += sprintf(str, "Manufacturer: 0x%x\n",
be32_to_cpu(cap.manufacturer_id));
- /* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
+ rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
+ "attempting to determine the 1.1 version");
+ if (rc)
+ return 0;
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ cap.tpm_version.Major, cap.tpm_version.Minor,
+ cap.tpm_version.revMajor, cap.tpm_version.revMinor);
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps);
+
+ssize_t tpm_show_caps_1_2(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ cap_t cap;
+ ssize_t rc;
+ char *str = buf;
+
+ rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap,
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(cap.manufacturer_id));
rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap,
"attempting to determine the 1.2 version");
- if (!rc) {
- str += sprintf(str,
- "TCG version: %d.%d\nFirmware version: %d.%d\n",
- cap.tpm_version_1_2.Major,
- cap.tpm_version_1_2.Minor,
- cap.tpm_version_1_2.revMajor,
- cap.tpm_version_1_2.revMinor);
- } else {
- /* Otherwise just use TPM_STRUCT_VER */
- rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap,
- "attempting to determine the 1.1 version");
- if (rc)
- return 0;
- str += sprintf(str,
- "TCG version: %d.%d\nFirmware version: %d.%d\n",
- cap.tpm_version.Major,
- cap.tpm_version.Minor,
- cap.tpm_version.revMajor,
- cap.tpm_version.revMinor);
- }
-
+ if (rc)
+ return 0;
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor,
+ cap.tpm_version_1_2.revMajor,
+ cap.tpm_version_1_2.revMinor);
return str - buf;
}
-EXPORT_SYMBOL_GPL(tpm_show_caps);
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -1092,8 +1102,8 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
-static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
- bool check_cancel, bool *canceled)
+static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, bool check_cancel,
+ bool *canceled)
{
u8 status = chip->vendor.status(chip);
@@ -1160,25 +1170,38 @@ EXPORT_SYMBOL_GPL(wait_for_tpm_stat);
*/
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);
+ int minor = iminor(inode);
+ struct tpm_chip *chip = NULL, *pos;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
+ if (pos->vendor.miscdev.minor == minor) {
+ chip = pos;
+ get_device(chip->dev);
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ if (!chip)
+ return -ENODEV;
if (test_and_set_bit(0, &chip->is_open)) {
dev_dbg(chip->dev, "Another process owns this TPM\n");
+ put_device(chip->dev);
return -EBUSY;
}
chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
if (chip->data_buffer == NULL) {
clear_bit(0, &chip->is_open);
+ put_device(chip->dev);
return -ENOMEM;
}
atomic_set(&chip->data_pending, 0);
file->private_data = chip;
- get_device(chip->dev);
return 0;
}
EXPORT_SYMBOL_GPL(tpm_open);
@@ -1440,6 +1463,7 @@ void tpm_dev_vendor_release(struct tpm_chip *chip)
chip->vendor.release(chip->dev);
clear_bit(chip->dev_num, dev_mask);
+ kfree(chip->vendor.miscdev.name);
}
EXPORT_SYMBOL_GPL(tpm_dev_vendor_release);
@@ -1463,7 +1487,7 @@ void tpm_dev_release(struct device *dev)
EXPORT_SYMBOL_GPL(tpm_dev_release);
/*
- * Called from tpm_<specific>.c probe function only for devices
+ * Called from tpm_<specific>.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
@@ -1472,13 +1496,17 @@ EXPORT_SYMBOL_GPL(tpm_dev_release);
struct tpm_chip *tpm_register_hardware(struct device *dev,
const struct tpm_vendor_specific *entry)
{
+#define DEVNAME_SIZE 7
+
+ char *devname;
struct tpm_chip *chip;
/* Driver specific per-device data */
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
- if (chip == NULL)
- return NULL;
+ if (chip == NULL || devname == NULL)
+ goto out_free;
mutex_init(&chip->buffer_mutex);
mutex_init(&chip->tpm_mutex);
@@ -1503,9 +1531,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
set_bit(chip->dev_num, dev_mask);
- scnprintf(chip->devname, sizeof(chip->devname), "%s%d", "tpm",
- chip->dev_num);
- chip->vendor.miscdev.name = chip->devname;
+ scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
+ chip->vendor.miscdev.name = devname;
chip->vendor.miscdev.parent = dev;
chip->dev = get_device(dev);
@@ -1531,7 +1558,7 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
goto put_device;
}
- chip->bios_dir = tpm_bios_log_setup(chip->devname);
+ chip->bios_dir = tpm_bios_log_setup(devname);
/* Make chip available */
spin_lock(&driver_lock);
@@ -1544,6 +1571,7 @@ put_device:
put_device(chip->dev);
out_free:
kfree(chip);
+ kfree(devname);
return NULL;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f328478..a7bfc17 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -59,6 +59,8 @@ extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+ char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
@@ -120,7 +122,6 @@ struct tpm_chip {
struct device *dev; /* Device stuff */
int dev_num; /* /dev/tpm# */
- char devname[7];
unsigned long is_open; /* only one allowed */
int time_expired;
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index c9a528d..99d6820 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -202,7 +202,7 @@ static int __init init_atmel(void)
have_region =
(atmel_request_region
- (base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
+ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
pdev = platform_device_register_simple("tpm_atmel", -1, NULL, 0);
if (IS_ERR(pdev)) {
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c
index 59f7cb2..84ddc55 100644
--- a/drivers/char/tpm/tpm_eventlog.c
+++ b/drivers/char/tpm/tpm_eventlog.c
@@ -406,6 +406,7 @@ out_tpm:
out:
return NULL;
}
+EXPORT_SYMBOL_GPL(tpm_bios_log_setup);
void tpm_bios_log_teardown(struct dentry **lst)
{
@@ -414,3 +415,5 @@ void tpm_bios_log_teardown(struct dentry **lst)
for (i = 0; i < 3; i++)
securityfs_remove(lst[i]);
}
+EXPORT_SYMBOL_GPL(tpm_bios_log_teardown);
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_i2c_atmel.c b/drivers/char/tpm/tpm_i2c_atmel.c
deleted file mode 100644
index c3cd7fe..0000000
--- a/drivers/char/tpm/tpm_i2c_atmel.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * ATMEL I2C TPM AT97SC3204T
- *
- * Copyright (C) 2012 V Lab Technologies
- * Teddy Reed <teddy@prosauce.org>
- * Copyright (C) 2013, Obsidian Research Corp.
- * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
- * Device driver for ATMEL I2C TPMs.
- *
- * Teddy Reed determined the basic I2C command flow, unlike other I2C TPM
- * devices the raw TCG formatted TPM command data is written via I2C and then
- * raw TCG formatted TPM command data is returned via I2C.
- *
- * TGC status/locality/etc functions seen in the LPC implementation do not
- * seem to be present.
- *
- * 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, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/>.
- */
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include "tpm.h"
-
-#define I2C_DRIVER_NAME "tpm_i2c_atmel"
-
-#define TPM_I2C_SHORT_TIMEOUT 750 /* ms */
-#define TPM_I2C_LONG_TIMEOUT 2000 /* 2 sec */
-
-#define ATMEL_STS_OK 1
-
-struct priv_data {
- size_t len;
- /* This is the amount we read on the first try. 25 was chosen to fit a
- * fair number of read responses in the buffer so a 2nd retry can be
- * avoided in small message cases. */
- u8 buffer[sizeof(struct tpm_output_header) + 25];
-};
-
-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);
- s32 status;
-
- priv->len = 0;
-
- if (len <= 2)
- return -EIO;
-
- status = i2c_master_send(client, buf, len);
-
- dev_dbg(chip->dev,
- "%s(buf=%*ph len=%0zx) -> sts=%d\n", __func__,
- (int)min_t(size_t, 64, len), buf, len, status);
- return status;
-}
-
-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 tpm_output_header *hdr =
- (struct tpm_output_header *)priv->buffer;
- u32 expected_len;
- int rc;
-
- if (priv->len == 0)
- return -EIO;
-
- /* Get the message size from the message header, if we didn't get the
- * whole message in read_status then we need to re-read the
- * message. */
- expected_len = be32_to_cpu(hdr->length);
- if (expected_len > count)
- return -ENOMEM;
-
- if (priv->len >= expected_len) {
- dev_dbg(chip->dev,
- "%s early(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
- (int)min_t(size_t, 64, expected_len), buf, count,
- expected_len);
- memcpy(buf, priv->buffer, expected_len);
- return expected_len;
- }
-
- rc = i2c_master_recv(client, buf, expected_len);
- dev_dbg(chip->dev,
- "%s reread(buf=%*ph count=%0zx) -> ret=%d\n", __func__,
- (int)min_t(size_t, 64, expected_len), buf, count,
- expected_len);
- return rc;
-}
-
-static void i2c_atmel_cancel(struct tpm_chip *chip)
-{
- dev_err(chip->dev, "TPM operation cancellation was requested, but is not supported");
-}
-
-static u8 i2c_atmel_read_status(struct tpm_chip *chip)
-{
- struct priv_data *priv = chip->vendor.priv;
- struct i2c_client *client = to_i2c_client(chip->dev);
- int rc;
-
- /* The TPM fails the I2C read until it is ready, so we do the entire
- * transfer here and buffer it locally. This way the common code can
- * properly handle the timeouts. */
- priv->len = 0;
- memset(priv->buffer, 0, sizeof(priv->buffer));
-
-
- /* 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,
- "%s: sts=%d", __func__, rc);
- if (rc <= 0)
- return 0;
-
- priv->len = rc;
-
- return ATMEL_STS_OK;
-}
-
-static const struct file_operations i2c_atmel_ops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .open = tpm_open,
- .read = tpm_read,
- .write = tpm_write,
- .release = tpm_release,
-};
-
-static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
-static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
-static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
-static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
-static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
-static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
-static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
-static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
-static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
-
-static struct attribute *i2c_atmel_attrs[] = {
- &dev_attr_pubek.attr,
- &dev_attr_pcrs.attr,
- &dev_attr_enabled.attr,
- &dev_attr_active.attr,
- &dev_attr_owned.attr,
- &dev_attr_temp_deactivated.attr,
- &dev_attr_caps.attr,
- &dev_attr_cancel.attr,
- &dev_attr_durations.attr,
- &dev_attr_timeouts.attr,
- NULL,
-};
-
-static struct attribute_group i2c_atmel_attr_grp = {
- .attrs = i2c_atmel_attrs
-};
-
-static bool i2c_atmel_req_canceled(struct tpm_chip *chip, u8 status)
-{
- return 0;
-}
-
-static const struct tpm_vendor_specific i2c_atmel = {
- .status = i2c_atmel_read_status,
- .recv = i2c_atmel_recv,
- .send = i2c_atmel_send,
- .cancel = i2c_atmel_cancel,
- .req_complete_mask = ATMEL_STS_OK,
- .req_complete_val = ATMEL_STS_OK,
- .req_canceled = i2c_atmel_req_canceled,
- .attr_group = &i2c_atmel_attr_grp,
- .miscdev.fops = &i2c_atmel_ops,
-};
-
-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->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
- GFP_KERNEL);
-
- /* Default timeouts */
- chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
- chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
- chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
- chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
- chip->vendor.irq = 0;
-
- /* 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;
- }
-
- return 0;
-
-out_err:
- tpm_dev_vendor_release(chip);
- tpm_remove_hardware(chip->dev);
- return rc;
-}
-
-static int i2c_atmel_remove(struct i2c_client *client)
-{
- struct device *dev = &(client->dev);
- struct tpm_chip *chip = dev_get_drvdata(dev);
-
- if (chip)
- tpm_dev_vendor_release(chip);
- tpm_remove_hardware(dev);
- kfree(chip);
- return 0;
-}
-
-static const struct i2c_device_id i2c_atmel_id[] = {
- {I2C_DRIVER_NAME, 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, i2c_atmel_id);
-
-#ifdef CONFIG_OF
-static const struct of_device_id i2c_atmel_of_match[] = {
- {.compatible = "atmel,at97sc3204t"},
- {},
-};
-MODULE_DEVICE_TABLE(of, i2c_atmel_of_match);
-#endif
-
-static SIMPLE_DEV_PM_OPS(i2c_atmel_pm_ops, tpm_pm_suspend, tpm_pm_resume);
-
-static struct i2c_driver i2c_atmel_driver = {
- .id_table = i2c_atmel_id,
- .probe = i2c_atmel_probe,
- .remove = i2c_atmel_remove,
- .driver = {
- .name = I2C_DRIVER_NAME,
- .owner = THIS_MODULE,
- .pm = &i2c_atmel_pm_ops,
- .of_match_table = of_match_ptr(i2c_atmel_of_match),
- },
-};
-
-module_i2c_driver(i2c_atmel_driver);
-
-MODULE_AUTHOR("Jason Gunthorpe <jgunthorpe@obsidianresearch.com>");
-MODULE_DESCRIPTION("Atmel TPM I2C Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c
index fefd2aa..b8735de 100644
--- a/drivers/char/tpm/tpm_i2c_infineon.c
+++ b/drivers/char/tpm/tpm_i2c_infineon.c
@@ -581,7 +581,7 @@ static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
@@ -685,6 +685,7 @@ out_vendor:
chip->dev->release = NULL;
chip->release = NULL;
tpm_dev.client = NULL;
+ dev_set_drvdata(chip->dev, chip);
out_err:
return rc;
}
@@ -765,6 +766,7 @@ static int tpm_tis_i2c_remove(struct i2c_client *client)
chip->dev->release = NULL;
chip->release = NULL;
tpm_dev.client = NULL;
+ dev_set_drvdata(chip->dev, chip);
return 0;
}
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
deleted file mode 100644
index 6276fea..0000000
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ /dev/null
@@ -1,710 +0,0 @@
-/******************************************************************************
- * Nuvoton TPM I2C Device Driver Interface for WPCT301/NPCT501,
- * based on the TCG TPM Interface Spec version 1.2.
- * Specifications at www.trustedcomputinggroup.org
- *
- * Copyright (C) 2011, Nuvoton Technology Corporation.
- * Dan Morav <dan.morav@nuvoton.com>
- * Copyright (C) 2013, Obsidian Research Corp.
- * Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
- *
- * 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, either version 2 of the License, or
- * (at your option) any later version.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/>.
- *
- * Nuvoton contact information: APC.Support@nuvoton.com
- *****************************************************************************/
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/wait.h>
-#include <linux/i2c.h>
-#include "tpm.h"
-
-/* I2C interface offsets */
-#define TPM_STS 0x00
-#define TPM_BURST_COUNT 0x01
-#define TPM_DATA_FIFO_W 0x20
-#define TPM_DATA_FIFO_R 0x40
-#define TPM_VID_DID_RID 0x60
-/* TPM command header size */
-#define TPM_HEADER_SIZE 10
-#define TPM_RETRY 5
-/*
- * I2C bus device maximum buffer size w/o counting I2C address or command
- * i.e. max size required for I2C write is 34 = addr, command, 32 bytes data
- */
-#define TPM_I2C_MAX_BUF_SIZE 32
-#define TPM_I2C_RETRY_COUNT 32
-#define TPM_I2C_BUS_DELAY 1 /* msec */
-#define TPM_I2C_RETRY_DELAY_SHORT 2 /* msec */
-#define TPM_I2C_RETRY_DELAY_LONG 10 /* msec */
-
-#define I2C_DRIVER_NAME "tpm_i2c_nuvoton"
-
-struct priv_data {
- unsigned int intrs;
-};
-
-static s32 i2c_nuvoton_read_buf(struct i2c_client *client, u8 offset, u8 size,
- u8 *data)
-{
- s32 status;
-
- status = i2c_smbus_read_i2c_block_data(client, offset, size, data);
- dev_dbg(&client->dev,
- "%s(offset=%u size=%u data=%*ph) -> sts=%d\n", __func__,
- offset, size, (int)size, data, status);
- return status;
-}
-
-static s32 i2c_nuvoton_write_buf(struct i2c_client *client, u8 offset, u8 size,
- u8 *data)
-{
- s32 status;
-
- status = i2c_smbus_write_i2c_block_data(client, offset, size, data);
- dev_dbg(&client->dev,
- "%s(offset=%u size=%u data=%*ph) -> sts=%d\n", __func__,
- offset, size, (int)size, data, status);
- return status;
-}
-
-#define TPM_STS_VALID 0x80
-#define TPM_STS_COMMAND_READY 0x40
-#define TPM_STS_GO 0x20
-#define TPM_STS_DATA_AVAIL 0x10
-#define TPM_STS_EXPECT 0x08
-#define TPM_STS_RESPONSE_RETRY 0x02
-#define TPM_STS_ERR_VAL 0x07 /* bit2...bit0 reads always 0 */
-
-#define TPM_I2C_SHORT_TIMEOUT 750 /* ms */
-#define TPM_I2C_LONG_TIMEOUT 2000 /* 2 sec */
-
-/* read TPM_STS register */
-static u8 i2c_nuvoton_read_status(struct tpm_chip *chip)
-{
- struct i2c_client *client = to_i2c_client(chip->dev);
- 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__,
- status);
- data = TPM_STS_ERR_VAL;
- }
-
- return data;
-}
-
-/* write byte to TPM_STS register */
-static s32 i2c_nuvoton_write_status(struct i2c_client *client, u8 data)
-{
- s32 status;
- int i;
-
- /* this causes the current command to be aborted */
- for (i = 0, status = -1; i < TPM_I2C_RETRY_COUNT && status < 0; i++) {
- status = i2c_nuvoton_write_buf(client, TPM_STS, 1, &data);
- msleep(TPM_I2C_BUS_DELAY);
- }
- return status;
-}
-
-/* write commandReady to TPM_STS register */
-static void i2c_nuvoton_ready(struct tpm_chip *chip)
-{
- struct i2c_client *client = to_i2c_client(chip->dev);
- 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,
- "%s() fail to write TPM_STS.commandReady\n", __func__);
-}
-
-/* read burstCount field from TPM_STS register
- * return -1 on fail to read */
-static int i2c_nuvoton_get_burstcount(struct i2c_client *client,
- struct tpm_chip *chip)
-{
- unsigned long stop = jiffies + chip->vendor.timeout_d;
- s32 status;
- int burst_count = -1;
- u8 data;
-
- /* wait for burstcount to be non-zero */
- do {
- /* in I2C burstCount is 1 byte */
- status = i2c_nuvoton_read_buf(client, TPM_BURST_COUNT, 1,
- &data);
- if (status > 0 && data > 0) {
- burst_count = min_t(u8, TPM_I2C_MAX_BUF_SIZE, data);
- break;
- }
- msleep(TPM_I2C_BUS_DELAY);
- } while (time_before(jiffies, stop));
-
- return burst_count;
-}
-
-/*
- * WPCT301/NPCT501 SINT# supports only dataAvail
- * any call to this function which is not waiting for dataAvail will
- * set queue to NULL to avoid waiting for interrupt
- */
-static bool i2c_nuvoton_check_status(struct tpm_chip *chip, u8 mask, u8 value)
-{
- u8 status = i2c_nuvoton_read_status(chip);
- return (status != TPM_STS_ERR_VAL) && ((status & mask) == value);
-}
-
-static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value,
- u32 timeout, wait_queue_head_t *queue)
-{
- if (chip->vendor.irq && queue) {
- s32 rc;
- DEFINE_WAIT(wait);
- struct priv_data *priv = chip->vendor.priv;
- unsigned int cur_intrs = priv->intrs;
-
- enable_irq(chip->vendor.irq);
- rc = wait_event_interruptible_timeout(*queue,
- cur_intrs != priv->intrs,
- timeout);
- if (rc > 0)
- return 0;
- /* At this point we know that the SINT pin is asserted, so we
- * do not need to do i2c_nuvoton_check_status */
- } else {
- unsigned long ten_msec, stop;
- bool status_valid;
-
- /* check current status */
- status_valid = i2c_nuvoton_check_status(chip, mask, value);
- if (status_valid)
- return 0;
-
- /* use polling to wait for the event */
- ten_msec = jiffies + msecs_to_jiffies(TPM_I2C_RETRY_DELAY_LONG);
- stop = jiffies + timeout;
- do {
- if (time_before(jiffies, ten_msec))
- msleep(TPM_I2C_RETRY_DELAY_SHORT);
- else
- msleep(TPM_I2C_RETRY_DELAY_LONG);
- status_valid = i2c_nuvoton_check_status(chip, mask,
- value);
- if (status_valid)
- return 0;
- } while (time_before(jiffies, stop));
- }
- dev_err(chip->dev, "%s(%02x, %02x) -> timeout\n", __func__, mask,
- value);
- return -ETIMEDOUT;
-}
-
-/* wait for dataAvail field to be set in the TPM_STS register */
-static int i2c_nuvoton_wait_for_data_avail(struct tpm_chip *chip, u32 timeout,
- wait_queue_head_t *queue)
-{
- return i2c_nuvoton_wait_for_stat(chip,
- TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- timeout, queue);
-}
-
-/* Read @count bytes into @buf from TPM_RD_FIFO register */
-static int i2c_nuvoton_recv_data(struct i2c_client *client,
- struct tpm_chip *chip, u8 *buf, size_t count)
-{
- s32 rc;
- int burst_count, bytes2read, size = 0;
-
- while (size < count &&
- i2c_nuvoton_wait_for_data_avail(chip,
- chip->vendor.timeout_c,
- &chip->vendor.read_queue) == 0) {
- burst_count = i2c_nuvoton_get_burstcount(client, chip);
- if (burst_count < 0) {
- dev_err(chip->dev,
- "%s() fail to read burstCount=%d\n", __func__,
- burst_count);
- return -EIO;
- }
- bytes2read = min_t(size_t, burst_count, count - size);
- rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_R,
- bytes2read, &buf[size]);
- if (rc < 0) {
- dev_err(chip->dev,
- "%s() fail on i2c_nuvoton_read_buf()=%d\n",
- __func__, rc);
- return -EIO;
- }
- dev_dbg(chip->dev, "%s(%d):", __func__, bytes2read);
- size += bytes2read;
- }
-
- return size;
-}
-
-/* Read TPM command results */
-static int i2c_nuvoton_recv(struct tpm_chip *chip, u8 *buf, size_t count)
-{
- struct device *dev = chip->dev;
- struct i2c_client *client = to_i2c_client(dev);
- s32 rc;
- int expected, status, burst_count, retries, size = 0;
-
- if (count < TPM_HEADER_SIZE) {
- i2c_nuvoton_ready(chip); /* return to idle */
- dev_err(dev, "%s() count < header size\n", __func__);
- return -EIO;
- }
- for (retries = 0; retries < TPM_RETRY; retries++) {
- if (retries > 0) {
- /* if this is not the first trial, set responseRetry */
- i2c_nuvoton_write_status(client,
- TPM_STS_RESPONSE_RETRY);
- }
- /*
- * read first available (> 10 bytes), including:
- * tag, paramsize, and result
- */
- status = i2c_nuvoton_wait_for_data_avail(
- chip, chip->vendor.timeout_c, &chip->vendor.read_queue);
- if (status != 0) {
- dev_err(dev, "%s() timeout on dataAvail\n", __func__);
- size = -ETIMEDOUT;
- continue;
- }
- burst_count = i2c_nuvoton_get_burstcount(client, chip);
- if (burst_count < 0) {
- dev_err(dev, "%s() fail to get burstCount\n", __func__);
- size = -EIO;
- continue;
- }
- size = i2c_nuvoton_recv_data(client, chip, buf,
- burst_count);
- if (size < TPM_HEADER_SIZE) {
- dev_err(dev, "%s() fail to read header\n", __func__);
- size = -EIO;
- continue;
- }
- /*
- * convert number of expected bytes field from big endian 32 bit
- * to machine native
- */
- expected = be32_to_cpu(*(__be32 *) (buf + 2));
- if (expected > count) {
- dev_err(dev, "%s() expected > count\n", __func__);
- size = -EIO;
- continue;
- }
- rc = i2c_nuvoton_recv_data(client, chip, &buf[size],
- expected - size);
- size += rc;
- if (rc < 0 || size < expected) {
- dev_err(dev, "%s() fail to read remainder of result\n",
- __func__);
- size = -EIO;
- continue;
- }
- if (i2c_nuvoton_wait_for_stat(
- chip, TPM_STS_VALID | TPM_STS_DATA_AVAIL,
- TPM_STS_VALID, chip->vendor.timeout_c,
- NULL)) {
- dev_err(dev, "%s() error left over data\n", __func__);
- size = -ETIMEDOUT;
- continue;
- }
- break;
- }
- i2c_nuvoton_ready(chip);
- dev_dbg(chip->dev, "%s() -> %d\n", __func__, size);
- return size;
-}
-
-/*
- * Send TPM command.
- *
- * 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 i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
-{
- struct device *dev = chip->dev;
- struct i2c_client *client = to_i2c_client(dev);
- u32 ordinal;
- size_t count = 0;
- int burst_count, bytes2write, retries, rc = -EIO;
-
- for (retries = 0; retries < TPM_RETRY; retries++) {
- i2c_nuvoton_ready(chip);
- if (i2c_nuvoton_wait_for_stat(chip, TPM_STS_COMMAND_READY,
- TPM_STS_COMMAND_READY,
- chip->vendor.timeout_b, NULL)) {
- dev_err(dev, "%s() timeout on commandReady\n",
- __func__);
- rc = -EIO;
- continue;
- }
- rc = 0;
- while (count < len - 1) {
- burst_count = i2c_nuvoton_get_burstcount(client,
- chip);
- if (burst_count < 0) {
- dev_err(dev, "%s() fail get burstCount\n",
- __func__);
- rc = -EIO;
- break;
- }
- bytes2write = min_t(size_t, burst_count,
- len - 1 - count);
- rc = i2c_nuvoton_write_buf(client, TPM_DATA_FIFO_W,
- bytes2write, &buf[count]);
- if (rc < 0) {
- dev_err(dev, "%s() fail i2cWriteBuf\n",
- __func__);
- break;
- }
- dev_dbg(dev, "%s(%d):", __func__, bytes2write);
- count += bytes2write;
- rc = i2c_nuvoton_wait_for_stat(chip,
- TPM_STS_VALID |
- TPM_STS_EXPECT,
- TPM_STS_VALID |
- TPM_STS_EXPECT,
- chip->vendor.timeout_c,
- NULL);
- if (rc < 0) {
- dev_err(dev, "%s() timeout on Expect\n",
- __func__);
- rc = -ETIMEDOUT;
- break;
- }
- }
- if (rc < 0)
- continue;
-
- /* write last byte */
- rc = i2c_nuvoton_write_buf(client, TPM_DATA_FIFO_W, 1,
- &buf[count]);
- if (rc < 0) {
- dev_err(dev, "%s() fail to write last byte\n",
- __func__);
- rc = -EIO;
- continue;
- }
- dev_dbg(dev, "%s(last): %02x", __func__, buf[count]);
- rc = i2c_nuvoton_wait_for_stat(chip,
- TPM_STS_VALID | TPM_STS_EXPECT,
- TPM_STS_VALID,
- chip->vendor.timeout_c, NULL);
- if (rc) {
- dev_err(dev, "%s() timeout on Expect to clear\n",
- __func__);
- rc = -ETIMEDOUT;
- continue;
- }
- break;
- }
- if (rc < 0) {
- /* retries == TPM_RETRY */
- i2c_nuvoton_ready(chip);
- return rc;
- }
- /* execute the TPM command */
- rc = i2c_nuvoton_write_status(client, TPM_STS_GO);
- if (rc < 0) {
- dev_err(dev, "%s() fail to write Go\n", __func__);
- i2c_nuvoton_ready(chip);
- return rc;
- }
- ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
- rc = i2c_nuvoton_wait_for_data_avail(chip,
- tpm_calc_ordinal_duration(chip,
- ordinal),
- &chip->vendor.read_queue);
- if (rc) {
- dev_err(dev, "%s() timeout command duration\n", __func__);
- i2c_nuvoton_ready(chip);
- return rc;
- }
-
- dev_dbg(dev, "%s() -> %zd\n", __func__, len);
- return len;
-}
-
-static bool i2c_nuvoton_req_canceled(struct tpm_chip *chip, u8 status)
-{
- return (status == TPM_STS_COMMAND_READY);
-}
-
-static const struct file_operations i2c_nuvoton_ops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .open = tpm_open,
- .read = tpm_read,
- .write = tpm_write,
- .release = tpm_release,
-};
-
-static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
-static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
-static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
-static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
-static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
-static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
-static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
-static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
-static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
-
-static struct attribute *i2c_nuvoton_attrs[] = {
- &dev_attr_pubek.attr,
- &dev_attr_pcrs.attr,
- &dev_attr_enabled.attr,
- &dev_attr_active.attr,
- &dev_attr_owned.attr,
- &dev_attr_temp_deactivated.attr,
- &dev_attr_caps.attr,
- &dev_attr_cancel.attr,
- &dev_attr_durations.attr,
- &dev_attr_timeouts.attr,
- NULL,
-};
-
-static struct attribute_group i2c_nuvoton_attr_grp = {
- .attrs = i2c_nuvoton_attrs
-};
-
-static const struct tpm_vendor_specific tpm_i2c = {
- .status = i2c_nuvoton_read_status,
- .recv = i2c_nuvoton_recv,
- .send = i2c_nuvoton_send,
- .cancel = i2c_nuvoton_ready,
- .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- .req_canceled = i2c_nuvoton_req_canceled,
- .attr_group = &i2c_nuvoton_attr_grp,
- .miscdev.fops = &i2c_nuvoton_ops,
-};
-
-/* The only purpose for the handler is to signal to any waiting threads that
- * the interrupt is currently being asserted. The driver does not do any
- * processing triggered by interrupts, and the chip provides no way to mask at
- * the source (plus that would be slow over I2C). Run the IRQ as a one-shot,
- * this means it cannot be shared. */
-static irqreturn_t i2c_nuvoton_int_handler(int dummy, void *dev_id)
-{
- struct tpm_chip *chip = dev_id;
- struct priv_data *priv = chip->vendor.priv;
-
- priv->intrs++;
- wake_up(&chip->vendor.read_queue);
- disable_irq_nosync(chip->vendor.irq);
- return IRQ_HANDLED;
-}
-
-static int get_vid(struct i2c_client *client, u32 *res)
-{
- static const u8 vid_did_rid_value[] = { 0x50, 0x10, 0xfe };
- u32 temp;
- s32 rc;
-
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
- return -ENODEV;
- rc = i2c_nuvoton_read_buf(client, TPM_VID_DID_RID, 4, (u8 *)&temp);
- if (rc < 0)
- return rc;
-
- /* check WPCT301 values - ignore RID */
- if (memcmp(&temp, vid_did_rid_value, sizeof(vid_did_rid_value))) {
- /*
- * f/w rev 2.81 has an issue where the VID_DID_RID is not
- * reporting the right value. so give it another chance at
- * offset 0x20 (FIFO_W).
- */
- rc = i2c_nuvoton_read_buf(client, TPM_DATA_FIFO_W, 4,
- (u8 *) (&temp));
- if (rc < 0)
- return rc;
-
- /* check WPCT301 values - ignore RID */
- if (memcmp(&temp, vid_did_rid_value,
- sizeof(vid_did_rid_value)))
- return -ENODEV;
- }
-
- *res = temp;
- return 0;
-}
-
-static int i2c_nuvoton_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- int rc;
- struct tpm_chip *chip;
- struct device *dev = &client->dev;
- u32 vid = 0;
-
- rc = get_vid(client, &vid);
- if (rc)
- return rc;
-
- 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->vendor.priv = devm_kzalloc(dev, sizeof(struct priv_data),
- GFP_KERNEL);
- init_waitqueue_head(&chip->vendor.read_queue);
- init_waitqueue_head(&chip->vendor.int_queue);
-
- /* Default timeouts */
- chip->vendor.timeout_a = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
- chip->vendor.timeout_b = msecs_to_jiffies(TPM_I2C_LONG_TIMEOUT);
- chip->vendor.timeout_c = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
- chip->vendor.timeout_d = msecs_to_jiffies(TPM_I2C_SHORT_TIMEOUT);
-
- /*
- * I2C intfcaps (interrupt capabilitieis) in the chip are hard coded to:
- * TPM_INTF_INT_LEVEL_LOW | TPM_INTF_DATA_AVAIL_INT
- * The IRQ should be set in the i2c_board_info (which is done
- * automatically in of_i2c_register_devices, for device tree users */
- chip->vendor.irq = client->irq;
-
- if (chip->vendor.irq) {
- dev_dbg(dev, "%s() chip-vendor.irq\n", __func__);
- rc = devm_request_irq(dev, chip->vendor.irq,
- i2c_nuvoton_int_handler,
- IRQF_TRIGGER_LOW,
- chip->vendor.miscdev.name,
- chip);
- if (rc) {
- dev_err(dev, "%s() Unable to request irq: %d for use\n",
- __func__, chip->vendor.irq);
- chip->vendor.irq = 0;
- } else {
- /* Clear any pending interrupt */
- i2c_nuvoton_ready(chip);
- /* - wait for TPM_STS==0xA0 (stsValid, commandReady) */
- rc = i2c_nuvoton_wait_for_stat(chip,
- TPM_STS_COMMAND_READY,
- TPM_STS_COMMAND_READY,
- chip->vendor.timeout_b,
- NULL);
- if (rc == 0) {
- /*
- * TIS is in ready state
- * write dummy byte to enter reception state
- * TPM_DATA_FIFO_W <- rc (0)
- */
- rc = i2c_nuvoton_write_buf(client,
- TPM_DATA_FIFO_W,
- 1, (u8 *) (&rc));
- if (rc < 0)
- goto out_err;
- /* TPM_STS <- 0x40 (commandReady) */
- i2c_nuvoton_ready(chip);
- } else {
- /*
- * timeout_b reached - command was
- * aborted. TIS should now be in idle state -
- * only TPM_STS_VALID should be set
- */
- if (i2c_nuvoton_read_status(chip) !=
- TPM_STS_VALID) {
- rc = -EIO;
- goto out_err;
- }
- }
- }
- }
-
- if (tpm_get_timeouts(chip)) {
- rc = -ENODEV;
- goto out_err;
- }
-
- if (tpm_do_selftest(chip)) {
- rc = -ENODEV;
- goto out_err;
- }
-
- return 0;
-
-out_err:
- tpm_dev_vendor_release(chip);
- tpm_remove_hardware(chip->dev);
- return rc;
-}
-
-static int i2c_nuvoton_remove(struct i2c_client *client)
-{
- struct device *dev = &(client->dev);
- struct tpm_chip *chip = dev_get_drvdata(dev);
-
- if (chip)
- tpm_dev_vendor_release(chip);
- tpm_remove_hardware(dev);
- kfree(chip);
- return 0;
-}
-
-
-static const struct i2c_device_id i2c_nuvoton_id[] = {
- {I2C_DRIVER_NAME, 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, i2c_nuvoton_id);
-
-#ifdef CONFIG_OF
-static const struct of_device_id i2c_nuvoton_of_match[] = {
- {.compatible = "nuvoton,npct501"},
- {.compatible = "winbond,wpct301"},
- {},
-};
-MODULE_DEVICE_TABLE(of, i2c_nuvoton_of_match);
-#endif
-
-static SIMPLE_DEV_PM_OPS(i2c_nuvoton_pm_ops, tpm_pm_suspend, tpm_pm_resume);
-
-static struct i2c_driver i2c_nuvoton_driver = {
- .id_table = i2c_nuvoton_id,
- .probe = i2c_nuvoton_probe,
- .remove = i2c_nuvoton_remove,
- .driver = {
- .name = I2C_DRIVER_NAME,
- .owner = THIS_MODULE,
- .pm = &i2c_nuvoton_pm_ops,
- .of_match_table = of_match_ptr(i2c_nuvoton_of_match),
- },
-};
-
-module_i2c_driver(i2c_nuvoton_driver);
-
-MODULE_AUTHOR("Dan Morav (dan.morav@nuvoton.com)");
-MODULE_DESCRIPTION("Nuvoton TPM I2C Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_i2c_stm_st33.c b/drivers/char/tpm/tpm_i2c_stm_st33.c
index a0d6ceb5..5bb8e2d 100644
--- a/drivers/char/tpm/tpm_i2c_stm_st33.c
+++ b/drivers/char/tpm/tpm_i2c_stm_st33.c
@@ -584,7 +584,7 @@ static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL);
-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
static struct attribute *stm_tpm_attrs[] = {
@@ -746,6 +746,8 @@ tpm_st33_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
tpm_get_timeouts(chip);
+ i2c_set_clientdata(client, chip);
+
dev_info(chip->dev, "TPM I2C Initialized\n");
return 0;
_irq_set:
@@ -805,18 +807,24 @@ static int tpm_st33_i2c_remove(struct i2c_client *client)
#ifdef CONFIG_PM_SLEEP
/*
* tpm_st33_i2c_pm_suspend suspend the TPM device
+ * Added: Work around when suspend and no tpm application is running, suspend
+ * may fail because chip->data_buffer is not set (only set in tpm_open in Linux
+ * TPM core)
* @param: client, the i2c_client drescription (TPM I2C description).
* @param: mesg, the power management message.
* @return: 0 in case of success.
*/
static int tpm_st33_i2c_pm_suspend(struct device *dev)
{
+ struct tpm_chip *chip = dev_get_drvdata(dev);
struct st33zp24_platform_data *pin_infos = dev->platform_data;
int ret = 0;
if (power_mgt) {
gpio_set_value(pin_infos->io_lpcpd, 0);
} else {
+ if (chip->data_buffer == NULL)
+ chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
ret = tpm_pm_suspend(dev);
}
return ret;
@@ -841,6 +849,8 @@ static int tpm_st33_i2c_pm_resume(struct device *dev)
TPM_STS_VALID) == TPM_STS_VALID,
chip->vendor.timeout_b);
} else {
+ if (chip->data_buffer == NULL)
+ chip->data_buffer = pin_infos->tpm_i2c_buffer[0];
ret = tpm_pm_resume(dev);
if (!ret)
tpm_do_selftest(chip);
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c
index 2783a42..56b07c3 100644
--- a/drivers/char/tpm/tpm_ibmvtpm.c
+++ b/drivers/char/tpm/tpm_ibmvtpm.c
@@ -98,7 +98,7 @@ static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count)
if (count < len) {
dev_err(ibmvtpm->dev,
- "Invalid size in recv: count=%zd, crq_size=%d\n",
+ "Invalid size in recv: count=%ld, crq_size=%d\n",
count, len);
return -EIO;
}
@@ -136,7 +136,7 @@ static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
if (count > ibmvtpm->rtce_size) {
dev_err(ibmvtpm->dev,
- "Invalid size in send: count=%zd, rtce_size=%d\n",
+ "Invalid size in send: count=%ld, rtce_size=%d\n",
count, ibmvtpm->rtce_size);
return -EIO;
}
@@ -419,7 +419,7 @@ static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
NULL);
-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c
index 8e562dc..2168d15 100644
--- a/drivers/char/tpm/tpm_ppi.c
+++ b/drivers/char/tpm/tpm_ppi.c
@@ -452,8 +452,12 @@ int tpm_add_ppi(struct kobject *parent)
{
return sysfs_create_group(parent, &ppi_attr_grp);
}
+EXPORT_SYMBOL_GPL(tpm_add_ppi);
void tpm_remove_ppi(struct kobject *parent)
{
sysfs_remove_group(parent, &ppi_attr_grp);
}
+EXPORT_SYMBOL_GPL(tpm_remove_ppi);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 1b74459..5796d01 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -448,7 +448,7 @@ static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
NULL);
-static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL);
static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL);
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index c8ff4df..94c280d 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -351,6 +351,8 @@ static int tpmfront_probe(struct xenbus_device *dev,
tpm_get_timeouts(priv->chip);
+ dev_set_drvdata(&dev->dev, priv->chip);
+
return rv;
}
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index feea87c..b79cf3e 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -577,8 +577,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
spin_lock(&portdev->c_ovq_lock);
if (virtqueue_add_outbuf(vq, sg, 1, &cpkt, GFP_ATOMIC) == 0) {
virtqueue_kick(vq);
- while (!virtqueue_get_buf(vq, &len)
- && !virtqueue_is_broken(vq))
+ while (!virtqueue_get_buf(vq, &len))
cpu_relax();
}
spin_unlock(&portdev->c_ovq_lock);
@@ -651,8 +650,7 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg,
* we need to kmalloc a GFP_ATOMIC buffer each time the
* console driver writes something out.
*/
- while (!virtqueue_get_buf(out_vq, &len)
- && !virtqueue_is_broken(out_vq))
+ while (!virtqueue_get_buf(out_vq, &len))
cpu_relax();
done:
spin_unlock_irqrestore(&port->outvq_lock, flags);
@@ -1839,8 +1837,12 @@ static void config_intr(struct virtio_device *vdev)
struct port *port;
u16 rows, cols;
- virtio_cread(vdev, struct virtio_console_config, cols, &cols);
- virtio_cread(vdev, struct virtio_console_config, rows, &rows);
+ vdev->config->get(vdev,
+ offsetof(struct virtio_console_config, cols),
+ &cols, sizeof(u16));
+ vdev->config->get(vdev,
+ offsetof(struct virtio_console_config, rows),
+ &rows, sizeof(u16));
port = find_port_by_id(portdev, 0);
set_console_size(port, rows, cols);
@@ -2012,9 +2014,10 @@ static int virtcons_probe(struct virtio_device *vdev)
/* Don't test MULTIPORT at all if we're rproc: not a valid feature! */
if (!is_rproc_serial(vdev) &&
- virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
- struct virtio_console_config, max_nr_ports,
- &portdev->config.max_nr_ports) == 0) {
+ virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT,
+ offsetof(struct virtio_console_config,
+ max_nr_ports),
+ &portdev->config.max_nr_ports) == 0) {
multiport = true;
}
@@ -2139,7 +2142,7 @@ static struct virtio_device_id rproc_serial_id_table[] = {
static unsigned int rproc_serial_features[] = {
};
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
static int virtcons_freeze(struct virtio_device *vdev)
{
struct ports_device *portdev;
@@ -2217,7 +2220,7 @@ static struct virtio_driver virtio_console = {
.probe = virtcons_probe,
.remove = virtcons_remove,
.config_changed = config_intr,
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
.freeze = virtcons_freeze,
.restore = virtcons_restore,
#endif
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index f6345f9..5224da5 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -721,7 +721,7 @@ static int hwicap_remove(struct device *dev)
{
struct hwicap_drvdata *drvdata;
- drvdata = dev_get_drvdata(dev);
+ drvdata = (struct hwicap_drvdata *)dev_get_drvdata(dev);
if (!drvdata)
return 0;
@@ -731,6 +731,7 @@ static int hwicap_remove(struct device *dev)
iounmap(drvdata->base_address);
release_mem_region(drvdata->mem_start, drvdata->mem_size);
kfree(drvdata);
+ dev_set_drvdata(dev, NULL);
mutex_lock(&icap_sem);
probed_devices[MINOR(dev->devt)-XHWICAP_MINOR] = 0;