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", |