diff options
-rw-r--r-- | drivers/pci/pci-acpi.c | 73 |
1 files changed, 39 insertions, 34 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 032b3268018b..b1bd6e6155a3 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -21,12 +21,18 @@ | |||
21 | 21 | ||
22 | struct acpi_osc_data { | 22 | struct acpi_osc_data { |
23 | acpi_handle handle; | 23 | acpi_handle handle; |
24 | u32 ctrlset_buf[3]; | 24 | u32 support_set; |
25 | u32 global_ctrlsets; | 25 | u32 control_set; |
26 | u32 query_result; | ||
26 | struct list_head sibiling; | 27 | struct list_head sibiling; |
27 | }; | 28 | }; |
28 | static LIST_HEAD(acpi_osc_data_list); | 29 | static LIST_HEAD(acpi_osc_data_list); |
29 | 30 | ||
31 | struct acpi_osc_args { | ||
32 | u32 capbuf[3]; | ||
33 | u32 query_result; | ||
34 | }; | ||
35 | |||
30 | static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) | 36 | static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) |
31 | { | 37 | { |
32 | struct acpi_osc_data *data; | 38 | struct acpi_osc_data *data; |
@@ -47,14 +53,14 @@ static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) | |||
47 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; | 53 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; |
48 | 54 | ||
49 | static acpi_status acpi_run_osc(acpi_handle handle, | 55 | static acpi_status acpi_run_osc(acpi_handle handle, |
50 | struct acpi_osc_data *osc_data) | 56 | struct acpi_osc_args *osc_args) |
51 | { | 57 | { |
52 | acpi_status status; | 58 | acpi_status status; |
53 | struct acpi_object_list input; | 59 | struct acpi_object_list input; |
54 | union acpi_object in_params[4]; | 60 | union acpi_object in_params[4]; |
55 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 61 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; |
56 | union acpi_object *out_obj; | 62 | union acpi_object *out_obj; |
57 | u32 osc_dw0, flags = osc_data->ctrlset_buf[OSC_QUERY_TYPE]; | 63 | u32 osc_dw0, flags = osc_args->capbuf[OSC_QUERY_TYPE]; |
58 | 64 | ||
59 | /* Setting up input parameters */ | 65 | /* Setting up input parameters */ |
60 | input.count = 4; | 66 | input.count = 4; |
@@ -68,7 +74,7 @@ static acpi_status acpi_run_osc(acpi_handle handle, | |||
68 | in_params[2].integer.value = 3; | 74 | in_params[2].integer.value = 3; |
69 | in_params[3].type = ACPI_TYPE_BUFFER; | 75 | in_params[3].type = ACPI_TYPE_BUFFER; |
70 | in_params[3].buffer.length = 12; | 76 | in_params[3].buffer.length = 12; |
71 | in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf; | 77 | in_params[3].buffer.pointer = (u8 *)osc_args->capbuf; |
72 | 78 | ||
73 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); | 79 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); |
74 | if (ACPI_FAILURE(status)) | 80 | if (ACPI_FAILURE(status)) |
@@ -99,11 +105,9 @@ static acpi_status acpi_run_osc(acpi_handle handle, | |||
99 | goto out_kfree; | 105 | goto out_kfree; |
100 | } | 106 | } |
101 | out_success: | 107 | out_success: |
102 | if (flags & OSC_QUERY_ENABLE) { | 108 | if (flags & OSC_QUERY_ENABLE) |
103 | /* Update Global Control Set */ | 109 | osc_args->query_result = |
104 | osc_data->global_ctrlsets = | ||
105 | *((u32 *)(out_obj->buffer.pointer + 8)); | 110 | *((u32 *)(out_obj->buffer.pointer + 8)); |
106 | } | ||
107 | status = AE_OK; | 111 | status = AE_OK; |
108 | 112 | ||
109 | out_kfree: | 113 | out_kfree: |
@@ -117,8 +121,9 @@ static acpi_status acpi_query_osc(acpi_handle handle, | |||
117 | acpi_status status; | 121 | acpi_status status; |
118 | acpi_status *ret_status = (acpi_status *)retval; | 122 | acpi_status *ret_status = (acpi_status *)retval; |
119 | struct acpi_osc_data *osc_data; | 123 | struct acpi_osc_data *osc_data; |
120 | u32 flags = (unsigned long)context, temp; | 124 | u32 flags = (unsigned long)context, support_set; |
121 | acpi_handle tmp; | 125 | acpi_handle tmp; |
126 | struct acpi_osc_args osc_args; | ||
122 | 127 | ||
123 | status = acpi_get_handle(handle, "_OSC", &tmp); | 128 | status = acpi_get_handle(handle, "_OSC", &tmp); |
124 | if (ACPI_FAILURE(status)) | 129 | if (ACPI_FAILURE(status)) |
@@ -130,21 +135,18 @@ static acpi_status acpi_query_osc(acpi_handle handle, | |||
130 | return AE_ERROR; | 135 | return AE_ERROR; |
131 | } | 136 | } |
132 | 137 | ||
133 | osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); | ||
134 | |||
135 | /* do _OSC query for all possible controls */ | 138 | /* do _OSC query for all possible controls */ |
136 | temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; | 139 | support_set = osc_data->support_set | (flags & OSC_SUPPORT_MASKS); |
137 | osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | 140 | osc_args.capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; |
138 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | 141 | osc_args.capbuf[OSC_SUPPORT_TYPE] = support_set; |
142 | osc_args.capbuf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | ||
139 | 143 | ||
140 | status = acpi_run_osc(handle, osc_data); | 144 | status = acpi_run_osc(handle, &osc_args); |
141 | *ret_status = status; | 145 | *ret_status = status; |
142 | 146 | ||
143 | osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; | 147 | if (ACPI_SUCCESS(status)) { |
144 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; | 148 | osc_data->support_set = support_set; |
145 | if (ACPI_FAILURE(status)) { | 149 | osc_data->query_result = osc_args.query_result; |
146 | /* no osc support at all */ | ||
147 | osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0; | ||
148 | } | 150 | } |
149 | 151 | ||
150 | return status; | 152 | return status; |
@@ -181,10 +183,11 @@ acpi_status __pci_osc_support_set(u32 flags, const char *hid) | |||
181 | **/ | 183 | **/ |
182 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | 184 | acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) |
183 | { | 185 | { |
184 | acpi_status status; | 186 | acpi_status status; |
185 | u32 ctrlset; | 187 | u32 ctrlset, control_set; |
186 | acpi_handle tmp; | 188 | acpi_handle tmp; |
187 | struct acpi_osc_data *osc_data; | 189 | struct acpi_osc_data *osc_data; |
190 | struct acpi_osc_args osc_args; | ||
188 | 191 | ||
189 | status = acpi_get_handle(handle, "_OSC", &tmp); | 192 | status = acpi_get_handle(handle, "_OSC", &tmp); |
190 | if (ACPI_FAILURE(status)) | 193 | if (ACPI_FAILURE(status)) |
@@ -197,19 +200,21 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | |||
197 | } | 200 | } |
198 | 201 | ||
199 | ctrlset = (flags & OSC_CONTROL_MASKS); | 202 | ctrlset = (flags & OSC_CONTROL_MASKS); |
200 | if (!ctrlset) { | 203 | if (!ctrlset) |
201 | return AE_TYPE; | 204 | return AE_TYPE; |
202 | } | 205 | |
203 | if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] && | 206 | if (osc_data->support_set && |
204 | ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) { | 207 | ((osc_data->query_result & ctrlset) != ctrlset)) |
205 | return AE_SUPPORT; | 208 | return AE_SUPPORT; |
206 | } | 209 | |
207 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; | 210 | control_set = osc_data->control_set | ctrlset; |
208 | status = acpi_run_osc(handle, osc_data); | 211 | osc_args.capbuf[OSC_QUERY_TYPE] = 0; |
209 | if (ACPI_FAILURE (status)) { | 212 | osc_args.capbuf[OSC_SUPPORT_TYPE] = osc_data->support_set; |
210 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; | 213 | osc_args.capbuf[OSC_CONTROL_TYPE] = control_set; |
211 | } | 214 | status = acpi_run_osc(handle, &osc_args); |
212 | 215 | if (ACPI_SUCCESS(status)) | |
216 | osc_data->control_set = control_set; | ||
217 | |||
213 | return status; | 218 | return status; |
214 | } | 219 | } |
215 | EXPORT_SYMBOL(pci_osc_control_set); | 220 | EXPORT_SYMBOL(pci_osc_control_set); |