Commit 5f05cdca authored by Phani Kiran Hemadri's avatar Phani Kiran Hemadri Committed by Herbert Xu
Browse files

crypto: cavium/nitrox - Configure asymmetric queue manager Hardware unit



This patch configures and initializes CNN55XX device AQM hardware unit.

Signed-off-by: default avatarPhani Kiran Hemadri <phemadri@marvell.com>
Reviewed-by: default avatarSrikanth Jampala <jsrikanth@marvell.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent b31c17c8
Loading
Loading
Loading
Loading
+111 −0
Original line number Diff line number Diff line
@@ -256,6 +256,117 @@ union aqm_grp_execmsk_hi {
	};
};

/**
 * struct aqmq_drbl - AQM Queue Doorbell Counter Registers
 * @dbell_count: Doorbell Counter
 */
union aqmq_drbl {
	u64 value;
	struct {
#if (defined(__BIG_ENDIAN_BITFIELD))
		u64 raz_32_63 : 32;
		u64 dbell_count : 32;
#else
		u64 dbell_count : 32;
		u64 raz_32_63 : 32;
#endif
	};
};

/**
 * struct aqmq_qsz - AQM Queue Host Queue Size Registers
 * @host_queue_size: Size, in numbers of 'aqmq_command_s' command
 * of the Host Ring.
 */
union aqmq_qsz {
	u64 value;
	struct {
#if (defined(__BIG_ENDIAN_BITFIELD))
		u64 raz_32_63 : 32;
		u64 host_queue_size : 32;
#else
		u64 host_queue_size : 32;
		u64 raz_32_63 : 32;
#endif
	};
};

/**
 * struct aqmq_cmp_thr - AQM Queue Commands Completed Threshold Registers
 * @commands_completed_threshold: Count of 'aqmq_command_s' commands executed
 * by AE engines for which completion interrupt is asserted.
 */
union aqmq_cmp_thr {
	u64 value;
	struct {
#if (defined(__BIG_ENDIAN_BITFIELD))
		u64 raz_32_63 : 32;
		u64 commands_completed_threshold : 32;
#else
		u64 commands_completed_threshold : 32;
		u64 raz_32_63 : 32;
#endif
	};
};

/**
 * struct aqmq_cmp_cnt - AQM Queue Commands Completed Count Registers
 * @resend: Bit to request completion interrupt Resend.
 * @completion_status: Command completion status of the ring.
 * @commands_completed_count: Count of 'aqmq_command_s' commands executed by
 * AE engines.
 */
union aqmq_cmp_cnt {
	u64 value;
	struct {
#if (defined(__BIG_ENDIAN_BITFIELD))
		u64 raz_34_63 : 30;
		u64 resend : 1;
		u64 completion_status : 1;
		u64 commands_completed_count : 32;
#else
		u64 commands_completed_count : 32;
		u64 completion_status : 1;
		u64 resend : 1;
		u64 raz_34_63 : 30;
#endif
	};
};

/**
 * struct aqmq_en - AQM Queue Enable Registers
 * @queue_status: 1 = AQMQ is enabled, 0 = AQMQ is disabled
 */
union aqmq_en {
	u64 value;
	struct {
#if (defined(__BIG_ENDIAN_BITFIELD))
		u64 raz_1_63 : 63;
		u64 queue_enable : 1;
#else
		u64 queue_enable : 1;
		u64 raz_1_63 : 63;
#endif
	};
};

/**
 * struct aqmq_activity_stat - AQM Queue Activity Status Registers
 * @queue_active: 1 = AQMQ is active, 0 = AQMQ is quiescent
 */
union aqmq_activity_stat {
	u64 value;
	struct {
#if (defined(__BIG_ENDIAN_BITFIELD))
		u64 raz_1_63 : 63;
		u64 queue_active : 1;
#else
		u64 queue_active : 1;
		u64 raz_1_63 : 63;
#endif
	};
};

/**
 * struct emu_fuse_map - EMU Fuse Map Registers
 * @ae_fuse: Fuse settings for AE 19..0
+143 −15
Original line number Diff line number Diff line
@@ -241,12 +241,12 @@ void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev)
}

/**
 * enable_nps_interrupts - enable NPS interrutps
 * enable_nps_core_interrupts - enable NPS core interrutps
 * @ndev: NITROX device.
 *
 * This includes NPS core, packet in and slc interrupts.
 * This includes NPS core interrupts.
 */
