Commit 38912bdb authored by Deepak SIKRI's avatar Deepak SIKRI Committed by David S. Miller

stmmac: sanitize the rx coe and add the type-1 csum (v2)

This patch sanities the RX coe and adds the Type-1 Rx checksum offload engine (COE).

So the RX COE can be passed through the platform but can be fixed
at run-time in case of the core has the HW capability register.

Also to support the Type-1 Rx COE the driver must append the
HW checksum at the end of payload in case the Rx checksum
engine was used to  offload the HW checksum.

This v2 version also fixes the IPC that has to be enabled and verified.
Signed-off-by: default avatarDeepak Sikri <deepak.sikri@st.com>
Hacked-by: default avatarGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 55f9a4d6
...@@ -228,7 +228,7 @@ struct stmmac_desc_ops { ...@@ -228,7 +228,7 @@ struct stmmac_desc_ops {
int (*get_rx_owner) (struct dma_desc *p); int (*get_rx_owner) (struct dma_desc *p);
void (*set_rx_owner) (struct dma_desc *p); void (*set_rx_owner) (struct dma_desc *p);
/* Get the receive frame size */ /* Get the receive frame size */
int (*get_rx_frame_len) (struct dma_desc *p); int (*get_rx_frame_len) (struct dma_desc *p, int rx_coe_type);
/* Return the reception status looking at the RDES1 */ /* Return the reception status looking at the RDES1 */
int (*rx_status) (void *data, struct stmmac_extra_stats *x, int (*rx_status) (void *data, struct stmmac_extra_stats *x,
struct dma_desc *p); struct dma_desc *p);
...@@ -261,8 +261,8 @@ struct stmmac_dma_ops { ...@@ -261,8 +261,8 @@ struct stmmac_dma_ops {
struct stmmac_ops { struct stmmac_ops {
/* MAC core initialization */ /* MAC core initialization */
void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned; void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
/* Support checksum offload engine */ /* Enable and verify that the IPC module is supported */
int (*rx_coe) (void __iomem *ioaddr); int (*rx_ipc) (void __iomem *ioaddr);
/* Dump MAC registers */ /* Dump MAC registers */
void (*dump_regs) (void __iomem *ioaddr); void (*dump_regs) (void __iomem *ioaddr);
/* Handle extra events on specific interrupts hw dependent */ /* Handle extra events on specific interrupts hw dependent */
......
...@@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr) ...@@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
#endif #endif
} }
static int dwmac1000_rx_coe_supported(void __iomem *ioaddr) static int dwmac1000_rx_ipc_enable(void __iomem *ioaddr)
{ {
u32 value = readl(ioaddr + GMAC_CONTROL); u32 value = readl(ioaddr + GMAC_CONTROL);
...@@ -211,7 +211,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr) ...@@ -211,7 +211,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
static const struct stmmac_ops dwmac1000_ops = { static const struct stmmac_ops dwmac1000_ops = {
.core_init = dwmac1000_core_init, .core_init = dwmac1000_core_init,
.rx_coe = dwmac1000_rx_coe_supported, .rx_ipc = dwmac1000_rx_ipc_enable,
.dump_regs = dwmac1000_dump_regs, .dump_regs = dwmac1000_dump_regs,
.host_irq_status = dwmac1000_irq_status, .host_irq_status = dwmac1000_irq_status,
.set_filter = dwmac1000_set_filter, .set_filter = dwmac1000_set_filter,
......
...@@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr) ...@@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr)
#endif #endif
} }
static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
{
return 0;
}
static void dwmac100_dump_mac_regs(void __iomem *ioaddr) static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
{ {
pr_info("\t----------------------------------------------\n" pr_info("\t----------------------------------------------\n"
...@@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr) ...@@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
readl(ioaddr + MAC_VLAN2)); readl(ioaddr + MAC_VLAN2));
} }
static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
{
return 0;
}
static void dwmac100_irq_status(void __iomem *ioaddr) static void dwmac100_irq_status(void __iomem *ioaddr)
{ {
return; return;
...@@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode) ...@@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
static const struct stmmac_ops dwmac100_ops = { static const struct stmmac_ops dwmac100_ops = {
.core_init = dwmac100_core_init, .core_init = dwmac100_core_init,
.rx_coe = dwmac100_rx_coe_supported, .rx_ipc = dwmac100_rx_ipc_enable,
.dump_regs = dwmac100_dump_mac_regs, .dump_regs = dwmac100_dump_mac_regs,
.host_irq_status = dwmac100_irq_status, .host_irq_status = dwmac100_irq_status,
.set_filter = dwmac100_set_filter, .set_filter = dwmac100_set_filter,
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/ *******************************************************************************/
#include <linux/stmmac.h>
#include "common.h" #include "common.h"
#include "descs_com.h" #include "descs_com.h"
...@@ -309,8 +310,16 @@ static void enh_desc_close_tx_desc(struct dma_desc *p) ...@@ -309,8 +310,16 @@ static void enh_desc_close_tx_desc(struct dma_desc *p)
p->des01.etx.interrupt = 1; p->des01.etx.interrupt = 1;
} }
static int enh_desc_get_rx_frame_len(struct dma_desc *p) static int enh_desc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
{ {
/* The type-1 checksum offload engines append the checksum at
* the end of frame and the two bytes of checksum are added in
* the length.
* Adjust for that in the framelen for type-1 checksum offload
* engines. */
if (rx_coe_type == STMMAC_RX_COE_TYPE1)
return p->des01.erx.frame_length - 2;
else
return p->des01.erx.frame_length; return p->des01.erx.frame_length;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
*******************************************************************************/ *******************************************************************************/
#include <linux/stmmac.h>
#include "common.h" #include "common.h"
#include "descs_com.h" #include "descs_com.h"
...@@ -201,8 +202,16 @@ static void ndesc_close_tx_desc(struct dma_desc *p) ...@@ -201,8 +202,16 @@ static void ndesc_close_tx_desc(struct dma_desc *p)
p->des01.tx.interrupt = 1; p->des01.tx.interrupt = 1;
} }
static int ndesc_get_rx_frame_len(struct dma_desc *p) static int ndesc_get_rx_frame_len(struct dma_desc *p, int rx_coe_type)
{ {
/* The type-1 checksum offload engines append the checksum at
* the end of frame and the two bytes of checksum are added in
* the length.
* Adjust for that in the framelen for type-1 checksum offload
* engines. */
if (rx_coe_type == STMMAC_RX_COE_TYPE1)
return p->des01.rx.frame_length - 2;
else
return p->des01.rx.frame_length; return p->des01.rx.frame_length;
} }
......
...@@ -56,8 +56,6 @@ struct stmmac_priv { ...@@ -56,8 +56,6 @@ struct stmmac_priv {
struct stmmac_extra_stats xstats; struct stmmac_extra_stats xstats;
struct napi_struct napi; struct napi_struct napi;
int rx_coe;
int no_csum_insertion; int no_csum_insertion;
struct phy_device *phydev; struct phy_device *phydev;
......
...@@ -1282,7 +1282,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) ...@@ -1282,7 +1282,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
struct sk_buff *skb; struct sk_buff *skb;
int frame_len; int frame_len;
frame_len = priv->hw->desc->get_rx_frame_len(p); frame_len = priv->hw->desc->get_rx_frame_len(p,
priv->plat->rx_coe);
/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
* Type frames (LLC/LLC-SNAP) */ * Type frames (LLC/LLC-SNAP) */
if (unlikely(status != llc_snap)) if (unlikely(status != llc_snap))
...@@ -1318,7 +1319,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit) ...@@ -1318,7 +1319,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
#endif #endif
skb->protocol = eth_type_trans(skb, priv->dev); skb->protocol = eth_type_trans(skb, priv->dev);
if (unlikely(!priv->rx_coe)) { if (unlikely(!priv->plat->rx_coe)) {
/* No RX COE for old mac10/100 devices */ /* No RX COE for old mac10/100 devices */
skb_checksum_none_assert(skb); skb_checksum_none_assert(skb);
netif_receive_skb(skb); netif_receive_skb(skb);
...@@ -1465,8 +1466,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev, ...@@ -1465,8 +1466,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *dev,
{ {
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
if (!priv->rx_coe) if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
features &= ~NETIF_F_RXCSUM; features &= ~NETIF_F_RXCSUM;
else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
features &= ~NETIF_F_IPV6_CSUM;
if (!priv->plat->tx_coe) if (!priv->plat->tx_coe)
features &= ~NETIF_F_ALL_CSUM; features &= ~NETIF_F_ALL_CSUM;
...@@ -1769,17 +1772,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv) ...@@ -1769,17 +1772,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
* register (if supported). * register (if supported).
*/ */
priv->plat->enh_desc = priv->dma_cap.enh_desc; priv->plat->enh_desc = priv->dma_cap.enh_desc;
priv->plat->tx_coe = priv->dma_cap.tx_coe;
priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
priv->plat->tx_coe = priv->dma_cap.tx_coe;
if (priv->dma_cap.rx_coe_type2)
priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
else if (priv->dma_cap.rx_coe_type1)
priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
} else } else
pr_info(" No HW DMA feature register supported"); pr_info(" No HW DMA feature register supported");
/* Select the enhnaced/normal descriptor structures */ /* Select the enhnaced/normal descriptor structures */
stmmac_selec_desc_mode(priv); stmmac_selec_desc_mode(priv);
priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); /* Enable the IPC (Checksum Offload) and check if the feature has been
if (priv->rx_coe) * enabled during the core configuration. */
pr_info(" RX Checksum Offload Engine supported\n"); ret = priv->hw->mac->rx_ipc(priv->ioaddr);
if (!ret) {
pr_warning(" RX IPC Checksum Offload not configured.\n");
priv->plat->rx_coe = STMMAC_RX_COE_NONE;
}
if (priv->plat->rx_coe)
pr_info(" RX Checksum Offload Engine supported (type %d)\n",
priv->plat->rx_coe);
if (priv->plat->tx_coe) if (priv->plat->tx_coe)
pr_info(" TX Checksum insertion supported\n"); pr_info(" TX Checksum insertion supported\n");
......
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