diff options
author | Jiri Kosina <jkosina@suse.cz> | 2012-02-03 17:12:42 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2012-02-03 17:13:05 -0500 |
commit | 972c5ae961d6e5103e2b33d935cfa4145fd47140 (patch) | |
tree | 350b2a76b979ba8766c09838617df67ff330eca0 /drivers/char | |
parent | 5196d20305d5e30d871111d3a876cf067dd94255 (diff) | |
parent | 7c7ed8ec337bf5f62cc5287a6eb6b2f1b7504c2f (diff) |
Merge branch 'master' into for-next
Sync with Linus' tree to be able to apply patch to a newer
code (namely drivers/gpu/drm/gma500/psb_intel_lvds.c)
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/amd64-agp.c | 2 | ||||
-rw-r--r-- | drivers/char/agp/backend.c | 12 | ||||
-rw-r--r-- | drivers/char/agp/generic.c | 8 | ||||
-rw-r--r-- | drivers/char/agp/sis-agp.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/atmel-rng.c | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/n2-drv.c | 13 | ||||
-rw-r--r-- | drivers/char/hw_random/octeon-rng.c | 13 | ||||
-rw-r--r-- | drivers/char/hw_random/pasemi-rng.c | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/picoxcell-rng.c | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/ppc4xx-rng.c | 12 | ||||
-rw-r--r-- | drivers/char/hw_random/timeriomem-rng.c | 13 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 2 | ||||
-rw-r--r-- | drivers/char/i8k.c | 8 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 2 | ||||
-rw-r--r-- | drivers/char/lp.c | 2 | ||||
-rw-r--r-- | drivers/char/nwflash.c | 2 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 2 | ||||
-rw-r--r-- | drivers/char/ramoops.c | 24 | ||||
-rw-r--r-- | drivers/char/random.c | 8 | ||||
-rw-r--r-- | drivers/char/tpm/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 146 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 12 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 90 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 140 |
24 files changed, 323 insertions, 228 deletions
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 780498d76581..444f8b6ab411 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #define ULI_X86_64_ENU_SCR_REG 0x54 | 33 | #define ULI_X86_64_ENU_SCR_REG 0x54 |
34 | 34 | ||
35 | static struct resource *aperture_resource; | 35 | static struct resource *aperture_resource; |
36 | static int __initdata agp_try_unsupported = 1; | 36 | static bool __initdata agp_try_unsupported = 1; |
37 | static int agp_bridges_found; | 37 | static int agp_bridges_found; |
38 | 38 | ||
39 | static void amd64_tlbflush(struct agp_memory *temp) | 39 | static void amd64_tlbflush(struct agp_memory *temp) |
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 4b71647782d0..317c28ce8328 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c | |||
@@ -194,10 +194,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
194 | 194 | ||
195 | err_out: | 195 | err_out: |
196 | if (bridge->driver->needs_scratch_page) { | 196 | if (bridge->driver->needs_scratch_page) { |
197 | void *va = page_address(bridge->scratch_page_page); | 197 | struct page *page = bridge->scratch_page_page; |
198 | 198 | ||
199 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); | 199 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); |
200 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); | 200 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); |
201 | } | 201 | } |
202 | if (got_gatt) | 202 | if (got_gatt) |
203 | bridge->driver->free_gatt_table(bridge); | 203 | bridge->driver->free_gatt_table(bridge); |
@@ -221,10 +221,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) | |||
221 | 221 | ||
222 | if (bridge->driver->agp_destroy_page && | 222 | if (bridge->driver->agp_destroy_page && |
223 | bridge->driver->needs_scratch_page) { | 223 | bridge->driver->needs_scratch_page) { |
224 | void *va = page_address(bridge->scratch_page_page); | 224 | struct page *page = bridge->scratch_page_page; |
225 | 225 | ||
226 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); | 226 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); |
227 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); | 227 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); |
228 | } | 228 | } |
229 | } | 229 | } |
230 | 230 | ||
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index b072648dc3f6..17e05d1076b3 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -514,12 +514,12 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ | |||
514 | switch (*bridge_agpstat & 7) { | 514 | switch (*bridge_agpstat & 7) { |
515 | case 4: | 515 | case 4: |
516 | *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); | 516 | *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); |
517 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate" | 517 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate. " |
518 | "Fixing up support for x2 & x1\n"); | 518 | "Fixing up support for x2 & x1\n"); |
519 | break; | 519 | break; |
520 | case 2: | 520 | case 2: |
521 | *bridge_agpstat |= AGPSTAT2_1X; | 521 | *bridge_agpstat |= AGPSTAT2_1X; |
522 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate" | 522 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate. " |
523 | "Fixing up support for x1\n"); | 523 | "Fixing up support for x1\n"); |
524 | break; | 524 | break; |
525 | default: | 525 | default: |
@@ -693,7 +693,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ | |||
693 | *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); | 693 | *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); |
694 | *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); | 694 | *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); |
695 | } else { | 695 | } else { |
696 | printk(KERN_INFO PFX "Fell back to AGPx4 mode because"); | 696 | printk(KERN_INFO PFX "Fell back to AGPx4 mode because "); |
697 | if (!(*bridge_agpstat & AGPSTAT3_8X)) { | 697 | if (!(*bridge_agpstat & AGPSTAT3_8X)) { |
698 | printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n", | 698 | printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n", |
699 | *bridge_agpstat, origbridge); | 699 | *bridge_agpstat, origbridge); |
@@ -956,7 +956,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
956 | bridge->driver->cache_flush(); | 956 | bridge->driver->cache_flush(); |
957 | #ifdef CONFIG_X86 | 957 | #ifdef CONFIG_X86 |
958 | if (set_memory_uc((unsigned long)table, 1 << page_order)) | 958 | if (set_memory_uc((unsigned long)table, 1 << page_order)) |
959 | printk(KERN_WARNING "Could not set GATT table memory to UC!"); | 959 | printk(KERN_WARNING "Could not set GATT table memory to UC!\n"); |
960 | 960 | ||
961 | bridge->gatt_table = (void *)table; | 961 | bridge->gatt_table = (void *)table; |
962 | #else | 962 | #else |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 29aacd81de78..08704ae53956 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #define PCI_DEVICE_ID_SI_662 0x0662 | 17 | #define PCI_DEVICE_ID_SI_662 0x0662 |
18 | #define PCI_DEVICE_ID_SI_671 0x0671 | 18 | #define PCI_DEVICE_ID_SI_671 0x0671 |
19 | 19 | ||
20 | static int __devinitdata agp_sis_force_delay = 0; | 20 | static bool __devinitdata agp_sis_force_delay = 0; |
21 | static int __devinitdata agp_sis_agp_spec = -1; | 21 | static int __devinitdata agp_sis_agp_spec = -1; |
22 | 22 | ||
23 | static int sis_fetch_size(void) | 23 | static int sis_fetch_size(void) |
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 241df2e76aba..f518b99f53f5 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c | |||
@@ -141,17 +141,7 @@ static struct platform_driver atmel_trng_driver = { | |||
141 | }, | 141 | }, |
142 | }; | 142 | }; |
143 | 143 | ||
144 | static int __init atmel_trng_init(void) | 144 | module_platform_driver(atmel_trng_driver); |
145 | { | ||
146 | return platform_driver_register(&atmel_trng_driver); | ||
147 | } | ||
148 | module_init(atmel_trng_init); | ||
149 | |||
150 | static void __exit atmel_trng_exit(void) | ||
151 | { | ||
152 | platform_driver_unregister(&atmel_trng_driver); | ||
153 | } | ||
154 | module_exit(atmel_trng_exit); | ||
155 | 145 | ||
156 | MODULE_LICENSE("GPL"); | 146 | MODULE_LICENSE("GPL"); |
157 | MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); | 147 | MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index c3de70de00d4..ebd48f0135da 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -770,15 +770,4 @@ static struct platform_driver n2rng_driver = { | |||
770 | .remove = __devexit_p(n2rng_remove), | 770 | .remove = __devexit_p(n2rng_remove), |
771 | }; | 771 | }; |
772 | 772 | ||
773 | static int __init n2rng_init(void) | 773 | module_platform_driver(n2rng_driver); |
774 | { | ||
775 | return platform_driver_register(&n2rng_driver); | ||
776 | } | ||
777 | |||
778 | static void __exit n2rng_exit(void) | ||
779 | { | ||
780 | platform_driver_unregister(&n2rng_driver); | ||
781 | } | ||
782 | |||
783 | module_init(n2rng_init); | ||
784 | module_exit(n2rng_exit); | ||
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c index 9cd0feca318c..0943edc782a1 100644 --- a/drivers/char/hw_random/octeon-rng.c +++ b/drivers/char/hw_random/octeon-rng.c | |||
@@ -131,18 +131,7 @@ static struct platform_driver octeon_rng_driver = { | |||
131 | .remove = __exit_p(octeon_rng_remove), | 131 | .remove = __exit_p(octeon_rng_remove), |
132 | }; | 132 | }; |
133 | 133 | ||
134 | static int __init octeon_rng_mod_init(void) | 134 | module_platform_driver(octeon_rng_driver); |
135 | { | ||
136 | return platform_driver_register(&octeon_rng_driver); | ||
137 | } | ||
138 | |||
139 | static void __exit octeon_rng_mod_exit(void) | ||
140 | { | ||
141 | platform_driver_unregister(&octeon_rng_driver); | ||
142 | } | ||
143 | |||
144 | module_init(octeon_rng_mod_init); | ||
145 | module_exit(octeon_rng_mod_exit); | ||
146 | 135 | ||
147 | MODULE_AUTHOR("David Daney"); | 136 | MODULE_AUTHOR("David Daney"); |
148 | MODULE_LICENSE("GPL"); | 137 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index 1d504815e6db..3a632673aed5 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c | |||
@@ -148,17 +148,7 @@ static struct platform_driver rng_driver = { | |||
148 | .remove = rng_remove, | 148 | .remove = rng_remove, |
149 | }; | 149 | }; |
150 | 150 | ||
151 | static int __init rng_init(void) | 151 | module_platform_driver(rng_driver); |
152 | { | ||
153 | return platform_driver_register(&rng_driver); | ||
154 | } | ||
155 | module_init(rng_init); | ||
156 | |||
157 | static void __exit rng_exit(void) | ||
158 | { | ||
159 | platform_driver_unregister(&rng_driver); | ||
160 | } | ||
161 | module_exit(rng_exit); | ||
162 | 152 | ||
163 | MODULE_LICENSE("GPL"); | 153 | MODULE_LICENSE("GPL"); |
164 | MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); | 154 | MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); |
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c index 990d55a5e3e8..97bd891422c7 100644 --- a/drivers/char/hw_random/picoxcell-rng.c +++ b/drivers/char/hw_random/picoxcell-rng.c | |||
@@ -191,17 +191,7 @@ static struct platform_driver picoxcell_trng_driver = { | |||
191 | }, | 191 | }, |
192 | }; | 192 | }; |
193 | 193 | ||
194 | static int __init picoxcell_trng_init(void) | 194 | module_platform_driver(picoxcell_trng_driver); |
195 | { | ||
196 | return platform_driver_register(&picoxcell_trng_driver); | ||
197 | } | ||
198 | module_init(picoxcell_trng_init); | ||
199 | |||
200 | static void __exit picoxcell_trng_exit(void) | ||
201 | { | ||
202 | platform_driver_unregister(&picoxcell_trng_driver); | ||
203 | } | ||
204 | module_exit(picoxcell_trng_exit); | ||
205 | 195 | ||
206 | MODULE_LICENSE("GPL"); | 196 | MODULE_LICENSE("GPL"); |
207 | MODULE_AUTHOR("Jamie Iles"); | 197 | MODULE_AUTHOR("Jamie Iles"); |
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c index b8afa6a4ff67..c51762c13031 100644 --- a/drivers/char/hw_random/ppc4xx-rng.c +++ b/drivers/char/hw_random/ppc4xx-rng.c | |||
@@ -139,17 +139,7 @@ static struct platform_driver ppc4xx_rng_driver = { | |||
139 | .remove = ppc4xx_rng_remove, | 139 | .remove = ppc4xx_rng_remove, |
140 | }; | 140 | }; |
141 | 141 | ||
142 | static int __init ppc4xx_rng_init(void) | 142 | module_platform_driver(ppc4xx_rng_driver); |
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 | 143 | ||
154 | MODULE_LICENSE("GPL"); | 144 | MODULE_LICENSE("GPL"); |
155 | MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>"); | 145 | MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>"); |
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index a8428e6f64a9..f1a1618db1fb 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c | |||
@@ -149,18 +149,7 @@ static struct platform_driver timeriomem_rng_driver = { | |||
149 | .remove = __devexit_p(timeriomem_rng_remove), | 149 | .remove = __devexit_p(timeriomem_rng_remove), |
150 | }; | 150 | }; |
151 | 151 | ||
152 | static int __init timeriomem_rng_init(void) | 152 | module_platform_driver(timeriomem_rng_driver); |
153 | { | ||
154 | return platform_driver_register(&timeriomem_rng_driver); | ||
155 | } | ||
156 | |||
157 | static void __exit timeriomem_rng_exit(void) | ||
158 | { | ||
159 | platform_driver_unregister(&timeriomem_rng_driver); | ||
160 | } | ||
161 | |||
162 | module_init(timeriomem_rng_init); | ||
163 | module_exit(timeriomem_rng_exit); | ||
164 | 153 | ||
165 | MODULE_LICENSE("GPL"); | 154 | MODULE_LICENSE("GPL"); |
166 | MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); | 155 | MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); |
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index fd699ccecf5b..723725bbb96b 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -47,7 +47,7 @@ static void register_buffer(u8 *buf, size_t size) | |||
47 | sg_init_one(&sg, buf, size); | 47 | sg_init_one(&sg, buf, size); |
48 | 48 | ||
49 | /* There should always be room for one buffer. */ | 49 | /* There should always be room for one buffer. */ |
50 | if (virtqueue_add_buf(vq, &sg, 0, 1, buf) < 0) | 50 | if (virtqueue_add_buf(vq, &sg, 0, 1, buf, GFP_KERNEL) < 0) |
51 | BUG(); | 51 | BUG(); |
52 | 52 | ||
53 | virtqueue_kick(vq); | 53 | virtqueue_kick(vq); |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 6e40072fbf67..40cc0cf2ded6 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
@@ -69,19 +69,19 @@ MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); | |||
69 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); | 69 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); |
70 | MODULE_LICENSE("GPL"); | 70 | MODULE_LICENSE("GPL"); |
71 | 71 | ||
72 | static int force; | 72 | static bool force; |
73 | module_param(force, bool, 0); | 73 | module_param(force, bool, 0); |
74 | MODULE_PARM_DESC(force, "Force loading without checking for supported models"); | 74 | MODULE_PARM_DESC(force, "Force loading without checking for supported models"); |
75 | 75 | ||
76 | static int ignore_dmi; | 76 | static bool ignore_dmi; |
77 | module_param(ignore_dmi, bool, 0); | 77 | module_param(ignore_dmi, bool, 0); |
78 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); | 78 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); |
79 | 79 | ||
80 | static int restricted; | 80 | static bool restricted; |
81 | module_param(restricted, bool, 0); | 81 | module_param(restricted, bool, 0); |
82 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); | 82 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); |
83 | 83 | ||
84 | static int power_status; | 84 | static bool power_status; |
85 | module_param(power_status, bool, 0600); | 85 | module_param(power_status, bool, 0600); |
86 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); | 86 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); |
87 | 87 | ||
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 9397ab49b72e..50fcf9c04569 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -1227,7 +1227,7 @@ static int smi_num; /* Used to sequence the SMIs */ | |||
1227 | #define DEFAULT_REGSPACING 1 | 1227 | #define DEFAULT_REGSPACING 1 |
1228 | #define DEFAULT_REGSIZE 1 | 1228 | #define DEFAULT_REGSIZE 1 |
1229 | 1229 | ||
1230 | static int si_trydefaults = 1; | 1230 | static bool si_trydefaults = 1; |
1231 | static char *si_type[SI_MAX_PARMS]; | 1231 | static char *si_type[SI_MAX_PARMS]; |
1232 | #define MAX_SI_TYPE_STR 30 | 1232 | #define MAX_SI_TYPE_STR 30 |
1233 | static char si_type_str[MAX_SI_TYPE_STR]; | 1233 | static char si_type_str[MAX_SI_TYPE_STR]; |
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index 97c3edb95ae7..f43485607063 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
@@ -829,7 +829,7 @@ static struct console lpcons = { | |||
829 | 829 | ||
830 | static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; | 830 | static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; |
831 | static char *parport[LP_NO]; | 831 | static char *parport[LP_NO]; |
832 | static int reset; | 832 | static bool reset; |
833 | 833 | ||
834 | module_param_array(parport, charp, NULL, 0); | 834 | module_param_array(parport, charp, NULL, 0); |
835 | module_param(reset, bool, 0); | 835 | module_param(reset, bool, 0); |
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index a12f52400dbc..bf586ae1ee83 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c | |||
@@ -51,7 +51,7 @@ static int write_block(unsigned long p, const char __user *buf, int count); | |||
51 | #define KFLASH_ID 0x89A6 //Intel flash | 51 | #define KFLASH_ID 0x89A6 //Intel flash |
52 | #define KFLASH_ID4 0xB0D4 //Intel flash 4Meg | 52 | #define KFLASH_ID4 0xB0D4 //Intel flash 4Meg |
53 | 53 | ||
54 | static int flashdebug; //if set - we will display progress msgs | 54 | static bool flashdebug; //if set - we will display progress msgs |
55 | 55 | ||
56 | static int gbWriteEnable; | 56 | static int gbWriteEnable; |
57 | static int gbWriteBase64Enable; | 57 | static int gbWriteBase64Enable; |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 15781396af25..07f6a5abe372 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -439,7 +439,7 @@ static int mgslpc_device_count = 0; | |||
439 | * .text section address and breakpoint on module load. | 439 | * .text section address and breakpoint on module load. |
440 | * This is useful for use with gdb and add-symbol-file command. | 440 | * This is useful for use with gdb and add-symbol-file command. |
441 | */ | 441 | */ |
442 | static int break_on_load=0; | 442 | static bool break_on_load=0; |
443 | 443 | ||
444 | /* | 444 | /* |
445 | * Driver major number, defaults to zero to get auto | 445 | * Driver major number, defaults to zero to get auto |
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c index 7c7f42a1f880..9fec3232b736 100644 --- a/drivers/char/ramoops.c +++ b/drivers/char/ramoops.c | |||
@@ -83,8 +83,7 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper, | |||
83 | struct timeval timestamp; | 83 | struct timeval timestamp; |
84 | 84 | ||
85 | if (reason != KMSG_DUMP_OOPS && | 85 | if (reason != KMSG_DUMP_OOPS && |
86 | reason != KMSG_DUMP_PANIC && | 86 | reason != KMSG_DUMP_PANIC) |
87 | reason != KMSG_DUMP_KEXEC) | ||
88 | return; | 87 | return; |
89 | 88 | ||
90 | /* Only dump oopses if dump_oops is set */ | 89 | /* Only dump oopses if dump_oops is set */ |
@@ -126,8 +125,8 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
126 | goto fail3; | 125 | goto fail3; |
127 | } | 126 | } |
128 | 127 | ||
129 | rounddown_pow_of_two(pdata->mem_size); | 128 | pdata->mem_size = rounddown_pow_of_two(pdata->mem_size); |
130 | rounddown_pow_of_two(pdata->record_size); | 129 | pdata->record_size = rounddown_pow_of_two(pdata->record_size); |
131 | 130 | ||
132 | /* Check for the minimum memory size */ | 131 | /* Check for the minimum memory size */ |
133 | if (pdata->mem_size < MIN_MEM_SIZE && | 132 | if (pdata->mem_size < MIN_MEM_SIZE && |
@@ -148,14 +147,6 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
148 | cxt->phys_addr = pdata->mem_address; | 147 | cxt->phys_addr = pdata->mem_address; |
149 | cxt->record_size = pdata->record_size; | 148 | cxt->record_size = pdata->record_size; |
150 | cxt->dump_oops = pdata->dump_oops; | 149 | cxt->dump_oops = pdata->dump_oops; |
151 | /* | ||
152 | * Update the module parameter variables as well so they are visible | ||
153 | * through /sys/module/ramoops/parameters/ | ||
154 | */ | ||
155 | mem_size = pdata->mem_size; | ||
156 | mem_address = pdata->mem_address; | ||
157 | record_size = pdata->record_size; | ||
158 | dump_oops = pdata->dump_oops; | ||
159 | 150 | ||
160 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { | 151 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { |
161 | pr_err("request mem region failed\n"); | 152 | pr_err("request mem region failed\n"); |
@@ -176,6 +167,15 @@ static int __init ramoops_probe(struct platform_device *pdev) | |||
176 | goto fail1; | 167 | goto fail1; |
177 | } | 168 | } |
178 | 169 | ||
170 | /* | ||
171 | * Update the module parameter variables as well so they are visible | ||
172 | * through /sys/module/ramoops/parameters/ | ||
173 | */ | ||
174 | mem_size = pdata->mem_size; | ||
175 | mem_address = pdata->mem_address; | ||
176 | record_size = pdata->record_size; | ||
177 | dump_oops = pdata->dump_oops; | ||
178 | |||
179 | return 0; | 179 | return 0; |
180 | 180 | ||
181 | fail1: | 181 | fail1: |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 85da8740586b..54ca8b23cde3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -387,7 +387,7 @@ static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); | |||
387 | static struct fasync_struct *fasync; | 387 | static struct fasync_struct *fasync; |
388 | 388 | ||
389 | #if 0 | 389 | #if 0 |
390 | static int debug; | 390 | static bool debug; |
391 | module_param(debug, bool, 0644); | 391 | module_param(debug, bool, 0644); |
392 | #define DEBUG_ENT(fmt, arg...) do { \ | 392 | #define DEBUG_ENT(fmt, arg...) do { \ |
393 | if (debug) \ | 393 | if (debug) \ |
@@ -965,6 +965,7 @@ EXPORT_SYMBOL(get_random_bytes); | |||
965 | */ | 965 | */ |
966 | static void init_std_data(struct entropy_store *r) | 966 | static void init_std_data(struct entropy_store *r) |
967 | { | 967 | { |
968 | int i; | ||
968 | ktime_t now; | 969 | ktime_t now; |
969 | unsigned long flags; | 970 | unsigned long flags; |
970 | 971 | ||
@@ -974,6 +975,11 @@ static void init_std_data(struct entropy_store *r) | |||
974 | 975 | ||
975 | now = ktime_get_real(); | 976 | now = ktime_get_real(); |
976 | mix_pool_bytes(r, &now, sizeof(now)); | 977 | mix_pool_bytes(r, &now, sizeof(now)); |
978 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) { | ||
979 | if (!arch_get_random_long(&flags)) | ||
980 | break; | ||
981 | mix_pool_bytes(r, &flags, sizeof(flags)); | ||
982 | } | ||
977 | mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); | 983 | mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); |
978 | } | 984 | } |
979 | 985 | ||
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index fa567f1158c2..7fc75e47e6d0 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -27,6 +27,7 @@ if TCG_TPM | |||
27 | 27 | ||
28 | config TCG_TIS | 28 | config TCG_TIS |
29 | tristate "TPM Interface Specification 1.2 Interface" | 29 | tristate "TPM Interface Specification 1.2 Interface" |
30 | depends on X86 | ||
30 | ---help--- | 31 | ---help--- |
31 | If you have a TPM security chip that is compliant with the | 32 | If you have a TPM security chip that is compliant with the |
32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 33 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
@@ -35,6 +36,7 @@ config TCG_TIS | |||
35 | 36 | ||
36 | config TCG_NSC | 37 | config TCG_NSC |
37 | tristate "National Semiconductor TPM Interface" | 38 | tristate "National Semiconductor TPM Interface" |
39 | depends on X86 | ||
38 | ---help--- | 40 | ---help--- |
39 | If you have a TPM security chip from National Semiconductor | 41 | If you have a TPM security chip from National Semiconductor |
40 | say Yes and it will be accessible from within Linux. To | 42 | say Yes and it will be accessible from within Linux. To |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 361a1dff8f77..32362cf35b8d 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
30 | #include <linux/freezer.h> | ||
30 | 31 | ||
31 | #include "tpm.h" | 32 | #include "tpm.h" |
32 | 33 | ||
@@ -440,7 +441,6 @@ out: | |||
440 | } | 441 | } |
441 | 442 | ||
442 | #define TPM_DIGEST_SIZE 20 | 443 | #define TPM_DIGEST_SIZE 20 |
443 | #define TPM_ERROR_SIZE 10 | ||
444 | #define TPM_RET_CODE_IDX 6 | 444 | #define TPM_RET_CODE_IDX 6 |
445 | 445 | ||
446 | enum tpm_capabilities { | 446 | enum tpm_capabilities { |
@@ -469,12 +469,14 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | |||
469 | len = tpm_transmit(chip,(u8 *) cmd, len); | 469 | len = tpm_transmit(chip,(u8 *) cmd, len); |
470 | if (len < 0) | 470 | if (len < 0) |
471 | return len; | 471 | return len; |
472 | if (len == TPM_ERROR_SIZE) { | 472 | else if (len < TPM_HEADER_SIZE) |
473 | err = be32_to_cpu(cmd->header.out.return_code); | 473 | return -EFAULT; |
474 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | 474 | |
475 | return err; | 475 | err = be32_to_cpu(cmd->header.out.return_code); |
476 | } | 476 | if (err != 0) |
477 | return 0; | 477 | dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); |
478 | |||
479 | return err; | ||
478 | } | 480 | } |
479 | 481 | ||
480 | #define TPM_INTERNAL_RESULT_SIZE 200 | 482 | #define TPM_INTERNAL_RESULT_SIZE 200 |
@@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) | |||
530 | } | 532 | } |
531 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 533 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
532 | 534 | ||
533 | void tpm_get_timeouts(struct tpm_chip *chip) | 535 | int tpm_get_timeouts(struct tpm_chip *chip) |
534 | { | 536 | { |
535 | struct tpm_cmd_t tpm_cmd; | 537 | struct tpm_cmd_t tpm_cmd; |
536 | struct timeout_t *timeout_cap; | 538 | struct timeout_t *timeout_cap; |
@@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip) | |||
552 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || | 554 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
553 | be32_to_cpu(tpm_cmd.header.out.length) | 555 | be32_to_cpu(tpm_cmd.header.out.length) |
554 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) | 556 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) |
555 | return; | 557 | return -EINVAL; |
556 | 558 | ||
557 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; | 559 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; |
558 | /* Don't overwrite default if value is 0 */ | 560 | /* Don't overwrite default if value is 0 */ |
@@ -583,12 +585,12 @@ duration: | |||
583 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 585 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
584 | "attempting to determine the durations"); | 586 | "attempting to determine the durations"); |
585 | if (rc) | 587 | if (rc) |
586 | return; | 588 | return rc; |
587 | 589 | ||
588 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || | 590 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
589 | be32_to_cpu(tpm_cmd.header.out.length) | 591 | be32_to_cpu(tpm_cmd.header.out.length) |
590 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) | 592 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) |
591 | return; | 593 | return -EINVAL; |
592 | 594 | ||
593 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; | 595 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; |
594 | chip->vendor.duration[TPM_SHORT] = | 596 | chip->vendor.duration[TPM_SHORT] = |
@@ -610,20 +612,36 @@ duration: | |||
610 | chip->vendor.duration_adjusted = true; | 612 | chip->vendor.duration_adjusted = true; |
611 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); | 613 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); |
612 | } | 614 | } |
615 | return 0; | ||
613 | } | 616 | } |
614 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | 617 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); |
615 | 618 | ||
616 | void tpm_continue_selftest(struct tpm_chip *chip) | 619 | #define TPM_ORD_CONTINUE_SELFTEST 83 |
620 | #define CONTINUE_SELFTEST_RESULT_SIZE 10 | ||
621 | |||
622 | static struct tpm_input_header continue_selftest_header = { | ||
623 | .tag = TPM_TAG_RQU_COMMAND, | ||
624 | .length = cpu_to_be32(10), | ||
625 | .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), | ||
626 | }; | ||
627 | |||
628 | /** | ||
629 | * tpm_continue_selftest -- run TPM's selftest | ||
630 | * @chip: TPM chip to use | ||
631 | * | ||
632 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
633 | * a TPM error code. | ||
634 | */ | ||
635 | static int tpm_continue_selftest(struct tpm_chip *chip) | ||
617 | { | 636 | { |
618 | u8 data[] = { | 637 | int rc; |
619 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 638 | struct tpm_cmd_t cmd; |
620 | 0, 0, 0, 10, /* length */ | ||
621 | 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ | ||
622 | }; | ||
623 | 639 | ||
624 | tpm_transmit(chip, data, sizeof(data)); | 640 | cmd.header.in = continue_selftest_header; |
641 | rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, | ||
642 | "continue selftest"); | ||
643 | return rc; | ||
625 | } | 644 | } |
626 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | ||
627 | 645 | ||
628 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 646 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
629 | char *buf) | 647 | char *buf) |
@@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = { | |||
718 | .ordinal = TPM_ORDINAL_PCRREAD | 736 | .ordinal = TPM_ORDINAL_PCRREAD |
719 | }; | 737 | }; |
720 | 738 | ||
721 | int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | 739 | static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
722 | { | 740 | { |
723 | int rc; | 741 | int rc; |
724 | struct tpm_cmd_t cmd; | 742 | struct tpm_cmd_t cmd; |
@@ -798,6 +816,54 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
798 | } | 816 | } |
799 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); | 817 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); |
800 | 818 | ||
819 | /** | ||
820 | * tpm_do_selftest - have the TPM continue its selftest and wait until it | ||
821 | * can receive further commands | ||
822 | * @chip: TPM chip to use | ||
823 | * | ||
824 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
825 | * a TPM error code. | ||
826 | */ | ||
827 | int tpm_do_selftest(struct tpm_chip *chip) | ||
828 | { | ||
829 | int rc; | ||
830 | u8 digest[TPM_DIGEST_SIZE]; | ||
831 | unsigned int loops; | ||
832 | unsigned int delay_msec = 1000; | ||
833 | unsigned long duration; | ||
834 | |||
835 | duration = tpm_calc_ordinal_duration(chip, | ||
836 | TPM_ORD_CONTINUE_SELFTEST); | ||
837 | |||
838 | loops = jiffies_to_msecs(duration) / delay_msec; | ||
839 | |||
840 | rc = tpm_continue_selftest(chip); | ||
841 | /* This may fail if there was no TPM driver during a suspend/resume | ||
842 | * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) | ||
843 | */ | ||
844 | if (rc) | ||
845 | return rc; | ||
846 | |||
847 | do { | ||
848 | rc = __tpm_pcr_read(chip, 0, digest); | ||
849 | if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { | ||
850 | dev_info(chip->dev, | ||
851 | "TPM is disabled/deactivated (0x%X)\n", rc); | ||
852 | /* TPM is disabled and/or deactivated; driver can | ||
853 | * proceed and TPM does handle commands for | ||
854 | * suspend/resume correctly | ||
855 | */ | ||
856 | return 0; | ||
857 | } | ||
858 | if (rc != TPM_WARN_DOING_SELFTEST) | ||
859 | return rc; | ||
860 | msleep(delay_msec); | ||
861 | } while (--loops > 0); | ||
862 | |||
863 | return rc; | ||
864 | } | ||
865 | EXPORT_SYMBOL_GPL(tpm_do_selftest); | ||
866 | |||
801 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) | 867 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) |
802 | { | 868 | { |
803 | struct tpm_chip *chip; | 869 | struct tpm_chip *chip; |
@@ -1005,6 +1071,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | |||
1005 | } | 1071 | } |
1006 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | 1072 | EXPORT_SYMBOL_GPL(tpm_store_cancel); |
1007 | 1073 | ||
1074 | int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
1075 | wait_queue_head_t *queue) | ||
1076 | { | ||
1077 | unsigned long stop; | ||
1078 | long rc; | ||
1079 | u8 status; | ||
1080 | |||
1081 | /* check current status */ | ||
1082 | status = chip->vendor.status(chip); | ||
1083 | if ((status & mask) == mask) | ||
1084 | return 0; | ||
1085 | |||
1086 | stop = jiffies + timeout; | ||
1087 | |||
1088 | if (chip->vendor.irq) { | ||
1089 | again: | ||
1090 | timeout = stop - jiffies; | ||
1091 | if ((long)timeout <= 0) | ||
1092 | return -ETIME; | ||
1093 | rc = wait_event_interruptible_timeout(*queue, | ||
1094 | ((chip->vendor.status(chip) | ||
1095 | & mask) == mask), | ||
1096 | timeout); | ||
1097 | if (rc > 0) | ||
1098 | return 0; | ||
1099 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
1100 | clear_thread_flag(TIF_SIGPENDING); | ||
1101 | goto again; | ||
1102 | } | ||
1103 | } else { | ||
1104 | do { | ||
1105 | msleep(TPM_TIMEOUT); | ||
1106 | status = chip->vendor.status(chip); | ||
1107 | if ((status & mask) == mask) | ||
1108 | return 0; | ||
1109 | } while (time_before(jiffies, stop)); | ||
1110 | } | ||
1111 | return -ETIME; | ||
1112 | } | ||
1113 | EXPORT_SYMBOL_GPL(wait_for_tpm_stat); | ||
1008 | /* | 1114 | /* |
1009 | * Device file system interface to the TPM | 1115 | * Device file system interface to the TPM |
1010 | * | 1116 | * |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 9c4163cfa3ce..010547138281 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -38,6 +38,11 @@ enum tpm_addr { | |||
38 | TPM_ADDR = 0x4E, | 38 | TPM_ADDR = 0x4E, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | #define TPM_WARN_DOING_SELFTEST 0x802 | ||
42 | #define TPM_ERR_DEACTIVATED 0x6 | ||
43 | #define TPM_ERR_DISABLED 0x7 | ||
44 | |||
45 | #define TPM_HEADER_SIZE 10 | ||
41 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, | 46 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, |
42 | char *); | 47 | char *); |
43 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | 48 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, |
@@ -279,9 +284,9 @@ struct tpm_cmd_t { | |||
279 | 284 | ||
280 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | 285 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); |
281 | 286 | ||
282 | extern void tpm_get_timeouts(struct tpm_chip *); | 287 | extern int tpm_get_timeouts(struct tpm_chip *); |
283 | extern void tpm_gen_interrupt(struct tpm_chip *); | 288 | extern void tpm_gen_interrupt(struct tpm_chip *); |
284 | extern void tpm_continue_selftest(struct tpm_chip *); | 289 | extern int tpm_do_selftest(struct tpm_chip *); |
285 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | 290 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); |
286 | extern struct tpm_chip* tpm_register_hardware(struct device *, | 291 | extern struct tpm_chip* tpm_register_hardware(struct device *, |
287 | const struct tpm_vendor_specific *); | 292 | const struct tpm_vendor_specific *); |
@@ -294,7 +299,8 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); | |||
294 | extern void tpm_remove_hardware(struct device *); | 299 | extern void tpm_remove_hardware(struct device *); |
295 | extern int tpm_pm_suspend(struct device *, pm_message_t); | 300 | extern int tpm_pm_suspend(struct device *, pm_message_t); |
296 | extern int tpm_pm_resume(struct device *); | 301 | extern int tpm_pm_resume(struct device *); |
297 | 302 | extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, | |
303 | wait_queue_head_t *); | ||
298 | #ifdef CONFIG_ACPI | 304 | #ifdef CONFIG_ACPI |
299 | extern struct dentry ** tpm_bios_log_setup(char *); | 305 | extern struct dentry ** tpm_bios_log_setup(char *); |
300 | extern void tpm_bios_log_teardown(struct dentry **); | 306 | extern void tpm_bios_log_teardown(struct dentry **); |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 3f4051a7c5a7..a1748621111b 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -29,8 +29,6 @@ | |||
29 | #include <linux/freezer.h> | 29 | #include <linux/freezer.h> |
30 | #include "tpm.h" | 30 | #include "tpm.h" |
31 | 31 | ||
32 | #define TPM_HEADER_SIZE 10 | ||
33 | |||
34 | enum tis_access { | 32 | enum tis_access { |
35 | TPM_ACCESS_VALID = 0x80, | 33 | TPM_ACCESS_VALID = 0x80, |
36 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | 34 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, |
@@ -193,54 +191,14 @@ static int get_burstcount(struct tpm_chip *chip) | |||
193 | return -EBUSY; | 191 | return -EBUSY; |
194 | } | 192 | } |
195 | 193 | ||
196 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
197 | wait_queue_head_t *queue) | ||
198 | { | ||
199 | unsigned long stop; | ||
200 | long rc; | ||
201 | u8 status; | ||
202 | |||
203 | /* check current status */ | ||
204 | status = tpm_tis_status(chip); | ||
205 | if ((status & mask) == mask) | ||
206 | return 0; | ||
207 | |||
208 | stop = jiffies + timeout; | ||
209 | |||
210 | if (chip->vendor.irq) { | ||
211 | again: | ||
212 | timeout = stop - jiffies; | ||
213 | if ((long)timeout <= 0) | ||
214 | return -ETIME; | ||
215 | rc = wait_event_interruptible_timeout(*queue, | ||
216 | ((tpm_tis_status | ||
217 | (chip) & mask) == | ||
218 | mask), timeout); | ||
219 | if (rc > 0) | ||
220 | return 0; | ||
221 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
222 | clear_thread_flag(TIF_SIGPENDING); | ||
223 | goto again; | ||
224 | } | ||
225 | } else { | ||
226 | do { | ||
227 | msleep(TPM_TIMEOUT); | ||
228 | status = tpm_tis_status(chip); | ||
229 | if ((status & mask) == mask) | ||
230 | return 0; | ||
231 | } while (time_before(jiffies, stop)); | ||
232 | } | ||
233 | return -ETIME; | ||
234 | } | ||
235 | |||
236 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | 194 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) |
237 | { | 195 | { |
238 | int size = 0, burstcnt; | 196 | int size = 0, burstcnt; |
239 | while (size < count && | 197 | while (size < count && |
240 | wait_for_stat(chip, | 198 | wait_for_tpm_stat(chip, |
241 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 199 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
242 | chip->vendor.timeout_c, | 200 | chip->vendor.timeout_c, |
243 | &chip->vendor.read_queue) | 201 | &chip->vendor.read_queue) |
244 | == 0) { | 202 | == 0) { |
245 | burstcnt = get_burstcount(chip); | 203 | burstcnt = get_burstcount(chip); |
246 | for (; burstcnt > 0 && size < count; burstcnt--) | 204 | for (; burstcnt > 0 && size < count; burstcnt--) |
@@ -282,8 +240,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
282 | goto out; | 240 | goto out; |
283 | } | 241 | } |
284 | 242 | ||
285 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 243 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
286 | &chip->vendor.int_queue); | 244 | &chip->vendor.int_queue); |
287 | status = tpm_tis_status(chip); | 245 | status = tpm_tis_status(chip); |
288 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | 246 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ |
289 | dev_err(chip->dev, "Error left over data\n"); | 247 | dev_err(chip->dev, "Error left over data\n"); |
@@ -297,7 +255,7 @@ out: | |||
297 | return size; | 255 | return size; |
298 | } | 256 | } |
299 | 257 | ||
300 | static int itpm; | 258 | static bool itpm; |
301 | module_param(itpm, bool, 0444); | 259 | module_param(itpm, bool, 0444); |
302 | MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); | 260 | MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); |
303 | 261 | ||
@@ -317,7 +275,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
317 | status = tpm_tis_status(chip); | 275 | status = tpm_tis_status(chip); |
318 | if ((status & TPM_STS_COMMAND_READY) == 0) { | 276 | if ((status & TPM_STS_COMMAND_READY) == 0) { |
319 | tpm_tis_ready(chip); | 277 | tpm_tis_ready(chip); |
320 | if (wait_for_stat | 278 | if (wait_for_tpm_stat |
321 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | 279 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, |
322 | &chip->vendor.int_queue) < 0) { | 280 | &chip->vendor.int_queue) < 0) { |
323 | rc = -ETIME; | 281 | rc = -ETIME; |
@@ -333,8 +291,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
333 | count++; | 291 | count++; |
334 | } | 292 | } |
335 | 293 | ||
336 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 294 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
337 | &chip->vendor.int_queue); | 295 | &chip->vendor.int_queue); |
338 | status = tpm_tis_status(chip); | 296 | status = tpm_tis_status(chip); |
339 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { | 297 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { |
340 | rc = -EIO; | 298 | rc = -EIO; |
@@ -345,8 +303,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
345 | /* write last byte */ | 303 | /* write last byte */ |
346 | iowrite8(buf[count], | 304 | iowrite8(buf[count], |
347 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); | 305 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); |
348 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 306 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
349 | &chip->vendor.int_queue); | 307 | &chip->vendor.int_queue); |
350 | status = tpm_tis_status(chip); | 308 | status = tpm_tis_status(chip); |
351 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | 309 | if ((status & TPM_STS_DATA_EXPECT) != 0) { |
352 | rc = -EIO; | 310 | rc = -EIO; |
@@ -381,7 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
381 | 339 | ||
382 | if (chip->vendor.irq) { | 340 | if (chip->vendor.irq) { |
383 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | 341 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
384 | if (wait_for_stat | 342 | if (wait_for_tpm_stat |
385 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 343 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
386 | tpm_calc_ordinal_duration(chip, ordinal), | 344 | tpm_calc_ordinal_duration(chip, ordinal), |
387 | &chip->vendor.read_queue) < 0) { | 345 | &chip->vendor.read_queue) < 0) { |
@@ -432,6 +390,9 @@ static int probe_itpm(struct tpm_chip *chip) | |||
432 | out: | 390 | out: |
433 | itpm = rem_itpm; | 391 | itpm = rem_itpm; |
434 | tpm_tis_ready(chip); | 392 | tpm_tis_ready(chip); |
393 | /* some TPMs need a break here otherwise they will not work | ||
394 | * correctly on the immediately subsequent command */ | ||
395 | msleep(chip->vendor.timeout_b); | ||
435 | release_locality(chip, chip->vendor.locality, 0); | 396 | release_locality(chip, chip->vendor.locality, 0); |
436 | 397 | ||
437 | return rc; | 398 | return rc; |
@@ -539,7 +500,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) | |||
539 | return IRQ_HANDLED; | 500 | return IRQ_HANDLED; |
540 | } | 501 | } |
541 | 502 | ||
542 | static int interrupts = 1; | 503 | static bool interrupts = 1; |
543 | module_param(interrupts, bool, 0444); | 504 | module_param(interrupts, bool, 0444); |
544 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 505 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
545 | 506 | ||
@@ -614,7 +575,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
614 | dev_dbg(dev, "\tData Avail Int Support\n"); | 575 | dev_dbg(dev, "\tData Avail Int Support\n"); |
615 | 576 | ||
616 | /* get the timeouts before testing for irqs */ | 577 | /* get the timeouts before testing for irqs */ |
617 | tpm_get_timeouts(chip); | 578 | if (tpm_get_timeouts(chip)) { |
579 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | ||
580 | rc = -ENODEV; | ||
581 | goto out_err; | ||
582 | } | ||
583 | |||
584 | if (tpm_do_selftest(chip)) { | ||
585 | dev_err(dev, "TPM self test failed\n"); | ||
586 | rc = -ENODEV; | ||
587 | goto out_err; | ||
588 | } | ||
618 | 589 | ||
619 | /* INTERRUPT Setup */ | 590 | /* INTERRUPT Setup */ |
620 | init_waitqueue_head(&chip->vendor.read_queue); | 591 | init_waitqueue_head(&chip->vendor.read_queue); |
@@ -722,7 +693,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
722 | list_add(&chip->vendor.list, &tis_chips); | 693 | list_add(&chip->vendor.list, &tis_chips); |
723 | spin_unlock(&tis_lock); | 694 | spin_unlock(&tis_lock); |
724 | 695 | ||
725 | tpm_continue_selftest(chip); | ||
726 | 696 | ||
727 | return 0; | 697 | return 0; |
728 | out_err: | 698 | out_err: |
@@ -790,7 +760,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) | |||
790 | 760 | ||
791 | ret = tpm_pm_resume(&dev->dev); | 761 | ret = tpm_pm_resume(&dev->dev); |
792 | if (!ret) | 762 | if (!ret) |
793 | tpm_continue_selftest(chip); | 763 | tpm_do_selftest(chip); |
794 | 764 | ||
795 | return ret; | 765 | return ret; |
796 | } | 766 | } |
@@ -858,7 +828,7 @@ static struct platform_driver tis_drv = { | |||
858 | 828 | ||
859 | static struct platform_device *pdev; | 829 | static struct platform_device *pdev; |
860 | 830 | ||
861 | static int force; | 831 | static bool force; |
862 | module_param(force, bool, 0444); | 832 | module_param(force, bool, 0444); |
863 | MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); | 833 | MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); |
864 | static int __init init_tis(void) | 834 | static int __init init_tis(void) |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 8e3c46d67cb3..b58b56187065 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -392,7 +392,7 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) | |||
392 | 392 | ||
393 | sg_init_one(sg, buf->buf, buf->size); | 393 | sg_init_one(sg, buf->buf, buf->size); |
394 | 394 | ||
395 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf); | 395 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC); |
396 | virtqueue_kick(vq); | 396 | virtqueue_kick(vq); |
397 | return ret; | 397 | return ret; |
398 | } | 398 | } |
@@ -457,7 +457,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | |||
457 | vq = portdev->c_ovq; | 457 | vq = portdev->c_ovq; |
458 | 458 | ||
459 | sg_init_one(sg, &cpkt, sizeof(cpkt)); | 459 | sg_init_one(sg, &cpkt, sizeof(cpkt)); |
460 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt) >= 0) { | 460 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) >= 0) { |
461 | virtqueue_kick(vq); | 461 | virtqueue_kick(vq); |
462 | while (!virtqueue_get_buf(vq, &len)) | 462 | while (!virtqueue_get_buf(vq, &len)) |
463 | cpu_relax(); | 463 | cpu_relax(); |
@@ -506,7 +506,7 @@ static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, | |||
506 | reclaim_consumed_buffers(port); | 506 | reclaim_consumed_buffers(port); |
507 | 507 | ||
508 | sg_init_one(sg, in_buf, in_count); | 508 | sg_init_one(sg, in_buf, in_count); |
509 | ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf); | 509 | ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf, GFP_ATOMIC); |
510 | 510 | ||
511 | /* Tell Host to go! */ | 511 | /* Tell Host to go! */ |
512 | virtqueue_kick(out_vq); | 512 | virtqueue_kick(out_vq); |
@@ -1271,6 +1271,20 @@ static void remove_port(struct kref *kref) | |||
1271 | kfree(port); | 1271 | kfree(port); |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | static void remove_port_data(struct port *port) | ||
1275 | { | ||
1276 | struct port_buffer *buf; | ||
1277 | |||
1278 | /* Remove unused data this port might have received. */ | ||
1279 | discard_port_data(port); | ||
1280 | |||
1281 | reclaim_consumed_buffers(port); | ||
1282 | |||
1283 | /* Remove buffers we queued up for the Host to send us data in. */ | ||
1284 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
1285 | free_buf(buf); | ||
1286 | } | ||
1287 | |||
1274 | /* | 1288 | /* |
1275 | * Port got unplugged. Remove port from portdev's list and drop the | 1289 | * Port got unplugged. Remove port from portdev's list and drop the |
1276 | * kref reference. If no userspace has this port opened, it will | 1290 | * kref reference. If no userspace has this port opened, it will |
@@ -1278,8 +1292,6 @@ static void remove_port(struct kref *kref) | |||
1278 | */ | 1292 | */ |
1279 | static void unplug_port(struct port *port) | 1293 | static void unplug_port(struct port *port) |
1280 | { | 1294 | { |
1281 | struct port_buffer *buf; | ||
1282 | |||
1283 | spin_lock_irq(&port->portdev->ports_lock); | 1295 | spin_lock_irq(&port->portdev->ports_lock); |
1284 | list_del(&port->list); | 1296 | list_del(&port->list); |
1285 | spin_unlock_irq(&port->portdev->ports_lock); | 1297 | spin_unlock_irq(&port->portdev->ports_lock); |
@@ -1300,14 +1312,7 @@ static void unplug_port(struct port *port) | |||
1300 | hvc_remove(port->cons.hvc); | 1312 | hvc_remove(port->cons.hvc); |
1301 | } | 1313 | } |
1302 | 1314 | ||
1303 | /* Remove unused data this port might have received. */ | 1315 | remove_port_data(port); |
1304 | discard_port_data(port); | ||
1305 | |||
1306 | reclaim_consumed_buffers(port); | ||
1307 | |||
1308 | /* Remove buffers we queued up for the Host to send us data in. */ | ||
1309 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
1310 | free_buf(buf); | ||
1311 | 1316 | ||
1312 | /* | 1317 | /* |
1313 | * We should just assume the device itself has gone off -- | 1318 | * We should just assume the device itself has gone off -- |
@@ -1659,6 +1664,28 @@ static const struct file_operations portdev_fops = { | |||
1659 | .owner = THIS_MODULE, | 1664 | .owner = THIS_MODULE, |
1660 | }; | 1665 | }; |
1661 | 1666 | ||
1667 | static void remove_vqs(struct ports_device *portdev) | ||
1668 | { | ||
1669 | portdev->vdev->config->del_vqs(portdev->vdev); | ||
1670 | kfree(portdev->in_vqs); | ||
1671 | kfree(portdev->out_vqs); | ||
1672 | } | ||
1673 | |||
1674 | static void remove_controlq_data(struct ports_device *portdev) | ||
1675 | { | ||
1676 | struct port_buffer *buf; | ||
1677 | unsigned int len; | ||
1678 | |||
1679 | if (!use_multiport(portdev)) | ||
1680 | return; | ||
1681 | |||
1682 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | ||
1683 | free_buf(buf); | ||
1684 | |||
1685 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
1686 | free_buf(buf); | ||
1687 | } | ||
1688 | |||
1662 | /* | 1689 | /* |
1663 | * Once we're further in boot, we get probed like any other virtio | 1690 | * Once we're further in boot, we get probed like any other virtio |
1664 | * device. | 1691 | * device. |
@@ -1764,9 +1791,7 @@ free_vqs: | |||
1764 | /* The host might want to notify mgmt sw about device add failure */ | 1791 | /* The host might want to notify mgmt sw about device add failure */ |
1765 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 1792 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
1766 | VIRTIO_CONSOLE_DEVICE_READY, 0); | 1793 | VIRTIO_CONSOLE_DEVICE_READY, 0); |
1767 | vdev->config->del_vqs(vdev); | 1794 | remove_vqs(portdev); |
1768 | kfree(portdev->in_vqs); | ||
1769 | kfree(portdev->out_vqs); | ||
1770 | free_chrdev: | 1795 | free_chrdev: |
1771 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | 1796 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); |
1772 | free: | 1797 | free: |
@@ -1804,21 +1829,8 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
1804 | * have to just stop using the port, as the vqs are going | 1829 | * have to just stop using the port, as the vqs are going |
1805 | * away. | 1830 | * away. |
1806 | */ | 1831 | */ |
1807 | if (use_multiport(portdev)) { | 1832 | remove_controlq_data(portdev); |
1808 | struct port_buffer *buf; | 1833 | remove_vqs(portdev); |
1809 | unsigned int len; | ||
1810 | |||
1811 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | ||
1812 | free_buf(buf); | ||
1813 | |||
1814 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
1815 | free_buf(buf); | ||
1816 | } | ||
1817 | |||
1818 | vdev->config->del_vqs(vdev); | ||
1819 | kfree(portdev->in_vqs); | ||
1820 | kfree(portdev->out_vqs); | ||
1821 | |||
1822 | kfree(portdev); | 1834 | kfree(portdev); |
1823 | } | 1835 | } |
1824 | 1836 | ||
@@ -1832,6 +1844,68 @@ static unsigned int features[] = { | |||
1832 | VIRTIO_CONSOLE_F_MULTIPORT, | 1844 | VIRTIO_CONSOLE_F_MULTIPORT, |
1833 | }; | 1845 | }; |
1834 | 1846 | ||
1847 | #ifdef CONFIG_PM | ||
1848 | static int virtcons_freeze(struct virtio_device *vdev) | ||
1849 | { | ||
1850 | struct ports_device *portdev; | ||
1851 | struct port *port; | ||
1852 | |||
1853 | portdev = vdev->priv; | ||
1854 | |||
1855 | vdev->config->reset(vdev); | ||
1856 | |||
1857 | virtqueue_disable_cb(portdev->c_ivq); | ||
1858 | cancel_work_sync(&portdev->control_work); | ||
1859 | /* | ||
1860 | * Once more: if control_work_handler() was running, it would | ||
1861 | * enable the cb as the last step. | ||
1862 | */ | ||
1863 | virtqueue_disable_cb(portdev->c_ivq); | ||
1864 | remove_controlq_data(portdev); | ||
1865 | |||
1866 | list_for_each_entry(port, &portdev->ports, list) { | ||
1867 | virtqueue_disable_cb(port->in_vq); | ||
1868 | virtqueue_disable_cb(port->out_vq); | ||
1869 | /* | ||
1870 | * We'll ask the host later if the new invocation has | ||
1871 | * the port opened or closed. | ||
1872 | */ | ||
1873 | port->host_connected = false; | ||
1874 | remove_port_data(port); | ||
1875 | } | ||
1876 | remove_vqs(portdev); | ||
1877 | |||
1878 | return 0; | ||
1879 | } | ||
1880 | |||
1881 | static int virtcons_restore(struct virtio_device *vdev) | ||
1882 | { | ||
1883 | struct ports_device *portdev; | ||
1884 | struct port *port; | ||
1885 | int ret; | ||
1886 | |||
1887 | portdev = vdev->priv; | ||
1888 | |||
1889 | ret = init_vqs(portdev); | ||
1890 | if (ret) | ||
1891 | return ret; | ||
1892 | |||
1893 | if (use_multiport(portdev)) | ||
1894 | fill_queue(portdev->c_ivq, &portdev->cvq_lock); | ||
1895 | |||
1896 | list_for_each_entry(port, &portdev->ports, list) { | ||
1897 | port->in_vq = portdev->in_vqs[port->id]; | ||
1898 | port->out_vq = portdev->out_vqs[port->id]; | ||
1899 | |||
1900 | fill_queue(port->in_vq, &port->inbuf_lock); | ||
1901 | |||
1902 | /* Get port open/close status on the host */ | ||
1903 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
1904 | } | ||
1905 | return 0; | ||
1906 | } | ||
1907 | #endif | ||
1908 | |||
1835 | static struct virtio_driver virtio_console = { | 1909 | static struct virtio_driver virtio_console = { |
1836 | .feature_table = features, | 1910 | .feature_table = features, |
1837 | .feature_table_size = ARRAY_SIZE(features), | 1911 | .feature_table_size = ARRAY_SIZE(features), |
@@ -1841,6 +1915,10 @@ static struct virtio_driver virtio_console = { | |||
1841 | .probe = virtcons_probe, | 1915 | .probe = virtcons_probe, |
1842 | .remove = virtcons_remove, | 1916 | .remove = virtcons_remove, |
1843 | .config_changed = config_intr, | 1917 | .config_changed = config_intr, |
1918 | #ifdef CONFIG_PM | ||
1919 | .freeze = virtcons_freeze, | ||
1920 | .restore = virtcons_restore, | ||
1921 | #endif | ||
1844 | }; | 1922 | }; |
1845 | 1923 | ||
1846 | static int __init init(void) | 1924 | static int __init init(void) |