X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fpci%2Fhotplug%2Facpiphp_ibm.c;h=7f03881a8b682aa958f4919fa570fecfc1674c60;hb=refs%2Fheads%2Fvserver;hp=fe7866c1ccbd9c4a5b1edd990ce56b3ded986d4a;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index fe7866c1c..7f03881a8 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -35,7 +35,6 @@ #include #include "acpiphp.h" -#include "pci_hotplug.h" #define DRIVER_VERSION "1.0.1" #define DRIVER_AUTHOR "Irene Zubarev , Vernon Mauery " @@ -47,7 +46,7 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_VERSION(DRIVER_VERSION); -module_param(debug, bool, 644); +module_param(debug, bool, 0644); MODULE_PARM_DESC(debug, " Debugging mode enabled or not"); #define MY_NAME "acpiphp_ibm" @@ -64,6 +63,8 @@ do { \ #define IBM_HARDWARE_ID1 "IBM37D0" #define IBM_HARDWARE_ID2 "IBM37D4" +#define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun) + /* union apci_descriptor - allows access to the * various device descriptors that are embedded in the * aPCI table @@ -84,6 +85,7 @@ union apci_descriptor { u8 attn; u8 status[2]; u8 sun; + u8 res[3]; } slot; struct { u8 type; @@ -128,6 +130,43 @@ static struct acpiphp_attention_info ibm_attention_info = .owner = THIS_MODULE, }; +/** + * ibm_slot_from_id - workaround for bad ibm hardware + * @id: the slot number that linux refers to the slot by + * + * Description: this method returns the aCPI slot descriptor + * corresponding to the Linux slot number. This descriptor + * has info about the aPCI slot id and attention status. + * This descriptor must be freed using kfree when done. + **/ +static union apci_descriptor *ibm_slot_from_id(int id) +{ + int ind = 0, size; + union apci_descriptor *ret = NULL, *des; + char *table; + + size = ibm_get_table_from_acpi(&table); + des = (union apci_descriptor *)table; + if (memcmp(des->header.sig, "aPCI", 4) != 0) + goto ibm_slot_done; + + des = (union apci_descriptor *)&table[ind += des->header.len]; + while (ind < size && (des->generic.type != 0x82 || + des->slot.slot_num != id)) { + des = (union apci_descriptor *)&table[ind += des->generic.len]; + } + + if (ind < size && des->slot.slot_num == id) + ret = des; + +ibm_slot_done: + if (ret) { + ret = kmalloc(sizeof(union apci_descriptor), GFP_KERNEL); + memcpy(ret, des, sizeof(union apci_descriptor)); + } + kfree(table); + return ret; +} /** * ibm_set_attention_status - callback method to set the attention LED @@ -139,32 +178,34 @@ static struct acpiphp_attention_info ibm_attention_info = **/ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) { - int retval = 0; union acpi_object args[2]; struct acpi_object_list params = { .pointer = args, .count = 2 }; acpi_status stat; - unsigned long rc = 0; - struct acpiphp_slot *acpi_slot; + unsigned long rc; + union apci_descriptor *ibm_slot; - acpi_slot = ((struct slot *)(slot->private))->acpi_slot; + ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); - dbg("%s: set slot %d attention status to %d\n", __FUNCTION__, - acpi_slot->sun, (status ? 1 : 0)); + dbg("%s: set slot %d (%d) attention status to %d\n", __FUNCTION__, + ibm_slot->slot.slot_num, ibm_slot->slot.slot_id, + (status ? 1 : 0)); args[0].type = ACPI_TYPE_INTEGER; - args[0].integer.value = acpi_slot->sun; + args[0].integer.value = ibm_slot->slot.slot_id; args[1].type = ACPI_TYPE_INTEGER; args[1].integer.value = (status) ? 1 : 0; + kfree(ibm_slot); + stat = acpi_evaluate_integer(ibm_acpi_handle, "APLS", ¶ms, &rc); if (ACPI_FAILURE(stat)) { - retval = -ENODEV; err("APLS evaluation failed: 0x%08x\n", stat); + return -ENODEV; } else if (!rc) { - retval = -ERANGE; err("APLS method failed: 0x%08lx\n", rc); + return -ERANGE; } - return retval; + return 0; } /** @@ -181,38 +222,21 @@ static int ibm_set_attention_status(struct hotplug_slot *slot, u8 status) **/ static int ibm_get_attention_status(struct hotplug_slot *slot, u8 *status) { - int retval = -EINVAL, ind = 0, size; - char *table = NULL; - struct acpiphp_slot *acpi_slot; - union apci_descriptor *des; + union apci_descriptor *ibm_slot; - acpi_slot = ((struct slot *)(slot->private))->acpi_slot; + ibm_slot = ibm_slot_from_id(hpslot_to_sun(slot)); - size = ibm_get_table_from_acpi(&table); - if (size <= 0 || !table) - goto get_attn_done; - // read the header - des = (union apci_descriptor *)&table[ind]; - if (memcmp(des->header.sig, "aPCI", 4) != 0) - goto get_attn_done; - des = (union apci_descriptor *)&table[ind += des->header.len]; - while (ind < size && (des->generic.type != 0x82 || - des->slot.slot_id != acpi_slot->sun)) - des = (union apci_descriptor *)&table[ind += des->generic.len]; - if (ind < size && des->slot.slot_id == acpi_slot->sun) { - retval = 0; - if (des->slot.attn & 0xa0 || des->slot.status[1] & 0x08) - *status = 1; - else - *status = 0; - } + if (ibm_slot->slot.attn & 0xa0 || ibm_slot->slot.status[1] & 0x08) + *status = 1; + else + *status = 0; - dbg("%s: get slot %d attention status is %d retval=%x\n", - __FUNCTION__, acpi_slot->sun, *status, retval); + dbg("%s: get slot %d (%d) attention status is %d\n", __FUNCTION__, + ibm_slot->slot.slot_num, ibm_slot->slot.slot_id, + *status); -get_attn_done: - kfree(table); - return retval; + kfree(ibm_slot); + return 0; } /** @@ -277,7 +301,7 @@ static int ibm_get_table_from_acpi(char **bufp) } package = (union acpi_object *) buffer.pointer; - if(!(package) || + if (!(package) || (package->type != ACPI_TYPE_PACKAGE) || !(package->package.elements)) { err("%s: Invalid APCI object\n", __FUNCTION__); @@ -295,13 +319,12 @@ static int ibm_get_table_from_acpi(char **bufp) if (bufp == NULL) goto read_table_done; - lbuf = kmalloc(size, GFP_KERNEL); + lbuf = kzalloc(size, GFP_KERNEL); dbg("%s: element count: %i, ASL table size: %i, &table = 0x%p\n", __FUNCTION__, package->package.count, size, lbuf); if (lbuf) { *bufp = lbuf; - memset(lbuf, 0, size); } else { size = -ENOMEM; goto read_table_done; @@ -380,7 +403,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, } info.hardware_id.value[sizeof(info.hardware_id.value) - 1] = '\0'; - if(info.current_status && (info.valid & ACPI_VALID_HID) && + if (info.current_status && (info.valid & ACPI_VALID_HID) && (!strcmp(info.hardware_id.value, IBM_HARDWARE_ID1) || !strcmp(info.hardware_id.value, IBM_HARDWARE_ID2))) { dbg("found hardware: %s, handle: %p\n", info.hardware_id.value, @@ -424,13 +447,11 @@ static int __init ibm_acpiphp_init(void) } ibm_note.device = device; - status = acpi_install_notify_handler( - ibm_acpi_handle, - ACPI_DEVICE_NOTIFY, - ibm_handle_events, + status = acpi_install_notify_handler(ibm_acpi_handle, + ACPI_DEVICE_NOTIFY, ibm_handle_events, &ibm_note); if (ACPI_FAILURE(status)) { - err("%s: Failed to register notification handler\n", + err("%s: Failed to register notification handler\n", __FUNCTION__); retval = -EBUSY; goto init_cleanup; @@ -457,17 +478,14 @@ static void __exit ibm_acpiphp_exit(void) if (acpiphp_unregister_attention(&ibm_attention_info)) err("%s: attention info deregistration failed", __FUNCTION__); - status = acpi_remove_notify_handler( + status = acpi_remove_notify_handler( ibm_acpi_handle, ACPI_DEVICE_NOTIFY, ibm_handle_events); - if (ACPI_FAILURE(status)) - err("%s: Notification handler removal failed\n", - __FUNCTION__); - // remove the /sys entries - if (sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr)) - err("%s: removal of sysfs file apci_table failed\n", - __FUNCTION__); + if (ACPI_FAILURE(status)) + err("%s: Notification handler removal failed\n", __FUNCTION__); + /* remove the /sys entries */ + sysfs_remove_bin_file(sysdir, &ibm_apci_table_attr); } module_init(ibm_acpiphp_init);