aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2016-01-07 19:36:24 -0500
committerJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2016-02-09 21:11:37 -0500
commit00194826e6be333083ba9ddbd6e83fb423206f8a (patch)
treef0539c44583256010bf71730b8ef13f71e1d2c76 /drivers/char
parent51dd43dff74b0547ad844638f6910ca29c956819 (diff)
tpm_tis: Clean up the force=1 module parameter
The TPM core has long assumed that every device has a driver attached, however the force path was attaching the TPM core outside of a driver context. This isn't generally reliable as the user could detatch the driver using sysfs or something, but commit b8b2c7d845d5 ("base/platform: assert that dev_pm_domain callbacks are called unconditionally") forced the issue by leaving the driver pointer NULL if there is no probe. Rework the TPM setup to create a platform device with resources and then allow the driver core to naturally bind and probe it through the normal mechanisms. All this structure is needed anyhow to enable TPM for OF environments. Finally, since the entire flow is changing convert the init/exit to use the modern ifdef-less coding style when possible Reported-by: "Wilck, Martin" <martin.wilck@ts.fujitsu.com> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Tested-by: Wilck, Martin <martin.wilck@ts.fujitsu.com> Tested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Acked-by: Peter Huewe <peterhuewe@gmx.de>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/tpm/tpm_tis.c169
1 files changed, 104 insertions, 65 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 7407835791ef..ca137b5b7c24 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -59,7 +59,6 @@ enum tis_int_flags {
59}; 59};
60 60
61enum tis_defaults { 61enum tis_defaults {
62 TIS_MEM_BASE = 0xFED40000,
63 TIS_MEM_LEN = 0x5000, 62 TIS_MEM_LEN = 0x5000,
64 TIS_SHORT_TIMEOUT = 750, /* ms */ 63 TIS_SHORT_TIMEOUT = 750, /* ms */
65 TIS_LONG_TIMEOUT = 2000, /* 2 sec */ 64 TIS_LONG_TIMEOUT = 2000, /* 2 sec */
@@ -74,15 +73,6 @@ struct tpm_info {
74 int irq; 73 int irq;
75}; 74};
76 75
77static struct tpm_info tis_default_info = {
78 .res = {
79 .start = TIS_MEM_BASE,
80 .end = TIS_MEM_BASE + TIS_MEM_LEN - 1,
81 .flags = IORESOURCE_MEM,
82 },
83 .irq = 0,
84};
85
86/* Some timeout values are needed before it is known whether the chip is 76/* Some timeout values are needed before it is known whether the chip is
87 * TPM 1.0 or TPM 2.0. 77 * TPM 1.0 or TPM 2.0.
88 */ 78 */
@@ -824,7 +814,6 @@ out_err:
824 return rc; 814 return rc;
825} 815}
826 816
827#ifdef CONFIG_PM_SLEEP
828static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) 817static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
829{ 818{
830 u32 intmask; 819 u32 intmask;
@@ -866,11 +855,9 @@ static int tpm_tis_resume(struct device *dev)
866 855
867 return 0; 856 return 0;
868} 857}
869#endif
870 858
871static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); 859static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
872 860
873#ifdef CONFIG_PNP
874static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, 861static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
875 const struct pnp_device_id *pnp_id) 862 const struct pnp_device_id *pnp_id)
876{ 863{
@@ -888,14 +875,12 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
888 else 875 else
889 tpm_info.irq = -1; 876 tpm_info.irq = -1;
890 877
891#ifdef CONFIG_ACPI
892 if (pnp_acpi_device(pnp_dev)) { 878 if (pnp_acpi_device(pnp_dev)) {
893 if (is_itpm(pnp_acpi_device(pnp_dev))) 879 if (is_itpm(pnp_acpi_device(pnp_dev)))
894 itpm = true; 880 itpm = true;
895 881
896 acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle; 882 acpi_dev_handle = ACPI_HANDLE(&pnp_dev->dev);
897 } 883 }
898#endif
899 884
900 return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle); 885 return tpm_tis_init(&pnp_dev->dev, &tpm_info, acpi_dev_handle);
901} 886}
@@ -936,7 +921,6 @@ static struct pnp_driver tis_pnp_driver = {
936module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, 921module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
937 sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); 922 sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
938MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); 923MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
939#endif
940 924
941#ifdef CONFIG_ACPI 925#ifdef CONFIG_ACPI
942static int tpm_check_resource(struct acpi_resource *ares, void *data) 926static int tpm_check_resource(struct acpi_resource *ares, void *data)
@@ -1023,80 +1007,135 @@ static struct acpi_driver tis_acpi_driver = {
1023}; 1007};
1024#endif 1008#endif
1025 1009
1010static struct platform_device *force_pdev;
1011
1012static int tpm_tis_plat_probe(struct platform_device *pdev)
1013{
1014 struct tpm_info tpm_info = {};
1015 struct resource *res;
1016
1017 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1018 if (res == NULL) {
1019 dev_err(&pdev->dev, "no memory resource defined\n");
1020 return -ENODEV;
1021 }
1022 tpm_info.res = *res;
1023
1024 res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1025 if (res) {
1026 tpm_info.irq = res->start;
1027 } else {
1028 if (pdev == force_pdev)
1029 tpm_info.irq = -1;
1030 else
1031 /* When forcing auto probe the IRQ */
1032 tpm_info.irq = 0;
1033 }
1034
1035 return tpm_tis_init(&pdev->dev, &tpm_info, NULL);
1036}
1037
1038static int tpm_tis_plat_remove(struct platform_device *pdev)
1039{
1040 struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
1041
1042 tpm_chip_unregister(chip);
1043 tpm_tis_remove(chip);
1044
1045 return 0;
1046}
1047
1026static struct platform_driver tis_drv = { 1048static struct platform_driver tis_drv = {
1049 .probe = tpm_tis_plat_probe,
1050 .remove = tpm_tis_plat_remove,
1027 .driver = { 1051 .driver = {
1028 .name = "tpm_tis", 1052 .name = "tpm_tis",
1029 .pm = &tpm_tis_pm, 1053 .pm = &tpm_tis_pm,
1030 }, 1054 },
1031}; 1055};
1032 1056
1033static struct platform_device *pdev;
1034
1035static bool force; 1057static bool force;
1058#ifdef CONFIG_X86
1036module_param(force, bool, 0444); 1059module_param(force, bool, 0444);
1037MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); 1060MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
1061#endif
1062
1063static int tpm_tis_force_device(void)
1064{
1065 struct platform_device *pdev;
1066 static const struct resource x86_resources[] = {
1067 {
1068 .start = 0xFED40000,
1069 .end = 0xFED40000 + TIS_MEM_LEN - 1,
1070 .flags = IORESOURCE_MEM,
1071 },
1072 };
1073
1074 if (!force)
1075 return 0;
1076
1077 /* The driver core will match the name tpm_tis of the device to
1078 * the tpm_tis platform driver and complete the setup via
1079 * tpm_tis_plat_probe
1080 */
1081 pdev = platform_device_register_simple("tpm_tis", -1, x86_resources,
1082 ARRAY_SIZE(x86_resources));
1083 if (IS_ERR(pdev))
1084 return PTR_ERR(pdev);
1085 force_pdev = pdev;
1086
1087 return 0;
1088}
1089
1038static int __init init_tis(void) 1090static int __init init_tis(void)
1039{ 1091{
1040 int rc; 1092 int rc;
1041#ifdef CONFIG_PNP 1093
1042 if (!force) { 1094 rc = tpm_tis_force_device();
1043 rc = pnp_register_driver(&tis_pnp_driver); 1095 if (rc)
1044 if (rc) 1096 goto err_force;
1045 return rc; 1097
1046 } 1098 rc = platform_driver_register(&tis_drv);
1047#endif 1099 if (rc)
1100 goto err_platform;
1101
1048#ifdef CONFIG_ACPI 1102#ifdef CONFIG_ACPI
1049 if (!force) { 1103 rc = acpi_bus_register_driver(&tis_acpi_driver);
1050 rc = acpi_bus_register_driver(&tis_acpi_driver); 1104 if (rc)
1051 if (rc) { 1105 goto err_acpi;
1052#ifdef CONFIG_PNP
1053 pnp_unregister_driver(&tis_pnp_driver);
1054#endif
1055 return rc;
1056 }
1057 }
1058#endif 1106#endif
1059 if (!force)
1060 return 0;
1061 1107
1062 rc = platform_driver_register(&tis_drv); 1108 if (IS_ENABLED(CONFIG_PNP)) {
1063 if (rc < 0) 1109 rc = pnp_register_driver(&tis_pnp_driver);
1064 return rc; 1110 if (rc)
1065 pdev = platform_device_register_simple("tpm_tis", -1, NULL, 0); 1111 goto err_pnp;
1066 if (IS_ERR(pdev)) {
1067 rc = PTR_ERR(pdev);
1068 goto err_dev;
1069 } 1112 }
1070 rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL); 1113
1071 if (rc)
1072 goto err_init;
1073 return 0; 1114 return 0;
1074err_init: 1115
1075 platform_device_unregister(pdev); 1116err_pnp:
1076err_dev: 1117#ifdef CONFIG_ACPI
1077 platform_driver_unregister(&tis_drv); 1118 acpi_bus_unregister_driver(&tis_acpi_driver);
1119err_acpi:
1120#endif
1121 platform_device_unregister(force_pdev);
1122err_platform:
1123 if (force_pdev)
1124 platform_device_unregister(force_pdev);
1125err_force:
1078 return rc; 1126 return rc;
1079} 1127}
1080 1128
1081static void __exit cleanup_tis(void) 1129static void __exit cleanup_tis(void)
1082{ 1130{
1083 struct tpm_chip *chip; 1131 pnp_unregister_driver(&tis_pnp_driver);
1084#if defined(CONFIG_PNP) || defined(CONFIG_ACPI)
1085 if (!force) {
1086#ifdef CONFIG_ACPI 1132#ifdef CONFIG_ACPI
1087 acpi_bus_unregister_driver(&tis_acpi_driver); 1133 acpi_bus_unregister_driver(&tis_acpi_driver);
1088#endif
1089#ifdef CONFIG_PNP
1090 pnp_unregister_driver(&tis_pnp_driver);
1091#endif
1092 return;
1093 }
1094#endif 1134#endif
1095 chip = dev_get_drvdata(&pdev->dev);
1096 tpm_chip_unregister(chip);
1097 tpm_tis_remove(chip);
1098 platform_device_unregister(pdev);
1099 platform_driver_unregister(&tis_drv); 1135 platform_driver_unregister(&tis_drv);
1136
1137 if (force_pdev)
1138 platform_device_unregister(force_pdev);
1100} 1139}
1101 1140
1102module_init(init_tis); 1141module_init(init_tis);