static void enable_nps_interrupts(struct nitrox_device *ndev)
static void enable_nps_core_interrupts(struct nitrox_device *ndev)
{
	union nps_core_int_ena_w1s core_int;

@@ -258,18 +258,9 @@ static void enable_nps_interrupts(struct nitrox_device *ndev)
	core_int.s.npco_dma_malform = 1;
	core_int.s.host_nps_wr_err = 1;
	nitrox_write_csr(ndev, NPS_CORE_INT_ENA_W1S, core_int.value);

	/* NPS packet in ring interrupts */
	nitrox_write_csr(ndev, NPS_PKT_IN_RERR_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_IN_RERR_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_IN_ERR_TYPE_ENA_W1S, (~0ULL));
	/* NPS packet slc port interrupts */
	nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_SLC_ERR_TYPE_ENA_W1S, (~0uLL));
}

void nitrox_config_nps_unit(struct nitrox_device *ndev)
void nitrox_config_nps_core_unit(struct nitrox_device *ndev)
{
	union nps_core_gbl_vfcfg core_gbl_vfcfg;

@@ -281,12 +272,149 @@ void nitrox_config_nps_unit(struct nitrox_device *ndev)
	core_gbl_vfcfg.s.ilk_disable = 1;
	core_gbl_vfcfg.s.cfg = __NDEV_MODE_PF;
	nitrox_write_csr(ndev, NPS_CORE_GBL_VFCFG, core_gbl_vfcfg.value);

	/* enable nps core interrupts */
	enable_nps_core_interrupts(ndev);
}

/**
 * enable_nps_pkt_interrupts - enable NPS packet interrutps
 * @ndev: NITROX device.
 *
 * This includes NPS packet in and slc interrupts.
 */
static void enable_nps_pkt_interrupts(struct nitrox_device *ndev)
{
	/* NPS packet in ring interrupts */
	nitrox_write_csr(ndev, NPS_PKT_IN_RERR_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_IN_RERR_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_IN_ERR_TYPE_ENA_W1S, (~0ULL));
	/* NPS packet slc port interrupts */
	nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_SLC_RERR_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, NPS_PKT_SLC_ERR_TYPE_ENA_W1S, (~0uLL));
}

void nitrox_config_nps_pkt_unit(struct nitrox_device *ndev)
{
	/* config input and solicit ports */
	nitrox_config_pkt_input_rings(ndev);
	nitrox_config_pkt_solicit_ports(ndev);

	/* enable interrupts */
	enable_nps_interrupts(ndev);
	/* enable nps packet interrupts */
	enable_nps_pkt_interrupts(ndev);
}

static void reset_aqm_ring(struct nitrox_device *ndev, int ring)
{
	union aqmq_en aqmq_en_reg;
	union aqmq_activity_stat activity_stat;
	union aqmq_cmp_cnt cmp_cnt;
	int max_retries = MAX_CSR_RETRIES;
	u64 offset;

	/* step 1: disable the queue */
	offset = AQMQ_ENX(ring);
	aqmq_en_reg.value = 0;
	aqmq_en_reg.queue_enable = 0;
	nitrox_write_csr(ndev, offset, aqmq_en_reg.value);

	/* step 2: wait for AQMQ_ACTIVITY_STATX[QUEUE_ACTIVE] to clear */
	usleep_range(100, 150);
	offset = AQMQ_ACTIVITY_STATX(ring);
	do {
		activity_stat.value = nitrox_read_csr(ndev, offset);
		if (!activity_stat.queue_active)
			break;
		udelay(50);
	} while (max_retries--);

	/* step 3: clear commands completed count */
	offset = AQMQ_CMP_CNTX(ring);
	cmp_cnt.value = nitrox_read_csr(ndev, offset);
	nitrox_write_csr(ndev, offset, cmp_cnt.value);
	usleep_range(50, 100);
}

void enable_aqm_ring(struct nitrox_device *ndev, int ring)
{
	union aqmq_en aqmq_en_reg;
	u64 offset;

	offset = AQMQ_ENX(ring);
	aqmq_en_reg.value = 0;
	aqmq_en_reg.queue_enable = 1;
	nitrox_write_csr(ndev, offset, aqmq_en_reg.value);
	usleep_range(50, 100);
}

