forked from Minki/linux
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: Deepak Sikri <deepak.sikri@st.com> Hacked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
55f9a4d6fa
commit
38912bdbde
@ -228,7 +228,7 @@ struct stmmac_desc_ops {
|
||||
int (*get_rx_owner) (struct dma_desc *p);
|
||||
void (*set_rx_owner) (struct dma_desc *p);
|
||||
/* 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 */
|
||||
int (*rx_status) (void *data, struct stmmac_extra_stats *x,
|
||||
struct dma_desc *p);
|
||||
@ -261,8 +261,8 @@ struct stmmac_dma_ops {
|
||||
struct stmmac_ops {
|
||||
/* MAC core initialization */
|
||||
void (*core_init) (void __iomem *ioaddr) ____cacheline_aligned;
|
||||
/* Support checksum offload engine */
|
||||
int (*rx_coe) (void __iomem *ioaddr);
|
||||
/* Enable and verify that the IPC module is supported */
|
||||
int (*rx_ipc) (void __iomem *ioaddr);
|
||||
/* Dump MAC registers */
|
||||
void (*dump_regs) (void __iomem *ioaddr);
|
||||
/* Handle extra events on specific interrupts hw dependent */
|
||||
|
@ -46,7 +46,7 @@ static void dwmac1000_core_init(void __iomem *ioaddr)
|
||||
#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);
|
||||
|
||||
@ -211,7 +211,7 @@ static void dwmac1000_irq_status(void __iomem *ioaddr)
|
||||
|
||||
static const struct stmmac_ops dwmac1000_ops = {
|
||||
.core_init = dwmac1000_core_init,
|
||||
.rx_coe = dwmac1000_rx_coe_supported,
|
||||
.rx_ipc = dwmac1000_rx_ipc_enable,
|
||||
.dump_regs = dwmac1000_dump_regs,
|
||||
.host_irq_status = dwmac1000_irq_status,
|
||||
.set_filter = dwmac1000_set_filter,
|
||||
|
@ -43,11 +43,6 @@ static void dwmac100_core_init(void __iomem *ioaddr)
|
||||
#endif
|
||||
}
|
||||
|
||||
static int dwmac100_rx_coe_supported(void __iomem *ioaddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
|
||||
{
|
||||
pr_info("\t----------------------------------------------\n"
|
||||
@ -72,6 +67,11 @@ static void dwmac100_dump_mac_regs(void __iomem *ioaddr)
|
||||
readl(ioaddr + MAC_VLAN2));
|
||||
}
|
||||
|
||||
static int dwmac100_rx_ipc_enable(void __iomem *ioaddr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwmac100_irq_status(void __iomem *ioaddr)
|
||||
{
|
||||
return;
|
||||
@ -160,7 +160,7 @@ static void dwmac100_pmt(void __iomem *ioaddr, unsigned long mode)
|
||||
|
||||
static const struct stmmac_ops dwmac100_ops = {
|
||||
.core_init = dwmac100_core_init,
|
||||
.rx_coe = dwmac100_rx_coe_supported,
|
||||
.rx_ipc = dwmac100_rx_ipc_enable,
|
||||
.dump_regs = dwmac100_dump_mac_regs,
|
||||
.host_irq_status = dwmac100_irq_status,
|
||||
.set_filter = dwmac100_set_filter,
|
||||
|
@ -22,6 +22,7 @@
|
||||
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/stmmac.h>
|
||||
#include "common.h"
|
||||
#include "descs_com.h"
|
||||
|
||||
@ -309,9 +310,17 @@ static void enh_desc_close_tx_desc(struct dma_desc *p)
|
||||
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)
|
||||
{
|
||||
return p->des01.erx.frame_length;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
const struct stmmac_desc_ops enh_desc_ops = {
|
||||
|
@ -22,6 +22,7 @@
|
||||
Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/stmmac.h>
|
||||
#include "common.h"
|
||||
#include "descs_com.h"
|
||||
|
||||
@ -201,9 +202,17 @@ static void ndesc_close_tx_desc(struct dma_desc *p)
|
||||
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)
|
||||
{
|
||||
return p->des01.rx.frame_length;
|
||||
/* 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;
|
||||
}
|
||||
|
||||
const struct stmmac_desc_ops ndesc_ops = {
|
||||
|
@ -56,8 +56,6 @@ struct stmmac_priv {
|
||||
|
||||
struct stmmac_extra_stats xstats;
|
||||
struct napi_struct napi;
|
||||
|
||||
int rx_coe;
|
||||
int no_csum_insertion;
|
||||
|
||||
struct phy_device *phydev;
|
||||
|
@ -1282,7 +1282,8 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
|
||||
struct sk_buff *skb;
|
||||
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
|
||||
* Type frames (LLC/LLC-SNAP) */
|
||||
if (unlikely(status != llc_snap))
|
||||
@ -1318,7 +1319,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit)
|
||||
#endif
|
||||
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 */
|
||||
skb_checksum_none_assert(skb);
|
||||
netif_receive_skb(skb);
|
||||
@ -1465,8 +1466,10 @@ static netdev_features_t stmmac_fix_features(struct net_device *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;
|
||||
else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
|
||||
features &= ~NETIF_F_IPV6_CSUM;
|
||||
if (!priv->plat->tx_coe)
|
||||
features &= ~NETIF_F_ALL_CSUM;
|
||||
|
||||
@ -1769,17 +1772,32 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
|
||||
* register (if supported).
|
||||
*/
|
||||
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->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
|
||||
pr_info(" No HW DMA feature register supported");
|
||||
|
||||
/* Select the enhnaced/normal descriptor structures */
|
||||
stmmac_selec_desc_mode(priv);
|
||||
|
||||
priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
|
||||
if (priv->rx_coe)
|
||||
pr_info(" RX Checksum Offload Engine supported\n");
|
||||
/* Enable the IPC (Checksum Offload) and check if the feature has been
|
||||
* enabled during the core configuration. */
|
||||
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)
|
||||
pr_info(" TX Checksum insertion supported\n");
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user