diff options
-rw-r--r-- | drivers/pci/pci-acpi.c | 165 |
1 files changed, 55 insertions, 110 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 9d6fc8e6285d..032b3268018b 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -46,40 +46,15 @@ static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) | |||
46 | 46 | ||
47 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; | 47 | static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; |
48 | 48 | ||
49 | static acpi_status | 49 | static acpi_status acpi_run_osc(acpi_handle handle, |
50 | acpi_query_osc ( | 50 | struct acpi_osc_data *osc_data) |
51 | acpi_handle handle, | ||
52 | u32 level, | ||
53 | void *context, | ||
54 | void **retval ) | ||
55 | { | 51 | { |
56 | acpi_status status; | 52 | acpi_status status; |
57 | struct acpi_object_list input; | 53 | struct acpi_object_list input; |
58 | union acpi_object in_params[4]; | 54 | union acpi_object in_params[4]; |
59 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 55 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; |
60 | union acpi_object *out_obj; | 56 | union acpi_object *out_obj; |
61 | u32 osc_dw0; | 57 | u32 osc_dw0, flags = osc_data->ctrlset_buf[OSC_QUERY_TYPE]; |
62 | acpi_status *ret_status = (acpi_status *)retval; | ||
63 | struct acpi_osc_data *osc_data; | ||
64 | u32 flags = (unsigned long)context, temp; | ||
65 | acpi_handle tmp; | ||
66 | |||
67 | status = acpi_get_handle(handle, "_OSC", &tmp); | ||
68 | if (ACPI_FAILURE(status)) | ||
69 | return status; | ||
70 | |||
71 | osc_data = acpi_get_osc_data(handle); | ||
72 | if (!osc_data) { | ||
73 | printk(KERN_ERR "acpi osc data array is full\n"); | ||
74 | return AE_ERROR; | ||
75 | } | ||
76 | |||
77 | osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); | ||
78 | |||
79 | /* do _OSC query for all possible controls */ | ||
80 | temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; | ||
81 | osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; | ||
82 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; | ||
83 | 58 | ||
84 | /* Setting up input parameters */ | 59 | /* Setting up input parameters */ |
85 | input.count = 4; | 60 | input.count = 4; |
@@ -97,14 +72,13 @@ acpi_query_osc ( | |||
97 | 72 | ||
98 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); | 73 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); |
99 | if (ACPI_FAILURE(status)) | 74 | if (ACPI_FAILURE(status)) |
100 | goto out_nofree; | 75 | return status; |
101 | out_obj = output.pointer; | ||
102 | 76 | ||
77 | out_obj = output.pointer; | ||
103 | if (out_obj->type != ACPI_TYPE_BUFFER) { | 78 | if (out_obj->type != ACPI_TYPE_BUFFER) { |
104 | printk(KERN_DEBUG | 79 | printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); |
105 | "Evaluate _OSC returns wrong type\n"); | ||
106 | status = AE_TYPE; | 80 | status = AE_TYPE; |
107 | goto query_osc_out; | 81 | goto out_kfree; |
108 | } | 82 | } |
109 | osc_dw0 = *((u32 *) out_obj->buffer.pointer); | 83 | osc_dw0 = *((u32 *) out_obj->buffer.pointer); |
110 | if (osc_dw0) { | 84 | if (osc_dw0) { |
@@ -115,93 +89,64 @@ acpi_query_osc ( | |||
115 | if (osc_dw0 & OSC_INVALID_REVISION_ERROR) | 89 | if (osc_dw0 & OSC_INVALID_REVISION_ERROR) |
116 | printk(KERN_DEBUG "_OSC invalid revision\n"); | 90 | printk(KERN_DEBUG "_OSC invalid revision\n"); |
117 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | 91 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { |
118 | /* Update Global Control Set */ | 92 | if (flags & OSC_QUERY_ENABLE) |
119 | osc_data->global_ctrlsets = | 93 | goto out_success; |
120 | *((u32 *)(out_obj->buffer.pointer + 8)); | 94 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); |
121 | status = AE_OK; | 95 | status = AE_SUPPORT; |
122 | goto query_osc_out; | 96 | goto out_kfree; |
123 | } | 97 | } |
124 | status = AE_ERROR; | 98 | status = AE_ERROR; |
125 | goto query_osc_out; | 99 | goto out_kfree; |
100 | } | ||
101 | out_success: | ||
102 | if (flags & OSC_QUERY_ENABLE) { | ||
103 | /* Update Global Control Set */ | ||
104 | osc_data->global_ctrlsets = | ||
105 | *((u32 *)(out_obj->buffer.pointer + 8)); | ||
126 | } | 106 | } |
127 | |||
128 | /* Update Global Control Set */ | ||
129 | osc_data->global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); | ||
130 | status = AE_OK; | 107 | status = AE_OK; |
131 | 108 | ||
132 | query_osc_out: | 109 | out_kfree: |
133 | kfree(output.pointer); | 110 | kfree(output.pointer); |
134 | out_nofree: | ||
135 | *ret_status = status; | ||
136 | |||
137 | osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; | ||
138 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; | ||
139 | if (ACPI_FAILURE(status)) { | ||
140 | /* no osc support at all */ | ||
141 | osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0; | ||
142 | } | ||
143 | |||
144 | return status; | 111 | return status; |
145 | } | 112 | } |
146 | 113 | ||
147 | 114 | static acpi_status acpi_query_osc(acpi_handle handle, | |
148 | static acpi_status | 115 | u32 level, void *context, void **retval) |
149 | acpi_run_osc ( | ||
150 | acpi_handle handle, | ||
151 | void *context) | ||
152 | { | 116 | { |
153 | acpi_status status; | 117 | acpi_status status; |
154 | struct acpi_object_list input; | 118 | acpi_status *ret_status = (acpi_status *)retval; |
155 | union acpi_object in_params[4]; | 119 | struct acpi_osc_data *osc_data; |
156 | struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; | 120 | u32 flags = (unsigned long)context, temp; |
157 | union acpi_object *out_obj; | 121 | acpi_handle tmp; |
158 | u32 osc_dw0; | ||
159 | |||
160 | /* Setting up input parameters */ | ||
161 | input.count = 4; | ||
162 | input.pointer = in_params; | ||
163 | in_params[0].type = ACPI_TYPE_BUFFER; | ||
164 | in_params[0].buffer.length = 16; | ||
165 | in_params[0].buffer.pointer = OSC_UUID; | ||
166 | in_params[1].type = ACPI_TYPE_INTEGER; | ||
167 | in_params[1].integer.value = 1; | ||
168 | in_params[2].type = ACPI_TYPE_INTEGER; | ||
169 | in_params[2].integer.value = 3; | ||
170 | in_params[3].type = ACPI_TYPE_BUFFER; | ||
171 | in_params[3].buffer.length = 12; | ||
172 | in_params[3].buffer.pointer = (u8 *)context; | ||
173 | 122 | ||
174 | status = acpi_evaluate_object(handle, "_OSC", &input, &output); | 123 | status = acpi_get_handle(handle, "_OSC", &tmp); |
175 | if (ACPI_FAILURE (status)) | 124 | if (ACPI_FAILURE(status)) |
176 | return status; | 125 | return status; |
177 | 126 | ||
178 | out_obj = output.pointer; | 127 | osc_data = acpi_get_osc_data(handle); |
179 | if (out_obj->type != ACPI_TYPE_BUFFER) { | 128 | if (!osc_data) { |
180 | printk(KERN_DEBUG | 129 | printk(KERN_ERR "acpi osc data array is full\n"); |
181 | "Evaluate _OSC returns wrong type\n"); | 130 | return AE_ERROR; |
182 | status = AE_TYPE; | ||
183 | goto run_osc_out; | ||
184 | } | 131 | } |
185 | osc_dw0 = *((u32 *) out_obj->buffer.pointer); | 132 | |
186 | if (osc_dw0) { | 133 | osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); |
187 | if (osc_dw0 & OSC_REQUEST_ERROR) | 134 | |
188 | printk(KERN_DEBUG "_OSC request fails\n"); | 135 | /* do _OSC query for all possible controls */ |
189 | if (osc_dw0 & OSC_INVALID_UUID_ERROR) | 136 | temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; |
190 | printk(KERN_DEBUG "_OSC invalid UUID\n"); | 137 | osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; |
191 | if (osc_dw0 & OSC_INVALID_REVISION_ERROR) | 138 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; |
192 | printk(KERN_DEBUG "_OSC invalid revision\n"); | 139 | |
193 | if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { | 140 | status = acpi_run_osc(handle, osc_data); |
194 | printk(KERN_DEBUG "_OSC FW not grant req. control\n"); | 141 | *ret_status = status; |
195 | status = AE_SUPPORT; | 142 | |
196 | goto run_osc_out; | 143 | osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; |
197 | } | 144 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; |
198 | status = AE_ERROR; | 145 | if (ACPI_FAILURE(status)) { |
199 | goto run_osc_out; | 146 | /* no osc support at all */ |
147 | osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0; | ||
200 | } | 148 | } |
201 | status = AE_OK; | ||
202 | 149 | ||
203 | run_osc_out: | ||
204 | kfree(output.pointer); | ||
205 | return status; | 150 | return status; |
206 | } | 151 | } |
207 | 152 | ||
@@ -260,7 +205,7 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) | |||
260 | return AE_SUPPORT; | 205 | return AE_SUPPORT; |
261 | } | 206 | } |
262 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; | 207 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; |
263 | status = acpi_run_osc(handle, osc_data->ctrlset_buf); | 208 | status = acpi_run_osc(handle, osc_data); |
264 | if (ACPI_FAILURE (status)) { | 209 | if (ACPI_FAILURE (status)) { |
265 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; | 210 | osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; |
266 | } | 211 | } |