Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03e1de50 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'stmmac-mq-part3'



Joao Pinto says:

====================
net: stmmac: adding multiple buffers and routing

As agreed with David Miller, this patch-set is the third and last to enable
multiple queues in stmmac.

This third one focuses on:

a) Enable multiple buffering to the driver and queue independent data
b) Configuration of RX and TX queues' priority
c) Configuration of RX queues' routing
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents de6b08fd abe80fdc
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -83,6 +83,13 @@ Optional properties:
			- snps,dcb-algorithm: Queue to be enabled as DCB
			- snps,avb-algorithm: Queue to be enabled as AVB
		- snps,map-to-dma-channel: Channel to map
		- Specifiy specific packet routing:
			- snps,route-avcp: AV Untagged Control packets
			- snps,route-ptp: PTP Packets
			- snps,route-dcbcp: DCB Control Packets
			- snps,route-up: Untagged Packets
			- snps,route-multi-broad: Multicast & Broadcast Packets
		- snps,priority: RX queue priority (Range: 0x0 to 0xF)
- Multiple TX Queues parameters: below the list of all the parameters to
				 configure the multiple TX queues:
	- snps,tx-queues-to-use: number of TX queues to be used in the driver
@@ -101,6 +108,7 @@ Optional properties:
			- snps,idle_slope: unlock on WoL
			- snps,high_credit: max write outstanding req. limit
			- snps,low_credit: max read outstanding req. limit
		- snps,priority: TX queue priority (Range: 0x0 to 0xF)
Examples:

	stmmac_axi_setup: stmmac-axi-config {
@@ -115,6 +123,7 @@ Examples:
		queue0 {
			snps,dcb-algorithm;
			snps,map-to-dma-channel = <0x0>;
			snps,priority = <0x0>;
		};
	};

@@ -124,6 +133,7 @@ Examples:
		queue0 {
			snps,weight = <0x10>;
			snps,dcb-algorithm;
			snps,priority = <0x0>;
		};

		queue1 {
@@ -132,6 +142,7 @@ Examples:
			snps,idle_slope = <0x1000>;
			snps,high_credit = <0x3E800>;
			snps,low_credit = <0xFFC18000>;
			snps,priority = <0x1>;
		};
	};

+25 −20
Original line number Diff line number Diff line
@@ -26,12 +26,15 @@

static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
{
	struct stmmac_priv *priv = (struct stmmac_priv *)p;
	unsigned int entry = priv->cur_tx;
	struct dma_desc *desc = priv->dma_tx + entry;
	struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)p;
	unsigned int nopaged_len = skb_headlen(skb);
	struct stmmac_priv *priv = tx_q->priv_data;
	unsigned int entry = tx_q->cur_tx;
	unsigned int bmax, des2;
	unsigned int i = 1, len;
	struct dma_desc *desc;

	desc = tx_q->dma_tx + entry;

	if (priv->plat->enh_desc)
		bmax = BUF_SIZE_8KiB;
