drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/marvell/octeon_ep_vf/octep_vf_cn9k.c
Extension
.c
Size
17507 bytes
Lines
491
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (reg_val & CN93_VF_SDP_R_MBOX_PF_VF_INT_STATUS) {
			cn93_handle_vf_mbox_intr(oct);
			octep_vf_write_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0), reg_val);
		}
	}
	napi_schedule_irqoff(oq->napi);
	return IRQ_HANDLED;
}

/* Re-initialize Octeon hardware registers */
static void octep_vf_reinit_regs_cn93(struct octep_vf_device *oct)
{
	u32 i;

	for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++)
		oct->hw_ops.setup_iq_regs(oct, i);

	for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++)
		oct->hw_ops.setup_oq_regs(oct, i);

	oct->hw_ops.enable_interrupts(oct);
	oct->hw_ops.enable_io_queues(oct);

	for (i = 0; i < CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf); i++)
		writel(oct->oq[i]->max_count, oct->oq[i]->pkts_credit_reg);
}

/* Enable all interrupts */
static void octep_vf_enable_interrupts_cn93(struct octep_vf_device *oct)
{
	int num_rings, q;
	u64 reg_val;

	num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
	for (q = 0; q < num_rings; q++) {
		reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q));
		reg_val |= BIT_ULL_MASK(62);
		octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q), reg_val);

		reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q));
		reg_val |= BIT_ULL_MASK(62);
		octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q), reg_val);
	}
	/* Enable PF to VF mbox interrupt by setting 2nd bit*/
	octep_vf_write_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0),
			     CN93_VF_SDP_R_MBOX_PF_VF_INT_ENAB);
}

/* Disable all interrupts */
static void octep_vf_disable_interrupts_cn93(struct octep_vf_device *oct)
{
	int num_rings, q;
	u64 reg_val;

	/* Disable PF to VF mbox interrupt by setting 2nd bit*/
	if (oct->mbox)
		octep_vf_write_csr64(oct, CN93_VF_SDP_R_MBOX_PF_VF_INT(0), 0x0);

	num_rings = CFG_GET_PORTS_ACTIVE_IO_RINGS(oct->conf);
	for (q = 0; q < num_rings; q++) {
		reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q));
		reg_val &= ~BIT_ULL_MASK(62);
		octep_vf_write_csr64(oct, CN93_VF_SDP_R_IN_INT_LEVELS(q), reg_val);

		reg_val = octep_vf_read_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q));
		reg_val &= ~BIT_ULL_MASK(62);
		octep_vf_write_csr64(oct, CN93_VF_SDP_R_OUT_INT_LEVELS(q), reg_val);
	}
}

/* Get new Octeon Read Index: index of descriptor that Octeon reads next. */
static u32 octep_vf_update_iq_read_index_cn93(struct octep_vf_iq *iq)
{
	u32 pkt_in_done = readl(iq->inst_cnt_reg);
	u32 last_done, new_idx;

	last_done = pkt_in_done - iq->pkt_in_done;
	iq->pkt_in_done = pkt_in_done;

	new_idx = (iq->octep_vf_read_index + last_done) % iq->max_count;

	return new_idx;
}

/* Enable a hardware Tx Queue */
static void octep_vf_enable_iq_cn93(struct octep_vf_device *oct, int iq_no)
{
	u64 loop = HZ;
	u64 reg_val;

Annotation

Implementation Notes