From patchwork Thu Mar 13 06:56:02 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Byungho An X-Patchwork-Id: 3822141 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 86FBBBF540 for ; Thu, 13 Mar 2014 06:56:14 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 3F49E2021F for ; Thu, 13 Mar 2014 06:56:13 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id AE82B2020A for ; Thu, 13 Mar 2014 06:56:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753149AbaCMG4G (ORCPT ); Thu, 13 Mar 2014 02:56:06 -0400 Received: from mailout1.samsung.com ([203.254.224.24]:48979 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751158AbaCMG4D (ORCPT ); Thu, 13 Mar 2014 02:56:03 -0400 Received: from epcpsbgr2.samsung.com (u142.gpu120.samsung.co.kr [203.254.230.142]) by mailout1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTP id <0N2D0028J4LEGYA0@mailout1.samsung.com>; Thu, 13 Mar 2014 15:56:02 +0900 (KST) Received: from epcpsbgm2.samsung.com ( [203.254.230.49]) by epcpsbgr2.samsung.com (EPCPMTA) with SMTP id 80.8B.09028.28651235; Thu, 13 Mar 2014 15:56:02 +0900 (KST) X-AuditID: cbfee68e-b7f566d000002344-db-532156826f12 Received: from epmmp1.local.host ( [203.254.227.16]) by epcpsbgm2.samsung.com (EPCPMTA) with SMTP id 3E.B5.28157.28651235; Thu, 13 Mar 2014 15:56:02 +0900 (KST) Received: from DObh74an01 ([12.36.166.149]) by mmp1.samsung.com (Oracle Communications Messaging Server 7u4-24.01 (7.0.4.24.0) 64bit (built Nov 17 2011)) with ESMTPA id <0N2D005TM4LESQ40@mmp1.samsung.com>; Thu, 13 Mar 2014 15:56:02 +0900 (KST) From: Byungho An To: netdev@vger.kernel.org, linux-samsung-soc@vger.kernel.org Cc: davem@davemloft.net, ilho215.lee@samsung.com, vipul.pandya@samsung.com, 'Joe Perches' Subject: [PATCH V2 RE-SEND 4/7] net: sxgbe: add Checksum offload support for Samsung sxgbe Date: Thu, 13 Mar 2014 15:56:02 +0900 Message-id: <007d01cf3e89$4be479e0$e3ad6da0$%an@samsung.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit X-Mailer: Microsoft Office Outlook 12.0 Thread-index: Ac8+iUvMUIbp6aCrSjuv2UH5Eld9Gg== Content-language: ko X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFjrBIsWRmVeSWpSXmKPExsVy+t8zQ92mMMVgg2knpS2unjvGaDHnfAuL xdF/CxktZt9/zGLRu+Aqm8WM8/uYLI4tELPYtuACswOHx5aVN5k8vqy6xuzRt2UVo8fnTXIB LFFcNimpOZllqUX6dglcGTM/LWYp6PGpuD71FksD41K7LkZODgkBE4klDz+xQNhiEhfurWfr YuTiEBJYxiix6E4/C0zR8qX32SESixglrnfMhXJ+M0rMun2LHaSKTUBNonnmZTYQW0TAVmLJ kc9gcWaBXIk/yzYzg9jCAjESn7qvgk1lEVCV+Hn1OFgNr4CNxJGGuywQtqDEj8n3WCB6tSTW 7zzOBGHLS2xe8xZoDgfQReoSj/7qQqzSk/ix4DIzRImIxL4X7xghjj7HLnH0mijEKgGJb5MP sUC0ykpsOsAMUSIpcXDFDZYJjGKzkCyehWTxLCSLZyHZsICRZRWjaGpBckFxUnqRkV5xYm5x aV66XnJ+7iZGSCz27WC8ecD6EGMy0PqJzFKiyfnAWM4riTc0NjOyMDUxNTYytzQjTVhJnHfR w6QgIYH0xJLU7NTUgtSi+KLSnNTiQ4xMHJxSDYxSTZ9UOkMWMJodypxoPOEfi+a04EjhgJP7 D4eKmHi2H59m8zar7FJZ5J4TB/lT1jLcS0kKydQr1lnvEn7y50rjvTKslZMeBqusf2So9GW5 qOE3NqaljcWX0tm44+4KhGso3r19kWlR/XLPjMyCml0zdF7a8U7giVzJzmR7Q0N/Z7rcP77J VkosxRmJhlrMRcWJAABtgw/bAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrGKsWRmVeSWpSXmKPExsVy+t9jAd2mMMVgg77/ohZXzx1jtJhzvoXF 4ui/hYwWs+8/ZrHoXXCVzWLG+X1MFscWiFlsW3CB2YHDY8vKm0weX1ZdY/bo27KK0ePzJrkA lqgGRpuM1MSU1CKF1Lzk/JTMvHRbJe/geOd4UzMDQ11DSwtzJYW8xNxUWyUXnwBdt8wcoDOU FMoSc0qBQgGJxcVK+naYJoSGuOlawDRG6PqGBMH1GBmggYR1jBkzPy1mKejxqbg+9RZLA+NS uy5GTg4JAROJ5Uvvs0PYYhIX7q1n62Lk4hASWMQocb1jLjuE85tRYtbtW2BVbAJqEs0zL7OB 2CICthJLjnwGizML5Er8WbaZGcQWFoiR+NR9lQXEZhFQlfh59ThYDa+AjcSRhrssELagxI/J 91ggerUk1u88zgRhy0tsXvMWaA4H0EXqEo/+6kKs0pP4seAyM0SJiMS+F+8YJzAKzEIyaRaS SbOQTJqFpGUBI8sqRtHUguSC4qT0XCO94sTc4tK8dL3k/NxNjOBYfya9g3FVg8UhRgEORiUe 3hXLFYKFWBPLiitzDzFKcDArifB6+igGC/GmJFZWpRblxxeV5qQWH2JMBnp0IrOUaHI+MA3l lcQbGpuYGVkamVkYmZibkyasJM57sNU6UEggPbEkNTs1tSC1CGYLEwenVAMjb2F3sqzzgerl /Fn1r9TSBIwnH77vpbc+Z1dyxt2ZjRNZ4xXqW7XnfK9mVPlj576Yfx/n3028eb5M5xr8rKPv pal13jtzYhtX0/HFJz64zvzaFDi/YZ9l2sopi6VWfzXSPSUsvnOT0yG/nDumu3VSXPqfSOi4 WIVXcgndDzHg2lwyObVWMFSJpTgj0VCLuag4EQCWPkzyOQMAAA== DLP-Filter: Pass X-MTR: 20000000000000000@CPGS X-CFilter-Loop: Reflected Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vipul Pandya This patch adds TX and RX checksum offload support. Signed-off-by: Vipul Pandya Neatening-by: Joe Perches Signed-off-by: Byungho An --- drivers/net/ethernet/samsung/sxgbe_common.h | 6 +++- drivers/net/ethernet/samsung/sxgbe_core.c | 20 ++++++++++++ drivers/net/ethernet/samsung/sxgbe_desc.c | 27 ++++++++++++---- drivers/net/ethernet/samsung/sxgbe_desc.h | 6 ++-- drivers/net/ethernet/samsung/sxgbe_main.c | 46 ++++++++++++++++++++------- 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/drivers/net/ethernet/samsung/sxgbe_common.h b/drivers/net/ethernet/samsung/sxgbe_common.h index 21d8ee6..68e8ad4 100644 --- a/drivers/net/ethernet/samsung/sxgbe_common.h +++ b/drivers/net/ethernet/samsung/sxgbe_common.h @@ -347,6 +347,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); @@ -462,7 +466,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; diff --git a/drivers/net/ethernet/samsung/sxgbe_core.c b/drivers/net/ethernet/samsung/sxgbe_core.c index bf93b16..5885fd6 100644 --- a/drivers/net/ethernet/samsung/sxgbe_core.c +++ 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) diff --git a/drivers/net/ethernet/samsung/sxgbe_desc.c b/drivers/net/ethernet/samsung/sxgbe_desc.c index fa21236..8d9ee61 100644 --- a/drivers/net/ethernet/samsung/sxgbe_desc.c +++ 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 */ diff --git a/drivers/net/ethernet/samsung/sxgbe_desc.h b/drivers/net/ethernet/samsung/sxgbe_desc.h index 976d5ac..032789c 100644 --- a/drivers/net/ethernet/samsung/sxgbe_desc.h +++ 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); diff --git a/drivers/net/ethernet/samsung/sxgbe_main.c b/drivers/net/ethernet/samsung/sxgbe_main.c index cd09cdd..e6b4406 100644 --- a/drivers/net/ethernet/samsung/sxgbe_main.c +++ 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); } } @@ -1402,7 +1403,7 @@ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev) /* prepare the descriptor */ priv->hw->desc->prepare_tx_desc(tx_desc, 0, len, - len); + len, cksum_flag); /* memory barrier to flush descriptor */ wmb(); @@ -1528,6 +1529,8 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) unsigned int entry = priv->rxq[qnum]->cur_rx; unsigned int next_entry = 0; unsigned int count = 0; + int checksum; + int status; while (count < limit) { struct sxgbe_rx_norm_desc *p; @@ -1544,7 +1547,18 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) next_entry = (++priv->rxq[qnum]->cur_rx) % rxsize; prefetch(priv->rxq[qnum]->dma_rx + next_entry); - /*TO DO read the status of the incoming frame */ + /* Read the status of the incoming frame and also get checksum + * value based on whether it is enabled in SXGBE hardware or + * not. + */ + status = priv->hw->desc->rx_wbstatus(p, &priv->xstats, + &checksum); + if (unlikely(status < 0)) { + entry = next_entry; + continue; + } + if (unlikely(!priv->rxcsum_insertion)) + checksum = CHECKSUM_NONE; skb = priv->rxq[qnum]->rx_skbuff[entry]; @@ -1558,7 +1572,11 @@ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) skb_put(skb, frame_len); - netif_receive_skb(skb); + skb->ip_summed = checksum; + if (checksum == CHECKSUM_NONE) + netif_receive_skb(skb); + else + napi_gro_receive(&priv->napi, skb); entry = next_entry; } @@ -1789,15 +1807,15 @@ static int sxgbe_set_features(struct net_device *dev, { struct sxgbe_priv_data *priv = netdev_priv(dev); netdev_features_t changed = dev->features ^ features; - u32 ctrl; if (changed & NETIF_F_RXCSUM) { - ctrl = readl(priv->ioaddr + SXGBE_CORE_RX_CONFIG_REG); - if (features & NETIF_F_RXCSUM) - ctrl |= SXGBE_RX_CSUMOFFLOAD_ENABLE; - else - ctrl &= ~SXGBE_RX_CSUMOFFLOAD_ENABLE; - writel(ctrl, priv->ioaddr + SXGBE_CORE_RX_CONFIG_REG); + if (features & NETIF_F_RXCSUM) { + priv->hw->mac->enable_rx_csum(priv->ioaddr); + priv->rxcsum_insertion = true; + } else { + priv->hw->mac->disable_rx_csum(priv->ioaddr); + priv->rxcsum_insertion = false; + } } return 0; @@ -2163,6 +2181,12 @@ struct sxgbe_priv_data *sxgbe_dvr_probe(struct device *device, } } + /* Enable Rx checksum offload */ + if (priv->hw_cap.rx_csum_offload) { + priv->hw->mac->enable_rx_csum(priv->ioaddr); + priv->rxcsum_insertion = true; + } + /* Rx Watchdog is available, enable depend on platform data */ if (!priv->plat->riwt_off) { priv->use_riwt = 1;