aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/ec.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 762b4cc9d7b1..f09386e9745f 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -78,6 +78,9 @@ enum {
78 EC_FLAGS_BLOCKED, /* Transactions are blocked */ 78 EC_FLAGS_BLOCKED, /* Transactions are blocked */
79}; 79};
80 80
81#define ACPI_EC_COMMAND_POLL 0x01 /* Available for command byte */
82#define ACPI_EC_COMMAND_COMPLETE 0x02 /* Completed last byte */
83
81/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */ 84/* ec.c is compiled in acpi namespace so this shows up as acpi.ec_delay param */
82static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; 85static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY;
83module_param(ec_delay, uint, 0644); 86module_param(ec_delay, uint, 0644);
@@ -109,7 +112,7 @@ struct transaction {
109 u8 ri; 112 u8 ri;
110 u8 wlen; 113 u8 wlen;
111 u8 rlen; 114 u8 rlen;
112 bool done; 115 u8 flags;
113}; 116};
114 117
115struct acpi_ec *boot_ec, *first_ec; 118struct acpi_ec *boot_ec, *first_ec;
@@ -150,63 +153,68 @@ static inline void acpi_ec_write_data(struct acpi_ec *ec, u8 data)
150 outb(data, ec->data_addr); 153 outb(data, ec->data_addr);
151} 154}
152 155
153static int ec_transaction_done(struct acpi_ec *ec) 156static int ec_transaction_completed(struct acpi_ec *ec)
154{ 157{
155 unsigned long flags; 158 unsigned long flags;
156 int ret = 0; 159 int ret = 0;
157 spin_lock_irqsave(&ec->lock, flags); 160 spin_lock_irqsave(&ec->lock, flags);
158 if (!ec->curr || ec->curr->done) 161 if (!ec->curr || (ec->curr->flags & ACPI_EC_COMMAND_COMPLETE))
159 ret = 1; 162 ret = 1;
160 spin_unlock_irqrestore(&ec->lock, flags); 163 spin_unlock_irqrestore(&ec->lock, flags);
161 return ret; 164 return ret;
162} 165}
163 166
164static void start_transaction(struct acpi_ec *ec)
165{
166 ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
167 ec->curr->done = false;
168 acpi_ec_write_cmd(ec, ec->curr->command);
169}
170
171static void advance_transaction(struct acpi_ec *ec) 167static void advance_transaction(struct acpi_ec *ec)
172{ 168{
173 unsigned long flags;
174 struct transaction *t; 169 struct transaction *t;
175 u8 status; 170 u8 status;
176 171
177 spin_lock_irqsave(&ec->lock, flags);
178 pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK"); 172 pr_debug("===== %s =====\n", in_interrupt() ? "IRQ" : "TASK");
179 status = acpi_ec_read_status(ec); 173 status = acpi_ec_read_status(ec);
180 t = ec->curr; 174 t = ec->curr;
181 if (!t) 175 if (!t)
182 goto unlock; 176 goto err;
183 if (t->wlen > t->wi) { 177 if (t->flags & ACPI_EC_COMMAND_POLL) {
184 if ((status & ACPI_EC_FLAG_IBF) == 0) 178 if (t->wlen > t->wi) {
185 acpi_ec_write_data(ec, 179 if ((status & ACPI_EC_FLAG_IBF) == 0)
186 t->wdata[t->wi++]); 180 acpi_ec_write_data(ec, t->wdata[t->wi++]);
187 else 181 else
188 goto err; 182 goto err;
189 } else if (t->rlen > t->ri) { 183 } else if (t->rlen > t->ri) {
190 if ((status & ACPI_EC_FLAG_OBF) == 1) { 184 if ((status & ACPI_EC_FLAG_OBF) == 1) {
191 t->rdata[t->ri++] = acpi_ec_read_data(ec); 185 t->rdata[t->ri++] = acpi_ec_read_data(ec);
192 if (t->rlen == t->ri) 186 if (t->rlen == t->ri)
193 t->done = true; 187 t->flags |= ACPI_EC_COMMAND_COMPLETE;
188 } else
189 goto err;
190 } else if (t->wlen == t->wi &&
191 (status & ACPI_EC_FLAG_IBF) == 0)
192 t->flags |= ACPI_EC_COMMAND_COMPLETE;
193 return;
194 } else {
195 if ((status & ACPI_EC_FLAG_IBF) == 0) {
196 acpi_ec_write_cmd(ec, t->command);
197 t->flags |= ACPI_EC_COMMAND_POLL;
194 } else 198 } else
195 goto err; 199 goto err;
196 } else if (t->wlen == t->wi && 200 return;
197 (status & ACPI_EC_FLAG_IBF) == 0) 201 }
198 t->done = true;
199 goto unlock;
200err: 202err:
201 /* 203 /*
202 * If SCI bit is set, then don't think it's a false IRQ 204 * If SCI bit is set, then don't think it's a false IRQ
203 * otherwise will take a not handled IRQ as a false one. 205 * otherwise will take a not handled IRQ as a false one.
204 */ 206 */
205 if (in_interrupt() && !(status & ACPI_EC_FLAG_SCI)) 207 if (!(status & ACPI_EC_FLAG_SCI)) {
206 ++t->irq_count; 208 if (in_interrupt() && t)
209 ++t->irq_count;
210 }
211}
207 212
208unlock: 213static void start_transaction(struct acpi_ec *ec)
209 spin_unlock_irqrestore(&ec->lock, flags); 214{
215 ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0;
216 ec->curr->flags = 0;
217 advance_transaction(ec);
210} 218}
211 219
212static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data); 220static int acpi_ec_sync_query(struct acpi_ec *ec, u8 *data);
@@ -231,15 +239,17 @@ static int ec_poll(struct acpi_ec *ec)
231 /* don't sleep with disabled interrupts */ 239 /* don't sleep with disabled interrupts */
232 if (EC_FLAGS_MSI || irqs_disabled()) { 240 if (EC_FLAGS_MSI || irqs_disabled()) {
233 udelay(ACPI_EC_MSI_UDELAY); 241 udelay(ACPI_EC_MSI_UDELAY);
234 if (ec_transaction_done(ec)) 242 if (ec_transaction_completed(ec))
235 return 0; 243 return 0;
236 } else { 244 } else {
237 if (wait_event_timeout(ec->wait, 245 if (wait_event_timeout(ec->wait,
238 ec_transaction_done(ec), 246 ec_transaction_completed(ec),
239 msecs_to_jiffies(1))) 247 msecs_to_jiffies(1)))
240 return 0; 248 return 0;
241 } 249 }
250 spin_lock_irqsave(&ec->lock, flags);
242 advance_transaction(ec); 251 advance_transaction(ec);
252 spin_unlock_irqrestore(&ec->lock, flags);
243 } while (time_before(jiffies, delay)); 253 } while (time_before(jiffies, delay));
244 pr_debug("controller reset, restart transaction\n"); 254 pr_debug("controller reset, restart transaction\n");
245 spin_lock_irqsave(&ec->lock, flags); 255 spin_lock_irqsave(&ec->lock, flags);
@@ -637,10 +647,13 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state)
637static u32 acpi_ec_gpe_handler(acpi_handle gpe_device, 647static u32 acpi_ec_gpe_handler(acpi_handle gpe_device,
638 u32 gpe_number, void *data) 648 u32 gpe_number, void *data)
639{ 649{
650 unsigned long flags;
640 struct acpi_ec *ec = data; 651 struct acpi_ec *ec = data;
641 652
653 spin_lock_irqsave(&ec->lock, flags);
642 advance_transaction(ec); 654 advance_transaction(ec);
643 if (ec_transaction_done(ec) && 655 spin_unlock_irqrestore(&ec->lock, flags);
656 if (ec_transaction_completed(ec) &&
644 (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { 657 (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) {
645 wake_up(&ec->wait); 658 wake_up(&ec->wait);
646 ec_check_sci(ec, acpi_ec_read_status(ec)); 659 ec_check_sci(ec, acpi_ec_read_status(ec));