From patchwork Mon Mar 18 08:28:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057726 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8TN3Wbwz9s47; Mon, 18 Mar 2019 19:28:24 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5nd5-00088w-A8; Mon, 18 Mar 2019 08:28:19 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5nd3-00087N-4L for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:28:17 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5nd2-0000Vx-0h for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:28:16 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 01/12] net-next: hinic: fix a problem in free_tx_poll() Date: Mon, 18 Mar 2019 16:28:12 +0800 Message-Id: <20190318082812.26711-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Zhao Chen BugLink: https://bugs.launchpad.net/bugs/1820187 This patch fixes the problem below. The problem can be reproduced by the following steps: 1) Connecting all HiNIC interfaces 2) On server side # sudo ifconfig eth0 192.168.100.1 up #Using MLX CX4 card # iperf -s 3) On client side # sudo ifconfig eth0 192.168.100.2 up #Using our HiNIC card # iperf -c 192.168.101.1 -P 10 -t 100000 after hours of testing, we will see errors: hinic 0000:05:00.0: No MGMT msg handler, mod = 0 hinic 0000:05:00.0: No MGMT msg handler, mod = 0 hinic 0000:05:00.0: No MGMT msg handler, mod = 0 hinic 0000:05:00.0: No MGMT msg handler, mod = 0 The errors are caused by the following problem. 1) The hinic_get_wqe() checks the "wq->delta" to allocate new WQEs: if (atomic_sub_return(num_wqebbs, &wq->delta) <= 0) { atomic_add(num_wqebbs, &wq->delta); return ERR_PTR(-EBUSY); } If the WQE occupies multiple pages, the shadow WQE will be used. Then the hinic_xmit_frame() fills the WQE. 2) While in parallel with 1), the free_tx_poll() checks the "wq->delta" to free old WQEs: if ((atomic_read(&wq->delta) + num_wqebbs) > wq->q_depth) return ERR_PTR(-EBUSY); There is a probability that the shadow WQE which hinic_xmit_frame() is using will be damaged by copy_wqe_to_shadow(): if (curr_pg != end_pg) { void *shadow_addr = &wq->shadow_wqe[curr_pg * wq->max_wqe_size]; copy_wqe_to_shadow(wq, shadow_addr, num_wqebbs, *cons_idx); return shadow_addr; } This can cause WQE data error and you will see the above error messages. This patch fixes the problem. Signed-off-by: Zhao Chen Signed-off-by: David S. Miller (cherry picked from commit 9c2956d2ad9e0e7d5827290ba9a716ed3fb83bcd) Signed-off-by: Ike Panhc --- .../net/ethernet/huawei/hinic/hinic_hw_qp.c | 36 ++++++++++++++----- .../net/ethernet/huawei/hinic/hinic_hw_qp.h | 6 +++- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 18 ++++++++-- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c index b9db6d649743..cb239627770f 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c @@ -635,17 +635,18 @@ void hinic_sq_write_wqe(struct hinic_sq *sq, u16 prod_idx, } /** - * hinic_sq_read_wqe - read wqe ptr in the current ci and update the ci + * hinic_sq_read_wqebb - read wqe ptr in the current ci and update the ci, the + * wqe only have one wqebb * @sq: send queue * @skb: return skb that was saved - * @wqe_size: the size of the wqe + * @wqe_size: the wqe size ptr * @cons_idx: consumer index of the wqe * * Return wqe in ci position **/ -struct hinic_sq_wqe *hinic_sq_read_wqe(struct hinic_sq *sq, - struct sk_buff **skb, - unsigned int *wqe_size, u16 *cons_idx) +struct hinic_sq_wqe *hinic_sq_read_wqebb(struct hinic_sq *sq, + struct sk_buff **skb, + unsigned int *wqe_size, u16 *cons_idx) { struct hinic_hw_wqe *hw_wqe; struct hinic_sq_wqe *sq_wqe; @@ -658,6 +659,8 @@ struct hinic_sq_wqe *hinic_sq_read_wqe(struct hinic_sq *sq, if (IS_ERR(hw_wqe)) return NULL; + *skb = sq->saved_skb[*cons_idx]; + sq_wqe = &hw_wqe->sq_wqe; ctrl = &sq_wqe->ctrl; ctrl_info = be32_to_cpu(ctrl->ctrl_info); @@ -665,11 +668,28 @@ struct hinic_sq_wqe *hinic_sq_read_wqe(struct hinic_sq *sq, *wqe_size = sizeof(*ctrl) + sizeof(sq_wqe->task); *wqe_size += SECT_SIZE_FROM_8BYTES(buf_sect_len); + *wqe_size = ALIGN(*wqe_size, sq->wq->wqebb_size); - *skb = sq->saved_skb[*cons_idx]; + return &hw_wqe->sq_wqe; +} + +/** + * hinic_sq_read_wqe - read wqe ptr in the current ci and update the ci + * @sq: send queue + * @skb: return skb that was saved + * @wqe_size: the size of the wqe + * @cons_idx: consumer index of the wqe + * + * Return wqe in ci position + **/ +struct hinic_sq_wqe *hinic_sq_read_wqe(struct hinic_sq *sq, + struct sk_buff **skb, + unsigned int wqe_size, u16 *cons_idx) +{ + struct hinic_hw_wqe *hw_wqe; - /* using the real wqe size to read wqe again */ - hw_wqe = hinic_read_wqe(sq->wq, *wqe_size, cons_idx); + hw_wqe = hinic_read_wqe(sq->wq, wqe_size, cons_idx); + *skb = sq->saved_skb[*cons_idx]; return &hw_wqe->sq_wqe; } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h index df729a1587e9..6c84f83ec283 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h @@ -165,7 +165,11 @@ void hinic_sq_write_wqe(struct hinic_sq *sq, u16 prod_idx, struct hinic_sq_wqe *hinic_sq_read_wqe(struct hinic_sq *sq, struct sk_buff **skb, - unsigned int *wqe_size, u16 *cons_idx); + unsigned int wqe_size, u16 *cons_idx); + +struct hinic_sq_wqe *hinic_sq_read_wqebb(struct hinic_sq *sq, + struct sk_buff **skb, + unsigned int *wqe_size, u16 *cons_idx); void hinic_sq_put_wqe(struct hinic_sq *sq, unsigned int wqe_size); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c index 2353ec829c04..c5fca0356c9c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c @@ -283,7 +283,11 @@ static void free_all_tx_skbs(struct hinic_txq *txq) int nr_sges; u16 ci; - while ((sq_wqe = hinic_sq_read_wqe(sq, &skb, &wqe_size, &ci))) { + while ((sq_wqe = hinic_sq_read_wqebb(sq, &skb, &wqe_size, &ci))) { + sq_wqe = hinic_sq_read_wqe(sq, &skb, wqe_size, &ci); + if (!sq_wqe) + break; + nr_sges = skb_shinfo(skb)->nr_frags + 1; hinic_sq_get_sges(sq_wqe, txq->free_sges, nr_sges); @@ -319,11 +323,21 @@ static int free_tx_poll(struct napi_struct *napi, int budget) do { hw_ci = HW_CONS_IDX(sq) & wq->mask; - sq_wqe = hinic_sq_read_wqe(sq, &skb, &wqe_size, &sw_ci); + /* Reading a WQEBB to get real WQE size and consumer index. */ + sq_wqe = hinic_sq_read_wqebb(sq, &skb, &wqe_size, &sw_ci); if ((!sq_wqe) || (((hw_ci - sw_ci) & wq->mask) * wq->wqebb_size < wqe_size)) break; + /* If this WQE have multiple WQEBBs, we will read again to get + * full size WQE. + */ + if (wqe_size > wq->wqebb_size) { + sq_wqe = hinic_sq_read_wqe(sq, &skb, wqe_size, &sw_ci); + if (unlikely(!sq_wqe)) + break; + } + tx_bytes += skb->len; pkts++; From patchwork Mon Mar 18 08:28:22 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057727 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8TY4cCqz9s47; Mon, 18 Mar 2019 19:28:33 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5ndE-0008BI-FM; Mon, 18 Mar 2019 08:28:28 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5ndD-0008Av-C6 for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:28:27 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5ndC-0000WW-8A for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:28:27 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 02/12] hinic: remove ndo_poll_controller Date: Mon, 18 Mar 2019 16:28:22 +0800 Message-Id: <20190318082822.26759-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Eric Dumazet BugLink: https://bugs.launchpad.net/bugs/1820187 As diagnosed by Song Liu, ndo_poll_controller() can be very dangerous on loaded hosts, since the cpu calling ndo_poll_controller() might steal all NAPI contexts (for all RX/TX queues of the NIC). This capture can last for unlimited amount of time, since one cpu is generally not able to drain all the queues under load. hinic uses NAPI for TX completions, so we better let core networking stack call the napi->poll() to avoid the capture. Note that hinic_netpoll() was incorrectly scheduling NAPI on both RX and TX queues. Signed-off-by: Eric Dumazet Cc: Aviad Krawczyk Signed-off-by: David S. Miller (cherry picked from commit e71fb423e0dea3c9f98f0101e965426edfe849cd) Signed-off-by: Ike Panhc --- .../net/ethernet/huawei/hinic/hinic_main.c | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 09e9da10b786..4a8f82938ed5 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -789,23 +789,6 @@ static void hinic_get_stats64(struct net_device *netdev, stats->tx_errors = nic_tx_stats->tx_dropped; } -#ifdef CONFIG_NET_POLL_CONTROLLER -static void hinic_netpoll(struct net_device *netdev) -{ - struct hinic_dev *nic_dev = netdev_priv(netdev); - int i, num_qps; - - num_qps = hinic_hwdev_num_qps(nic_dev->hwdev); - for (i = 0; i < num_qps; i++) { - struct hinic_txq *txq = &nic_dev->txqs[i]; - struct hinic_rxq *rxq = &nic_dev->rxqs[i]; - - napi_schedule(&txq->napi); - napi_schedule(&rxq->napi); - } -} -#endif - static const struct net_device_ops hinic_netdev_ops = { .ndo_open = hinic_open, .ndo_stop = hinic_close, @@ -818,9 +801,6 @@ static const struct net_device_ops hinic_netdev_ops = { .ndo_start_xmit = hinic_xmit_frame, .ndo_tx_timeout = hinic_tx_timeout, .ndo_get_stats64 = hinic_get_stats64, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = hinic_netpoll, -#endif }; static void netdev_features_init(struct net_device *netdev) From patchwork Mon Mar 18 08:28:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057730 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8Tq1pfjz9sBr; Mon, 18 Mar 2019 19:28:47 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5ndR-0008Eb-MN; Mon, 18 Mar 2019 08:28:41 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5ndN-0008Dx-RB for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:28:37 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5ndL-0000XK-SD for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:28:37 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 03/12] net-next/hinic: add checksum offload and TSO support Date: Mon, 18 Mar 2019 16:28:32 +0800 Message-Id: <20190318082832.26806-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Zhao Chen BugLink: https://bugs.launchpad.net/bugs/1820187 This patch adds checksum offload and TSO support for the HiNIC driver. Perfomance test (Iperf) shows more than 100% improvement in TCP streams. Signed-off-by: Zhao Chen Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit cc18a7543d2f63a2c93fc61cfa7fd8be5464f75e) Signed-off-by: Ike Panhc --- .../net/ethernet/huawei/hinic/hinic_hw_dev.h | 2 + .../net/ethernet/huawei/hinic/hinic_hw_qp.c | 121 +++++-- .../net/ethernet/huawei/hinic/hinic_hw_qp.h | 27 ++ .../net/ethernet/huawei/hinic/hinic_hw_wq.c | 14 + .../net/ethernet/huawei/hinic/hinic_hw_wq.h | 2 + .../net/ethernet/huawei/hinic/hinic_hw_wqe.h | 97 ++++-- .../net/ethernet/huawei/hinic/hinic_main.c | 23 +- .../net/ethernet/huawei/hinic/hinic_port.c | 32 ++ .../net/ethernet/huawei/hinic/hinic_port.h | 18 ++ drivers/net/ethernet/huawei/hinic/hinic_tx.c | 295 +++++++++++++++++- 10 files changed, 571 insertions(+), 60 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index 0f5563f3b779..097b5502603f 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -58,6 +58,8 @@ enum hinic_port_cmd { HINIC_PORT_CMD_GET_GLOBAL_QPN = 102, + HINIC_PORT_CMD_SET_TSO = 112, + HINIC_PORT_CMD_GET_CAP = 170, }; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c index cb239627770f..967c993d5303 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c @@ -70,8 +70,6 @@ #define SQ_MASKED_IDX(sq, idx) ((idx) & (sq)->wq->mask) #define RQ_MASKED_IDX(rq, idx) ((idx) & (rq)->wq->mask) -#define TX_MAX_MSS_DEFAULT 0x3E00 - enum sq_wqe_type { SQ_NORMAL_WQE = 0, }; @@ -494,33 +492,16 @@ static void sq_prepare_ctrl(struct hinic_sq_ctrl *ctrl, u16 prod_idx, HINIC_SQ_CTRL_SET(SQ_NORMAL_WQE, DATA_FORMAT) | HINIC_SQ_CTRL_SET(ctrl_size, LEN); - ctrl->queue_info = HINIC_SQ_CTRL_SET(TX_MAX_MSS_DEFAULT, - QUEUE_INFO_MSS); + ctrl->queue_info = HINIC_SQ_CTRL_SET(HINIC_MSS_DEFAULT, + QUEUE_INFO_MSS) | + HINIC_SQ_CTRL_SET(1, QUEUE_INFO_UC); } static void sq_prepare_task(struct hinic_sq_task *task) { - task->pkt_info0 = - HINIC_SQ_TASK_INFO0_SET(0, L2HDR_LEN) | - HINIC_SQ_TASK_INFO0_SET(HINIC_L4_OFF_DISABLE, L4_OFFLOAD) | - HINIC_SQ_TASK_INFO0_SET(HINIC_OUTER_L3TYPE_UNKNOWN, - INNER_L3TYPE) | - HINIC_SQ_TASK_INFO0_SET(HINIC_VLAN_OFF_DISABLE, - VLAN_OFFLOAD) | - HINIC_SQ_TASK_INFO0_SET(HINIC_PKT_NOT_PARSED, PARSE_FLAG); - - task->pkt_info1 = - HINIC_SQ_TASK_INFO1_SET(HINIC_MEDIA_UNKNOWN, MEDIA_TYPE) | - HINIC_SQ_TASK_INFO1_SET(0, INNER_L4_LEN) | - HINIC_SQ_TASK_INFO1_SET(0, INNER_L3_LEN); - - task->pkt_info2 = - HINIC_SQ_TASK_INFO2_SET(0, TUNNEL_L4_LEN) | - HINIC_SQ_TASK_INFO2_SET(0, OUTER_L3_LEN) | - HINIC_SQ_TASK_INFO2_SET(HINIC_TUNNEL_L4TYPE_UNKNOWN, - TUNNEL_L4TYPE) | - HINIC_SQ_TASK_INFO2_SET(HINIC_OUTER_L3TYPE_UNKNOWN, - OUTER_L3TYPE); + task->pkt_info0 = 0; + task->pkt_info1 = 0; + task->pkt_info2 = 0; task->ufo_v6_identify = 0; @@ -529,6 +510,86 @@ static void sq_prepare_task(struct hinic_sq_task *task) task->zero_pad = 0; } +void hinic_task_set_l2hdr(struct hinic_sq_task *task, u32 len) +{ + task->pkt_info0 |= HINIC_SQ_TASK_INFO0_SET(len, L2HDR_LEN); +} + +void hinic_task_set_outter_l3(struct hinic_sq_task *task, + enum hinic_l3_offload_type l3_type, + u32 network_len) +{ + task->pkt_info2 |= HINIC_SQ_TASK_INFO2_SET(l3_type, OUTER_L3TYPE) | + HINIC_SQ_TASK_INFO2_SET(network_len, OUTER_L3LEN); +} + +void hinic_task_set_inner_l3(struct hinic_sq_task *task, + enum hinic_l3_offload_type l3_type, + u32 network_len) +{ + task->pkt_info0 |= HINIC_SQ_TASK_INFO0_SET(l3_type, INNER_L3TYPE); + task->pkt_info1 |= HINIC_SQ_TASK_INFO1_SET(network_len, INNER_L3LEN); +} + +void hinic_task_set_tunnel_l4(struct hinic_sq_task *task, + enum hinic_l4_offload_type l4_type, + u32 tunnel_len) +{ + task->pkt_info2 |= HINIC_SQ_TASK_INFO2_SET(l4_type, TUNNEL_L4TYPE) | + HINIC_SQ_TASK_INFO2_SET(tunnel_len, TUNNEL_L4LEN); +} + +void hinic_set_cs_inner_l4(struct hinic_sq_task *task, u32 *queue_info, + enum hinic_l4_offload_type l4_offload, + u32 l4_len, u32 offset) +{ + u32 tcp_udp_cs = 0, sctp = 0; + u32 mss = HINIC_MSS_DEFAULT; + + if (l4_offload == TCP_OFFLOAD_ENABLE || + l4_offload == UDP_OFFLOAD_ENABLE) + tcp_udp_cs = 1; + else if (l4_offload == SCTP_OFFLOAD_ENABLE) + sctp = 1; + + task->pkt_info0 |= HINIC_SQ_TASK_INFO0_SET(l4_offload, L4_OFFLOAD); + task->pkt_info1 |= HINIC_SQ_TASK_INFO1_SET(l4_len, INNER_L4LEN); + + *queue_info |= HINIC_SQ_CTRL_SET(offset, QUEUE_INFO_PLDOFF) | + HINIC_SQ_CTRL_SET(tcp_udp_cs, QUEUE_INFO_TCPUDP_CS) | + HINIC_SQ_CTRL_SET(sctp, QUEUE_INFO_SCTP); + + *queue_info = HINIC_SQ_CTRL_CLEAR(*queue_info, QUEUE_INFO_MSS); + *queue_info |= HINIC_SQ_CTRL_SET(mss, QUEUE_INFO_MSS); +} + +void hinic_set_tso_inner_l4(struct hinic_sq_task *task, u32 *queue_info, + enum hinic_l4_offload_type l4_offload, + u32 l4_len, u32 offset, u32 ip_ident, u32 mss) +{ + u32 tso = 0, ufo = 0; + + if (l4_offload == TCP_OFFLOAD_ENABLE) + tso = 1; + else if (l4_offload == UDP_OFFLOAD_ENABLE) + ufo = 1; + + task->ufo_v6_identify = ip_ident; + + task->pkt_info0 |= HINIC_SQ_TASK_INFO0_SET(l4_offload, L4_OFFLOAD); + task->pkt_info0 |= HINIC_SQ_TASK_INFO0_SET(tso || ufo, TSO_FLAG); + task->pkt_info1 |= HINIC_SQ_TASK_INFO1_SET(l4_len, INNER_L4LEN); + + *queue_info |= HINIC_SQ_CTRL_SET(offset, QUEUE_INFO_PLDOFF) | + HINIC_SQ_CTRL_SET(tso, QUEUE_INFO_TSO) | + HINIC_SQ_CTRL_SET(ufo, QUEUE_INFO_UFO) | + HINIC_SQ_CTRL_SET(!!l4_offload, QUEUE_INFO_TCPUDP_CS); + + /* set MSS value */ + *queue_info = HINIC_SQ_CTRL_CLEAR(*queue_info, QUEUE_INFO_MSS); + *queue_info |= HINIC_SQ_CTRL_SET(mss, QUEUE_INFO_MSS); +} + /** * hinic_sq_prepare_wqe - prepare wqe before insert to the queue * @sq: send queue @@ -612,6 +673,16 @@ struct hinic_sq_wqe *hinic_sq_get_wqe(struct hinic_sq *sq, return &hw_wqe->sq_wqe; } +/** + * hinic_sq_return_wqe - return the wqe to the sq + * @sq: send queue + * @wqe_size: the size of the wqe + **/ +void hinic_sq_return_wqe(struct hinic_sq *sq, unsigned int wqe_size) +{ + hinic_return_wqe(sq->wq, wqe_size); +} + /** * hinic_sq_write_wqe - write the wqe to the sq * @sq: send queue diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h index 6c84f83ec283..a0dc63a4bfc7 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h @@ -149,6 +149,31 @@ int hinic_get_sq_free_wqebbs(struct hinic_sq *sq); int hinic_get_rq_free_wqebbs(struct hinic_rq *rq); +void hinic_task_set_l2hdr(struct hinic_sq_task *task, u32 len); + +void hinic_task_set_outter_l3(struct hinic_sq_task *task, + enum hinic_l3_offload_type l3_type, + u32 network_len); + +void hinic_task_set_inner_l3(struct hinic_sq_task *task, + enum hinic_l3_offload_type l3_type, + u32 network_len); + +void hinic_task_set_tunnel_l4(struct hinic_sq_task *task, + enum hinic_l4_offload_type l4_type, + u32 tunnel_len); + +void hinic_set_cs_inner_l4(struct hinic_sq_task *task, + u32 *queue_info, + enum hinic_l4_offload_type l4_offload, + u32 l4_len, u32 offset); + +void hinic_set_tso_inner_l4(struct hinic_sq_task *task, + u32 *queue_info, + enum hinic_l4_offload_type l4_offload, + u32 l4_len, + u32 offset, u32 ip_ident, u32 mss); + void hinic_sq_prepare_wqe(struct hinic_sq *sq, u16 prod_idx, struct hinic_sq_wqe *wqe, struct hinic_sge *sges, int nr_sges); @@ -159,6 +184,8 @@ void hinic_sq_write_db(struct hinic_sq *sq, u16 prod_idx, unsigned int wqe_size, struct hinic_sq_wqe *hinic_sq_get_wqe(struct hinic_sq *sq, unsigned int wqe_size, u16 *prod_idx); +void hinic_sq_return_wqe(struct hinic_sq *sq, unsigned int wqe_size); + void hinic_sq_write_wqe(struct hinic_sq *sq, u16 prod_idx, struct hinic_sq_wqe *wqe, struct sk_buff *skb, unsigned int wqe_size); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c index 3e3181c089bd..f92f1bf3901a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c @@ -774,6 +774,20 @@ struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size, return WQ_PAGE_ADDR(wq, *prod_idx) + WQE_PAGE_OFF(wq, *prod_idx); } +/** + * hinic_return_wqe - return the wqe when transmit failed + * @wq: wq to return wqe + * @wqe_size: wqe size + **/ +void hinic_return_wqe(struct hinic_wq *wq, unsigned int wqe_size) +{ + int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size; + + atomic_sub(num_wqebbs, &wq->prod_idx); + + atomic_add(num_wqebbs, &wq->delta); +} + /** * hinic_put_wqe - return the wqe place to use for a new wqe * @wq: wq to return wqe diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h index 9c030a0f035e..9b66545ba563 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h @@ -104,6 +104,8 @@ void hinic_wq_free(struct hinic_wqs *wqs, struct hinic_wq *wq); struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size, u16 *prod_idx); +void hinic_return_wqe(struct hinic_wq *wq, unsigned int wqe_size); + void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size); struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size, diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h index bc73485483c5..9754d6ed5f4a 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h @@ -62,19 +62,33 @@ (((val) >> HINIC_CMDQ_WQE_HEADER_##member##_SHIFT) \ & HINIC_CMDQ_WQE_HEADER_##member##_MASK) -#define HINIC_SQ_CTRL_BUFDESC_SECT_LEN_SHIFT 0 -#define HINIC_SQ_CTRL_TASKSECT_LEN_SHIFT 16 -#define HINIC_SQ_CTRL_DATA_FORMAT_SHIFT 22 -#define HINIC_SQ_CTRL_LEN_SHIFT 29 - -#define HINIC_SQ_CTRL_BUFDESC_SECT_LEN_MASK 0xFF -#define HINIC_SQ_CTRL_TASKSECT_LEN_MASK 0x1F -#define HINIC_SQ_CTRL_DATA_FORMAT_MASK 0x1 -#define HINIC_SQ_CTRL_LEN_MASK 0x3 - -#define HINIC_SQ_CTRL_QUEUE_INFO_MSS_SHIFT 13 - -#define HINIC_SQ_CTRL_QUEUE_INFO_MSS_MASK 0x3FFF +#define HINIC_SQ_CTRL_BUFDESC_SECT_LEN_SHIFT 0 +#define HINIC_SQ_CTRL_TASKSECT_LEN_SHIFT 16 +#define HINIC_SQ_CTRL_DATA_FORMAT_SHIFT 22 +#define HINIC_SQ_CTRL_LEN_SHIFT 29 + +#define HINIC_SQ_CTRL_BUFDESC_SECT_LEN_MASK 0xFF +#define HINIC_SQ_CTRL_TASKSECT_LEN_MASK 0x1F +#define HINIC_SQ_CTRL_DATA_FORMAT_MASK 0x1 +#define HINIC_SQ_CTRL_LEN_MASK 0x3 + +#define HINIC_SQ_CTRL_QUEUE_INFO_PLDOFF_SHIFT 2 +#define HINIC_SQ_CTRL_QUEUE_INFO_UFO_SHIFT 10 +#define HINIC_SQ_CTRL_QUEUE_INFO_TSO_SHIFT 11 +#define HINIC_SQ_CTRL_QUEUE_INFO_TCPUDP_CS_SHIFT 12 +#define HINIC_SQ_CTRL_QUEUE_INFO_MSS_SHIFT 13 +#define HINIC_SQ_CTRL_QUEUE_INFO_SCTP_SHIFT 27 +#define HINIC_SQ_CTRL_QUEUE_INFO_UC_SHIFT 28 +#define HINIC_SQ_CTRL_QUEUE_INFO_PRI_SHIFT 29 + +#define HINIC_SQ_CTRL_QUEUE_INFO_PLDOFF_MASK 0xFF +#define HINIC_SQ_CTRL_QUEUE_INFO_UFO_MASK 0x1 +#define HINIC_SQ_CTRL_QUEUE_INFO_TSO_MASK 0x1 +#define HINIC_SQ_CTRL_QUEUE_INFO_TCPUDP_CS_MASK 0x1 +#define HINIC_SQ_CTRL_QUEUE_INFO_MSS_MASK 0x3FFF +#define HINIC_SQ_CTRL_QUEUE_INFO_SCTP_MASK 0x1 +#define HINIC_SQ_CTRL_QUEUE_INFO_UC_MASK 0x1 +#define HINIC_SQ_CTRL_QUEUE_INFO_PRI_MASK 0x7 #define HINIC_SQ_CTRL_SET(val, member) \ (((u32)(val) & HINIC_SQ_CTRL_##member##_MASK) \ @@ -84,6 +98,10 @@ (((val) >> HINIC_SQ_CTRL_##member##_SHIFT) \ & HINIC_SQ_CTRL_##member##_MASK) +#define HINIC_SQ_CTRL_CLEAR(val, member) \ + ((u32)(val) & (~(HINIC_SQ_CTRL_##member##_MASK \ + << HINIC_SQ_CTRL_##member##_SHIFT))) + #define HINIC_SQ_TASK_INFO0_L2HDR_LEN_SHIFT 0 #define HINIC_SQ_TASK_INFO0_L4_OFFLOAD_SHIFT 8 #define HINIC_SQ_TASK_INFO0_INNER_L3TYPE_SHIFT 10 @@ -108,28 +126,28 @@ /* 8 bits reserved */ #define HINIC_SQ_TASK_INFO1_MEDIA_TYPE_SHIFT 8 -#define HINIC_SQ_TASK_INFO1_INNER_L4_LEN_SHIFT 16 -#define HINIC_SQ_TASK_INFO1_INNER_L3_LEN_SHIFT 24 +#define HINIC_SQ_TASK_INFO1_INNER_L4LEN_SHIFT 16 +#define HINIC_SQ_TASK_INFO1_INNER_L3LEN_SHIFT 24 /* 8 bits reserved */ #define HINIC_SQ_TASK_INFO1_MEDIA_TYPE_MASK 0xFF -#define HINIC_SQ_TASK_INFO1_INNER_L4_LEN_MASK 0xFF -#define HINIC_SQ_TASK_INFO1_INNER_L3_LEN_MASK 0xFF +#define HINIC_SQ_TASK_INFO1_INNER_L4LEN_MASK 0xFF +#define HINIC_SQ_TASK_INFO1_INNER_L3LEN_MASK 0xFF #define HINIC_SQ_TASK_INFO1_SET(val, member) \ (((u32)(val) & HINIC_SQ_TASK_INFO1_##member##_MASK) << \ HINIC_SQ_TASK_INFO1_##member##_SHIFT) -#define HINIC_SQ_TASK_INFO2_TUNNEL_L4_LEN_SHIFT 0 -#define HINIC_SQ_TASK_INFO2_OUTER_L3_LEN_SHIFT 12 -#define HINIC_SQ_TASK_INFO2_TUNNEL_L4TYPE_SHIFT 19 +#define HINIC_SQ_TASK_INFO2_TUNNEL_L4LEN_SHIFT 0 +#define HINIC_SQ_TASK_INFO2_OUTER_L3LEN_SHIFT 8 +#define HINIC_SQ_TASK_INFO2_TUNNEL_L4TYPE_SHIFT 16 /* 1 bit reserved */ -#define HINIC_SQ_TASK_INFO2_OUTER_L3TYPE_SHIFT 22 +#define HINIC_SQ_TASK_INFO2_OUTER_L3TYPE_SHIFT 24 /* 8 bits reserved */ -#define HINIC_SQ_TASK_INFO2_TUNNEL_L4_LEN_MASK 0xFFF -#define HINIC_SQ_TASK_INFO2_OUTER_L3_LEN_MASK 0x7F -#define HINIC_SQ_TASK_INFO2_TUNNEL_L4TYPE_MASK 0x3 +#define HINIC_SQ_TASK_INFO2_TUNNEL_L4LEN_MASK 0xFF +#define HINIC_SQ_TASK_INFO2_OUTER_L3LEN_MASK 0xFF +#define HINIC_SQ_TASK_INFO2_TUNNEL_L4TYPE_MASK 0x7 /* 1 bit reserved */ #define HINIC_SQ_TASK_INFO2_OUTER_L3TYPE_MASK 0x3 /* 8 bits reserved */ @@ -187,12 +205,15 @@ sizeof(struct hinic_sq_task) + \ (nr_sges) * sizeof(struct hinic_sq_bufdesc)) -#define HINIC_SCMD_DATA_LEN 16 +#define HINIC_SCMD_DATA_LEN 16 + +#define HINIC_MAX_SQ_BUFDESCS 17 -#define HINIC_MAX_SQ_BUFDESCS 17 +#define HINIC_SQ_WQE_MAX_SIZE 320 +#define HINIC_RQ_WQE_SIZE 32 -#define HINIC_SQ_WQE_MAX_SIZE 320 -#define HINIC_RQ_WQE_SIZE 32 +#define HINIC_MSS_DEFAULT 0x3E00 +#define HINIC_MSS_MIN 0x50 enum hinic_l4offload_type { HINIC_L4_OFF_DISABLE = 0, @@ -211,6 +232,26 @@ enum hinic_pkt_parsed { HINIC_PKT_PARSED = 1, }; +enum hinic_l3_offload_type { + L3TYPE_UNKNOWN = 0, + IPV6_PKT = 1, + IPV4_PKT_NO_CHKSUM_OFFLOAD = 2, + IPV4_PKT_WITH_CHKSUM_OFFLOAD = 3, +}; + +enum hinic_l4_offload_type { + OFFLOAD_DISABLE = 0, + TCP_OFFLOAD_ENABLE = 1, + SCTP_OFFLOAD_ENABLE = 2, + UDP_OFFLOAD_ENABLE = 3, +}; + +enum hinic_l4_tunnel_type { + NOT_TUNNEL, + TUNNEL_UDP_NO_CSUM, + TUNNEL_UDP_CSUM, +}; + enum hinic_outer_l3type { HINIC_OUTER_L3TYPE_UNKNOWN = 0, HINIC_OUTER_L3TYPE_IPV6 = 1, diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 4a8f82938ed5..fdf2bdb6b0d0 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -805,7 +805,8 @@ static const struct net_device_ops hinic_netdev_ops = { static void netdev_features_init(struct net_device *netdev) { - netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA; + netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6; netdev->vlan_features = netdev->hw_features; @@ -863,6 +864,20 @@ static void link_status_event_handler(void *handle, void *buf_in, u16 in_size, *out_size = sizeof(*ret_link_status); } +static int set_features(struct hinic_dev *nic_dev, + netdev_features_t pre_features, + netdev_features_t features, bool force_change) +{ + netdev_features_t changed = force_change ? ~0 : pre_features ^ features; + int err = 0; + + if (changed & NETIF_F_TSO) + err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ? + HINIC_TSO_ENABLE : HINIC_TSO_DISABLE); + + return err; +} + /** * nic_dev_init - Initialize the NIC device * @pdev: the NIC pci device @@ -963,7 +978,12 @@ static int nic_dev_init(struct pci_dev *pdev) hinic_hwdev_cb_register(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS, nic_dev, link_status_event_handler); + err = set_features(nic_dev, 0, nic_dev->netdev->features, true); + if (err) + goto err_set_features; + SET_NETDEV_DEV(netdev, &pdev->dev); + err = register_netdev(netdev); if (err) { dev_err(&pdev->dev, "Failed to register netdev\n"); @@ -973,6 +993,7 @@ static int nic_dev_init(struct pci_dev *pdev) return 0; err_reg_netdev: +err_set_features: hinic_hwdev_cb_unregister(nic_dev->hwdev, HINIC_MGMT_MSG_CMD_LINK_STATUS); cancel_work_sync(&rx_mode_work->work); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c index 4d4e3f05fb5f..7575a7d3bd9f 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c @@ -377,3 +377,35 @@ int hinic_port_get_cap(struct hinic_dev *nic_dev, return 0; } + +/** + * hinic_port_set_tso - set port tso configuration + * @nic_dev: nic device + * @state: the tso state to set + * + * Return 0 - Success, negative - Failure + **/ +int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state) +{ + struct hinic_hwdev *hwdev = nic_dev->hwdev; + struct hinic_hwif *hwif = hwdev->hwif; + struct hinic_tso_config tso_cfg = {0}; + struct pci_dev *pdev = hwif->pdev; + u16 out_size; + int err; + + tso_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif); + tso_cfg.tso_en = state; + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_TSO, + &tso_cfg, sizeof(tso_cfg), + &tso_cfg, &out_size); + if (err || out_size != sizeof(tso_cfg) || tso_cfg.status) { + dev_err(&pdev->dev, + "Failed to set port tso, ret = %d\n", + tso_cfg.status); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.h b/drivers/net/ethernet/huawei/hinic/hinic_port.h index 9404365195dd..f6e3220fe28f 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_port.h @@ -72,6 +72,11 @@ enum hinic_speed { HINIC_SPEED_UNKNOWN = 0xFF, }; +enum hinic_tso_state { + HINIC_TSO_DISABLE = 0, + HINIC_TSO_ENABLE = 1, +}; + struct hinic_port_mac_cmd { u8 status; u8 version; @@ -167,6 +172,17 @@ struct hinic_port_cap { u8 rsvd2[3]; }; +struct hinic_tso_config { + u8 status; + u8 version; + u8 rsvd0[6]; + + u16 func_id; + u16 rsvd1; + u8 tso_en; + u8 resv2[3]; +}; + int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr, u16 vlan_id); @@ -195,4 +211,6 @@ int hinic_port_set_func_state(struct hinic_dev *nic_dev, int hinic_port_get_cap(struct hinic_dev *nic_dev, struct hinic_port_cap *port_cap); +int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c index c5fca0356c9c..11e73e67358d 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c @@ -26,6 +26,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include "hinic_common.h" #include "hinic_hw_if.h" @@ -45,9 +52,31 @@ #define CI_UPDATE_NO_PENDING 0 #define CI_UPDATE_NO_COALESC 0 -#define HW_CONS_IDX(sq) be16_to_cpu(*(u16 *)((sq)->hw_ci_addr)) +#define HW_CONS_IDX(sq) be16_to_cpu(*(u16 *)((sq)->hw_ci_addr)) -#define MIN_SKB_LEN 64 +#define MIN_SKB_LEN 17 + +#define MAX_PAYLOAD_OFFSET 221 +#define TRANSPORT_OFFSET(l4_hdr, skb) ((u32)((l4_hdr) - (skb)->data)) + +union hinic_l3 { + struct iphdr *v4; + struct ipv6hdr *v6; + unsigned char *hdr; +}; + +union hinic_l4 { + struct tcphdr *tcp; + struct udphdr *udp; + unsigned char *hdr; +}; + +enum hinic_offload_type { + TX_OFFLOAD_TSO = BIT(0), + TX_OFFLOAD_CSUM = BIT(1), + TX_OFFLOAD_VLAN = BIT(2), + TX_OFFLOAD_INVALID = BIT(3), +}; /** * hinic_txq_clean_stats - Clean the statistics of specific queue @@ -175,18 +204,263 @@ static void tx_unmap_skb(struct hinic_dev *nic_dev, struct sk_buff *skb, DMA_TO_DEVICE); } +static void get_inner_l3_l4_type(struct sk_buff *skb, union hinic_l3 *ip, + union hinic_l4 *l4, + enum hinic_offload_type offload_type, + enum hinic_l3_offload_type *l3_type, + u8 *l4_proto) +{ + u8 *exthdr; + + if (ip->v4->version == 4) { + *l3_type = (offload_type == TX_OFFLOAD_CSUM) ? + IPV4_PKT_NO_CHKSUM_OFFLOAD : + IPV4_PKT_WITH_CHKSUM_OFFLOAD; + *l4_proto = ip->v4->protocol; + } else if (ip->v4->version == 6) { + *l3_type = IPV6_PKT; + exthdr = ip->hdr + sizeof(*ip->v6); + *l4_proto = ip->v6->nexthdr; + if (exthdr != l4->hdr) { + int start = exthdr - skb->data; + __be16 frag_off; + + ipv6_skip_exthdr(skb, start, l4_proto, &frag_off); + } + } else { + *l3_type = L3TYPE_UNKNOWN; + *l4_proto = 0; + } +} + +static void get_inner_l4_info(struct sk_buff *skb, union hinic_l4 *l4, + enum hinic_offload_type offload_type, u8 l4_proto, + enum hinic_l4_offload_type *l4_offload, + u32 *l4_len, u32 *offset) +{ + *l4_offload = OFFLOAD_DISABLE; + *offset = 0; + *l4_len = 0; + + switch (l4_proto) { + case IPPROTO_TCP: + *l4_offload = TCP_OFFLOAD_ENABLE; + /* doff in unit of 4B */ + *l4_len = l4->tcp->doff * 4; + *offset = *l4_len + TRANSPORT_OFFSET(l4->hdr, skb); + break; + + case IPPROTO_UDP: + *l4_offload = UDP_OFFLOAD_ENABLE; + *l4_len = sizeof(struct udphdr); + *offset = TRANSPORT_OFFSET(l4->hdr, skb); + break; + + case IPPROTO_SCTP: + /* only csum offload support sctp */ + if (offload_type != TX_OFFLOAD_CSUM) + break; + + *l4_offload = SCTP_OFFLOAD_ENABLE; + *l4_len = sizeof(struct sctphdr); + *offset = TRANSPORT_OFFSET(l4->hdr, skb); + break; + + default: + break; + } +} + +static __sum16 csum_magic(union hinic_l3 *ip, unsigned short proto) +{ + return (ip->v4->version == 4) ? + csum_tcpudp_magic(ip->v4->saddr, ip->v4->daddr, 0, proto, 0) : + csum_ipv6_magic(&ip->v6->saddr, &ip->v6->daddr, 0, proto, 0); +} + +static int offload_tso(struct hinic_sq_task *task, u32 *queue_info, + struct sk_buff *skb) +{ + u32 offset, l4_len, ip_identify, network_hdr_len; + enum hinic_l3_offload_type l3_offload; + enum hinic_l4_offload_type l4_offload; + union hinic_l3 ip; + union hinic_l4 l4; + u8 l4_proto; + + if (!skb_is_gso(skb)) + return 0; + + if (skb_cow_head(skb, 0) < 0) + return -EPROTONOSUPPORT; + + if (skb->encapsulation) { + u32 gso_type = skb_shinfo(skb)->gso_type; + u32 tunnel_type = 0; + u32 l4_tunnel_len; + + ip.hdr = skb_network_header(skb); + l4.hdr = skb_transport_header(skb); + network_hdr_len = skb_inner_network_header_len(skb); + + if (ip.v4->version == 4) { + ip.v4->tot_len = 0; + l3_offload = IPV4_PKT_WITH_CHKSUM_OFFLOAD; + } else if (ip.v4->version == 6) { + l3_offload = IPV6_PKT; + } else { + l3_offload = 0; + } + + hinic_task_set_outter_l3(task, l3_offload, + skb_network_header_len(skb)); + + if (gso_type & SKB_GSO_UDP_TUNNEL_CSUM) { + l4.udp->check = ~csum_magic(&ip, IPPROTO_UDP); + tunnel_type = TUNNEL_UDP_CSUM; + } else if (gso_type & SKB_GSO_UDP_TUNNEL) { + tunnel_type = TUNNEL_UDP_NO_CSUM; + } + + l4_tunnel_len = skb_inner_network_offset(skb) - + skb_transport_offset(skb); + hinic_task_set_tunnel_l4(task, tunnel_type, l4_tunnel_len); + + ip.hdr = skb_inner_network_header(skb); + l4.hdr = skb_inner_transport_header(skb); + } else { + ip.hdr = skb_network_header(skb); + l4.hdr = skb_transport_header(skb); + network_hdr_len = skb_network_header_len(skb); + } + + /* initialize inner IP header fields */ + if (ip.v4->version == 4) + ip.v4->tot_len = 0; + else + ip.v6->payload_len = 0; + + get_inner_l3_l4_type(skb, &ip, &l4, TX_OFFLOAD_TSO, &l3_offload, + &l4_proto); + + hinic_task_set_inner_l3(task, l3_offload, network_hdr_len); + + ip_identify = 0; + if (l4_proto == IPPROTO_TCP) + l4.tcp->check = ~csum_magic(&ip, IPPROTO_TCP); + + get_inner_l4_info(skb, &l4, TX_OFFLOAD_TSO, l4_proto, &l4_offload, + &l4_len, &offset); + + hinic_set_tso_inner_l4(task, queue_info, l4_offload, l4_len, offset, + ip_identify, skb_shinfo(skb)->gso_size); + + return 1; +} + +static int offload_csum(struct hinic_sq_task *task, u32 *queue_info, + struct sk_buff *skb) +{ + enum hinic_l4_offload_type l4_offload; + u32 offset, l4_len, network_hdr_len; + enum hinic_l3_offload_type l3_type; + union hinic_l3 ip; + union hinic_l4 l4; + u8 l4_proto; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + + if (skb->encapsulation) { + u32 l4_tunnel_len; + + ip.hdr = skb_network_header(skb); + + if (ip.v4->version == 4) + l3_type = IPV4_PKT_NO_CHKSUM_OFFLOAD; + else if (ip.v4->version == 6) + l3_type = IPV6_PKT; + else + l3_type = L3TYPE_UNKNOWN; + + hinic_task_set_outter_l3(task, l3_type, + skb_network_header_len(skb)); + + l4_tunnel_len = skb_inner_network_offset(skb) - + skb_transport_offset(skb); + + hinic_task_set_tunnel_l4(task, TUNNEL_UDP_NO_CSUM, + l4_tunnel_len); + + ip.hdr = skb_inner_network_header(skb); + l4.hdr = skb_inner_transport_header(skb); + network_hdr_len = skb_inner_network_header_len(skb); + } else { + ip.hdr = skb_network_header(skb); + l4.hdr = skb_transport_header(skb); + network_hdr_len = skb_network_header_len(skb); + } + + get_inner_l3_l4_type(skb, &ip, &l4, TX_OFFLOAD_CSUM, &l3_type, + &l4_proto); + + hinic_task_set_inner_l3(task, l3_type, network_hdr_len); + + get_inner_l4_info(skb, &l4, TX_OFFLOAD_CSUM, l4_proto, &l4_offload, + &l4_len, &offset); + + hinic_set_cs_inner_l4(task, queue_info, l4_offload, l4_len, offset); + + return 1; +} + +static int hinic_tx_offload(struct sk_buff *skb, struct hinic_sq_task *task, + u32 *queue_info) +{ + enum hinic_offload_type offload = 0; + int enabled; + + enabled = offload_tso(task, queue_info, skb); + if (enabled > 0) { + offload |= TX_OFFLOAD_TSO; + } else if (enabled == 0) { + enabled = offload_csum(task, queue_info, skb); + if (enabled) + offload |= TX_OFFLOAD_CSUM; + } else { + return -EPROTONOSUPPORT; + } + + if (offload) + hinic_task_set_l2hdr(task, skb_network_offset(skb)); + + /* payload offset should not more than 221 */ + if (HINIC_SQ_CTRL_GET(*queue_info, QUEUE_INFO_PLDOFF) > + MAX_PAYLOAD_OFFSET) { + return -EPROTONOSUPPORT; + } + + /* mss should not less than 80 */ + if (HINIC_SQ_CTRL_GET(*queue_info, QUEUE_INFO_MSS) < HINIC_MSS_MIN) { + *queue_info = HINIC_SQ_CTRL_CLEAR(*queue_info, QUEUE_INFO_MSS); + *queue_info |= HINIC_SQ_CTRL_SET(HINIC_MSS_MIN, QUEUE_INFO_MSS); + } + + return 0; +} + netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct hinic_dev *nic_dev = netdev_priv(netdev); + u16 prod_idx, q_id = skb->queue_mapping; struct netdev_queue *netdev_txq; int nr_sges, err = NETDEV_TX_OK; struct hinic_sq_wqe *sq_wqe; unsigned int wqe_size; struct hinic_txq *txq; struct hinic_qp *qp; - u16 prod_idx; - txq = &nic_dev->txqs[skb->queue_mapping]; + txq = &nic_dev->txqs[q_id]; qp = container_of(txq->sq, struct hinic_qp, sq); if (skb->len < MIN_SKB_LEN) { @@ -236,15 +510,23 @@ netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) process_sq_wqe: hinic_sq_prepare_wqe(txq->sq, prod_idx, sq_wqe, txq->sges, nr_sges); + err = hinic_tx_offload(skb, &sq_wqe->task, &sq_wqe->ctrl.queue_info); + if (err) + goto offload_error; + hinic_sq_write_wqe(txq->sq, prod_idx, sq_wqe, skb, wqe_size); flush_skbs: - netdev_txq = netdev_get_tx_queue(netdev, skb->queue_mapping); + netdev_txq = netdev_get_tx_queue(netdev, q_id); if ((!skb->xmit_more) || (netif_xmit_stopped(netdev_txq))) hinic_sq_write_db(txq->sq, prod_idx, wqe_size, 0); return err; +offload_error: + hinic_sq_return_wqe(txq->sq, wqe_size); + tx_unmap_skb(nic_dev, skb, txq->sges); + skb_error: dev_kfree_skb_any(skb); @@ -252,7 +534,8 @@ netdev_tx_t hinic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) u64_stats_update_begin(&txq->txq_stats.syncp); txq->txq_stats.tx_dropped++; u64_stats_update_end(&txq->txq_stats.syncp); - return err; + + return NETDEV_TX_OK; } /** From patchwork Mon Mar 18 08:29:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057732 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8Vb2rhdz9s47; Mon, 18 Mar 2019 19:29:27 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5ne6-0008KF-AT; Mon, 18 Mar 2019 08:29:22 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5ne5-0008K8-1p for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:21 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5ne4-0000c1-3h for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:20 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 04/12] hinic: Fix l4_type parameter in hinic_task_set_tunnel_l4 Date: Mon, 18 Mar 2019 16:29:16 +0800 Message-Id: <20190318082916.26857-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Nathan Chancellor BugLink: https://bugs.launchpad.net/bugs/1820187 Clang warns: drivers/net/ethernet/huawei/hinic/hinic_tx.c:392:34: error: implicit conversion from enumeration type 'enum hinic_l4_tunnel_type' to different enumeration type 'enum hinic_l4_offload_type' [-Werror,-Wenum-conversion] hinic_task_set_tunnel_l4(task, TUNNEL_UDP_NO_CSUM, ~~~~~~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~ 1 error generated. It seems that hinic_task_set_tunnel_l4 was meant to take an enum of type hinic_l4_tunnel_type, not hinic_l4_offload_type, given both the name of the functions and the values used. Fixes: cc18a7543d2f ("net-next/hinic: add checksum offload and TSO support") Signed-off-by: Nathan Chancellor Reviewed-by: Nick Desaulniers Signed-off-by: David S. Miller (cherry picked from commit 6e29464b8a72e74ec7c3f816f53bfe46a43601bc) Signed-off-by: Ike Panhc --- drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c | 2 +- drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c index 967c993d5303..bbf9bdd0ee3e 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.c @@ -532,7 +532,7 @@ void hinic_task_set_inner_l3(struct hinic_sq_task *task, } void hinic_task_set_tunnel_l4(struct hinic_sq_task *task, - enum hinic_l4_offload_type l4_type, + enum hinic_l4_tunnel_type l4_type, u32 tunnel_len) { task->pkt_info2 |= HINIC_SQ_TASK_INFO2_SET(l4_type, TUNNEL_L4TYPE) | diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h index a0dc63a4bfc7..038522e202b6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_qp.h @@ -160,7 +160,7 @@ void hinic_task_set_inner_l3(struct hinic_sq_task *task, u32 network_len); void hinic_task_set_tunnel_l4(struct hinic_sq_task *task, - enum hinic_l4_offload_type l4_type, + enum hinic_l4_tunnel_type l4_type, u32 tunnel_len); void hinic_set_cs_inner_l4(struct hinic_sq_task *task, From patchwork Mon Mar 18 08:29:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057733 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8Vp3tcHz9s3q; Mon, 18 Mar 2019 19:29:38 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5neH-0008Ly-FQ; Mon, 18 Mar 2019 08:29:33 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5neG-0008Ln-6l for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:32 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5neF-0000cl-5b for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:31 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 05/12] net-next/hinic:replace multiply and division operators Date: Mon, 18 Mar 2019 16:29:26 +0800 Message-Id: <20190318082926.26904-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 To improve performance, this patch uses bit operations to replace multiply and division operators. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit ebda9b46cebc9c1245fcfe96c76525717ef984cc) Signed-off-by: Ike Panhc --- .../net/ethernet/huawei/hinic/hinic_hw_wq.c | 55 ++++++++++++------- .../net/ethernet/huawei/hinic/hinic_hw_wq.h | 3 +- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c index f92f1bf3901a..1dfa7eb05c10 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.c @@ -74,12 +74,6 @@ ((void *)((cmdq_pages)->shadow_page_vaddr) \ + (wq)->block_idx * CMDQ_BLOCK_SIZE) -#define WQE_PAGE_OFF(wq, idx) (((idx) & ((wq)->num_wqebbs_per_page - 1)) * \ - (wq)->wqebb_size) - -#define WQE_PAGE_NUM(wq, idx) (((idx) / ((wq)->num_wqebbs_per_page)) \ - & ((wq)->num_q_pages - 1)) - #define WQ_PAGE_ADDR(wq, idx) \ ((wq)->shadow_block_vaddr[WQE_PAGE_NUM(wq, idx)]) @@ -93,6 +87,17 @@ (((unsigned long)(wqe) - (unsigned long)(wq)->shadow_wqe) \ / (wq)->max_wqe_size) +static inline int WQE_PAGE_OFF(struct hinic_wq *wq, u16 idx) +{ + return (((idx) & ((wq)->num_wqebbs_per_page - 1)) + << (wq)->wqebb_size_shift); +} + +static inline int WQE_PAGE_NUM(struct hinic_wq *wq, u16 idx) +{ + return (((idx) >> ((wq)->wqebbs_per_page_shift)) + & ((wq)->num_q_pages - 1)); +} /** * queue_alloc_page - allocate page for Queue * @hwif: HW interface for allocating DMA @@ -513,10 +518,11 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq, struct hinic_hwif *hwif = wqs->hwif; struct pci_dev *pdev = hwif->pdev; u16 num_wqebbs_per_page; + u16 wqebb_size_shift; int err; - if (wqebb_size == 0) { - dev_err(&pdev->dev, "wqebb_size must be > 0\n"); + if (!is_power_of_2(wqebb_size)) { + dev_err(&pdev->dev, "wqebb_size must be power of 2\n"); return -EINVAL; } @@ -530,9 +536,11 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq, return -EINVAL; } - num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) / wqebb_size; + wqebb_size_shift = ilog2(wqebb_size); + num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) + >> wqebb_size_shift; - if (num_wqebbs_per_page & (num_wqebbs_per_page - 1)) { + if (!is_power_of_2(num_wqebbs_per_page)) { dev_err(&pdev->dev, "num wqebbs per page must be power of 2\n"); return -EINVAL; } @@ -550,7 +558,8 @@ int hinic_wq_allocate(struct hinic_wqs *wqs, struct hinic_wq *wq, wq->q_depth = q_depth; wq->max_wqe_size = max_wqe_size; wq->num_wqebbs_per_page = num_wqebbs_per_page; - + wq->wqebbs_per_page_shift = ilog2(num_wqebbs_per_page); + wq->wqebb_size_shift = wqebb_size_shift; wq->block_vaddr = WQ_BASE_VADDR(wqs, wq); wq->shadow_block_vaddr = WQ_BASE_ADDR(wqs, wq); wq->block_paddr = WQ_BASE_PADDR(wqs, wq); @@ -604,11 +613,13 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages, u16 q_depth, u16 max_wqe_size) { struct pci_dev *pdev = hwif->pdev; + u16 num_wqebbs_per_page_shift; u16 num_wqebbs_per_page; + u16 wqebb_size_shift; int i, j, err = -ENOMEM; - if (wqebb_size == 0) { - dev_err(&pdev->dev, "wqebb_size must be > 0\n"); + if (!is_power_of_2(wqebb_size)) { + dev_err(&pdev->dev, "wqebb_size must be power of 2\n"); return -EINVAL; } @@ -622,9 +633,11 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages, return -EINVAL; } - num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) / wqebb_size; + wqebb_size_shift = ilog2(wqebb_size); + num_wqebbs_per_page = ALIGN(wq_page_size, wqebb_size) + >> wqebb_size_shift; - if (num_wqebbs_per_page & (num_wqebbs_per_page - 1)) { + if (!is_power_of_2(num_wqebbs_per_page)) { dev_err(&pdev->dev, "num wqebbs per page must be power of 2\n"); return -EINVAL; } @@ -636,6 +649,7 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages, dev_err(&pdev->dev, "Failed to allocate CMDQ page\n"); return err; } + num_wqebbs_per_page_shift = ilog2(num_wqebbs_per_page); for (i = 0; i < cmdq_blocks; i++) { wq[i].hwif = hwif; @@ -647,7 +661,8 @@ int hinic_wqs_cmdq_alloc(struct hinic_cmdq_pages *cmdq_pages, wq[i].q_depth = q_depth; wq[i].max_wqe_size = max_wqe_size; wq[i].num_wqebbs_per_page = num_wqebbs_per_page; - + wq[i].wqebbs_per_page_shift = num_wqebbs_per_page_shift; + wq[i].wqebb_size_shift = wqebb_size_shift; wq[i].block_vaddr = CMDQ_BASE_VADDR(cmdq_pages, &wq[i]); wq[i].shadow_block_vaddr = CMDQ_BASE_ADDR(cmdq_pages, &wq[i]); wq[i].block_paddr = CMDQ_BASE_PADDR(cmdq_pages, &wq[i]); @@ -741,7 +756,7 @@ struct hinic_hw_wqe *hinic_get_wqe(struct hinic_wq *wq, unsigned int wqe_size, *prod_idx = MASKED_WQE_IDX(wq, atomic_read(&wq->prod_idx)); - num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size; + num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) >> wq->wqebb_size_shift; if (atomic_sub_return(num_wqebbs, &wq->delta) <= 0) { atomic_add(num_wqebbs, &wq->delta); @@ -795,7 +810,8 @@ void hinic_return_wqe(struct hinic_wq *wq, unsigned int wqe_size) **/ void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size) { - int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size; + int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) + >> wq->wqebb_size_shift; atomic_add(num_wqebbs, &wq->cons_idx); @@ -813,7 +829,8 @@ void hinic_put_wqe(struct hinic_wq *wq, unsigned int wqe_size) struct hinic_hw_wqe *hinic_read_wqe(struct hinic_wq *wq, unsigned int wqe_size, u16 *cons_idx) { - int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) / wq->wqebb_size; + int num_wqebbs = ALIGN(wqe_size, wq->wqebb_size) + >> wq->wqebb_size_shift; u16 curr_cons_idx, end_cons_idx; int curr_pg, end_pg; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h index 9b66545ba563..0a936cd6709b 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wq.h @@ -39,7 +39,8 @@ struct hinic_wq { u16 q_depth; u16 max_wqe_size; u16 num_wqebbs_per_page; - + u16 wqebbs_per_page_shift; + u16 wqebb_size_shift; /* The addresses are 64 bit in the HW */ u64 block_paddr; void **shadow_block_vaddr; From patchwork Mon Mar 18 08:29:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057734 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8W06cj5z9sBV; Mon, 18 Mar 2019 19:29:48 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5neR-0008OQ-KK; Mon, 18 Mar 2019 08:29:43 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5neQ-0008O9-1K for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:42 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5neP-0000dW-07 for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:41 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 06/12] net-next/hinic:add rx checksum offload for HiNIC Date: Mon, 18 Mar 2019 16:29:37 +0800 Message-Id: <20190318082937.26951-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 In order to improve performance, this patch adds rx checksum offload for the HiNIC driver. Performance test(Iperf) shows more than 80% improvement in TCP streams. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit 4a61abb100c8a647959147034f60e9fce17ce9af) Signed-off-by: Ike Panhc --- .../net/ethernet/huawei/hinic/hinic_hw_dev.h | 2 ++ .../net/ethernet/huawei/hinic/hinic_hw_wqe.h | 4 +++ .../net/ethernet/huawei/hinic/hinic_main.c | 7 ++++- .../net/ethernet/huawei/hinic/hinic_port.c | 28 +++++++++++++++++++ .../net/ethernet/huawei/hinic/hinic_port.h | 10 +++++++ drivers/net/ethernet/huawei/hinic/hinic_rx.c | 24 ++++++++++++++++ drivers/net/ethernet/huawei/hinic/hinic_rx.h | 4 +++ 7 files changed, 78 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index 097b5502603f..d1a7d2522d82 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -50,6 +50,8 @@ enum hinic_port_cmd { HINIC_PORT_CMD_GET_LINK_STATE = 24, + HINIC_PORT_CMD_SET_RX_CSUM = 26, + HINIC_PORT_CMD_SET_PORT_STATE = 41, HINIC_PORT_CMD_FWCTXT_INIT = 69, diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h index 9754d6ed5f4a..138941527872 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_wqe.h @@ -170,6 +170,10 @@ #define HINIC_RQ_CQE_STATUS_RXDONE_MASK 0x1 +#define HINIC_RQ_CQE_STATUS_CSUM_ERR_SHIFT 0 + +#define HINIC_RQ_CQE_STATUS_CSUM_ERR_MASK 0xFFFFU + #define HINIC_RQ_CQE_STATUS_GET(val, member) \ (((val) >> HINIC_RQ_CQE_STATUS_##member##_SHIFT) & \ HINIC_RQ_CQE_STATUS_##member##_MASK) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index fdf2bdb6b0d0..c675077f9774 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -806,7 +806,8 @@ static const struct net_device_ops hinic_netdev_ops = { static void netdev_features_init(struct net_device *netdev) { netdev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6; + NETIF_F_IPV6_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_RXCSUM; netdev->vlan_features = netdev->hw_features; @@ -869,12 +870,16 @@ static int set_features(struct hinic_dev *nic_dev, netdev_features_t features, bool force_change) { netdev_features_t changed = force_change ? ~0 : pre_features ^ features; + u32 csum_en = HINIC_RX_CSUM_OFFLOAD_EN; int err = 0; if (changed & NETIF_F_TSO) err = hinic_port_set_tso(nic_dev, (features & NETIF_F_TSO) ? HINIC_TSO_ENABLE : HINIC_TSO_DISABLE); + if (changed & NETIF_F_RXCSUM) + err = hinic_set_rx_csum_offload(nic_dev, csum_en); + return err; } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c index 7575a7d3bd9f..e9f76e904610 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c @@ -409,3 +409,31 @@ int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state) return 0; } + +int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en) +{ + struct hinic_checksum_offload rx_csum_cfg = {0}; + struct hinic_hwdev *hwdev = nic_dev->hwdev; + struct hinic_hwif *hwif = hwdev->hwif; + struct pci_dev *pdev = hwif->pdev; + u16 out_size; + int err; + + if (!hwdev) + return -EINVAL; + + rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif); + rx_csum_cfg.rx_csum_offload = en; + + err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_RX_CSUM, + &rx_csum_cfg, sizeof(rx_csum_cfg), + &rx_csum_cfg, &out_size); + if (err || !out_size || rx_csum_cfg.status) { + dev_err(&pdev->dev, + "Failed to set rx csum offload, ret = %d\n", + rx_csum_cfg.status); + return -EINVAL; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.h b/drivers/net/ethernet/huawei/hinic/hinic_port.h index f6e3220fe28f..02d896eed455 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_port.h @@ -183,6 +183,15 @@ struct hinic_tso_config { u8 resv2[3]; }; +struct hinic_checksum_offload { + u8 status; + u8 version; + u8 rsvd0[6]; + + u16 func_id; + u16 rsvd1; + u32 rx_csum_offload; +}; int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr, u16 vlan_id); @@ -213,4 +222,5 @@ int hinic_port_get_cap(struct hinic_dev *nic_dev, int hinic_port_set_tso(struct hinic_dev *nic_dev, enum hinic_tso_state state); +int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en); #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index 4c0f7eda1166..93e8f207f6da 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -89,6 +89,28 @@ static void rxq_stats_init(struct hinic_rxq *rxq) hinic_rxq_clean_stats(rxq); } +static void rx_csum(struct hinic_rxq *rxq, u16 cons_idx, + struct sk_buff *skb) +{ + struct net_device *netdev = rxq->netdev; + struct hinic_rq_cqe *cqe; + struct hinic_rq *rq; + u32 csum_err; + u32 status; + + rq = rxq->rq; + cqe = rq->cqe[cons_idx]; + status = be32_to_cpu(cqe->status); + csum_err = HINIC_RQ_CQE_STATUS_GET(status, CSUM_ERR); + + if (!(netdev->features & NETIF_F_RXCSUM)) + return; + + if (!csum_err) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; +} /** * rx_alloc_skb - allocate skb and map it to dma address * @rxq: rx queue @@ -328,6 +350,8 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget) rx_unmap_skb(rxq, hinic_sge_to_dma(&sge)); + rx_csum(rxq, ci, skb); + prefetch(skb->data); pkt_len = sge.len; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.h b/drivers/net/ethernet/huawei/hinic/hinic_rx.h index 27c9af4b1c12..ab3fabab91b2 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.h @@ -23,6 +23,10 @@ #include "hinic_hw_qp.h" +#define HINIC_RX_CSUM_OFFLOAD_EN 0xFFF +#define HINIC_RX_CSUM_HW_CHECK_NONE BIT(7) +#define HINIC_RX_CSUM_IPSU_OTHER_ERR BIT(8) + struct hinic_rxq_stats { u64 pkts; u64 bytes; From patchwork Mon Mar 18 08:29:47 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057735 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8W96X4Nz9s47; Mon, 18 Mar 2019 19:29:57 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5nea-0008QZ-Rx; Mon, 18 Mar 2019 08:29:52 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5neZ-0008QN-Ic for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:51 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5neY-0000eM-K8 for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:29:51 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 07/12] net-next/hinic:fix a bug in set mac address Date: Mon, 18 Mar 2019 16:29:47 +0800 Message-Id: <20190318082947.27000-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 In add_mac_addr(), if the MAC address is a muliticast address, it will not be set, which causes the network card fail to receive the multicast packet. This patch fixes this bug. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit 9ea72dc9430306b77c73a8a21beb51437cde1d6d) Signed-off-by: Ike Panhc --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index c675077f9774..6d48dc62a44b 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -600,9 +600,6 @@ static int add_mac_addr(struct net_device *netdev, const u8 *addr) u16 vid = 0; int err; - if (!is_valid_ether_addr(addr)) - return -EADDRNOTAVAIL; - netif_info(nic_dev, drv, netdev, "set mac addr = %02x %02x %02x %02x %02x %02x\n", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]); @@ -726,6 +723,7 @@ static void set_rx_mode(struct work_struct *work) { struct hinic_rx_mode_work *rx_mode_work = work_to_rx_mode_work(work); struct hinic_dev *nic_dev = rx_mode_work_to_nic_dev(rx_mode_work); + struct netdev_hw_addr *ha; netif_info(nic_dev, drv, nic_dev->netdev, "set rx mode work\n"); @@ -733,6 +731,9 @@ static void set_rx_mode(struct work_struct *work) __dev_uc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr); __dev_mc_sync(nic_dev->netdev, add_mac_addr, remove_mac_addr); + + netdev_for_each_mc_addr(ha, nic_dev->netdev) + add_mac_addr(nic_dev->netdev, ha->addr); } static void hinic_set_rx_mode(struct net_device *netdev) From patchwork Mon Mar 18 08:29:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057736 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8WM2qf4z9s3q; Mon, 18 Mar 2019 19:30:07 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5nek-0008TY-17; Mon, 18 Mar 2019 08:30:02 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5nei-0008SR-TF for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:00 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5nei-0000fD-1k for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:00 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 08/12] net-next/hinic: fix a bug in rx data flow Date: Mon, 18 Mar 2019 16:29:56 +0800 Message-Id: <20190318082956.27047-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 In rx_alloc_pkts(), there is a loop call of tasklet, which causes 100% cpu utilization, even no packets are being received. This patch fixes this bug. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit b1a200484143a727ce293e0f200a543cc7584152) Signed-off-by: Ike Panhc --- drivers/net/ethernet/huawei/hinic/hinic_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index 93e8f207f6da..f86f2e693224 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -229,9 +229,9 @@ static int rx_alloc_pkts(struct hinic_rxq *rxq) wmb(); /* write all the wqes before update PI */ hinic_rq_update(rxq->rq, prod_idx); + tasklet_schedule(&rxq->rx_task); } - tasklet_schedule(&rxq->rx_task); return i; } From patchwork Mon Mar 18 08:30:05 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057737 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8WX2jZSz9s3q; Mon, 18 Mar 2019 19:30:16 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5net-0008Vq-9B; Mon, 18 Mar 2019 08:30:11 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5ner-0008Vd-T4 for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:09 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5neq-0000gn-Rn for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:09 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 09/12] net: hinic: fix null pointer dereference on pointer hwdev Date: Mon, 18 Mar 2019 16:30:05 +0800 Message-Id: <20190318083005.27095-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Colin Ian King BugLink: https://bugs.launchpad.net/bugs/1820187 Pointer hwdev is being dereferenced when declaring hwif , however, later on hwdev is being null checked, hence we have dereference before null check error. Fix this by assigning hwif and pdef only once hwdev has been null checked. Detected by CoverityScan, CID#1485581 ("Dereference before null check") Fixes: 4a61abb100c8 ("net-next/hinic:add rx checksum offload for HiNIC") Signed-off-by: Colin Ian King Signed-off-by: David S. Miller (cherry picked from commit e159e592872edc0536f55ec242dbc5b70a593265) Signed-off-by: Ike Panhc --- drivers/net/ethernet/huawei/hinic/hinic_port.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c index e9f76e904610..122c93597268 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c @@ -414,14 +414,16 @@ int hinic_set_rx_csum_offload(struct hinic_dev *nic_dev, u32 en) { struct hinic_checksum_offload rx_csum_cfg = {0}; struct hinic_hwdev *hwdev = nic_dev->hwdev; - struct hinic_hwif *hwif = hwdev->hwif; - struct pci_dev *pdev = hwif->pdev; + struct hinic_hwif *hwif; + struct pci_dev *pdev; u16 out_size; int err; if (!hwdev) return -EINVAL; + hwif = hwdev->hwif; + pdev = hwif->pdev; rx_csum_cfg.func_id = HINIC_HWIF_FUNC_IDX(hwif); rx_csum_cfg.rx_csum_offload = en; From patchwork Mon Mar 18 08:30:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057738 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8Wk4xpKz9s3q; Mon, 18 Mar 2019 19:30:26 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5nf3-00006W-Ez; Mon, 18 Mar 2019 08:30:21 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5nf1-000065-Vh for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:19 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5nf1-0000hZ-1Q for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:19 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 10/12] hinic: optmize rx refill buffer mechanism Date: Mon, 18 Mar 2019 16:30:15 +0800 Message-Id: <20190318083015.27143-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 There is no need to schedule a different tasklet for refill, This patch remove it. Suggested-by: Neil Horman Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit e1a76515b0c20c3477200c1345c477cc0e68c4ad) Signed-off-by: Ike Panhc --- drivers/net/ethernet/huawei/hinic/hinic_rx.c | 23 +++++--------------- drivers/net/ethernet/huawei/hinic/hinic_rx.h | 2 -- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index f86f2e693224..0098b206e7e9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -43,6 +43,7 @@ #define RX_IRQ_NO_LLI_TIMER 0 #define RX_IRQ_NO_CREDIT 0 #define RX_IRQ_NO_RESEND_TIMER 0 +#define HINIC_RX_BUFFER_WRITE 16 /** * hinic_rxq_clean_stats - Clean the statistics of specific queue @@ -229,7 +230,6 @@ static int rx_alloc_pkts(struct hinic_rxq *rxq) wmb(); /* write all the wqes before update PI */ hinic_rq_update(rxq->rq, prod_idx); - tasklet_schedule(&rxq->rx_task); } return i; @@ -258,17 +258,6 @@ static void free_all_rx_skbs(struct hinic_rxq *rxq) } } -/** - * rx_alloc_task - tasklet for queue allocation - * @data: rx queue - **/ -static void rx_alloc_task(unsigned long data) -{ - struct hinic_rxq *rxq = (struct hinic_rxq *)data; - - (void)rx_alloc_pkts(rxq); -} - /** * rx_recv_jumbo_pkt - Rx handler for jumbo pkt * @rxq: rx queue @@ -333,6 +322,7 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget) struct hinic_qp *qp = container_of(rxq->rq, struct hinic_qp, rq); u64 pkt_len = 0, rx_bytes = 0; struct hinic_rq_wqe *rq_wqe; + unsigned int free_wqebbs; int num_wqes, pkts = 0; struct hinic_sge sge; struct sk_buff *skb; @@ -376,8 +366,9 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget) rx_bytes += pkt_len; } - if (pkts) - tasklet_schedule(&rxq->rx_task); /* rx_alloc_pkts */ + free_wqebbs = hinic_get_rq_free_wqebbs(rxq->rq); + if (free_wqebbs > HINIC_RX_BUFFER_WRITE) + rx_alloc_pkts(rxq); u64_stats_update_begin(&rxq->rxq_stats.syncp); rxq->rxq_stats.pkts += pkts; @@ -494,8 +485,6 @@ int hinic_init_rxq(struct hinic_rxq *rxq, struct hinic_rq *rq, sprintf(rxq->irq_name, "hinic_rxq%d", qp->q_id); - tasklet_init(&rxq->rx_task, rx_alloc_task, (unsigned long)rxq); - pkts = rx_alloc_pkts(rxq); if (!pkts) { err = -ENOMEM; @@ -512,7 +501,6 @@ int hinic_init_rxq(struct hinic_rxq *rxq, struct hinic_rq *rq, err_req_rx_irq: err_rx_pkts: - tasklet_kill(&rxq->rx_task); free_all_rx_skbs(rxq); devm_kfree(&netdev->dev, rxq->irq_name); return err; @@ -528,7 +516,6 @@ void hinic_clean_rxq(struct hinic_rxq *rxq) rx_free_irq(rxq); - tasklet_kill(&rxq->rx_task); free_all_rx_skbs(rxq); devm_kfree(&netdev->dev, rxq->irq_name); } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.h b/drivers/net/ethernet/huawei/hinic/hinic_rx.h index ab3fabab91b2..f8ed3fa6c8ee 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.h @@ -42,8 +42,6 @@ struct hinic_rxq { char *irq_name; - struct tasklet_struct rx_task; - struct napi_struct napi; }; From patchwork Mon Mar 18 08:30:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057742 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8X06kBhz9s3q; Mon, 18 Mar 2019 19:30:37 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5nfE-00009c-Q6; Mon, 18 Mar 2019 08:30:32 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5nfC-00009K-Q7 for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:30 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5nfB-0000iN-RC for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:30 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 11/12] net-next/hinic:add shutdown callback Date: Mon, 18 Mar 2019 16:30:26 +0800 Message-Id: <20190318083026.27191-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 If there is no shutdown callback, our board will report pcie UNF errors after restarting. This patch add shutdown callback for hinic. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit 53fe3ed19df0bca6ce752fae8e483910b6f112f6) Signed-off-by: Ike Panhc --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 6d48dc62a44b..da323b9e1f62 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -1106,6 +1106,11 @@ static void hinic_remove(struct pci_dev *pdev) dev_info(&pdev->dev, "HiNIC driver - removed\n"); } +static void hinic_shutdown(struct pci_dev *pdev) +{ + pci_disable_device(pdev); +} + static const struct pci_device_id hinic_pci_table[] = { { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_QUAD_PORT_25GE), 0}, { PCI_VDEVICE(HUAWEI, HINIC_DEV_ID_DUAL_PORT_25GE), 0}, @@ -1119,6 +1124,7 @@ static struct pci_driver hinic_driver = { .id_table = hinic_pci_table, .probe = hinic_probe, .remove = hinic_remove, + .shutdown = hinic_shutdown, }; module_pci_driver(hinic_driver); From patchwork Mon Mar 18 08:30:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ike Panhc X-Patchwork-Id: 1057743 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 44N8X71jRZz9s3q; Mon, 18 Mar 2019 19:30:47 +1100 (AEDT) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1h5nfN-0000BV-WC; Mon, 18 Mar 2019 08:30:41 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1h5nfM-0000BE-AY for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:40 +0000 Received: from 1.general.ikepanhc.us.vpn ([10.172.69.54] helo=canonical.com) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.76) (envelope-from ) id 1h5nfL-0000iz-5G for kernel-team@lists.ubuntu.com; Mon, 18 Mar 2019 08:30:40 +0000 From: Ike Panhc To: kernel-team@lists.ubuntu.com Subject: [PATCH 12/12] net-next/hinic: replace disable_irq_nosync/enable_irq Date: Mon, 18 Mar 2019 16:30:35 +0800 Message-Id: <20190318083035.27238-1-ike.pan@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190318082733.26665-1-ike.pan@canonical.com> References: <20190318082733.26665-1-ike.pan@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Xue Chaojing BugLink: https://bugs.launchpad.net/bugs/1820187 In order to avoid frequent system interrupts when sending and receiving packets. we replace disable_irq_nosync/enable_irq with hinic_set_msix_state(), hinic_set_msix_state is used to access memory mapped hinic devices. Signed-off-by: Xue Chaojing Signed-off-by: David S. Miller (cherry picked from commit 905b464ad9008905db099f90ae20f373c7051804) Signed-off-by: Ike Panhc --- .../net/ethernet/huawei/hinic/hinic_hw_dev.c | 13 +++++++++ .../net/ethernet/huawei/hinic/hinic_hw_dev.h | 3 ++ .../net/ethernet/huawei/hinic/hinic_hw_if.c | 28 +++++++++++++++++++ .../net/ethernet/huawei/hinic/hinic_hw_if.h | 14 ++++++++++ drivers/net/ethernet/huawei/hinic/hinic_rx.c | 11 ++++++-- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 8 ++++-- 6 files changed, 73 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c index 79b567447084..368db2009ba9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.c @@ -1011,3 +1011,16 @@ int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, &hw_ci, sizeof(hw_ci), NULL, NULL, HINIC_MGMT_MSG_SYNC); } + +/** + * hinic_hwdev_set_msix_state- set msix state + * @hwdev: the NIC HW device + * @msix_index: IRQ corresponding index number + * @flag: msix state + * + **/ +void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index, + enum hinic_msix_state flag) +{ + hinic_set_msix_state(hwdev->hwif, msix_index, flag); +} diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h index d1a7d2522d82..c9e621e19dd0 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_dev.h @@ -240,4 +240,7 @@ int hinic_hwdev_msix_set(struct hinic_hwdev *hwdev, u16 msix_index, int hinic_hwdev_hw_ci_addr_set(struct hinic_hwdev *hwdev, struct hinic_sq *sq, u8 pending_limit, u8 coalesc_timer); +void hinic_hwdev_set_msix_state(struct hinic_hwdev *hwdev, u16 msix_index, + enum hinic_msix_state flag); + #endif diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c index 823a17061a97..9b160f076904 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.c @@ -168,6 +168,22 @@ void hinic_db_state_set(struct hinic_hwif *hwif, hinic_hwif_write_reg(hwif, HINIC_CSR_FUNC_ATTR4_ADDR, attr4); } +void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx, + enum hinic_msix_state flag) +{ + u32 offset = msix_idx * HINIC_PCI_MSIX_ENTRY_SIZE + + HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL; + u32 mask_bits; + + mask_bits = readl(hwif->intr_regs_base + offset); + mask_bits &= ~HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT; + + if (flag) + mask_bits |= HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT; + + writel(mask_bits, hwif->intr_regs_base + offset); +} + /** * hwif_ready - test if the HW is ready for use * @hwif: the HW interface of a pci function device @@ -321,6 +337,13 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev) return -ENOMEM; } + hwif->intr_regs_base = pci_ioremap_bar(pdev, HINIC_PCI_INTR_REGS_BAR); + if (!hwif->intr_regs_base) { + dev_err(&pdev->dev, "Failed to map configuration regs\n"); + err = -ENOMEM; + goto err_map_intr_bar; + } + err = hwif_ready(hwif); if (err) { dev_err(&pdev->dev, "HW interface is not ready\n"); @@ -337,7 +360,11 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev) return 0; err_hwif_ready: + iounmap(hwif->intr_regs_base); + +err_map_intr_bar: iounmap(hwif->cfg_regs_bar); + return err; } @@ -347,5 +374,6 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev) **/ void hinic_free_hwif(struct hinic_hwif *hwif) { + iounmap(hwif->intr_regs_base); iounmap(hwif->cfg_regs_bar); } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h index 5b4760c0e9f5..22ec7f73e0a6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw_if.h @@ -152,6 +152,7 @@ #define HINIC_IS_PPF(hwif) (HINIC_FUNC_TYPE(hwif) == HINIC_PPF) #define HINIC_PCI_CFG_REGS_BAR 0 +#define HINIC_PCI_INTR_REGS_BAR 2 #define HINIC_PCI_DB_BAR 4 #define HINIC_PCIE_ST_DISABLE 0 @@ -164,6 +165,10 @@ #define HINIC_EQ_MSIX_LLI_CREDIT_LIMIT_DEFAULT 0 /* Disabled */ #define HINIC_EQ_MSIX_RESEND_TIMER_DEFAULT 7 /* max */ +#define HINIC_PCI_MSIX_ENTRY_SIZE 16 +#define HINIC_PCI_MSIX_ENTRY_VECTOR_CTRL 12 +#define HINIC_PCI_MSIX_ENTRY_CTRL_MASKBIT 1 + enum hinic_pcie_nosnoop { HINIC_PCIE_SNOOP = 0, HINIC_PCIE_NO_SNOOP = 1, @@ -207,6 +212,11 @@ enum hinic_db_state { HINIC_DB_DISABLE = 1, }; +enum hinic_msix_state { + HINIC_MSIX_ENABLE, + HINIC_MSIX_DISABLE, +}; + struct hinic_func_attr { u16 func_idx; u8 pf_idx; @@ -226,6 +236,7 @@ struct hinic_func_attr { struct hinic_hwif { struct pci_dev *pdev; void __iomem *cfg_regs_bar; + void __iomem *intr_regs_base; struct hinic_func_attr attr; }; @@ -251,6 +262,9 @@ int hinic_msix_attr_get(struct hinic_hwif *hwif, u16 msix_index, u8 *lli_timer, u8 *lli_credit_limit, u8 *resend_timer); +void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx, + enum hinic_msix_state flag); + int hinic_msix_attr_cnt_clear(struct hinic_hwif *hwif, u16 msix_index); void hinic_set_pf_action(struct hinic_hwif *hwif, enum hinic_pf_action action); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_rx.c b/drivers/net/ethernet/huawei/hinic/hinic_rx.c index 0098b206e7e9..b6d218768ec1 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_rx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_rx.c @@ -381,6 +381,7 @@ static int rxq_recv(struct hinic_rxq *rxq, int budget) static int rx_poll(struct napi_struct *napi, int budget) { struct hinic_rxq *rxq = container_of(napi, struct hinic_rxq, napi); + struct hinic_dev *nic_dev = netdev_priv(rxq->netdev); struct hinic_rq *rq = rxq->rq; int pkts; @@ -389,7 +390,10 @@ static int rx_poll(struct napi_struct *napi, int budget) return budget; napi_complete(napi); - enable_irq(rq->irq); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + rq->msix_entry, + HINIC_MSIX_ENABLE); + return pkts; } @@ -414,7 +418,10 @@ static irqreturn_t rx_irq(int irq, void *data) struct hinic_dev *nic_dev; /* Disable the interrupt until napi will be completed */ - disable_irq_nosync(rq->irq); + nic_dev = netdev_priv(rxq->netdev); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + rq->msix_entry, + HINIC_MSIX_DISABLE); nic_dev = netdev_priv(rxq->netdev); hinic_hwdev_msix_cnt_set(nic_dev->hwdev, rq->msix_entry); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c index 11e73e67358d..e17bf33eba0c 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c @@ -655,7 +655,9 @@ static int free_tx_poll(struct napi_struct *napi, int budget) if (pkts < budget) { napi_complete(napi); - enable_irq(sq->irq); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + sq->msix_entry, + HINIC_MSIX_ENABLE); return pkts; } @@ -682,7 +684,9 @@ static irqreturn_t tx_irq(int irq, void *data) nic_dev = netdev_priv(txq->netdev); /* Disable the interrupt until napi will be completed */ - disable_irq_nosync(txq->sq->irq); + hinic_hwdev_set_msix_state(nic_dev->hwdev, + txq->sq->msix_entry, + HINIC_MSIX_DISABLE); hinic_hwdev_msix_cnt_set(nic_dev->hwdev, txq->sq->msix_entry);