void nitrox_config_aqm_rings(struct nitrox_device *ndev)
{
	int ring;

	for (ring = 0; ring < ndev->nr_queues; ring++) {
		struct nitrox_cmdq *cmdq = ndev->aqmq[ring];
		union aqmq_drbl drbl;
		union aqmq_qsz qsize;
		union aqmq_cmp_thr cmp_thr;
		u64 offset;

		/* steps 1 - 3 */
		reset_aqm_ring(ndev, ring);

		/* step 4: clear doorbell count of ring */
		offset = AQMQ_DRBLX(ring);
		drbl.value = 0;
		drbl.dbell_count = 0xFFFFFFFF;
		nitrox_write_csr(ndev, offset, drbl.value);

		/* step 5: configure host ring details */

		/* set host address for next command of ring */
		offset = AQMQ_NXT_CMDX(ring);
		nitrox_write_csr(ndev, offset, 0ULL);

		/* set host address of ring base */
		offset = AQMQ_BADRX(ring);
		nitrox_write_csr(ndev, offset, cmdq->dma);

		/* set ring size */
		offset = AQMQ_QSZX(ring);
		qsize.value = 0;
		qsize.host_queue_size = ndev->qlen;
		nitrox_write_csr(ndev, offset, qsize.value);

		/* set command completion threshold */
		offset = AQMQ_CMP_THRX(ring);
		cmp_thr.value = 0;
		cmp_thr.commands_completed_threshold = 1;
		nitrox_write_csr(ndev, offset, cmp_thr.value);

		/* step 6: enable the queue */
		enable_aqm_ring(ndev, ring);
	}
}

static void enable_aqm_interrupts(struct nitrox_device *ndev)
{
	/* clear interrupt enable bits */
	nitrox_write_csr(ndev, AQM_DBELL_OVF_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_DBELL_OVF_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_DMA_RD_ERR_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_DMA_RD_ERR_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_EXEC_NA_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_EXEC_NA_HI_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_EXEC_ERR_LO_ENA_W1S, (~0ULL));
	nitrox_write_csr(ndev, AQM_EXEC_ERR_HI_ENA_W1S, (~0ULL));
}

void nitrox_config_aqm_unit(struct nitrox_device *ndev)
{
	/* config aqm command queues */
	nitrox_config_aqm_rings(ndev);

	/* enable aqm interrupts */
	enable_aqm_interrupts(ndev);
}

void nitrox_config_pom_unit(struct nitrox_device *ndev)
+5 −1
Original line number Diff line number Diff line
@@ -4,10 +4,13 @@

#include "nitrox_dev.h"

void nitrox_config_aqm_rings(struct nitrox_device *ndev);
void nitrox_config_aqm_unit(struct nitrox_device *ndev);
void nitrox_config_emu_unit(struct nitrox_device *ndev);
void nitrox_config_pkt_input_rings(struct nitrox_device *ndev);
void nitrox_config_pkt_solicit_ports(struct nitrox_device *ndev);
void nitrox_config_nps_unit(struct nitrox_device *ndev);
void nitrox_config_nps_core_unit(struct nitrox_device *ndev);
void nitrox_config_nps_pkt_unit(struct nitrox_device *ndev);
void nitrox_config_pom_unit(struct nitrox_device *ndev);
void nitrox_config_rand_unit(struct nitrox_device *ndev);
void nitrox_config_efl_unit(struct nitrox_device *ndev);
@@ -15,6 +18,7 @@ void nitrox_config_bmi_unit(struct nitrox_device *ndev);
void nitrox_config_bmo_unit(struct nitrox_device *ndev);
void nitrox_config_lbc_unit(struct nitrox_device *ndev);
void invalidate_lbc(struct nitrox_device *ndev);
void enable_aqm_ring(struct nitrox_device *ndev, int qno);
void enable_pkt_input_ring(struct nitrox_device *ndev, int ring);
void enable_pkt_solicit_port(struct nitrox_device *ndev, int port);
void config_nps_core_vfcfg_mode(struct nitrox_device *ndev, enum vf_mode mode);
+3 −1
Original line number Diff line number Diff line
@@ -387,7 +387,9 @@ static int nitrox_pf_hw_init(struct nitrox_device *ndev)
	/* get cores information */
	nitrox_get_hwinfo(ndev);

	nitrox_config_nps_unit(ndev);
	nitrox_config_nps_core_unit(ndev);
	nitrox_config_aqm_unit(ndev);
	nitrox_config_nps_pkt_unit(ndev);
	nitrox_config_pom_unit(ndev);
	nitrox_config_efl_unit(ndev);
	/* configure IO units */
+3 −0
Original line number Diff line number Diff line
@@ -109,6 +109,9 @@ static int nitrox_pf_reinit(struct nitrox_device *ndev)
		return err;
	}

	/* configure the AQM queues */
	nitrox_config_aqm_rings(ndev);

	/* configure the packet queues */
	nitrox_config_pkt_input_rings(ndev);
	nitrox_config_pkt_solicit_ports(ndev);