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

Commit be434d50 authored by Giuseppe Cavallaro's avatar Giuseppe Cavallaro Committed by David S. Miller
Browse files

stmmac: optimize tx desc management



This patch is to optimize the way to manage the TDES inside the
xmit function. When prepare the frame, some settings (e.g. OWN
bit) can be merged. This has been reworked to improve the tx
performances.

Signed-off-by: default avatarFabrice Gasnier <fabrice.gasnier@st.com>
Signed-off-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarAlexandre TORGUE <alexandre.torgue@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c1fa3212
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -50,7 +50,9 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
		return -1;
	priv->tx_skbuff_dma[entry].buf = desc->des2;
	priv->tx_skbuff_dma[entry].len = bmax;
	priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum, STMMAC_CHAIN_MODE);
	/* 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;
@@ -66,8 +68,8 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
			priv->tx_skbuff_dma[entry].buf = desc->des2;
			priv->tx_skbuff_dma[entry].len = bmax;
			priv->hw->desc->prepare_tx_desc(desc, 0, bmax, csum,
							STMMAC_CHAIN_MODE);
			priv->hw->desc->set_tx_owner(desc);
							STMMAC_CHAIN_MODE, 1,
							false);
			len -= bmax;
			i++;
		} else {
@@ -78,9 +80,10 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
				return -1;
			priv->tx_skbuff_dma[entry].buf = desc->des2;
			priv->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);
			priv->hw->desc->set_tx_owner(desc);
							STMMAC_CHAIN_MODE, 1,
							true);
			len = 0;
		}
	}
+2 −3
Original line number Diff line number Diff line
@@ -338,12 +338,11 @@ struct stmmac_desc_ops {

	/* Invoked by the xmit function to prepare the tx descriptor */
	void (*prepare_tx_desc) (struct dma_desc *p, int is_fs, int len,
				 int csum_flag, int mode);
				 bool csum_flag, int mode, bool tx_own,
				 bool ls_ic);
	/* Set/get the owner of the descriptor */
	void (*set_tx_owner) (struct dma_desc *p);
	int (*get_tx_owner) (struct dma_desc *p);
	/* Invoked by the xmit function to close the tx descriptor */
	void (*close_tx_desc) (struct dma_desc *p);
	/* Clean the tx descriptor as soon as the tx irq is received */
	void (*release_tx_desc) (struct dma_desc *p, int mode);
	/* Clear interrupt on tx frame completion. When this bit is
+15 −7
Original line number Diff line number Diff line
@@ -302,7 +302,8 @@ static void enh_desc_release_tx_desc(struct dma_desc *p, int mode)
}

static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
				     int csum_flag, int mode)
				     bool csum_flag, int mode, bool tx_own,
				     bool ls_ic)
{
	unsigned int tdes0 = p->des0;

@@ -316,6 +317,19 @@ static void enh_desc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
	else
		tdes0 &= ~(TX_CIC_FULL << ETDES0_CHECKSUM_INSERTION_SHIFT);

	if (tx_own)
		tdes0 |= ETDES0_OWN;

	if (is_fs & tx_own)
		/* When the own bit, for the first frame, has to be set, all
		 * descriptors for the same frame has to be set before, to
		 * avoid race condition.
		 */
		wmb();

	if (ls_ic)
		tdes0 |= ETDES0_LAST_SEGMENT | ETDES0_INTERRUPT;

	p->des0 = tdes0;

	if (mode == STMMAC_CHAIN_MODE)
@@ -329,11 +343,6 @@ static void enh_desc_clear_tx_ic(struct dma_desc *p)
	p->des0 &= ~ETDES0_INTERRUPT;
}

static void enh_desc_close_tx_desc(struct dma_desc *p)
{
	p->des0 |= ETDES0_LAST_SEGMENT | ETDES0_INTERRUPT;
}

static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
{
	unsigned int csum = 0;
@@ -403,7 +412,6 @@ const struct stmmac_desc_ops enh_desc_ops = {
	.release_tx_desc = enh_desc_release_tx_desc,
	.prepare_tx_desc = enh_desc_prepare_tx_desc,
	.clear_tx_ic = enh_desc_clear_tx_ic,
	.close_tx_desc = enh_desc_close_tx_desc,
	.get_tx_ls = enh_desc_get_tx_ls,
	.set_tx_owner = enh_desc_set_tx_owner,
	.set_rx_owner = enh_desc_set_rx_owner,
+8 −7
Original line number Diff line number Diff line
@@ -185,7 +185,8 @@ static void ndesc_release_tx_desc(struct dma_desc *p, int mode)
}

static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
				  int csum_flag, int mode)
				  bool csum_flag, int mode, bool tx_own,
				  bool ls_ic)
{
	unsigned int tdes1 = p->des1;

@@ -199,6 +200,12 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len,
	else
		tdes1 &= ~(TX_CIC_FULL << TDES1_CHECKSUM_INSERTION_SHIFT);

	if (tx_own)
		tdes1 |= TDES0_OWN;

	if (ls_ic)
		tdes1 |= TDES1_LAST_SEGMENT | TDES1_INTERRUPT;

	p->des1 = tdes1;

	if (mode == STMMAC_CHAIN_MODE)
@@ -212,11 +219,6 @@ static void ndesc_clear_tx_ic(struct dma_desc *p)
	p->des1 &= ~TDES1_INTERRUPT;
}

static void ndesc_close_tx_desc(struct dma_desc *p)
{
	p->des1 |= TDES1_LAST_SEGMENT | TDES1_INTERRUPT;
}

static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
{
	unsigned int csum = 0;
@@ -278,7 +280,6 @@ const struct stmmac_desc_ops ndesc_ops = {
	.release_tx_desc = ndesc_release_tx_desc,
	.prepare_tx_desc = ndesc_prepare_tx_desc,
	.clear_tx_ic = ndesc_clear_tx_ic,
	.close_tx_desc = ndesc_close_tx_desc,
	.get_tx_ls = ndesc_get_tx_ls,
	.set_tx_owner = ndesc_set_tx_owner,
	.set_rx_owner = ndesc_set_rx_owner,
+3 −4
Original line number Diff line number Diff line
@@ -61,7 +61,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)

		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
		priv->hw->desc->prepare_tx_desc(desc, 1, bmax, csum,
						STMMAC_RING_MODE);
						STMMAC_RING_MODE, 0, false);
		wmb();
		priv->tx_skbuff[entry] = NULL;
		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
@@ -81,9 +81,8 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)

		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum,
						STMMAC_RING_MODE);
						STMMAC_RING_MODE, 1, true);
		wmb();
		priv->hw->desc->set_tx_owner(desc);
	} else {
		desc->des2 = dma_map_single(priv->device, skb->data,
					    nopaged_len, DMA_TO_DEVICE);
@@ -94,7 +93,7 @@ static int stmmac_jumbo_frm(void *p, struct sk_buff *skb, int csum)
		priv->tx_skbuff_dma[entry].is_jumbo = true;
		desc->des3 = desc->des2 + BUF_SIZE_4KiB;
		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, csum,
						STMMAC_RING_MODE);
						STMMAC_RING_MODE, 0, true);
	}

	priv->cur_tx = entry;
Loading