aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/ec.c
diff options
context:
space:
mode:
authorLennart Poettering <mzxreary@0pointer.de>2007-05-04 08:16:19 -0400
committerLen Brown <len.brown@intel.com>2007-05-10 03:52:22 -0400
commit00eb43a1897a8845d0edb198cec69ac5f1f299dd (patch)
tree32cab402e51882c7854eab20556f0da75525cdc7 /drivers/acpi/ec.c
parenta64e62a07097f67108f0b68bc15216c3a4a5299b (diff)
acpi,msi-laptop: Fall back to EC polling mode for MSI laptop specific EC commands
The ACPI EC that is used in MSI laptops knows some non-standard commands for changing the screen brighntess and a few other things, which are used by the msi-laptop.c driver. Unfortunately for these commands no GPE events for IBF and OBF are triggered. Since nowadays the EC code uses the ec_intr=1 mode by default, this causes these operations to timeout, although they don't fail. In result, all operations that you can do with the msi-laptop.c driver take more or less 1s to complete, which is awfully slow. In one of the more recent kernels (2.6.20?) the EC subsystem has been revamped. With that change the EC timeout has been increased. before that increase the MSI EC accesses were slow -- but not *that* slow, hence I took notice of this limitation of the MSI EC hardware only very recently. The standard EC operations on the MSI EC as defined in the ACPI spec support GPE events properly. The following patch adds a new argument "force_poll" to the ec_transaction() function (and friends). If set to 1, the function will poll for IBF/OBF even if ec_intr=1 is enabled. If set to 0 the current behaviour is used. The msi-laptop driver is modified to make use of this new flag, so that OBF/IBF is polled for the special MSI EC transactions -- but only for them. Signed-off-by: Lennart Poettering <mzxreary@0pointer.de> Acked-by: Alexey Starikovskiy <aystarik@gmail.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/ec.c')
-rw-r--r--drivers/acpi/ec.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index e08cf98f504f..82f496c07675 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -147,9 +147,10 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event,
147 return 0; 147 return 0;
148} 148}
149 149
150static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count) 150static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event,
151 unsigned count, int force_poll)
151{ 152{
152 if (acpi_ec_mode == EC_POLL) { 153 if (unlikely(force_poll) || acpi_ec_mode == EC_POLL) {
153 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); 154 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
154 while (time_before(jiffies, delay)) { 155 while (time_before(jiffies, delay)) {
155 if (acpi_ec_check_status(ec, event, 0)) 156 if (acpi_ec_check_status(ec, event, 0))
@@ -173,14 +174,15 @@ static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, unsigned count)
173 174
174static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, 175static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
175 const u8 * wdata, unsigned wdata_len, 176 const u8 * wdata, unsigned wdata_len,
176 u8 * rdata, unsigned rdata_len) 177 u8 * rdata, unsigned rdata_len,
178 int force_poll)
177{ 179{
178 int result = 0; 180 int result = 0;
179 unsigned count = atomic_read(&ec->event_count); 181 unsigned count = atomic_read(&ec->event_count);
180 acpi_ec_write_cmd(ec, command); 182 acpi_ec_write_cmd(ec, command);
181 183
182 for (; wdata_len > 0; --wdata_len) { 184 for (; wdata_len > 0; --wdata_len) {
183 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); 185 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
184 if (result) { 186 if (result) {
185 printk(KERN_ERR PREFIX 187 printk(KERN_ERR PREFIX
186 "write_cmd timeout, command = %d\n", command); 188 "write_cmd timeout, command = %d\n", command);
@@ -191,7 +193,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
191 } 193 }
192 194
193 if (!rdata_len) { 195 if (!rdata_len) {
194 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count); 196 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, count, force_poll);
195 if (result) { 197 if (result) {
196 printk(KERN_ERR PREFIX 198 printk(KERN_ERR PREFIX
197 "finish-write timeout, command = %d\n", command); 199 "finish-write timeout, command = %d\n", command);
@@ -202,7 +204,7 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
202 } 204 }
203 205
204 for (; rdata_len > 0; --rdata_len) { 206 for (; rdata_len > 0; --rdata_len) {
205 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count); 207 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, count, force_poll);
206 if (result) { 208 if (result) {
207 printk(KERN_ERR PREFIX "read timeout, command = %d\n", 209 printk(KERN_ERR PREFIX "read timeout, command = %d\n",
208 command); 210 command);
@@ -217,7 +219,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
217 219
218static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, 220static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
219 const u8 * wdata, unsigned wdata_len, 221 const u8 * wdata, unsigned wdata_len,
220 u8 * rdata, unsigned rdata_len) 222 u8 * rdata, unsigned rdata_len,
223 int force_poll)
221{ 224{
222 int status; 225 int status;
223 u32 glk; 226 u32 glk;
@@ -240,7 +243,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
240 /* Make sure GPE is enabled before doing transaction */ 243 /* Make sure GPE is enabled before doing transaction */
241 acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); 244 acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR);
242 245
243 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); 246 status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0, 0);
244 if (status) { 247 if (status) {
245 printk(KERN_DEBUG PREFIX 248 printk(KERN_DEBUG PREFIX
246 "input buffer is not empty, aborting transaction\n"); 249 "input buffer is not empty, aborting transaction\n");
@@ -249,7 +252,8 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
249 252
250 status = acpi_ec_transaction_unlocked(ec, command, 253 status = acpi_ec_transaction_unlocked(ec, command,
251 wdata, wdata_len, 254 wdata, wdata_len,
252 rdata, rdata_len); 255 rdata, rdata_len,
256 force_poll);
253 257
254 end: 258 end:
255 259
@@ -267,12 +271,12 @@ static int acpi_ec_transaction(struct acpi_ec *ec, u8 command,
267int acpi_ec_burst_enable(struct acpi_ec *ec) 271int acpi_ec_burst_enable(struct acpi_ec *ec)
268{ 272{
269 u8 d; 273 u8 d;
270 return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1); 274 return acpi_ec_transaction(ec, ACPI_EC_BURST_ENABLE, NULL, 0, &d, 1, 0);
271} 275}
272 276
273int acpi_ec_burst_disable(struct acpi_ec *ec) 277int acpi_ec_burst_disable(struct acpi_ec *ec)
274{ 278{
275 return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0); 279 return acpi_ec_transaction(ec, ACPI_EC_BURST_DISABLE, NULL, 0, NULL, 0, 0);
276} 280}
277 281
278static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) 282static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
@@ -281,7 +285,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data)
281 u8 d; 285 u8 d;
282 286
283 result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ, 287 result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_READ,
284 &address, 1, &d, 1); 288 &address, 1, &d, 1, 0);
285 *data = d; 289 *data = d;
286 return result; 290 return result;
287} 291}
@@ -290,7 +294,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data)
290{ 294{
291 u8 wdata[2] = { address, data }; 295 u8 wdata[2] = { address, data };
292 return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE, 296 return acpi_ec_transaction(ec, ACPI_EC_COMMAND_WRITE,
293 wdata, 2, NULL, 0); 297 wdata, 2, NULL, 0, 0);
294} 298}
295 299
296/* 300/*
@@ -349,13 +353,15 @@ EXPORT_SYMBOL(ec_write);
349 353
350int ec_transaction(u8 command, 354int ec_transaction(u8 command,
351 const u8 * wdata, unsigned wdata_len, 355 const u8 * wdata, unsigned wdata_len,
352 u8 * rdata, unsigned rdata_len) 356 u8 * rdata, unsigned rdata_len,
357 int force_poll)
353{ 358{
354 if (!first_ec) 359 if (!first_ec)
355 return -ENODEV; 360 return -ENODEV;
356 361
357 return acpi_ec_transaction(first_ec, command, wdata, 362 return acpi_ec_transaction(first_ec, command, wdata,
358 wdata_len, rdata, rdata_len); 363 wdata_len, rdata, rdata_len,
364 force_poll);
359} 365}
360 366
361EXPORT_SYMBOL(ec_transaction); 367EXPORT_SYMBOL(ec_transaction);
@@ -374,7 +380,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data)
374 * bit to be cleared (and thus clearing the interrupt source). 380 * bit to be cleared (and thus clearing the interrupt source).
375 */ 381 */
376 382
377 result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1); 383 result = acpi_ec_transaction(ec, ACPI_EC_COMMAND_QUERY, NULL, 0, &d, 1, 0);
378 if (result) 384 if (result)
379 return result; 385 return result;
380 386
@@ -410,6 +416,7 @@ static u32 acpi_ec_gpe_handler(void *data)
410 acpi_status status = AE_OK; 416 acpi_status status = AE_OK;
411 u8 value; 417 u8 value;
412 struct acpi_ec *ec = data; 418 struct acpi_ec *ec = data;
419
413 atomic_inc(&ec->event_count); 420 atomic_inc(&ec->event_count);
414 421
415 if (acpi_ec_mode == EC_INTR) { 422 if (acpi_ec_mode == EC_INTR) {