@@ -45,16 +48,16 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
	desc->des2 = cpu_to_le32(des2);
	if (dma_mapping_error(priv->device, des2))
		return -1;
	priv->tx_skbuff_dma[entry].buf = des2;
	priv->tx_skbuff_dma[entry].len = bmax;
	tx_q->tx_skbuff_dma[entry].buf = des2;
	tx_q->tx_skbuff_dma[entry].len = bmax;
	/* do not close the descriptor and do not set own bit */
	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE,
					0, false);

	while (len != 0) {
		priv->tx_skbuff[entry] = NULL;
		tx_q->tx_skbuff[entry] = NULL;
		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
		desc = priv->dma_tx + entry;
		desc = tx_q->dma_tx + entry;

		if (len > bmax) {
			des2 = dma_map_single(priv->device,
@@ -63,8 +66,8 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
			desc->des2 = cpu_to_le32(des2);
			if (dma_mapping_error(priv->device, des2))
				return -1;
			priv->tx_skbuff_dma[entry].buf = des2;
			priv->tx_skbuff_dma[entry].len = bmax;
			tx_q->tx_skbuff_dma[entry].buf = des2;
			tx_q->tx_skbuff_dma[entry].len = bmax;
			priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
							STMMAC_CHAIN_MODE, 1,
							false);
@@ -77,8 +80,8 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
			desc->des2 = cpu_to_le32(des2);
			if (dma_mapping_error(priv->device, des2))
				return -1;
			priv->tx_skbuff_dma[entry].buf = des2;
			priv->tx_skbuff_dma[entry].len = len;
			tx_q->tx_skbuff_dma[entry].buf = des2;
			tx_q->tx_skbuff_dma[entry].len = len;
			/* last descriptor can be set now */
			priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
							STMMAC_CHAIN_MODE, 1,
@@ -87,7 +90,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
		}
	}

	priv->cur_tx = entry;
	tx_q->cur_tx = entry;

	return entry;
}
@@ -136,32 +139,34 @@ static void stmmac_init_dma_chain(void *des, dma_addr_t phy_addr,

static void stmmac_refill_desc3(void *priv_ptr, struct dma_desc *p)
{
	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
	struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)priv_ptr;
	struct stmmac_priv *priv = rx_q->priv_data;

	if (priv->hwts_rx_en && !priv->extend_desc)
		/* NOTE: Device will overwrite des3 with timestamp value if
		 * 1588-2002 time stamping is enabled, hence reinitialize it
		 * to keep explicit chaining in the descriptor.
		 */
		p->des3 = cpu_to_le32((unsigned int)(priv->dma_rx_phy +
				      (((priv->dirty_rx) + 1) %
		p->des3 = cpu_to_le32((unsigned int)(rx_q->dma_rx_phy +
				      (((rx_q->dirty_rx) + 1) %
				       DMA_RX_SIZE) *
				      sizeof(struct dma_desc)));
}

static void stmmac_clean_desc3(void *priv_ptr, struct dma_desc *p)
{
	struct stmmac_priv *priv = (struct stmmac_priv *)priv_ptr;
	unsigned int entry = priv->dirty_tx;
	struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)priv_ptr;
	struct stmmac_priv *priv = tx_q->priv_data;
	unsigned int entry = tx_q->dirty_tx;

	if (priv->tx_skbuff_dma[entry].last_segment && !priv->extend_desc &&
	if (tx_q->tx_skbuff_dma[entry].last_segment && !priv->extend_desc &&
	    priv->hwts_tx_en)
		/* NOTE: Device will overwrite des3 with timestamp value if
		 * 1588-2002 time stamping is enabled, hence reinitialize it
		 * to keep explicit chaining in the descriptor.
		 */
		p->des3 = cpu_to_le32((unsigned int)((priv->dma_tx_phy +
				      ((priv->dirty_tx + 1) % DMA_TX_SIZE))
		p->des3 = cpu_to_le32((unsigned int)((tx_q->dma_tx_phy +
				      ((tx_q->dirty_tx + 1) % DMA_TX_SIZE))
				      * sizeof(struct dma_desc)));
}

+21 −0
Original line number Diff line number Diff line
@@ -246,6 +246,15 @@ struct stmmac_extra_stats {
#define STMMAC_TX_MAX_FRAMES	256
#define STMMAC_TX_FRAMES	64

/* Packets types */
enum packets_types {
	PACKET_AVCPQ = 0x1, /* AV Untagged Control packets */
	PACKET_PTPQ = 0x2, /* PTP Packets */
	PACKET_DCBCPQ = 0x3, /* DCB Control Packets */
	PACKET_UPQ = 0x4, /* Untagged Packets */
	PACKET_MCBCQ = 0x5, /* Multicast & Broadcast Packets */
};

/* Rx IPC status */
enum rx_frame_status {
	good_frame = 0x0,
@@ -469,6 +478,13 @@ struct stmmac_ops {
	int (*rx_ipc)(struct mac_device_info *hw);
	/* Enable RX Queues */
	void (*rx_queue_enable)(struct mac_device_info *hw, u8 mode, u32 queue);
	/* RX Queues Priority */
	void (*rx_queue_prio)(struct mac_device_info *hw, u32 prio, u32 queue);
	/* TX Queues Priority */
	void (*tx_queue_prio)(struct mac_device_info *hw, u32 prio, u32 queue);
	/* RX Queues Routing */
	void (*rx_queue_routing)(struct mac_device_info *hw, u8 packet,
				 u32 queue);
	/* Program RX Algorithms */
	void (*prog_mtl_rx_algorithms)(struct mac_device_info *hw, u32 rx_alg);
	/* Program TX Algorithms */
@@ -577,6 +593,11 @@ struct mac_device_info {
	unsigned int ps;
};

struct stmmac_rx_routing {
	u32 reg_mask;
	u32 reg_shift;
};

struct mac_device_info *dwmac1000_setup(void __iomem *ioaddr, int mcbins,
					int perfect_uc_entries,
					int *synopsys_id);
+29 −0
Original line number Diff line number Diff line
@@ -22,7 +22,12 @@
#define GMAC_HASH_TAB_32_63		0x00000014
#define GMAC_RX_FLOW_CTRL		0x00000090
#define GMAC_QX_TX_FLOW_CTRL(x)		(0x70 + x * 4)
#define GMAC_TXQ_PRTY_MAP0		0x98
#define GMAC_TXQ_PRTY_MAP1		0x9C
#define GMAC_RXQ_CTRL0			0x000000a0
#define GMAC_RXQ_CTRL1			0x000000a4
#define GMAC_RXQ_CTRL2			0x000000a8
#define GMAC_RXQ_CTRL3			0x000000ac
#define GMAC_INT_STATUS			0x000000b0
#define GMAC_INT_EN			0x000000b4
#define GMAC_1US_TIC_COUNTER		0x000000dc
@@ -39,6 +44,22 @@
#define GMAC_ADDR_HIGH(reg)		(0x300 + reg * 8)
#define GMAC_ADDR_LOW(reg)		(0x304 + reg * 8)

/* RX Queues Routing */
#define GMAC_RXQCTRL_AVCPQ_MASK		GENMASK(2, 0)
#define GMAC_RXQCTRL_AVCPQ_SHIFT	0
#define GMAC_RXQCTRL_PTPQ_MASK		GENMASK(6, 4)
#define GMAC_RXQCTRL_PTPQ_SHIFT		4
#define GMAC_RXQCTRL_DCBCPQ_MASK	GENMASK(10, 8)
#define GMAC_RXQCTRL_DCBCPQ_SHIFT	8
#define GMAC_RXQCTRL_UPQ_MASK		GENMASK(14, 12)
#define GMAC_RXQCTRL_UPQ_SHIFT		12
#define GMAC_RXQCTRL_MCBCQ_MASK		GENMASK(18, 16)
#define GMAC_RXQCTRL_MCBCQ_SHIFT	16
#define GMAC_RXQCTRL_MCBCQEN		BIT(20)
#define GMAC_RXQCTRL_MCBCQEN_SHIFT	20
#define GMAC_RXQCTRL_TACPQE		BIT(21)
#define GMAC_RXQCTRL_TACPQE_SHIFT	21

/* MAC Packet Filtering */
#define GMAC_PACKET_FILTER_PR		BIT(0)
#define GMAC_PACKET_FILTER_HMC		BIT(2)
@@ -54,6 +75,14 @@
/* MAC Flow Control RX */
#define GMAC_RX_FLOW_CTRL_RFE		BIT(0)

/* RX Queues Priorities */
#define GMAC_RXQCTRL_PSRQX_MASK(x)	GENMASK(7 + ((x) * 8), 0 + ((x) * 8))
#define GMAC_RXQCTRL_PSRQX_SHIFT(x)	((x) * 8)

/* TX Queues Priorities */
#define GMAC_TXQCTRL_PSTQX_MASK(x)	GENMASK(7 + ((x) * 8), 0 + ((x) * 8))
#define GMAC_TXQCTRL_PSTQX_SHIFT(x)	((x) * 8)

/* MAC Flow Control TX */
#define GMAC_TX_FLOW_CTRL_TFE		BIT(1)
#define GMAC_TX_FLOW_CTRL_PT_SHIFT	16
+71 −0
Original line number Diff line number Diff line
@@ -74,6 +74,74 @@ static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
	writel(value, ioaddr + GMAC_RXQ_CTRL0);
}

static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
				     u32 prio, u32 queue)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 base_register;
	u32 value;

	base_register = (queue < 4) ? GMAC_RXQ_CTRL2 : GMAC_RXQ_CTRL3;

	value = readl(ioaddr + base_register);

	value &= ~GMAC_RXQCTRL_PSRQX_MASK(queue);
	value |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
						GMAC_RXQCTRL_PSRQX_MASK(queue);
	writel(value, ioaddr + base_register);
}

static void dwmac4_tx_queue_priority(struct mac_device_info *hw,
				     u32 prio, u32 queue)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 base_register;
	u32 value;

	base_register = (queue < 4) ? GMAC_TXQ_PRTY_MAP0 : GMAC_TXQ_PRTY_MAP1;

	value = readl(ioaddr + base_register);

	value &= ~GMAC_TXQCTRL_PSTQX_MASK(queue);
	value |= (prio << GMAC_TXQCTRL_PSTQX_SHIFT(queue)) &
						GMAC_TXQCTRL_PSTQX_MASK(queue);

	writel(value, ioaddr + base_register);
}

static void dwmac4_tx_queue_routing(struct mac_device_info *hw,
				    u8 packet, u32 queue)
{
	void __iomem *ioaddr = hw->pcsr;
	u32 value;

	const struct stmmac_rx_routing route_possibilities[] = {
		{ GMAC_RXQCTRL_AVCPQ_MASK, GMAC_RXQCTRL_AVCPQ_SHIFT },
		{ GMAC_RXQCTRL_PTPQ_MASK, GMAC_RXQCTRL_PTPQ_SHIFT },
		{ GMAC_RXQCTRL_DCBCPQ_MASK, GMAC_RXQCTRL_DCBCPQ_SHIFT },
		{ GMAC_RXQCTRL_UPQ_MASK, GMAC_RXQCTRL_UPQ_SHIFT },
		{ GMAC_RXQCTRL_MCBCQ_MASK, GMAC_RXQCTRL_MCBCQ_SHIFT },
	};

	value = readl(ioaddr + GMAC_RXQ_CTRL1);

	/* routing configuration */
	value &= ~route_possibilities[packet - 1].reg_mask;
	value |= (queue << route_possibilities[packet-1].reg_shift) &
		 route_possibilities[packet - 1].reg_mask;

	/* some packets require extra ops */
	if (packet == PACKET_AVCPQ) {
		value &= ~GMAC_RXQCTRL_TACPQE;
		value |= 0x1 << GMAC_RXQCTRL_TACPQE_SHIFT;
	} else if (packet == PACKET_MCBCQ) {
		value &= ~GMAC_RXQCTRL_MCBCQEN;
		value |= 0x1 << GMAC_RXQCTRL_MCBCQEN_SHIFT;
	}

	writel(value, ioaddr + GMAC_RXQ_CTRL1);
}

static void dwmac4_prog_mtl_rx_algorithms(struct mac_device_info *hw,
					  u32 rx_alg)
{
@@ -603,6 +671,9 @@ static const struct stmmac_ops dwmac4_ops = {
	.core_init = dwmac4_core_init,
	.rx_ipc = dwmac4_rx_ipc_enable,
	.rx_queue_enable = dwmac4_rx_queue_enable,
	.rx_queue_prio = dwmac4_rx_queue_priority,
	.tx_queue_prio = dwmac4_tx_queue_priority,
	.rx_queue_routing = dwmac4_tx_queue_routing,
	.prog_mtl_rx_algorithms = dwmac4_prog_mtl_rx_algorithms,
	.prog_mtl_tx_algorithms = dwmac4_prog_mtl_tx_algorithms,
	.set_mtl_tx_queue_weight = dwmac4_set_mtl_tx_queue_weight,
Loading