diff options
author | Anssi Hannula <anssi.hannula@iki.fi> | 2011-02-20 13:07:22 -0500 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2011-03-28 06:07:18 -0400 |
commit | c3021ea1beeeb1aa8a92fa6946a6e25fc55f171d (patch) | |
tree | 11fd3dd2fa1c100fcbf639d76a22386f825984b5 /drivers/platform/x86/hp-wmi.c | |
parent | 25bb067a08c5db70cd8bcf9e160ac81718ea075c (diff) |
hp-wmi: allow setting input and output buffer sizes separately
Split buffersize parameter of hp_wmi_perform_query to insize and
outsize. Existing callers are changed to use the same value for insize
and outsize to avoid any regressions, with the exception of
hp_wmi_set_block where the output buffer is unused and therefore outsize
is set to 0 (this change is not seen by BIOS code).
The maximum input buffer size is kept at 4 bytes as per struct
bios_args. Some commands exist that take longer buffers, but they
haven't been implemented. The data portion of bios_args can be trivially
made dynamically allocated later when such larger buffers become needed.
Signed-off-by: Anssi Hannula <anssi.hannula@iki.fi>
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Diffstat (limited to 'drivers/platform/x86/hp-wmi.c')
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 8e27c27900a3..5c8ae65950d4 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c | |||
@@ -86,7 +86,6 @@ struct bios_args { | |||
86 | struct bios_return { | 86 | struct bios_return { |
87 | u32 sigpass; | 87 | u32 sigpass; |
88 | u32 return_code; | 88 | u32 return_code; |
89 | u32 value; | ||
90 | }; | 89 | }; |
91 | 90 | ||
92 | enum hp_return_value { | 91 | enum hp_return_value { |
@@ -136,7 +135,8 @@ static struct platform_driver hp_wmi_driver = { | |||
136 | * query: The commandtype -> What should be queried | 135 | * query: The commandtype -> What should be queried |
137 | * write: The command -> 0 read, 1 write, 3 ODM specific | 136 | * write: The command -> 0 read, 1 write, 3 ODM specific |
138 | * buffer: Buffer used as input and/or output | 137 | * buffer: Buffer used as input and/or output |
139 | * buffersize: Size of buffer | 138 | * insize: Size of input buffer |
139 | * outsize: Size of output buffer | ||
140 | * | 140 | * |
141 | * returns zero on success | 141 | * returns zero on success |
142 | * an HP WMI query specific error code (which is positive) | 142 | * an HP WMI query specific error code (which is positive) |
@@ -147,23 +147,28 @@ static struct platform_driver hp_wmi_driver = { | |||
147 | * size. E.g. Battery info query (0x7) is defined to have 1 byte input | 147 | * size. E.g. Battery info query (0x7) is defined to have 1 byte input |
148 | * and 128 byte output. The caller would do: | 148 | * and 128 byte output. The caller would do: |
149 | * buffer = kzalloc(128, GFP_KERNEL); | 149 | * buffer = kzalloc(128, GFP_KERNEL); |
150 | * ret = hp_wmi_perform_query(0x7, 0, buffer, 128) | 150 | * ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128) |
151 | */ | 151 | */ |
152 | static int hp_wmi_perform_query(int query, int write, u32 *buffer, | 152 | static int hp_wmi_perform_query(int query, int write, void *buffer, |
153 | int buffersize) | 153 | int insize, int outsize) |
154 | { | 154 | { |
155 | struct bios_return bios_return; | 155 | struct bios_return *bios_return; |
156 | int actual_outsize; | ||
156 | union acpi_object *obj; | 157 | union acpi_object *obj; |
157 | struct bios_args args = { | 158 | struct bios_args args = { |
158 | .signature = 0x55434553, | 159 | .signature = 0x55434553, |
159 | .command = write ? 0x2 : 0x1, | 160 | .command = write ? 0x2 : 0x1, |
160 | .commandtype = query, | 161 | .commandtype = query, |
161 | .datasize = buffersize, | 162 | .datasize = insize, |
162 | .data = *buffer, | 163 | .data = 0, |
163 | }; | 164 | }; |
164 | struct acpi_buffer input = { sizeof(struct bios_args), &args }; | 165 | struct acpi_buffer input = { sizeof(struct bios_args), &args }; |
165 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | 166 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; |
166 | 167 | ||
168 | if (WARN_ON(insize > sizeof(args.data))) | ||
169 | return -EINVAL; | ||
170 | memcpy(&args.data, buffer, insize); | ||
171 | |||
167 | wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output); | 172 | wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output); |
168 | 173 | ||
169 | obj = output.pointer; | 174 | obj = output.pointer; |
@@ -175,19 +180,26 @@ static int hp_wmi_perform_query(int query, int write, u32 *buffer, | |||
175 | return -EINVAL; | 180 | return -EINVAL; |
176 | } | 181 | } |
177 | 182 | ||
178 | bios_return = *((struct bios_return *)obj->buffer.pointer); | 183 | bios_return = (struct bios_return *)obj->buffer.pointer; |
179 | 184 | ||
180 | if (bios_return.return_code) { | 185 | if (bios_return->return_code) { |
181 | if (bios_return.return_code != HPWMI_RET_UNKNOWN_CMDTYPE) | 186 | if (bios_return->return_code != HPWMI_RET_UNKNOWN_CMDTYPE) |
182 | printk(KERN_WARNING PREFIX "query 0x%x returned " | 187 | printk(KERN_WARNING PREFIX "query 0x%x returned " |
183 | "error 0x%x\n", | 188 | "error 0x%x\n", |
184 | query, bios_return.return_code); | 189 | query, bios_return->return_code); |
185 | kfree(obj); | 190 | kfree(obj); |
186 | return bios_return.return_code; | 191 | return bios_return->return_code; |
187 | } | 192 | } |
188 | 193 | ||
189 | memcpy(buffer, &bios_return.value, sizeof(bios_return.value)); | 194 | if (!outsize) { |
195 | /* ignore output data */ | ||
196 | kfree(obj); | ||
197 | return 0; | ||
198 | } | ||
190 | 199 | ||
200 | actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); | ||
201 | memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); | ||
202 | memset(buffer + actual_outsize, 0, outsize - actual_outsize); | ||
191 | kfree(obj); | 203 | kfree(obj); |
192 | return 0; | 204 | return 0; |
193 | } | 205 | } |
@@ -196,7 +208,7 @@ static int hp_wmi_display_state(void) | |||
196 | { | 208 | { |
197 | int state = 0; | 209 | int state = 0; |
198 | int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state, | 210 | int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state, |
199 | sizeof(state)); | 211 | sizeof(state), sizeof(state)); |
200 | if (ret) | 212 | if (ret) |
201 | return -EINVAL; | 213 | return -EINVAL; |
202 | return state; | 214 | return state; |
@@ -206,7 +218,7 @@ static int hp_wmi_hddtemp_state(void) | |||
206 | { | 218 | { |
207 | int state = 0; | 219 | int state = 0; |
208 | int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state, | 220 | int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state, |
209 | sizeof(state)); | 221 | sizeof(state), sizeof(state)); |
210 | if (ret) | 222 | if (ret) |
211 | return -EINVAL; | 223 | return -EINVAL; |
212 | return state; | 224 | return state; |
@@ -216,7 +228,7 @@ static int hp_wmi_als_state(void) | |||
216 | { | 228 | { |
217 | int state = 0; | 229 | int state = 0; |
218 | int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state, | 230 | int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state, |
219 | sizeof(state)); | 231 | sizeof(state), sizeof(state)); |
220 | if (ret) | 232 | if (ret) |
221 | return -EINVAL; | 233 | return -EINVAL; |
222 | return state; | 234 | return state; |
@@ -226,7 +238,7 @@ static int hp_wmi_dock_state(void) | |||
226 | { | 238 | { |
227 | int state = 0; | 239 | int state = 0; |
228 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, | 240 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, |
229 | sizeof(state)); | 241 | sizeof(state), sizeof(state)); |
230 | 242 | ||
231 | if (ret) | 243 | if (ret) |
232 | return -EINVAL; | 244 | return -EINVAL; |
@@ -238,7 +250,7 @@ static int hp_wmi_tablet_state(void) | |||
238 | { | 250 | { |
239 | int state = 0; | 251 | int state = 0; |
240 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, | 252 | int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state, |
241 | sizeof(state)); | 253 | sizeof(state), sizeof(state)); |
242 | if (ret) | 254 | if (ret) |
243 | return ret; | 255 | return ret; |
244 | 256 | ||
@@ -252,7 +264,7 @@ static int hp_wmi_set_block(void *data, bool blocked) | |||
252 | int ret; | 264 | int ret; |
253 | 265 | ||
254 | ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, | 266 | ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1, |
255 | &query, sizeof(query)); | 267 | &query, sizeof(query), 0); |
256 | if (ret) | 268 | if (ret) |
257 | return -EINVAL; | 269 | return -EINVAL; |
258 | return 0; | 270 | return 0; |
@@ -267,7 +279,8 @@ static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) | |||
267 | int wireless = 0; | 279 | int wireless = 0; |
268 | int mask; | 280 | int mask; |
269 | hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, | 281 | hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, |
270 | &wireless, sizeof(wireless)); | 282 | &wireless, sizeof(wireless), |
283 | sizeof(wireless)); | ||
271 | /* TBD: Pass error */ | 284 | /* TBD: Pass error */ |
272 | 285 | ||
273 | mask = 0x200 << (r * 8); | 286 | mask = 0x200 << (r * 8); |
@@ -283,7 +296,8 @@ static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) | |||
283 | int wireless = 0; | 296 | int wireless = 0; |
284 | int mask; | 297 | int mask; |
285 | hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, | 298 | hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, |
286 | &wireless, sizeof(wireless)); | 299 | &wireless, sizeof(wireless), |
300 | sizeof(wireless)); | ||
287 | /* TBD: Pass error */ | 301 | /* TBD: Pass error */ |
288 | 302 | ||
289 | mask = 0x800 << (r * 8); | 303 | mask = 0x800 << (r * 8); |
@@ -344,7 +358,7 @@ static ssize_t set_als(struct device *dev, struct device_attribute *attr, | |||
344 | { | 358 | { |
345 | u32 tmp = simple_strtoul(buf, NULL, 10); | 359 | u32 tmp = simple_strtoul(buf, NULL, 10); |
346 | int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, | 360 | int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp, |
347 | sizeof(tmp)); | 361 | sizeof(tmp), sizeof(tmp)); |
348 | if (ret) | 362 | if (ret) |
349 | return -EINVAL; | 363 | return -EINVAL; |
350 | 364 | ||
@@ -417,6 +431,7 @@ static void hp_wmi_notify(u32 value, void *context) | |||
417 | case HPWMI_BEZEL_BUTTON: | 431 | case HPWMI_BEZEL_BUTTON: |
418 | ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, | 432 | ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, |
419 | &key_code, | 433 | &key_code, |
434 | sizeof(key_code), | ||
420 | sizeof(key_code)); | 435 | sizeof(key_code)); |
421 | if (ret) | 436 | if (ret) |
422 | break; | 437 | break; |
@@ -523,7 +538,7 @@ static int __devinit hp_wmi_bios_setup(struct platform_device *device) | |||
523 | int wireless = 0; | 538 | int wireless = 0; |
524 | 539 | ||
525 | err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless, | 540 | err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless, |
526 | sizeof(wireless)); | 541 | sizeof(wireless), sizeof(wireless)); |
527 | if (err) | 542 | if (err) |
528 | return err; | 543 | return err; |
529 | 544 | ||