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