diff options
author | Vipul Pandya <vipul.pandya@samsung.com> | 2014-03-25 15:11:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-03-26 16:49:31 -0400 |
commit | 8f7807ae41bb57e003b7dc07e83e186d11747bde (patch) | |
tree | 217e4b7a92a05ee7ef1527eb51e554cea9090f15 /drivers/net | |
parent | 1051125d8d57b6ff074d450c10ccbe0e39856456 (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')
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_common.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_core.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_desc.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 46 |
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 | ||
345 | const struct sxgbe_core_ops *sxgbe_get_core_ops(void); | 349 | const 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 | ||
221 | static 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 | |||
230 | static 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 | |||
221 | const struct sxgbe_core_ops core_ops = { | 239 | const 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 | ||
239 | const struct sxgbe_core_ops *sxgbe_get_core_ops(void) | 259 | const 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, | |||
1252 | static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev) | 1252 | static 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; |