diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/apm-emulation.c | 2 | ||||
-rw-r--r-- | drivers/char/bsr.c | 2 | ||||
-rw-r--r-- | drivers/char/generic_nvram.c | 4 | ||||
-rw-r--r-- | drivers/char/hpet.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/Kconfig | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/core.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/n2-drv.c | 29 | ||||
-rw-r--r-- | drivers/char/hw_random/n2rng.h | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/nomadik-rng.c | 3 | ||||
-rw-r--r-- | drivers/char/hw_random/omap-rng.c | 6 | ||||
-rw-r--r-- | drivers/char/hw_random/ppc4xx-rng.c | 156 | ||||
-rw-r--r-- | drivers/char/hw_random/timeriomem-rng.c | 3 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_watchdog.c | 2 | ||||
-rw-r--r-- | drivers/char/mspec.c | 2 | ||||
-rw-r--r-- | drivers/char/nvram.c | 2 | ||||
-rw-r--r-- | drivers/char/ps3flash.c | 13 | ||||
-rw-r--r-- | drivers/char/ramoops.c | 93 | ||||
-rw-r--r-- | drivers/char/random.c | 15 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 102 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 7 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_nsc.c | 14 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 182 | ||||
-rw-r--r-- | drivers/char/xilinx_hwicap/xilinx_hwicap.c | 2 |
24 files changed, 553 insertions, 105 deletions
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index 548708c4b2b8..a7346ab97a3c 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c | |||
@@ -606,7 +606,7 @@ static int apm_suspend_notifier(struct notifier_block *nb, | |||
606 | return NOTIFY_OK; | 606 | return NOTIFY_OK; |
607 | 607 | ||
608 | /* interrupted by signal */ | 608 | /* interrupted by signal */ |
609 | return NOTIFY_BAD; | 609 | return notifier_from_errno(err); |
610 | 610 | ||
611 | case PM_POST_SUSPEND: | 611 | case PM_POST_SUSPEND: |
612 | /* | 612 | /* |
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index cf39bc08ce08..0c688232aab3 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
@@ -212,7 +212,7 @@ static int bsr_add_node(struct device_node *bn) | |||
212 | 212 | ||
213 | cur->bsr_minor = i + total_bsr_devs; | 213 | cur->bsr_minor = i + total_bsr_devs; |
214 | cur->bsr_addr = res.start; | 214 | cur->bsr_addr = res.start; |
215 | cur->bsr_len = res.end - res.start + 1; | 215 | cur->bsr_len = resource_size(&res); |
216 | cur->bsr_bytes = bsr_bytes[i]; | 216 | cur->bsr_bytes = bsr_bytes[i]; |
217 | cur->bsr_stride = bsr_stride[i]; | 217 | cur->bsr_stride = bsr_stride[i]; |
218 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); | 218 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); |
diff --git a/drivers/char/generic_nvram.c b/drivers/char/generic_nvram.c index 0e941b57482e..6c4f4b5a9dd3 100644 --- a/drivers/char/generic_nvram.c +++ b/drivers/char/generic_nvram.c | |||
@@ -34,12 +34,16 @@ static ssize_t nvram_len; | |||
34 | static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) | 34 | static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) |
35 | { | 35 | { |
36 | switch (origin) { | 36 | switch (origin) { |
37 | case 0: | ||
38 | break; | ||
37 | case 1: | 39 | case 1: |
38 | offset += file->f_pos; | 40 | offset += file->f_pos; |
39 | break; | 41 | break; |
40 | case 2: | 42 | case 2: |
41 | offset += nvram_len; | 43 | offset += nvram_len; |
42 | break; | 44 | break; |
45 | default: | ||
46 | offset = -1; | ||
43 | } | 47 | } |
44 | if (offset < 0) | 48 | if (offset < 0) |
45 | return -EINVAL; | 49 | return -EINVAL; |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 34d6a1cab8de..0833896cf6f2 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -952,7 +952,7 @@ int hpet_alloc(struct hpet_data *hdp) | |||
952 | #ifdef CONFIG_IA64 | 952 | #ifdef CONFIG_IA64 |
953 | if (!hpet_clocksource) { | 953 | if (!hpet_clocksource) { |
954 | hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc; | 954 | hpet_mctr = (void __iomem *)&hpetp->hp_hpet->hpet_mc; |
955 | CLKSRC_FSYS_MMIO_SET(clocksource_hpet.fsys_mmio, hpet_mctr); | 955 | clocksource_hpet.archdata.fsys_mmio = hpet_mctr; |
956 | clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq); | 956 | clocksource_register_hz(&clocksource_hpet, hpetp->hp_tick_freq); |
957 | hpetp->hp_clocksource = &clocksource_hpet; | 957 | hpetp->hp_clocksource = &clocksource_hpet; |
958 | hpet_clocksource = &clocksource_hpet; | 958 | hpet_clocksource = &clocksource_hpet; |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index a60043b3e409..1d2ebc7a4947 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -210,3 +210,15 @@ config HW_RANDOM_PICOXCELL | |||
210 | module will be called picoxcell-rng. | 210 | module will be called picoxcell-rng. |
211 | 211 | ||
212 | If unsure, say Y. | 212 | If unsure, say Y. |
213 | |||
214 | config HW_RANDOM_PPC4XX | ||
215 | tristate "PowerPC 4xx generic true random number generator support" | ||
216 | depends on HW_RANDOM && PPC && 4xx | ||
217 | ---help--- | ||
218 | This driver provides the kernel-side support for the TRNG hardware | ||
219 | found in the security function of some PowerPC 4xx SoCs. | ||
220 | |||
221 | To compile this driver as a module, choose M here: the | ||
222 | module will be called ppc4xx-rng. | ||
223 | |||
224 | If unsure, say N. | ||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 3db4eb8b19c0..c88f244c8a71 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -20,3 +20,4 @@ obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o | |||
20 | obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o | 20 | obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o |
21 | obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o | 21 | obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o |
22 | obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o | 22 | obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o |
23 | obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o | ||
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 2016aad85203..1bafb40ec8a2 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
@@ -19,7 +19,7 @@ | |||
19 | Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> | 19 | Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com> |
20 | 20 | ||
21 | Added generic RNG API | 21 | Added generic RNG API |
22 | Copyright 2006 Michael Buesch <mbuesch@freenet.de> | 22 | Copyright 2006 Michael Buesch <m@bues.ch> |
23 | Copyright 2005 (c) MontaVista Software, Inc. | 23 | Copyright 2005 (c) MontaVista Software, Inc. |
24 | 24 | ||
25 | Please read Documentation/hw_random.txt for details on use. | 25 | Please read Documentation/hw_random.txt for details on use. |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index ac6739e085e3..c3de70de00d4 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* n2-drv.c: Niagara-2 RNG driver. | 1 | /* n2-drv.c: Niagara-2 RNG driver. |
2 | * | 2 | * |
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2008, 2011 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
@@ -22,8 +22,8 @@ | |||
22 | 22 | ||
23 | #define DRV_MODULE_NAME "n2rng" | 23 | #define DRV_MODULE_NAME "n2rng" |
24 | #define PFX DRV_MODULE_NAME ": " | 24 | #define PFX DRV_MODULE_NAME ": " |
25 | #define DRV_MODULE_VERSION "0.1" | 25 | #define DRV_MODULE_VERSION "0.2" |
26 | #define DRV_MODULE_RELDATE "May 15, 2008" | 26 | #define DRV_MODULE_RELDATE "July 27, 2011" |
27 | 27 | ||
28 | static char version[] __devinitdata = | 28 | static char version[] __devinitdata = |
29 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 29 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
@@ -623,14 +623,14 @@ static const struct of_device_id n2rng_match[]; | |||
623 | static int __devinit n2rng_probe(struct platform_device *op) | 623 | static int __devinit n2rng_probe(struct platform_device *op) |
624 | { | 624 | { |
625 | const struct of_device_id *match; | 625 | const struct of_device_id *match; |
626 | int victoria_falls; | 626 | int multi_capable; |
627 | int err = -ENOMEM; | 627 | int err = -ENOMEM; |
628 | struct n2rng *np; | 628 | struct n2rng *np; |
629 | 629 | ||
630 | match = of_match_device(n2rng_match, &op->dev); | 630 | match = of_match_device(n2rng_match, &op->dev); |
631 | if (!match) | 631 | if (!match) |
632 | return -EINVAL; | 632 | return -EINVAL; |
633 | victoria_falls = (match->data != NULL); | 633 | multi_capable = (match->data != NULL); |
634 | 634 | ||
635 | n2rng_driver_version(); | 635 | n2rng_driver_version(); |
636 | np = kzalloc(sizeof(*np), GFP_KERNEL); | 636 | np = kzalloc(sizeof(*np), GFP_KERNEL); |
@@ -640,8 +640,8 @@ static int __devinit n2rng_probe(struct platform_device *op) | |||
640 | 640 | ||
641 | INIT_DELAYED_WORK(&np->work, n2rng_work); | 641 | INIT_DELAYED_WORK(&np->work, n2rng_work); |
642 | 642 | ||
643 | if (victoria_falls) | 643 | if (multi_capable) |
644 | np->flags |= N2RNG_FLAG_VF; | 644 | np->flags |= N2RNG_FLAG_MULTI; |
645 | 645 | ||
646 | err = -ENODEV; | 646 | err = -ENODEV; |
647 | np->hvapi_major = 2; | 647 | np->hvapi_major = 2; |
@@ -658,10 +658,10 @@ static int __devinit n2rng_probe(struct platform_device *op) | |||
658 | } | 658 | } |
659 | } | 659 | } |
660 | 660 | ||
661 | if (np->flags & N2RNG_FLAG_VF) { | 661 | if (np->flags & N2RNG_FLAG_MULTI) { |
662 | if (np->hvapi_major < 2) { | 662 | if (np->hvapi_major < 2) { |
663 | dev_err(&op->dev, "VF RNG requires HVAPI major " | 663 | dev_err(&op->dev, "multi-unit-capable RNG requires " |
664 | "version 2 or later, got %lu\n", | 664 | "HVAPI major version 2 or later, got %lu\n", |
665 | np->hvapi_major); | 665 | np->hvapi_major); |
666 | goto out_hvapi_unregister; | 666 | goto out_hvapi_unregister; |
667 | } | 667 | } |
@@ -688,8 +688,8 @@ static int __devinit n2rng_probe(struct platform_device *op) | |||
688 | goto out_free_units; | 688 | goto out_free_units; |
689 | 689 | ||
690 | dev_info(&op->dev, "Found %s RNG, units: %d\n", | 690 | dev_info(&op->dev, "Found %s RNG, units: %d\n", |
691 | ((np->flags & N2RNG_FLAG_VF) ? | 691 | ((np->flags & N2RNG_FLAG_MULTI) ? |
692 | "Victoria Falls" : "Niagara2"), | 692 | "multi-unit-capable" : "single-unit"), |
693 | np->num_units); | 693 | np->num_units); |
694 | 694 | ||
695 | np->hwrng.name = "n2rng"; | 695 | np->hwrng.name = "n2rng"; |
@@ -751,6 +751,11 @@ static const struct of_device_id n2rng_match[] = { | |||
751 | .compatible = "SUNW,vf-rng", | 751 | .compatible = "SUNW,vf-rng", |
752 | .data = (void *) 1, | 752 | .data = (void *) 1, |
753 | }, | 753 | }, |
754 | { | ||
755 | .name = "random-number-generator", | ||
756 | .compatible = "SUNW,kt-rng", | ||
757 | .data = (void *) 1, | ||
758 | }, | ||
754 | {}, | 759 | {}, |
755 | }; | 760 | }; |
756 | MODULE_DEVICE_TABLE(of, n2rng_match); | 761 | MODULE_DEVICE_TABLE(of, n2rng_match); |
diff --git a/drivers/char/hw_random/n2rng.h b/drivers/char/hw_random/n2rng.h index 4bea07f30978..f244ac89087f 100644 --- a/drivers/char/hw_random/n2rng.h +++ b/drivers/char/hw_random/n2rng.h | |||
@@ -68,7 +68,7 @@ struct n2rng { | |||
68 | struct platform_device *op; | 68 | struct platform_device *op; |
69 | 69 | ||
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | #define N2RNG_FLAG_VF 0x00000001 /* Victoria Falls RNG, else N2 */ | 71 | #define N2RNG_FLAG_MULTI 0x00000001 /* Multi-unit capable RNG */ |
72 | #define N2RNG_FLAG_CONTROL 0x00000002 /* Operating in control domain */ | 72 | #define N2RNG_FLAG_CONTROL 0x00000002 /* Operating in control domain */ |
73 | #define N2RNG_FLAG_READY 0x00000008 /* Ready for hw-rng layer */ | 73 | #define N2RNG_FLAG_READY 0x00000008 /* Ready for hw-rng layer */ |
74 | #define N2RNG_FLAG_SHUTDOWN 0x00000010 /* Driver unregistering */ | 74 | #define N2RNG_FLAG_SHUTDOWN 0x00000010 /* Driver unregistering */ |
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index dd1d143eb8ea..52e08ca3ccd7 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c | |||
@@ -55,7 +55,7 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) | |||
55 | 55 | ||
56 | ret = amba_request_regions(dev, dev->dev.init_name); | 56 | ret = amba_request_regions(dev, dev->dev.init_name); |
57 | if (ret) | 57 | if (ret) |
58 | return ret; | 58 | goto out_clk; |
59 | ret = -ENOMEM; | 59 | ret = -ENOMEM; |
60 | base = ioremap(dev->res.start, resource_size(&dev->res)); | 60 | base = ioremap(dev->res.start, resource_size(&dev->res)); |
61 | if (!base) | 61 | if (!base) |
@@ -70,6 +70,7 @@ out_unmap: | |||
70 | iounmap(base); | 70 | iounmap(base); |
71 | out_release: | 71 | out_release: |
72 | amba_release_regions(dev); | 72 | amba_release_regions(dev); |
73 | out_clk: | ||
73 | clk_disable(rng_clk); | 74 | clk_disable(rng_clk); |
74 | clk_put(rng_clk); | 75 | clk_put(rng_clk); |
75 | return ret; | 76 | return ret; |
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index 2cc755a64302..b757fac3cd1f 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c | |||
@@ -113,8 +113,10 @@ static int __devinit omap_rng_probe(struct platform_device *pdev) | |||
113 | 113 | ||
114 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 114 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
115 | 115 | ||
116 | if (!res) | 116 | if (!res) { |
117 | return -ENOENT; | 117 | ret = -ENOENT; |
118 | goto err_region; | ||
119 | } | ||
118 | 120 | ||
119 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { | 121 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { |
120 | ret = -EBUSY; | 122 | ret = -EBUSY; |
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c new file mode 100644 index 000000000000..b8afa6a4ff67 --- /dev/null +++ b/drivers/char/hw_random/ppc4xx-rng.c | |||
@@ -0,0 +1,156 @@ | |||
1 | /* | ||
2 | * Generic PowerPC 44x RNG driver | ||
3 | * | ||
4 | * Copyright 2011 IBM Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; version 2 of the License. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/platform_device.h> | ||
14 | #include <linux/hw_random.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/of_platform.h> | ||
17 | #include <asm/io.h> | ||
18 | |||
19 | #define PPC4XX_TRNG_DEV_CTRL 0x60080 | ||
20 | |||
21 | #define PPC4XX_TRNGE 0x00020000 | ||
22 | #define PPC4XX_TRNG_CTRL 0x0008 | ||
23 | #define PPC4XX_TRNG_CTRL_DALM 0x20 | ||
24 | #define PPC4XX_TRNG_STAT 0x0004 | ||
25 | #define PPC4XX_TRNG_STAT_B 0x1 | ||
26 | #define PPC4XX_TRNG_DATA 0x0000 | ||
27 | |||
28 | #define MODULE_NAME "ppc4xx_rng" | ||
29 | |||
30 | static int ppc4xx_rng_data_present(struct hwrng *rng, int wait) | ||
31 | { | ||
32 | void __iomem *rng_regs = (void __iomem *) rng->priv; | ||
33 | int busy, i, present = 0; | ||
34 | |||
35 | for (i = 0; i < 20; i++) { | ||
36 | busy = (in_le32(rng_regs + PPC4XX_TRNG_STAT) & PPC4XX_TRNG_STAT_B); | ||
37 | if (!busy || !wait) { | ||
38 | present = 1; | ||
39 | break; | ||
40 | } | ||
41 | udelay(10); | ||
42 | } | ||
43 | return present; | ||
44 | } | ||
45 | |||
46 | static int ppc4xx_rng_data_read(struct hwrng *rng, u32 *data) | ||
47 | { | ||
48 | void __iomem *rng_regs = (void __iomem *) rng->priv; | ||
49 | *data = in_le32(rng_regs + PPC4XX_TRNG_DATA); | ||
50 | return 4; | ||
51 | } | ||
52 | |||
53 | static int ppc4xx_rng_enable(int enable) | ||
54 | { | ||
55 | struct device_node *ctrl; | ||
56 | void __iomem *ctrl_reg; | ||
57 | int err = 0; | ||
58 | u32 val; | ||
59 | |||
60 | /* Find the main crypto device node and map it to turn the TRNG on */ | ||
61 | ctrl = of_find_compatible_node(NULL, NULL, "amcc,ppc4xx-crypto"); | ||
62 | if (!ctrl) | ||
63 | return -ENODEV; | ||
64 | |||
65 | ctrl_reg = of_iomap(ctrl, 0); | ||
66 | if (!ctrl_reg) { | ||
67 | err = -ENODEV; | ||
68 | goto out; | ||
69 | } | ||
70 | |||
71 | val = in_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL); | ||
72 | |||
73 | if (enable) | ||
74 | val |= PPC4XX_TRNGE; | ||
75 | else | ||
76 | val = val & ~PPC4XX_TRNGE; | ||
77 | |||
78 | out_le32(ctrl_reg + PPC4XX_TRNG_DEV_CTRL, val); | ||
79 | iounmap(ctrl_reg); | ||
80 | |||
81 | out: | ||
82 | of_node_put(ctrl); | ||
83 | |||
84 | return err; | ||
85 | } | ||
86 | |||
87 | static struct hwrng ppc4xx_rng = { | ||
88 | .name = MODULE_NAME, | ||
89 | .data_present = ppc4xx_rng_data_present, | ||
90 | .data_read = ppc4xx_rng_data_read, | ||
91 | }; | ||
92 | |||
93 | static int __devinit ppc4xx_rng_probe(struct platform_device *dev) | ||
94 | { | ||
95 | void __iomem *rng_regs; | ||
96 | int err = 0; | ||
97 | |||
98 | rng_regs = of_iomap(dev->dev.of_node, 0); | ||
99 | if (!rng_regs) | ||
100 | return -ENODEV; | ||
101 | |||
102 | err = ppc4xx_rng_enable(1); | ||
103 | if (err) | ||
104 | return err; | ||
105 | |||
106 | out_le32(rng_regs + PPC4XX_TRNG_CTRL, PPC4XX_TRNG_CTRL_DALM); | ||
107 | ppc4xx_rng.priv = (unsigned long) rng_regs; | ||
108 | |||
109 | err = hwrng_register(&ppc4xx_rng); | ||
110 | |||
111 | return err; | ||
112 | } | ||
113 | |||
114 | static int __devexit ppc4xx_rng_remove(struct platform_device *dev) | ||
115 | { | ||
116 | void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv; | ||
117 | |||
118 | hwrng_unregister(&ppc4xx_rng); | ||
119 | ppc4xx_rng_enable(0); | ||
120 | iounmap(rng_regs); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static struct of_device_id ppc4xx_rng_match[] = { | ||
126 | { .compatible = "ppc4xx-rng", }, | ||
127 | { .compatible = "amcc,ppc460ex-rng", }, | ||
128 | { .compatible = "amcc,ppc440epx-rng", }, | ||
129 | {}, | ||
130 | }; | ||
131 | |||
132 | static struct platform_driver ppc4xx_rng_driver = { | ||
133 | .driver = { | ||
134 | .name = MODULE_NAME, | ||
135 | .owner = THIS_MODULE, | ||
136 | .of_match_table = ppc4xx_rng_match, | ||
137 | }, | ||
138 | .probe = ppc4xx_rng_probe, | ||
139 | .remove = ppc4xx_rng_remove, | ||
140 | }; | ||
141 | |||
142 | static int __init ppc4xx_rng_init(void) | ||
143 | { | ||
144 | return platform_driver_register(&ppc4xx_rng_driver); | ||
145 | } | ||
146 | module_init(ppc4xx_rng_init); | ||
147 | |||
148 | static void __exit ppc4xx_rng_exit(void) | ||
149 | { | ||
150 | platform_driver_unregister(&ppc4xx_rng_driver); | ||
151 | } | ||
152 | module_exit(ppc4xx_rng_exit); | ||
153 | |||
154 | MODULE_LICENSE("GPL"); | ||
155 | MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>"); | ||
156 | MODULE_DESCRIPTION("HW RNG driver for PPC 4xx processors"); | ||
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index a94e930575f2..a8428e6f64a9 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c | |||
@@ -100,8 +100,7 @@ static int __devinit timeriomem_rng_probe(struct platform_device *pdev) | |||
100 | 100 | ||
101 | timeriomem_rng_data = pdev->dev.platform_data; | 101 | timeriomem_rng_data = pdev->dev.platform_data; |
102 | 102 | ||
103 | timeriomem_rng_data->address = ioremap(res->start, | 103 | timeriomem_rng_data->address = ioremap(res->start, resource_size(res)); |
104 | res->end - res->start + 1); | ||
105 | if (!timeriomem_rng_data->address) | 104 | if (!timeriomem_rng_data->address) |
106 | return -EIO; | 105 | return -EIO; |
107 | 106 | ||
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 320668f4c3aa..3302586655c4 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
@@ -52,7 +52,7 @@ | |||
52 | #include <linux/string.h> | 52 | #include <linux/string.h> |
53 | #include <linux/ctype.h> | 53 | #include <linux/ctype.h> |
54 | #include <linux/delay.h> | 54 | #include <linux/delay.h> |
55 | #include <asm/atomic.h> | 55 | #include <linux/atomic.h> |
56 | 56 | ||
57 | #ifdef CONFIG_X86 | 57 | #ifdef CONFIG_X86 |
58 | /* | 58 | /* |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 25d139c9dbed..5c0d96a820fa 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
@@ -46,7 +46,7 @@ | |||
46 | #include <asm/page.h> | 46 | #include <asm/page.h> |
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | #include <asm/pgtable.h> | 48 | #include <asm/pgtable.h> |
49 | #include <asm/atomic.h> | 49 | #include <linux/atomic.h> |
50 | #include <asm/tlbflush.h> | 50 | #include <asm/tlbflush.h> |
51 | #include <asm/uncached.h> | 51 | #include <asm/uncached.h> |
52 | #include <asm/sn/addrs.h> | 52 | #include <asm/sn/addrs.h> |
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 166f1e7aaa7e..da3cfee782dc 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c | |||
@@ -224,6 +224,8 @@ static loff_t nvram_llseek(struct file *file, loff_t offset, int origin) | |||
224 | case 2: | 224 | case 2: |
225 | offset += NVRAM_BYTES; | 225 | offset += NVRAM_BYTES; |
226 | break; | 226 | break; |
227 | default: | ||
228 | return -EINVAL; | ||
227 | } | 229 | } |
228 | 230 | ||
229 | return (offset >= 0) ? (file->f_pos = offset) : -EINVAL; | 231 | return (offset >= 0) ? (file->f_pos = offset) : -EINVAL; |
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c index 85c004a518ee..d0c57c2e2909 100644 --- a/drivers/char/ps3flash.c +++ b/drivers/char/ps3flash.c | |||
@@ -101,12 +101,16 @@ static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin) | |||
101 | 101 | ||
102 | mutex_lock(&file->f_mapping->host->i_mutex); | 102 | mutex_lock(&file->f_mapping->host->i_mutex); |
103 | switch (origin) { | 103 | switch (origin) { |
104 | case 0: | ||
105 | break; | ||
104 | case 1: | 106 | case 1: |
105 | offset += file->f_pos; | 107 | offset += file->f_pos; |
106 | break; | 108 | break; |
107 | case 2: | 109 | case 2: |
108 | offset += dev->regions[dev->region_idx].size*dev->blk_size; | 110 | offset += dev->regions[dev->region_idx].size*dev->blk_size; |
109 | break; | 111 | break; |
112 | default: | ||
113 | offset = -1; | ||
110 | } | 114 | } |
111 | if (offset < 0) { | 115 | if (offset < 0) { |
112 | res = -EINVAL; | 116 | res = -EINVAL; |
@@ -305,9 +309,14 @@ static int ps3flash_flush(struct file *file, fl_owner_t id) | |||
305 | return ps3flash_writeback(ps3flash_dev); | 309 | return ps3flash_writeback(ps3flash_dev); |
306 | } | 310 | } |
307 | 311 | ||
308 | static int ps3flash_fsync(struct file *file, int datasync) | 312 | static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync) |
309 | { | 313 | { |
310 | return ps3flash_writeback(ps3flash_dev); | 314 | struct inode *inode = file->f_path.dentry->d_inode; |
315 | int err; | ||
316 | mutex_lock(&inode->i_mutex); | ||
317 | err = ps3flash_writeback(ps3flash_dev); | ||
318 | mutex_unlock(&inode->i_mutex); | ||
319 | return err; | ||
311 | } | 320 | } |
312 | 321 | ||
313 | static irqreturn_t ps3flash_interrupt(int irq, void *data) | 322 | static irqreturn_t ps3flash_interrupt(int irq, void *data) |
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index 1a9f5f6d6ac5..fca0c51bbc90 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c | |||
@@ -19,18 +19,26 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
23 | |||
22 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/err.h> | ||
23 | #include <linux/module.h> | 26 | #include <linux/module.h> |
24 | #include <linux/kmsg_dump.h> | 27 | #include <linux/kmsg_dump.h> |
25 | #include <linux/time.h> | 28 | #include <linux/time.h> |
26 | #include <linux/io.h> | 29 | #include <linux/io.h> |
27 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
28 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/slab.h> | ||
29 | #include <linux/ramoops.h> | 33 | #include <linux/ramoops.h> |
30 | 34 | ||
31 | #define RAMOOPS_KERNMSG_HDR "====" | 35 | #define RAMOOPS_KERNMSG_HDR "====" |
36 | #define MIN_MEM_SIZE 4096UL | ||
32 | 37 | ||
33 | #define RECORD_SIZE 4096UL | 38 | static ulong record_size = MIN_MEM_SIZE; |
39 | module_param(record_size, ulong, 0400); | ||
40 | MODULE_PARM_DESC(record_size, | ||
41 | "size of each dump done on oops/panic"); | ||
34 | 42 | ||
35 | static ulong mem_address; | 43 | static ulong mem_address; |
36 | module_param(mem_address, ulong, 0400); | 44 | module_param(mem_address, ulong, 0400); |
@@ -52,10 +60,15 @@ static struct ramoops_context { | |||
52 | void *virt_addr; | 60 | void *virt_addr; |
53 | phys_addr_t phys_addr; | 61 | phys_addr_t phys_addr; |
54 | unsigned long size; | 62 | unsigned long size; |
63 | unsigned long record_size; | ||
64 | int dump_oops; | ||
55 | int count; | 65 | int count; |
56 | int max_count; | 66 | int max_count; |
57 | } oops_cxt; | 67 | } oops_cxt; |
58 | 68 | ||
69 | static struct platform_device *dummy; | ||
70 | static struct ramoops_platform_data *dummy_data; | ||
71 | |||
59 | static void ramoops_do_dump(struct kmsg_dumper *dumper, | 72 | static void ramoops_do_dump(struct kmsg_dumper *dumper, |
60 | enum kmsg_dump_reason reason, const char *s1, unsigned long l1, | 73 | enum kmsg_dump_reason reason, const char *s1, unsigned long l1, |
61 | const char *s2, unsigned long l2) | 74 | const char *s2, unsigned long l2) |
@@ -74,13 +87,13 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, | |||
74 | return; | 87 | return; |
75 | 88 | ||
76 | /* Only dump oopses if dump_oops is set */ | 89 | /* Only dump oopses if dump_oops is set */ |
77 | if (reason == KMSG_DUMP_OOPS && !dump_oops) | 90 | if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) |
78 | return; | 91 | return; |
79 | 92 | ||
80 | buf = cxt->virt_addr + (cxt->count * RECORD_SIZE); | 93 | buf = cxt->virt_addr + (cxt->count * cxt->record_size); |
81 | buf_orig = buf; | 94 | buf_orig = buf; |
82 | 95 | ||
83 | memset(buf, '\0', RECORD_SIZE); | 96 | memset(buf, '\0', cxt->record_size); |
84 | res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); | 97 | res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); |
85 | buf += res; | 98 | buf += res; |
86 | do_gettimeofday(×tamp); | 99 | do_gettimeofday(×tamp); |
@@ -88,8 +101,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, | |||
88 | buf += res; | 101 | buf += res; |
89 | 102 | ||
90 | hdr_size = buf - buf_orig; | 103 | hdr_size = buf - buf_orig; |
91 | l2_cpy = min(l2, RECORD_SIZE - hdr_size); | 104 | l2_cpy = min(l2, cxt->record_size - hdr_size); |
92 | l1_cpy = min(l1, RECORD_SIZE - hdr_size - l2_cpy); | 105 | l1_cpy = min(l1, cxt->record_size - hdr_size - l2_cpy); |
93 | 106 | ||
94 | s2_start = l2 - l2_cpy; | 107 | s2_start = l2 - l2_cpy; |
95 | s1_start = l1 - l1_cpy; | 108 | s1_start = l1 - l1_cpy; |
@@ -106,44 +119,51 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
106 | struct ramoops_context *cxt = &oops_cxt; | 119 | struct ramoops_context *cxt = &oops_cxt; |
107 | int err = -EINVAL; | 120 | int err = -EINVAL; |
108 | 121 | ||
109 | if (pdata) { | 122 | if (!pdata->mem_size || !pdata->record_size) { |
110 | mem_size = pdata->mem_size; | 123 | pr_err("The memory size and the record size must be " |
111 | mem_address = pdata->mem_address; | 124 | "non-zero\n"); |
125 | goto fail3; | ||
112 | } | 126 | } |
113 | 127 | ||
114 | if (!mem_size) { | 128 | rounddown_pow_of_two(pdata->mem_size); |
115 | printk(KERN_ERR "ramoops: invalid size specification"); | 129 | rounddown_pow_of_two(pdata->record_size); |
130 | |||
131 | /* Check for the minimum memory size */ | ||
132 | if (pdata->mem_size < MIN_MEM_SIZE && | ||
133 | pdata->record_size < MIN_MEM_SIZE) { | ||
134 | pr_err("memory size too small, minium is %lu\n", MIN_MEM_SIZE); | ||
116 | goto fail3; | 135 | goto fail3; |
117 | } | 136 | } |
118 | 137 | ||
119 | rounddown_pow_of_two(mem_size); | 138 | if (pdata->mem_size < pdata->record_size) { |
120 | 139 | pr_err("The memory size must be larger than the " | |
121 | if (mem_size < RECORD_SIZE) { | 140 | "records size\n"); |
122 | printk(KERN_ERR "ramoops: size too small"); | ||
123 | goto fail3; | 141 | goto fail3; |
124 | } | 142 | } |
125 | 143 | ||
126 | cxt->max_count = mem_size / RECORD_SIZE; | 144 | cxt->max_count = pdata->mem_size / pdata->record_size; |
127 | cxt->count = 0; | 145 | cxt->count = 0; |
128 | cxt->size = mem_size; | 146 | cxt->size = pdata->mem_size; |
129 | cxt->phys_addr = mem_address; | 147 | cxt->phys_addr = pdata->mem_address; |
148 | cxt->record_size = pdata->record_size; | ||
149 | cxt->dump_oops = pdata->dump_oops; | ||
130 | 150 | ||
131 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { | 151 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { |
132 | printk(KERN_ERR "ramoops: request mem region failed"); | 152 | pr_err("request mem region failed\n"); |
133 | err = -EINVAL; | 153 | err = -EINVAL; |
134 | goto fail3; | 154 | goto fail3; |
135 | } | 155 | } |
136 | 156 | ||
137 | cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size); | 157 | cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size); |
138 | if (!cxt->virt_addr) { | 158 | if (!cxt->virt_addr) { |
139 | printk(KERN_ERR "ramoops: ioremap failed"); | 159 | pr_err("ioremap failed\n"); |
140 | goto fail2; | 160 | goto fail2; |
141 | } | 161 | } |
142 | 162 | ||
143 | cxt->dump.dump = ramoops_do_dump; | 163 | cxt->dump.dump = ramoops_do_dump; |
144 | err = kmsg_dump_register(&cxt->dump); | 164 | err = kmsg_dump_register(&cxt->dump); |
145 | if (err) { | 165 | if (err) { |
146 | printk(KERN_ERR "ramoops: registering kmsg dumper failed"); | 166 | pr_err("registering kmsg dumper failed\n"); |
147 | goto fail1; | 167 | goto fail1; |
148 | } | 168 | } |
149 | 169 | ||
@@ -162,7 +182,7 @@ static int __exit ramoops_remove(struct platform_device *pdev) | |||
162 | struct ramoops_context *cxt = &oops_cxt; | 182 | struct ramoops_context *cxt = &oops_cxt; |
163 | 183 | ||
164 | if (kmsg_dump_unregister(&cxt->dump) < 0) | 184 | if (kmsg_dump_unregister(&cxt->dump) < 0) |
165 | printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper"); | 185 | pr_warn("could not unregister kmsg_dumper\n"); |
166 | 186 | ||
167 | iounmap(cxt->virt_addr); | 187 | iounmap(cxt->virt_addr); |
168 | release_mem_region(cxt->phys_addr, cxt->size); | 188 | release_mem_region(cxt->phys_addr, cxt->size); |
@@ -179,12 +199,39 @@ static struct platform_driver ramoops_driver = { | |||
179 | 199 | ||
180 | static int __init ramoops_init(void) | 200 | static int __init ramoops_init(void) |
181 | { | 201 | { |
182 | return platform_driver_probe(&ramoops_driver, ramoops_probe); | 202 | int ret; |
203 | ret = platform_driver_probe(&ramoops_driver, ramoops_probe); | ||
204 | if (ret == -ENODEV) { | ||
205 | /* | ||
206 | * If we didn't find a platform device, we use module parameters | ||
207 | * building platform data on the fly. | ||
208 | */ | ||
209 | pr_info("platform device not found, using module parameters\n"); | ||
210 | dummy_data = kzalloc(sizeof(struct ramoops_platform_data), | ||
211 | GFP_KERNEL); | ||
212 | if (!dummy_data) | ||
213 | return -ENOMEM; | ||
214 | dummy_data->mem_size = mem_size; | ||
215 | dummy_data->mem_address = mem_address; | ||
216 | dummy_data->record_size = record_size; | ||
217 | dummy_data->dump_oops = dump_oops; | ||
218 | dummy = platform_create_bundle(&ramoops_driver, ramoops_probe, | ||
219 | NULL, 0, dummy_data, | ||
220 | sizeof(struct ramoops_platform_data)); | ||
221 | |||
222 | if (IS_ERR(dummy)) | ||
223 | ret = PTR_ERR(dummy); | ||
224 | else | ||
225 | ret = 0; | ||
226 | } | ||
227 | |||
228 | return ret; | ||
183 | } | 229 | } |
184 | 230 | ||
185 | static void __exit ramoops_exit(void) | 231 | static void __exit ramoops_exit(void) |
186 | { | 232 | { |
187 | platform_driver_unregister(&ramoops_driver); | 233 | platform_driver_unregister(&ramoops_driver); |
234 | kfree(dummy_data); | ||
188 | } | 235 | } |
189 | 236 | ||
190 | module_init(ramoops_init); | 237 | module_init(ramoops_init); |
diff --git a/drivers/char/random.c b/drivers/char/random.c index d4ddeba56682..729281961f22 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -1523,6 +1523,21 @@ __u32 secure_ip_id(__be32 daddr) | |||
1523 | return half_md4_transform(hash, keyptr->secret); | 1523 | return half_md4_transform(hash, keyptr->secret); |
1524 | } | 1524 | } |
1525 | 1525 | ||
1526 | __u32 secure_ipv6_id(const __be32 daddr[4]) | ||
1527 | { | ||
1528 | const struct keydata *keyptr; | ||
1529 | __u32 hash[4]; | ||
1530 | |||
1531 | keyptr = get_keyptr(); | ||
1532 | |||
1533 | hash[0] = (__force __u32)daddr[0]; | ||
1534 | hash[1] = (__force __u32)daddr[1]; | ||
1535 | hash[2] = (__force __u32)daddr[2]; | ||
1536 | hash[3] = (__force __u32)daddr[3]; | ||
1537 | |||
1538 | return half_md4_transform(hash, keyptr->secret); | ||
1539 | } | ||
1540 | |||
1526 | #ifdef CONFIG_INET | 1541 | #ifdef CONFIG_INET |
1527 | 1542 | ||
1528 | __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, | 1543 | __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr, |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 7beb0e25f1e1..caf8012ef47c 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -534,6 +534,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) | |||
534 | struct duration_t *duration_cap; | 534 | struct duration_t *duration_cap; |
535 | ssize_t rc; | 535 | ssize_t rc; |
536 | u32 timeout; | 536 | u32 timeout; |
537 | unsigned int scale = 1; | ||
537 | 538 | ||
538 | tpm_cmd.header.in = tpm_getcap_header; | 539 | tpm_cmd.header.in = tpm_getcap_header; |
539 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | 540 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
@@ -545,24 +546,30 @@ void tpm_get_timeouts(struct tpm_chip *chip) | |||
545 | if (rc) | 546 | if (rc) |
546 | goto duration; | 547 | goto duration; |
547 | 548 | ||
548 | if (be32_to_cpu(tpm_cmd.header.out.length) | 549 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
549 | != 4 * sizeof(u32)) | 550 | be32_to_cpu(tpm_cmd.header.out.length) |
550 | goto duration; | 551 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) |
552 | return; | ||
551 | 553 | ||
552 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; | 554 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; |
553 | /* Don't overwrite default if value is 0 */ | 555 | /* Don't overwrite default if value is 0 */ |
554 | timeout = be32_to_cpu(timeout_cap->a); | 556 | timeout = be32_to_cpu(timeout_cap->a); |
557 | if (timeout && timeout < 1000) { | ||
558 | /* timeouts in msec rather usec */ | ||
559 | scale = 1000; | ||
560 | chip->vendor.timeout_adjusted = true; | ||
561 | } | ||
555 | if (timeout) | 562 | if (timeout) |
556 | chip->vendor.timeout_a = usecs_to_jiffies(timeout); | 563 | chip->vendor.timeout_a = usecs_to_jiffies(timeout * scale); |
557 | timeout = be32_to_cpu(timeout_cap->b); | 564 | timeout = be32_to_cpu(timeout_cap->b); |
558 | if (timeout) | 565 | if (timeout) |
559 | chip->vendor.timeout_b = usecs_to_jiffies(timeout); | 566 | chip->vendor.timeout_b = usecs_to_jiffies(timeout * scale); |
560 | timeout = be32_to_cpu(timeout_cap->c); | 567 | timeout = be32_to_cpu(timeout_cap->c); |
561 | if (timeout) | 568 | if (timeout) |
562 | chip->vendor.timeout_c = usecs_to_jiffies(timeout); | 569 | chip->vendor.timeout_c = usecs_to_jiffies(timeout * scale); |
563 | timeout = be32_to_cpu(timeout_cap->d); | 570 | timeout = be32_to_cpu(timeout_cap->d); |
564 | if (timeout) | 571 | if (timeout) |
565 | chip->vendor.timeout_d = usecs_to_jiffies(timeout); | 572 | chip->vendor.timeout_d = usecs_to_jiffies(timeout * scale); |
566 | 573 | ||
567 | duration: | 574 | duration: |
568 | tpm_cmd.header.in = tpm_getcap_header; | 575 | tpm_cmd.header.in = tpm_getcap_header; |
@@ -575,23 +582,31 @@ duration: | |||
575 | if (rc) | 582 | if (rc) |
576 | return; | 583 | return; |
577 | 584 | ||
578 | if (be32_to_cpu(tpm_cmd.header.out.return_code) | 585 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
579 | != 3 * sizeof(u32)) | 586 | be32_to_cpu(tpm_cmd.header.out.length) |
587 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) | ||
580 | return; | 588 | return; |
589 | |||
581 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; | 590 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; |
582 | chip->vendor.duration[TPM_SHORT] = | 591 | chip->vendor.duration[TPM_SHORT] = |
583 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); | 592 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); |
593 | chip->vendor.duration[TPM_MEDIUM] = | ||
594 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); | ||
595 | chip->vendor.duration[TPM_LONG] = | ||
596 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); | ||
597 | |||
584 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above | 598 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above |
585 | * value wrong and apparently reports msecs rather than usecs. So we | 599 | * value wrong and apparently reports msecs rather than usecs. So we |
586 | * fix up the resulting too-small TPM_SHORT value to make things work. | 600 | * fix up the resulting too-small TPM_SHORT value to make things work. |
601 | * We also scale the TPM_MEDIUM and -_LONG values by 1000. | ||
587 | */ | 602 | */ |
588 | if (chip->vendor.duration[TPM_SHORT] < (HZ/100)) | 603 | if (chip->vendor.duration[TPM_SHORT] < (HZ / 100)) { |
589 | chip->vendor.duration[TPM_SHORT] = HZ; | 604 | chip->vendor.duration[TPM_SHORT] = HZ; |
590 | 605 | chip->vendor.duration[TPM_MEDIUM] *= 1000; | |
591 | chip->vendor.duration[TPM_MEDIUM] = | 606 | chip->vendor.duration[TPM_LONG] *= 1000; |
592 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); | 607 | chip->vendor.duration_adjusted = true; |
593 | chip->vendor.duration[TPM_LONG] = | 608 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); |
594 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); | 609 | } |
595 | } | 610 | } |
596 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | 611 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); |
597 | 612 | ||
@@ -600,7 +615,7 @@ void tpm_continue_selftest(struct tpm_chip *chip) | |||
600 | u8 data[] = { | 615 | u8 data[] = { |
601 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 616 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
602 | 0, 0, 0, 10, /* length */ | 617 | 0, 0, 0, 10, /* length */ |
603 | 0, 0, 0, 83, /* TPM_ORD_GetCapability */ | 618 | 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ |
604 | }; | 619 | }; |
605 | 620 | ||
606 | tpm_transmit(chip, data, sizeof(data)); | 621 | tpm_transmit(chip, data, sizeof(data)); |
@@ -863,18 +878,24 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
863 | data = tpm_cmd.params.readpubek_out_buffer; | 878 | data = tpm_cmd.params.readpubek_out_buffer; |
864 | str += | 879 | str += |
865 | sprintf(str, | 880 | sprintf(str, |
866 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" | 881 | "Algorithm: %02X %02X %02X %02X\n" |
867 | "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X" | 882 | "Encscheme: %02X %02X\n" |
868 | " %02X %02X %02X %02X %02X %02X %02X %02X\n" | 883 | "Sigscheme: %02X %02X\n" |
869 | "Modulus length: %d\nModulus: \n", | 884 | "Parameters: %02X %02X %02X %02X " |
870 | data[10], data[11], data[12], data[13], data[14], | 885 | "%02X %02X %02X %02X " |
871 | data[15], data[16], data[17], data[22], data[23], | 886 | "%02X %02X %02X %02X\n" |
872 | data[24], data[25], data[26], data[27], data[28], | 887 | "Modulus length: %d\n" |
873 | data[29], data[30], data[31], data[32], data[33], | 888 | "Modulus:\n", |
874 | be32_to_cpu(*((__be32 *) (data + 34)))); | 889 | data[0], data[1], data[2], data[3], |
890 | data[4], data[5], | ||
891 | data[6], data[7], | ||
892 | data[12], data[13], data[14], data[15], | ||
893 | data[16], data[17], data[18], data[19], | ||
894 | data[20], data[21], data[22], data[23], | ||
895 | be32_to_cpu(*((__be32 *) (data + 24)))); | ||
875 | 896 | ||
876 | for (i = 0; i < 256; i++) { | 897 | for (i = 0; i < 256; i++) { |
877 | str += sprintf(str, "%02X ", data[i + 38]); | 898 | str += sprintf(str, "%02X ", data[i + 28]); |
878 | if ((i + 1) % 16 == 0) | 899 | if ((i + 1) % 16 == 0) |
879 | str += sprintf(str, "\n"); | 900 | str += sprintf(str, "\n"); |
880 | } | 901 | } |
@@ -937,6 +958,35 @@ ssize_t tpm_show_caps_1_2(struct device * dev, | |||
937 | } | 958 | } |
938 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | 959 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); |
939 | 960 | ||
961 | ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr, | ||
962 | char *buf) | ||
963 | { | ||
964 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
965 | |||
966 | return sprintf(buf, "%d %d %d [%s]\n", | ||
967 | jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), | ||
968 | jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), | ||
969 | jiffies_to_usecs(chip->vendor.duration[TPM_LONG]), | ||
970 | chip->vendor.duration_adjusted | ||
971 | ? "adjusted" : "original"); | ||
972 | } | ||
973 | EXPORT_SYMBOL_GPL(tpm_show_durations); | ||
974 | |||
975 | ssize_t tpm_show_timeouts(struct device *dev, struct device_attribute *attr, | ||
976 | char *buf) | ||
977 | { | ||
978 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
979 | |||
980 | return sprintf(buf, "%d %d %d %d [%s]\n", | ||
981 | jiffies_to_usecs(chip->vendor.timeout_a), | ||
982 | jiffies_to_usecs(chip->vendor.timeout_b), | ||
983 | jiffies_to_usecs(chip->vendor.timeout_c), | ||
984 | jiffies_to_usecs(chip->vendor.timeout_d), | ||
985 | chip->vendor.timeout_adjusted | ||
986 | ? "adjusted" : "original"); | ||
987 | } | ||
988 | EXPORT_SYMBOL_GPL(tpm_show_timeouts); | ||
989 | |||
940 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | 990 | ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, |
941 | const char *buf, size_t count) | 991 | const char *buf, size_t count) |
942 | { | 992 | { |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 72ddb031b69a..9c4163cfa3ce 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -56,6 +56,10 @@ extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr, | |||
56 | char *); | 56 | char *); |
57 | extern ssize_t tpm_show_temp_deactivated(struct device *, | 57 | extern ssize_t tpm_show_temp_deactivated(struct device *, |
58 | struct device_attribute *attr, char *); | 58 | struct device_attribute *attr, char *); |
59 | extern ssize_t tpm_show_durations(struct device *, | ||
60 | struct device_attribute *attr, char *); | ||
61 | extern ssize_t tpm_show_timeouts(struct device *, | ||
62 | struct device_attribute *attr, char *); | ||
59 | 63 | ||
60 | struct tpm_chip; | 64 | struct tpm_chip; |
61 | 65 | ||
@@ -67,6 +71,7 @@ struct tpm_vendor_specific { | |||
67 | unsigned long base; /* TPM base address */ | 71 | unsigned long base; /* TPM base address */ |
68 | 72 | ||
69 | int irq; | 73 | int irq; |
74 | int probed_irq; | ||
70 | 75 | ||
71 | int region_size; | 76 | int region_size; |
72 | int have_region; | 77 | int have_region; |
@@ -81,7 +86,9 @@ struct tpm_vendor_specific { | |||
81 | struct list_head list; | 86 | struct list_head list; |
82 | int locality; | 87 | int locality; |
83 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ | 88 | unsigned long timeout_a, timeout_b, timeout_c, timeout_d; /* jiffies */ |
89 | bool timeout_adjusted; | ||
84 | unsigned long duration[3]; /* jiffies */ | 90 | unsigned long duration[3]; /* jiffies */ |
91 | bool duration_adjusted; | ||
85 | 92 | ||
86 | wait_queue_head_t read_queue; | 93 | wait_queue_head_t read_queue; |
87 | wait_queue_head_t int_queue; | 94 | wait_queue_head_t int_queue; |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index a605cb7dd898..82facc9104c7 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -330,12 +330,12 @@ static int __init init_nsc(void) | |||
330 | pdev->dev.driver = &nsc_drv.driver; | 330 | pdev->dev.driver = &nsc_drv.driver; |
331 | pdev->dev.release = tpm_nsc_remove; | 331 | pdev->dev.release = tpm_nsc_remove; |
332 | 332 | ||
333 | if ((rc = platform_device_register(pdev)) < 0) | 333 | if ((rc = platform_device_add(pdev)) < 0) |
334 | goto err_free_dev; | 334 | goto err_put_dev; |
335 | 335 | ||
336 | if (request_region(base, 2, "tpm_nsc0") == NULL ) { | 336 | if (request_region(base, 2, "tpm_nsc0") == NULL ) { |
337 | rc = -EBUSY; | 337 | rc = -EBUSY; |
338 | goto err_unreg_dev; | 338 | goto err_del_dev; |
339 | } | 339 | } |
340 | 340 | ||
341 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { | 341 | if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) { |
@@ -382,10 +382,10 @@ static int __init init_nsc(void) | |||
382 | 382 | ||
383 | err_rel_reg: | 383 | err_rel_reg: |
384 | release_region(base, 2); | 384 | release_region(base, 2); |
385 | err_unreg_dev: | 385 | err_del_dev: |
386 | platform_device_unregister(pdev); | 386 | platform_device_del(pdev); |
387 | err_free_dev: | 387 | err_put_dev: |
388 | kfree(pdev); | 388 | platform_device_put(pdev); |
389 | err_unreg_drv: | 389 | err_unreg_drv: |
390 | platform_driver_unregister(&nsc_drv); | 390 | platform_driver_unregister(&nsc_drv); |
391 | return rc; | 391 | return rc; |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index dd21df55689d..7fc2f108f490 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/wait.h> | 27 | #include <linux/wait.h> |
28 | #include <linux/acpi.h> | 28 | #include <linux/acpi.h> |
29 | #include <linux/freezer.h> | ||
29 | #include "tpm.h" | 30 | #include "tpm.h" |
30 | 31 | ||
31 | #define TPM_HEADER_SIZE 10 | 32 | #define TPM_HEADER_SIZE 10 |
@@ -79,7 +80,7 @@ enum tis_defaults { | |||
79 | static LIST_HEAD(tis_chips); | 80 | static LIST_HEAD(tis_chips); |
80 | static DEFINE_SPINLOCK(tis_lock); | 81 | static DEFINE_SPINLOCK(tis_lock); |
81 | 82 | ||
82 | #ifdef CONFIG_ACPI | 83 | #ifdef CONFIG_PNP |
83 | static int is_itpm(struct pnp_dev *dev) | 84 | static int is_itpm(struct pnp_dev *dev) |
84 | { | 85 | { |
85 | struct acpi_device *acpi = pnp_acpi_device(dev); | 86 | struct acpi_device *acpi = pnp_acpi_device(dev); |
@@ -92,11 +93,6 @@ static int is_itpm(struct pnp_dev *dev) | |||
92 | 93 | ||
93 | return 0; | 94 | return 0; |
94 | } | 95 | } |
95 | #else | ||
96 | static int is_itpm(struct pnp_dev *dev) | ||
97 | { | ||
98 | return 0; | ||
99 | } | ||
100 | #endif | 96 | #endif |
101 | 97 | ||
102 | static int check_locality(struct tpm_chip *chip, int l) | 98 | static int check_locality(struct tpm_chip *chip, int l) |
@@ -120,7 +116,7 @@ static void release_locality(struct tpm_chip *chip, int l, int force) | |||
120 | 116 | ||
121 | static int request_locality(struct tpm_chip *chip, int l) | 117 | static int request_locality(struct tpm_chip *chip, int l) |
122 | { | 118 | { |
123 | unsigned long stop; | 119 | unsigned long stop, timeout; |
124 | long rc; | 120 | long rc; |
125 | 121 | ||
126 | if (check_locality(chip, l) >= 0) | 122 | if (check_locality(chip, l) >= 0) |
@@ -129,17 +125,25 @@ static int request_locality(struct tpm_chip *chip, int l) | |||
129 | iowrite8(TPM_ACCESS_REQUEST_USE, | 125 | iowrite8(TPM_ACCESS_REQUEST_USE, |
130 | chip->vendor.iobase + TPM_ACCESS(l)); | 126 | chip->vendor.iobase + TPM_ACCESS(l)); |
131 | 127 | ||
128 | stop = jiffies + chip->vendor.timeout_a; | ||
129 | |||
132 | if (chip->vendor.irq) { | 130 | if (chip->vendor.irq) { |
131 | again: | ||
132 | timeout = stop - jiffies; | ||
133 | if ((long)timeout <= 0) | ||
134 | return -1; | ||
133 | rc = wait_event_interruptible_timeout(chip->vendor.int_queue, | 135 | rc = wait_event_interruptible_timeout(chip->vendor.int_queue, |
134 | (check_locality | 136 | (check_locality |
135 | (chip, l) >= 0), | 137 | (chip, l) >= 0), |
136 | chip->vendor.timeout_a); | 138 | timeout); |
137 | if (rc > 0) | 139 | if (rc > 0) |
138 | return l; | 140 | return l; |
139 | 141 | if (rc == -ERESTARTSYS && freezing(current)) { | |
142 | clear_thread_flag(TIF_SIGPENDING); | ||
143 | goto again; | ||
144 | } | ||
140 | } else { | 145 | } else { |
141 | /* wait for burstcount */ | 146 | /* wait for burstcount */ |
142 | stop = jiffies + chip->vendor.timeout_a; | ||
143 | do { | 147 | do { |
144 | if (check_locality(chip, l) >= 0) | 148 | if (check_locality(chip, l) >= 0) |
145 | return l; | 149 | return l; |
@@ -196,15 +200,24 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | |||
196 | if ((status & mask) == mask) | 200 | if ((status & mask) == mask) |
197 | return 0; | 201 | return 0; |
198 | 202 | ||
203 | stop = jiffies + timeout; | ||
204 | |||
199 | if (chip->vendor.irq) { | 205 | if (chip->vendor.irq) { |
206 | again: | ||
207 | timeout = stop - jiffies; | ||
208 | if ((long)timeout <= 0) | ||
209 | return -ETIME; | ||
200 | rc = wait_event_interruptible_timeout(*queue, | 210 | rc = wait_event_interruptible_timeout(*queue, |
201 | ((tpm_tis_status | 211 | ((tpm_tis_status |
202 | (chip) & mask) == | 212 | (chip) & mask) == |
203 | mask), timeout); | 213 | mask), timeout); |
204 | if (rc > 0) | 214 | if (rc > 0) |
205 | return 0; | 215 | return 0; |
216 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
217 | clear_thread_flag(TIF_SIGPENDING); | ||
218 | goto again; | ||
219 | } | ||
206 | } else { | 220 | } else { |
207 | stop = jiffies + timeout; | ||
208 | do { | 221 | do { |
209 | msleep(TPM_TIMEOUT); | 222 | msleep(TPM_TIMEOUT); |
210 | status = tpm_tis_status(chip); | 223 | status = tpm_tis_status(chip); |
@@ -288,11 +301,10 @@ MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); | |||
288 | * tpm.c can skip polling for the data to be available as the interrupt is | 301 | * tpm.c can skip polling for the data to be available as the interrupt is |
289 | * waited for here | 302 | * waited for here |
290 | */ | 303 | */ |
291 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | 304 | static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) |
292 | { | 305 | { |
293 | int rc, status, burstcnt; | 306 | int rc, status, burstcnt; |
294 | size_t count = 0; | 307 | size_t count = 0; |
295 | u32 ordinal; | ||
296 | 308 | ||
297 | if (request_locality(chip, 0) < 0) | 309 | if (request_locality(chip, 0) < 0) |
298 | return -EBUSY; | 310 | return -EBUSY; |
@@ -327,8 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
327 | 339 | ||
328 | /* write last byte */ | 340 | /* write last byte */ |
329 | iowrite8(buf[count], | 341 | iowrite8(buf[count], |
330 | chip->vendor.iobase + | 342 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); |
331 | TPM_DATA_FIFO(chip->vendor.locality)); | ||
332 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 343 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
333 | &chip->vendor.int_queue); | 344 | &chip->vendor.int_queue); |
334 | status = tpm_tis_status(chip); | 345 | status = tpm_tis_status(chip); |
@@ -337,6 +348,28 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
337 | goto out_err; | 348 | goto out_err; |
338 | } | 349 | } |
339 | 350 | ||
351 | return 0; | ||
352 | |||
353 | out_err: | ||
354 | tpm_tis_ready(chip); | ||
355 | release_locality(chip, chip->vendor.locality, 0); | ||
356 | return rc; | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * If interrupts are used (signaled by an irq set in the vendor structure) | ||
361 | * tpm.c can skip polling for the data to be available as the interrupt is | ||
362 | * waited for here | ||
363 | */ | ||
364 | static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | ||
365 | { | ||
366 | int rc; | ||
367 | u32 ordinal; | ||
368 | |||
369 | rc = tpm_tis_send_data(chip, buf, len); | ||
370 | if (rc < 0) | ||
371 | return rc; | ||
372 | |||
340 | /* go and do it */ | 373 | /* go and do it */ |
341 | iowrite8(TPM_STS_GO, | 374 | iowrite8(TPM_STS_GO, |
342 | chip->vendor.iobase + TPM_STS(chip->vendor.locality)); | 375 | chip->vendor.iobase + TPM_STS(chip->vendor.locality)); |
@@ -358,6 +391,47 @@ out_err: | |||
358 | return rc; | 391 | return rc; |
359 | } | 392 | } |
360 | 393 | ||
394 | /* | ||
395 | * Early probing for iTPM with STS_DATA_EXPECT flaw. | ||
396 | * Try sending command without itpm flag set and if that | ||
397 | * fails, repeat with itpm flag set. | ||
398 | */ | ||
399 | static int probe_itpm(struct tpm_chip *chip) | ||
400 | { | ||
401 | int rc = 0; | ||
402 | u8 cmd_getticks[] = { | ||
403 | 0x00, 0xc1, 0x00, 0x00, 0x00, 0x0a, | ||
404 | 0x00, 0x00, 0x00, 0xf1 | ||
405 | }; | ||
406 | size_t len = sizeof(cmd_getticks); | ||
407 | int rem_itpm = itpm; | ||
408 | |||
409 | itpm = 0; | ||
410 | |||
411 | rc = tpm_tis_send_data(chip, cmd_getticks, len); | ||
412 | if (rc == 0) | ||
413 | goto out; | ||
414 | |||
415 | tpm_tis_ready(chip); | ||
416 | release_locality(chip, chip->vendor.locality, 0); | ||
417 | |||
418 | itpm = 1; | ||
419 | |||
420 | rc = tpm_tis_send_data(chip, cmd_getticks, len); | ||
421 | if (rc == 0) { | ||
422 | dev_info(chip->dev, "Detected an iTPM.\n"); | ||
423 | rc = 1; | ||
424 | } else | ||
425 | rc = -EFAULT; | ||
426 | |||
427 | out: | ||
428 | itpm = rem_itpm; | ||
429 | tpm_tis_ready(chip); | ||
430 | release_locality(chip, chip->vendor.locality, 0); | ||
431 | |||
432 | return rc; | ||
433 | } | ||
434 | |||
361 | static const struct file_operations tis_ops = { | 435 | static const struct file_operations tis_ops = { |
362 | .owner = THIS_MODULE, | 436 | .owner = THIS_MODULE, |
363 | .llseek = no_llseek, | 437 | .llseek = no_llseek, |
@@ -376,6 +450,8 @@ static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, | |||
376 | NULL); | 450 | NULL); |
377 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); | 451 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); |
378 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | 452 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); |
453 | static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); | ||
454 | static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); | ||
379 | 455 | ||
380 | static struct attribute *tis_attrs[] = { | 456 | static struct attribute *tis_attrs[] = { |
381 | &dev_attr_pubek.attr, | 457 | &dev_attr_pubek.attr, |
@@ -385,7 +461,9 @@ static struct attribute *tis_attrs[] = { | |||
385 | &dev_attr_owned.attr, | 461 | &dev_attr_owned.attr, |
386 | &dev_attr_temp_deactivated.attr, | 462 | &dev_attr_temp_deactivated.attr, |
387 | &dev_attr_caps.attr, | 463 | &dev_attr_caps.attr, |
388 | &dev_attr_cancel.attr, NULL, | 464 | &dev_attr_cancel.attr, |
465 | &dev_attr_durations.attr, | ||
466 | &dev_attr_timeouts.attr, NULL, | ||
389 | }; | 467 | }; |
390 | 468 | ||
391 | static struct attribute_group tis_attr_grp = { | 469 | static struct attribute_group tis_attr_grp = { |
@@ -416,7 +494,7 @@ static irqreturn_t tis_int_probe(int irq, void *dev_id) | |||
416 | if (interrupt == 0) | 494 | if (interrupt == 0) |
417 | return IRQ_NONE; | 495 | return IRQ_NONE; |
418 | 496 | ||
419 | chip->vendor.irq = irq; | 497 | chip->vendor.probed_irq = irq; |
420 | 498 | ||
421 | /* Clear interrupts handled with TPM_EOI */ | 499 | /* Clear interrupts handled with TPM_EOI */ |
422 | iowrite32(interrupt, | 500 | iowrite32(interrupt, |
@@ -464,7 +542,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
464 | resource_size_t len, unsigned int irq) | 542 | resource_size_t len, unsigned int irq) |
465 | { | 543 | { |
466 | u32 vendor, intfcaps, intmask; | 544 | u32 vendor, intfcaps, intmask; |
467 | int rc, i; | 545 | int rc, i, irq_s, irq_e; |
468 | struct tpm_chip *chip; | 546 | struct tpm_chip *chip; |
469 | 547 | ||
470 | if (!(chip = tpm_register_hardware(dev, &tpm_tis))) | 548 | if (!(chip = tpm_register_hardware(dev, &tpm_tis))) |
@@ -493,6 +571,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
493 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", | 571 | "1.2 TPM (device-id 0x%X, rev-id %d)\n", |
494 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | 572 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); |
495 | 573 | ||
574 | if (!itpm) { | ||
575 | itpm = probe_itpm(chip); | ||
576 | if (itpm < 0) { | ||
577 | rc = -ENODEV; | ||
578 | goto out_err; | ||
579 | } | ||
580 | } | ||
581 | |||
496 | if (itpm) | 582 | if (itpm) |
497 | dev_info(dev, "Intel iTPM workaround enabled\n"); | 583 | dev_info(dev, "Intel iTPM workaround enabled\n"); |
498 | 584 | ||
@@ -522,6 +608,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
522 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) | 608 | if (intfcaps & TPM_INTF_DATA_AVAIL_INT) |
523 | dev_dbg(dev, "\tData Avail Int Support\n"); | 609 | dev_dbg(dev, "\tData Avail Int Support\n"); |
524 | 610 | ||
611 | /* get the timeouts before testing for irqs */ | ||
612 | tpm_get_timeouts(chip); | ||
613 | |||
525 | /* INTERRUPT Setup */ | 614 | /* INTERRUPT Setup */ |
526 | init_waitqueue_head(&chip->vendor.read_queue); | 615 | init_waitqueue_head(&chip->vendor.read_queue); |
527 | init_waitqueue_head(&chip->vendor.int_queue); | 616 | init_waitqueue_head(&chip->vendor.int_queue); |
@@ -540,13 +629,19 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
540 | if (interrupts) | 629 | if (interrupts) |
541 | chip->vendor.irq = irq; | 630 | chip->vendor.irq = irq; |
542 | if (interrupts && !chip->vendor.irq) { | 631 | if (interrupts && !chip->vendor.irq) { |
543 | chip->vendor.irq = | 632 | irq_s = |
544 | ioread8(chip->vendor.iobase + | 633 | ioread8(chip->vendor.iobase + |
545 | TPM_INT_VECTOR(chip->vendor.locality)); | 634 | TPM_INT_VECTOR(chip->vendor.locality)); |
635 | if (irq_s) { | ||
636 | irq_e = irq_s; | ||
637 | } else { | ||
638 | irq_s = 3; | ||
639 | irq_e = 15; | ||
640 | } | ||
546 | 641 | ||
547 | for (i = 3; i < 16 && chip->vendor.irq == 0; i++) { | 642 | for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) { |
548 | iowrite8(i, chip->vendor.iobase + | 643 | iowrite8(i, chip->vendor.iobase + |
549 | TPM_INT_VECTOR(chip->vendor.locality)); | 644 | TPM_INT_VECTOR(chip->vendor.locality)); |
550 | if (request_irq | 645 | if (request_irq |
551 | (i, tis_int_probe, IRQF_SHARED, | 646 | (i, tis_int_probe, IRQF_SHARED, |
552 | chip->vendor.miscdev.name, chip) != 0) { | 647 | chip->vendor.miscdev.name, chip) != 0) { |
@@ -568,9 +663,22 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
568 | chip->vendor.iobase + | 663 | chip->vendor.iobase + |
569 | TPM_INT_ENABLE(chip->vendor.locality)); | 664 | TPM_INT_ENABLE(chip->vendor.locality)); |
570 | 665 | ||
666 | chip->vendor.probed_irq = 0; | ||
667 | |||
571 | /* Generate Interrupts */ | 668 | /* Generate Interrupts */ |
572 | tpm_gen_interrupt(chip); | 669 | tpm_gen_interrupt(chip); |
573 | 670 | ||
671 | chip->vendor.irq = chip->vendor.probed_irq; | ||
672 | |||
673 | /* free_irq will call into tis_int_probe; | ||
674 | clear all irqs we haven't seen while doing | ||
675 | tpm_gen_interrupt */ | ||
676 | iowrite32(ioread32 | ||
677 | (chip->vendor.iobase + | ||
678 | TPM_INT_STATUS(chip->vendor.locality)), | ||
679 | chip->vendor.iobase + | ||
680 | TPM_INT_STATUS(chip->vendor.locality)); | ||
681 | |||
574 | /* Turn off */ | 682 | /* Turn off */ |
575 | iowrite32(intmask, | 683 | iowrite32(intmask, |
576 | chip->vendor.iobase + | 684 | chip->vendor.iobase + |
@@ -609,7 +717,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
609 | list_add(&chip->vendor.list, &tis_chips); | 717 | list_add(&chip->vendor.list, &tis_chips); |
610 | spin_unlock(&tis_lock); | 718 | spin_unlock(&tis_lock); |
611 | 719 | ||
612 | tpm_get_timeouts(chip); | ||
613 | tpm_continue_selftest(chip); | 720 | tpm_continue_selftest(chip); |
614 | 721 | ||
615 | return 0; | 722 | return 0; |
@@ -619,6 +726,29 @@ out_err: | |||
619 | tpm_remove_hardware(chip->dev); | 726 | tpm_remove_hardware(chip->dev); |
620 | return rc; | 727 | return rc; |
621 | } | 728 | } |
729 | |||
730 | static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | ||
731 | { | ||
732 | u32 intmask; | ||
733 | |||
734 | /* reenable interrupts that device may have lost or | ||
735 | BIOS/firmware may have disabled */ | ||
736 | iowrite8(chip->vendor.irq, chip->vendor.iobase + | ||
737 | TPM_INT_VECTOR(chip->vendor.locality)); | ||
738 | |||
739 | intmask = | ||
740 | ioread32(chip->vendor.iobase + | ||
741 | TPM_INT_ENABLE(chip->vendor.locality)); | ||
742 | |||
743 | intmask |= TPM_INTF_CMD_READY_INT | ||
744 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | ||
745 | | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE; | ||
746 | |||
747 | iowrite32(intmask, | ||
748 | chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); | ||
749 | } | ||
750 | |||
751 | |||
622 | #ifdef CONFIG_PNP | 752 | #ifdef CONFIG_PNP |
623 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 753 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, |
624 | const struct pnp_device_id *pnp_id) | 754 | const struct pnp_device_id *pnp_id) |
@@ -650,6 +780,9 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) | |||
650 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 780 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
651 | int ret; | 781 | int ret; |
652 | 782 | ||
783 | if (chip->vendor.irq) | ||
784 | tpm_tis_reenable_interrupts(chip); | ||
785 | |||
653 | ret = tpm_pm_resume(&dev->dev); | 786 | ret = tpm_pm_resume(&dev->dev); |
654 | if (!ret) | 787 | if (!ret) |
655 | tpm_continue_selftest(chip); | 788 | tpm_continue_selftest(chip); |
@@ -702,6 +835,11 @@ static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) | |||
702 | 835 | ||
703 | static int tpm_tis_resume(struct platform_device *dev) | 836 | static int tpm_tis_resume(struct platform_device *dev) |
704 | { | 837 | { |
838 | struct tpm_chip *chip = dev_get_drvdata(&dev->dev); | ||
839 | |||
840 | if (chip->vendor.irq) | ||
841 | tpm_tis_reenable_interrupts(chip); | ||
842 | |||
705 | return tpm_pm_resume(&dev->dev); | 843 | return tpm_pm_resume(&dev->dev); |
706 | } | 844 | } |
707 | static struct platform_driver tis_drv = { | 845 | static struct platform_driver tis_drv = { |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 39ccdeada791..e90e1c74fd4c 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -621,7 +621,7 @@ static int __devinit hwicap_setup(struct device *dev, int id, | |||
621 | 621 | ||
622 | drvdata->mem_start = regs_res->start; | 622 | drvdata->mem_start = regs_res->start; |
623 | drvdata->mem_end = regs_res->end; | 623 | drvdata->mem_end = regs_res->end; |
624 | drvdata->mem_size = regs_res->end - regs_res->start + 1; | 624 | drvdata->mem_size = resource_size(regs_res); |
625 | 625 | ||
626 | if (!request_mem_region(drvdata->mem_start, | 626 | if (!request_mem_region(drvdata->mem_start, |
627 | drvdata->mem_size, DRIVER_NAME)) { | 627 | drvdata->mem_size, DRIVER_NAME)) { |