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

Commit a993db88 authored by Jose Abreu's avatar Jose Abreu Committed by David S. Miller
Browse files

net: stmmac: Enable support for > 32 Bits addressing in XGMAC



Currently, stmmac only supports 32 bits addressing for SKB. Enable the
support for upto 48 bits addressing in XGMAC core.

This avoids the use of bounce buffers and increases performance.

Changes from v1:
	- Fallback to 32 bits in failure (Andrew)

Signed-off-by: default avatarJose Abreu <joabreu@synopsys.com>
Cc: Joao Pinto <jpinto@synopsys.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Cc: Alexandre Torgue <alexandre.torgue@st.com>
Cc: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a66b5884
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -351,6 +351,7 @@ struct dma_features {
	unsigned int frpsel;
	unsigned int frpbs;
	unsigned int frpes;
	unsigned int addr64;
};

/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
+2 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@
#define XGMAC_HWFEAT_GMIISEL		BIT(1)
#define XGMAC_HW_FEATURE1		0x00000120
#define XGMAC_HWFEAT_TSOEN		BIT(18)
#define XGMAC_HWFEAT_ADDR64		GENMASK(15, 14)
#define XGMAC_HWFEAT_TXFIFOSIZE		GENMASK(10, 6)
#define XGMAC_HWFEAT_RXFIFOSIZE		GENMASK(4, 0)
#define XGMAC_HW_FEATURE2		0x00000124
@@ -172,6 +173,7 @@
#define XGMAC_EN_LPI			BIT(15)
#define XGMAC_LPI_XIT_PKT		BIT(14)
#define XGMAC_AAL			BIT(12)
#define XGMAC_EAME			BIT(11)
#define XGMAC_BLEN			GENMASK(7, 1)
#define XGMAC_BLEN256			BIT(7)
#define XGMAC_BLEN128			BIT(6)
+2 −2
Original line number Diff line number Diff line
@@ -242,8 +242,8 @@ static void dwxgmac2_get_addr(struct dma_desc *p, unsigned int *addr)

static void dwxgmac2_set_addr(struct dma_desc *p, dma_addr_t addr)
{
	p->des0 = cpu_to_le32(addr);
	p->des1 = 0;
	p->des0 = cpu_to_le32(lower_32_bits(addr));
	p->des1 = cpu_to_le32(upper_32_bits(addr));
}

static void dwxgmac2_clear(struct dma_desc *p)
+18 −1
Original line number Diff line number Diff line
@@ -27,7 +27,7 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
	if (dma_cfg->aal)
		value |= XGMAC_AAL;

	writel(value, ioaddr + XGMAC_DMA_SYSBUS_MODE);
	writel(value | XGMAC_EAME, ioaddr + XGMAC_DMA_SYSBUS_MODE);
}

static void dwxgmac2_dma_init_chan(void __iomem *ioaddr,
@@ -361,6 +361,23 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
	/* MAC HW feature 1 */
	hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1);
	dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18;

	dma_cap->addr64 = (hw_cap & XGMAC_HWFEAT_ADDR64) >> 14;
	switch (dma_cap->addr64) {
	case 0:
		dma_cap->addr64 = 32;
		break;
	case 1:
		dma_cap->addr64 = 40;
		break;
	case 2:
		dma_cap->addr64 = 48;
		break;
	default:
		dma_cap->addr64 = 32;
		break;
	}

	dma_cap->tx_fifo_size =
		128 << ((hw_cap & XGMAC_HWFEAT_TXFIFOSIZE) >> 6);
	dma_cap->rx_fifo_size =
+43 −12
Original line number Diff line number Diff line
@@ -2772,7 +2772,7 @@ static int stmmac_release(struct net_device *dev)
 *  This function fills descriptor and request new descriptors according to
 *  buffer length to fill
 */
static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des,
				 int total_len, bool last_segment, u32 queue)
{
	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
@@ -2783,11 +2783,18 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
	tmp_len = total_len;

	while (tmp_len > 0) {
		dma_addr_t curr_addr;

		tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
		WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
		desc = tx_q->dma_tx + tx_q->cur_tx;

		desc->des0 = cpu_to_le32(des + (total_len - tmp_len));
		curr_addr = des + (total_len - tmp_len);
		if (priv->dma_cap.addr64 <= 32)
			desc->des0 = cpu_to_le32(curr_addr);
		else
			stmmac_set_desc_addr(priv, desc, curr_addr);

		buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
			    TSO_MAX_BUFF_SIZE : tmp_len;

@@ -2833,11 +2840,12 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
	struct stmmac_priv *priv = netdev_priv(dev);
	int nfrags = skb_shinfo(skb)->nr_frags;
	u32 queue = skb_get_queue_mapping(skb);
	unsigned int first_entry, des;
	unsigned int first_entry;
	struct stmmac_tx_queue *tx_q;
	int tmp_pay_len = 0;
	u32 pay_len, mss;
	u8 proto_hdr_len;
	dma_addr_t des;
	int i;

	tx_q = &priv->tx_queue[queue];
@@ -2894,6 +2902,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
	tx_q->tx_skbuff_dma[first_entry].buf = des;
	tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);

	if (priv->dma_cap.addr64 <= 32) {
		first->des0 = cpu_to_le32(des);

		/* Fill start of payload in buff2 of first descriptor */
@@ -2902,6 +2911,10 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)

		/* If needed take extra descriptors to fill the remaining payload */
		tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
	} else {
		stmmac_set_desc_addr(priv, first, des);
		tmp_pay_len = pay_len;
	}

	stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);

@@ -3031,12 +3044,12 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
	int i, csum_insertion = 0, is_jumbo = 0;
	u32 queue = skb_get_queue_mapping(skb);
	int nfrags = skb_shinfo(skb)->nr_frags;
	int entry;
	unsigned int first_entry;
	struct dma_desc *desc, *first;
	struct stmmac_tx_queue *tx_q;
	unsigned int first_entry;
	unsigned int enh_desc;
	unsigned int des;
	dma_addr_t des;
	int entry;

	tx_q = &priv->tx_queue[queue];

@@ -4316,6 +4329,24 @@ int stmmac_dvr_probe(struct device *device,
		priv->tso = true;
		dev_info(priv->device, "TSO feature enabled\n");
	}

	if (priv->dma_cap.addr64) {
		ret = dma_set_mask_and_coherent(device,
				DMA_BIT_MASK(priv->dma_cap.addr64));
		if (!ret) {
			dev_info(priv->device, "Using %d bits DMA width\n",
				 priv->dma_cap.addr64);
		} else {
			ret = dma_set_mask_and_coherent(device, DMA_BIT_MASK(32));
			if (ret) {
				dev_err(priv->device, "Failed to set DMA Mask\n");
				goto error_hw_init;
			}

			priv->dma_cap.addr64 = 32;
		}
	}

	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED