/** * mei_txe_input_payload_write - write a dword to the host buffer * at offset idx * * @dev: the device structure * @idx: index in the host buffer * @value: value */ static void mei_txe_input_payload_write(struct mei_device *dev, unsigned long idx, u32 value) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_txe_sec_reg_write(hw, SEC_IPC_INPUT_PAYLOAD_REG + (idx * sizeof(u32)), value); }
static int mei_alloc_dma(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); hw->pool_size = SZ_4M; dev_dbg(&dev->pdev->dev, "MEIMM: dma size %zd\n", hw->pool_size); if (hw->pool_size == 0) return 0; /* Limit pools size to satt max range */ hw->pool_size = min_t(size_t, hw->pool_size, SATT_RANGE_MAX); hw->pool_vaddr = dma_alloc_coherent(&dev->pdev->dev, hw->pool_size, &hw->pool_paddr, GFP_KERNEL); dev_dbg(&dev->pdev->dev, "DMA Memory Allocated vaddr=%p, paddr=%lu, size=%zd\n", hw->pool_vaddr, (unsigned long)hw->pool_paddr, hw->pool_size); if (!hw->pool_vaddr) { dev_err(&dev->pdev->dev, "DMA Memory Allocation failed for size %zd\n", hw->pool_size); return -ENOMEM; } if (hw->pool_paddr & ~DMA_BIT_MASK(36)) { dev_err(&dev->pdev->dev, "Phys Address is beyond DMA_MASK(32) 0x%0lX\n", (unsigned long)hw->pool_paddr); } hw->pool_release = mei_free_dma; return 0; }
/** * mei_txe_readiness_clear - clear host readiness bit * * @dev: the device structure */ static void mei_txe_readiness_clear(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_txe_br_reg_write(hw, SICR_HOST_IPC_READINESS_REQ_REG, SICR_HOST_IPC_READINESS_RDY_CLR); }
/** * mei_txe_aliveness_req_get - get aliveness requested register value * * @dev: the device structure * * Extract HICR_HOST_ALIVENESS_RESP_ACK bit from * from HICR_HOST_ALIVENESS_REQ register value */ static u32 mei_txe_aliveness_req_get(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 reg; reg = mei_txe_br_reg_read(hw, SICR_HOST_ALIVENESS_REQ_REG); return reg & SICR_HOST_ALIVENESS_REQ_REQUESTED; }
/** * mei_txe_intr_disable - disable all interrupts * * @dev: the device structure */ static void mei_txe_intr_disable(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_txe_br_reg_write(hw, HHIER_REG, 0); mei_txe_br_reg_write(hw, HIER_REG, 0); }
/** * mei_txe_intr_enable - enable all interrupts * * @dev: the device structure */ static void mei_txe_intr_enable(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_txe_br_reg_write(hw, HHIER_REG, IPC_HHIER_MSK); mei_txe_br_reg_write(hw, HIER_REG, HIER_INT_EN_MSK); }
/** * mei_txe_out_data_read - read dword from the device buffer * at offset idx * * @dev: the device structure * @idx: index in the device buffer * * returns register value at index */ static u32 mei_txe_out_data_read(const struct mei_device *dev, unsigned long idx) { struct mei_txe_hw *hw = to_txe_hw(dev); return mei_txe_br_reg_read(hw, BRIDGE_IPC_OUTPUT_PAYLOAD_REG + (idx * sizeof(u32))); }
/** * mei_txe_readiness_set_host_rdy * * @dev: the device structure */ static void mei_txe_readiness_set_host_rdy(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_txe_br_reg_write(hw, SICR_HOST_IPC_READINESS_REQ_REG, SICR_HOST_IPC_READINESS_HOST_RDY); }
/** * mei_txe_read - reads a message from the txe device. * * @dev: the device structure * @buf: message buffer will be written * @len: message size will be read * * returns -EINVAL on error wrong argument and 0 on success */ static int mei_txe_read(struct mei_device *dev, unsigned char *buf, unsigned long len) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 i; u32 *reg_buf = (u32 *)buf; u32 rem = len & 0x3; if (WARN_ON(!buf || !len)) return -EINVAL; dev_dbg(&dev->pdev->dev, "buffer-length = %lu buf[0]0x%08X\n", len, mei_txe_out_data_read(dev, 0)); for (i = 0; i < len / 4; i++) { /* skip header: index starts from 1 */ u32 reg = mei_txe_out_data_read(dev, i + 1); dev_dbg(&dev->pdev->dev, "buf[%d] = 0x%08X\n", i, reg); *reg_buf++ = reg; } if (rem) { u32 reg = mei_txe_out_data_read(dev, i + 1); memcpy(reg_buf, ®, rem); } mei_txe_output_ready_set(hw); return 0; }
int mei_txe_dma_setup(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); int err; err = mei_reserver_dma_acpi(dev); if (err) err = mei_alloc_dma(dev); if (err) return err; err = mei_txe_setup_satt2(dev, dma_to_phys(&dev->pdev->dev, hw->pool_paddr), hw->pool_size); if (err) { if (hw->pool_release) hw->pool_release(hw); return err; } hw->mdev = mei_mm_init(&dev->pdev->dev, hw->pool_vaddr, hw->pool_paddr, hw->pool_size); if (IS_ERR_OR_NULL(hw->mdev)) return PTR_ERR(hw->mdev); return 0; }
/** * mei_txe_host_is_ready - check if the host is ready * * @dev: the device structure * * Return: true if host is ready */ static inline bool mei_txe_host_is_ready(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 reg = mei_txe_br_reg_read(hw, HICR_SEC_IPC_READINESS_REG); return !!(reg & HICR_SEC_IPC_READINESS_HOST_RDY); }
/** * mei_txe_aliveness_get - get aliveness response register value * @dev: the device structure * * Extract HICR_HOST_ALIVENESS_RESP_ACK bit * from HICR_HOST_ALIVENESS_RESP register value */ static u32 mei_txe_aliveness_get(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 reg; reg = mei_txe_br_reg_read(hw, HICR_HOST_ALIVENESS_RESP_REG); return reg & HICR_HOST_ALIVENESS_RESP_ACK; }
/** * mei_txe_setup_satt2 - SATT2 configuration for DMA support. * * @dev: the device structure * @addr: physical address start of the range * @range: physical range size */ int mei_txe_setup_satt2(struct mei_device *dev, phys_addr_t addr, u32 range) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 lo32 = lower_32_bits(addr); u32 hi32 = upper_32_bits(addr); u32 ctrl; /* SATT is limited to 36 Bits */ if (hi32 & ~0xF) return -EINVAL; /* SATT has to be 16Byte aligned */ if (lo32 & 0xF) return -EINVAL; /* SATT range has to be 4Bytes aligned */ if (range & 0x4) return -EINVAL; /* SATT is limited to 32 MB range*/ if (range > SATT_RANGE_MAX) return -EINVAL; ctrl = SATT2_CTRL_VALID_MSK; ctrl |= hi32 << SATT2_CTRL_BR_BASE_ADDR_REG_SHIFT; mei_txe_br_reg_write(hw, SATT2_SAP_SIZE_REG, range); mei_txe_br_reg_write(hw, SATT2_BRG_BA_LSB_REG, lo32); mei_txe_br_reg_write(hw, SATT2_CTRL_REG, ctrl); dev_dbg(&dev->pdev->dev, "SATT2: SAP_SIZE_OFFSET=0x%08X, BRG_BA_LSB_OFFSET=0x%08X, CTRL_OFFSET=0x%08X\n", range, lo32, ctrl); return 0; }
/** * mei_txe_aliveness_wait - waits for aliveness to settle * * @dev: the device structure * @expected: expected aliveness value * * Waits for HICR_HOST_ALIVENESS_RESP.ALIVENESS_RESP to be set * returns returns 0 on success and < 0 otherwise */ static int mei_txe_aliveness_wait(struct mei_device *dev, u32 expected) { struct mei_txe_hw *hw = to_txe_hw(dev); const unsigned long timeout = msecs_to_jiffies(SEC_ALIVENESS_WAIT_TIMEOUT); long err; int ret; hw->aliveness = mei_txe_aliveness_get(dev); if (hw->aliveness == expected) return 0; mutex_unlock(&dev->device_lock); err = wait_event_timeout(hw->wait_aliveness_resp, dev->pg_event == MEI_PG_EVENT_RECEIVED, timeout); mutex_lock(&dev->device_lock); hw->aliveness = mei_txe_aliveness_get(dev); ret = hw->aliveness == expected ? 0 : -ETIME; if (ret) dev_warn(&dev->pdev->dev, "aliveness timed out = %ld aliveness = %d event = %d\n", err, hw->aliveness, dev->pg_event); else dev_dbg(&dev->pdev->dev, "aliveness settled after = %d msec aliveness = %d event = %d\n", jiffies_to_msecs(timeout - err), hw->aliveness, dev->pg_event); dev->pg_event = MEI_PG_EVENT_IDLE; return ret; }
static acpi_status txei_walk_resource(struct acpi_resource *res, void *data) { struct mei_device *dev = (struct mei_device *)data; struct mei_txe_hw *hw = to_txe_hw(dev); struct acpi_resource_fixed_memory32 *fixmem32; if (res->type != ACPI_RESOURCE_TYPE_FIXED_MEMORY32) return AE_OK; fixmem32 = &res->data.fixed_memory32; dev_dbg(&dev->pdev->dev, "TXE8086 MEMORY32 addr 0x%x len %d\n", fixmem32->address, fixmem32->address_length); if (!fixmem32->address || !fixmem32->address_length) { dev_err(&dev->pdev->dev, "TXE8086 MEMORY32 addr 0x%x len %d\n", fixmem32->address, fixmem32->address_length); return AE_NO_MEMORY; } hw->pool_paddr = fixmem32->address; hw->pool_size = fixmem32->address_length; return AE_OK; }
/** * mei_txe_is_input_ready - check if TXE is ready for receiving data * * @dev: the device structure */ static bool mei_txe_is_input_ready(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 status; status = mei_txe_sec_reg_read(hw, SEC_IPC_INPUT_STATUS_REG); return !!(SEC_IPC_INPUT_STATUS_RDY & status); }
/** * mei_txe_intr_clear - clear all interrupts * * @dev: the device structure */ static inline void mei_txe_intr_clear(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_txe_sec_reg_write_silent(hw, SEC_IPC_HOST_INT_STATUS_REG, SEC_IPC_HOST_INT_STATUS_PENDING); mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_STS_MSK); mei_txe_br_reg_write(hw, HHISR_REG, IPC_HHIER_MSK); }
static int mei_txe_write(struct mei_device *dev, struct mei_msg_hdr *header, const unsigned char *buf) { struct mei_txe_hw *hw = to_txe_hw(dev); unsigned long rem; unsigned long length; int slots = dev->hbuf_depth; u32 *reg_buf = (u32 *)buf; u32 dw_cnt; int i; if (WARN_ON(!header || !buf)) return -EINVAL; length = header->length; dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header)); dw_cnt = mei_data2slots(length); if (dw_cnt > slots) return -EMSGSIZE; if (WARN(!hw->aliveness, "txe write: aliveness not asserted\n")) return -EAGAIN; /* Enable Input Ready Interrupt. */ mei_txe_input_ready_interrupt_enable(dev); if (!mei_txe_is_input_ready(dev)) { char fw_sts_str[MEI_FW_STATUS_STR_SZ]; mei_fw_status_str(dev, fw_sts_str, MEI_FW_STATUS_STR_SZ); dev_err(dev->dev, "Input is not ready %s\n", fw_sts_str); return -EAGAIN; } mei_txe_input_payload_write(dev, 0, *((u32 *)header)); for (i = 0; i < length / 4; i++) mei_txe_input_payload_write(dev, i + 1, reg_buf[i]); rem = length & 0x3; if (rem > 0) { u32 reg = 0; memcpy(®, &buf[length - rem], rem); mei_txe_input_payload_write(dev, i + 1, reg); } /* after each write the whole buffer is consumed */ hw->slots = 0; /* Set Input-Doorbell */ mei_txe_input_doorbell_set(hw); return 0; }
/** * mei_txe_input_ready_interrupt_enable - sets the Input Ready Interrupt * * @dev: the device structure */ static void mei_txe_input_ready_interrupt_enable(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 hintmsk; /* Enable the SEC_IPC_HOST_INT_MASK_IN_RDY interrupt */ hintmsk = mei_txe_sec_reg_read(hw, SEC_IPC_HOST_INT_MASK_REG); hintmsk |= SEC_IPC_HOST_INT_MASK_IN_RDY; mei_txe_sec_reg_write(hw, SEC_IPC_HOST_INT_MASK_REG, hintmsk); }
void mei_txe_dma_unset(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); mei_mm_deinit(hw->mdev); /* FIXME: do we need to unset satt2 ? */ if (hw->pool_release) hw->pool_release(hw); }
/** * mei_txe_hw_config - configure hardware at the start of the devices * * @dev: the device structure * * Configure hardware at the start of the device should be done only * once at the device probe time */ static void mei_txe_hw_config(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); /* Doesn't change in runtime */ dev->hbuf_depth = PAYLOAD_SIZE / 4; hw->aliveness = mei_txe_aliveness_get(dev); hw->readiness = mei_txe_readiness_get(dev); dev_dbg(&dev->pdev->dev, "aliveness_resp = 0x%08x, readiness = 0x%08x.\n", hw->aliveness, hw->readiness); }
/** * mei_txe_aliveness_set - request for aliveness change * * @dev: the device structure * @req: requested aliveness value * * Request for aliveness change and returns true if the change is * really needed and false if aliveness is already * in the requested state * Requires device lock to be held */ static bool mei_txe_aliveness_set(struct mei_device *dev, u32 req) { struct mei_txe_hw *hw = to_txe_hw(dev); bool do_req = hw->aliveness != req; dev_dbg(&dev->pdev->dev, "Aliveness current=%d request=%d\n", hw->aliveness, req); if (do_req) { dev->pg_event = MEI_PG_EVENT_WAIT; mei_txe_br_reg_write(hw, SICR_HOST_ALIVENESS_REQ_REG, req); } return do_req; }
/** * mei_txe_hw_start - start the hardware after reset * * @dev: the device structure * * Return: 0 on success an error code otherwise */ static int mei_txe_hw_start(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); int ret; u32 hisr; /* bring back interrupts */ mei_txe_intr_enable(dev); ret = mei_txe_readiness_wait(dev); if (ret < 0) { dev_err(dev->dev, "waiting for readiness failed\n"); return ret; } /* * If HISR.INT2_STS interrupt status bit is set then clear it. */ hisr = mei_txe_br_reg_read(hw, HISR_REG); if (hisr & HISR_INT_2_STS) mei_txe_br_reg_write(hw, HISR_REG, HISR_INT_2_STS); /* Clear the interrupt cause of OutputDoorbell */ clear_bit(TXE_INTR_OUT_DB_BIT, &hw->intr_cause); ret = mei_txe_aliveness_set_sync(dev, 1); if (ret < 0) { dev_err(dev->dev, "wait for aliveness failed ... bailing out\n"); return ret; } pm_runtime_set_active(dev->dev); /* enable input ready interrupts: * SEC_IPC_HOST_INT_MASK.IPC_INPUT_READY_INT_MASK */ mei_txe_input_ready_interrupt_enable(dev); /* Set the SICR_SEC_IPC_OUTPUT_STATUS.IPC_OUTPUT_READY bit */ mei_txe_output_ready_set(hw); /* Set bit SICR_HOST_IPC_READINESS.HOST_RDY */ mei_txe_readiness_set_host_rdy(dev); return 0; }
/** * mei_txe_check_and_ack_intrs - translate multi BAR interrupt into * single bit mask and acknowledge the interrupts * * @dev: the device structure * @do_ack: acknowledge interrupts * * Return: true if found interrupts to process. */ static bool mei_txe_check_and_ack_intrs(struct mei_device *dev, bool do_ack) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 hisr; u32 hhisr; u32 ipc_isr; u32 aliveness; bool generated; /* read interrupt registers */ hhisr = mei_txe_br_reg_read(hw, HHISR_REG); generated = (hhisr & IPC_HHIER_MSK); if (!generated) goto out; hisr = mei_txe_br_reg_read(hw, HISR_REG); aliveness = mei_txe_aliveness_get(dev); if (hhisr & IPC_HHIER_SEC && aliveness) { ipc_isr = mei_txe_sec_reg_read_silent(hw, SEC_IPC_HOST_INT_STATUS_REG); } else { ipc_isr = 0; hhisr &= ~IPC_HHIER_SEC; } generated = generated || (hisr & HISR_INT_STS_MSK) || (ipc_isr & SEC_IPC_HOST_INT_STATUS_PENDING); if (generated && do_ack) { /* Save the interrupt causes */ hw->intr_cause |= hisr & HISR_INT_STS_MSK; if (ipc_isr & SEC_IPC_HOST_INT_STATUS_IN_RDY) hw->intr_cause |= TXE_INTR_IN_READY; mei_txe_intr_disable(dev); /* Clear the interrupts in hierarchy: * IPC and Bridge, than the High Level */ mei_txe_sec_reg_write_silent(hw, SEC_IPC_HOST_INT_STATUS_REG, ipc_isr); mei_txe_br_reg_write(hw, HISR_REG, hisr); mei_txe_br_reg_write(hw, HHISR_REG, hhisr); } out: return generated; }
/** * mei_txe_hw_reset - resets host and fw. * * @dev: the device structure * @intr_enable: if interrupt should be enabled after reset. * * returns 0 on success and < 0 in case of error */ static int mei_txe_hw_reset(struct mei_device *dev, bool intr_enable) { struct mei_txe_hw *hw = to_txe_hw(dev); u32 aliveness_req; /* * read input doorbell to ensure consistency between Bridge and SeC * return value might be garbage return */ (void)mei_txe_sec_reg_read_silent(hw, SEC_IPC_INPUT_DOORBELL_REG); aliveness_req = mei_txe_aliveness_req_get(dev); hw->aliveness = mei_txe_aliveness_get(dev); /* Disable interrupts in this stage we will poll */ mei_txe_intr_disable(dev); /* * If Aliveness Request and Aliveness Response are not equal then * wait for them to be equal * Since we might have interrupts disabled - poll for it */ if (aliveness_req != hw->aliveness) if (mei_txe_aliveness_poll(dev, aliveness_req) < 0) { dev_err(&dev->pdev->dev, "wait for aliveness settle failed ... bailing out\n"); return -EIO; } /* * If Aliveness Request and Aliveness Response are set then clear them */ if (aliveness_req) { mei_txe_aliveness_set(dev, 0); if (mei_txe_aliveness_poll(dev, 0) < 0) { dev_err(&dev->pdev->dev, "wait for aliveness failed ... bailing out\n"); return -EIO; } } /* * Set rediness RDY_CLR bit */ mei_txe_readiness_clear(dev); return 0; }
/** * mei_txe_dev_init - allocates and initializes txe hardware specific structure * * @pdev: pci device * * Return: struct mei_device * on success or NULL */ struct mei_device *mei_txe_dev_init(struct pci_dev *pdev) { struct mei_device *dev; struct mei_txe_hw *hw; dev = kzalloc(sizeof(struct mei_device) + sizeof(struct mei_txe_hw), GFP_KERNEL); if (!dev) return NULL; mei_device_init(dev, &pdev->dev, &mei_txe_hw_ops); hw = to_txe_hw(dev); init_waitqueue_head(&hw->wait_aliveness_resp); return dev; }
/** * mei_txe_pending_interrupts - check if there are pending interrupts * only Aliveness, Input ready, and output doorbell are of relevance * * @dev: the device structure * * Checks if there are pending interrupts * only Aliveness, Readiness, Input ready, and Output doorbell are relevant */ static bool mei_txe_pending_interrupts(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); bool ret = (hw->intr_cause & (TXE_INTR_READINESS | TXE_INTR_ALIVENESS | TXE_INTR_IN_READY | TXE_INTR_OUT_DB)); if (ret) { dev_dbg(&dev->pdev->dev, "Pending Interrupts InReady=%01d Readiness=%01d, Aliveness=%01d, OutDoor=%01d\n", !!(hw->intr_cause & TXE_INTR_IN_READY), !!(hw->intr_cause & TXE_INTR_READINESS), !!(hw->intr_cause & TXE_INTR_ALIVENESS), !!(hw->intr_cause & TXE_INTR_OUT_DB)); } return ret; }
static int mei_txe_pci_resume(struct device *device) { struct pci_dev *pdev = to_pci_dev(device); struct mei_device *dev; struct mei_txe_hw *hw; int err; dev = pci_get_drvdata(pdev); if (!dev) return -ENODEV; pci_enable_msi(pdev); mei_clear_interrupts(dev); /* request and enable interrupt */ if (pci_dev_msi_enabled(pdev)) err = request_threaded_irq(pdev->irq, NULL, mei_txe_irq_thread_handler, IRQF_ONESHOT, KBUILD_MODNAME, dev); else err = request_threaded_irq(pdev->irq, mei_txe_irq_quick_handler, mei_txe_irq_thread_handler, IRQF_SHARED, KBUILD_MODNAME, dev); if (err) { dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n", pdev->irq); return err; } hw = to_txe_hw(dev); err = mei_txe_setup_satt2(dev, dma_to_phys(&dev->pdev->dev, hw->pool_paddr), hw->pool_size); if (err) return err; err = mei_restart(dev); return err; }
/** * mei_remove - Device Removal Routine * * @pdev: PCI device structure * * mei_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. */ static void mei_txe_remove(struct pci_dev *pdev) { struct mei_device *dev; struct mei_txe_hw *hw; dev = pci_get_drvdata(pdev); if (!dev) { dev_err(&pdev->dev, "mei: dev =NULL\n"); return; } pm_runtime_get_noresume(&pdev->dev); hw = to_txe_hw(dev); mei_stop(dev); if (!pci_dev_run_wake(pdev)) mei_txe_unset_pm_domain(dev); /* disable interrupts */ mei_disable_interrupts(dev); free_irq(pdev->irq, dev); pci_disable_msi(pdev); mei_mm_deinit(hw->mdev); if (hw->pool_release) hw->pool_release(hw); pci_set_drvdata(pdev, NULL); mei_txe_pci_iounmap(pdev, hw); mei_deregister(dev); kfree(dev); pci_release_regions(pdev); pci_disable_device(pdev); }
static int mei_reserver_dma_acpi(struct mei_device *dev) { struct mei_txe_hw *hw = to_txe_hw(dev); acpi_handle handle; acpi_status ret; handle = ACPI_HANDLE(&dev->pdev->dev); if (!handle) { dev_err(&dev->pdev->dev, "TXE8086 acpi NULL handle received\n"); return -ENODEV; } dev_dbg(&dev->pdev->dev, "TXE8086 acpi handle received\n"); ret = acpi_walk_resources(handle, METHOD_NAME__CRS, txei_walk_resource, dev); if (ACPI_FAILURE(ret)) { dev_err(&dev->pdev->dev, "TXE8086: acpi_walk_resources FAILURE\n"); return -ENOMEM; } if (!hw->pool_size) { dev_err(&dev->pdev->dev, "TXE8086: acpi __CRS resource not found\n"); return -ENOMEM; } dev_dbg(&dev->pdev->dev, "DMA Memory reserved memory usage: size=%zd\n", hw->pool_size); /* limit the pool_size to SATT_RANGE_MAX */ hw->pool_size = min_t(size_t, hw->pool_size, SATT_RANGE_MAX); hw->pool_vaddr = ioremap(hw->pool_paddr, hw->pool_size); /* FIXME: is this fatal ? */ if (!hw->pool_vaddr) dev_err(&dev->pdev->dev, "TXE8086: acpi __CRS cannot remap\n"); hw->pool_release = mei_release_dma_acpi; return 0; }