X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Facpi%2Fpci_link.c;h=394ae89409c2bdee53ddaf0f5045787bba6e3401;hb=9dbeb8967262f2e6777441318780f224261ec410;hp=7f3e7e77e79436e9984c52a4d6c80345f3f3265d;hpb=e21c1ca3f98529921c829a792dfdbfc5a5dc393b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 7f3e7e7..394ae89 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -43,26 +43,33 @@ #include #include -#define _COMPONENT ACPI_PCI_COMPONENT -ACPI_MODULE_NAME("pci_link") +#define PREFIX "ACPI: " + +#define _COMPONENT ACPI_PCI_COMPONENT +ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" -#define ACPI_PCI_LINK_HID "PNP0C0F" -#define ACPI_PCI_LINK_DRIVER_NAME "ACPI PCI Interrupt Link Driver" #define ACPI_PCI_LINK_DEVICE_NAME "PCI Interrupt Link" #define ACPI_PCI_LINK_FILE_INFO "info" #define ACPI_PCI_LINK_FILE_STATUS "state" -#define ACPI_PCI_LINK_MAX_POSSIBLE 16 +#define ACPI_PCI_LINK_MAX_POSSIBLE 16 + static int acpi_pci_link_add(struct acpi_device *device); static int acpi_pci_link_remove(struct acpi_device *device, int type); +static struct acpi_device_id link_device_ids[] = { + {"PNP0C0F", 0}, + {"", 0}, +}; +MODULE_DEVICE_TABLE(acpi, link_device_ids); + static struct acpi_driver acpi_pci_link_driver = { - .name = ACPI_PCI_LINK_DRIVER_NAME, + .name = "pci_link", .class = ACPI_PCI_LINK_CLASS, - .ids = ACPI_PCI_LINK_HID, + .ids = link_device_ids, .ops = { .add = acpi_pci_link_add, .remove = acpi_pci_link_remove, - }, + }, }; /* @@ -72,7 +79,7 @@ static struct acpi_driver acpi_pci_link_driver = { struct acpi_pci_link_irq { u8 active; /* Current IRQ */ u8 triggering; /* All IRQs */ - u8 polarity; /* All IRQs */ + u8 polarity; /* All IRQs */ u8 resource_type; u8 possible_count; u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; @@ -81,17 +88,14 @@ struct acpi_pci_link_irq { }; struct acpi_pci_link { - struct list_head node; - struct acpi_device *device; - struct acpi_pci_link_irq irq; - int refcnt; + struct list_head list; + struct acpi_device *device; + struct acpi_pci_link_irq irq; + int refcnt; }; -static struct { - int count; - struct list_head entries; -} acpi_link; -DEFINE_MUTEX(acpi_link_lock); +static LIST_HEAD(acpi_link_list); +static DEFINE_MUTEX(acpi_link_lock); /* -------------------------------------------------------------------------- PCI Link Device Management @@ -100,29 +104,31 @@ DEFINE_MUTEX(acpi_link_lock); /* * set context (link) possible list from resource list */ -static acpi_status -acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) +static acpi_status acpi_pci_link_check_possible(struct acpi_resource *resource, + void *context) { - struct acpi_pci_link *link = (struct acpi_pci_link *)context; - u32 i = 0; - + struct acpi_pci_link *link = context; + u32 i; switch (resource->type) { case ACPI_RESOURCE_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_TYPE_END_TAG: return AE_OK; case ACPI_RESOURCE_TYPE_IRQ: { struct acpi_resource_irq *p = &resource->data.irq; if (!p || !p->interrupt_count) { - printk(KERN_WARNING PREFIX "Blank IRQ resource\n"); + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Blank _PRS IRQ resource\n")); return AE_OK; } for (i = 0; (i < p->interrupt_count && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { if (!p->interrupts[i]) { - printk(KERN_WARNING PREFIX "Invalid IRQ %d\n", - p->interrupts[i]); + printk(KERN_WARNING PREFIX + "Invalid _PRS IRQ %d\n", + p->interrupts[i]); continue; } link->irq.possible[i] = p->interrupts[i]; @@ -139,15 +145,16 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) &resource->data.extended_irq; if (!p || !p->interrupt_count) { printk(KERN_WARNING PREFIX - "Blank EXT IRQ resource\n"); + "Blank _PRS EXT IRQ resource\n"); return AE_OK; } for (i = 0; (i < p->interrupt_count && i < ACPI_PCI_LINK_MAX_POSSIBLE); i++) { if (!p->interrupts[i]) { - printk(KERN_WARNING PREFIX "Invalid IRQ %d\n", - p->interrupts[i]); + printk(KERN_WARNING PREFIX + "Invalid _PRS IRQ %d\n", + p->interrupts[i]); continue; } link->irq.possible[i] = p->interrupts[i]; @@ -159,7 +166,8 @@ acpi_pci_link_check_possible(struct acpi_resource *resource, void *context) break; } default: - printk(KERN_ERR PREFIX "Resource is not an IRQ entry\n"); + printk(KERN_ERR PREFIX "_PRS resource type 0x%x isn't an IRQ\n", + resource->type); return AE_OK; } @@ -170,10 +178,6 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) { acpi_status status; - - if (!link) - return -EINVAL; - status = acpi_walk_resources(link->device->handle, METHOD_NAME__PRS, acpi_pci_link_check_possible, link); if (ACPI_FAILURE(status)) { @@ -188,13 +192,15 @@ static int acpi_pci_link_get_possible(struct acpi_pci_link *link) return 0; } -static acpi_status -acpi_pci_link_check_current(struct acpi_resource *resource, void *context) +static acpi_status acpi_pci_link_check_current(struct acpi_resource *resource, + void *context) { - int *irq = (int *)context; - + int *irq = context; switch (resource->type) { + case ACPI_RESOURCE_TYPE_START_DEPENDENT: + case ACPI_RESOURCE_TYPE_END_TAG: + return AE_OK; case ACPI_RESOURCE_TYPE_IRQ: { struct acpi_resource_irq *p = &resource->data.irq; @@ -204,7 +210,7 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) * particularly those those w/ _STA disabled */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Blank IRQ resource\n")); + "Blank _CRS IRQ resource\n")); return AE_OK; } *irq = p->interrupts[0]; @@ -220,7 +226,7 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) * return at least 1 IRQ */ printk(KERN_WARNING PREFIX - "Blank EXT IRQ resource\n"); + "Blank _CRS EXT IRQ resource\n"); return AE_OK; } *irq = p->interrupts[0]; @@ -228,10 +234,11 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) } break; default: - printk(KERN_ERR PREFIX "Resource %d isn't an IRQ\n", resource->type); - case ACPI_RESOURCE_TYPE_END_TAG: + printk(KERN_ERR PREFIX "_CRS resource type 0x%x isn't an IRQ\n", + resource->type); return AE_OK; } + return AE_CTRL_TERMINATE; } @@ -245,12 +252,9 @@ acpi_pci_link_check_current(struct acpi_resource *resource, void *context) static int acpi_pci_link_get_current(struct acpi_pci_link *link) { int result = 0; - acpi_status status = AE_OK; + acpi_status status; int irq = 0; - if (!link) - return -EINVAL; - link->irq.active = 0; /* in practice, status disabled is meaningless, ignore it */ @@ -295,23 +299,21 @@ static int acpi_pci_link_get_current(struct acpi_pci_link *link) static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) { - int result = 0; - acpi_status status = AE_OK; + int result; + acpi_status status; struct { struct acpi_resource res; struct acpi_resource end; } *resource; struct acpi_buffer buffer = { 0, NULL }; - - if (!link || !irq) + if (!irq) return -EINVAL; - resource = kmalloc(sizeof(*resource) + 1, GFP_ATOMIC); + resource = kzalloc(sizeof(*resource) + 1, irqs_disabled() ? GFP_ATOMIC: GFP_KERNEL); if (!resource) return -ENOMEM; - memset(resource, 0, sizeof(*resource) + 1); buffer.length = sizeof(*resource) + 1; buffer.pointer = resource; @@ -467,30 +469,22 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ - PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ - PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ - PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ - PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ + PIRQ_PENALTY_ISA_USED, /* IRQ12 mouse */ + PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ + PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ + PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ /* >IRQ15 */ }; int __init acpi_irq_penalty_init(void) { - struct list_head *node = NULL; - struct acpi_pci_link *link = NULL; - int i = 0; - + struct acpi_pci_link *link; + int i; /* * Update penalties to facilitate IRQ balancing. */ - list_for_each(node, &acpi_link.entries) { - - link = list_entry(node, struct acpi_pci_link, node); - if (!link) { - printk(KERN_ERR PREFIX "Invalid link context\n"); - continue; - } + list_for_each_entry(link, &acpi_link_list, list) { /* * reflect the possible and active irqs in the penalty table -- @@ -514,19 +508,17 @@ int __init acpi_irq_penalty_init(void) } } /* Add a penalty for the SCI */ - acpi_irq_penalty[acpi_fadt.sci_int] += PIRQ_PENALTY_PCI_USING; - + acpi_irq_penalty[acpi_gbl_FADT.sci_interrupt] += PIRQ_PENALTY_PCI_USING; return 0; } -static int acpi_irq_balance; /* 0: static, 1: balance */ +static int acpi_irq_balance = -1; /* 0: static, 1: balance */ static int acpi_pci_link_allocate(struct acpi_pci_link *link) { int irq; int i; - if (link->irq.initialized) { if (link->refcnt == 0) /* This means the link is disabled but initialized */ @@ -554,11 +546,10 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) /* * if active found, use it; else pick entry from end of possible list. */ - if (link->irq.active) { + if (link->irq.active) irq = link->irq.active; - } else { + else irq = link->irq.possible[link->irq.possible_count - 1]; - } if (acpi_irq_balance || !link->irq.active) { /* @@ -581,13 +572,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) return -ENODEV; } else { acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; - printk(PREFIX "%s [%s] enabled at IRQ %d\n", + printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", acpi_device_name(link->device), acpi_device_bid(link->device), link->irq.active); } link->irq.initialized = 1; - return 0; } @@ -596,16 +586,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * success: return IRQ >= 0 * failure: return -1 */ - -int -acpi_pci_link_allocate_irq(acpi_handle handle, - int index, - int *triggering, int *polarity, char **name) +int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, + int *polarity, char **name) { - int result = 0; - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; - + int result; + struct acpi_device *device; + struct acpi_pci_link *link; result = acpi_bus_get_device(handle, &device); if (result) { @@ -613,7 +599,7 @@ acpi_pci_link_allocate_irq(acpi_handle handle, return -1; } - link = (struct acpi_pci_link *)acpi_driver_data(device); + link = acpi_driver_data(device); if (!link) { printk(KERN_ERR PREFIX "Invalid link context\n"); return -1; @@ -657,18 +643,17 @@ acpi_pci_link_allocate_irq(acpi_handle handle, */ int acpi_pci_link_free_irq(acpi_handle handle) { - struct acpi_device *device = NULL; - struct acpi_pci_link *link = NULL; + struct acpi_device *device; + struct acpi_pci_link *link; acpi_status result; - result = acpi_bus_get_device(handle, &device); if (result) { printk(KERN_ERR PREFIX "Invalid link device\n"); return -1; } - link = (struct acpi_pci_link *)acpi_driver_data(device); + link = acpi_driver_data(device); if (!link) { printk(KERN_ERR PREFIX "Invalid link context\n"); return -1; @@ -696,9 +681,9 @@ int acpi_pci_link_free_irq(acpi_handle handle) "Link %s is dereferenced\n", acpi_device_bid(link->device))); - if (link->refcnt == 0) { - acpi_ut_evaluate_object(link->device->handle, "_DIS", 0, NULL); - } + if (link->refcnt == 0) + acpi_evaluate_object(link->device->handle, "_DIS", NULL, NULL); + mutex_unlock(&acpi_link_lock); return (link->irq.active); } @@ -709,24 +694,19 @@ int acpi_pci_link_free_irq(acpi_handle handle) static int acpi_pci_link_add(struct acpi_device *device) { - int result = 0; - struct acpi_pci_link *link = NULL; - int i = 0; + int result; + struct acpi_pci_link *link; + int i; int found = 0; - - if (!device) - return -EINVAL; - - link = kmalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); + link = kzalloc(sizeof(struct acpi_pci_link), GFP_KERNEL); if (!link) return -ENOMEM; - memset(link, 0, sizeof(struct acpi_pci_link)); link->device = device; strcpy(acpi_device_name(device), ACPI_PCI_LINK_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); - acpi_driver_data(device) = link; + device->driver_data = link; mutex_lock(&acpi_link_lock); result = acpi_pci_link_get_possible(link); @@ -736,7 +716,7 @@ static int acpi_pci_link_add(struct acpi_device *device) /* query and set link->irq.active */ acpi_pci_link_get_current(link); - printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), + printk(KERN_INFO PREFIX "%s [%s] (IRQs", acpi_device_name(device), acpi_device_bid(device)); for (i = 0; i < link->irq.possible_count; i++) { if (link->irq.active == link->irq.possible[i]) { @@ -756,13 +736,11 @@ static int acpi_pci_link_add(struct acpi_device *device) printk("\n"); - /* TBD: Acquire/release lock */ - list_add_tail(&link->node, &acpi_link.entries); - acpi_link.count++; + list_add_tail(&link->list, &acpi_link_list); end: /* disable all links -- to be activated on use */ - acpi_ut_evaluate_object(device->handle, "_DIS", 0, NULL); + acpi_evaluate_object(device->handle, "_DIS", NULL, NULL); mutex_unlock(&acpi_link_lock); if (result) @@ -773,28 +751,17 @@ static int acpi_pci_link_add(struct acpi_device *device) static int acpi_pci_link_resume(struct acpi_pci_link *link) { - if (link->refcnt && link->irq.active && link->irq.initialized) return (acpi_pci_link_set(link, link->irq.active)); - else - return 0; + + return 0; } static int irqrouter_resume(struct sys_device *dev) { - struct list_head *node = NULL; - struct acpi_pci_link *link = NULL; - - - /* Make sure SCI is enabled again (Apple firmware bug?) */ - acpi_set_register(ACPI_BITREG_SCI_ENABLE, 1, ACPI_MTX_DO_NOT_LOCK); + struct acpi_pci_link *link; - list_for_each(node, &acpi_link.entries) { - link = list_entry(node, struct acpi_pci_link, node); - if (!link) { - printk(KERN_ERR PREFIX "Invalid link context\n"); - continue; - } + list_for_each_entry(link, &acpi_link_list, list) { acpi_pci_link_resume(link); } return 0; @@ -802,20 +769,15 @@ static int irqrouter_resume(struct sys_device *dev) static int acpi_pci_link_remove(struct acpi_device *device, int type) { - struct acpi_pci_link *link = NULL; + struct acpi_pci_link *link; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - link = (struct acpi_pci_link *)acpi_driver_data(device); + link = acpi_driver_data(device); mutex_lock(&acpi_link_lock); - list_del(&link->node); + list_del(&link->list); mutex_unlock(&acpi_link_lock); kfree(link); - return 0; } @@ -838,7 +800,7 @@ static int __init acpi_irq_penalty_update(char *str, int used) if (irq < 0) continue; - if (irq >= ACPI_MAX_IRQS) + if (irq >= ARRAY_SIZE(acpi_irq_penalty)) continue; if (used) @@ -861,10 +823,12 @@ static int __init acpi_irq_penalty_update(char *str, int used) */ void acpi_penalize_isa_irq(int irq, int active) { - if (active) - acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; - else - acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; + if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { + if (active) + acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; + else + acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; + } } /* @@ -899,7 +863,7 @@ static int __init acpi_irq_nobalance_set(char *str) __setup("acpi_irq_nobalance", acpi_irq_nobalance_set); -int __init acpi_irq_balance_set(char *str) +static int __init acpi_irq_balance_set(char *str) { acpi_irq_balance = 1; return 1; @@ -909,7 +873,7 @@ __setup("acpi_irq_balance", acpi_irq_balance_set); /* FIXME: we will remove this interface after all drivers call pci_disable_device */ static struct sysdev_class irqrouter_sysdev_class = { - set_kset_name("irqrouter"), + .name = "irqrouter", .resume = irqrouter_resume, }; @@ -922,7 +886,6 @@ static int __init irqrouter_init_sysfs(void) { int error; - if (acpi_disabled || acpi_noirq) return 0; @@ -937,12 +900,16 @@ device_initcall(irqrouter_init_sysfs); static int __init acpi_pci_link_init(void) { - if (acpi_noirq) return 0; - acpi_link.count = 0; - INIT_LIST_HEAD(&acpi_link.entries); + if (acpi_irq_balance == -1) { + /* no command line switch: enable balancing in IOAPIC mode */ + if (acpi_irq_model == ACPI_IRQ_MODEL_IOAPIC) + acpi_irq_balance = 1; + else + acpi_irq_balance = 0; + } if (acpi_bus_register_driver(&acpi_pci_link_driver) < 0) return -ENODEV;