aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/samsung
diff options
context:
space:
mode:
authorVipul Pandya <vipul.pandya@samsung.com>2014-03-25 15:11:02 -0400
committerDavid S. Miller <davem@davemloft.net>2014-03-26 16:49:31 -0400
commit8f7807ae41bb57e003b7dc07e83e186d11747bde (patch)
tree217e4b7a92a05ee7ef1527eb51e554cea9090f15 /drivers/net/ethernet/samsung
parent1051125d8d57b6ff074d450c10ccbe0e39856456 (diff)
net: sxgbe: add Checksum offload support for Samsung sxgbe
This patch adds TX and RX checksum offload support. Signed-off-by: Vipul Pandya <vipul.pandya@samsung.com> Neatening-by: Joe Perches <joe@perches.com> Signed-off-by: Byungho An <bh74.an@samsung.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/samsung')
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h5
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c20
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h2
-rw-r--r--drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c46
4 files changed, 61 insertions, 12 deletions
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
index 7293c4c14be8..4893cfd298a7 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h
@@ -340,6 +340,10 @@ struct sxgbe_core_ops {
340 void (*set_eee_timer)(void __iomem *ioaddr, const int ls, 340 void (*set_eee_timer)(void __iomem *ioaddr, const int ls,
341 const int tw); 341 const int tw);
342 void (*set_eee_pls)(void __iomem *ioaddr, const int link); 342 void (*set_eee_pls)(void __iomem *ioaddr, const int link);
343
344 /* Enable disable checksum offload operations */
345 void (*enable_rx_csum)(void __iomem *ioaddr);
346 void (*disable_rx_csum)(void __iomem *ioaddr);
343}; 347};
344 348
345const struct sxgbe_core_ops *sxgbe_get_core_ops(void); 349const struct sxgbe_core_ops *sxgbe_get_core_ops(void);
@@ -452,6 +456,7 @@ struct sxgbe_priv_data {
452 struct sxgbe_ops *hw; /* sxgbe specific ops */ 456 struct sxgbe_ops *hw; /* sxgbe specific ops */
453 int no_csum_insertion; 457 int no_csum_insertion;
454 int irq; 458 int irq;
459 int rxcsum_insertion;
455 spinlock_t stats_lock; /* lock for tx/rx statatics */ 460 spinlock_t stats_lock; /* lock for tx/rx statatics */
456 461
457 struct phy_device *phydev; 462 struct phy_device *phydev;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
index 01647901f55f..66d4a74a137c 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c
@@ -218,6 +218,24 @@ static void sxgbe_set_eee_timer(void __iomem *ioaddr,
218 writel(value, ioaddr + SXGBE_CORE_LPI_TIMER_CTRL); 218 writel(value, ioaddr + SXGBE_CORE_LPI_TIMER_CTRL);
219} 219}
220 220
221static void sxgbe_enable_rx_csum(void __iomem *ioaddr)
222{
223 u32 ctrl;
224
225 ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
226 ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE;
227 writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
228}
229
230static void sxgbe_disable_rx_csum(void __iomem *ioaddr)
231{
232 u32 ctrl;
233
234 ctrl = readl(ioaddr + SXGBE_CORE_RX_CONFIG_REG);
235 ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE;
236 writel(ctrl, ioaddr + SXGBE_CORE_RX_CONFIG_REG);
237}
238
221const struct sxgbe_core_ops core_ops = { 239const struct sxgbe_core_ops core_ops = {
222 .core_init = sxgbe_core_init, 240 .core_init = sxgbe_core_init,
223 .dump_regs = sxgbe_core_dump_regs, 241 .dump_regs = sxgbe_core_dump_regs,
@@ -234,6 +252,8 @@ const struct sxgbe_core_ops core_ops = {
234 .reset_eee_mode = sxgbe_reset_eee_mode, 252 .reset_eee_mode = sxgbe_reset_eee_mode,
235 .set_eee_timer = sxgbe_set_eee_timer, 253 .set_eee_timer = sxgbe_set_eee_timer,
236 .set_eee_pls = sxgbe_set_eee_pls, 254 .set_eee_pls = sxgbe_set_eee_pls,
255 .enable_rx_csum = sxgbe_enable_rx_csum,
256 .disable_rx_csum = sxgbe_disable_rx_csum,
237}; 257};
238 258
239const struct sxgbe_core_ops *sxgbe_get_core_ops(void) 259const struct sxgbe_core_ops *sxgbe_get_core_ops(void)
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
index 6d44b9faf64e..838cb9fb0ea9 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h
@@ -113,7 +113,7 @@ struct sxgbe_rx_norm_desc {
113 /* WB RDES3 */ 113 /* WB RDES3 */
114 u32 pkt_len:14; 114 u32 pkt_len:14;
115 u32 rdes3_reserved:1; 115 u32 rdes3_reserved:1;
116 u32 err_summary:15; 116 u32 err_summary:1;
117 u32 err_l2_type:4; 117 u32 err_l2_type:4;
118 u32 layer34_pkt_type:4; 118 u32 layer34_pkt_type:4;
119 u32 no_coagulation_pkt:1; 119 u32 no_coagulation_pkt:1;
diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
index dc0249bfa03b..96b4b2c25b16 100644
--- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
+++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
@@ -1252,6 +1252,7 @@ void sxgbe_tso_prepare(struct sxgbe_priv_data *priv,
1252static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev) 1252static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
1253{ 1253{
1254 unsigned int entry, frag_num; 1254 unsigned int entry, frag_num;
1255 int cksum_flag = 0;
1255 struct netdev_queue *dev_txq; 1256 struct netdev_queue *dev_txq;
1256 unsigned txq_index = skb_get_queue_mapping(skb); 1257 unsigned txq_index = skb_get_queue_mapping(skb);
1257 struct sxgbe_priv_data *priv = netdev_priv(dev); 1258 struct sxgbe_priv_data *priv = netdev_priv(dev);
@@ -1332,7 +1333,7 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
1332 __func__); 1333 __func__);
1333 1334
1334 priv->hw->desc->prepare_tx_desc(tx_desc, 1, no_pagedlen, 1335 priv->hw->desc->prepare_tx_desc(tx_desc, 1, no_pagedlen,
1335 no_pagedlen, 0); 1336 no_pagedlen, cksum_flag);
1336 } 1337 }
1337 } 1338 }
1338 1339
@@ -1350,7 +1351,7 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev)
1350 1351
1351 /* prepare the descriptor */ 1352 /* prepare the descriptor */
1352 priv->hw->desc->prepare_tx_desc(tx_desc, 0, len, 1353 priv->hw->desc->prepare_tx_desc(tx_desc, 0, len,
1353 len, 0); 1354 len, cksum_flag);
1354 /* memory barrier to flush descriptor */ 1355 /* memory barrier to flush descriptor */
1355 wmb(); 1356 wmb();
1356 1357
@@ -1471,6 +1472,8 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit)
1471 unsigned int entry = priv->rxq[qnum]->cur_rx; 1472 unsigned int entry = priv->rxq[qnum]->cur_rx;
1472 unsigned int next_entry = 0; 1473 unsigned int next_entry = 0;
1473 unsigned int count = 0; 1474 unsigned int count = 0;
1475 int checksum;
1476 int status;
1474 1477
1475 while (count < limit) { 1478 while (count < limit) {
1476 struct sxgbe_rx_norm_desc *p; 1479 struct sxgbe_rx_norm_desc *p;
@@ -1487,7 +1490,18 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit)
1487 next_entry = (++priv->rxq[qnum]->cur_rx) % rxsize; 1490 next_entry = (++priv->rxq[qnum]->cur_rx) % rxsize;
1488 prefetch(priv->rxq[qnum]->dma_rx + next_entry); 1491 prefetch(priv->rxq[qnum]->dma_rx + next_entry);
1489 1492
1490 /*TO DO read the status of the incoming frame */ 1493 /* Read the status of the incoming frame and also get checksum
1494 * value based on whether it is enabled in SXGBE hardware or
1495 * not.
1496 */
1497 status = priv->hw->desc->rx_wbstatus(p, &priv->xstats,
1498 &checksum);
1499 if (unlikely(status < 0)) {
1500 entry = next_entry;
1501 continue;
1502 }
1503 if (unlikely(!priv->rxcsum_insertion))
1504 checksum = CHECKSUM_NONE;
1491 1505
1492 skb = priv->rxq[qnum]->rx_skbuff[entry]; 1506 skb = priv->rxq[qnum]->rx_skbuff[entry];
1493 1507
@@ -1501,7 +1515,11 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit)
1501 1515
1502 skb_put(skb, frame_len); 1516 skb_put(skb, frame_len);
1503 1517
1504 netif_receive_skb(skb); 1518 skb->ip_summed = checksum;
1519 if (checksum == CHECKSUM_NONE)
1520 netif_receive_skb(skb);
1521 else
1522 napi_gro_receive(&priv->napi, skb);
1505 1523
1506 entry = next_entry; 1524 entry = next_entry;
1507 } 1525 }
@@ -1748,15 +1766,15 @@ static int sxgbe_set_features(struct net_device *dev,
1748{ 1766{
1749 struct sxgbe_priv_data *priv = netdev_priv(dev); 1767 struct sxgbe_priv_data *priv = netdev_priv(dev);
1750 netdev_features_t changed = dev->features ^ features; 1768 netdev_features_t changed = dev->features ^ features;
1751 u32 ctrl;
1752 1769
1753 if (changed & NETIF_F_RXCSUM) { 1770 if (changed & NETIF_F_RXCSUM) {
1754 ctrl = readl(priv->ioaddr + SXGBE_CORE_RX_CONFIG_REG); 1771 if (features & NETIF_F_RXCSUM) {
1755 if (features & NETIF_F_RXCSUM) 1772 priv->hw->mac->enable_rx_csum(priv->ioaddr);
1756 ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE; 1773 priv->rxcsum_insertion = true;
1757 else 1774 } else {
1758 ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE; 1775 priv->hw->mac->disable_rx_csum(priv->ioaddr);
1759 writel(ctrl, priv->ioaddr + SXGBE_CORE_RX_CONFIG_REG); 1776 priv->rxcsum_insertion = false;
1777 }
1760 } 1778 }
1761 1779
1762 return 0; 1780 return 0;
@@ -2115,6 +2133,12 @@ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device,
2115 } 2133 }
2116 } 2134 }
2117 2135
2136 /* Enable Rx checksum offload */
2137 if (priv->hw_cap.rx_csum_offload) {
2138 priv->hw->mac->enable_rx_csum(priv->ioaddr);
2139 priv->rxcsum_insertion = true;
2140 }
2141
2118 /* Rx Watchdog is available, enable depend on platform data */ 2142 /* Rx Watchdog is available, enable depend on platform data */
2119 if (!priv->plat->riwt_off) { 2143 if (!priv->plat->riwt_off) {
2120 priv->use_riwt = 1; 2144 priv->use_riwt = 1;