Exemplo n.º 1
0
/**
 * 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);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
/**
 * 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);
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
0
/**
 * 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)));
}
Exemplo n.º 8
0
/**
 * 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);
}
Exemplo n.º 9
0
/**
 * 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, &reg, rem);
	}

	mei_txe_output_ready_set(hw);
	return 0;
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
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);
}
Exemplo n.º 12
0
/**
 * 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;
}
Exemplo n.º 13
0
/**
 * 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;
}
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
/**
 * 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);
}
Exemplo n.º 17
0
/**
 * 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);
}
Exemplo n.º 18
0
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(&reg, &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;
}
Exemplo n.º 19
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);
}
Exemplo n.º 20
0
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);
}
Exemplo n.º 21
0
/**
 *  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);
}
Exemplo n.º 22
0
/**
 * 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;
}
Exemplo n.º 23
0
/**
 * 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;
}
Exemplo n.º 24
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;
}
Exemplo n.º 25
0
/**
 * 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;
}
Exemplo n.º 26
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;
}
Exemplo n.º 27
0
/**
 * 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;
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
/**
 * 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);
}
Exemplo n.º 30
0
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;
}