aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorAlexey Starikovskiy <astarikovskiy@suse.de>2007-11-20 19:23:32 -0500
committerLen Brown <len.brown@intel.com>2007-11-20 20:06:15 -0500
commite790cc8bbb990df900eabdda18a5a480d22a60c8 (patch)
tree536d3bf16bb658817a1978bcc4270624f3661da0 /drivers/acpi
parent3ebe08a749a0971a5407818169dc16212ef562f9 (diff)
ACPI: EC: Workaround for optimized controllers (version 3)
Some controllers fail to send confirmation GPE after address or data write. Detect this and don't expect such confirmation in future. This is a generalization of previous workaround (66c5f4e7367b0085652931b2f3366de29e7ff5ec), which did only read address. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=9327 Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de> Tested-by: Romano Giannetti <romano.giannetti@gmail.com> Tested-by: Mats Johannesson Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/ec.c46
-rw-r--r--drivers/acpi/processor_core.c5
2 files changed, 37 insertions, 14 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index d5a5958d4b20..7d6b84119792 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -78,7 +78,10 @@ enum {
78 EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */ 78 EC_FLAGS_WAIT_GPE = 0, /* Don't check status until GPE arrives */
79 EC_FLAGS_QUERY_PENDING, /* Query is pending */ 79 EC_FLAGS_QUERY_PENDING, /* Query is pending */
80 EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */ 80 EC_FLAGS_GPE_MODE, /* Expect GPE to be sent for status change */
81 EC_FLAGS_ONLY_IBF_GPE, /* Expect GPE only for IBF = 0 event */ 81 EC_FLAGS_NO_ADDRESS_GPE, /* Expect GPE only for non-address event */
82 EC_FLAGS_ADDRESS, /* Address is being written */
83 EC_FLAGS_NO_WDATA_GPE, /* Don't expect WDATA GPE event */
84 EC_FLAGS_WDATA, /* Data is being written */
82}; 85};
83 86
84static int acpi_ec_remove(struct acpi_device *device, int type); 87static int acpi_ec_remove(struct acpi_device *device, int type);
@@ -175,39 +178,54 @@ static inline int acpi_ec_check_status(struct acpi_ec *ec, enum ec_event event)
175 178
176static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll) 179static int acpi_ec_wait(struct acpi_ec *ec, enum ec_event event, int force_poll)
177{ 180{
181 int ret = 0;
182 if (unlikely(test_bit(EC_FLAGS_ADDRESS, &ec->flags) &&
183 test_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags)))
184 force_poll = 1;
185 if (unlikely(test_bit(EC_FLAGS_WDATA, &ec->flags) &&
186 test_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags)))
187 force_poll = 1;
178 if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) && 188 if (likely(test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) &&
179 likely(!force_poll)) { 189 likely(!force_poll)) {
180 if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event), 190 if (wait_event_timeout(ec->wait, acpi_ec_check_status(ec, event),
181 msecs_to_jiffies(ACPI_EC_DELAY))) 191 msecs_to_jiffies(ACPI_EC_DELAY)))
182 return 0; 192 goto end;
183 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); 193 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
184 if (acpi_ec_check_status(ec, event)) { 194 if (acpi_ec_check_status(ec, event)) {
185 if (event == ACPI_EC_EVENT_OBF_1) { 195 if (test_bit(EC_FLAGS_ADDRESS, &ec->flags)) {
186 /* miss OBF = 1 GPE, don't expect it anymore */ 196 /* miss address GPE, don't expect it anymore */
187 pr_info(PREFIX "missing OBF_1 confirmation," 197 pr_info(PREFIX "missing address confirmation, "
188 "switching to degraded mode.\n"); 198 "don't expect it any longer.\n");
189 set_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags); 199 set_bit(EC_FLAGS_NO_ADDRESS_GPE, &ec->flags);
200 } else if (test_bit(EC_FLAGS_WDATA, &ec->flags)) {
201 /* miss write data GPE, don't expect it */
202 pr_info(PREFIX "missing write data confirmation, "
203 "don't expect it any longer.\n");
204 set_bit(EC_FLAGS_NO_WDATA_GPE, &ec->flags);
190 } else { 205 } else {
191 /* missing GPEs, switch back to poll mode */ 206 /* missing GPEs, switch back to poll mode */
192 if (printk_ratelimit()) 207 if (printk_ratelimit())
193 pr_info(PREFIX "missing IBF_1 confirmations," 208 pr_info(PREFIX "missing confirmations, "
194 "switch off interrupt mode.\n"); 209 "switch off interrupt mode.\n");
195 clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); 210 clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
196 } 211 }
197 return 0; 212 goto end;
198 } 213 }
199 } else { 214 } else {
200 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); 215 unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY);
201 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags); 216 clear_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
202 while (time_before(jiffies, delay)) { 217 while (time_before(jiffies, delay)) {
203 if (acpi_ec_check_status(ec, event)) 218 if (acpi_ec_check_status(ec, event))
204 return 0; 219 goto end;
205 } 220 }
206 } 221 }
207 pr_err(PREFIX "acpi_ec_wait timeout," 222 pr_err(PREFIX "acpi_ec_wait timeout,"
208 " status = %d, expect_event = %d\n", 223 " status = %d, expect_event = %d\n",
209 acpi_ec_read_status(ec), event); 224 acpi_ec_read_status(ec), event);
210 return -ETIME; 225 ret = -ETIME;
226 end:
227 clear_bit(EC_FLAGS_ADDRESS, &ec->flags);
228 return ret;
211} 229}
212 230
213static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command, 231static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
@@ -226,11 +244,15 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
226 "write_cmd timeout, command = %d\n", command); 244 "write_cmd timeout, command = %d\n", command);
227 goto end; 245 goto end;
228 } 246 }
247 /* mark the address byte written to EC */
248 if (rdata_len + wdata_len > 1)
249 set_bit(EC_FLAGS_ADDRESS, &ec->flags);
229 set_bit(EC_FLAGS_WAIT_GPE, &ec->flags); 250 set_bit(EC_FLAGS_WAIT_GPE, &ec->flags);
230 acpi_ec_write_data(ec, *(wdata++)); 251 acpi_ec_write_data(ec, *(wdata++));
231 } 252 }
232 253
233 if (!rdata_len) { 254 if (!rdata_len) {
255 set_bit(EC_FLAGS_WDATA, &ec->flags);
234 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll); 256 result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, force_poll);
235 if (result) { 257 if (result) {
236 pr_err(PREFIX 258 pr_err(PREFIX
@@ -241,8 +263,6 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, u8 command,
241 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); 263 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags);
242 264
243 for (; rdata_len > 0; --rdata_len) { 265 for (; rdata_len > 0; --rdata_len) {
244 if (test_bit(EC_FLAGS_ONLY_IBF_GPE, &ec->flags))
245 force_poll = 1;
246 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll); 266 result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF_1, force_poll);
247 if (result) { 267 if (result) {
248 pr_err(PREFIX "read timeout, command = %d\n", command); 268 pr_err(PREFIX "read timeout, command = %d\n", command);
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 235a51e328c3..692b2a0a05b2 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -684,7 +684,7 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
684{ 684{
685 struct acpi_processor *pr = data; 685 struct acpi_processor *pr = data;
686 struct acpi_device *device = NULL; 686 struct acpi_device *device = NULL;
687 687 int saved;
688 688
689 if (!pr) 689 if (!pr)
690 return; 690 return;
@@ -694,7 +694,10 @@ static void acpi_processor_notify(acpi_handle handle, u32 event, void *data)
694 694
695 switch (event) { 695 switch (event) {
696 case ACPI_PROCESSOR_NOTIFY_PERFORMANCE: 696 case ACPI_PROCESSOR_NOTIFY_PERFORMANCE:
697 saved = pr->performance_platform_limit;
697 acpi_processor_ppc_has_changed(pr); 698 acpi_processor_ppc_has_changed(pr);
699 if (saved == pr->performance_platform_limit)
700 break;
698 acpi_bus_generate_proc_event(device, event, 701 acpi_bus_generate_proc_event(device, event,
699 pr->performance_platform_limit); 702 pr->performance_platform_limit);
700 acpi_bus_generate_netlink_event(device->pnp.device_class, 703 acpi_bus_generate_netlink_event(device->pnp.device_class,