aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/ec.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 06b78e5e33a1..390f8f8666da 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -75,7 +75,8 @@ enum {
75 EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ 75 EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
76 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 76 EC_FLAGS_QUERY_PENDING, /* Query is pending */
77 EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ 77 EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
78 EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ 78 EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */
79 EC_FLAGS_ADDRESS, /* Address is being written */
79}; 80};
80 81
81static int acpi_ec_remove(struct acpi_device *device, int type); 82static int acpi_ec_remove(struct acpi_device *device, int type);
@@ -166,38 +167,45 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
166 167
167static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) 168static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
168{ 169{
170 int ret = 0;
171 if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) &&
172 test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags)))
173 force_poll = 1;
169 if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && 174 if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
170 likely(!force_poll)) { 175 likely(!force_poll)) {
171 if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), 176 if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
172 msecs_to_jiffies(ACPI_EC_DELAY))) 177 msecs_to_jiffies(ACPI_EC_DELAY)))
173 return 0; 178 goto end;
174 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); 179 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
175 if (acpi_ec_check_status(ec, event)) { 180 if (acpi_ec_check_status(ec, event)) {
176 if (event == ACPI_EC_EVENT_OBF_1) { 181 if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
177 /* miss OBF = 1 GPE, don't expect it anymore */ 182 /* miss address GPE, don't expect it anymore */
178 printk(KERN_INFO PREFIX "missing OBF_1 confirmation," 183 printk(KERN_INFO PREFIX "missing address confirmation,"
179 "switching to degraded mode.\n"); 184 "don't expect it any longer.\n");
180 set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); 185 set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags);
181 } else { 186 } else {
182 /* missing GPEs, switch back to poll mode */ 187 /* missing GPEs, switch back to poll mode */
183 printk(KERN_INFO PREFIX "missing IBF_1 confirmations," 188 printk(KERN_INFO PREFIX "missing confirmations,"
184 "switch off interrupt mode.\n"); 189 "switch off interrupt mode.\n");
185 clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); 190 clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
186 } 191 }
187 return 0; 192 goto end;
188 } 193 }
189 } else { 194 } else {
190 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); 195 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
191 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); 196 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
192 while (time_before(jiffies, delay)) { 197 while (time_before(jiffies, delay)) {
193 if (acpi_ec_check_status(ec, event)) 198 if (acpi_ec_check_status(ec, event))
194 return 0; 199 goto end;
195 } 200 }
196 } 201 }
197 printk(KERN_ERR PREFIX "acpi_ec_wait timeout," 202 printk(KERN_ERR PREFIX "acpi_ec_wait timeout,"
198 " status = %d, expect_event = %d\n", 203 " status = %d, expect_event = %d\n",
199 acpi_ec_read_status(ec), event); 204 acpi_ec_read_status(ec), event);
200 return -ETIME; 205 ret = -ETIME;
206 end:
207 clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
208 return ret;
201} 209}
202 210
203static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, 211static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
@@ -216,6 +224,9 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
216 "write_cmd timeout, command = %d\n", command); 224 "write_cmd timeout, command = %d\n", command);
217 goto end; 225 goto end;
218 } 226 }
227 /* mark the address byte written to EC */
228 if (rdata_len + wdata_len > 1)
229 set_bit(EC_FLAGS_ADDRESS, &ec->flags);
219 set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); 230 set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
220 acpi_ec_write_data(ec, *(wdata++)); 231 acpi_ec_write_data(ec, *(wdata++));
221 } 232 }
@@ -231,8 +242,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
231 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); 242 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
232 243
233 for (; rdata_len > 0; --rdata_len) { 244 for (; rdata_len > 0; --rdata_len) {
234 if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
235 force_poll = 1;
236 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); 245 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
237 if (result) { 246 if (result) {
238 printk(KERN_ERR PREFIX "read timeout, command = %d\n", 247 printk(KERN_ERR PREFIX "read timeout, command = %d\n",