From nobody Wed Sep 10 05:39:07 2025 Received: from szxga05-in.huawei.com (szxga05-in.huawei.com [45.249.212.191]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 565FC30F7F1; Tue, 9 Sep 2025 07:34:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.191 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757403251; cv=none; b=CSLRe2j8XdG8pA9xBpz47TP97y7sigMf42aaek4Tb8e4XCxb8Sp0pr10QwY6RbiVHTwO4HunI6FBlxkrl1d9ktA1ZpE8rPNB6rlwZuVTDBKVK8KXZZ5A5fHKWXZRDGUV0NMXbUT+ftnILPhLeGsBJq1sZolJTpQaiL1BM7R+Lrg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757403251; c=relaxed/simple; bh=1jGNa9J3QDcL5DTi7KJdeol6LXIaopGEj9OKxW3xKRw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=kuEeHyQ1qvEfmpprRnPiHdk8R3ReIUs2oz0COsBqdkmEvx+fCiXn4fawO4oIcJJPwZv5SJpzdPvofqic90xlj1dLZOkHmJMzm6B+zCosAI5QaXOCz/af/UrVAfa4LBY+UFSVuaGsUdMpZg1qURvpedIpXI8RkL202WgRMuItk0g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; arc=none smtp.client-ip=45.249.212.191 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Received: from mail.maildlp.com (unknown [172.19.162.112]) by szxga05-in.huawei.com (SkyGuard) with ESMTP id 4cLb8X30pWz24j4R; Tue, 9 Sep 2025 15:30:52 +0800 (CST) Received: from kwepemf100013.china.huawei.com (unknown [7.202.181.12]) by mail.maildlp.com (Postfix) with ESMTPS id 7377814013B; Tue, 9 Sep 2025 15:34:06 +0800 (CST) Received: from DESKTOP-62GVMTR.china.huawei.com (10.174.189.55) by kwepemf100013.china.huawei.com (7.202.181.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Tue, 9 Sep 2025 15:34:04 +0800 From: Fan Gong To: Fan Gong , Zhu Yikai CC: , , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Andrew Lunn , , Jonathan Corbet , Bjorn Helgaas , luosifu , Xin Guo , Shen Chenyang , Zhou Shuai , Wu Like , Shi Jing , Luo Yang , Meny Yossefi , Gur Stavi , Lee Trager , Michael Ellerman , Vadim Fedorenko , Suman Ghosh , Przemek Kitszel , Joe Damato , Christophe JAILLET Subject: [PATCH net-next v05 09/14] hinic3: Queue pair context initialization Date: Tue, 9 Sep 2025 15:33:34 +0800 Message-ID: <8323dc5ce83f9d442c00824dd7dd24e55ddfb666.1757401320.git.zhuyikai1@h-partners.com> X-Mailer: git-send-email 2.51.0.windows.1 In-Reply-To: References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100002.china.huawei.com (7.221.188.206) To kwepemf100013.china.huawei.com (7.202.181.12) Content-Type: text/plain; charset="utf-8" Initialize queue pair context of hardware interaction. Co-developed-by: Zhu Yikai Signed-off-by: Zhu Yikai Signed-off-by: Fan Gong --- .../ethernet/huawei/hinic3/hinic3_hw_comm.c | 88 +++ .../ethernet/huawei/hinic3/hinic3_hw_comm.h | 3 + .../huawei/hinic3/hinic3_mgmt_interface.h | 20 + .../huawei/hinic3/hinic3_netdev_ops.c | 42 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.c | 35 ++ .../ethernet/huawei/hinic3/hinic3_nic_cfg.h | 12 + .../ethernet/huawei/hinic3/hinic3_nic_io.c | 579 ++++++++++++++++++ .../ethernet/huawei/hinic3/hinic3_nic_io.h | 3 + 8 files changed, 782 insertions(+) diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.c index 4badf1d4173a..3c37d7e8e628 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -334,3 +334,91 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev) =20 return ret; } + +static int get_hw_rx_buf_size_idx(int rx_buf_sz, u16 *buf_sz_idx) +{ + /* Supported RX buffer sizes in bytes. Configured by array index. */ + static const int supported_sizes[16] =3D { + [0] =3D 32, [1] =3D 64, [2] =3D 96, [3] =3D 128, + [4] =3D 192, [5] =3D 256, [6] =3D 384, [7] =3D 512, + [8] =3D 768, [9] =3D 1024, [10] =3D 1536, [11] =3D 2048, + [12] =3D 3072, [13] =3D 4096, [14] =3D 8192, [15] =3D 16384, + }; + u16 idx; + + /* Scan from biggest to smallest. Choose supported size that is equal or + * smaller. For smaller value HW will under-utilize posted buffers. For + * bigger value HW may overrun posted buffers. + */ + idx =3D ARRAY_SIZE(supported_sizes); + while (idx > 0) { + idx--; + if (supported_sizes[idx] <=3D rx_buf_sz) { + *buf_sz_idx =3D idx; + return 0; + } + } + + return -EINVAL; +} + +int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_= depth, + int rx_buf_sz) +{ + struct comm_cmd_set_root_ctxt root_ctxt =3D {}; + struct mgmt_msg_params msg_params =3D {}; + u16 buf_sz_idx; + int err; + + err =3D get_hw_rx_buf_size_idx(rx_buf_sz, &buf_sz_idx); + if (err) + return err; + + root_ctxt.func_id =3D hinic3_global_func_id(hwdev); + + root_ctxt.set_cmdq_depth =3D 0; + root_ctxt.cmdq_depth =3D 0; + + root_ctxt.lro_en =3D 1; + + root_ctxt.rq_depth =3D ilog2(rq_depth); + root_ctxt.rx_buf_sz =3D buf_sz_idx; + root_ctxt.sq_depth =3D ilog2(sq_depth); + + mgmt_msg_params_init_default(&msg_params, &root_ctxt, + sizeof(root_ctxt)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_VAT, &msg_params); + if (err || root_ctxt.head.status) { + dev_err(hwdev->dev, + "Failed to set root context, err: %d, status: 0x%x\n", + err, root_ctxt.head.status); + return -EFAULT; + } + + return 0; +} + +int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev) +{ + struct comm_cmd_set_root_ctxt root_ctxt =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + root_ctxt.func_id =3D hinic3_global_func_id(hwdev); + + mgmt_msg_params_init_default(&msg_params, &root_ctxt, + sizeof(root_ctxt)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_COMM, + COMM_CMD_SET_VAT, &msg_params); + if (err || root_ctxt.head.status) { + dev_err(hwdev->dev, + "Failed to set root context, err: %d, status: 0x%x\n", + err, root_ctxt.head.status); + return -EFAULT; + } + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_hw_comm.h index 35b93e36e004..304f5691f0c2 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.h @@ -40,5 +40,8 @@ int hinic3_set_wq_page_size(struct hinic3_hwdev *hwdev, u= 16 func_idx, u32 page_size); int hinic3_set_cmdq_depth(struct hinic3_hwdev *hwdev, u16 cmdq_depth); int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev); +int hinic3_set_root_ctxt(struct hinic3_hwdev *hwdev, u32 rq_depth, u32 sq_= depth, + int rx_buf_sz); +int hinic3_clean_root_ctxt(struct hinic3_hwdev *hwdev); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/d= rivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index c4434efdc7f7..b891290a3d6e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -56,6 +56,19 @@ struct l2nic_cmd_update_mac { u8 new_mac[ETH_ALEN]; }; =20 +struct l2nic_cmd_set_ci_attr { + struct mgmt_msg_head msg_head; + u16 func_idx; + u8 dma_attr_off; + u8 pending_limit; + u8 coalescing_time; + u8 intr_en; + u16 intr_idx; + u32 l2nic_sqn; + u32 rsvd; + u64 ci_addr; +}; + struct l2nic_cmd_force_pkt_drop { struct mgmt_msg_head msg_head; u8 port; @@ -82,6 +95,13 @@ enum l2nic_cmd { L2NIC_CMD_MAX =3D 256, }; =20 +/* NIC CMDQ MODE */ +enum l2nic_ucode_cmd { + L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX =3D 0, + L2NIC_UCODE_CMD_CLEAN_QUEUE_CTX =3D 1, + L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL =3D 4, +}; + enum hinic3_nic_feature_cap { HINIC3_NIC_F_CSUM =3D BIT(0), HINIC3_NIC_F_SCTP_CRC =3D BIT(1), diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drive= rs/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index c0010308f7d6..2c5c7051e72e 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -220,6 +220,39 @@ static void hinic3_free_channel_resources(struct net_d= evice *netdev, hinic3_free_qps(nic_dev, qp_params); } =20 +static int hinic3_open_channel(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + int err; + + err =3D hinic3_init_qp_ctxts(nic_dev); + if (err) { + netdev_err(netdev, "Failed to init qps\n"); + return err; + } + + err =3D hinic3_qps_irq_init(netdev); + if (err) { + netdev_err(netdev, "Failed to init txrxq irq\n"); + goto err_free_qp_ctxts; + } + + return 0; + +err_free_qp_ctxts: + hinic3_free_qp_ctxts(nic_dev); + + return err; +} + +static void hinic3_close_channel(struct net_device *netdev) +{ + struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); + + hinic3_qps_irq_uninit(netdev); + hinic3_free_qp_ctxts(nic_dev); +} + static int hinic3_open(struct net_device *netdev) { struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); @@ -245,8 +278,16 @@ static int hinic3_open(struct net_device *netdev) =20 hinic3_init_qps(nic_dev, &qp_params); =20 + err =3D hinic3_open_channel(netdev); + if (err) + goto err_uninit_qps; + return 0; =20 +err_uninit_qps: + hinic3_uninit_qps(nic_dev, &qp_params); + hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); + err_destroy_num_qps: hinic3_destroy_num_qps(netdev); err_free_nicio_res: @@ -260,6 +301,7 @@ static int hinic3_close(struct net_device *netdev) struct hinic3_nic_dev *nic_dev =3D netdev_priv(netdev); struct hinic3_dyna_qp_params qp_params; =20 + hinic3_close_channel(netdev); hinic3_uninit_qps(nic_dev, &qp_params); hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params); =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.c index 049f9536cb86..5b18764781d4 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c @@ -229,6 +229,41 @@ int hinic3_update_mac(struct hinic3_hwdev *hwdev, cons= t u8 *old_mac, err, mac_info.msg_head.status); return -EIO; } + + return 0; +} + +int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, struct hinic3_sq_attr = *attr) +{ + struct l2nic_cmd_set_ci_attr cons_idx_attr =3D {}; + struct mgmt_msg_params msg_params =3D {}; + int err; + + cons_idx_attr.func_idx =3D hinic3_global_func_id(hwdev); + cons_idx_attr.dma_attr_off =3D attr->dma_attr_off; + cons_idx_attr.pending_limit =3D attr->pending_limit; + cons_idx_attr.coalescing_time =3D attr->coalescing_time; + + if (attr->intr_en) { + cons_idx_attr.intr_en =3D attr->intr_en; + cons_idx_attr.intr_idx =3D attr->intr_idx; + } + + cons_idx_attr.l2nic_sqn =3D attr->l2nic_sqn; + cons_idx_attr.ci_addr =3D attr->ci_dma_base; + + mgmt_msg_params_init_default(&msg_params, &cons_idx_attr, + sizeof(cons_idx_attr)); + + err =3D hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC, + L2NIC_CMD_SET_SQ_CI_ATTR, &msg_params); + if (err || cons_idx_attr.msg_head.status) { + dev_err(hwdev->dev, + "Failed to set ci attribute table, err: %d, status: 0x%x\n", + err, cons_idx_attr.msg_head.status); + return -EFAULT; + } + return 0; } =20 diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/= net/ethernet/huawei/hinic3/hinic3_nic_cfg.h index 6b6851650a37..dd1615745f02 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h @@ -22,6 +22,16 @@ enum hinic3_nic_event_type { HINIC3_NIC_EVENT_LINK_UP =3D 1, }; =20 +struct hinic3_sq_attr { + u8 dma_attr_off; + u8 pending_limit; + u8 coalescing_time; + u8 intr_en; + u16 intr_idx; + u32 l2nic_sqn; + u64 ci_dma_base; +}; + int hinic3_get_nic_feature_from_hw(struct hinic3_nic_dev *nic_dev); int hinic3_set_nic_feature_to_hw(struct hinic3_nic_dev *nic_dev); bool hinic3_test_support(struct hinic3_nic_dev *nic_dev, @@ -38,6 +48,8 @@ int hinic3_del_mac(struct hinic3_hwdev *hwdev, const u8 *= mac_addr, u16 vlan_id, int hinic3_update_mac(struct hinic3_hwdev *hwdev, const u8 *old_mac, u8 *new_mac, u16 vlan_id, u16 func_id); =20 +int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, + struct hinic3_sq_attr *attr); int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev); =20 #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.c index 8f06ff5c377d..65881f6bf2af 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. =20 +#include "hinic3_cmdq.h" #include "hinic3_hw_comm.h" #include "hinic3_hw_intf.h" #include "hinic3_hwdev.h" @@ -9,6 +10,11 @@ #include "hinic3_nic_dev.h" #include "hinic3_nic_io.h" =20 +#define HINIC3_DEFAULT_TX_CI_PENDING_LIMIT 1 +#define HINIC3_DEFAULT_TX_CI_COALESCING_TIME 1 +#define HINIC3_DEFAULT_DROP_THD_ON (0xFFFF) +#define HINIC3_DEFAULT_DROP_THD_OFF 0 + #define HINIC3_CI_Q_ADDR_SIZE (64) =20 #define HINIC3_CI_TABLE_SIZE(num_qps) \ @@ -17,6 +23,186 @@ #define HINIC3_CI_VADDR(base_addr, q_id) \ ((u8 *)(base_addr) + (q_id) * HINIC3_CI_Q_ADDR_SIZE) =20 +#define HINIC3_CI_PADDR(base_paddr, q_id) \ + ((base_paddr) + (q_id) * HINIC3_CI_Q_ADDR_SIZE) + +#define SQ_WQ_PREFETCH_MAX 1 +#define SQ_WQ_PREFETCH_MIN 1 +#define SQ_WQ_PREFETCH_THRESHOLD 16 + +#define RQ_WQ_PREFETCH_MAX 4 +#define RQ_WQ_PREFETCH_MIN 1 +#define RQ_WQ_PREFETCH_THRESHOLD 256 + +/* (2048 - 8) / 64 */ +#define HINIC3_Q_CTXT_MAX 31 + +enum hinic3_qp_ctxt_type { + HINIC3_QP_CTXT_TYPE_SQ =3D 0, + HINIC3_QP_CTXT_TYPE_RQ =3D 1, +}; + +struct hinic3_qp_ctxt_hdr { + __le16 num_queues; + __le16 queue_type; + __le16 start_qid; + __le16 rsvd; +}; + +struct hinic3_sq_ctxt { + __le32 ci_pi; + __le32 drop_mode_sp; + __le32 wq_pfn_hi_owner; + __le32 wq_pfn_lo; + + __le32 rsvd0; + __le32 pkt_drop_thd; + __le32 global_sq_id; + __le32 vlan_ceq_attr; + + __le32 pref_cache; + __le32 pref_ci_owner; + __le32 pref_wq_pfn_hi_ci; + __le32 pref_wq_pfn_lo; + + __le32 rsvd8; + __le32 rsvd9; + __le32 wq_block_pfn_hi; + __le32 wq_block_pfn_lo; +}; + +struct hinic3_rq_ctxt { + __le32 ci_pi; + __le32 ceq_attr; + __le32 wq_pfn_hi_type_owner; + __le32 wq_pfn_lo; + + __le32 rsvd[3]; + __le32 cqe_sge_len; + + __le32 pref_cache; + __le32 pref_ci_owner; + __le32 pref_wq_pfn_hi_ci; + __le32 pref_wq_pfn_lo; + + __le32 pi_paddr_hi; + __le32 pi_paddr_lo; + __le32 wq_block_pfn_hi; + __le32 wq_block_pfn_lo; +}; + +struct hinic3_sq_ctxt_block { + struct hinic3_qp_ctxt_hdr cmdq_hdr; + struct hinic3_sq_ctxt sq_ctxt[HINIC3_Q_CTXT_MAX]; +}; + +struct hinic3_rq_ctxt_block { + struct hinic3_qp_ctxt_hdr cmdq_hdr; + struct hinic3_rq_ctxt rq_ctxt[HINIC3_Q_CTXT_MAX]; +}; + +struct hinic3_clean_queue_ctxt { + struct hinic3_qp_ctxt_hdr cmdq_hdr; + __le32 rsvd; +}; + +#define SQ_CTXT_SIZE(num_sqs) \ + (sizeof(struct hinic3_qp_ctxt_hdr) + \ + (num_sqs) * sizeof(struct hinic3_sq_ctxt)) + +#define RQ_CTXT_SIZE(num_rqs) \ + (sizeof(struct hinic3_qp_ctxt_hdr) + \ + (num_rqs) * sizeof(struct hinic3_rq_ctxt)) + +#define SQ_CTXT_PREF_CI_HI_SHIFT 12 +#define SQ_CTXT_PREF_CI_HI(val) ((val) >> SQ_CTXT_PREF_CI_HI_SH= IFT) + +#define SQ_CTXT_PI_IDX_MASK GENMASK(15, 0) +#define SQ_CTXT_CI_IDX_MASK GENMASK(31, 16) +#define SQ_CTXT_CI_PI_SET(val, member) \ + FIELD_PREP(SQ_CTXT_##member##_MASK, val) + +#define SQ_CTXT_MODE_SP_FLAG_MASK BIT(0) +#define SQ_CTXT_MODE_PKT_DROP_MASK BIT(1) +#define SQ_CTXT_MODE_SET(val, member) \ + FIELD_PREP(SQ_CTXT_MODE_##member##_MASK, val) + +#define SQ_CTXT_WQ_PAGE_HI_PFN_MASK GENMASK(19, 0) +#define SQ_CTXT_WQ_PAGE_OWNER_MASK BIT(23) +#define SQ_CTXT_WQ_PAGE_SET(val, member) \ + FIELD_PREP(SQ_CTXT_WQ_PAGE_##member##_MASK, val) + +#define SQ_CTXT_PKT_DROP_THD_ON_MASK GENMASK(15, 0) +#define SQ_CTXT_PKT_DROP_THD_OFF_MASK GENMASK(31, 16) +#define SQ_CTXT_PKT_DROP_THD_SET(val, member) \ + FIELD_PREP(SQ_CTXT_PKT_DROP_##member##_MASK, val) + +#define SQ_CTXT_GLOBAL_SQ_ID_MASK GENMASK(12, 0) +#define SQ_CTXT_GLOBAL_QUEUE_ID_SET(val, member) \ + FIELD_PREP(SQ_CTXT_##member##_MASK, val) + +#define SQ_CTXT_VLAN_INSERT_MODE_MASK GENMASK(20, 19) +#define SQ_CTXT_VLAN_CEQ_EN_MASK BIT(23) +#define SQ_CTXT_VLAN_CEQ_SET(val, member) \ + FIELD_PREP(SQ_CTXT_VLAN_##member##_MASK, val) + +#define SQ_CTXT_PREF_CACHE_THRESHOLD_MASK GENMASK(13, 0) +#define SQ_CTXT_PREF_CACHE_MAX_MASK GENMASK(24, 14) +#define SQ_CTXT_PREF_CACHE_MIN_MASK GENMASK(31, 25) + +#define SQ_CTXT_PREF_CI_HI_MASK GENMASK(3, 0) +#define SQ_CTXT_PREF_OWNER_MASK BIT(4) + +#define SQ_CTXT_PREF_WQ_PFN_HI_MASK GENMASK(19, 0) +#define SQ_CTXT_PREF_CI_LOW_MASK GENMASK(31, 20) +#define SQ_CTXT_PREF_SET(val, member) \ + FIELD_PREP(SQ_CTXT_PREF_##member##_MASK, val) + +#define SQ_CTXT_WQ_BLOCK_PFN_HI_MASK GENMASK(22, 0) +#define SQ_CTXT_WQ_BLOCK_SET(val, member) \ + FIELD_PREP(SQ_CTXT_WQ_BLOCK_##member##_MASK, val) + +#define RQ_CTXT_PI_IDX_MASK GENMASK(15, 0) +#define RQ_CTXT_CI_IDX_MASK GENMASK(31, 16) +#define RQ_CTXT_CI_PI_SET(val, member) \ + FIELD_PREP(RQ_CTXT_##member##_MASK, val) + +#define RQ_CTXT_CEQ_ATTR_INTR_MASK GENMASK(30, 21) +#define RQ_CTXT_CEQ_ATTR_EN_MASK BIT(31) +#define RQ_CTXT_CEQ_ATTR_SET(val, member) \ + FIELD_PREP(RQ_CTXT_CEQ_ATTR_##member##_MASK, val) + +#define RQ_CTXT_WQ_PAGE_HI_PFN_MASK GENMASK(19, 0) +#define RQ_CTXT_WQ_PAGE_WQE_TYPE_MASK GENMASK(29, 28) +#define RQ_CTXT_WQ_PAGE_OWNER_MASK BIT(31) +#define RQ_CTXT_WQ_PAGE_SET(val, member) \ + FIELD_PREP(RQ_CTXT_WQ_PAGE_##member##_MASK, val) + +#define RQ_CTXT_CQE_LEN_MASK GENMASK(29, 28) +#define RQ_CTXT_CQE_LEN_SET(val, member) \ + FIELD_PREP(RQ_CTXT_##member##_MASK, val) + +#define RQ_CTXT_PREF_CACHE_THRESHOLD_MASK GENMASK(13, 0) +#define RQ_CTXT_PREF_CACHE_MAX_MASK GENMASK(24, 14) +#define RQ_CTXT_PREF_CACHE_MIN_MASK GENMASK(31, 25) + +#define RQ_CTXT_PREF_CI_HI_MASK GENMASK(3, 0) +#define RQ_CTXT_PREF_OWNER_MASK BIT(4) + +#define RQ_CTXT_PREF_WQ_PFN_HI_MASK GENMASK(19, 0) +#define RQ_CTXT_PREF_CI_LOW_MASK GENMASK(31, 20) +#define RQ_CTXT_PREF_SET(val, member) \ + FIELD_PREP(RQ_CTXT_PREF_##member##_MASK, val) + +#define RQ_CTXT_WQ_BLOCK_PFN_HI_MASK GENMASK(22, 0) +#define RQ_CTXT_WQ_BLOCK_SET(val, member) \ + FIELD_PREP(RQ_CTXT_WQ_BLOCK_##member##_MASK, val) + +#define WQ_PAGE_PFN_SHIFT 12 +#define WQ_BLOCK_PFN_SHIFT 9 +#define WQ_PAGE_PFN(page_addr) ((page_addr) >> WQ_PAGE_PFN_SHIFT) +#define WQ_BLOCK_PFN(page_addr) ((page_addr) >> WQ_BLOCK_PFN_SHIFT) + int hinic3_init_nic_io(struct hinic3_nic_dev *nic_dev) { struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; @@ -304,3 +490,396 @@ void hinic3_uninit_qps(struct hinic3_nic_dev *nic_dev, qp_params->rqs =3D nic_io->rq; qp_params->num_qps =3D nic_io->num_qps; } + +static void hinic3_qp_prepare_cmdq_header(struct hinic3_qp_ctxt_hdr *qp_ct= xt_hdr, + enum hinic3_qp_ctxt_type ctxt_type, + u16 num_queues, u16 q_id) +{ + qp_ctxt_hdr->queue_type =3D cpu_to_le16(ctxt_type); + qp_ctxt_hdr->num_queues =3D cpu_to_le16(num_queues); + qp_ctxt_hdr->start_qid =3D cpu_to_le16(q_id); + qp_ctxt_hdr->rsvd =3D 0; +} + +static void hinic3_sq_prepare_ctxt(struct hinic3_io_queue *sq, u16 sq_id, + struct hinic3_sq_ctxt *sq_ctxt) +{ + u64 wq_page_addr, wq_page_pfn, wq_block_pfn; + u32 wq_block_pfn_hi, wq_block_pfn_lo; + u32 wq_page_pfn_hi, wq_page_pfn_lo; + u16 pi_start, ci_start; + + ci_start =3D hinic3_get_sq_local_ci(sq); + pi_start =3D hinic3_get_sq_local_pi(sq); + + wq_page_addr =3D hinic3_wq_get_first_wqe_page_addr(&sq->wq); + + wq_page_pfn =3D WQ_PAGE_PFN(wq_page_addr); + wq_page_pfn_hi =3D upper_32_bits(wq_page_pfn); + wq_page_pfn_lo =3D lower_32_bits(wq_page_pfn); + + wq_block_pfn =3D WQ_BLOCK_PFN(sq->wq.wq_block_paddr); + wq_block_pfn_hi =3D upper_32_bits(wq_block_pfn); + wq_block_pfn_lo =3D lower_32_bits(wq_block_pfn); + + sq_ctxt->ci_pi =3D + cpu_to_le32(SQ_CTXT_CI_PI_SET(ci_start, CI_IDX) | + SQ_CTXT_CI_PI_SET(pi_start, PI_IDX)); + + sq_ctxt->drop_mode_sp =3D + cpu_to_le32(SQ_CTXT_MODE_SET(0, SP_FLAG) | + SQ_CTXT_MODE_SET(0, PKT_DROP)); + + sq_ctxt->wq_pfn_hi_owner =3D + cpu_to_le32(SQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) | + SQ_CTXT_WQ_PAGE_SET(1, OWNER)); + + sq_ctxt->wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + sq_ctxt->pkt_drop_thd =3D + cpu_to_le32(SQ_CTXT_PKT_DROP_THD_SET(HINIC3_DEFAULT_DROP_THD_ON, THD_ON)= | + SQ_CTXT_PKT_DROP_THD_SET(HINIC3_DEFAULT_DROP_THD_OFF, THD_OFF)); + + sq_ctxt->global_sq_id =3D + cpu_to_le32(SQ_CTXT_GLOBAL_QUEUE_ID_SET((u32)sq_id, + GLOBAL_SQ_ID)); + + /* enable insert c-vlan by default */ + sq_ctxt->vlan_ceq_attr =3D + cpu_to_le32(SQ_CTXT_VLAN_CEQ_SET(0, CEQ_EN) | + SQ_CTXT_VLAN_CEQ_SET(1, INSERT_MODE)); + + sq_ctxt->rsvd0 =3D 0; + + sq_ctxt->pref_cache =3D + cpu_to_le32(SQ_CTXT_PREF_SET(SQ_WQ_PREFETCH_MIN, CACHE_MIN) | + SQ_CTXT_PREF_SET(SQ_WQ_PREFETCH_MAX, CACHE_MAX) | + SQ_CTXT_PREF_SET(SQ_WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD)); + + sq_ctxt->pref_ci_owner =3D + cpu_to_le32(SQ_CTXT_PREF_SET(SQ_CTXT_PREF_CI_HI(ci_start), CI_HI) | + SQ_CTXT_PREF_SET(1, OWNER)); + + sq_ctxt->pref_wq_pfn_hi_ci =3D + cpu_to_le32(SQ_CTXT_PREF_SET(ci_start, CI_LOW) | + SQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI)); + + sq_ctxt->pref_wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + sq_ctxt->wq_block_pfn_hi =3D + cpu_to_le32(SQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI)); + + sq_ctxt->wq_block_pfn_lo =3D cpu_to_le32(wq_block_pfn_lo); +} + +static void hinic3_rq_prepare_ctxt_get_wq_info(struct hinic3_io_queue *rq, + u32 *wq_page_pfn_hi, + u32 *wq_page_pfn_lo, + u32 *wq_block_pfn_hi, + u32 *wq_block_pfn_lo) +{ + u64 wq_page_addr, wq_page_pfn, wq_block_pfn; + + wq_page_addr =3D hinic3_wq_get_first_wqe_page_addr(&rq->wq); + + wq_page_pfn =3D WQ_PAGE_PFN(wq_page_addr); + *wq_page_pfn_hi =3D upper_32_bits(wq_page_pfn); + *wq_page_pfn_lo =3D lower_32_bits(wq_page_pfn); + + wq_block_pfn =3D WQ_BLOCK_PFN(rq->wq.wq_block_paddr); + *wq_block_pfn_hi =3D upper_32_bits(wq_block_pfn); + *wq_block_pfn_lo =3D lower_32_bits(wq_block_pfn); +} + +static void hinic3_rq_prepare_ctxt(struct hinic3_io_queue *rq, + struct hinic3_rq_ctxt *rq_ctxt) +{ + u32 wq_block_pfn_hi, wq_block_pfn_lo; + u32 wq_page_pfn_hi, wq_page_pfn_lo; + u16 pi_start, ci_start; + + ci_start =3D (rq->wq.cons_idx & rq->wq.idx_mask) << HINIC3_NORMAL_RQ_WQE; + pi_start =3D (rq->wq.prod_idx & rq->wq.idx_mask) << HINIC3_NORMAL_RQ_WQE; + + hinic3_rq_prepare_ctxt_get_wq_info(rq, &wq_page_pfn_hi, &wq_page_pfn_lo, + &wq_block_pfn_hi, &wq_block_pfn_lo); + + rq_ctxt->ci_pi =3D + cpu_to_le32(RQ_CTXT_CI_PI_SET(ci_start, CI_IDX) | + RQ_CTXT_CI_PI_SET(pi_start, PI_IDX)); + + rq_ctxt->ceq_attr =3D + cpu_to_le32(RQ_CTXT_CEQ_ATTR_SET(0, EN) | + RQ_CTXT_CEQ_ATTR_SET(rq->msix_entry_idx, INTR)); + + rq_ctxt->wq_pfn_hi_type_owner =3D + cpu_to_le32(RQ_CTXT_WQ_PAGE_SET(wq_page_pfn_hi, HI_PFN) | + RQ_CTXT_WQ_PAGE_SET(1, OWNER)); + + /* use 16Byte WQE */ + rq_ctxt->wq_pfn_hi_type_owner |=3D + cpu_to_le32(RQ_CTXT_WQ_PAGE_SET(2, WQE_TYPE)); + rq_ctxt->cqe_sge_len =3D cpu_to_le32(RQ_CTXT_CQE_LEN_SET(1, CQE_LEN)); + + rq_ctxt->wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + rq_ctxt->pref_cache =3D + cpu_to_le32(RQ_CTXT_PREF_SET(RQ_WQ_PREFETCH_MIN, CACHE_MIN) | + RQ_CTXT_PREF_SET(RQ_WQ_PREFETCH_MAX, CACHE_MAX) | + RQ_CTXT_PREF_SET(RQ_WQ_PREFETCH_THRESHOLD, CACHE_THRESHOLD)); + + rq_ctxt->pref_ci_owner =3D + cpu_to_le32(RQ_CTXT_PREF_SET(SQ_CTXT_PREF_CI_HI(ci_start), CI_HI) | + RQ_CTXT_PREF_SET(1, OWNER)); + + rq_ctxt->pref_wq_pfn_hi_ci =3D + cpu_to_le32(RQ_CTXT_PREF_SET(wq_page_pfn_hi, WQ_PFN_HI) | + RQ_CTXT_PREF_SET(ci_start, CI_LOW)); + + rq_ctxt->pref_wq_pfn_lo =3D cpu_to_le32(wq_page_pfn_lo); + + rq_ctxt->wq_block_pfn_hi =3D + cpu_to_le32(RQ_CTXT_WQ_BLOCK_SET(wq_block_pfn_hi, PFN_HI)); + + rq_ctxt->wq_block_pfn_lo =3D cpu_to_le32(wq_block_pfn_lo); +} + +static int init_sq_ctxts(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_sq_ctxt_block *sq_ctxt_block; + u16 q_id, curr_id, max_ctxts, i; + struct hinic3_sq_ctxt *sq_ctxt; + struct hinic3_cmd_buf *cmd_buf; + struct hinic3_io_queue *sq; + __le64 out_param; + int err =3D 0; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + q_id =3D 0; + while (q_id < nic_io->num_qps) { + sq_ctxt_block =3D cmd_buf->buf; + sq_ctxt =3D sq_ctxt_block->sq_ctxt; + + max_ctxts =3D (nic_io->num_qps - q_id) > HINIC3_Q_CTXT_MAX ? + HINIC3_Q_CTXT_MAX : (nic_io->num_qps - q_id); + + hinic3_qp_prepare_cmdq_header(&sq_ctxt_block->cmdq_hdr, + HINIC3_QP_CTXT_TYPE_SQ, max_ctxts, + q_id); + + for (i =3D 0; i < max_ctxts; i++) { + curr_id =3D q_id + i; + sq =3D &nic_io->sq[curr_id]; + hinic3_sq_prepare_ctxt(sq, curr_id, &sq_ctxt[i]); + } + + hinic3_cmdq_buf_swab32(sq_ctxt_block, sizeof(*sq_ctxt_block)); + + cmd_buf->size =3D cpu_to_le16(SQ_CTXT_SIZE(max_ctxts)); + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to set SQ ctxts, err: %d, out_param: 0x%llx= \n", + err, out_param); + err =3D -EFAULT; + break; + } + + q_id +=3D max_ctxts; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int init_rq_ctxts(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_rq_ctxt_block *rq_ctxt_block; + u16 q_id, curr_id, max_ctxts, i; + struct hinic3_rq_ctxt *rq_ctxt; + struct hinic3_cmd_buf *cmd_buf; + struct hinic3_io_queue *rq; + __le64 out_param; + int err =3D 0; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + q_id =3D 0; + while (q_id < nic_io->num_qps) { + rq_ctxt_block =3D cmd_buf->buf; + rq_ctxt =3D rq_ctxt_block->rq_ctxt; + + max_ctxts =3D (nic_io->num_qps - q_id) > HINIC3_Q_CTXT_MAX ? + HINIC3_Q_CTXT_MAX : (nic_io->num_qps - q_id); + + hinic3_qp_prepare_cmdq_header(&rq_ctxt_block->cmdq_hdr, + HINIC3_QP_CTXT_TYPE_RQ, max_ctxts, + q_id); + + for (i =3D 0; i < max_ctxts; i++) { + curr_id =3D q_id + i; + rq =3D &nic_io->rq[curr_id]; + hinic3_rq_prepare_ctxt(rq, &rq_ctxt[i]); + } + + hinic3_cmdq_buf_swab32(rq_ctxt_block, sizeof(*rq_ctxt_block)); + + cmd_buf->size =3D cpu_to_le16(RQ_CTXT_SIZE(max_ctxts)); + + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_MODIFY_QUEUE_CTX, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to set RQ ctxts, err: %d, out_param: 0x%llx= \n", + err, out_param); + err =3D -EFAULT; + break; + } + + q_id +=3D max_ctxts; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int init_qp_ctxts(struct hinic3_nic_dev *nic_dev) +{ + int err; + + err =3D init_sq_ctxts(nic_dev); + if (err) + return err; + + err =3D init_rq_ctxts(nic_dev); + if (err) + return err; + + return 0; +} + +static int clean_queue_offload_ctxt(struct hinic3_nic_dev *nic_dev, + enum hinic3_qp_ctxt_type ctxt_type) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_clean_queue_ctxt *ctxt_block; + struct hinic3_cmd_buf *cmd_buf; + __le64 out_param; + int err; + + cmd_buf =3D hinic3_alloc_cmd_buf(hwdev); + if (!cmd_buf) { + dev_err(hwdev->dev, "Failed to allocate cmd buf\n"); + return -ENOMEM; + } + + ctxt_block =3D cmd_buf->buf; + ctxt_block->cmdq_hdr.num_queues =3D cpu_to_le16(nic_io->max_qps); + ctxt_block->cmdq_hdr.queue_type =3D cpu_to_le16(ctxt_type); + ctxt_block->cmdq_hdr.start_qid =3D 0; + ctxt_block->cmdq_hdr.rsvd =3D 0; + ctxt_block->rsvd =3D 0; + + hinic3_cmdq_buf_swab32(ctxt_block, sizeof(*ctxt_block)); + + cmd_buf->size =3D cpu_to_le16(sizeof(*ctxt_block)); + + err =3D hinic3_cmdq_direct_resp(hwdev, MGMT_MOD_L2NIC, + L2NIC_UCODE_CMD_CLEAN_QUEUE_CTX, + cmd_buf, &out_param); + if (err || out_param) { + dev_err(hwdev->dev, "Failed to clean queue offload ctxts, err: %d,out_pa= ram: 0x%llx\n", + err, out_param); + + err =3D -EFAULT; + } + + hinic3_free_cmd_buf(hwdev, cmd_buf); + + return err; +} + +static int clean_qp_offload_ctxt(struct hinic3_nic_dev *nic_dev) +{ + /* clean LRO/TSO context space */ + return (clean_queue_offload_ctxt(nic_dev, HINIC3_QP_CTXT_TYPE_SQ) || + clean_queue_offload_ctxt(nic_dev, HINIC3_QP_CTXT_TYPE_RQ)); +} + +/* init qps ctxt and set sq ci attr and arm all sq */ +int hinic3_init_qp_ctxts(struct hinic3_nic_dev *nic_dev) +{ + struct hinic3_nic_io *nic_io =3D nic_dev->nic_io; + struct hinic3_hwdev *hwdev =3D nic_dev->hwdev; + struct hinic3_sq_attr sq_attr; + u32 rq_depth; + u16 q_id; + int err; + + err =3D init_qp_ctxts(nic_dev); + if (err) { + dev_err(hwdev->dev, "Failed to init QP ctxts\n"); + return err; + } + + /* clean LRO/TSO context space */ + err =3D clean_qp_offload_ctxt(nic_dev); + if (err) { + dev_err(hwdev->dev, "Failed to clean qp offload ctxts\n"); + return err; + } + + rq_depth =3D nic_io->rq[0].wq.q_depth << HINIC3_NORMAL_RQ_WQE; + + err =3D hinic3_set_root_ctxt(hwdev, rq_depth, nic_io->sq[0].wq.q_depth, + nic_io->rx_buf_len); + if (err) { + dev_err(hwdev->dev, "Failed to set root context\n"); + return err; + } + + for (q_id =3D 0; q_id < nic_io->num_qps; q_id++) { + sq_attr.ci_dma_base =3D + HINIC3_CI_PADDR(nic_io->ci_dma_base, q_id) >> 0x2; + sq_attr.pending_limit =3D HINIC3_DEFAULT_TX_CI_PENDING_LIMIT; + sq_attr.coalescing_time =3D HINIC3_DEFAULT_TX_CI_COALESCING_TIME; + sq_attr.intr_en =3D 1; + sq_attr.intr_idx =3D nic_io->sq[q_id].msix_entry_idx; + sq_attr.l2nic_sqn =3D q_id; + sq_attr.dma_attr_off =3D 0; + err =3D hinic3_set_ci_table(hwdev, &sq_attr); + if (err) { + dev_err(hwdev->dev, "Failed to set ci table\n"); + goto err_clean_root_ctxt; + } + } + + return 0; + +err_clean_root_ctxt: + hinic3_clean_root_ctxt(hwdev); + + return err; +} + +void hinic3_free_qp_ctxts(struct hinic3_nic_dev *nic_dev) +{ + hinic3_clean_root_ctxt(nic_dev->hwdev); +} diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/n= et/ethernet/huawei/hinic3/hinic3_nic_io.h index c103095c37ef..12eefabcf1db 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h @@ -139,4 +139,7 @@ void hinic3_init_qps(struct hinic3_nic_dev *nic_dev, void hinic3_uninit_qps(struct hinic3_nic_dev *nic_dev, struct hinic3_dyna_qp_params *qp_params); =20 +int hinic3_init_qp_ctxts(struct hinic3_nic_dev *nic_dev); +void hinic3_free_qp_ctxts(struct hinic3_nic_dev *nic_dev); + #endif --=20 2.43.0