aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tpm/tpm_tis.c
diff options
context:
space:
mode:
authorJarkko Sakkinen <jarkko.sakkinen@linux.intel.com>2014-12-12 14:46:34 -0500
committerPeter Huewe <peterhuewe@gmx.de>2015-01-17 08:00:09 -0500
commitafb5abc262e962089ef2d7c2bbf71bb6f53a2a78 (patch)
tree5e59c2de94a0f083634e5ead5cf46c34df79eace /drivers/char/tpm/tpm_tis.c
parent87155b7311bfec75b590b823b11f77adf2a16412 (diff)
tpm: two-phase chip management functions
tpm_register_hardware() and tpm_remove_hardware() are called often before initializing the device. The problem is that the device might not be fully initialized when it comes visible to the user space. This patch resolves the issue by diving initialization into two parts: - tpmm_chip_alloc() creates struct tpm_chip. - tpm_chip_register() sets up the character device and sysfs attributes. The framework takes care of freeing struct tpm_chip by using the devres API. The broken release callback has been wiped. ACPI drivers do not ever get this callback. Regards to Jason Gunthorpe for carefully reviewing this part of the code. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Reviewed-by: Jasob Gunthorpe <jason.gunthorpe@obsidianresearch.com> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Tested-by: Scot Doyle <lkml14@scotdoyle.com> Tested-by: Peter Huewe <peterhuewe@gmx.de> [phuewe: update to upstream changes] Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
Diffstat (limited to 'drivers/char/tpm/tpm_tis.c')
-rw-r--r--drivers/char/tpm/tpm_tis.c80
1 files changed, 31 insertions, 49 deletions
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index ccb140d60532..36f4fec11c2a 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -79,9 +79,6 @@ struct priv_data {
79 bool irq_tested; 79 bool irq_tested;
80}; 80};
81 81
82static LIST_HEAD(tis_chips);
83static DEFINE_MUTEX(tis_lock);
84
85#if defined(CONFIG_PNP) && defined(CONFIG_ACPI) 82#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
86static int is_itpm(struct pnp_dev *dev) 83static int is_itpm(struct pnp_dev *dev)
87{ 84{
@@ -572,6 +569,17 @@ static bool interrupts = true;
572module_param(interrupts, bool, 0444); 569module_param(interrupts, bool, 0444);
573MODULE_PARM_DESC(interrupts, "Enable interrupts"); 570MODULE_PARM_DESC(interrupts, "Enable interrupts");
574 571
572static void tpm_tis_remove(struct tpm_chip *chip)
573{
574 iowrite32(~TPM_GLOBAL_INT_ENABLE &
575 ioread32(chip->vendor.iobase +
576 TPM_INT_ENABLE(chip->vendor.
577 locality)),
578 chip->vendor.iobase +
579 TPM_INT_ENABLE(chip->vendor.locality));
580 release_locality(chip, chip->vendor.locality, 1);
581}
582
575static int tpm_tis_init(struct device *dev, resource_size_t start, 583static int tpm_tis_init(struct device *dev, resource_size_t start,
576 resource_size_t len, unsigned int irq) 584 resource_size_t len, unsigned int irq)
577{ 585{
@@ -583,15 +591,16 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
583 priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL); 591 priv = devm_kzalloc(dev, sizeof(struct priv_data), GFP_KERNEL);
584 if (priv == NULL) 592 if (priv == NULL)
585 return -ENOMEM; 593 return -ENOMEM;
586 if (!(chip = tpm_register_hardware(dev, &tpm_tis))) 594
587 return -ENODEV; 595 chip = tpmm_chip_alloc(dev, &tpm_tis);
596 if (IS_ERR(chip))
597 return PTR_ERR(chip);
598
588 chip->vendor.priv = priv; 599 chip->vendor.priv = priv;
589 600
590 chip->vendor.iobase = ioremap(start, len); 601 chip->vendor.iobase = devm_ioremap(dev, start, len);
591 if (!chip->vendor.iobase) { 602 if (!chip->vendor.iobase)
592 rc = -EIO; 603 return -EIO;
593 goto out_err;
594 }
595 604
596 /* Default timeouts */ 605 /* Default timeouts */
597 chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); 606 chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT);
@@ -685,8 +694,8 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
685 for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) { 694 for (i = irq_s; i <= irq_e && chip->vendor.irq == 0; i++) {
686 iowrite8(i, chip->vendor.iobase + 695 iowrite8(i, chip->vendor.iobase +
687 TPM_INT_VECTOR(chip->vendor.locality)); 696 TPM_INT_VECTOR(chip->vendor.locality));
688 if (request_irq 697 if (devm_request_irq
689 (i, tis_int_probe, IRQF_SHARED, 698 (dev, i, tis_int_probe, IRQF_SHARED,
690 chip->vendor.miscdev.name, chip) != 0) { 699 chip->vendor.miscdev.name, chip) != 0) {
691 dev_info(chip->dev, 700 dev_info(chip->dev,
692 "Unable to request irq: %d for probe\n", 701 "Unable to request irq: %d for probe\n",
@@ -726,15 +735,14 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
726 iowrite32(intmask, 735 iowrite32(intmask,
727 chip->vendor.iobase + 736 chip->vendor.iobase +
728 TPM_INT_ENABLE(chip->vendor.locality)); 737 TPM_INT_ENABLE(chip->vendor.locality));
729 free_irq(i, chip);
730 } 738 }
731 } 739 }
732 if (chip->vendor.irq) { 740 if (chip->vendor.irq) {
733 iowrite8(chip->vendor.irq, 741 iowrite8(chip->vendor.irq,
734 chip->vendor.iobase + 742 chip->vendor.iobase +
735 TPM_INT_VECTOR(chip->vendor.locality)); 743 TPM_INT_VECTOR(chip->vendor.locality));
736 if (request_irq 744 if (devm_request_irq
737 (chip->vendor.irq, tis_int_handler, IRQF_SHARED, 745 (dev, chip->vendor.irq, tis_int_handler, IRQF_SHARED,
738 chip->vendor.miscdev.name, chip) != 0) { 746 chip->vendor.miscdev.name, chip) != 0) {
739 dev_info(chip->dev, 747 dev_info(chip->dev,
740 "Unable to request irq: %d for use\n", 748 "Unable to request irq: %d for use\n",
@@ -767,17 +775,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
767 goto out_err; 775 goto out_err;
768 } 776 }
769 777
770 INIT_LIST_HEAD(&chip->vendor.list); 778 return tpm_chip_register(chip);
771 mutex_lock(&tis_lock);
772 list_add(&chip->vendor.list, &tis_chips);
773 mutex_unlock(&tis_lock);
774
775
776 return 0;
777out_err: 779out_err:
778 if (chip->vendor.iobase) 780 tpm_tis_remove(chip);
779 iounmap(chip->vendor.iobase);
780 tpm_remove_hardware(chip->dev);
781 return rc; 781 return rc;
782} 782}
783 783
@@ -859,13 +859,10 @@ MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
859static void tpm_tis_pnp_remove(struct pnp_dev *dev) 859static void tpm_tis_pnp_remove(struct pnp_dev *dev)
860{ 860{
861 struct tpm_chip *chip = pnp_get_drvdata(dev); 861 struct tpm_chip *chip = pnp_get_drvdata(dev);
862 862 tpm_chip_unregister(chip);
863 tpm_dev_vendor_release(chip); 863 tpm_tis_remove(chip);
864
865 kfree(chip);
866} 864}
867 865
868
869static struct pnp_driver tis_pnp_driver = { 866static struct pnp_driver tis_pnp_driver = {
870 .name = "tpm_tis", 867 .name = "tpm_tis",
871 .id_table = tpm_pnp_tbl, 868 .id_table = tpm_pnp_tbl,
@@ -884,7 +881,7 @@ MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
884 881
885static struct platform_driver tis_drv = { 882static struct platform_driver tis_drv = {
886 .driver = { 883 .driver = {
887 .name = "tpm_tis", 884 .name = "tpm_tis",
888 .pm = &tpm_tis_pm, 885 .pm = &tpm_tis_pm,
889 }, 886 },
890}; 887};
@@ -923,31 +920,16 @@ err_dev:
923 920
924static void __exit cleanup_tis(void) 921static void __exit cleanup_tis(void)
925{ 922{
926 struct tpm_vendor_specific *i, *j;
927 struct tpm_chip *chip; 923 struct tpm_chip *chip;
928 mutex_lock(&tis_lock);
929 list_for_each_entry_safe(i, j, &tis_chips, list) {
930 chip = to_tpm_chip(i);
931 tpm_remove_hardware(chip->dev);
932 iowrite32(~TPM_GLOBAL_INT_ENABLE &
933 ioread32(chip->vendor.iobase +
934 TPM_INT_ENABLE(chip->vendor.
935 locality)),
936 chip->vendor.iobase +
937 TPM_INT_ENABLE(chip->vendor.locality));
938 release_locality(chip, chip->vendor.locality, 1);
939 if (chip->vendor.irq)
940 free_irq(chip->vendor.irq, chip);
941 iounmap(i->iobase);
942 list_del(&i->list);
943 }
944 mutex_unlock(&tis_lock);
945#ifdef CONFIG_PNP 924#ifdef CONFIG_PNP
946 if (!force) { 925 if (!force) {
947 pnp_unregister_driver(&tis_pnp_driver); 926 pnp_unregister_driver(&tis_pnp_driver);
948 return; 927 return;
949 } 928 }
950#endif 929#endif
930 chip = dev_get_drvdata(&pdev->dev);
931 tpm_chip_unregister(chip);
932 tpm_tis_remove(chip);
951 platform_device_unregister(pdev); 933 platform_device_unregister(pdev);
952 platform_driver_unregister(&tis_drv); 934 platform_driver_unregister(&tis_drv);
953} 935}