X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fpci%2Fhotplug%2Facpiphp_ibm.c;h=7e7f913ba7b9e47712a9dc6cfd0d4ca5764bbe89;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=fe7866c1ccbd9c4a5b1edd990ce56b3ded986d4a;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index fe7866c1c..7e7f913ba 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -47,7 +47,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 +64,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 +86,7 @@ union apci_descriptor { u8 attn; u8 status[2]; u8 sun; + u8 res[3]; } slot; struct { u8 type; @@ -128,6 +131,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 +179,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 +223,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; } /**