b/drivers/net/ethernet/samsung/sxgbe_common.h
@@ -351,6 +351,10 @@ struct sxgbe_core_ops {
void (*set_eee_timer)(void __iomem *ioaddr, const int ls,
const int tw);
void (*set_eee_pls)(void __iomem *ioaddr, const int link);
+
+ /* Enable disable checksum offload operations */
+ void (*enable_rx_csum)(void __iomem *ioaddr);
+ void (*disable_rx_csum)(void __iomem *ioaddr);
};
const struct sxgbe_core_ops *sxgbe_get_core_ops(void);
@@ -466,7 +470,7 @@ struct sxgbe_priv_data {
struct net_device *dev;
struct device *device;
struct sxgbe_ops *hw;/* sxgbe specific ops */
- int no_csum_insertion;
+ int rxcsum_insertion;
spinlock_t lock;
spinlock_t stats_lock;
b/drivers/net/ethernet/samsung/sxgbe_core.c
@@ -217,6 +217,24 @@ static void sxgbe_set_eee_timer(void __iomem *ioaddr,
writel(value, ioaddr + SXGBE_CORE_LPI_TIMER_CTRL);
}
+static void sxgbe_enable_rx_csum(void __iomem *ioaddr)
+{
+ u32 ctrl;
+
+ ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
+ ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE;
+ writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
+}
+
+static void sxgbe_disable_rx_csum(void __iomem *ioaddr)
+{
+ u32 ctrl;
+
+ ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
+ ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE;
+ writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
+}
+
const struct sxgbe_core_ops core_ops = {
.core_init = sxgbe_core_init,
.dump_regs = sxgbe_core_dump_regs,
@@ -233,6 +251,8 @@ const struct sxgbe_core_ops core_ops = {
.reset_eee_mode = sxgbe_reset_eee_mode,
.set_eee_timer = sxgbe_set_eee_timer,
.set_eee_pls = sxgbe_set_eee_pls,
+ .enable_rx_csum = sxgbe_enable_rx_csum,
+ .disable_rx_csum = sxgbe_disable_rx_csum,
};
const struct sxgbe_core_ops *sxgbe_get_core_ops(void)
b/drivers/net/ethernet/samsung/sxgbe_desc.c
@@ -47,6 +47,9 @@ static void sxgbe_prepare_tx_desc(struct
sxgbe_tx_norm_desc *p, u8 is_fd,
p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.total_pkt_len =
pkt_len;
+ if (cksum)
+ p->tdes23.tx_rd_des23.tx_pkt_len.cksum_pktlen.cksum_ctl =
+ cic_full;
}
/* Set VLAN control information */
@@ -250,31 +253,40 @@ static int sxgbe_get_rx_ld_status(struct
sxgbe_rx_norm_desc *p)
/* Return the RX status looking at the WB fields */
-static void sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc *p,
- struct sxgbe_extra_stats *x)
+static int sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc *p,
+ struct sxgbe_extra_stats *x, int *checksum)
{
+ int status = 0;
+ *checksum = CHECKSUM_UNNECESSARY;
if (p->rdes23.rx_wb_des23.err_summary) {
switch (p->rdes23.rx_wb_des23.err_l2_type) {
case RX_GMII_ERR:
+ status = -EINVAL;
x->rx_code_gmii_err++;
break;
case RX_WATCHDOG_ERR:
+ status = -EINVAL;
x->rx_watchdog_err++;
break;
case RX_CRC_ERR:
+ status = -EINVAL;
x->rx_crc_err++;
break;
case RX_GAINT_ERR:
+ status = -EINVAL;
x->rx_gaint_pkt_err++;
break;
case RX_IP_HDR_ERR:
+ *checksum = CHECKSUM_NONE;
x->ip_hdr_err++;
break;
case RX_PAYLOAD_ERR:
+ *checksum = CHECKSUM_NONE;
x->ip_payload_err++;
break;
case RX_OVERFLOW_ERR:
+ status = -EINVAL;
x->overflow_error++;
break;
default:
@@ -366,12 +378,14 @@ static void sxgbe_rx_wbstatus(struct
sxgbe_rx_norm_desc *p,
if (p->rdes23.rx_wb_des23.vlan_filter_match)
x->vlan_filter_match++;
- if (p->rdes23.rx_wb_des23.sa_filter_fail)
+ if (p->rdes23.rx_wb_des23.sa_filter_fail) {
+ status = -EINVAL;
x->sa_filter_fail++;
-
- if (p->rdes23.rx_wb_des23.da_filter_fail)
+ }
+ if (p->rdes23.rx_wb_des23.da_filter_fail) {
+ status = -EINVAL;
x->da_filter_fail++;
-
+ }
if (p->rdes23.rx_wb_des23.hash_filter_pass)
x->hash_filter_pass++;
@@ -381,6 +395,7 @@ static void sxgbe_rx_wbstatus(struct sxgbe_rx_norm_desc
*p,
if (p->rdes23.rx_wb_des23.l4_filter_match)
x->l4_filter_match++;
+ return status;
}
/* Get own bit of context descriptor */
b/drivers/net/ethernet/samsung/sxgbe_desc.h
@@ -113,7 +113,7 @@ struct sxgbe_rx_norm_desc {
/* WB RDES3 */
u32 pkt_len:14;
u32 rdes3_reserved:1;
- u32 err_summary:15;
+ u32 err_summary:1;
u32 err_l2_type:4;
u32 layer34_pkt_type:4;
u32 no_coagulation_pkt:1;
@@ -273,8 +273,8 @@ struct sxgbe_desc_ops {
int (*get_rx_ld_status)(struct sxgbe_rx_norm_desc *p);
/* Return the reception status looking at the RDES1 */
- void (*rx_wbstatus)(struct sxgbe_rx_norm_desc *p,
- struct sxgbe_extra_stats *x);
+ int (*rx_wbstatus)(struct sxgbe_rx_norm_desc *p,
+ struct sxgbe_extra_stats *x, int *checksum);
/* Get own bit */
int (*get_rx_ctxt_owner)(struct sxgbe_rx_ctxt_desc *p);
b/drivers/net/ethernet/samsung/sxgbe_main.c
@@ -1314,6 +1314,7 @@ void sxgbe_tso_prepare(struct sxgbe_priv_data *priv,
static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned int entry, frag_num;
+ int cksum_flag = 0;
struct netdev_queue *dev_txq;
unsigned txq_index = skb_get_queue_mapping(skb);
struct sxgbe_priv_data *priv = netdev_priv(dev);
@@ -1385,7 +1386,7 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb,
struct net_device *dev)
__func__);
priv->hw->desc->prepare_tx_desc(tx_desc, 1,
no_pagedlen,
- no_pagedlen);
+ no_pagedlen,
cksum_flag);