diff mbox

[1/2] tpm, tpm_tis: use acpi_driver instead of pnp_driver

Message ID 1443546431-14948-2-git-send-email-jarkko.sakkinen@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jarkko Sakkinen Sept. 29, 2015, 5:07 p.m. UTC
Migrate to struct acpi_driver in order to get out of 7 character
limitation for the HID.

Reported-by: Matthew Garrett <mjg59@srcf.ucam.org>
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/char/tpm/tpm_tis.c | 124 ++++++++++++++++++++++++++-------------------
 1 file changed, 73 insertions(+), 51 deletions(-)

Comments

Jason Gunthorpe Sept. 29, 2015, 5:26 p.m. UTC | #1
On Tue, Sep 29, 2015 at 08:07:10PM +0300, Jarkko Sakkinen wrote:

> -static struct pnp_device_id tpm_pnp_tbl[] = {
> +static struct acpi_device_id tpm_acpi_tbl[] = {
>  	{"PNP0C31", 0},		/* TPM */
>  	{"ATM1200", 0},		/* Atmel */
>  	{"IFX0102", 0},		/* Infineon */
> @@ -925,28 +941,34 @@ static struct pnp_device_id tpm_pnp_tbl[] = {
>  	{"", 0},		/* User Specified */
>  	{"", 0}			/* Terminator */
>  };

Is this OK? I don't know alot about x86 PNP, but I thought the
pnp_device_id scheme would work with ACPI and legacy PNPBIOS stuff,
and changing to ACPI means ACPI only?

If so, should we care? Is there a spec for non-ACPI TPM discovery we
need to be following here?

>  	struct tpm_chip *chip;
> -#ifdef CONFIG_PNP
> +#ifdef CONFIG_ACPI

Can you look at the various ifdefs and see if they can be something
like:

>  	if (!force) {
> -		pnp_unregister_driver(&tis_pnp_driver);
> +		acpi_bus_unregister_driver(&tis_acpi_driver);

  if (IS_ENABLED(CONFIG_ACPI))
		acpi_bus_unregister_driver(&tis_acpi_driver);

I think alot of the core driver stuff supports that now?

Jason

------------------------------------------------------------------------------
Matthew Garrett Sept. 29, 2015, 5:30 p.m. UTC | #2
On Tue, Sep 29, 2015 at 08:07:10PM +0300, Jarkko Sakkinen wrote:
> Migrate to struct acpi_driver in order to get out of 7 character
> limitation for the HID.

Are we guaranteed that there are no old systems reporting these devices 
via pnpbios rather than acpi?
Jarkko Sakkinen Sept. 30, 2015, 5:56 a.m. UTC | #3
On Tue, Sep 29, 2015 at 11:26:53AM -0600, Jason Gunthorpe wrote:
> On Tue, Sep 29, 2015 at 08:07:10PM +0300, Jarkko Sakkinen wrote:
> 
> > -static struct pnp_device_id tpm_pnp_tbl[] = {
> > +static struct acpi_device_id tpm_acpi_tbl[] = {
> >  	{"PNP0C31", 0},		/* TPM */
> >  	{"ATM1200", 0},		/* Atmel */
> >  	{"IFX0102", 0},		/* Infineon */
> > @@ -925,28 +941,34 @@ static struct pnp_device_id tpm_pnp_tbl[] = {
> >  	{"", 0},		/* User Specified */
> >  	{"", 0}			/* Terminator */
> >  };
> 
> Is this OK? I don't know alot about x86 PNP, but I thought the
> pnp_device_id scheme would work with ACPI and legacy PNPBIOS stuff,
> and changing to ACPI means ACPI only?
> 
> If so, should we care? Is there a spec for non-ACPI TPM discovery we
> need to be following here?

I found at least all the IDs listed from drivers/acpi/acpi_pnp.c but you
might be right that they might be (don't know) with pnpbios.

Maybe a better solution would to have two tables and have only MSFT0101
in tpm_acpi_tbl in order to make sure that old functionality is not
broken up because we want this also to the stable kernels.

/Jarkko

------------------------------------------------------------------------------
Jarkko Sakkinen Sept. 30, 2015, 5:58 a.m. UTC | #4
On Tue, Sep 29, 2015 at 06:30:25PM +0100, Matthew Garrett wrote:
> On Tue, Sep 29, 2015 at 08:07:10PM +0300, Jarkko Sakkinen wrote:
> > Migrate to struct acpi_driver in order to get out of 7 character
> > limitation for the HID.
> 
> Are we guaranteed that there are no old systems reporting these devices 
> via pnpbios rather than acpi?

Right. I think it would make sense to be conservative and use
acpi_driver only for MSFT0101 because at least I don't know answer
to this question. It would be a risk to take these fixes to the stable
kernels othwerwise.

> -- 
> Matthew Garrett | mjg59@srcf.ucam.org

/Jarkko

------------------------------------------------------------------------------
Matthew Garrett Sept. 30, 2015, 6:02 a.m. UTC | #5
On Wed, Sep 30, 2015 at 08:58:35AM +0300, Jarkko Sakkinen wrote:
> Right. I think it would make sense to be conservative and use
> acpi_driver only for MSFT0101 because at least I don't know answer
> to this question. It would be a risk to take these fixes to the stable
> kernels othwerwise.

In that case I'd suggest just adding it to the platform driver struct 
and tidying up the init path a little (and having the platform driver 
init code request resources rather than hardcoding them). It'll make it 
easier to deal with any systems that declare TPMs in other tables such 
as Device Tree later on.
Matthew Garrett Sept. 30, 2015, 6:04 a.m. UTC | #6
On Wed, Sep 30, 2015 at 08:56:12AM +0300, Jarkko Sakkinen wrote:

> I found at least all the IDs listed from drivers/acpi/acpi_pnp.c but you
> might be right that they might be (don't know) with pnpbios.

The entries in acpi_pnp.c mean "If this device is declared in an ACPI 
table, create a PNP device". TPMs are kind of at the cutoff where some 
vendors may have shipped non-ACPI systems with TPMs that were declared 
via pnpbios, so there's a (small) risk that there are some people using 
TPMs tied to PNP devices without a corresponding ACPI device.

> Maybe a better solution would to have two tables and have only MSFT0101
> in tpm_acpi_tbl in order to make sure that old functionality is not
> broken up because we want this also to the stable kernels.

I'd agree here.
diff mbox

Patch

diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index f2dffa7..87581b2 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -1,6 +1,6 @@ 
 /*
  * Copyright (C) 2005, 2006 IBM Corporation
- * Copyright (C) 2014 Intel Corporation
+ * Copyright (C) 2014, 2015 Intel Corporation
  *
  * Authors:
  * Leendert van Doorn <leendert@watson.ibm.com>
@@ -22,7 +22,6 @@ 
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/pnp.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
@@ -65,6 +64,17 @@  enum tis_defaults {
 	TIS_LONG_TIMEOUT = 2000,	/* 2 sec */
 };
 
+struct tpm_info {
+	unsigned long start;
+	unsigned long len;
+	unsigned int irq;
+};
+
+static struct tpm_info tis_default_info = {
+	.start = TIS_MEM_BASE,
+	.len = TIS_MEM_LEN,
+	.irq = 0,
+};
 
 /* Some timeout values are needed before it is known whether the chip is
  * TPM 1.0 or TPM 2.0.
@@ -90,24 +100,19 @@  struct priv_data {
 	bool irq_tested;
 };
 
-#if defined(CONFIG_PNP) && defined(CONFIG_ACPI)
-static int is_itpm(struct pnp_dev *dev)
+#if defined(CONFIG_ACPI)
+static int is_itpm(struct acpi_device *dev)
 {
-	struct acpi_device *acpi = pnp_acpi_device(dev);
 	struct acpi_hardware_id *id;
 
-	if (!acpi)
-		return 0;
-
-	list_for_each_entry(id, &acpi->pnp.ids, list) {
+	list_for_each_entry(id, &dev->pnp.ids, list)
 		if (!strcmp("INTC0102", id->id))
 			return 1;
-	}
 
 	return 0;
 }
 #else
-static inline int is_itpm(struct pnp_dev *dev)
+static inline int is_itpm(struct acpi_device *dev)
 {
 	return 0;
 }
@@ -600,9 +605,8 @@  static void tpm_tis_remove(struct tpm_chip *chip)
 	release_locality(chip, chip->vendor.locality, 1);
 }
 
-static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
-			resource_size_t start, resource_size_t len,
-			unsigned int irq)
+static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info,
+			acpi_handle acpi_dev_handle)
 {
 	u32 vendor, intfcaps, intmask;
 	int rc, i, irq_s, irq_e, probe;
@@ -622,7 +626,7 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 	chip->acpi_dev_handle = acpi_dev_handle;
 #endif
 
-	chip->vendor.iobase = devm_ioremap(dev, start, len);
+	chip->vendor.iobase = devm_ioremap(dev, tpm_info->start, tpm_info->len);
 	if (!chip->vendor.iobase)
 		return -EIO;
 
@@ -707,7 +711,7 @@  static int tpm_tis_init(struct device *dev, acpi_handle acpi_dev_handle,
 		  chip->vendor.iobase +
 		  TPM_INT_ENABLE(chip->vendor.locality));
 	if (interrupts)
-		chip->vendor.irq = irq;
+		chip->vendor.irq = tpm_info->irq;
 	if (interrupts && !chip->vendor.irq) {
 		irq_s =
 		    ioread8(chip->vendor.iobase +
@@ -886,34 +890,46 @@  static int tpm_tis_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
 
-#ifdef CONFIG_PNP
-static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
-				      const struct pnp_device_id *pnp_id)
+#ifdef CONFIG_ACPI
+static int tpm_check_resource(struct acpi_resource *ares, void *data)
+{
+	struct tpm_info *tpm_info = (struct tpm_info *) data;
+	struct resource res;
+
+	if (acpi_dev_resource_interrupt(ares, 0, &res)) {
+		tpm_info->irq = res.start;
+	} else if (acpi_dev_resource_memory(ares, &res)) {
+		tpm_info->start = res.start;
+		tpm_info->len = resource_size(&res);
+	}
+
+	return 1;
+}
+
+static int tpm_tis_acpi_init(struct acpi_device *acpi_dev)
 {
-	resource_size_t start, len;
-	unsigned int irq = 0;
-	acpi_handle acpi_dev_handle = NULL;
+	struct list_head resources;
+	struct tpm_info tpm_info = tis_default_info;
+	int ret;
+
+	INIT_LIST_HEAD(&resources);
+	ret = acpi_dev_get_resources(acpi_dev, &resources, tpm_check_resource,
+				     &tpm_info);
+	if (ret < 0)
+		return ret;
 
-	start = pnp_mem_start(pnp_dev, 0);
-	len = pnp_mem_len(pnp_dev, 0);
+	acpi_dev_free_resource_list(&resources);
 
-	if (pnp_irq_valid(pnp_dev, 0))
-		irq = pnp_irq(pnp_dev, 0);
-	else
+	if (!tpm_info.irq)
 		interrupts = false;
 
-	if (is_itpm(pnp_dev))
+	if (is_itpm(acpi_dev))
 		itpm = true;
 
-#ifdef CONFIG_ACPI
-	if (pnp_acpi_device(pnp_dev))
-		acpi_dev_handle = pnp_acpi_device(pnp_dev)->handle;
-#endif
-
-	return tpm_tis_init(&pnp_dev->dev, acpi_dev_handle, start, len, irq);
+	return tpm_tis_init(&acpi_dev->dev, &tpm_info, acpi_dev->handle);
 }
 
-static struct pnp_device_id tpm_pnp_tbl[] = {
+static struct acpi_device_id tpm_acpi_tbl[] = {
 	{"PNP0C31", 0},		/* TPM */
 	{"ATM1200", 0},		/* Atmel */
 	{"IFX0102", 0},		/* Infineon */
@@ -925,28 +941,34 @@  static struct pnp_device_id tpm_pnp_tbl[] = {
 	{"", 0},		/* User Specified */
 	{"", 0}			/* Terminator */
 };
-MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl);
+MODULE_DEVICE_TABLE(acpi, tpm_acpi_tbl);
 
-static void tpm_tis_pnp_remove(struct pnp_dev *dev)
+static int tpm_tis_acpi_remove(struct acpi_device *dev)
 {
-	struct tpm_chip *chip = pnp_get_drvdata(dev);
+	struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+
 	tpm_chip_unregister(chip);
 	tpm_tis_remove(chip);
+
+	return 0;
 }
 
-static struct pnp_driver tis_pnp_driver = {
+static struct acpi_driver tis_acpi_driver = {
 	.name = "tpm_tis",
-	.id_table = tpm_pnp_tbl,
-	.probe = tpm_tis_pnp_init,
-	.remove = tpm_tis_pnp_remove,
-	.driver	= {
+	.ids = tpm_acpi_tbl,
+	.ops = {
+		.add = tpm_tis_acpi_init,
+		.remove = tpm_tis_acpi_remove,
+	},
+	.drv = {
 		.pm = &tpm_tis_pm,
 	},
 };
 
-#define TIS_HID_USR_IDX sizeof(tpm_pnp_tbl)/sizeof(struct pnp_device_id) -2
-module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
-		    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
+#define TIS_HID_USR_IDX \
+	(sizeof(tpm_acpi_tbl) / sizeof(struct acpi_device_id) - 2)
+module_param_string(hid, tpm_acpi_tbl[TIS_HID_USR_IDX].id,
+		    sizeof(tpm_acpi_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
 #endif
 
@@ -965,9 +987,9 @@  MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry");
 static int __init init_tis(void)
 {
 	int rc;
-#ifdef CONFIG_PNP
+#ifdef CONFIG_ACPI
 	if (!force)
-		return pnp_register_driver(&tis_pnp_driver);
+		return acpi_bus_register_driver(&tis_acpi_driver);
 #endif
 
 	rc = platform_driver_register(&tis_drv);
@@ -978,7 +1000,7 @@  static int __init init_tis(void)
 		rc = PTR_ERR(pdev);
 		goto err_dev;
 	}
-	rc = tpm_tis_init(&pdev->dev, NULL, TIS_MEM_BASE, TIS_MEM_LEN, 0);
+	rc = tpm_tis_init(&pdev->dev, &tis_default_info, NULL);
 	if (rc)
 		goto err_init;
 	return 0;
@@ -992,9 +1014,9 @@  err_dev:
 static void __exit cleanup_tis(void)
 {
 	struct tpm_chip *chip;
-#ifdef CONFIG_PNP
+#ifdef CONFIG_ACPI
 	if (!force) {
-		pnp_unregister_driver(&tis_pnp_driver);
+		acpi_bus_unregister_driver(&tis_acpi_driver);
 		return;
 	}
 #endif