*************** *** 178,211 **** unsigned long flags; int ret = 0; spin_lock_irqsave(&ec->curr_lock, flags); - if (!ec->curr || (!ec->curr->wlen && !ec->curr->rlen)) ret = 1; spin_unlock_irqrestore(&ec->curr_lock, flags); return ret; } static void gpe_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; spin_lock_irqsave(&ec->curr_lock, flags); if (!ec->curr) goto unlock; - if (ec->curr->wlen > 0) { - if ((status & ACPI_EC_FLAG_IBF) == 0) { - acpi_ec_write_data(ec, *(ec->curr->wdata++)); - --ec->curr->wlen; - } else - /* false interrupt, state didn't change */ - ++ec->curr->irq_count; - - } else if (ec->curr->rlen > 0) { - if ((status & ACPI_EC_FLAG_OBF) == 1) { - *(ec->curr->rdata++) = acpi_ec_read_data(ec); - --ec->curr->rlen; - } else - /* false interrupt, state didn't change */ - ++ec->curr->irq_count; } unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } --- 180,226 ---- unsigned long flags; int ret = 0; spin_lock_irqsave(&ec->curr_lock, flags); + if (!ec->curr || + (ec->curr->wlen <= ec->curr->wi && + ec->curr->rlen <= ec->curr->ri)) ret = 1; spin_unlock_irqrestore(&ec->curr_lock, flags); return ret; } + static void start_transaction(struct acpi_ec *ec) + { + ec->curr->irq_count = ec->curr->wi = ec->curr->ri = 0; + acpi_ec_write_cmd(ec, ec->curr->command); + } + static void gpe_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; spin_lock_irqsave(&ec->curr_lock, flags); if (!ec->curr) goto unlock; + if (ec->curr->wlen > ec->curr->wi) { + if ((status & ACPI_EC_FLAG_IBF) == 0) + acpi_ec_write_data(ec, + ec->curr->wdata[ec->curr->wi++]); + else goto err; + + } else if (ec->curr->rlen > ec->curr->ri) { + if ((status & ACPI_EC_FLAG_OBF) == 1) + ec->curr->rdata[ec->curr->ri++] = + acpi_ec_read_data(ec); + else goto err; } + goto unlock; + err: + /* restart command */ + if (!status) { + pr_debug(PREFIX "controller reset, restart transaction\n"); + start_transaction(ec); + } else + /* false interrupt, state didn't change */ + ++ec->curr->irq_count; unlock: spin_unlock_irqrestore(&ec->curr_lock, flags); } *************** *** 268,276 **** /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ - t->irq_count = 0; ec->curr = t; - acpi_ec_write_cmd(ec, ec->curr->command); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); --- 283,290 ---- /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ ec->curr = t; + start_transaction(ec); if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp);