hpet: convert from ACPI to PNP driver
v2 cover hpet: convert from ACPI to PNP driver
The HPET driver parses ACPI _CRS data manually, but PNPACPI already does that, and it does a more complete job, so we can simplify the HPET driver quite a bit by taking advantage of that.
Clemens, if you like these, will you take care of merging them, or do I need to shepherd them through some other path?
Changes from v1 to v2:
- Wrap PNP code in "#ifdef CONFIG_PNP" (Venki)
- Fix leak when hpet_alloc() fails (Venki)
---
Bjorn Helgaas (4):
hpet: convert from ACPI to PNP driver
hpet: pass physical address, not entire hpet_data, to hpet_is_known()
hpet: clean up io mapping when hpet_alloc() fails
MAINTAINERS: remove obsolete HPET ACPI entry
MAINTAINERS | 5 -- drivers/char/hpet.c | 119 ++++++++++++++++----------------------------------- 2 files changed, 38 insertions(+), 86 deletions(-)
PATCH v2 1/4 hpet: convert from ACPI to PNP driver
PNPACPI already parses _CRS, and does a more complete job than we did here, so let's just take advantage of that.
---
drivers/char/hpet.c | 109 +++++++++++++++------------------------------------ 1 files changed, 33 insertions(+), 76 deletions(-)
drivers/char/hpet.c +33 -76
@@ -31,6 +31,7 @@#include <linux/seq_file.h> #include <linux/bitops.h> #include <linux/clocksource.h> +#include <linux/pnp.h> #include <asm/current.h> #include <asm/uaccess.h>
@@ -40,7 +41,6 @@#include <asm/div64.h> #include <linux/acpi.h> -#include <acpi/acpi_bus.h> #include <linux/hpet.h> /*
@@ -899,101 +899,56 @@ int hpet_alloc(struct hpet_data *hdp)return 0 ; } -static acpi_status hpet_resources (struct acpi_resource *res,void *data) +#ifdef CONFIG_PNP +static int hpet_pnp_add (struct pnp_dev *dev,const struct pnp_device_id *dev_id) { -struct hpet_data *hdp; -acpi_status status; -struct acpi_resource_address64 addr; - - hdp = data; - - status =acpi_resource_to_address64 (res, &addr); - -if (ACPI_SUCCESS (status)) { - hdp->hd_phys_address = addr.minimum; - hdp->hd_address =ioremap (addr.minimum, addr.address_length); - -if (hpet_is_known (hdp)) { -iounmap (hdp->hd_address); -return AE_ALREADY_EXISTS ; - } - }else if (res->type ==ACPI_RESOURCE_TYPE_FIXED_MEMORY32 ) { -struct acpi_resource_fixed_memory32 *fixmem32; - - fixmem32 = &res->data.fixed_memory32; -if (!fixmem32) -return AE_NO_MEMORY ; - - hdp->hd_phys_address = fixmem32->address; - hdp->hd_address =ioremap (fixmem32->address, -HPET_RANGE_SIZE ); - -if (hpet_is_known (hdp)) { -iounmap (hdp->hd_address); -return AE_ALREADY_EXISTS ; - } - }else if (res->type ==ACPI_RESOURCE_TYPE_EXTENDED_IRQ ) { -struct acpi_resource_extended_irq *irqp; -int i, irq; - - irqp = &res->data.extended_irq; - -for (i =0 ; i < irqp->interrupt_count; i++) { - irq =acpi_register_gsi (NULL , irqp->interrupts[i], - irqp->triggering, irqp->polarity); -if (irq <0 ) -return AE_ERROR ; - - hdp->hd_irq[hdp->hd_nirqs] = irq; - hdp->hd_nirqs++; - } - } - -return AE_OK ; -} - -static int hpet_acpi_add (struct acpi_device *device) -{ -acpi_status result;struct hpet_data data; +struct resource *mem, *irq; +int i;memset (&data,0 ,sizeof (data)); - result = -acpi_walk_resources (device->handle,METHOD_NAME__CRS , - hpet_resources, &data); - -if (ACPI_FAILURE (result)) + mem =pnp_get_resource (dev,IORESOURCE_MEM ,0 ); +if (!mem)return -ENODEV ; -if (!data.hd_address || !data.hd_nirqs) { -printk ("%s: no address or irqs in _CRS\n" , __func__); + data.hd_phys_address = mem->start; + +if (hpet_is_known (&data))return -ENODEV ; + + i =0 ; +while (data.hd_nirqs <ARRAY_SIZE (data.hd_irq)) { + irq =pnp_get_resource (dev,IORESOURCE_IRQ , i++); +if (pnp_resource_valid (irq) &&pnp_resource_enabled (irq)) + data.hd_irq[data.hd_nirqs++] = irq->start; } +if (!data.hd_nirqs) +return -ENODEV ; + + data.hd_address =ioremap (mem->start,resource_size (mem));return hpet_alloc (&data); } -static int hpet_acpi_remove (struct acpi_device *device,int type) +static void hpet_pnp_remove (struct pnp_dev *dev) {/* XXX need to unregister clocksource, dealloc mem, etc */ -return -EINVAL ; } -static const struct acpi_device_id hpet_device_ids[] = { +static const struct pnp_device_id hpet_device_ids[] = { {"PNP0103" ,0 }, {"" ,0 }, };MODULE_DEVICE_TABLE (acpi, hpet_device_ids); -static struct acpi_driver hpet_acpi_driver = { +static struct pnp_driver hpet_pnp_driver = { .name ="hpet" , - .ids = hpet_device_ids, - .ops = { - .add = hpet_acpi_add, - .remove = hpet_acpi_remove, - }, + .id_table = hpet_device_ids, + .probe = hpet_pnp_add, + .remove = hpet_pnp_remove, }; +#endif static struct miscdevice hpet_misc = {HPET_MINOR ,"hpet" , &hpet_fops };
@@ -1007,26 +962,28 @@ static int __init hpet_init(void) sysctl_header =register_sysctl_table (dev_root); - result =acpi_bus_register_driver (&hpet_acpi_driver); +#ifdef CONFIG_PNP + result =pnp_register_driver (&hpet_pnp_driver);if (result <0 ) {if (sysctl_header)unregister_sysctl_table (sysctl_header);misc_deregister (&hpet_misc);return result; } +#endif return 0 ; } static void __exit hpet_exit(void) { -acpi_bus_unregister_driver (&hpet_acpi_driver); +#ifdef CONFIG_PNP +pnp_unregister_driver (&hpet_pnp_driver); +#endif if (sysctl_header)unregister_sysctl_table (sysctl_header);misc_deregister (&hpet_misc); - -return ; }module_init (hpet_init);
Quoted 184 lines · Bjorn Helgaas
PNPACPI already parses
_CRS, and does a more complete job than we did here, so let's just take advantage of that.Signed-off-by Bjorn Helgaas <[email protected]>---
drivers/char/hpet.c | 109 +++++++++++++++------------------------------------
1 files changed, 33 insertions(+), 76 deletions(-)drivers/char/hpet.c +32
-74@@ -31,6 +31,7 @@ #include <linux/seq_file.h> #include <linux/bitops.h> #include <linux/clocksource.h> +#include <linux/pnp.h> #include <asm/current.h> #include <asm/uaccess.h>@@ -40,7 +41,6 @@ #include <asm/div64.h> #include <linux/acpi.h> -#include <acpi/acpi_bus.h> #include <linux/hpet.h> /*@@ -899,101 +899,56 @@ int hpet_alloc(struct hpet_data *hdp) return 0; } -static acpi_status hpet_resources (struct acpi_resource *res,void *data) +#ifdef CONFIG_PNP +static int hpet_pnp_add (struct pnp_dev *dev,const struct pnp_device_id *dev_id) { - struct hpet_data *hdp; - acpi_status status; - struct acpi_resource_address64 addr; - - hdp = data; - - status = acpi_resource_to_address64(res, &addr); - - if (ACPI_SUCCESS(status)) { - hdp->hd_phys_address = addr.minimum; - hdp->hd_address = ioremap(addr.minimum, addr.address_length); - - if (hpet_is_known(hdp)) { - iounmap(hdp->hd_address); - return AE_ALREADY_EXISTS; - } - } else if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { - struct acpi_resource_fixed_memory32 *fixmem32; - - fixmem32 = &res->data.fixed_memory32; - if (!fixmem32) - return AE_NO_MEMORY; - - hdp->hd_phys_address = fixmem32->address; - hdp->hd_address = ioremap(fixmem32->address, - HPET_RANGE_SIZE); - - if (hpet_is_known(hdp)) { - iounmap(hdp->hd_address); - return AE_ALREADY_EXISTS; - } - } else if (res->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) { - struct acpi_resource_extended_irq *irqp; - int i, irq; - - irqp = &res->data.extended_irq; - - for (i = 0; i < irqp->interrupt_count; i++) { - irq = acpi_register_gsi(NULL, irqp->interrupts[i], - irqp->triggering, irqp->polarity); - if (irq < 0) - return AE_ERROR; - - hdp->hd_irq[hdp->hd_nirqs] = irq; - hdp->hd_nirqs++; - } - } - - return AE_OK; -} - -static int hpet_acpi_add (struct acpi_device *device) -{ - acpi_status result; struct hpet_data data; + struct resource *mem, *irq; + int i; memset(&data, 0, sizeof(data)); - result = - acpi_walk_resources(device->handle, METHOD_NAME__CRS, - hpet_resources, &data); - - if (ACPI_FAILURE(result)) + mem = pnp_get_resource(dev, IORESOURCE_MEM, 0); + if (!mem) return -ENODEV; - if (!data.hd_address || !data.hd_nirqs) { - printk("%s: no address or irqs in _CRS\n", __func__); + data.hd_phys_address = mem->start; + + if (hpet_is_known(&data)) return -ENODEV; + + i = 0; + while (data.hd_nirqs < ARRAY_SIZE(data.hd_irq)) { + irq = pnp_get_resource(dev, IORESOURCE_IRQ, i++); + if (pnp_resource_valid(irq) && pnp_resource_enabled(irq)) + data.hd_irq[data.hd_nirqs++] = irq->start; } + if (!data.hd_nirqs) + return -ENODEV; + + data.hd_address = ioremap(mem->start, resource_size(mem)); return hpet_alloc(&data); } -static int hpet_acpi_remove (struct acpi_device *device,int type) +static void hpet_pnp_remove (struct pnp_dev *dev) { /* XXX need to unregister clocksource, dealloc mem, etc */ - return -EINVAL; } -static const struct acpi_device_id hpet_device_ids[] = { +static const struct pnp_device_id hpet_device_ids[] = { {"PNP0103", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, hpet_device_ids); -static struct acpi_driver hpet_acpi_driver = { +static struct pnp_driver hpet_pnp_driver = { .name = "hpet", - .ids = hpet_device_ids, - .ops = { - .add = hpet_acpi_add, - .remove = hpet_acpi_remove, - }, + .id_table = hpet_device_ids, + .probe = hpet_pnp_add, + .remove = hpet_pnp_remove, }; +#endif static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops };@@ -1007,26 +962,28 @@ static int __init hpet_init(void) sysctl_header = register_sysctl_table(dev_root); - result = acpi_bus_register_driver(&hpet_acpi_driver); +#ifdef CONFIG_PNP + result = pnp_register_driver(&hpet_pnp_driver); if (result < 0) { if (sysctl_header) unregister_sysctl_table(sysctl_header); misc_deregister(&hpet_misc); return result; } +#endif return 0; } static void __exit hpet_exit(void) { - acpi_bus_unregister_driver(&hpet_acpi_driver); +#ifdef CONFIG_PNP + pnp_unregister_driver(&hpet_pnp_driver);
drivers/char/hpet.c static int __init hpet_init(void) · line 989
Quoted 10 lines
drivers/char/hpet.c +1
-2+#endif if (sysctl_header) unregister_sysctl_table(sysctl_header); misc_deregister(&hpet_misc); - - return; } module_init(hpet_init);
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 2/4 hpet: pass physical address, not entire hpet_data, to hpet_is_known()
In reply to Bjorn HelgaasNo functional change; hpet_is_known() only needs the physical address, so supplying that instead of the whole struct hpet_data makes the callers a little simpler.
---
drivers/char/hpet.c | 14 +++++--------- 1 files changed, 5 insertions(+), 9 deletions(-)
drivers/char/hpet.c +5 -9
@@ -662,12 +662,12 @@ static const struct file_operations hpet_fops = { .mmap = hpet_mmap, }; -static int hpet_is_known (struct hpet_data *hdp) +static int hpet_is_known (unsigned long phys_address) {struct hpets *hpetp;for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) -if (hpetp->hp_hpet_phys == hdp->hd_phys_address) +if (hpetp->hp_hpet_phys == phys_address)return 1 ;return 0 ;
@@ -788,7 +788,7 @@ int hpet_alloc(struct hpet_data *hdp)* If platform dependent code has allocated the hpet that * ACPI has also reported, then we catch it here. */ -if (hpet_is_known (hdp)) { +if (hpet_is_known (hdp->hd_phys_address)) {printk (KERN_DEBUG "%s: duplicate HPET ignored\n" , __func__);return 0 ;
@@ -909,12 +909,7 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id)memset (&data,0 ,sizeof (data)); mem =pnp_get_resource (dev,IORESOURCE_MEM ,0 ); -if (!mem) -return -ENODEV ; - - data.hd_phys_address = mem->start; - -if (hpet_is_known (&data)) +if (!mem ||hpet_is_known (mem->start))return -ENODEV ; i =0 ;
@@ -926,6 +921,7 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id)if (!data.hd_nirqs)return -ENODEV ; + data.hd_phys_address = mem->start; data.hd_address =ioremap (mem->start,resource_size (mem));return hpet_alloc (&data);
Re: [PATCH v2 2/4] hpet: pass physical address, not entire hpet_data, to hpet_is_known()
Quoted 58 lines · Bjorn Helgaas
No functional change;
hpet_is_known()only needs the physical address, so supplying that instead of the whole structhpet_datamakes the callers a little simpler.Signed-off-by Bjorn Helgaas <[email protected]>Acked-by Clemens Ladisch <[email protected]>---
drivers/char/hpet.c | 14 +++++---------
1 files changed, 5 insertions(+), 9 deletions(-)drivers/char/hpet.c +4
-9@@ -662,12 +662,12 @@ static const struct file_operations hpet_fops = { .mmap = hpet_mmap, }; -static int hpet_is_known (struct hpet_data *hdp) +static int hpet_is_known (unsigned long phys_address) { struct hpets *hpetp; for (hpetp = hpets; hpetp; hpetp = hpetp->hp_next) - if (hpetp->hp_hpet_phys == hdp->hd_phys_address) + if (hpetp->hp_hpet_phys == phys_address) return 1; return 0;@@ -788,7 +788,7 @@ int hpet_alloc(struct hpet_data *hdp)* If platform dependent code has allocated the hpet that * ACPI has also reported, then we catch it here. */ - if (hpet_is_known(hdp)) { + if (hpet_is_known(hdp->hd_phys_address)) { printk(KERN_DEBUG "%s: duplicate HPET ignored\n", __func__); return 0;@@ -909,12 +909,7 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) memset(&data, 0, sizeof(data)); mem = pnp_get_resource(dev, IORESOURCE_MEM, 0); - if (!mem) - return -ENODEV; - - data.hd_phys_address = mem->start; - - if (hpet_is_known(&data)) + if (!mem || hpet_is_known(mem->start)) return -ENODEV; i = 0;
drivers/char/hpet.c static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) · line 927
Quoted 7 lines
drivers/char/hpet.c +1
-0@@ -926,6 +921,7 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) if (!data.hd_nirqs) return -ENODEV; + data.hd_phys_address = mem->start; data.hd_address = ioremap(mem->start, resource_size(mem)); return hpet_alloc(&data);
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 3/4 hpet: clean up io mapping when hpet_alloc() fails
In reply to Bjorn HelgaasWhen hpet_alloc() fails, we should iounmap() the timer so we don't leak the mapping.
---
drivers/char/hpet.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-)
drivers/char/hpet.c +6 -2
@@ -904,7 +904,7 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) {struct hpet_data data;struct resource *mem, *irq; -int i; +int i, ret;memset (&data,0 ,sizeof (data));
@@ -924,7 +924,11 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) data.hd_phys_address = mem->start; data.hd_address =ioremap (mem->start,resource_size (mem)); -return hpet_alloc (&data); + ret =hpet_alloc (&data); +if (ret) +iounmap (data.hd_address); + +return ret; }static void hpet_pnp_remove (struct pnp_dev *dev)
Re: [PATCH v2 3/4] hpet: clean up io mapping when hpet_alloc() fails
Quoted 29 lines · Bjorn Helgaas
When
hpet_alloc()fails, we shouldiounmap()the timer so we don't leak the mapping.Signed-off-by Bjorn Helgaas <[email protected]>---
drivers/char/hpet.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)drivers/char/hpet.c +1
-1@@ -904,7 +904,7 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) { struct hpet_data data; struct resource *mem, *irq; - int i; + int i, ret; memset(&data, 0, sizeof(data));@@ -924,7 +924,11 @@ static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) data.hd_phys_address = mem->start; data.hd_address = ioremap(mem->start, resource_size(mem));
drivers/char/hpet.c static int hpet_pnp_add(struct pnp_dev *dev, const struct pnp_device_id *dev_id) · line 934
Quoted 10 lines
drivers/char/hpet.c +5
-1- return hpet_alloc(&data); + ret = hpet_alloc(&data); + if (ret) + iounmap(data.hd_address); + + return ret; } static void hpet_pnp_remove(struct pnp_dev *dev)
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v2 4/4 MAINTAINERS: remove obsolete HPET ACPI entry
In reply to Bjorn HelgaasBob Picco is no longer at HP.
---
MAINTAINERS | 5 ----- 1 files changed, 0 insertions(+), 5 deletions(-)
MAINTAINERS +0 -5
@@ -2664,11 +2664,6 @@ HPET: x86_64 M: Vojtech Pavlik <[email protected]> S: Maintained -HPET: ACPI -M: Bob Picco <[email protected]> -S: Maintained -F: drivers/char/hpet.c - HPFS FILESYSTEM M: Mikulas Patocka <[email protected]> W: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
Clemens Ladisch
maintainerQuoted 1 line · Bjorn Helgaas
Clemens, if you like these,
Yes.
Quoted 2 lines
will you take care of merging them, or do I need to shepherd them through some other path?
I don't have a tree for this; HPET patches are usually picked up by akpm.
Regards,
Clemens
Andrew, did you see these? Can you put them in -mm or whatever your normal path for HPET patches is?
Thanks,
Bjorn
Quoted 14 lines · Clemens Ladisch
Quoted 1 line · Bjorn Helgaas
Clemens, if you like these,
Yes.
Quoted 2 lines
will you take care of merging them, or do I need to shepherd them through some other path?
I don't have a tree for this; HPET patches are usually picked up by akpm.
Regards,
Clemens