* A GPE block driver @ 2004-11-06 6:44 Matthew Wilcox 2004-11-06 7:49 ` [ACPI] " Matthew Wilcox 0 siblings, 1 reply; 6+ messages in thread From: Matthew Wilcox @ 2004-11-06 6:44 UTC (permalink / raw) To: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f I have a GPE block driver (PNP ID ACPI0006) almost written. I have a couple of questions though ... 1. Given an acpi_device, how do I get an acpi_namespace_node? 2. Where does gpe_block_base_number come from? Is that the _UID? -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ------------------------------------------------------- This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [ACPI] A GPE block driver 2004-11-06 6:44 A GPE block driver Matthew Wilcox @ 2004-11-06 7:49 ` Matthew Wilcox 2004-11-07 14:43 ` Matthew Wilcox 0 siblings, 1 reply; 6+ messages in thread From: Matthew Wilcox @ 2004-11-06 7:49 UTC (permalink / raw) To: Matthew Wilcox; +Cc: acpi-devel, linux-ia64 On Sat, Nov 06, 2004 at 06:44:42AM +0000, Matthew Wilcox wrote: > I have a GPE block driver (PNP ID ACPI0006) almost written. I have > a couple of questions though ... > > 1. Given an acpi_device, how do I get an acpi_namespace_node? > 2. Where does gpe_block_base_number come from? Is that the _UID? Never mind. I was using the wrong interface. Here's the driver. I can't actually test it until someone goes into the server room to push a button on the machine. I do suspect there to be a problem though. I get the message: GSI 120 (level, low) -> CPU 3 (0x0c02) vector 63 but there is no entry in /proc/interrupts for vector 63. I think the right thing to do would be to add a request_irq() somewhere in the acpi_install_gpe_block() call path. FADT GPE blocks don't need this -- they use the sci_irq. But other blocks can use their own IRQ. Index: linux-2.6/drivers/acpi/Kconfig =================================================================== RCS file: /var/cvs/linux-2.6/drivers/acpi/Kconfig,v retrieving revision 1.13 diff -u -p -r1.13 Kconfig --- linux-2.6/drivers/acpi/Kconfig 11 Oct 2004 21:41:01 -0000 1.13 +++ linux-2.6/drivers/acpi/Kconfig 6 Nov 2004 07:39:03 -0000 @@ -119,6 +119,15 @@ config ACPI_FAN This driver adds support for ACPI fan devices, allowing user-mode applications to perform basic fan control (on, off, status). +config ACPI_GPE_BLOCK + tristate "GPE block" + depends on ACPI_INTERPRETER + depends on !IA64_SGI_SN + default m + help + GPE block devices are used to increase the number of interrupts + available on larger machines. + config ACPI_PROCESSOR tristate "Processor" depends on ACPI_INTERPRETER Index: linux-2.6/drivers/acpi/Makefile =================================================================== RCS file: /var/cvs/linux-2.6/drivers/acpi/Makefile,v retrieving revision 1.4 diff -u -p -r1.4 Makefile --- linux-2.6/drivers/acpi/Makefile 13 Sep 2004 15:22:51 -0000 1.4 +++ linux-2.6/drivers/acpi/Makefile 6 Nov 2004 07:39:03 -0000 @@ -38,6 +38,7 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_EC) += ec.o obj-$(CONFIG_ACPI_FAN) += fan.o +obj-$(CONFIG_ACPI_GPE_BLOCK) += gpe-block.o obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o Index: linux-2.6/drivers/acpi/gpe-block.c =================================================================== RCS file: linux-2.6/drivers/acpi/gpe-block.c diff -N linux-2.6/drivers/acpi/gpe-block.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux-2.6/drivers/acpi/gpe-block.c 6 Nov 2004 07:39:03 -0000 @@ -0,0 +1,110 @@ +/* + * drivers/acpi/gpe-block.c + * + * Copyright (c) Matthew Wilcox for Hewlett Packard 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/module.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> +#include <acpi/acevents.h> + +MODULE_AUTHOR("Matthew Wilcox <willy@hp.com>"); +MODULE_LICENSE("GPL"); + +struct gpe_block { + struct acpi_generic_address address; + u32 register_count; + u8 gpe_block_base_number; + u32 interrupt_level; +}; + +static acpi_status acpi_gpe_block_crs_irq(struct acpi_resource_ext_irq *irq, + struct gpe_block *data) +{ + data->interrupt_level = acpi_register_gsi(irq->interrupts[0], + irq->edge_level, irq->active_high_low); + return AE_OK; +} + +static acpi_status acpi_gpe_block_crs_addr(struct acpi_resource_address64 *addr, + struct gpe_block *data) +{ + if (addr->resource_type == ACPI_MEMORY_RANGE) { + data->address.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; + } else if (addr->resource_type == ACPI_IO_RANGE) { + data->address.address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; + } else { + return AE_CTRL_TERMINATE; + } + + data->address.register_bit_width = ACPI_GPE_REGISTER_WIDTH; + data->address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH; + data->address.address = addr->min_address_range; + data->register_count = (addr->max_address_range - addr->min_address_range) / (ACPI_GPE_REGISTER_WIDTH * 2); + + return AE_OK; +} + +static acpi_status acpi_gpe_block_crs_add(struct acpi_resource *res, void *data) +{ + if (res->id == ACPI_RSTYPE_EXT_IRQ) + return acpi_gpe_block_crs_irq(&res->data.extended_irq, data); + + if (res->id == ACPI_RSTYPE_ADDRESS16 || + res->id == ACPI_RSTYPE_ADDRESS32 || + res->id == ACPI_RSTYPE_ADDRESS64) { + struct acpi_resource_address64 address; + acpi_resource_to_address64(res, &address); + return acpi_gpe_block_crs_addr(&address, data); + } + + return AE_OK; +} + +static int acpi_gpe_block_add(struct acpi_device *device) +{ + struct gpe_block block; + + block.register_count = 0; + acpi_walk_resources(device->handle, METHOD_NAME__CRS, + acpi_gpe_block_crs_add, &block); + if (block.register_count == 0) + return 0; + + return acpi_install_gpe_block(device->handle, &block.address, + block.register_count, block.interrupt_level); +} + +static int acpi_gpe_block_remove(struct acpi_device *device, int type) +{ + return acpi_remove_gpe_block(device->handle); +} + +static struct acpi_driver acpi_gpe_block_driver = { + .name = "gpe-block", + .ids = "ACPI0006", + .ops = { + .add = acpi_gpe_block_add, + .remove = acpi_gpe_block_remove, + }, +}; + +static int __init acpi_gpe_block_init(void) +{ + int result = acpi_bus_register_driver(&acpi_gpe_block_driver); + return (result < 0) ? -ENODEV : 0; +} + +static void __exit acpi_gpe_block_exit(void) +{ + acpi_bus_unregister_driver(&acpi_gpe_block_driver); +} + +module_init(acpi_gpe_block_init); +module_exit(acpi_gpe_block_exit); -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [ACPI] A GPE block driver 2004-11-06 7:49 ` [ACPI] " Matthew Wilcox @ 2004-11-07 14:43 ` Matthew Wilcox 2004-11-07 14:47 ` [PATCH] Teach OSL to handle multiple interrupts [1/2] Matthew Wilcox 2004-11-07 14:50 ` [PATCH] GPE block driver [2/2] Matthew Wilcox 0 siblings, 2 replies; 6+ messages in thread From: Matthew Wilcox @ 2004-11-07 14:43 UTC (permalink / raw) To: Matthew Wilcox; +Cc: acpi-devel, linux-ia64 On Sat, Nov 06, 2004 at 07:49:00AM +0000, Matthew Wilcox wrote: > Here's the driver. I can't actually test it until someone goes into > the server room to push a button on the machine. > > I do suspect there to be a problem though. I get the message: > GSI 120 (level, low) -> CPU 3 (0x0c02) vector 63 > but there is no entry in /proc/interrupts for vector 63. I think the > right thing to do would be to add a request_irq() somewhere in the > acpi_install_gpe_block() call path. FADT GPE blocks don't need this -- > they use the sci_irq. But other blocks can use their own IRQ. OK, the problem was more detailed and subtle than that. osl.c assumes there will be only one interrupt, which is not true in the presence of GPE blocks. So I rewrote the interrupt handler. I'll send two follow-up mails to this; the first will be the changes I propose for the ACPI core and the second will be the new GPE block driver which has several bugs fixed over the one I posted yesterday. -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] Teach OSL to handle multiple interrupts [1/2] 2004-11-07 14:43 ` Matthew Wilcox @ 2004-11-07 14:47 ` Matthew Wilcox [not found] ` <20041107144754.GD23303-+pPCBgu9SkPzIGdyhVEDUDl5KyyQGfY2kSSpQ9I8OhVaa/9Udqfwiw@public.gmane.org> 2004-11-07 14:50 ` [PATCH] GPE block driver [2/2] Matthew Wilcox 1 sibling, 1 reply; 6+ messages in thread From: Matthew Wilcox @ 2004-11-07 14:47 UTC (permalink / raw) To: Matthew Wilcox; +Cc: acpi-devel, linux-ia64 OSL assumed that there would only be one ACPI IRQ. In the presence of GPE blocks, there are multiple ACPI IRQs. Index: linux-2.6/drivers/acpi/osl.c =================================================================== RCS file: /var/cvs/linux-2.6/drivers/acpi/osl.c,v retrieving revision 1.13 diff -u -p -r1.13 osl.c --- linux-2.6/drivers/acpi/osl.c 11 Oct 2004 21:41:01 -0000 1.13 +++ linux-2.6/drivers/acpi/osl.c 7 Nov 2004 14:34:33 -0000 @@ -66,9 +66,6 @@ int acpi_in_debugger; extern char line_buf[80]; #endif /*ENABLE_DEBUGGER*/ -static unsigned int acpi_irq_irq; -static acpi_osd_handler acpi_irq_handler; -static void *acpi_irq_context; static struct workqueue_struct *kacpid_wq; acpi_status @@ -96,13 +93,12 @@ acpi_os_initialize1(void) return AE_OK; } +static void acpi_os_remove_interrupt_handlers(void); + acpi_status acpi_os_terminate(void) { - if (acpi_irq_handler) { - acpi_os_remove_interrupt_handler(acpi_irq_irq, - acpi_irq_handler); - } + acpi_os_remove_interrupt_handlers(); destroy_workqueue(kacpid_wq); @@ -255,52 +251,129 @@ acpi_os_table_override (struct acpi_tabl return AE_OK; } +struct acpi_dev_id { + acpi_osd_handler handler; + void *context; + int irq; + struct acpi_dev_id *next; +}; + static irqreturn_t acpi_irq(int irq, void *dev_id, struct pt_regs *regs) { - return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; + struct acpi_dev_id *irq_ctx = dev_id; + acpi_osd_handler handler = irq_ctx->handler; + void *context = irq_ctx->context; + return (*handler)(context) ? IRQ_HANDLED : IRQ_NONE; +} + +struct acpi_dev_id *dev_id_list; + +static void *alloc_dev_id(acpi_osd_handler handler, void *context, int irq) +{ + struct acpi_dev_id *irq_ctx = kmalloc(sizeof(*irq_ctx), GFP_KERNEL); + irq_ctx->handler = handler; + irq_ctx->context = context; + irq_ctx->irq = irq; + irq_ctx->next = dev_id_list; + dev_id_list = irq_ctx; + return irq_ctx; +} + +/* + * XXX: Ideally, we would match the context too, but that information + * isn't passed to the acpi_os_remove_interrupt_handler() function. + */ +static void *find_dev_id(int irq, acpi_osd_handler handler) +{ + struct acpi_dev_id *irq_ctx = dev_id_list; + for (irq_ctx = dev_id_list; irq_ctx; irq_ctx = irq_ctx->next) { + if ((irq_ctx->handler == handler) && (irq_ctx->irq == irq)) + return irq_ctx; + } + printk("find_dev_id: handler %p for irq %d not found\n", handler, irq); + return NULL; +} + +static void free_dev_id(struct acpi_dev_id *dev_id) +{ + struct acpi_dev_id **pprev = &dev_id_list; + for (;;) { + struct acpi_dev_id *irq_ctx = *pprev; + if (!irq_ctx) + break; + if (irq_ctx != dev_id) { + pprev = &irq_ctx->next; + continue; + } + + *pprev = irq_ctx->next; + kfree(irq_ctx); + return; + } + printk("free_dev_id: dev_id %p not found\n", dev_id); } acpi_status acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context) { unsigned int irq; + void *dev_id; /* - * Ignore the GSI from the core, and use the value in our copy of the - * FADT. It may not be the same if an interrupt source override exists - * for the SCI. + * If this is the FADT interrupt, ignore the GSI from the core and + * use the value in our copy of the FADT instead. It may not be the + * same if an interrupt source override exists for the SCI. */ - gsi = acpi_fadt.sci_int; + if (gsi == acpi_gbl_FADT->sci_int) + gsi = acpi_fadt.sci_int; + if (acpi_gsi_to_irq(gsi, &irq) < 0) { printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", gsi); return AE_OK; } - acpi_irq_handler = handler; - acpi_irq_context = context; - if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { + dev_id = alloc_dev_id(handler, context, irq); + if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", dev_id)) { printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); + free_dev_id(dev_id); return AE_NOT_ACQUIRED; } - acpi_irq_irq = irq; return AE_OK; } acpi_status -acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) +acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler) { - if (irq) { - free_irq(irq, acpi_irq); - acpi_irq_handler = NULL; - acpi_irq_irq = 0; + int irq; + void *dev_id; + + if (gsi == acpi_gbl_FADT->sci_int) + gsi = acpi_fadt.sci_int; + + if (acpi_gsi_to_irq(gsi, &irq) < 0) { + printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", + gsi); + return AE_OK; } + dev_id = find_dev_id(irq, handler); + free_irq(irq, dev_id); + free_dev_id(dev_id); + return AE_OK; } +static void acpi_os_remove_interrupt_handlers(void) +{ + while (dev_id_list) { + acpi_os_remove_interrupt_handler(dev_id_list->irq, + dev_id_list->handler); + } +} + /* * Running in interpreter thread context, safe to sleep */ -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 6+ messages in thread
[parent not found: <20041107144754.GD23303-+pPCBgu9SkPzIGdyhVEDUDl5KyyQGfY2kSSpQ9I8OhVaa/9Udqfwiw@public.gmane.org>]
* Re: [PATCH] Teach OSL to handle multiple interrupts [1/2] [not found] ` <20041107144754.GD23303-+pPCBgu9SkPzIGdyhVEDUDl5KyyQGfY2kSSpQ9I8OhVaa/9Udqfwiw@public.gmane.org> @ 2004-11-11 15:08 ` Matthew Wilcox 0 siblings, 0 replies; 6+ messages in thread From: Matthew Wilcox @ 2004-11-11 15:08 UTC (permalink / raw) To: Len Brown; +Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f Patches sent after this one have been applied. Is this patch still in review? On Sun, Nov 07, 2004 at 02:47:54PM +0000, Matthew Wilcox wrote: > > OSL assumed that there would only be one ACPI IRQ. In the presence of > GPE blocks, there are multiple ACPI IRQs. > > Index: linux-2.6/drivers/acpi/osl.c > =================================================================== > RCS file: /var/cvs/linux-2.6/drivers/acpi/osl.c,v > retrieving revision 1.13 > diff -u -p -r1.13 osl.c > --- linux-2.6/drivers/acpi/osl.c 11 Oct 2004 21:41:01 -0000 1.13 > +++ linux-2.6/drivers/acpi/osl.c 7 Nov 2004 14:34:33 -0000 > @@ -66,9 +66,6 @@ int acpi_in_debugger; > extern char line_buf[80]; > #endif /*ENABLE_DEBUGGER*/ > > -static unsigned int acpi_irq_irq; > -static acpi_osd_handler acpi_irq_handler; > -static void *acpi_irq_context; > static struct workqueue_struct *kacpid_wq; > > acpi_status > @@ -96,13 +93,12 @@ acpi_os_initialize1(void) > return AE_OK; > } > > +static void acpi_os_remove_interrupt_handlers(void); > + > acpi_status > acpi_os_terminate(void) > { > - if (acpi_irq_handler) { > - acpi_os_remove_interrupt_handler(acpi_irq_irq, > - acpi_irq_handler); > - } > + acpi_os_remove_interrupt_handlers(); > > destroy_workqueue(kacpid_wq); > > @@ -255,52 +251,129 @@ acpi_os_table_override (struct acpi_tabl > return AE_OK; > } > > +struct acpi_dev_id { > + acpi_osd_handler handler; > + void *context; > + int irq; > + struct acpi_dev_id *next; > +}; > + > static irqreturn_t > acpi_irq(int irq, void *dev_id, struct pt_regs *regs) > { > - return (*acpi_irq_handler)(acpi_irq_context) ? IRQ_HANDLED : IRQ_NONE; > + struct acpi_dev_id *irq_ctx = dev_id; > + acpi_osd_handler handler = irq_ctx->handler; > + void *context = irq_ctx->context; > + return (*handler)(context) ? IRQ_HANDLED : IRQ_NONE; > +} > + > +struct acpi_dev_id *dev_id_list; > + > +static void *alloc_dev_id(acpi_osd_handler handler, void *context, int irq) > +{ > + struct acpi_dev_id *irq_ctx = kmalloc(sizeof(*irq_ctx), GFP_KERNEL); > + irq_ctx->handler = handler; > + irq_ctx->context = context; > + irq_ctx->irq = irq; > + irq_ctx->next = dev_id_list; > + dev_id_list = irq_ctx; > + return irq_ctx; > +} > + > +/* > + * XXX: Ideally, we would match the context too, but that information > + * isn't passed to the acpi_os_remove_interrupt_handler() function. > + */ > +static void *find_dev_id(int irq, acpi_osd_handler handler) > +{ > + struct acpi_dev_id *irq_ctx = dev_id_list; > + for (irq_ctx = dev_id_list; irq_ctx; irq_ctx = irq_ctx->next) { > + if ((irq_ctx->handler == handler) && (irq_ctx->irq == irq)) > + return irq_ctx; > + } > + printk("find_dev_id: handler %p for irq %d not found\n", handler, irq); > + return NULL; > +} > + > +static void free_dev_id(struct acpi_dev_id *dev_id) > +{ > + struct acpi_dev_id **pprev = &dev_id_list; > + for (;;) { > + struct acpi_dev_id *irq_ctx = *pprev; > + if (!irq_ctx) > + break; > + if (irq_ctx != dev_id) { > + pprev = &irq_ctx->next; > + continue; > + } > + > + *pprev = irq_ctx->next; > + kfree(irq_ctx); > + return; > + } > + printk("free_dev_id: dev_id %p not found\n", dev_id); > } > > acpi_status > acpi_os_install_interrupt_handler(u32 gsi, acpi_osd_handler handler, void *context) > { > unsigned int irq; > + void *dev_id; > > /* > - * Ignore the GSI from the core, and use the value in our copy of the > - * FADT. It may not be the same if an interrupt source override exists > - * for the SCI. > + * If this is the FADT interrupt, ignore the GSI from the core and > + * use the value in our copy of the FADT instead. It may not be the > + * same if an interrupt source override exists for the SCI. > */ > - gsi = acpi_fadt.sci_int; > + if (gsi == acpi_gbl_FADT->sci_int) > + gsi = acpi_fadt.sci_int; > + > if (acpi_gsi_to_irq(gsi, &irq) < 0) { > printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", > gsi); > return AE_OK; > } > > - acpi_irq_handler = handler; > - acpi_irq_context = context; > - if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", acpi_irq)) { > + dev_id = alloc_dev_id(handler, context, irq); > + if (request_irq(irq, acpi_irq, SA_SHIRQ, "acpi", dev_id)) { > printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq); > + free_dev_id(dev_id); > return AE_NOT_ACQUIRED; > } > - acpi_irq_irq = irq; > > return AE_OK; > } > > acpi_status > -acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler) > +acpi_os_remove_interrupt_handler(u32 gsi, acpi_osd_handler handler) > { > - if (irq) { > - free_irq(irq, acpi_irq); > - acpi_irq_handler = NULL; > - acpi_irq_irq = 0; > + int irq; > + void *dev_id; > + > + if (gsi == acpi_gbl_FADT->sci_int) > + gsi = acpi_fadt.sci_int; > + > + if (acpi_gsi_to_irq(gsi, &irq) < 0) { > + printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n", > + gsi); > + return AE_OK; > } > > + dev_id = find_dev_id(irq, handler); > + free_irq(irq, dev_id); > + free_dev_id(dev_id); > + > return AE_OK; > } > > +static void acpi_os_remove_interrupt_handlers(void) > +{ > + while (dev_id_list) { > + acpi_os_remove_interrupt_handler(dev_id_list->irq, > + dev_id_list->handler); > + } > +} > + > /* > * Running in interpreter thread context, safe to sleep > */ > > -- > "Next the statesmen will invent cheap lies, putting the blame upon > the nation that is attacked, and every man will be glad of those > conscience-soothing falsities, and will diligently study them, and refuse > to examine any refutations of them; and thus he will by and by convince > himself that the war is just, and will thank God for the better sleep > he enjoys after this process of grotesque self-deception." -- Mark Twain -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ------------------------------------------------------- This SF.Net email is sponsored by: Sybase ASE Linux Express Edition - download now for FREE LinuxWorld Reader's Choice Award Winner for best database on Linux. http://ads.osdn.com/?ad_id=5588&alloc_id=12065&op=click ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] GPE block driver [2/2] 2004-11-07 14:43 ` Matthew Wilcox 2004-11-07 14:47 ` [PATCH] Teach OSL to handle multiple interrupts [1/2] Matthew Wilcox @ 2004-11-07 14:50 ` Matthew Wilcox 1 sibling, 0 replies; 6+ messages in thread From: Matthew Wilcox @ 2004-11-07 14:50 UTC (permalink / raw) To: Matthew Wilcox; +Cc: acpi-devel, linux-ia64 GPE blocks are used to extend the number of events that ACPI can handle, particularly on larger machines. Index: linux-2.6/drivers/acpi/Kconfig =================================================================== RCS file: /var/cvs/linux-2.6/drivers/acpi/Kconfig,v retrieving revision 1.13 diff -u -p -r1.13 Kconfig --- linux-2.6/drivers/acpi/Kconfig 11 Oct 2004 21:41:01 -0000 1.13 +++ linux-2.6/drivers/acpi/Kconfig 7 Nov 2004 14:34:33 -0000 @@ -119,6 +119,15 @@ config ACPI_FAN This driver adds support for ACPI fan devices, allowing user-mode applications to perform basic fan control (on, off, status). +config ACPI_GPE_BLOCK + tristate "GPE block" + depends on ACPI_INTERPRETER + depends on !IA64_SGI_SN + default m + help + GPE block devices are used to increase the number of interrupts + available on larger machines. + config ACPI_PROCESSOR tristate "Processor" depends on ACPI_INTERPRETER Index: linux-2.6/drivers/acpi/Makefile =================================================================== RCS file: /var/cvs/linux-2.6/drivers/acpi/Makefile,v retrieving revision 1.4 diff -u -p -r1.4 Makefile --- linux-2.6/drivers/acpi/Makefile 13 Sep 2004 15:22:51 -0000 1.4 +++ linux-2.6/drivers/acpi/Makefile 7 Nov 2004 14:34:33 -0000 @@ -38,6 +38,7 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_BUTTON) += button.o obj-$(CONFIG_ACPI_EC) += ec.o obj-$(CONFIG_ACPI_FAN) += fan.o +obj-$(CONFIG_ACPI_GPE_BLOCK) += gpe-block.o obj-$(CONFIG_ACPI_PCI) += pci_root.o pci_link.o pci_irq.o pci_bind.o obj-$(CONFIG_ACPI_POWER) += power.o obj-$(CONFIG_ACPI_PROCESSOR) += processor.o Index: linux-2.6/drivers/acpi/gpe-block.c =================================================================== RCS file: linux-2.6/drivers/acpi/gpe-block.c diff -N linux-2.6/drivers/acpi/gpe-block.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ linux-2.6/drivers/acpi/gpe-block.c 7 Nov 2004 14:34:33 -0000 @@ -0,0 +1,155 @@ +/* + * drivers/acpi/gpe-block.c + * + * Copyright (c) Matthew Wilcox for Hewlett Packard 2004 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + */ + +#include <linux/acpi.h> +#include <linux/ioport.h> +#include <linux/module.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> +#include <acpi/acpixf.h> + +MODULE_AUTHOR("Matthew Wilcox <willy@hp.com>"); +MODULE_LICENSE("GPL"); +MODULE_VERSION("0.2"); + +#define NAME "gpe-block" + +struct gpe_block { + struct acpi_generic_address address; + u32 register_count; + u32 interrupt_level; +}; + +static acpi_status acpi_gpe_block_crs_irq(struct acpi_resource_ext_irq *irq, + struct gpe_block *data) +{ + acpi_register_gsi(irq->interrupts[0], irq->edge_level, + irq->active_high_low); + data->interrupt_level = irq->interrupts[0]; + return AE_OK; +} + +static acpi_status acpi_gpe_block_crs_addr(struct acpi_resource_address64 *addr, + struct gpe_block *data) +{ + int size = addr->max_address_range - addr->min_address_range + 1; + if (addr->resource_type == ACPI_MEMORY_RANGE) { + data->address.address_space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY; + if (!request_mem_region(addr->min_address_range, size, NAME)) + return AE_CTRL_TERMINATE; + + } else if (addr->resource_type == ACPI_IO_RANGE) { + data->address.address_space_id = ACPI_ADR_SPACE_SYSTEM_IO; + if (!request_region(addr->min_address_range, size, NAME)) + return AE_CTRL_TERMINATE; + } else { + return AE_CTRL_TERMINATE; + } + + data->address.register_bit_width = ACPI_GPE_REGISTER_WIDTH; + data->address.register_bit_offset = ACPI_GPE_REGISTER_WIDTH; + data->address.address = addr->min_address_range; + data->register_count = size / 2; + + return AE_OK; +} + +static acpi_status acpi_gpe_block_crs_add(struct acpi_resource *res, void *data) +{ + if (res->id == ACPI_RSTYPE_EXT_IRQ) + return acpi_gpe_block_crs_irq(&res->data.extended_irq, data); + + if (res->id == ACPI_RSTYPE_ADDRESS16 || + res->id == ACPI_RSTYPE_ADDRESS32 || + res->id == ACPI_RSTYPE_ADDRESS64) { + struct acpi_resource_address64 address; + acpi_resource_to_address64(res, &address); + return acpi_gpe_block_crs_addr(&address, data); + } + + return AE_OK; +} + +static acpi_status acpi_gpe_block_crs_remove(struct acpi_resource *res, + void *context) +{ + struct acpi_resource_address64 addr; + int size; + int *fadt = context; + + *fadt = 0; + + if (res->id != ACPI_RSTYPE_ADDRESS16 && + res->id != ACPI_RSTYPE_ADDRESS32 && + res->id != ACPI_RSTYPE_ADDRESS64) + return AE_OK; + + acpi_resource_to_address64(res, &addr); + + size = addr.max_address_range - addr.min_address_range + 1; + if (addr.resource_type == ACPI_MEMORY_RANGE) { + release_mem_region(addr.min_address_range, size); + } else if (addr.resource_type == ACPI_IO_RANGE) { + release_region(addr.min_address_range, size); + } + return AE_OK; +} + +static int acpi_gpe_block_add(struct acpi_device *device) +{ + struct gpe_block block; + + block.register_count = 0; + acpi_walk_resources(device->handle, METHOD_NAME__CRS, + acpi_gpe_block_crs_add, &block); + if (block.register_count == 0) + return 0; + + acpi_install_gpe_block(device->handle, &block.address, + block.register_count, block.interrupt_level); + + return AE_OK; +} + +static int acpi_gpe_block_remove(struct acpi_device *device, int type) +{ + int fadt = 1; + + acpi_walk_resources(device->handle, METHOD_NAME__CRS, + acpi_gpe_block_crs_remove, &fadt); + if (fadt) + return AE_OK; + + return acpi_remove_gpe_block(device->handle); +} + +static struct acpi_driver acpi_gpe_block_driver = { + .name = NAME, + .ids = "ACPI0006", + .ops = { + .add = acpi_gpe_block_add, + .remove = acpi_gpe_block_remove, + }, +}; + +static int __init acpi_gpe_block_init(void) +{ + int result = acpi_bus_register_driver(&acpi_gpe_block_driver); + return (result < 0) ? -ENODEV : 0; +} + +static void __exit acpi_gpe_block_exit(void) +{ + acpi_bus_unregister_driver(&acpi_gpe_block_driver); +} + +module_init(acpi_gpe_block_init); +module_exit(acpi_gpe_block_exit); -- "Next the statesmen will invent cheap lies, putting the blame upon the nation that is attacked, and every man will be glad of those conscience-soothing falsities, and will diligently study them, and refuse to examine any refutations of them; and thus he will by and by convince himself that the war is just, and will thank God for the better sleep he enjoys after this process of grotesque self-deception." -- Mark Twain ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-11-11 15:08 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-06 6:44 A GPE block driver Matthew Wilcox
2004-11-06 7:49 ` [ACPI] " Matthew Wilcox
2004-11-07 14:43 ` Matthew Wilcox
2004-11-07 14:47 ` [PATCH] Teach OSL to handle multiple interrupts [1/2] Matthew Wilcox
[not found] ` <20041107144754.GD23303-+pPCBgu9SkPzIGdyhVEDUDl5KyyQGfY2kSSpQ9I8OhVaa/9Udqfwiw@public.gmane.org>
2004-11-11 15:08 ` Matthew Wilcox
2004-11-07 14:50 ` [PATCH] GPE block driver [2/2] Matthew Wilcox
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox