예제 #1
0
/**
 * mic_ack_interrupt - Device specific interrupt handling.
 * @mdev: pointer to mic_device instance
 *
 * Returns: bitmask of doorbell events triggered.
 */
static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
{
	u32 reg = 0;
	struct mic_mw *mw = &mdev->mmio;
	u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;

	/* Clear pending bit array. */
	if (MIC_A0_STEP == mdev->stepping)
		mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
			MIC_X100_SBOX_MSIXPBACR);

	if (mdev->irq_info.num_vectors <= 1) {
		reg = mic_mmio_read(mw, sicr0);

		if (unlikely(!reg))
			goto done;

		mic_mmio_write(mw, reg, sicr0);
	}

	if (mdev->stepping >= MIC_B0_STEP)
		mdev->intr_ops->enable_interrupts(mdev);
done:
	return reg;
}
예제 #2
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_ack_interrupt - Read the interrupt sources register and
 * clear it. This function will be called in the MSI/INTx case.
 * @mdev: Pointer to mic_device instance.
 *
 * Returns: bitmask of interrupt sources triggered.
 */
static u32 mic_x100_ack_interrupt(struct mic_device *mdev)
{
	u32 sicr0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICR0;
	u32 reg = mic_mmio_read(&mdev->mmio, sicr0);
	mic_mmio_write(&mdev->mmio, reg, sicr0);
	return reg;
}
예제 #3
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_write_spad - write to the scratchpad register
 * @mdev: pointer to mic_device instance
 * @idx: index to the scratchpad register, 0 based
 * @val: the data value to put into the register
 *
 * This function allows writing of a 32bit value to the indexed scratchpad
 * register.
 *
 * RETURNS: none.
 */
