aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c165
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
47static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; 47static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66};
48 48
49static acpi_status 49static acpi_status acpi_run_osc(acpi_handle handle,
50acpi_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 }
101out_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
132query_osc_out: 109out_kfree:
133 kfree(output.pointer); 110 kfree(output.pointer);
134out_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 114static acpi_status acpi_query_osc(acpi_handle handle,
148static acpi_status 115 u32 level, void *context, void **retval)
149acpi_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
203run_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 }