diff options
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/agp/intel-agp.c | 21 | ||||
-rw-r--r-- | drivers/char/agp/parisc-agp.c | 23 | ||||
-rw-r--r-- | drivers/char/hvc_iucv.c | 259 | ||||
-rw-r--r-- | drivers/char/hw_random/Kconfig | 14 | ||||
-rw-r--r-- | drivers/char/hw_random/Makefile | 1 | ||||
-rw-r--r-- | drivers/char/hw_random/omap-rng.c | 2 | ||||
-rw-r--r-- | drivers/char/hw_random/timeriomem-rng.c | 151 | ||||
-rw-r--r-- | drivers/char/pcmcia/synclink_cs.c | 18 | ||||
-rw-r--r-- | drivers/char/random.c | 6 | ||||
-rw-r--r-- | drivers/char/synclink.c | 18 | ||||
-rw-r--r-- | drivers/char/synclink_gt.c | 18 | ||||
-rw-r--r-- | drivers/char/synclinkmp.c | 18 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.c | 530 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 142 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_atmel.c | 28 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis.c | 28 | ||||
-rw-r--r-- | drivers/char/vc_screen.c | 16 | ||||
-rw-r--r-- | drivers/char/vt.c | 5 |
18 files changed, 934 insertions, 364 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 4373adb2119a..9d9490e22e07 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 | 26 | #define PCI_DEVICE_ID_INTEL_82965GME_IG 0x2A12 |
27 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC | 27 | #define PCI_DEVICE_ID_INTEL_82945GME_HB 0x27AC |
28 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE | 28 | #define PCI_DEVICE_ID_INTEL_82945GME_IG 0x27AE |
29 | #define PCI_DEVICE_ID_INTEL_IGDGM_HB 0xA010 | ||
30 | #define PCI_DEVICE_ID_INTEL_IGDGM_IG 0xA011 | ||
31 | #define PCI_DEVICE_ID_INTEL_IGDG_HB 0xA000 | ||
32 | #define PCI_DEVICE_ID_INTEL_IGDG_IG 0xA001 | ||
29 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 | 33 | #define PCI_DEVICE_ID_INTEL_G33_HB 0x29C0 |
30 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 | 34 | #define PCI_DEVICE_ID_INTEL_G33_IG 0x29C2 |
31 | #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 | 35 | #define PCI_DEVICE_ID_INTEL_Q35_HB 0x29B0 |
@@ -60,7 +64,12 @@ | |||
60 | 64 | ||
61 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ | 65 | #define IS_G33 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_G33_HB || \ |
62 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ | 66 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q35_HB || \ |
63 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB) | 67 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q33_HB || \ |
68 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ | ||
69 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) | ||
70 | |||
71 | #define IS_IGD (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDGM_HB || \ | ||
72 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGDG_HB) | ||
64 | 73 | ||
65 | #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ | 74 | #define IS_G4X (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_IGD_E_HB || \ |
66 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ | 75 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_Q45_HB || \ |
@@ -510,7 +519,7 @@ static void intel_i830_init_gtt_entries(void) | |||
510 | size = 512; | 519 | size = 512; |
511 | } | 520 | } |
512 | size += 4; /* add in BIOS popup space */ | 521 | size += 4; /* add in BIOS popup space */ |
513 | } else if (IS_G33) { | 522 | } else if (IS_G33 && !IS_IGD) { |
514 | /* G33's GTT size defined in gmch_ctrl */ | 523 | /* G33's GTT size defined in gmch_ctrl */ |
515 | switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { | 524 | switch (gmch_ctrl & G33_PGETBL_SIZE_MASK) { |
516 | case G33_PGETBL_SIZE_1M: | 525 | case G33_PGETBL_SIZE_1M: |
@@ -526,7 +535,7 @@ static void intel_i830_init_gtt_entries(void) | |||
526 | size = 512; | 535 | size = 512; |
527 | } | 536 | } |
528 | size += 4; | 537 | size += 4; |
529 | } else if (IS_G4X) { | 538 | } else if (IS_G4X || IS_IGD) { |
530 | /* On 4 series hardware, GTT stolen is separate from graphics | 539 | /* On 4 series hardware, GTT stolen is separate from graphics |
531 | * stolen, ignore it in stolen gtt entries counting. However, | 540 | * stolen, ignore it in stolen gtt entries counting. However, |
532 | * 4KB of the stolen memory doesn't get mapped to the GTT. | 541 | * 4KB of the stolen memory doesn't get mapped to the GTT. |
@@ -2161,6 +2170,10 @@ static const struct intel_driver_description { | |||
2161 | NULL, &intel_g33_driver }, | 2170 | NULL, &intel_g33_driver }, |
2162 | { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", | 2171 | { PCI_DEVICE_ID_INTEL_Q33_HB, PCI_DEVICE_ID_INTEL_Q33_IG, 0, "Q33", |
2163 | NULL, &intel_g33_driver }, | 2172 | NULL, &intel_g33_driver }, |
2173 | { PCI_DEVICE_ID_INTEL_IGDGM_HB, PCI_DEVICE_ID_INTEL_IGDGM_IG, 0, "IGD", | ||
2174 | NULL, &intel_g33_driver }, | ||
2175 | { PCI_DEVICE_ID_INTEL_IGDG_HB, PCI_DEVICE_ID_INTEL_IGDG_IG, 0, "IGD", | ||
2176 | NULL, &intel_g33_driver }, | ||
2164 | { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, | 2177 | { PCI_DEVICE_ID_INTEL_GM45_HB, PCI_DEVICE_ID_INTEL_GM45_IG, 0, |
2165 | "Mobile IntelĀ® GM45 Express", NULL, &intel_i965_driver }, | 2178 | "Mobile IntelĀ® GM45 Express", NULL, &intel_i965_driver }, |
2166 | { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, | 2179 | { PCI_DEVICE_ID_INTEL_IGD_E_HB, PCI_DEVICE_ID_INTEL_IGD_E_IG, 0, |
@@ -2355,6 +2368,8 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
2355 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), | 2368 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), |
2356 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), | 2369 | ID(PCI_DEVICE_ID_INTEL_82945GM_HB), |
2357 | ID(PCI_DEVICE_ID_INTEL_82945GME_HB), | 2370 | ID(PCI_DEVICE_ID_INTEL_82945GME_HB), |
2371 | ID(PCI_DEVICE_ID_INTEL_IGDGM_HB), | ||
2372 | ID(PCI_DEVICE_ID_INTEL_IGDG_HB), | ||
2358 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), | 2373 | ID(PCI_DEVICE_ID_INTEL_82946GZ_HB), |
2359 | ID(PCI_DEVICE_ID_INTEL_82G35_HB), | 2374 | ID(PCI_DEVICE_ID_INTEL_82G35_HB), |
2360 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), | 2375 | ID(PCI_DEVICE_ID_INTEL_82965Q_HB), |
diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index db60539bf67a..699e3422ad93 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c | |||
@@ -359,9 +359,16 @@ fail: | |||
359 | return error; | 359 | return error; |
360 | } | 360 | } |
361 | 361 | ||
362 | static struct device *next_device(struct klist_iter *i) { | 362 | static int |
363 | struct klist_node * n = klist_next(i); | 363 | find_quicksilver(struct device *dev, void *data) |
364 | return n ? container_of(n, struct device, knode_parent) : NULL; | 364 | { |
365 | struct parisc_device **lba = data; | ||
366 | struct parisc_device *padev = to_parisc_device(dev); | ||
367 | |||
368 | if (IS_QUICKSILVER(padev)) | ||
369 | *lba = padev; | ||
370 | |||
371 | return 0; | ||
365 | } | 372 | } |
366 | 373 | ||
367 | static int | 374 | static int |
@@ -372,8 +379,6 @@ parisc_agp_init(void) | |||
372 | int err = -1; | 379 | int err = -1; |
373 | struct parisc_device *sba = NULL, *lba = NULL; | 380 | struct parisc_device *sba = NULL, *lba = NULL; |
374 | struct lba_device *lbadev = NULL; | 381 | struct lba_device *lbadev = NULL; |
375 | struct device *dev = NULL; | ||
376 | struct klist_iter i; | ||
377 | 382 | ||
378 | if (!sba_list) | 383 | if (!sba_list) |
379 | goto out; | 384 | goto out; |
@@ -386,13 +391,7 @@ parisc_agp_init(void) | |||
386 | } | 391 | } |
387 | 392 | ||
388 | /* Now search our Pluto for our precious AGP device... */ | 393 | /* Now search our Pluto for our precious AGP device... */ |
389 | klist_iter_init(&sba->dev.klist_children, &i); | 394 | device_for_each_child(&sba->dev, &lba, find_quicksilver); |
390 | while ((dev = next_device(&i))) { | ||
391 | struct parisc_device *padev = to_parisc_device(dev); | ||
392 | if (IS_QUICKSILVER(padev)) | ||
393 | lba = padev; | ||
394 | } | ||
395 | klist_iter_exit(&i); | ||
396 | 395 | ||
397 | if (!lba) { | 396 | if (!lba) { |
398 | printk(KERN_INFO DRVPFX "No AGP devices found.\n"); | 397 | printk(KERN_INFO DRVPFX "No AGP devices found.\n"); |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index a53496828b76..54481a887769 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -13,10 +13,11 @@ | |||
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <asm/ebcdic.h> | 15 | #include <asm/ebcdic.h> |
16 | #include <linux/ctype.h> | ||
16 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
17 | #include <linux/init.h> | 18 | #include <linux/init.h> |
18 | #include <linux/mempool.h> | 19 | #include <linux/mempool.h> |
19 | #include <linux/module.h> | 20 | #include <linux/moduleparam.h> |
20 | #include <linux/tty.h> | 21 | #include <linux/tty.h> |
21 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
22 | #include <net/iucv/iucv.h> | 23 | #include <net/iucv/iucv.h> |
@@ -95,6 +96,12 @@ static unsigned long hvc_iucv_devices = 1; | |||
95 | /* Array of allocated hvc iucv tty lines... */ | 96 | /* Array of allocated hvc iucv tty lines... */ |
96 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; | 97 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; |
97 | #define IUCV_HVC_CON_IDX (0) | 98 | #define IUCV_HVC_CON_IDX (0) |
99 | /* List of z/VM user ID filter entries (struct iucv_vmid_filter) */ | ||
100 | #define MAX_VMID_FILTER (500) | ||
101 | static size_t hvc_iucv_filter_size; | ||
102 | static void *hvc_iucv_filter; | ||
103 | static const char *hvc_iucv_filter_string; | ||
104 | static DEFINE_RWLOCK(hvc_iucv_filter_lock); | ||
98 | 105 | ||
99 | /* Kmem cache and mempool for iucv_tty_buffer elements */ | 106 | /* Kmem cache and mempool for iucv_tty_buffer elements */ |
100 | static struct kmem_cache *hvc_iucv_buffer_cache; | 107 | static struct kmem_cache *hvc_iucv_buffer_cache; |
@@ -618,6 +625,27 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) | |||
618 | } | 625 | } |
619 | 626 | ||
620 | /** | 627 | /** |
628 | * hvc_iucv_filter_connreq() - Filter connection request based on z/VM user ID | ||
629 | * @ipvmid: Originating z/VM user ID (right padded with blanks) | ||
630 | * | ||
631 | * Returns 0 if the z/VM user ID @ipvmid is allowed to connection, otherwise | ||
632 | * non-zero. | ||
633 | */ | ||
634 | static int hvc_iucv_filter_connreq(u8 ipvmid[8]) | ||
635 | { | ||
636 | size_t i; | ||
637 | |||
638 | /* Note: default policy is ACCEPT if no filter is set */ | ||
639 | if (!hvc_iucv_filter_size) | ||
640 | return 0; | ||
641 | |||
642 | for (i = 0; i < hvc_iucv_filter_size; i++) | ||
643 | if (0 == memcmp(ipvmid, hvc_iucv_filter + (8 * i), 8)) | ||
644 | return 0; | ||
645 | return 1; | ||
646 | } | ||
647 | |||
648 | /** | ||
621 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. | 649 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. |
622 | * @path: Pending path (struct iucv_path) | 650 | * @path: Pending path (struct iucv_path) |
623 | * @ipvmid: z/VM system identifier of originator | 651 | * @ipvmid: z/VM system identifier of originator |
@@ -641,6 +669,7 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
641 | { | 669 | { |
642 | struct hvc_iucv_private *priv; | 670 | struct hvc_iucv_private *priv; |
643 | u8 nuser_data[16]; | 671 | u8 nuser_data[16]; |
672 | u8 vm_user_id[9]; | ||
644 | int i, rc; | 673 | int i, rc; |
645 | 674 | ||
646 | priv = NULL; | 675 | priv = NULL; |
@@ -653,6 +682,20 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
653 | if (!priv) | 682 | if (!priv) |
654 | return -ENODEV; | 683 | return -ENODEV; |
655 | 684 | ||
685 | /* Enforce that ipvmid is allowed to connect to us */ | ||
686 | read_lock(&hvc_iucv_filter_lock); | ||
687 | rc = hvc_iucv_filter_connreq(ipvmid); | ||
688 | read_unlock(&hvc_iucv_filter_lock); | ||
689 | if (rc) { | ||
690 | iucv_path_sever(path, ipuser); | ||
691 | iucv_path_free(path); | ||
692 | memcpy(vm_user_id, ipvmid, 8); | ||
693 | vm_user_id[8] = 0; | ||
694 | pr_info("A connection request from z/VM user ID %s " | ||
695 | "was refused\n", vm_user_id); | ||
696 | return 0; | ||
697 | } | ||
698 | |||
656 | spin_lock(&priv->lock); | 699 | spin_lock(&priv->lock); |
657 | 700 | ||
658 | /* If the terminal is already connected or being severed, then sever | 701 | /* If the terminal is already connected or being severed, then sever |
@@ -877,6 +920,171 @@ static int __init hvc_iucv_alloc(int id, unsigned int is_console) | |||
877 | } | 920 | } |
878 | 921 | ||
879 | /** | 922 | /** |
923 | * hvc_iucv_parse_filter() - Parse filter for a single z/VM user ID | ||
924 | * @filter: String containing a comma-separated list of z/VM user IDs | ||
925 | */ | ||
926 | static const char *hvc_iucv_parse_filter(const char *filter, char *dest) | ||
927 | { | ||
928 | const char *nextdelim, *residual; | ||
929 | size_t len; | ||
930 | |||
931 | nextdelim = strchr(filter, ','); | ||
932 | if (nextdelim) { | ||
933 | len = nextdelim - filter; | ||
934 | residual = nextdelim + 1; | ||
935 | } else { | ||
936 | len = strlen(filter); | ||
937 | residual = filter + len; | ||
938 | } | ||
939 | |||
940 | if (len == 0) | ||
941 | return ERR_PTR(-EINVAL); | ||
942 | |||
943 | /* check for '\n' (if called from sysfs) */ | ||
944 | if (filter[len - 1] == '\n') | ||
945 | len--; | ||
946 | |||
947 | if (len > 8) | ||
948 | return ERR_PTR(-EINVAL); | ||
949 | |||
950 | /* pad with blanks and save upper case version of user ID */ | ||
951 | memset(dest, ' ', 8); | ||
952 | while (len--) | ||
953 | dest[len] = toupper(filter[len]); | ||
954 | return residual; | ||
955 | } | ||
956 | |||
957 | /** | ||
958 | * hvc_iucv_setup_filter() - Set up z/VM user ID filter | ||
959 | * @filter: String consisting of a comma-separated list of z/VM user IDs | ||
960 | * | ||
961 | * The function parses the @filter string and creates an array containing | ||
962 | * the list of z/VM user ID filter entries. | ||
963 | * Return code 0 means success, -EINVAL if the filter is syntactically | ||
964 | * incorrect, -ENOMEM if there was not enough memory to allocate the | ||
965 | * filter list array, or -ENOSPC if too many z/VM user IDs have been specified. | ||
966 | */ | ||
967 | static int hvc_iucv_setup_filter(const char *val) | ||
968 | { | ||
969 | const char *residual; | ||
970 | int err; | ||
971 | size_t size, count; | ||
972 | void *array, *old_filter; | ||
973 | |||
974 | count = strlen(val); | ||
975 | if (count == 0 || (count == 1 && val[0] == '\n')) { | ||
976 | size = 0; | ||
977 | array = NULL; | ||
978 | goto out_replace_filter; /* clear filter */ | ||
979 | } | ||
980 | |||
981 | /* count user IDs in order to allocate sufficient memory */ | ||
982 | size = 1; | ||
983 | residual = val; | ||
984 | while ((residual = strchr(residual, ',')) != NULL) { | ||
985 | residual++; | ||
986 | size++; | ||
987 | } | ||
988 | |||
989 | /* check if the specified list exceeds the filter limit */ | ||
990 | if (size > MAX_VMID_FILTER) | ||
991 | return -ENOSPC; | ||
992 | |||
993 | array = kzalloc(size * 8, GFP_KERNEL); | ||
994 | if (!array) | ||
995 | return -ENOMEM; | ||
996 | |||
997 | count = size; | ||
998 | residual = val; | ||
999 | while (*residual && count) { | ||
1000 | residual = hvc_iucv_parse_filter(residual, | ||
1001 | array + ((size - count) * 8)); | ||
1002 | if (IS_ERR(residual)) { | ||
1003 | err = PTR_ERR(residual); | ||
1004 | kfree(array); | ||
1005 | goto out_err; | ||
1006 | } | ||
1007 | count--; | ||
1008 | } | ||
1009 | |||
1010 | out_replace_filter: | ||
1011 | write_lock_bh(&hvc_iucv_filter_lock); | ||
1012 | old_filter = hvc_iucv_filter; | ||
1013 | hvc_iucv_filter_size = size; | ||
1014 | hvc_iucv_filter = array; | ||
1015 | write_unlock_bh(&hvc_iucv_filter_lock); | ||
1016 | kfree(old_filter); | ||
1017 | |||
1018 | err = 0; | ||
1019 | out_err: | ||
1020 | return err; | ||
1021 | } | ||
1022 | |||
1023 | /** | ||
1024 | * param_set_vmidfilter() - Set z/VM user ID filter parameter | ||
1025 | * @val: String consisting of a comma-separated list of z/VM user IDs | ||
1026 | * @kp: Kernel parameter pointing to hvc_iucv_filter array | ||
1027 | * | ||
1028 | * The function sets up the z/VM user ID filter specified as comma-separated | ||
1029 | * list of user IDs in @val. | ||
1030 | * Note: If it is called early in the boot process, @val is stored and | ||
1031 | * parsed later in hvc_iucv_init(). | ||
1032 | */ | ||
1033 | static int param_set_vmidfilter(const char *val, struct kernel_param *kp) | ||
1034 | { | ||
1035 | int rc; | ||
1036 | |||
1037 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
1038 | return -ENODEV; | ||
1039 | |||
1040 | if (!val) | ||
1041 | return -EINVAL; | ||
1042 | |||
1043 | rc = 0; | ||
1044 | if (slab_is_available()) | ||
1045 | rc = hvc_iucv_setup_filter(val); | ||
1046 | else | ||
1047 | hvc_iucv_filter_string = val; /* defer... */ | ||
1048 | return rc; | ||
1049 | } | ||
1050 | |||
1051 | /** | ||
1052 | * param_get_vmidfilter() - Get z/VM user ID filter | ||
1053 | * @buffer: Buffer to store z/VM user ID filter, | ||
1054 | * (buffer size assumption PAGE_SIZE) | ||
1055 | * @kp: Kernel parameter pointing to the hvc_iucv_filter array | ||
1056 | * | ||
1057 | * The function stores the filter as a comma-separated list of z/VM user IDs | ||
1058 | * in @buffer. Typically, sysfs routines call this function for attr show. | ||
1059 | */ | ||
1060 | static int param_get_vmidfilter(char *buffer, struct kernel_param *kp) | ||
1061 | { | ||
1062 | int rc; | ||
1063 | size_t index, len; | ||
1064 | void *start, *end; | ||
1065 | |||
1066 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
1067 | return -ENODEV; | ||
1068 | |||
1069 | rc = 0; | ||
1070 | read_lock_bh(&hvc_iucv_filter_lock); | ||
1071 | for (index = 0; index < hvc_iucv_filter_size; index++) { | ||
1072 | start = hvc_iucv_filter + (8 * index); | ||
1073 | end = memchr(start, ' ', 8); | ||
1074 | len = (end) ? end - start : 8; | ||
1075 | memcpy(buffer + rc, start, len); | ||
1076 | rc += len; | ||
1077 | buffer[rc++] = ','; | ||
1078 | } | ||
1079 | read_unlock_bh(&hvc_iucv_filter_lock); | ||
1080 | if (rc) | ||
1081 | buffer[--rc] = '\0'; /* replace last comma and update rc */ | ||
1082 | return rc; | ||
1083 | } | ||
1084 | |||
1085 | #define param_check_vmidfilter(name, p) __param_check(name, p, void) | ||
1086 | |||
1087 | /** | ||
880 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization | 1088 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
881 | */ | 1089 | */ |
882 | static int __init hvc_iucv_init(void) | 1090 | static int __init hvc_iucv_init(void) |
@@ -884,24 +1092,53 @@ static int __init hvc_iucv_init(void) | |||
884 | int rc; | 1092 | int rc; |
885 | unsigned int i; | 1093 | unsigned int i; |
886 | 1094 | ||
1095 | if (!hvc_iucv_devices) | ||
1096 | return -ENODEV; | ||
1097 | |||
887 | if (!MACHINE_IS_VM) { | 1098 | if (!MACHINE_IS_VM) { |
888 | pr_info("The z/VM IUCV HVC device driver cannot " | 1099 | pr_notice("The z/VM IUCV HVC device driver cannot " |
889 | "be used without z/VM\n"); | 1100 | "be used without z/VM\n"); |
890 | return -ENODEV; | 1101 | rc = -ENODEV; |
1102 | goto out_error; | ||
891 | } | 1103 | } |
892 | 1104 | ||
893 | if (!hvc_iucv_devices) | 1105 | if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) { |
894 | return -ENODEV; | 1106 | pr_err("%lu is not a valid value for the hvc_iucv= " |
1107 | "kernel parameter\n", hvc_iucv_devices); | ||
1108 | rc = -EINVAL; | ||
1109 | goto out_error; | ||
1110 | } | ||
895 | 1111 | ||
896 | if (hvc_iucv_devices > MAX_HVC_IUCV_LINES) | 1112 | /* parse hvc_iucv_allow string and create z/VM user ID filter list */ |
897 | return -EINVAL; | 1113 | if (hvc_iucv_filter_string) { |
1114 | rc = hvc_iucv_setup_filter(hvc_iucv_filter_string); | ||
1115 | switch (rc) { | ||
1116 | case 0: | ||
1117 | break; | ||
1118 | case -ENOMEM: | ||
1119 | pr_err("Allocating memory failed with " | ||
1120 | "reason code=%d\n", 3); | ||
1121 | goto out_error; | ||
1122 | case -EINVAL: | ||
1123 | pr_err("hvc_iucv_allow= does not specify a valid " | ||
1124 | "z/VM user ID list\n"); | ||
1125 | goto out_error; | ||
1126 | case -ENOSPC: | ||
1127 | pr_err("hvc_iucv_allow= specifies too many " | ||
1128 | "z/VM user IDs\n"); | ||
1129 | goto out_error; | ||
1130 | default: | ||
1131 | goto out_error; | ||
1132 | } | ||
1133 | } | ||
898 | 1134 | ||
899 | hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, | 1135 | hvc_iucv_buffer_cache = kmem_cache_create(KMSG_COMPONENT, |
900 | sizeof(struct iucv_tty_buffer), | 1136 | sizeof(struct iucv_tty_buffer), |
901 | 0, 0, NULL); | 1137 | 0, 0, NULL); |
902 | if (!hvc_iucv_buffer_cache) { | 1138 | if (!hvc_iucv_buffer_cache) { |
903 | pr_err("Allocating memory failed with reason code=%d\n", 1); | 1139 | pr_err("Allocating memory failed with reason code=%d\n", 1); |
904 | return -ENOMEM; | 1140 | rc = -ENOMEM; |
1141 | goto out_error; | ||
905 | } | 1142 | } |
906 | 1143 | ||
907 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, | 1144 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, |
@@ -909,7 +1146,8 @@ static int __init hvc_iucv_init(void) | |||
909 | if (!hvc_iucv_mempool) { | 1146 | if (!hvc_iucv_mempool) { |
910 | pr_err("Allocating memory failed with reason code=%d\n", 2); | 1147 | pr_err("Allocating memory failed with reason code=%d\n", 2); |
911 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 1148 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
912 | return -ENOMEM; | 1149 | rc = -ENOMEM; |
1150 | goto out_error; | ||
913 | } | 1151 | } |
914 | 1152 | ||
915 | /* register the first terminal device as console | 1153 | /* register the first terminal device as console |
@@ -953,6 +1191,8 @@ out_error_hvc: | |||
953 | out_error_memory: | 1191 | out_error_memory: |
954 | mempool_destroy(hvc_iucv_mempool); | 1192 | mempool_destroy(hvc_iucv_mempool); |
955 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 1193 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
1194 | out_error: | ||
1195 | hvc_iucv_devices = 0; /* ensure that we do not provide any device */ | ||
956 | return rc; | 1196 | return rc; |
957 | } | 1197 | } |
958 | 1198 | ||
@@ -968,3 +1208,4 @@ static int __init hvc_iucv_config(char *val) | |||
968 | 1208 | ||
969 | device_initcall(hvc_iucv_init); | 1209 | device_initcall(hvc_iucv_init); |
970 | __setup("hvc_iucv=", hvc_iucv_config); | 1210 | __setup("hvc_iucv=", hvc_iucv_config); |
1211 | core_param(hvc_iucv_allow, hvc_iucv_filter, vmidfilter, 0640); | ||
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8822eca58ffa..5fab6470f4b2 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -20,6 +20,20 @@ config HW_RANDOM | |||
20 | 20 | ||
21 | If unsure, say Y. | 21 | If unsure, say Y. |
22 | 22 | ||
23 | config HW_RANDOM_TIMERIOMEM | ||
24 | tristate "Timer IOMEM HW Random Number Generator support" | ||
25 | depends on HW_RANDOM && HAS_IOMEM | ||
26 | ---help--- | ||
27 | This driver provides kernel-side support for a generic Random | ||
28 | Number Generator used by reading a 'dumb' iomem address that | ||
29 | is to be read no faster than, for example, once a second; | ||
30 | the default FPGA bitstream on the TS-7800 has such functionality. | ||
31 | |||
32 | To compile this driver as a module, choose M here: the | ||
33 | module will be called timeriomem-rng. | ||
34 | |||
35 | If unsure, say Y. | ||
36 | |||
23 | config HW_RANDOM_INTEL | 37 | config HW_RANDOM_INTEL |
24 | tristate "Intel HW Random Number Generator support" | 38 | tristate "Intel HW Random Number Generator support" |
25 | depends on HW_RANDOM && (X86 || IA64) && PCI | 39 | depends on HW_RANDOM && (X86 || IA64) && PCI |
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b6effb7522c2..e81d21a5f28f 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_HW_RANDOM) += rng-core.o | 5 | obj-$(CONFIG_HW_RANDOM) += rng-core.o |
6 | rng-core-y := core.o | 6 | rng-core-y := core.o |
7 | obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o | ||
7 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o | 8 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o |
8 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o | 9 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o |
9 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o | 10 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o |
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index ba68a4671cb5..538313f9e7ac 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c | |||
@@ -102,7 +102,7 @@ static int __init omap_rng_probe(struct platform_device *pdev) | |||
102 | return -EBUSY; | 102 | return -EBUSY; |
103 | 103 | ||
104 | if (cpu_is_omap24xx()) { | 104 | if (cpu_is_omap24xx()) { |
105 | rng_ick = clk_get(&pdev->dev, "rng_ick"); | 105 | rng_ick = clk_get(&pdev->dev, "ick"); |
106 | if (IS_ERR(rng_ick)) { | 106 | if (IS_ERR(rng_ick)) { |
107 | dev_err(&pdev->dev, "Could not get rng_ick\n"); | 107 | dev_err(&pdev->dev, "Could not get rng_ick\n"); |
108 | ret = PTR_ERR(rng_ick); | 108 | ret = PTR_ERR(rng_ick); |
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c new file mode 100644 index 000000000000..10ad41be5897 --- /dev/null +++ b/drivers/char/hw_random/timeriomem-rng.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * drivers/char/hw_random/timeriomem-rng.c | ||
3 | * | ||
4 | * Copyright (C) 2009 Alexander Clouter <alex@digriz.org.uk> | ||
5 | * | ||
6 | * Derived from drivers/char/hw_random/omap-rng.c | ||
7 | * Copyright 2005 (c) MontaVista Software, Inc. | ||
8 | * Author: Deepak Saxena <dsaxena@plexity.net> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * Overview: | ||
15 | * This driver is useful for platforms that have an IO range that provides | ||
16 | * periodic random data from a single IO memory address. All the platform | ||
17 | * has to do is provide the address and 'wait time' that new data becomes | ||
18 | * available. | ||
19 | * | ||
20 | * TODO: add support for reading sizes other than 32bits and masking | ||
21 | */ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/hw_random.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <linux/timeriomem-rng.h> | ||
29 | #include <linux/jiffies.h> | ||
30 | #include <linux/sched.h> | ||
31 | #include <linux/timer.h> | ||
32 | #include <linux/completion.h> | ||
33 | |||
34 | static struct timeriomem_rng_data *timeriomem_rng_data; | ||
35 | |||
36 | static void timeriomem_rng_trigger(unsigned long); | ||
37 | static DEFINE_TIMER(timeriomem_rng_timer, timeriomem_rng_trigger, 0, 0); | ||
38 | |||
39 | /* | ||
40 | * have data return 1, however return 0 if we have nothing | ||
41 | */ | ||
42 | static int timeriomem_rng_data_present(struct hwrng *rng, int wait) | ||
43 | { | ||
44 | if (rng->priv == 0) | ||
45 | return 1; | ||
46 | |||
47 | if (!wait || timeriomem_rng_data->present) | ||
48 | return timeriomem_rng_data->present; | ||
49 | |||
50 | wait_for_completion(&timeriomem_rng_data->completion); | ||
51 | |||
52 | return 1; | ||
53 | } | ||
54 | |||
55 | static int timeriomem_rng_data_read(struct hwrng *rng, u32 *data) | ||
56 | { | ||
57 | unsigned long cur; | ||
58 | s32 delay; | ||
59 | |||
60 | *data = readl(timeriomem_rng_data->address); | ||
61 | |||
62 | if (rng->priv != 0) { | ||
63 | cur = jiffies; | ||
64 | |||
65 | delay = cur - timeriomem_rng_timer.expires; | ||
66 | delay = rng->priv - (delay % rng->priv); | ||
67 | |||
68 | timeriomem_rng_timer.expires = cur + delay; | ||
69 | timeriomem_rng_data->present = 0; | ||
70 | |||
71 | init_completion(&timeriomem_rng_data->completion); | ||
72 | add_timer(&timeriomem_rng_timer); | ||
73 | } | ||
74 | |||
75 | return 4; | ||
76 | } | ||
77 | |||
78 | static void timeriomem_rng_trigger(unsigned long dummy) | ||
79 | { | ||
80 | timeriomem_rng_data->present = 1; | ||
81 | complete(&timeriomem_rng_data->completion); | ||
82 | } | ||
83 | |||
84 | static struct hwrng timeriomem_rng_ops = { | ||
85 | .name = "timeriomem", | ||
86 | .data_present = timeriomem_rng_data_present, | ||
87 | .data_read = timeriomem_rng_data_read, | ||
88 | .priv = 0, | ||
89 | }; | ||
90 | |||
91 | static int __init timeriomem_rng_probe(struct platform_device *pdev) | ||
92 | { | ||
93 | int ret; | ||
94 | |||
95 | timeriomem_rng_data = pdev->dev.platform_data; | ||
96 | |||
97 | if (timeriomem_rng_data->period != 0 | ||
98 | && usecs_to_jiffies(timeriomem_rng_data->period) > 0) { | ||
99 | timeriomem_rng_timer.expires = jiffies; | ||
100 | |||
101 | timeriomem_rng_ops.priv = usecs_to_jiffies( | ||
102 | timeriomem_rng_data->period); | ||
103 | } | ||
104 | timeriomem_rng_data->present = 1; | ||
105 | |||
106 | ret = hwrng_register(&timeriomem_rng_ops); | ||
107 | if (ret) { | ||
108 | dev_err(&pdev->dev, "problem registering\n"); | ||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n", | ||
113 | timeriomem_rng_data->address, | ||
114 | timeriomem_rng_data->period); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int __devexit timeriomem_rng_remove(struct platform_device *pdev) | ||
120 | { | ||
121 | del_timer_sync(&timeriomem_rng_timer); | ||
122 | hwrng_unregister(&timeriomem_rng_ops); | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | static struct platform_driver timeriomem_rng_driver = { | ||
128 | .driver = { | ||
129 | .name = "timeriomem_rng", | ||
130 | .owner = THIS_MODULE, | ||
131 | }, | ||
132 | .probe = timeriomem_rng_probe, | ||
133 | .remove = __devexit_p(timeriomem_rng_remove), | ||
134 | }; | ||
135 | |||
136 | static int __init timeriomem_rng_init(void) | ||
137 | { | ||
138 | return platform_driver_register(&timeriomem_rng_driver); | ||
139 | } | ||
140 | |||
141 | static void __exit timeriomem_rng_exit(void) | ||
142 | { | ||
143 | platform_driver_unregister(&timeriomem_rng_driver); | ||
144 | } | ||
145 | |||
146 | module_init(timeriomem_rng_init); | ||
147 | module_exit(timeriomem_rng_exit); | ||
148 | |||
149 | MODULE_LICENSE("GPL"); | ||
150 | MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); | ||
151 | MODULE_DESCRIPTION("Timer IOMEM H/W RNG driver"); | ||
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index dc073e167abc..5608a1e5a3b3 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
@@ -4311,10 +4311,17 @@ static void hdlcdev_rx(MGSLPC_INFO *info, char *buf, int size) | |||
4311 | dev->stats.rx_bytes += size; | 4311 | dev->stats.rx_bytes += size; |
4312 | 4312 | ||
4313 | netif_rx(skb); | 4313 | netif_rx(skb); |
4314 | |||
4315 | dev->last_rx = jiffies; | ||
4316 | } | 4314 | } |
4317 | 4315 | ||
4316 | static const struct net_device_ops hdlcdev_ops = { | ||
4317 | .ndo_open = hdlcdev_open, | ||
4318 | .ndo_stop = hdlcdev_close, | ||
4319 | .ndo_change_mtu = hdlc_change_mtu, | ||
4320 | .ndo_start_xmit = hdlc_start_xmit, | ||
4321 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
4322 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
4323 | }; | ||
4324 | |||
4318 | /** | 4325 | /** |
4319 | * called by device driver when adding device instance | 4326 | * called by device driver when adding device instance |
4320 | * do generic HDLC initialization | 4327 | * do generic HDLC initialization |
@@ -4341,11 +4348,8 @@ static int hdlcdev_init(MGSLPC_INFO *info) | |||
4341 | dev->irq = info->irq_level; | 4348 | dev->irq = info->irq_level; |
4342 | 4349 | ||
4343 | /* network layer callbacks and settings */ | 4350 | /* network layer callbacks and settings */ |
4344 | dev->do_ioctl = hdlcdev_ioctl; | 4351 | dev->netdev_ops = &hdlcdev_ops; |
4345 | dev->open = hdlcdev_open; | 4352 | dev->watchdog_timeo = 10 * HZ; |
4346 | dev->stop = hdlcdev_close; | ||
4347 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
4348 | dev->watchdog_timeo = 10*HZ; | ||
4349 | dev->tx_queue_len = 50; | 4353 | dev->tx_queue_len = 50; |
4350 | 4354 | ||
4351 | /* generic HDLC layer callbacks and settings */ | 4355 | /* generic HDLC layer callbacks and settings */ |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 7c13581ca9cd..7c43ae782b26 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -241,6 +241,10 @@ | |||
241 | #include <linux/percpu.h> | 241 | #include <linux/percpu.h> |
242 | #include <linux/cryptohash.h> | 242 | #include <linux/cryptohash.h> |
243 | 243 | ||
244 | #ifdef CONFIG_GENERIC_HARDIRQS | ||
245 | # include <linux/irq.h> | ||
246 | #endif | ||
247 | |||
244 | #include <asm/processor.h> | 248 | #include <asm/processor.h> |
245 | #include <asm/uaccess.h> | 249 | #include <asm/uaccess.h> |
246 | #include <asm/irq.h> | 250 | #include <asm/irq.h> |
@@ -558,7 +562,7 @@ struct timer_rand_state { | |||
558 | unsigned dont_count_entropy:1; | 562 | unsigned dont_count_entropy:1; |
559 | }; | 563 | }; |
560 | 564 | ||
561 | #ifndef CONFIG_SPARSE_IRQ | 565 | #ifndef CONFIG_GENERIC_HARDIRQS |
562 | 566 | ||
563 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; | 567 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; |
564 | 568 | ||
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index b8063d4cad32..0057a8f58cb1 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
@@ -8007,10 +8007,17 @@ static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size) | |||
8007 | dev->stats.rx_bytes += size; | 8007 | dev->stats.rx_bytes += size; |
8008 | 8008 | ||
8009 | netif_rx(skb); | 8009 | netif_rx(skb); |
8010 | |||
8011 | dev->last_rx = jiffies; | ||
8012 | } | 8010 | } |
8013 | 8011 | ||
8012 | static const struct net_device_ops hdlcdev_ops = { | ||
8013 | .ndo_open = hdlcdev_open, | ||
8014 | .ndo_stop = hdlcdev_close, | ||
8015 | .ndo_change_mtu = hdlc_change_mtu, | ||
8016 | .ndo_start_xmit = hdlc_start_xmit, | ||
8017 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
8018 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
8019 | }; | ||
8020 | |||
8014 | /** | 8021 | /** |
8015 | * called by device driver when adding device instance | 8022 | * called by device driver when adding device instance |
8016 | * do generic HDLC initialization | 8023 | * do generic HDLC initialization |
@@ -8038,11 +8045,8 @@ static int hdlcdev_init(struct mgsl_struct *info) | |||
8038 | dev->dma = info->dma_level; | 8045 | dev->dma = info->dma_level; |
8039 | 8046 | ||
8040 | /* network layer callbacks and settings */ | 8047 | /* network layer callbacks and settings */ |
8041 | dev->do_ioctl = hdlcdev_ioctl; | 8048 | dev->netdev_ops = &hdlcdev_ops; |
8042 | dev->open = hdlcdev_open; | 8049 | dev->watchdog_timeo = 10 * HZ; |
8043 | dev->stop = hdlcdev_close; | ||
8044 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
8045 | dev->watchdog_timeo = 10*HZ; | ||
8046 | dev->tx_queue_len = 50; | 8050 | dev->tx_queue_len = 50; |
8047 | 8051 | ||
8048 | /* generic HDLC layer callbacks and settings */ | 8052 | /* generic HDLC layer callbacks and settings */ |
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index f329f459817c..efb3dc928a43 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -1763,10 +1763,17 @@ static void hdlcdev_rx(struct slgt_info *info, char *buf, int size) | |||
1763 | dev->stats.rx_bytes += size; | 1763 | dev->stats.rx_bytes += size; |
1764 | 1764 | ||
1765 | netif_rx(skb); | 1765 | netif_rx(skb); |
1766 | |||
1767 | dev->last_rx = jiffies; | ||
1768 | } | 1766 | } |
1769 | 1767 | ||
1768 | static const struct net_device_ops hdlcdev_ops = { | ||
1769 | .ndo_open = hdlcdev_open, | ||
1770 | .ndo_stop = hdlcdev_close, | ||
1771 | .ndo_change_mtu = hdlc_change_mtu, | ||
1772 | .ndo_start_xmit = hdlc_start_xmit, | ||
1773 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
1774 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
1775 | }; | ||
1776 | |||
1770 | /** | 1777 | /** |
1771 | * called by device driver when adding device instance | 1778 | * called by device driver when adding device instance |
1772 | * do generic HDLC initialization | 1779 | * do generic HDLC initialization |
@@ -1794,11 +1801,8 @@ static int hdlcdev_init(struct slgt_info *info) | |||
1794 | dev->irq = info->irq_level; | 1801 | dev->irq = info->irq_level; |
1795 | 1802 | ||
1796 | /* network layer callbacks and settings */ | 1803 | /* network layer callbacks and settings */ |
1797 | dev->do_ioctl = hdlcdev_ioctl; | 1804 | dev->netdev_ops = &hdlcdev_ops; |
1798 | dev->open = hdlcdev_open; | 1805 | dev->watchdog_timeo = 10 * HZ; |
1799 | dev->stop = hdlcdev_close; | ||
1800 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
1801 | dev->watchdog_timeo = 10*HZ; | ||
1802 | dev->tx_queue_len = 50; | 1806 | dev->tx_queue_len = 50; |
1803 | 1807 | ||
1804 | /* generic HDLC layer callbacks and settings */ | 1808 | /* generic HDLC layer callbacks and settings */ |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 7b0c5b2dd263..8eb6c89a980e 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
@@ -1907,10 +1907,17 @@ static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size) | |||
1907 | dev->stats.rx_bytes += size; | 1907 | dev->stats.rx_bytes += size; |
1908 | 1908 | ||
1909 | netif_rx(skb); | 1909 | netif_rx(skb); |
1910 | |||
1911 | dev->last_rx = jiffies; | ||
1912 | } | 1910 | } |
1913 | 1911 | ||
1912 | static const struct net_device_ops hdlcdev_ops = { | ||
1913 | .ndo_open = hdlcdev_open, | ||
1914 | .ndo_stop = hdlcdev_close, | ||
1915 | .ndo_change_mtu = hdlc_change_mtu, | ||
1916 | .ndo_start_xmit = hdlc_start_xmit, | ||
1917 | .ndo_do_ioctl = hdlcdev_ioctl, | ||
1918 | .ndo_tx_timeout = hdlcdev_tx_timeout, | ||
1919 | }; | ||
1920 | |||
1914 | /** | 1921 | /** |
1915 | * called by device driver when adding device instance | 1922 | * called by device driver when adding device instance |
1916 | * do generic HDLC initialization | 1923 | * do generic HDLC initialization |
@@ -1938,11 +1945,8 @@ static int hdlcdev_init(SLMP_INFO *info) | |||
1938 | dev->irq = info->irq_level; | 1945 | dev->irq = info->irq_level; |
1939 | 1946 | ||
1940 | /* network layer callbacks and settings */ | 1947 | /* network layer callbacks and settings */ |
1941 | dev->do_ioctl = hdlcdev_ioctl; | 1948 | dev->netdev_ops = &hdlcdev_ops; |
1942 | dev->open = hdlcdev_open; | 1949 | dev->watchdog_timeo = 10 * HZ; |
1943 | dev->stop = hdlcdev_close; | ||
1944 | dev->tx_timeout = hdlcdev_tx_timeout; | ||
1945 | dev->watchdog_timeo = 10*HZ; | ||
1946 | dev->tx_queue_len = 50; | 1950 | dev->tx_queue_len = 50; |
1947 | 1951 | ||
1948 | /* generic HDLC layer callbacks and settings */ | 1952 | /* generic HDLC layer callbacks and settings */ |
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9c47dc48c9fd..ccdd828adcef 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
@@ -429,134 +429,148 @@ out: | |||
429 | #define TPM_DIGEST_SIZE 20 | 429 | #define TPM_DIGEST_SIZE 20 |
430 | #define TPM_ERROR_SIZE 10 | 430 | #define TPM_ERROR_SIZE 10 |
431 | #define TPM_RET_CODE_IDX 6 | 431 | #define TPM_RET_CODE_IDX 6 |
432 | #define TPM_GET_CAP_RET_SIZE_IDX 10 | ||
433 | #define TPM_GET_CAP_RET_UINT32_1_IDX 14 | ||
434 | #define TPM_GET_CAP_RET_UINT32_2_IDX 18 | ||
435 | #define TPM_GET_CAP_RET_UINT32_3_IDX 22 | ||
436 | #define TPM_GET_CAP_RET_UINT32_4_IDX 26 | ||
437 | #define TPM_GET_CAP_PERM_DISABLE_IDX 16 | ||
438 | #define TPM_GET_CAP_PERM_INACTIVE_IDX 18 | ||
439 | #define TPM_GET_CAP_RET_BOOL_1_IDX 14 | ||
440 | #define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 | ||
441 | |||
442 | #define TPM_CAP_IDX 13 | ||
443 | #define TPM_CAP_SUBCAP_IDX 21 | ||
444 | 432 | ||
445 | enum tpm_capabilities { | 433 | enum tpm_capabilities { |
446 | TPM_CAP_FLAG = 4, | 434 | TPM_CAP_FLAG = cpu_to_be32(4), |
447 | TPM_CAP_PROP = 5, | 435 | TPM_CAP_PROP = cpu_to_be32(5), |
436 | CAP_VERSION_1_1 = cpu_to_be32(0x06), | ||
437 | CAP_VERSION_1_2 = cpu_to_be32(0x1A) | ||
448 | }; | 438 | }; |
449 | 439 | ||
450 | enum tpm_sub_capabilities { | 440 | enum tpm_sub_capabilities { |
451 | TPM_CAP_PROP_PCR = 0x1, | 441 | TPM_CAP_PROP_PCR = cpu_to_be32(0x101), |
452 | TPM_CAP_PROP_MANUFACTURER = 0x3, | 442 | TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), |
453 | TPM_CAP_FLAG_PERM = 0x8, | 443 | TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), |
454 | TPM_CAP_FLAG_VOL = 0x9, | 444 | TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), |
455 | TPM_CAP_PROP_OWNER = 0x11, | 445 | TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), |
456 | TPM_CAP_PROP_TIS_TIMEOUT = 0x15, | 446 | TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), |
457 | TPM_CAP_PROP_TIS_DURATION = 0x20, | 447 | TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), |
458 | }; | ||
459 | 448 | ||
460 | /* | ||
461 | * This is a semi generic GetCapability command for use | ||
462 | * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG | ||
463 | * and their associated sub_capabilities. | ||
464 | */ | ||
465 | |||
466 | static const u8 tpm_cap[] = { | ||
467 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
468 | 0, 0, 0, 22, /* length */ | ||
469 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | ||
470 | 0, 0, 0, 0, /* TPM_CAP_<TYPE> */ | ||
471 | 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */ | ||
472 | 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */ | ||
473 | }; | 449 | }; |
474 | 450 | ||
475 | static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, | 451 | static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, |
476 | char *desc) | 452 | int len, const char *desc) |
477 | { | 453 | { |
478 | int err; | 454 | int err; |
479 | 455 | ||
480 | len = tpm_transmit(chip, data, len); | 456 | len = tpm_transmit(chip,(u8 *) cmd, len); |
481 | if (len < 0) | 457 | if (len < 0) |
482 | return len; | 458 | return len; |
483 | if (len == TPM_ERROR_SIZE) { | 459 | if (len == TPM_ERROR_SIZE) { |
484 | err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); | 460 | err = be32_to_cpu(cmd->header.out.return_code); |
485 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | 461 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); |
486 | return err; | 462 | return err; |
487 | } | 463 | } |
488 | return 0; | 464 | return 0; |
489 | } | 465 | } |
490 | 466 | ||
467 | #define TPM_INTERNAL_RESULT_SIZE 200 | ||
468 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) | ||
469 | #define TPM_ORD_GET_CAP cpu_to_be32(101) | ||
470 | |||
471 | static const struct tpm_input_header tpm_getcap_header = { | ||
472 | .tag = TPM_TAG_RQU_COMMAND, | ||
473 | .length = cpu_to_be32(22), | ||
474 | .ordinal = TPM_ORD_GET_CAP | ||
475 | }; | ||
476 | |||
477 | ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, | ||
478 | const char *desc) | ||
479 | { | ||
480 | struct tpm_cmd_t tpm_cmd; | ||
481 | int rc; | ||
482 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
483 | |||
484 | tpm_cmd.header.in = tpm_getcap_header; | ||
485 | if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { | ||
486 | tpm_cmd.params.getcap_in.cap = subcap_id; | ||
487 | /*subcap field not necessary */ | ||
488 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); | ||
489 | tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); | ||
490 | } else { | ||
491 | if (subcap_id == TPM_CAP_FLAG_PERM || | ||
492 | subcap_id == TPM_CAP_FLAG_VOL) | ||
493 | tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG; | ||
494 | else | ||
495 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; | ||
496 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); | ||
497 | tpm_cmd.params.getcap_in.subcap = subcap_id; | ||
498 | } | ||
499 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); | ||
500 | if (!rc) | ||
501 | *cap = tpm_cmd.params.getcap_out.cap; | ||
502 | return rc; | ||
503 | } | ||
504 | |||
491 | void tpm_gen_interrupt(struct tpm_chip *chip) | 505 | void tpm_gen_interrupt(struct tpm_chip *chip) |
492 | { | 506 | { |
493 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | 507 | struct tpm_cmd_t tpm_cmd; |
494 | ssize_t rc; | 508 | ssize_t rc; |
495 | 509 | ||
496 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 510 | tpm_cmd.header.in = tpm_getcap_header; |
497 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 511 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
498 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | 512 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
513 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | ||
499 | 514 | ||
500 | rc = transmit_cmd(chip, data, sizeof(data), | 515 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
501 | "attempting to determine the timeouts"); | 516 | "attempting to determine the timeouts"); |
502 | } | 517 | } |
503 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 518 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
504 | 519 | ||
505 | void tpm_get_timeouts(struct tpm_chip *chip) | 520 | void tpm_get_timeouts(struct tpm_chip *chip) |
506 | { | 521 | { |
507 | u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; | 522 | struct tpm_cmd_t tpm_cmd; |
523 | struct timeout_t *timeout_cap; | ||
524 | struct duration_t *duration_cap; | ||
508 | ssize_t rc; | 525 | ssize_t rc; |
509 | u32 timeout; | 526 | u32 timeout; |
510 | 527 | ||
511 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 528 | tpm_cmd.header.in = tpm_getcap_header; |
512 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 529 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
513 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; | 530 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
531 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; | ||
514 | 532 | ||
515 | rc = transmit_cmd(chip, data, sizeof(data), | 533 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
516 | "attempting to determine the timeouts"); | 534 | "attempting to determine the timeouts"); |
517 | if (rc) | 535 | if (rc) |
518 | goto duration; | 536 | goto duration; |
519 | 537 | ||
520 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | 538 | if (be32_to_cpu(tpm_cmd.header.out.length) |
521 | != 4 * sizeof(u32)) | 539 | != 4 * sizeof(u32)) |
522 | goto duration; | 540 | goto duration; |
523 | 541 | ||
542 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; | ||
524 | /* Don't overwrite default if value is 0 */ | 543 | /* Don't overwrite default if value is 0 */ |
525 | timeout = | 544 | timeout = be32_to_cpu(timeout_cap->a); |
526 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); | ||
527 | if (timeout) | 545 | if (timeout) |
528 | chip->vendor.timeout_a = usecs_to_jiffies(timeout); | 546 | chip->vendor.timeout_a = usecs_to_jiffies(timeout); |
529 | timeout = | 547 | timeout = be32_to_cpu(timeout_cap->b); |
530 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); | ||
531 | if (timeout) | 548 | if (timeout) |
532 | chip->vendor.timeout_b = usecs_to_jiffies(timeout); | 549 | chip->vendor.timeout_b = usecs_to_jiffies(timeout); |
533 | timeout = | 550 | timeout = be32_to_cpu(timeout_cap->c); |
534 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); | ||
535 | if (timeout) | 551 | if (timeout) |
536 | chip->vendor.timeout_c = usecs_to_jiffies(timeout); | 552 | chip->vendor.timeout_c = usecs_to_jiffies(timeout); |
537 | timeout = | 553 | timeout = be32_to_cpu(timeout_cap->d); |
538 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); | ||
539 | if (timeout) | 554 | if (timeout) |
540 | chip->vendor.timeout_d = usecs_to_jiffies(timeout); | 555 | chip->vendor.timeout_d = usecs_to_jiffies(timeout); |
541 | 556 | ||
542 | duration: | 557 | duration: |
543 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 558 | tpm_cmd.header.in = tpm_getcap_header; |
544 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | 559 | tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; |
545 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; | 560 | tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); |
561 | tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; | ||
546 | 562 | ||
547 | rc = transmit_cmd(chip, data, sizeof(data), | 563 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
548 | "attempting to determine the durations"); | 564 | "attempting to determine the durations"); |
549 | if (rc) | 565 | if (rc) |
550 | return; | 566 | return; |
551 | 567 | ||
552 | if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) | 568 | if (be32_to_cpu(tpm_cmd.header.out.return_code) |
553 | != 3 * sizeof(u32)) | 569 | != 3 * sizeof(u32)) |
554 | return; | 570 | return; |
555 | 571 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; | |
556 | chip->vendor.duration[TPM_SHORT] = | 572 | chip->vendor.duration[TPM_SHORT] = |
557 | usecs_to_jiffies(be32_to_cpu | 573 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); |
558 | (*((__be32 *) (data + | ||
559 | TPM_GET_CAP_RET_UINT32_1_IDX)))); | ||
560 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above | 574 | /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above |
561 | * value wrong and apparently reports msecs rather than usecs. So we | 575 | * value wrong and apparently reports msecs rather than usecs. So we |
562 | * fix up the resulting too-small TPM_SHORT value to make things work. | 576 | * fix up the resulting too-small TPM_SHORT value to make things work. |
@@ -565,13 +579,9 @@ duration: | |||
565 | chip->vendor.duration[TPM_SHORT] = HZ; | 579 | chip->vendor.duration[TPM_SHORT] = HZ; |
566 | 580 | ||
567 | chip->vendor.duration[TPM_MEDIUM] = | 581 | chip->vendor.duration[TPM_MEDIUM] = |
568 | usecs_to_jiffies(be32_to_cpu | 582 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); |
569 | (*((__be32 *) (data + | ||
570 | TPM_GET_CAP_RET_UINT32_2_IDX)))); | ||
571 | chip->vendor.duration[TPM_LONG] = | 583 | chip->vendor.duration[TPM_LONG] = |
572 | usecs_to_jiffies(be32_to_cpu | 584 | usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); |
573 | (*((__be32 *) (data + | ||
574 | TPM_GET_CAP_RET_UINT32_3_IDX)))); | ||
575 | } | 585 | } |
576 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | 586 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); |
577 | 587 | ||
@@ -587,36 +597,18 @@ void tpm_continue_selftest(struct tpm_chip *chip) | |||
587 | } | 597 | } |
588 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | 598 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); |
589 | 599 | ||
590 | #define TPM_INTERNAL_RESULT_SIZE 200 | ||
591 | |||
592 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 600 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
593 | char *buf) | 601 | char *buf) |
594 | { | 602 | { |
595 | u8 *data; | 603 | cap_t cap; |
596 | ssize_t rc; | 604 | ssize_t rc; |
597 | 605 | ||
598 | struct tpm_chip *chip = dev_get_drvdata(dev); | 606 | rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, |
599 | if (chip == NULL) | 607 | "attempting to determine the permanent enabled state"); |
600 | return -ENODEV; | 608 | if (rc) |
601 | |||
602 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
603 | if (!data) | ||
604 | return -ENOMEM; | ||
605 | |||
606 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
607 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
608 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
609 | |||
610 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
611 | "attemtping to determine the permanent enabled state"); | ||
612 | if (rc) { | ||
613 | kfree(data); | ||
614 | return 0; | 609 | return 0; |
615 | } | ||
616 | |||
617 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); | ||
618 | 610 | ||
619 | kfree(data); | 611 | rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); |
620 | return rc; | 612 | return rc; |
621 | } | 613 | } |
622 | EXPORT_SYMBOL_GPL(tpm_show_enabled); | 614 | EXPORT_SYMBOL_GPL(tpm_show_enabled); |
@@ -624,31 +616,15 @@ EXPORT_SYMBOL_GPL(tpm_show_enabled); | |||
624 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, | 616 | ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, |
625 | char *buf) | 617 | char *buf) |
626 | { | 618 | { |
627 | u8 *data; | 619 | cap_t cap; |
628 | ssize_t rc; | 620 | ssize_t rc; |
629 | 621 | ||
630 | struct tpm_chip *chip = dev_get_drvdata(dev); | 622 | rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, |
631 | if (chip == NULL) | 623 | "attempting to determine the permanent active state"); |
632 | return -ENODEV; | 624 | if (rc) |
633 | |||
634 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
635 | if (!data) | ||
636 | return -ENOMEM; | ||
637 | |||
638 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
639 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | ||
640 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; | ||
641 | |||
642 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
643 | "attemtping to determine the permanent active state"); | ||
644 | if (rc) { | ||
645 | kfree(data); | ||
646 | return 0; | 625 | return 0; |
647 | } | ||
648 | 626 | ||
649 | rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); | 627 | rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); |
650 | |||
651 | kfree(data); | ||
652 | return rc; | 628 | return rc; |
653 | } | 629 | } |
654 | EXPORT_SYMBOL_GPL(tpm_show_active); | 630 | EXPORT_SYMBOL_GPL(tpm_show_active); |
@@ -656,31 +632,15 @@ EXPORT_SYMBOL_GPL(tpm_show_active); | |||
656 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, | 632 | ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, |
657 | char *buf) | 633 | char *buf) |
658 | { | 634 | { |
659 | u8 *data; | 635 | cap_t cap; |
660 | ssize_t rc; | 636 | ssize_t rc; |
661 | 637 | ||
662 | struct tpm_chip *chip = dev_get_drvdata(dev); | 638 | rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, |
663 | if (chip == NULL) | 639 | "attempting to determine the owner state"); |
664 | return -ENODEV; | 640 | if (rc) |
665 | |||
666 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
667 | if (!data) | ||
668 | return -ENOMEM; | ||
669 | |||
670 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
671 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
672 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; | ||
673 | |||
674 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
675 | "attempting to determine the owner state"); | ||
676 | if (rc) { | ||
677 | kfree(data); | ||
678 | return 0; | 641 | return 0; |
679 | } | ||
680 | |||
681 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); | ||
682 | 642 | ||
683 | kfree(data); | 643 | rc = sprintf(buf, "%d\n", cap.owned); |
684 | return rc; | 644 | return rc; |
685 | } | 645 | } |
686 | EXPORT_SYMBOL_GPL(tpm_show_owned); | 646 | EXPORT_SYMBOL_GPL(tpm_show_owned); |
@@ -688,116 +648,180 @@ EXPORT_SYMBOL_GPL(tpm_show_owned); | |||
688 | ssize_t tpm_show_temp_deactivated(struct device * dev, | 648 | ssize_t tpm_show_temp_deactivated(struct device * dev, |
689 | struct device_attribute * attr, char *buf) | 649 | struct device_attribute * attr, char *buf) |
690 | { | 650 | { |
691 | u8 *data; | 651 | cap_t cap; |
692 | ssize_t rc; | 652 | ssize_t rc; |
693 | 653 | ||
694 | struct tpm_chip *chip = dev_get_drvdata(dev); | 654 | rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, |
695 | if (chip == NULL) | 655 | "attempting to determine the temporary state"); |
696 | return -ENODEV; | 656 | if (rc) |
657 | return 0; | ||
697 | 658 | ||
698 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | 659 | rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); |
699 | if (!data) | 660 | return rc; |
700 | return -ENOMEM; | 661 | } |
662 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | ||
701 | 663 | ||
702 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | 664 | /* |
703 | data[TPM_CAP_IDX] = TPM_CAP_FLAG; | 665 | * tpm_chip_find_get - return tpm_chip for given chip number |
704 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; | 666 | */ |
667 | static struct tpm_chip *tpm_chip_find_get(int chip_num) | ||
668 | { | ||
669 | struct tpm_chip *pos, *chip = NULL; | ||
705 | 670 | ||
706 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | 671 | rcu_read_lock(); |
707 | "attempting to determine the temporary state"); | 672 | list_for_each_entry_rcu(pos, &tpm_chip_list, list) { |
708 | if (rc) { | 673 | if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) |
709 | kfree(data); | 674 | continue; |
710 | return 0; | 675 | |
676 | if (try_module_get(pos->dev->driver->owner)) { | ||
677 | chip = pos; | ||
678 | break; | ||
679 | } | ||
711 | } | 680 | } |
681 | rcu_read_unlock(); | ||
682 | return chip; | ||
683 | } | ||
712 | 684 | ||
713 | rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); | 685 | #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) |
686 | #define READ_PCR_RESULT_SIZE 30 | ||
687 | static struct tpm_input_header pcrread_header = { | ||
688 | .tag = TPM_TAG_RQU_COMMAND, | ||
689 | .length = cpu_to_be32(14), | ||
690 | .ordinal = TPM_ORDINAL_PCRREAD | ||
691 | }; | ||
714 | 692 | ||
715 | kfree(data); | 693 | int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
694 | { | ||
695 | int rc; | ||
696 | struct tpm_cmd_t cmd; | ||
697 | |||
698 | cmd.header.in = pcrread_header; | ||
699 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); | ||
700 | BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); | ||
701 | rc = transmit_cmd(chip, &cmd, cmd.header.in.length, | ||
702 | "attempting to read a pcr value"); | ||
703 | |||
704 | if (rc == 0) | ||
705 | memcpy(res_buf, cmd.params.pcrread_out.pcr_result, | ||
706 | TPM_DIGEST_SIZE); | ||
716 | return rc; | 707 | return rc; |
717 | } | 708 | } |
718 | EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); | ||
719 | 709 | ||
720 | static const u8 pcrread[] = { | 710 | /** |
721 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 711 | * tpm_pcr_read - read a pcr value |
722 | 0, 0, 0, 14, /* length */ | 712 | * @chip_num: tpm idx # or ANY |
723 | 0, 0, 0, 21, /* TPM_ORD_PcrRead */ | 713 | * @pcr_idx: pcr idx to retrieve |
724 | 0, 0, 0, 0 /* PCR index */ | 714 | * @res_buf: TPM_PCR value |
715 | * size of res_buf is 20 bytes (or NULL if you don't care) | ||
716 | * | ||
717 | * The TPM driver should be built-in, but for whatever reason it | ||
718 | * isn't, protect against the chip disappearing, by incrementing | ||
719 | * the module usage count. | ||
720 | */ | ||
721 | int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) | ||
722 | { | ||
723 | struct tpm_chip *chip; | ||
724 | int rc; | ||
725 | |||
726 | chip = tpm_chip_find_get(chip_num); | ||
727 | if (chip == NULL) | ||
728 | return -ENODEV; | ||
729 | rc = __tpm_pcr_read(chip, pcr_idx, res_buf); | ||
730 | module_put(chip->dev->driver->owner); | ||
731 | return rc; | ||
732 | } | ||
733 | EXPORT_SYMBOL_GPL(tpm_pcr_read); | ||
734 | |||
735 | /** | ||
736 | * tpm_pcr_extend - extend pcr value with hash | ||
737 | * @chip_num: tpm idx # or AN& | ||
738 | * @pcr_idx: pcr idx to extend | ||
739 | * @hash: hash value used to extend pcr value | ||
740 | * | ||
741 | * The TPM driver should be built-in, but for whatever reason it | ||
742 | * isn't, protect against the chip disappearing, by incrementing | ||
743 | * the module usage count. | ||
744 | */ | ||
745 | #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) | ||
746 | #define EXTEND_PCR_SIZE 34 | ||
747 | static struct tpm_input_header pcrextend_header = { | ||
748 | .tag = TPM_TAG_RQU_COMMAND, | ||
749 | .length = cpu_to_be32(34), | ||
750 | .ordinal = TPM_ORD_PCR_EXTEND | ||
725 | }; | 751 | }; |
726 | 752 | ||
753 | int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | ||
754 | { | ||
755 | struct tpm_cmd_t cmd; | ||
756 | int rc; | ||
757 | struct tpm_chip *chip; | ||
758 | |||
759 | chip = tpm_chip_find_get(chip_num); | ||
760 | if (chip == NULL) | ||
761 | return -ENODEV; | ||
762 | |||
763 | cmd.header.in = pcrextend_header; | ||
764 | BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); | ||
765 | cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); | ||
766 | memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); | ||
767 | rc = transmit_cmd(chip, &cmd, cmd.header.in.length, | ||
768 | "attempting extend a PCR value"); | ||
769 | |||
770 | module_put(chip->dev->driver->owner); | ||
771 | return rc; | ||
772 | } | ||
773 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); | ||
774 | |||
727 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, | 775 | ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, |
728 | char *buf) | 776 | char *buf) |
729 | { | 777 | { |
730 | u8 *data; | 778 | cap_t cap; |
779 | u8 digest[TPM_DIGEST_SIZE]; | ||
731 | ssize_t rc; | 780 | ssize_t rc; |
732 | int i, j, num_pcrs; | 781 | int i, j, num_pcrs; |
733 | __be32 index; | ||
734 | char *str = buf; | 782 | char *str = buf; |
735 | |||
736 | struct tpm_chip *chip = dev_get_drvdata(dev); | 783 | struct tpm_chip *chip = dev_get_drvdata(dev); |
737 | if (chip == NULL) | ||
738 | return -ENODEV; | ||
739 | 784 | ||
740 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | 785 | rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, |
741 | if (!data) | ||
742 | return -ENOMEM; | ||
743 | |||
744 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
745 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
746 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; | ||
747 | |||
748 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
749 | "attempting to determine the number of PCRS"); | 786 | "attempting to determine the number of PCRS"); |
750 | if (rc) { | 787 | if (rc) |
751 | kfree(data); | ||
752 | return 0; | 788 | return 0; |
753 | } | ||
754 | 789 | ||
755 | num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); | 790 | num_pcrs = be32_to_cpu(cap.num_pcrs); |
756 | for (i = 0; i < num_pcrs; i++) { | 791 | for (i = 0; i < num_pcrs; i++) { |
757 | memcpy(data, pcrread, sizeof(pcrread)); | 792 | rc = __tpm_pcr_read(chip, i, digest); |
758 | index = cpu_to_be32(i); | ||
759 | memcpy(data + 10, &index, 4); | ||
760 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
761 | "attempting to read a PCR"); | ||
762 | if (rc) | 793 | if (rc) |
763 | goto out; | 794 | break; |
764 | str += sprintf(str, "PCR-%02d: ", i); | 795 | str += sprintf(str, "PCR-%02d: ", i); |
765 | for (j = 0; j < TPM_DIGEST_SIZE; j++) | 796 | for (j = 0; j < TPM_DIGEST_SIZE; j++) |
766 | str += sprintf(str, "%02X ", *(data + 10 + j)); | 797 | str += sprintf(str, "%02X ", digest[j]); |
767 | str += sprintf(str, "\n"); | 798 | str += sprintf(str, "\n"); |
768 | } | 799 | } |
769 | out: | ||
770 | kfree(data); | ||
771 | return str - buf; | 800 | return str - buf; |
772 | } | 801 | } |
773 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); | 802 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); |
774 | 803 | ||
775 | #define READ_PUBEK_RESULT_SIZE 314 | 804 | #define READ_PUBEK_RESULT_SIZE 314 |
776 | static const u8 readpubek[] = { | 805 | #define TPM_ORD_READPUBEK cpu_to_be32(124) |
777 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | 806 | struct tpm_input_header tpm_readpubek_header = { |
778 | 0, 0, 0, 30, /* length */ | 807 | .tag = TPM_TAG_RQU_COMMAND, |
779 | 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ | 808 | .length = cpu_to_be32(30), |
809 | .ordinal = TPM_ORD_READPUBEK | ||
780 | }; | 810 | }; |
781 | 811 | ||
782 | ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | 812 | ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, |
783 | char *buf) | 813 | char *buf) |
784 | { | 814 | { |
785 | u8 *data; | 815 | u8 *data; |
816 | struct tpm_cmd_t tpm_cmd; | ||
786 | ssize_t err; | 817 | ssize_t err; |
787 | int i, rc; | 818 | int i, rc; |
788 | char *str = buf; | 819 | char *str = buf; |
789 | 820 | ||
790 | struct tpm_chip *chip = dev_get_drvdata(dev); | 821 | struct tpm_chip *chip = dev_get_drvdata(dev); |
791 | if (chip == NULL) | ||
792 | return -ENODEV; | ||
793 | 822 | ||
794 | data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); | 823 | tpm_cmd.header.in = tpm_readpubek_header; |
795 | if (!data) | 824 | err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, |
796 | return -ENOMEM; | ||
797 | |||
798 | memcpy(data, readpubek, sizeof(readpubek)); | ||
799 | |||
800 | err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, | ||
801 | "attempting to read the PUBEK"); | 825 | "attempting to read the PUBEK"); |
802 | if (err) | 826 | if (err) |
803 | goto out; | 827 | goto out; |
@@ -812,7 +836,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
812 | 256 byte modulus | 836 | 256 byte modulus |
813 | ignore checksum 20 bytes | 837 | ignore checksum 20 bytes |
814 | */ | 838 | */ |
815 | 839 | data = tpm_cmd.params.readpubek_out_buffer; | |
816 | str += | 840 | str += |
817 | sprintf(str, | 841 | sprintf(str, |
818 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" | 842 | "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" |
@@ -832,65 +856,33 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, | |||
832 | } | 856 | } |
833 | out: | 857 | out: |
834 | rc = str - buf; | 858 | rc = str - buf; |
835 | kfree(data); | ||
836 | return rc; | 859 | return rc; |
837 | } | 860 | } |
838 | EXPORT_SYMBOL_GPL(tpm_show_pubek); | 861 | EXPORT_SYMBOL_GPL(tpm_show_pubek); |
839 | 862 | ||
840 | #define CAP_VERSION_1_1 6 | ||
841 | #define CAP_VERSION_1_2 0x1A | ||
842 | #define CAP_VERSION_IDX 13 | ||
843 | static const u8 cap_version[] = { | ||
844 | 0, 193, /* TPM_TAG_RQU_COMMAND */ | ||
845 | 0, 0, 0, 18, /* length */ | ||
846 | 0, 0, 0, 101, /* TPM_ORD_GetCapability */ | ||
847 | 0, 0, 0, 0, | ||
848 | 0, 0, 0, 0 | ||
849 | }; | ||
850 | 863 | ||
851 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, | 864 | ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, |
852 | char *buf) | 865 | char *buf) |
853 | { | 866 | { |
854 | u8 *data; | 867 | cap_t cap; |
855 | ssize_t rc; | 868 | ssize_t rc; |
856 | char *str = buf; | 869 | char *str = buf; |
857 | 870 | ||
858 | struct tpm_chip *chip = dev_get_drvdata(dev); | 871 | rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, |
859 | if (chip == NULL) | ||
860 | return -ENODEV; | ||
861 | |||
862 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
863 | if (!data) | ||
864 | return -ENOMEM; | ||
865 | |||
866 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
867 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
868 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
869 | |||
870 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
871 | "attempting to determine the manufacturer"); | 872 | "attempting to determine the manufacturer"); |
872 | if (rc) { | 873 | if (rc) |
873 | kfree(data); | ||
874 | return 0; | 874 | return 0; |
875 | } | ||
876 | |||
877 | str += sprintf(str, "Manufacturer: 0x%x\n", | 875 | str += sprintf(str, "Manufacturer: 0x%x\n", |
878 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | 876 | be32_to_cpu(cap.manufacturer_id)); |
879 | 877 | ||
880 | memcpy(data, cap_version, sizeof(cap_version)); | 878 | rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, |
881 | data[CAP_VERSION_IDX] = CAP_VERSION_1_1; | 879 | "attempting to determine the 1.1 version"); |
882 | rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, | ||
883 | "attempting to determine the 1.1 version"); | ||
884 | if (rc) | 880 | if (rc) |
885 | goto out; | 881 | return 0; |
886 | |||
887 | str += sprintf(str, | 882 | str += sprintf(str, |
888 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | 883 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
889 | (int) data[14], (int) data[15], (int) data[16], | 884 | cap.tpm_version.Major, cap.tpm_version.Minor, |
890 | (int) data[17]); | 885 | cap.tpm_version.revMajor, cap.tpm_version.revMinor); |
891 | |||
892 | out: | ||
893 | kfree(data); | ||
894 | return str - buf; | 886 | return str - buf; |
895 | } | 887 | } |
896 | EXPORT_SYMBOL_GPL(tpm_show_caps); | 888 | EXPORT_SYMBOL_GPL(tpm_show_caps); |
@@ -898,51 +890,25 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); | |||
898 | ssize_t tpm_show_caps_1_2(struct device * dev, | 890 | ssize_t tpm_show_caps_1_2(struct device * dev, |
899 | struct device_attribute * attr, char *buf) | 891 | struct device_attribute * attr, char *buf) |
900 | { | 892 | { |
901 | u8 *data; | 893 | cap_t cap; |
902 | ssize_t len; | 894 | ssize_t rc; |
903 | char *str = buf; | 895 | char *str = buf; |
904 | 896 | ||
905 | struct tpm_chip *chip = dev_get_drvdata(dev); | 897 | rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, |
906 | if (chip == NULL) | 898 | "attempting to determine the manufacturer"); |
907 | return -ENODEV; | 899 | if (rc) |
908 | |||
909 | data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); | ||
910 | if (!data) | ||
911 | return -ENOMEM; | ||
912 | |||
913 | memcpy(data, tpm_cap, sizeof(tpm_cap)); | ||
914 | data[TPM_CAP_IDX] = TPM_CAP_PROP; | ||
915 | data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; | ||
916 | |||
917 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); | ||
918 | if (len <= TPM_ERROR_SIZE) { | ||
919 | dev_dbg(chip->dev, "A TPM error (%d) occurred " | ||
920 | "attempting to determine the manufacturer\n", | ||
921 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
922 | kfree(data); | ||
923 | return 0; | 900 | return 0; |
924 | } | ||
925 | |||
926 | str += sprintf(str, "Manufacturer: 0x%x\n", | 901 | str += sprintf(str, "Manufacturer: 0x%x\n", |
927 | be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); | 902 | be32_to_cpu(cap.manufacturer_id)); |
928 | 903 | rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, | |
929 | memcpy(data, cap_version, sizeof(cap_version)); | 904 | "attempting to determine the 1.2 version"); |
930 | data[CAP_VERSION_IDX] = CAP_VERSION_1_2; | 905 | if (rc) |
931 | 906 | return 0; | |
932 | len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); | ||
933 | if (len <= TPM_ERROR_SIZE) { | ||
934 | dev_err(chip->dev, "A TPM error (%d) occurred " | ||
935 | "attempting to determine the 1.2 version\n", | ||
936 | be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); | ||
937 | goto out; | ||
938 | } | ||
939 | str += sprintf(str, | 907 | str += sprintf(str, |
940 | "TCG version: %d.%d\nFirmware version: %d.%d\n", | 908 | "TCG version: %d.%d\nFirmware version: %d.%d\n", |
941 | (int) data[16], (int) data[17], (int) data[18], | 909 | cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor, |
942 | (int) data[19]); | 910 | cap.tpm_version_1_2.revMajor, |
943 | 911 | cap.tpm_version_1_2.revMinor); | |
944 | out: | ||
945 | kfree(data); | ||
946 | return str - buf; | 912 | return str - buf; |
947 | } | 913 | } |
948 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); | 914 | EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e30df4a4388..8e00b4ddd083 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/miscdevice.h> | 26 | #include <linux/miscdevice.h> |
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/tpm.h> | ||
29 | 30 | ||
30 | enum tpm_timeout { | 31 | enum tpm_timeout { |
31 | TPM_TIMEOUT = 5, /* msecs */ | 32 | TPM_TIMEOUT = 5, /* msecs */ |
@@ -123,6 +124,147 @@ static inline void tpm_write_index(int base, int index, int value) | |||
123 | outb(index, base); | 124 | outb(index, base); |
124 | outb(value & 0xFF, base+1); | 125 | outb(value & 0xFF, base+1); |
125 | } | 126 | } |
127 | struct tpm_input_header { | ||
128 | __be16 tag; | ||
129 | __be32 length; | ||
130 | __be32 ordinal; | ||
131 | }__attribute__((packed)); | ||
132 | |||
133 | struct tpm_output_header { | ||
134 | __be16 tag; | ||
135 | __be32 length; | ||
136 | __be32 return_code; | ||
137 | }__attribute__((packed)); | ||
138 | |||
139 | struct stclear_flags_t { | ||
140 | __be16 tag; | ||
141 | u8 deactivated; | ||
142 | u8 disableForceClear; | ||
143 | u8 physicalPresence; | ||
144 | u8 physicalPresenceLock; | ||
145 | u8 bGlobalLock; | ||
146 | }__attribute__((packed)); | ||
147 | |||
148 | struct tpm_version_t { | ||
149 | u8 Major; | ||
150 | u8 Minor; | ||
151 | u8 revMajor; | ||
152 | u8 revMinor; | ||
153 | }__attribute__((packed)); | ||
154 | |||
155 | struct tpm_version_1_2_t { | ||
156 | __be16 tag; | ||
157 | u8 Major; | ||
158 | u8 Minor; | ||
159 | u8 revMajor; | ||
160 | u8 revMinor; | ||
161 | }__attribute__((packed)); | ||
162 | |||
163 | struct timeout_t { | ||
164 | __be32 a; | ||
165 | __be32 b; | ||
166 | __be32 c; | ||
167 | __be32 d; | ||
168 | }__attribute__((packed)); | ||
169 | |||
170 | struct duration_t { | ||
171 | __be32 tpm_short; | ||
172 | __be32 tpm_medium; | ||
173 | __be32 tpm_long; | ||
174 | }__attribute__((packed)); | ||
175 | |||
176 | struct permanent_flags_t { | ||
177 | __be16 tag; | ||
178 | u8 disable; | ||
179 | u8 ownership; | ||
180 | u8 deactivated; | ||
181 | u8 readPubek; | ||
182 | u8 disableOwnerClear; | ||
183 | u8 allowMaintenance; | ||
184 | u8 physicalPresenceLifetimeLock; | ||
185 | u8 physicalPresenceHWEnable; | ||
186 | u8 physicalPresenceCMDEnable; | ||
187 | u8 CEKPUsed; | ||
188 | u8 TPMpost; | ||
189 | u8 TPMpostLock; | ||
190 | u8 FIPS; | ||
191 | u8 operator; | ||
192 | u8 enableRevokeEK; | ||
193 | u8 nvLocked; | ||
194 | u8 readSRKPub; | ||
195 | u8 tpmEstablished; | ||
196 | u8 maintenanceDone; | ||
197 | u8 disableFullDALogicInfo; | ||
198 | }__attribute__((packed)); | ||
199 | |||
200 | typedef union { | ||
201 | struct permanent_flags_t perm_flags; | ||
202 | struct stclear_flags_t stclear_flags; | ||
203 | bool owned; | ||
204 | __be32 num_pcrs; | ||
205 | struct tpm_version_t tpm_version; | ||
206 | struct tpm_version_1_2_t tpm_version_1_2; | ||
207 | __be32 manufacturer_id; | ||
208 | struct timeout_t timeout; | ||
209 | struct duration_t duration; | ||
210 | } cap_t; | ||
211 | |||
212 | struct tpm_getcap_params_in { | ||
213 | __be32 cap; | ||
214 | __be32 subcap_size; | ||
215 | __be32 subcap; | ||
216 | }__attribute__((packed)); | ||
217 | |||
218 | struct tpm_getcap_params_out { | ||
219 | __be32 cap_size; | ||
220 | cap_t cap; | ||
221 | }__attribute__((packed)); | ||
222 | |||
223 | struct tpm_readpubek_params_out { | ||
224 | u8 algorithm[4]; | ||
225 | u8 encscheme[2]; | ||
226 | u8 sigscheme[2]; | ||
227 | u8 parameters[12]; /*assuming RSA*/ | ||
228 | __be32 keysize; | ||
229 | u8 modulus[256]; | ||
230 | u8 checksum[20]; | ||
231 | }__attribute__((packed)); | ||
232 | |||
233 | typedef union { | ||
234 | struct tpm_input_header in; | ||
235 | struct tpm_output_header out; | ||
236 | } tpm_cmd_header; | ||
237 | |||
238 | #define TPM_DIGEST_SIZE 20 | ||
239 | struct tpm_pcrread_out { | ||
240 | u8 pcr_result[TPM_DIGEST_SIZE]; | ||
241 | }__attribute__((packed)); | ||
242 | |||
243 | struct tpm_pcrread_in { | ||
244 | __be32 pcr_idx; | ||
245 | }__attribute__((packed)); | ||
246 | |||
247 | struct tpm_pcrextend_in { | ||
248 | __be32 pcr_idx; | ||
249 | u8 hash[TPM_DIGEST_SIZE]; | ||
250 | }__attribute__((packed)); | ||
251 | |||
252 | typedef union { | ||
253 | struct tpm_getcap_params_out getcap_out; | ||
254 | struct tpm_readpubek_params_out readpubek_out; | ||
255 | u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; | ||
256 | struct tpm_getcap_params_in getcap_in; | ||
257 | struct tpm_pcrread_in pcrread_in; | ||
258 | struct tpm_pcrread_out pcrread_out; | ||
259 | struct tpm_pcrextend_in pcrextend_in; | ||
260 | } tpm_cmd_params; | ||
261 | |||
262 | struct tpm_cmd_t { | ||
263 | tpm_cmd_header header; | ||
264 | tpm_cmd_params params; | ||
265 | }__attribute__((packed)); | ||
266 | |||
267 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | ||
126 | 268 | ||
127 | extern void tpm_get_timeouts(struct tpm_chip *); | 269 | extern void tpm_get_timeouts(struct tpm_chip *); |
128 | extern void tpm_gen_interrupt(struct tpm_chip *); | 270 | extern void tpm_gen_interrupt(struct tpm_chip *); |
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index d0e7926eb486..c64a1bc65349 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
@@ -168,12 +168,22 @@ static void atml_plat_remove(void) | |||
168 | } | 168 | } |
169 | } | 169 | } |
170 | 170 | ||
171 | static struct device_driver atml_drv = { | 171 | static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg) |
172 | .name = "tpm_atmel", | 172 | { |
173 | .bus = &platform_bus_type, | 173 | return tpm_pm_suspend(&dev->dev, msg); |
174 | .owner = THIS_MODULE, | 174 | } |
175 | .suspend = tpm_pm_suspend, | 175 | |
176 | .resume = tpm_pm_resume, | 176 | static int tpm_atml_resume(struct platform_device *dev) |
177 | { | ||
178 | return tpm_pm_resume(&dev->dev); | ||
179 | } | ||
180 | static struct platform_driver atml_drv = { | ||
181 | .driver = { | ||
182 | .name = "tpm_atmel", | ||
183 | .owner = THIS_MODULE, | ||
184 | }, | ||
185 | .suspend = tpm_atml_suspend, | ||
186 | .resume = tpm_atml_resume, | ||
177 | }; | 187 | }; |
178 | 188 | ||
179 | static int __init init_atmel(void) | 189 | static int __init init_atmel(void) |
@@ -184,7 +194,7 @@ static int __init init_atmel(void) | |||
184 | unsigned long base; | 194 | unsigned long base; |
185 | struct tpm_chip *chip; | 195 | struct tpm_chip *chip; |
186 | 196 | ||
187 | rc = driver_register(&atml_drv); | 197 | rc = platform_driver_register(&atml_drv); |
188 | if (rc) | 198 | if (rc) |
189 | return rc; | 199 | return rc; |
190 | 200 | ||
@@ -223,13 +233,13 @@ err_rel_reg: | |||
223 | atmel_release_region(base, | 233 | atmel_release_region(base, |
224 | region_size); | 234 | region_size); |
225 | err_unreg_drv: | 235 | err_unreg_drv: |
226 | driver_unregister(&atml_drv); | 236 | platform_driver_unregister(&atml_drv); |
227 | return rc; | 237 | return rc; |
228 | } | 238 | } |
229 | 239 | ||
230 | static void __exit cleanup_atmel(void) | 240 | static void __exit cleanup_atmel(void) |
231 | { | 241 | { |
232 | driver_unregister(&atml_drv); | 242 | platform_driver_unregister(&atml_drv); |
233 | atml_plat_remove(); | 243 | atml_plat_remove(); |
234 | } | 244 | } |
235 | 245 | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 717af7ad1bdf..aec1931608aa 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -654,12 +654,22 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | |||
654 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 654 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
655 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 655 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
656 | 656 | ||
657 | static struct device_driver tis_drv = { | 657 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) |
658 | .name = "tpm_tis", | 658 | { |
659 | .bus = &platform_bus_type, | 659 | return tpm_pm_suspend(&dev->dev, msg); |
660 | .owner = THIS_MODULE, | 660 | } |
661 | .suspend = tpm_pm_suspend, | 661 | |
662 | .resume = tpm_pm_resume, | 662 | static int tpm_tis_resume(struct platform_device *dev) |
663 | { | ||
664 | return tpm_pm_resume(&dev->dev); | ||
665 | } | ||
666 | static struct platform_driver tis_drv = { | ||
667 | .driver = { | ||
668 | .name = "tpm_tis", | ||
669 | .owner = THIS_MODULE, | ||
670 | }, | ||
671 | .suspend = tpm_tis_suspend, | ||
672 | .resume = tpm_tis_resume, | ||
663 | }; | 673 | }; |
664 | 674 | ||
665 | static struct platform_device *pdev; | 675 | static struct platform_device *pdev; |
@@ -672,14 +682,14 @@ static int __init init_tis(void) | |||
672 | int rc; | 682 | int rc; |
673 | 683 | ||
674 | if (force) { | 684 | if (force) { |
675 | rc = driver_register(&tis_drv); | 685 | rc = platform_driver_register(&tis_drv); |
676 | if (rc < 0) | 686 | if (rc < 0) |
677 | return rc; | 687 | return rc; |
678 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) | 688 | if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) |
679 | return PTR_ERR(pdev); | 689 | return PTR_ERR(pdev); |
680 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { | 690 | if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { |
681 | platform_device_unregister(pdev); | 691 | platform_device_unregister(pdev); |
682 | driver_unregister(&tis_drv); | 692 | platform_driver_unregister(&tis_drv); |
683 | } | 693 | } |
684 | return rc; | 694 | return rc; |
685 | } | 695 | } |
@@ -711,7 +721,7 @@ static void __exit cleanup_tis(void) | |||
711 | 721 | ||
712 | if (force) { | 722 | if (force) { |
713 | platform_device_unregister(pdev); | 723 | platform_device_unregister(pdev); |
714 | driver_unregister(&tis_drv); | 724 | platform_driver_unregister(&tis_drv); |
715 | } else | 725 | } else |
716 | pnp_unregister_driver(&tis_pnp_driver); | 726 | pnp_unregister_driver(&tis_pnp_driver); |
717 | } | 727 | } |
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 4f3b3f95fc42..d94d25c12aa8 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c | |||
@@ -479,18 +479,18 @@ static const struct file_operations vcs_fops = { | |||
479 | 479 | ||
480 | static struct class *vc_class; | 480 | static struct class *vc_class; |
481 | 481 | ||
482 | void vcs_make_sysfs(struct tty_struct *tty) | 482 | void vcs_make_sysfs(int index) |
483 | { | 483 | { |
484 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL, | 484 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, |
485 | "vcs%u", tty->index + 1); | 485 | "vcs%u", index + 1); |
486 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL, | 486 | device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, |
487 | "vcsa%u", tty->index + 1); | 487 | "vcsa%u", index + 1); |
488 | } | 488 | } |
489 | 489 | ||
490 | void vcs_remove_sysfs(struct tty_struct *tty) | 490 | void vcs_remove_sysfs(int index) |
491 | { | 491 | { |
492 | device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); | 492 | device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1)); |
493 | device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); | 493 | device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129)); |
494 | } | 494 | } |
495 | 495 | ||
496 | int __init vcs_init(void) | 496 | int __init vcs_init(void) |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7900bd63b36d..2c1d133819b5 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -778,6 +778,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ | |||
778 | } | 778 | } |
779 | vc->vc_kmalloced = 1; | 779 | vc->vc_kmalloced = 1; |
780 | vc_init(vc, vc->vc_rows, vc->vc_cols, 1); | 780 | vc_init(vc, vc->vc_rows, vc->vc_cols, 1); |
781 | vcs_make_sysfs(currcons); | ||
781 | atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); | 782 | atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); |
782 | } | 783 | } |
783 | return 0; | 784 | return 0; |
@@ -987,7 +988,9 @@ void vc_deallocate(unsigned int currcons) | |||
987 | if (vc_cons_allocated(currcons)) { | 988 | if (vc_cons_allocated(currcons)) { |
988 | struct vc_data *vc = vc_cons[currcons].d; | 989 | struct vc_data *vc = vc_cons[currcons].d; |
989 | struct vt_notifier_param param = { .vc = vc }; | 990 | struct vt_notifier_param param = { .vc = vc }; |
991 | |||
990 | atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); | 992 | atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); |
993 | vcs_remove_sysfs(currcons); | ||
991 | vc->vc_sw->con_deinit(vc); | 994 | vc->vc_sw->con_deinit(vc); |
992 | put_pid(vc->vt_pid); | 995 | put_pid(vc->vt_pid); |
993 | module_put(vc->vc_sw->owner); | 996 | module_put(vc->vc_sw->owner); |
@@ -2775,7 +2778,6 @@ static int con_open(struct tty_struct *tty, struct file *filp) | |||
2775 | tty->termios->c_iflag |= IUTF8; | 2778 | tty->termios->c_iflag |= IUTF8; |
2776 | else | 2779 | else |
2777 | tty->termios->c_iflag &= ~IUTF8; | 2780 | tty->termios->c_iflag &= ~IUTF8; |
2778 | vcs_make_sysfs(tty); | ||
2779 | release_console_sem(); | 2781 | release_console_sem(); |
2780 | return ret; | 2782 | return ret; |
2781 | } | 2783 | } |
@@ -2795,7 +2797,6 @@ static void con_shutdown(struct tty_struct *tty) | |||
2795 | BUG_ON(vc == NULL); | 2797 | BUG_ON(vc == NULL); |
2796 | acquire_console_sem(); | 2798 | acquire_console_sem(); |
2797 | vc->vc_tty = NULL; | 2799 | vc->vc_tty = NULL; |
2798 | vcs_remove_sysfs(tty); | ||
2799 | release_console_sem(); | 2800 | release_console_sem(); |
2800 | tty_shutdown(tty); | 2801 | tty_shutdown(tty); |
2801 | } | 2802 | } |