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:
Deepak SIKRI 2012-04-04 04:33:21 +00:00 committed by David S. Miller
parent 55f9a4d6fa
commit 38912bdbde
7 changed files with 58 additions and 24 deletions

View File

@ -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 */

View File

@ -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,

View File

@ -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,

View File

@ -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 = {

View File

@ -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 = {

View File

@ -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;

View File

@ -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");