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

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
...@@ -351,6 +351,7 @@ struct dma_features { ...@@ -351,6 +351,7 @@ struct dma_features {
unsigned int frpsel; unsigned int frpsel;
unsigned int frpbs; unsigned int frpbs;
unsigned int frpes; unsigned int frpes;
unsigned int addr64;
}; };
/* GMAC TX FIFO is 8K, Rx FIFO is 16K */ /* GMAC TX FIFO is 8K, Rx FIFO is 16K */
......
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
#define XGMAC_HWFEAT_GMIISEL BIT(1) #define XGMAC_HWFEAT_GMIISEL BIT(1)
#define XGMAC_HW_FEATURE1 0x00000120 #define XGMAC_HW_FEATURE1 0x00000120
#define XGMAC_HWFEAT_TSOEN BIT(18) #define XGMAC_HWFEAT_TSOEN BIT(18)
#define XGMAC_HWFEAT_ADDR64 GENMASK(15, 14)
#define XGMAC_HWFEAT_TXFIFOSIZE GENMASK(10, 6) #define XGMAC_HWFEAT_TXFIFOSIZE GENMASK(10, 6)
#define XGMAC_HWFEAT_RXFIFOSIZE GENMASK(4, 0) #define XGMAC_HWFEAT_RXFIFOSIZE GENMASK(4, 0)
#define XGMAC_HW_FEATURE2 0x00000124 #define XGMAC_HW_FEATURE2 0x00000124
...@@ -172,6 +173,7 @@ ...@@ -172,6 +173,7 @@
#define XGMAC_EN_LPI BIT(15) #define XGMAC_EN_LPI BIT(15)
#define XGMAC_LPI_XIT_PKT BIT(14) #define XGMAC_LPI_XIT_PKT BIT(14)
#define XGMAC_AAL BIT(12) #define XGMAC_AAL BIT(12)
#define XGMAC_EAME BIT(11)
#define XGMAC_BLEN GENMASK(7, 1) #define XGMAC_BLEN GENMASK(7, 1)
#define XGMAC_BLEN256 BIT(7) #define XGMAC_BLEN256 BIT(7)
#define XGMAC_BLEN128 BIT(6) #define XGMAC_BLEN128 BIT(6)
......
...@@ -242,8 +242,8 @@ static void dwxgmac2_get_addr(struct dma_desc *p, unsigned int *addr) ...@@ -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) static void dwxgmac2_set_addr(struct dma_desc *p, dma_addr_t addr)
{ {
p->des0 = cpu_to_le32(addr); p->des0 = cpu_to_le32(lower_32_bits(addr));
p->des1 = 0; p->des1 = cpu_to_le32(upper_32_bits(addr));
} }
static void dwxgmac2_clear(struct dma_desc *p) static void dwxgmac2_clear(struct dma_desc *p)
......
...@@ -27,7 +27,7 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr, ...@@ -27,7 +27,7 @@ static void dwxgmac2_dma_init(void __iomem *ioaddr,
if (dma_cfg->aal) if (dma_cfg->aal)
value |= XGMAC_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, static void dwxgmac2_dma_init_chan(void __iomem *ioaddr,
...@@ -361,6 +361,23 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr, ...@@ -361,6 +361,23 @@ static void dwxgmac2_get_hw_feature(void __iomem *ioaddr,
/* MAC HW feature 1 */ /* MAC HW feature 1 */
hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1); hw_cap = readl(ioaddr + XGMAC_HW_FEATURE1);
dma_cap->tsoen = (hw_cap & XGMAC_HWFEAT_TSOEN) >> 18; 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 = dma_cap->tx_fifo_size =
128 << ((hw_cap & XGMAC_HWFEAT_TXFIFOSIZE) >> 6); 128 << ((hw_cap & XGMAC_HWFEAT_TXFIFOSIZE) >> 6);
dma_cap->rx_fifo_size = dma_cap->rx_fifo_size =
......
...@@ -2772,7 +2772,7 @@ static int stmmac_release(struct net_device *dev) ...@@ -2772,7 +2772,7 @@ static int stmmac_release(struct net_device *dev)
* This function fills descriptor and request new descriptors according to * This function fills descriptor and request new descriptors according to
* buffer length to fill * 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) int total_len, bool last_segment, u32 queue)
{ {
struct stmmac_tx_queue *tx_q = &priv->tx_queue[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, ...@@ -2783,11 +2783,18 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
tmp_len = total_len; tmp_len = total_len;
while (tmp_len > 0) { while (tmp_len > 0) {
dma_addr_t curr_addr;
tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]); WARN_ON(tx_q->tx_skbuff[tx_q->cur_tx]);
desc = tx_q->dma_tx + 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 ? buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
TSO_MAX_BUFF_SIZE : tmp_len; 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) ...@@ -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); struct stmmac_priv *priv = netdev_priv(dev);
int nfrags = skb_shinfo(skb)->nr_frags; int nfrags = skb_shinfo(skb)->nr_frags;
u32 queue = skb_get_queue_mapping(skb); u32 queue = skb_get_queue_mapping(skb);
unsigned int first_entry, des; unsigned int first_entry;
struct stmmac_tx_queue *tx_q; struct stmmac_tx_queue *tx_q;
int tmp_pay_len = 0; int tmp_pay_len = 0;
u32 pay_len, mss; u32 pay_len, mss;
u8 proto_hdr_len; u8 proto_hdr_len;
dma_addr_t des;
int i; int i;
tx_q = &priv->tx_queue[queue]; tx_q = &priv->tx_queue[queue];
...@@ -2894,14 +2902,19 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -2894,14 +2902,19 @@ 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].buf = des;
tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb); tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
first->des0 = cpu_to_le32(des); if (priv->dma_cap.addr64 <= 32) {
first->des0 = cpu_to_le32(des);
/* Fill start of payload in buff2 of first descriptor */ /* Fill start of payload in buff2 of first descriptor */
if (pay_len) if (pay_len)
first->des1 = cpu_to_le32(des + proto_hdr_len); first->des1 = cpu_to_le32(des + proto_hdr_len);
/* If needed take extra descriptors to fill the remaining payload */ /* If needed take extra descriptors to fill the remaining payload */
tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; 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); 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) ...@@ -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; int i, csum_insertion = 0, is_jumbo = 0;
u32 queue = skb_get_queue_mapping(skb); u32 queue = skb_get_queue_mapping(skb);
int nfrags = skb_shinfo(skb)->nr_frags; int nfrags = skb_shinfo(skb)->nr_frags;
int entry;
unsigned int first_entry;
struct dma_desc *desc, *first; struct dma_desc *desc, *first;
struct stmmac_tx_queue *tx_q; struct stmmac_tx_queue *tx_q;
unsigned int first_entry;
unsigned int enh_desc; unsigned int enh_desc;
unsigned int des; dma_addr_t des;
int entry;
tx_q = &priv->tx_queue[queue]; tx_q = &priv->tx_queue[queue];
...@@ -4316,6 +4329,24 @@ int stmmac_dvr_probe(struct device *device, ...@@ -4316,6 +4329,24 @@ int stmmac_dvr_probe(struct device *device,
priv->tso = true; priv->tso = true;
dev_info(priv->device, "TSO feature enabled\n"); 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->features |= ndev->hw_features | NETIF_F_HIGHDMA;
ndev->watchdog_timeo = msecs_to_jiffies(watchdog); ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
#ifdef STMMAC_VLAN_TAG_USED #ifdef STMMAC_VLAN_TAG_USED
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment