drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/stmicro/stmmac/stmmac_fpe.c
Extension
.c
Size
9713 bytes
Lines
315
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

struct stmmac_fpe_reg {
	const u32 mac_fpe_reg;		/* offset of MAC_FPE_CTRL_STS */
	const u32 mtl_fpe_reg;		/* offset of MTL_FPE_CTRL_STS */
	const u32 rxq_ctrl1_reg;	/* offset of MAC_RxQ_Ctrl1 */
	const u32 fprq_mask;		/* Frame Preemption Residue Queue */
	const u32 int_en_reg;		/* offset of MAC_Interrupt_Enable */
	const u32 int_en_bit;		/* Frame Preemption Interrupt Enable */
};

bool stmmac_fpe_supported(struct stmmac_priv *priv)
{
	return priv->dma_cap.fpesel && priv->fpe_cfg.reg &&
		priv->hw->mac->fpe_map_preemption_class;
}

static void stmmac_fpe_configure_tx(struct ethtool_mmsv *mmsv, bool tx_enable)
{
	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
	const struct stmmac_fpe_reg *reg = cfg->reg;
	u32 num_rxq = priv->plat->rx_queues_to_use;
	void __iomem *ioaddr = priv->ioaddr;
	u32 value;

	if (tx_enable) {
		cfg->fpe_csr = STMMAC_MAC_FPE_CTRL_STS_EFPE;
		value = readl(ioaddr + reg->rxq_ctrl1_reg);
		value &= ~reg->fprq_mask;
		/* Keep this SHIFT, FIELD_PREP() expects a constant mask :-/ */
		value |= (num_rxq - 1) << __ffs(reg->fprq_mask);
		writel(value, ioaddr + reg->rxq_ctrl1_reg);
	} else {
		cfg->fpe_csr = 0;
	}
	writel(cfg->fpe_csr, ioaddr + reg->mac_fpe_reg);
}

static void stmmac_fpe_configure_pmac(struct ethtool_mmsv *mmsv, bool pmac_enable)
{
	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
	const struct stmmac_fpe_reg *reg = cfg->reg;
	void __iomem *ioaddr = priv->ioaddr;
	unsigned long flags;
	u32 value;

	spin_lock_irqsave(&priv->hw->irq_ctrl_lock, flags);
	value = readl(ioaddr + reg->int_en_reg);

	if (pmac_enable) {
		if (!(value & reg->int_en_bit)) {
			/* Dummy read to clear any pending masked interrupts */
			readl(ioaddr + reg->mac_fpe_reg);

			value |= reg->int_en_bit;
		}
	} else {
		value &= ~reg->int_en_bit;
	}

	writel(value, ioaddr + reg->int_en_reg);
	spin_unlock_irqrestore(&priv->hw->irq_ctrl_lock, flags);
}

static void stmmac_fpe_send_mpacket(struct ethtool_mmsv *mmsv,
				    enum ethtool_mpacket type)
{
	struct stmmac_fpe_cfg *cfg = container_of(mmsv, struct stmmac_fpe_cfg, mmsv);
	struct stmmac_priv *priv = container_of(cfg, struct stmmac_priv, fpe_cfg);
	const struct stmmac_fpe_reg *reg = cfg->reg;
	void __iomem *ioaddr = priv->ioaddr;
	u32 value = cfg->fpe_csr;

	if (type == ETHTOOL_MPACKET_VERIFY)
		value |= STMMAC_MAC_FPE_CTRL_STS_SVER;
	else if (type == ETHTOOL_MPACKET_RESPONSE)
		value |= STMMAC_MAC_FPE_CTRL_STS_SRSP;

	writel(value, ioaddr + reg->mac_fpe_reg);
}

static const struct ethtool_mmsv_ops stmmac_mmsv_ops = {
	.configure_tx = stmmac_fpe_configure_tx,
	.configure_pmac = stmmac_fpe_configure_pmac,
	.send_mpacket = stmmac_fpe_send_mpacket,
};

static void stmmac_fpe_event_status(struct stmmac_priv *priv, int status)
{
	struct stmmac_fpe_cfg *fpe_cfg = &priv->fpe_cfg;

Annotation

Implementation Notes