ACPI/PCI: handle multiple _OSC

There is an IA64 system here which have two pci root bridges with _OSC.
One _OSC disables SHPC control bit but the other not. Below patch makes
_OSC data per-device instead of one global, otherwise linux takes both
root bridges don't support SHPC.

Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>

authored by Shaohua Li and committed by Jesse Barnes a5d1c879 4a367f3a

+66 -29
+66 -29
drivers/pci/pci-acpi.c
··· 19 19 #include <linux/pci-acpi.h> 20 20 #include "pci.h" 21 21 22 - static u32 ctrlset_buf[3] = {0, 0, 0}; 23 - static u32 global_ctrlsets = 0; 22 + struct acpi_osc_data { 23 + acpi_handle handle; 24 + u32 ctrlset_buf[3]; 25 + u32 global_ctrlsets; 26 + struct list_head sibiling; 27 + }; 28 + static LIST_HEAD(acpi_osc_data_list); 29 + 30 + static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) 31 + { 32 + struct acpi_osc_data *data; 33 + 34 + list_for_each_entry(data, &acpi_osc_data_list, sibiling) { 35 + if (data->handle == handle) 36 + return data; 37 + } 38 + data = kzalloc(sizeof(*data), GFP_KERNEL); 39 + if (!data) 40 + return NULL; 41 + INIT_LIST_HEAD(&data->sibiling); 42 + data->handle = handle; 43 + list_add_tail(&data->sibiling, &acpi_osc_data_list); 44 + return data; 45 + } 46 + 24 47 static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 25 48 26 49 static acpi_status ··· 60 37 union acpi_object *out_obj; 61 38 u32 osc_dw0; 62 39 acpi_status *ret_status = (acpi_status *)retval; 40 + struct acpi_osc_data *osc_data = acpi_get_osc_data(handle); 41 + u32 flags = (unsigned long)context, temp; 63 42 64 - 43 + if (!osc_data) { 44 + printk(KERN_ERR "acpi osc data array is full\n"); 45 + return AE_ERROR; 46 + } 47 + 48 + osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); 49 + 50 + /* do _OSC query for all possible controls */ 51 + temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; 52 + osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 53 + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 54 + 65 55 /* Setting up input parameters */ 66 56 input.count = 4; 67 57 input.pointer = in_params; ··· 87 51 in_params[2].integer.value = 3; 88 52 in_params[3].type = ACPI_TYPE_BUFFER; 89 53 in_params[3].buffer.length = 12; 90 - in_params[3].buffer.pointer = (u8 *)context; 54 + in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf; 91 55 92 56 status = acpi_evaluate_object(handle, "_OSC", &input, &output); 93 - if (ACPI_FAILURE (status)) { 94 - *ret_status = status; 95 - return status; 96 - } 57 + if (ACPI_FAILURE(status)) 58 + goto out_nofree; 97 59 out_obj = output.pointer; 98 60 99 61 if (out_obj->type != ACPI_TYPE_BUFFER) { ··· 110 76 printk(KERN_DEBUG "_OSC invalid revision\n"); 111 77 if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { 112 78 /* Update Global Control Set */ 113 - global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); 79 + osc_data->global_ctrlsets = 80 + *((u32 *)(out_obj->buffer.pointer + 8)); 114 81 status = AE_OK; 115 82 goto query_osc_out; 116 83 } ··· 120 85 } 121 86 122 87 /* Update Global Control Set */ 123 - global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); 88 + osc_data->global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); 124 89 status = AE_OK; 125 90 126 91 query_osc_out: 127 92 kfree(output.pointer); 93 + out_nofree: 128 94 *ret_status = status; 95 + 96 + osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; 97 + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; 98 + if (ACPI_FAILURE(status)) { 99 + /* no osc support at all */ 100 + osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0; 101 + } 102 + 129 103 return status; 130 104 } 131 105 ··· 209 165 **/ 210 166 acpi_status __pci_osc_support_set(u32 flags, const char *hid) 211 167 { 212 - u32 temp; 213 168 acpi_status retval = AE_NOT_FOUND; 214 169 215 170 if (!(flags & OSC_SUPPORT_MASKS)) { 216 171 return AE_TYPE; 217 172 } 218 - ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); 219 - 220 - /* do _OSC query for all possible controls */ 221 - temp = ctrlset_buf[OSC_CONTROL_TYPE]; 222 - ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; 223 - ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; 224 173 acpi_get_devices(hid, 225 174 acpi_query_osc, 226 - ctrlset_buf, 175 + (void *)(unsigned long)flags, 227 176 (void **) &retval ); 228 - ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; 229 - ctrlset_buf[OSC_CONTROL_TYPE] = temp; 230 - if (ACPI_FAILURE(retval)) { 231 - /* no osc support at all */ 232 - ctrlset_buf[OSC_SUPPORT_TYPE] = 0; 233 - } 234 177 return AE_OK; 235 178 } 236 179 ··· 232 201 { 233 202 acpi_status status; 234 203 u32 ctrlset; 204 + struct acpi_osc_data *osc_data = acpi_get_osc_data(handle); 205 + 206 + if (!osc_data) { 207 + printk(KERN_ERR "acpi osc data array is full\n"); 208 + return AE_ERROR; 209 + } 235 210 236 211 ctrlset = (flags & OSC_CONTROL_MASKS); 237 212 if (!ctrlset) { 238 213 return AE_TYPE; 239 214 } 240 - if (ctrlset_buf[OSC_SUPPORT_TYPE] && 241 - ((global_ctrlsets & ctrlset) != ctrlset)) { 215 + if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] && 216 + ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) { 242 217 return AE_SUPPORT; 243 218 } 244 - ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; 245 - status = acpi_run_osc(handle, ctrlset_buf); 219 + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; 220 + status = acpi_run_osc(handle, osc_data->ctrlset_buf); 246 221 if (ACPI_FAILURE (status)) { 247 - ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; 222 + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; 248 223 } 249 224 250 225 return status;