static void
mic_x100_write_spad(struct mic_device *mdev, unsigned int idx, u32 val)
{
	dev_dbg(mdev->sdev->parent, "Writing 0x%x to scratch pad index %d\n",
		val, idx);
	mic_mmio_write(&mdev->mmio, val,
		       MIC_X100_SBOX_BASE_ADDRESS +
		       MIC_X100_SBOX_SPAD0 + idx * 4);
}
예제 #4
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_send_rdmasr_intr - Send an RDMASR interrupt to MIC.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_send_rdmasr_intr(struct mic_device *mdev,
			int doorbell)
{
	int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
	wmb();
	mic_mmio_write(&mdev->mmio, 0,
		       MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
}
예제 #5
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_disable_interrupts - Disable interrupts.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_disable_interrupts(struct mic_device *mdev)
{
	u32 reg;
	struct mic_mw *mw = &mdev->mmio;
	u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
	u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;
	u32 sicc0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICC0;

	reg = mic_mmio_read(mw, sice0);
	mic_mmio_write(mw, reg, sicc0);

	if (mdev->irq_info.num_vectors > 1) {
		reg = mic_mmio_read(mw, siac0);
		reg &= ~(MIC_X100_SBOX_DBR_BITS(0xf) |
			MIC_X100_SBOX_DMA_BITS(0xff));
		mic_mmio_write(mw, reg, siac0);
	}
}
예제 #6
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_send_firmware_intr - Send an interrupt to the firmware on MIC.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_send_firmware_intr(struct mic_device *mdev)
{
	u32 apicicr_low;
	u64 apic_icr_offset = MIC_X100_SBOX_APICICR7;
	int vector = MIC_X100_BSP_INTERRUPT_VECTOR;
	struct mic_mw *mw = &mdev->mmio;

	/*
	 * For MIC we need to make sure we "hit"
	 * the send_icr bit (13).
	 */
	apicicr_low = (vector | (1 << 13));

	mic_mmio_write(mw, mic_x100_get_apic_id(mdev),
		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset + 4);

	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
	wmb();
	mic_mmio_write(mw, apicicr_low,
		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
}
예제 #7
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_intr_workarounds - These hardware specific workarounds are
 * to be invoked everytime an interrupt is handled.
 * @mdev: Pointer to mic_device instance.
 *
 * Returns: none
 */
static void mic_x100_intr_workarounds(struct mic_device *mdev)
{
	struct mic_mw *mw = &mdev->mmio;

	/* Clear pending bit array. */
	if (MIC_A0_STEP == mdev->stepping)
		mic_mmio_write(mw, 1, MIC_X100_SBOX_BASE_ADDRESS +
			MIC_X100_SBOX_MSIXPBACR);

	if (mdev->stepping >= MIC_B0_STEP)
		mdev->intr_ops->enable_interrupts(mdev);
}
예제 #8
0
파일: mic_x100.c 프로젝트: 020gzh/linux
static void mic_x100_send_rdmasr_intr(struct mic_mw *mw, int doorbell)
{
	int rdmasr_offset = MIC_X100_SBOX_RDMASR0 + (doorbell << 2);
	/*
	 * Ensure that the interrupt is ordered w.r.t. previous stores
	 * to main memory. Fence instructions are not implemented in X100
	 * since execution is in order but a compiler barrier is still
	 * required.
	 */
	wmb();
	mic_mmio_write(mw, 0, MIC_X100_SBOX_BASE_ADDRESS + rdmasr_offset);
}
예제 #9
0
파일: mic_x100.c 프로젝트: 020gzh/linux
/**
 * __mic_send_intr - Send interrupt to Host.
 * @mdev: pointer to mic_device instance
 * @doorbell: Doorbell number.
 */
void mic_send_intr(struct mic_device *mdev, int doorbell)
{
	struct mic_mw *mw = &mdev->mmio;

	if (doorbell > MIC_X100_MAX_DOORBELL_IDX)
		return;
	/* Ensure that the interrupt is ordered w.r.t previous stores. */
	wmb();
	mic_mmio_write(mw, MIC_X100_SBOX_SDBIC0_DBREQ_BIT,
		       MIC_X100_SBOX_BASE_ADDRESS +
		       (MIC_X100_SBOX_SDBIC0 + (4 * doorbell)));
}
예제 #10
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_enable_interrupts - Enable interrupts.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_enable_interrupts(struct mic_device *mdev)
{
	u32 reg;
	struct mic_mw *mw = &mdev->mmio;
	u32 sice0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SICE0;
	u32 siac0 = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_SIAC0;

	reg = mic_mmio_read(mw, sice0);
	reg |= MIC_X100_SBOX_DBR_BITS(0xf) | MIC_X100_SBOX_DMA_BITS(0xff);
	mic_mmio_write(mw, reg, sice0);

	/*
	 * Enable auto-clear when enabling interrupts. Applicable only for
	 * MSI-x. Legacy and MSI mode cannot have auto-clear enabled.
	 */
	if (mdev->irq_info.num_vectors > 1) {
		reg = mic_mmio_read(mw, siac0);
		reg |= MIC_X100_SBOX_DBR_BITS(0xf) |
			MIC_X100_SBOX_DMA_BITS(0xff);
		mic_mmio_write(mw, reg, siac0);
	}
}
예제 #11
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_program_msi_to_src_map - program the MSI mapping registers
 * @mdev: pointer to mic_device instance
 * @idx: index to the mapping register, 0 based
 * @offset: The bit offset in the register that needs to be updated.
 * @set: boolean specifying if the bit in the specified offset needs
 * to be set or cleared.
 *
 * RETURNS: None.
 */
static void
mic_x100_program_msi_to_src_map(struct mic_device *mdev,
				int idx, int offset, bool set)
{
	unsigned long reg;
	struct mic_mw *mw = &mdev->mmio;
	u32 mxar = MIC_X100_SBOX_BASE_ADDRESS +
		MIC_X100_SBOX_MXAR0 + idx * 4;

	reg = mic_mmio_read(mw, mxar);
	if (set)
		__set_bit(offset, &reg);
	else
		__clear_bit(offset, &reg);
	mic_mmio_write(mw, reg, mxar);
}
예제 #12
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_send_sbox_intr(struct mic_device *mdev,
			int doorbell)
{
	struct mic_mw *mw = &mdev->mmio;
	u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
	u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
					apic_icr_offset);

	/* for MIC we need to make sure we "hit" the send_icr bit (13) */
	apicicr_low = (apicicr_low | (1 << 13));

	/* Ensure that the interrupt is ordered w.r.t. previous stores. */
	wmb();
	mic_mmio_write(mw, apicicr_low,
		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
}
예제 #13
0
파일: mic_x100.c 프로젝트: 7799/linux
/**
 * mic_x100_hw_reset - Reset the MIC device.
 * @mdev: pointer to mic_device instance
 */
static void mic_x100_hw_reset(struct mic_device *mdev)
{
	u32 reset_reg;
	u32 rgcr = MIC_X100_SBOX_BASE_ADDRESS + MIC_X100_SBOX_RGCR;
	struct mic_mw *mw = &mdev->mmio;

	/* Ensure that the reset is ordered w.r.t. previous loads and stores */
	mb();
	/* Trigger reset */
	reset_reg = mic_mmio_read(mw, rgcr);
	reset_reg |= 0x1;
	mic_mmio_write(mw, reset_reg, rgcr);
	/*
	 * It seems we really want to delay at least 1 second
	 * after touching reset to prevent a lot of problems.
	 */
	msleep(1000);
}
예제 #14
0
파일: mic_x100.c 프로젝트: 020gzh/linux
/*
 * mic_x100_send_sbox_intr - Send an MIC_X100_SBOX interrupt to MIC.
 */
static void mic_x100_send_sbox_intr(struct mic_mw *mw, int doorbell)
{
	u64 apic_icr_offset = MIC_X100_SBOX_APICICR0 + doorbell * 8;
	u32 apicicr_low = mic_mmio_read(mw, MIC_X100_SBOX_BASE_ADDRESS +
					apic_icr_offset);

	/* for MIC we need to make sure we "hit" the send_icr bit (13) */
	apicicr_low = (apicicr_low | (1 << 13));
	/*
	 * Ensure that the interrupt is ordered w.r.t. previous stores
	 * to main memory. Fence instructions are not implemented in X100
	 * since execution is in order but a compiler barrier is still
	 * required.
	 */
	wmb();
	mic_mmio_write(mw, apicicr_low,
		       MIC_X100_SBOX_BASE_ADDRESS + apic_icr_offset);
}