/* read chunk of given fw_cfg blob (caller responsible for sanity-check) */ static inline void fw_cfg_read_blob(u16 key, void *buf, loff_t pos, size_t count) { u32 glk = -1U; acpi_status status; /* If we have ACPI, ensure mutual exclusion against any potential * device access by the firmware, e.g. via AML methods: */ status = acpi_acquire_global_lock(ACPI_WAIT_FOREVER, &glk); if (ACPI_FAILURE(status) && status != AE_NOT_CONFIGURED) { /* Should never get here */ WARN(1, "fw_cfg_read_blob: Failed to lock ACPI!\n"); memset(buf, 0, count); return; } mutex_lock(&fw_cfg_dev_lock); iowrite16(fw_cfg_sel_endianness(key), fw_cfg_reg_ctrl); while (pos-- > 0) ioread8(fw_cfg_reg_data); ioread8_rep(fw_cfg_reg_data, buf, count); mutex_unlock(&fw_cfg_dev_lock); acpi_release_global_lock(glk); }
static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) { int status; u32 glk; if (!ec || (!t) || (t->wlen && !t->wdata) || (t->rlen && !t->rdata)) return -EINVAL; if (t->rdata) memset(t->rdata, 0, t->rlen); mutex_lock(&ec->lock); if (test_bit(EC_FLAGS_BLOCKED, &ec->flags)) { status = -EINVAL; goto unlock; } if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { status = -ENODEV; goto unlock; } } if (ec_wait_ibf0(ec)) { pr_err(PREFIX "input buffer is not empty, " "aborting transaction\n"); status = -ETIME; goto end; } pr_debug(PREFIX "transaction start\n"); /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { /* It has to be disabled, so that it doesn't trigger. */ acpi_disable_gpe(NULL, ec->gpe); } status = acpi_ec_transaction_unlocked(ec, t); /* check if we received SCI during transaction */ ec_check_sci_sync(ec, acpi_ec_read_status(ec)); if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { msleep(1); /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { pr_info(PREFIX "GPE storm detected, " "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); } pr_debug(PREFIX "transaction end\n"); end: if (ec->global_lock) acpi_release_global_lock(glk); unlock: mutex_unlock(&ec->lock); return status; }
static int acpi_ec_write ( struct acpi_ec *ec, u8 address, u8 data) { int result = 0; acpi_status status = AE_OK; unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_write"); if (!ec) return_VALUE(-EINVAL); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } spin_lock_irqsave(&ec->lock, flags); acpi_hw_low_level_write(8, ACPI_EC_COMMAND_WRITE, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; acpi_hw_low_level_write(8, address, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; acpi_hw_low_level_write(8, data, &ec->data_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_IBE); if (result) goto end; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Wrote [%02x] to address [%02x]\n", data, address)); end: spin_unlock_irqrestore(&ec->lock, flags); if (ec->global_lock) acpi_release_global_lock(glk); return_VALUE(result); }
static int acpi_ec_query ( struct acpi_ec *ec, u32 *data) { int result = 0; acpi_status status = AE_OK; unsigned long flags = 0; u32 glk = 0; ACPI_FUNCTION_TRACE("acpi_ec_query"); if (!ec || !data) return_VALUE(-EINVAL); *data = 0; if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) return_VALUE(-ENODEV); } /* * Query the EC to find out which _Qxx method we need to evaluate. * Note that successful completion of the query causes the ACPI_EC_SCI * bit to be cleared (and thus clearing the interrupt source). */ spin_lock_irqsave(&ec->lock, flags); acpi_hw_low_level_write(8, ACPI_EC_COMMAND_QUERY, &ec->command_addr); result = acpi_ec_wait(ec, ACPI_EC_EVENT_OBF); if (result) goto end; acpi_hw_low_level_read(8, data, &ec->data_addr); if (!*data) result = -ENODATA; end: spin_unlock_irqrestore(&ec->lock, flags); if (ec->global_lock) acpi_release_global_lock(glk); return_VALUE(result); }
static int acpi_ec_transaction(struct acpi_ec *ec, u8 command, const u8 * wdata, unsigned wdata_len, u8 * rdata, unsigned rdata_len) { int status; u32 glk; if (!ec || (wdata_len && !wdata) || (rdata_len && !rdata)) return -EINVAL; if (rdata) memset(rdata, 0, rdata_len); mutex_lock(&ec->lock); if (ec->global_lock) { status = acpi_acquire_global_lock(ACPI_EC_UDELAY_GLK, &glk); if (ACPI_FAILURE(status)) { mutex_unlock(&ec->lock); return -ENODEV; } } /* Make sure GPE is enabled before doing transaction */ acpi_enable_gpe(NULL, ec->gpe, ACPI_NOT_ISR); status = acpi_ec_wait(ec, ACPI_EC_EVENT_IBF_0, 0); if (status) { printk(KERN_DEBUG PREFIX "input buffer is not empty, aborting transaction\n"); goto end; } status = acpi_ec_transaction_unlocked(ec, command, wdata, wdata_len, rdata, rdata_len); end: if (ec->global_lock) acpi_release_global_lock(glk); mutex_unlock(&ec->lock); return status; }