net: stmmac: gmac4+: Add Split Header support
authorJose Abreu <Jose.Abreu@synopsys.com>
Mon, 11 Nov 2019 14:42:35 +0000 (15:42 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 12 Nov 2019 07:13:19 +0000 (23:13 -0800)
GMAC4+ cores also support the Split Header feature.

Add the support for Split Header feature in the RX path following the
same implementation logic that XGMAC followed.

Signed-off-by: Jose Abreu <Jose.Abreu@synopsys.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.h

index 07e97f45755d2c4d07eb2e556d0c8281d4a73c56..2dc70d104161316cfb0285918c5dcabd73cfa5cf 100644 (file)
@@ -14,6 +14,7 @@
 
 /*  MAC registers */
 #define GMAC_CONFIG                    0x00000000
+#define GMAC_EXT_CONFIG                        0x00000004
 #define GMAC_PACKET_FILTER             0x00000008
 #define GMAC_HASH_TAB(x)               (0x10 + (x) * 4)
 #define GMAC_VLAN_TAG                  0x00000050
@@ -188,6 +189,11 @@ enum power_event {
 #define GMAC_CONFIG_TE                 BIT(1)
 #define GMAC_CONFIG_RE                 BIT(0)
 
+/* MAC extended config */
+#define GMAC_CONFIG_HDSMS              GENMASK(22, 20)
+#define GMAC_CONFIG_HDSMS_SHIFT                20
+#define GMAC_CONFIG_HDSMS_256          (0x2 << GMAC_CONFIG_HDSMS_SHIFT)
+
 /* MAC HW features0 bitmap */
 #define GMAC_HW_FEAT_SAVLANINS         BIT(27)
 #define GMAC_HW_FEAT_ADDMAC            BIT(18)
@@ -211,6 +217,7 @@ enum power_event {
 #define GMAC_HW_HASH_TB_SZ             GENMASK(25, 24)
 #define GMAC_HW_FEAT_AVSEL             BIT(20)
 #define GMAC_HW_TSOEN                  BIT(18)
+#define GMAC_HW_FEAT_SPHEN             BIT(17)
 #define GMAC_HW_ADDR64                 GENMASK(15, 14)
 #define GMAC_HW_TXFIFOSIZE             GENMASK(10, 6)
 #define GMAC_HW_RXFIFOSIZE             GENMASK(4, 0)
index 707ab5eba8da86f5f80ad423c178eaed1c872b82..3e14da69f3785e0296f90991380b753021849f98 100644 (file)
@@ -83,9 +83,10 @@ static int dwmac4_wrback_get_rx_status(void *data, struct stmmac_extra_stats *x,
        if (unlikely(rdes3 & RDES3_OWN))
                return dma_own;
 
-       /* Verify rx error by looking at the last segment. */
-       if (likely(!(rdes3 & RDES3_LAST_DESCRIPTOR)))
+       if (unlikely(rdes3 & RDES3_CONTEXT_DESCRIPTOR))
                return discard_frame;
+       if (likely(!(rdes3 & RDES3_LAST_DESCRIPTOR)))
+               return rx_not_ls;
 
        if (unlikely(rdes3 & RDES3_ERROR_SUMMARY)) {
                if (unlikely(rdes3 & RDES3_GIANT_PACKET))
@@ -188,7 +189,7 @@ static void dwmac4_set_tx_owner(struct dma_desc *p)
 
 static void dwmac4_set_rx_owner(struct dma_desc *p, int disable_rx_ic)
 {
-       p->des3 = cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
+       p->des3 |= cpu_to_le32(RDES3_OWN | RDES3_BUFFER1_VALID_ADDR);
 
        if (!disable_rx_ic)
                p->des3 |= cpu_to_le32(RDES3_INT_ON_COMPLETION_EN);
@@ -492,6 +493,18 @@ static void dwmac4_set_vlan(struct dma_desc *p, u32 type)
        p->des2 |= cpu_to_le32(type & TDES2_VLAN_TAG_MASK);
 }
 
+static int dwmac4_get_rx_header_len(struct dma_desc *p, unsigned int *len)
+{
+       *len = le32_to_cpu(p->des2) & RDES2_HL;
+       return 0;
+}
+
+static void dwmac4_set_sec_addr(struct dma_desc *p, dma_addr_t addr)
+{
+       p->des2 = cpu_to_le32(lower_32_bits(addr));
+       p->des3 = cpu_to_le32(upper_32_bits(addr) | RDES3_BUFFER2_VALID_ADDR);
+}
+
 const struct stmmac_desc_ops dwmac4_desc_ops = {
        .tx_status = dwmac4_wrback_get_tx_status,
        .rx_status = dwmac4_wrback_get_rx_status,
@@ -519,6 +532,8 @@ const struct stmmac_desc_ops dwmac4_desc_ops = {
        .set_sarc = dwmac4_set_sarc,
        .set_vlan_tag = dwmac4_set_vlan_tag,
        .set_vlan = dwmac4_set_vlan,
+       .get_rx_header_len = dwmac4_get_rx_header_len,
+       .set_sec_addr = dwmac4_set_sec_addr,
 };
 
 const struct stmmac_mode_ops dwmac4_ring_mode_ops = {
index 0d7b3bbcd5a778509dc4cc16fb976a5a859a7b64..6d92109dc9aa1359a759483a41987b6564022147 100644 (file)
 #define RDES2_L4_FILTER_MATCH          BIT(28)
 #define RDES2_L3_L4_FILT_NB_MATCH_MASK GENMASK(27, 26)
 #define RDES2_L3_L4_FILT_NB_MATCH_SHIFT        26
+#define RDES2_HL                       GENMASK(9, 0)
 
 /* RDES3 (write back format) */
 #define RDES3_PACKET_SIZE_MASK         GENMASK(14, 0)
index b24c89572745740a0900f607160f2e78383fa2c5..36a0af8bf89f21a997a9143c251f6f6878dc8242 100644 (file)
@@ -368,6 +368,7 @@ static void dwmac4_get_hw_feature(void __iomem *ioaddr,
        dma_cap->hash_tb_sz = (hw_cap & GMAC_HW_HASH_TB_SZ) >> 24;
        dma_cap->av = (hw_cap & GMAC_HW_FEAT_AVSEL) >> 20;
        dma_cap->tsoen = (hw_cap & GMAC_HW_TSOEN) >> 18;
+       dma_cap->sphen = (hw_cap & GMAC_HW_FEAT_SPHEN) >> 17;
 
        dma_cap->addr64 = (hw_cap & GMAC_HW_ADDR64) >> 14;
        switch (dma_cap->addr64) {
@@ -460,6 +461,22 @@ static void dwmac4_set_bfsize(void __iomem *ioaddr, int bfsize, u32 chan)
        writel(value, ioaddr + DMA_CHAN_RX_CONTROL(chan));
 }
 
+static void dwmac4_enable_sph(void __iomem *ioaddr, bool en, u32 chan)
+{
+       u32 value = readl(ioaddr + GMAC_EXT_CONFIG);
+
+       value &= ~GMAC_CONFIG_HDSMS;
+       value |= GMAC_CONFIG_HDSMS_256; /* Segment max 256 bytes */
+       writel(value, ioaddr + GMAC_EXT_CONFIG);
+
+       value = readl(ioaddr + DMA_CHAN_CONTROL(chan));
+       if (en)
+               value |= DMA_CONTROL_SPH;
+       else
+               value &= ~DMA_CONTROL_SPH;
+       writel(value, ioaddr + DMA_CHAN_CONTROL(chan));
+}
+
 const struct stmmac_dma_ops dwmac4_dma_ops = {
        .reset = dwmac4_dma_reset,
        .init = dwmac4_dma_init,
@@ -486,6 +503,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = {
        .enable_tso = dwmac4_enable_tso,
        .qmode = dwmac4_qmode,
        .set_bfsize = dwmac4_set_bfsize,
+       .enable_sph = dwmac4_enable_sph,
 };
 
 const struct stmmac_dma_ops dwmac410_dma_ops = {
@@ -514,4 +532,5 @@ const struct stmmac_dma_ops dwmac410_dma_ops = {
        .enable_tso = dwmac4_enable_tso,
        .qmode = dwmac4_qmode,
        .set_bfsize = dwmac4_set_bfsize,
+       .enable_sph = dwmac4_enable_sph,
 };
index 5299fa1001a3a2a0cb20c2a094c8b18271aff9bb..589931795847062f6f9c45f3bebf2e18810e4221 100644 (file)
 #define DMA_CHAN_STATUS(x)             (DMA_CHANX_BASE_ADDR(x) + 0x60)
 
 /* DMA Control X */
+#define DMA_CONTROL_SPH                        BIT(24)
 #define DMA_CONTROL_MSS_MASK           GENMASK(13, 0)
 
 /* DMA Tx Channel X Control register defines */