mailweb.openeuler.org
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
2025
January
2024
December
November
October
September
August
July
June
May
April
March
February
January
2023
December
November
October
September
August
July
June
May
April
March
February
January
2022
December
November
October
September
August
July
June
May
April
March
February
January
2021
December
November
October
September
August
July
June
May
April
March
February
January
2020
December
November
October
September
August
July
June
May
April
March
February
January
2019
December
List overview
Download
Kernel
January 2025
----- 2025 -----
January 2025
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
kernel@openeuler.org
63 participants
481 discussions
Start a n
N
ew thread
[PATCH openEuler-22.03-LTS-SP1] RDMA/hns: Fix cpu stuck caused by printings during reset
by Tengda Wu
02 Jan '25
02 Jan '25
From: wenglianfa <wenglianfa(a)huawei.com> mainline inclusion from mainline-v6.13-rc1 commit 323275ac2ff15b2b7b3eac391ae5d8c5a3c3a999 category: bugfix bugzilla:
https://gitee.com/src-openeuler/kernel/issues/IBEGGK
CVE: CVE-2024-56722 Reference:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
-------------------------------- During reset, cmd to destroy resources such as qp, cq, and mr may fail, and error logs will be printed. When a large number of resources are destroyed, there will be lots of printings, and it may lead to a cpu stuck. Delete some unnecessary printings and replace other printing functions in these paths with the ratelimited version. Fixes: 9a4435375cd1 ("IB/hns: Add driver files for hns RoCE driver") Fixes: c7bcb13442e1 ("RDMA/hns: Add SRQ support for hip08 kernel mode") Fixes: 70f92521584f ("RDMA/hns: Use the reserved loopback QPs to free MR before destroying MPT") Fixes: 926a01dc000d ("RDMA/hns: Add QP operations support for hip08 SoC") Signed-off-by: wenglianfa <wenglianfa(a)huawei.com> Signed-off-by: Junxian Huang <huangjunxian6(a)hisilicon.com> Link:
https://patch.msgid.link/20241024124000.2931869-6-huangjunxian6@hisilicon.c…
Signed-off-by: Leon Romanovsky <leon(a)kernel.org> Conflicts: drivers/infiniband/hw/hns/hns_roce_hw_v2.c [This is due to we did not backport the cleanup patch b9989ab3f61e ("RDMA/hns: Remove unnecessary QP type checks")] Signed-off-by: Tengda Wu <wutengda2(a)huawei.com> --- drivers/infiniband/hw/hns/hns_roce_cq.c | 4 +- drivers/infiniband/hw/hns/hns_roce_hem.c | 4 +- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 74 +++++++++++----------- drivers/infiniband/hw/hns/hns_roce_mr.c | 4 +- drivers/infiniband/hw/hns/hns_roce_srq.c | 4 +- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/drivers/infiniband/hw/hns/hns_roce_cq.c b/drivers/infiniband/hw/hns/hns_roce_cq.c index 01a18fbc5525..2045bd3db831 100644 --- a/drivers/infiniband/hw/hns/hns_roce_cq.c +++ b/drivers/infiniband/hw/hns/hns_roce_cq.c @@ -180,8 +180,8 @@ static void free_cqc(struct hns_roce_dev *hr_dev, struct hns_roce_cq *hr_cq) ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_CQC, hr_cq->cqn); if (ret) - dev_err(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", ret, - hr_cq->cqn); + dev_err_ratelimited(dev, "DESTROY_CQ failed (%d) for CQN %06lx\n", + ret, hr_cq->cqn); xa_erase_irq(&cq_table->array, hr_cq->cqn); diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c index f21358515bf9..9a24a3a68e8e 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hem.c +++ b/drivers/infiniband/hw/hns/hns_roce_hem.c @@ -713,8 +713,8 @@ void hns_roce_table_put(struct hns_roce_dev *hr_dev, ret = hr_dev->hw->clear_hem(hr_dev, table, obj, HEM_HOP_STEP_DIRECT); if (ret) - dev_warn(dev, "failed to clear HEM base address, ret = %d.\n", - ret); + dev_warn_ratelimited(dev, "failed to clear HEM base address, ret = %d.\n", + ret); hns_roce_free_hem(hr_dev, table->hem[i]); table->hem[i] = NULL; diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index fa958ea9c569..21ff5ccde4ae 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -451,19 +451,21 @@ static int check_send_valid(struct hns_roce_dev *hr_dev, } else if (unlikely(hr_qp->state == IB_QPS_RESET || hr_qp->state == IB_QPS_INIT || hr_qp->state == IB_QPS_RTR)) { - ibdev_err(ibdev, "failed to post WQE, QP state %u!\n", - hr_qp->state); + ibdev_err_ratelimited(ibdev, + "failed to post WQE, QP state %u!\n", + hr_qp->state); return -EINVAL; } else if (unlikely(hr_dev->state >= HNS_ROCE_DEVICE_STATE_RST_DOWN)) { - ibdev_err(ibdev, "failed to post WQE, dev state %d!\n", - hr_dev->state); + ibdev_err_ratelimited(ibdev, + "failed to post WQE, dev state %d!\n", + hr_dev->state); return -EIO; } if (check_dca_attach_enable(hr_qp)) { ret = dca_attach_qp_buf(hr_dev, hr_qp); if (unlikely(ret)) { - ibdev_err(&hr_dev->ib_dev, + ibdev_err_ratelimited(&hr_dev->ib_dev, "failed to attach DCA for QP-%ld send!\n", hr_qp->qpn); return ret; @@ -3027,8 +3029,8 @@ static int free_mr_modify_rsv_qp(struct hns_roce_dev *hr_dev, ret = hr_dev->hw->modify_qp(&hr_qp->ibqp, attr, mask, IB_QPS_INIT, IB_QPS_INIT, NULL); if (ret) { - ibdev_err(ibdev, "failed to modify qp to init, ret = %d.\n", - ret); + ibdev_err_ratelimited(ibdev, "failed to modify qp to init, ret = %d.\n", + ret); return ret; } @@ -3716,8 +3718,8 @@ static int free_mr_post_send_lp_wqe(struct hns_roce_qp *hr_qp) ret = hns_roce_v2_post_send(&hr_qp->ibqp, send_wr, &bad_wr); if (ret) { - ibdev_err(ibdev, "failed to post wqe for free mr, ret = %d.\n", - ret); + ibdev_err_ratelimited(ibdev, "failed to post wqe for free mr, ret = %d.\n", + ret); return ret; } @@ -3756,9 +3758,9 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev) ret = free_mr_post_send_lp_wqe(hr_qp); if (ret) { - ibdev_err(ibdev, - "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n", - hr_qp->qpn, ret); + ibdev_err_ratelimited(ibdev, + "failed to send wqe (qp:0x%lx) for free mr, ret = %d.\n", + hr_qp->qpn, ret); break; } @@ -3769,16 +3771,16 @@ static void free_mr_send_cmd_to_hw(struct hns_roce_dev *hr_dev) while (cqe_cnt) { npolled = hns_roce_v2_poll_cq(&free_mr->rsv_cq->ib_cq, cqe_cnt, wc); if (npolled < 0) { - ibdev_err(ibdev, - "failed to poll cqe for free mr, remain %d cqe.\n", - cqe_cnt); + ibdev_err_ratelimited(ibdev, + "failed to poll cqe for free mr, remain %d cqe.\n", + cqe_cnt); goto out; } if (time_after(jiffies, end)) { - ibdev_err(ibdev, - "failed to poll cqe for free mr and timeout, remain %d cqe.\n", - cqe_cnt); + ibdev_err_ratelimited(ibdev, + "failed to poll cqe for free mr and timeout, remain %d cqe.\n", + cqe_cnt); goto out; } cqe_cnt -= npolled; @@ -5387,10 +5389,8 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp, struct hns_roce_dev *hr_dev = to_hr_dev(ibqp->device); int ret = 0; - if (!check_qp_state(cur_state, new_state)) { - ibdev_err(&hr_dev->ib_dev, "Illegal state for QP!\n"); + if (!check_qp_state(cur_state, new_state)) return -EINVAL; - } if (cur_state == IB_QPS_RESET && new_state == IB_QPS_INIT) { memset(qpc_mask, 0, hr_dev->caps.qpc_sz); @@ -5652,7 +5652,7 @@ static int hns_roce_v2_modify_qp(struct ib_qp *ibqp, /* SW pass context to HW */ ret = hns_roce_v2_qp_modify(hr_dev, context, qpc_mask, hr_qp); if (ret) { - ibdev_err(ibdev, "failed to modify QP, ret = %d.\n", ret); + ibdev_err_ratelimited(ibdev, "failed to modify QP, ret = %d.\n", ret); goto out; } @@ -5777,7 +5777,9 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, ret = hns_roce_v2_query_qpc(hr_dev, hr_qp->qpn, &context); if (ret) { - ibdev_err(ibdev, "failed to query QPC, ret = %d.\n", ret); + ibdev_err_ratelimited(ibdev, + "failed to query QPC, ret = %d.\n", + ret); ret = -EINVAL; goto out; } @@ -5785,7 +5787,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, state = hr_reg_read(&context, QPC_QP_ST); tmp_qp_state = to_ib_qp_st((enum hns_roce_v2_qp_state)state); if (tmp_qp_state == -1) { - ibdev_err(ibdev, "Illegal ib_qp_state\n"); + ibdev_err_ratelimited(ibdev, "Illegal ib_qp_state\n"); ret = -EINVAL; goto out; } @@ -5911,9 +5913,9 @@ int hns_roce_v2_destroy_qp_common(struct hns_roce_dev *hr_dev, ret = hns_roce_v2_modify_qp(&hr_qp->ibqp, NULL, 0, hr_qp->state, IB_QPS_RESET, udata); if (ret) - ibdev_err(ibdev, - "failed to modify QP to RST, ret = %d.\n", - ret); + ibdev_err_ratelimited(ibdev, + "failed to modify QP to RST, ret = %d.\n", + ret); } send_cq = hr_qp->ibqp.send_cq ? to_hr_cq(hr_qp->ibqp.send_cq) : NULL; @@ -5949,9 +5951,9 @@ int hns_roce_v2_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) ret = hns_roce_v2_destroy_qp_common(hr_dev, hr_qp, udata); if (ret) - ibdev_err(&hr_dev->ib_dev, - "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n", - hr_qp->qpn, ret); + ibdev_err_ratelimited(&hr_dev->ib_dev, + "failed to destroy QP, QPN = 0x%06lx, ret = %d.\n", + hr_qp->qpn, ret); hns_roce_qp_destroy(hr_dev, hr_qp, udata); @@ -6224,9 +6226,9 @@ static int hns_roce_v2_modify_cq(struct ib_cq *cq, u16 cq_count, u16 cq_period) HNS_ROCE_CMD_MODIFY_CQC, hr_cq->cqn); hns_roce_free_cmd_mailbox(hr_dev, mailbox); if (ret) - ibdev_err(&hr_dev->ib_dev, - "failed to process cmd when modifying CQ, ret = %d.\n", - ret); + ibdev_err_ratelimited(&hr_dev->ib_dev, + "failed to process cmd when modifying CQ, ret = %d.\n", + ret); return ret; } @@ -6246,9 +6248,9 @@ static int hns_roce_v2_query_cqc(struct hns_roce_dev *hr_dev, u32 cqn, ret = hns_roce_cmd_mbox(hr_dev, 0, mailbox->dma, HNS_ROCE_CMD_QUERY_CQC, cqn); if (ret) { - ibdev_err(&hr_dev->ib_dev, - "failed to process cmd when querying CQ, ret = %d.\n", - ret); + ibdev_err_ratelimited(&hr_dev->ib_dev, + "failed to process cmd when querying CQ, ret = %d.\n", + ret); goto err_mailbox; } diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index 5c11bb22facc..09ef095524da 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -136,8 +136,8 @@ static void hns_roce_mr_free(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr key_to_hw_index(mr->key) & (hr_dev->caps.num_mtpts - 1)); if (ret) - ibdev_warn(ibdev, "failed to destroy mpt, ret = %d.\n", - ret); + ibdev_warn_ratelimited(ibdev, "failed to destroy mpt, ret = %d.\n", + ret); } free_mr_pbl(hr_dev, mr); diff --git a/drivers/infiniband/hw/hns/hns_roce_srq.c b/drivers/infiniband/hw/hns/hns_roce_srq.c index a3999fc69719..b004df101e9d 100644 --- a/drivers/infiniband/hw/hns/hns_roce_srq.c +++ b/drivers/infiniband/hw/hns/hns_roce_srq.c @@ -150,8 +150,8 @@ static void free_srqc(struct hns_roce_dev *hr_dev, struct hns_roce_srq *srq) ret = hns_roce_destroy_hw_ctx(hr_dev, HNS_ROCE_CMD_DESTROY_SRQ, srq->srqn); if (ret) - dev_err(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n", - ret, srq->srqn); + dev_err_ratelimited(hr_dev->dev, "DESTROY_SRQ failed (%d) for SRQN %06lx\n", + ret, srq->srqn); xa_erase_irq(&srq_table->xa, srq->srqn); -- 2.34.1
2
2
0
0
[PATCH openEuler-22.03-LTS-SP1 0/2] CVE-2024-45009
by Wang Liang
02 Jan '25
02 Jan '25
Matthieu Baerts (NGI0) (2): mptcp: pm: only decrement add_addr_accepted for MPJ req mptcp: pm: fix UaF read in mptcp_pm_nl_rm_addr_or_subflow net/mptcp/pm_netlink.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) -- 2.34.1
2
3
0
0
[PATCH OLK-5.10] apparmor: test: Fix memory leak for aa_unpack_strdup()
by Gu Bowen
02 Jan '25
02 Jan '25
From: Jinjie Ruan <ruanjinjie(a)huawei.com> stable inclusion from stable-v5.10.231 commit f856246ff6da25c4f8fdd73a9c875e878b085e9f category: bugfix bugzilla:
https://gitee.com/src-openeuler/kernel/issues/IBEGGQ
CVE: CVE-2024-56741 Reference:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
-------------------------------- commit 7290f59231910ccba427d441a6e8b8c6f6112448 upstream. The string allocated by kmemdup() in aa_unpack_strdup() is not freed and cause following memory leaks, free them to fix it. unreferenced object 0xffffff80c6af8a50 (size 8): comm "kunit_try_catch", pid 225, jiffies 4294894407 hex dump (first 8 bytes): 74 65 73 74 69 6e 67 00 testing. backtrace (crc 5eab668b): [<0000000001e3714d>] kmemleak_alloc+0x34/0x40 [<000000006e6c7776>] __kmalloc_node_track_caller_noprof+0x300/0x3e0 [<000000006870467c>] kmemdup_noprof+0x34/0x60 [<000000001176bb03>] aa_unpack_strdup+0xd0/0x18c [<000000008ecde918>] policy_unpack_test_unpack_strdup_with_null_name+0xf8/0x3ec [<0000000032ef8f77>] kunit_try_run_case+0x13c/0x3ac [<00000000f3edea23>] kunit_generic_run_threadfn_adapter+0x80/0xec [<00000000adf936cf>] kthread+0x2e8/0x374 [<0000000041bb1628>] ret_from_fork+0x10/0x20 unreferenced object 0xffffff80c2a29090 (size 8): comm "kunit_try_catch", pid 227, jiffies 4294894409 hex dump (first 8 bytes): 74 65 73 74 69 6e 67 00 testing. backtrace (crc 5eab668b): [<0000000001e3714d>] kmemleak_alloc+0x34/0x40 [<000000006e6c7776>] __kmalloc_node_track_caller_noprof+0x300/0x3e0 [<000000006870467c>] kmemdup_noprof+0x34/0x60 [<000000001176bb03>] aa_unpack_strdup+0xd0/0x18c [<0000000046a45c1a>] policy_unpack_test_unpack_strdup_with_name+0xd0/0x3c4 [<0000000032ef8f77>] kunit_try_run_case+0x13c/0x3ac [<00000000f3edea23>] kunit_generic_run_threadfn_adapter+0x80/0xec [<00000000adf936cf>] kthread+0x2e8/0x374 [<0000000041bb1628>] ret_from_fork+0x10/0x20 Cc: stable(a)vger.kernel.org Fixes: 4d944bcd4e73 ("apparmor: add AppArmor KUnit tests for policy unpack") Signed-off-by: Jinjie Ruan <ruanjinjie(a)huawei.com> Signed-off-by: John Johansen <john.johansen(a)canonical.com> Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org> Signed-off-by: Gu Bowen <gubowen5(a)huawei.com> --- security/apparmor/policy_unpack_test.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/security/apparmor/policy_unpack_test.c b/security/apparmor/policy_unpack_test.c index 4951d9bef579..128baa08a989 100644 --- a/security/apparmor/policy_unpack_test.c +++ b/security/apparmor/policy_unpack_test.c @@ -283,6 +283,8 @@ static void policy_unpack_test_unpack_strdup_with_null_name(struct kunit *test) ((uintptr_t)puf->e->start <= (uintptr_t)string) && ((uintptr_t)string <= (uintptr_t)puf->e->end)); KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA); + + kfree(string); } static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test) @@ -298,6 +300,8 @@ static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test) ((uintptr_t)puf->e->start <= (uintptr_t)string) && ((uintptr_t)string <= (uintptr_t)puf->e->end)); KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA); + + kfree(string); } static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test) @@ -315,6 +319,8 @@ static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test) KUNIT_EXPECT_EQ(test, size, 0); KUNIT_EXPECT_PTR_EQ(test, string, (char *)NULL); KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start); + + kfree(string); } static void policy_unpack_test_unpack_nameX_with_null_name(struct kunit *test) -- 2.25.1
2
1
0
0
[PATCH OLK-6.6] Add Huawei Intelligent Network Card Driver:hibifur
by Zhang Zhenghao
02 Jan '25
02 Jan '25
driver inclusion category: feature bugzilla:
https://gitee.com/openeuler/kernel/issues/IBCO6Q
CVE: NA --------------------------------- The BIFUR drive supports the following features: Supports Huawei's self-developed SP670 series network cards; Supports users to allocate specific PF to derive VF for single function stream bifurcation; Signed-off-by: Zhang Zhenghao <zhangzhenghao9(a)huawei.com> --- MAINTAINERS | 7 + arch/arm64/configs/openeuler_defconfig | 1 + arch/x86/configs/openeuler_defconfig | 1 + drivers/net/ethernet/huawei/Kconfig | 1 + drivers/net/ethernet/huawei/Makefile | 1 + drivers/net/ethernet/huawei/hibifur/Kconfig | 13 + drivers/net/ethernet/huawei/hibifur/Makefile | 26 + .../ethernet/huawei/hibifur/bifur_common.h | 57 ++ .../net/ethernet/huawei/hibifur/bifur_event.c | 381 +++++++++ .../net/ethernet/huawei/hibifur/bifur_event.h | 26 + .../net/ethernet/huawei/hibifur/bifur_main.c | 791 ++++++++++++++++++ .../net/ethernet/huawei/hibifur/bifur_main.h | 57 ++ .../net/ethernet/huawei/hibifur/bifur_pfile.c | 545 ++++++++++++ .../net/ethernet/huawei/hibifur/bifur_pfile.h | 75 ++ .../ethernet/huawei/hibifur/bifur_vf_mgr.c | 263 ++++++ .../ethernet/huawei/hibifur/bifur_vf_mgr.h | 58 ++ .../huawei/hibifur/include/hinic3_hmm.h | 87 ++ .../huawei/hibifur/include/hinic3_rdma.h | 202 +++++ .../huawei/hibifur/include/nic/nic_mpu_cmd.h | 183 ++++ .../huawei/hibifur/include/nic/nic_npu_cmd.h | 29 + .../hibifur/include/nic/nic_npu_cmd_defs.h | 133 +++ .../ethernet/huawei/hibifur/include/node_id.h | 52 ++ .../net/ethernet/huawei/hinic3/hinic3_crm.h | 14 + .../net/ethernet/huawei/hinic3/hinic3_main.c | 18 +- .../huawei/hinic3/hinic3_mgmt_interface.h | 9 + .../net/ethernet/huawei/hinic3/hinic3_mt.h | 7 +- .../huawei/hinic3/hw/hinic3_dev_mgmt.c | 3 + .../huawei/hinic3/hw/hinic3_dev_mgmt.h | 2 + .../ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c | 14 + .../ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h | 2 + .../ethernet/huawei/hinic3/hw/hinic3_lld.c | 2 +- .../huawei/hinic3/hw/hinic3_nictool.c | 22 +- .../include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h | 2 + 33 files changed, 3065 insertions(+), 19 deletions(-) create mode 100644 drivers/net/ethernet/huawei/hibifur/Kconfig create mode 100644 drivers/net/ethernet/huawei/hibifur/Makefile create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_common.h create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_event.c create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_event.h create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_main.c create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_main.h create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_pfile.c create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_pfile.h create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.c create mode 100644 drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.h create mode 100644 drivers/net/ethernet/huawei/hibifur/include/hinic3_hmm.h create mode 100644 drivers/net/ethernet/huawei/hibifur/include/hinic3_rdma.h create mode 100644 drivers/net/ethernet/huawei/hibifur/include/nic/nic_mpu_cmd.h create mode 100644 drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd.h create mode 100644 drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd_defs.h create mode 100644 drivers/net/ethernet/huawei/hibifur/include/node_id.h diff --git a/MAINTAINERS b/MAINTAINERS index 219b3d11e..b22778025 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -9690,6 +9690,13 @@ F: drivers/net/ethernet/huawei/hinic3/cqm/ F: drivers/net/ethernet/huawei/hinic3/hw/ F: drivers/net/ethernet/huawei/hinic3/include/ +HUAWEI BIFUR DRIVER +M: Xiaoping zheng <zhengxiaoping5(a)huawei.com> +L: netdev(a)vger.kernel.org +S: Supported +F: drivers/net/ethernet/huawei/hibifur/ +F: drivers/net/ethernet/huawei/hibifur/include/ + HUAWEI PVRDMA DRIVER M: Chengbo Gu <guchengbo(a)huawei.com> R: Xiaoping zheng <zhengxiaoping5(a)huawei.com> diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index fc6053a50..d4a573c8d 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -2940,6 +2940,7 @@ CONFIG_NET_VENDOR_HUAWEI=y CONFIG_HINIC=m CONFIG_HINIC3=m CONFIG_BMA=m +CONFIG_HIBIFUR=m # CONFIG_NET_VENDOR_I825XX is not set CONFIG_NET_VENDOR_INTEL=y # CONFIG_E100 is not set diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index adfaef0cb..bcb212458 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -2933,6 +2933,7 @@ CONFIG_NET_VENDOR_HUAWEI=y CONFIG_HINIC=m CONFIG_HINIC3=m CONFIG_BMA=m +CONFIG_HIBIFUR=m # CONFIG_NET_VENDOR_I825XX is not set CONFIG_NET_VENDOR_INTEL=y # CONFIG_E100 is not set diff --git a/drivers/net/ethernet/huawei/Kconfig b/drivers/net/ethernet/huawei/Kconfig index 0df9544dc..fc22693e4 100644 --- a/drivers/net/ethernet/huawei/Kconfig +++ b/drivers/net/ethernet/huawei/Kconfig @@ -18,5 +18,6 @@ if NET_VENDOR_HUAWEI source "drivers/net/ethernet/huawei/hinic/Kconfig" source "drivers/net/ethernet/huawei/hinic3/Kconfig" source "drivers/net/ethernet/huawei/bma/Kconfig" +source "drivers/net/ethernet/huawei/hibifur/Kconfig" endif # NET_VENDOR_HUAWEI diff --git a/drivers/net/ethernet/huawei/Makefile b/drivers/net/ethernet/huawei/Makefile index d88e8fd77..97ee28af8 100644 --- a/drivers/net/ethernet/huawei/Makefile +++ b/drivers/net/ethernet/huawei/Makefile @@ -6,3 +6,4 @@ obj-$(CONFIG_HINIC) += hinic/ obj-$(CONFIG_HINIC3) += hinic3/ obj-$(CONFIG_BMA) += bma/ +obj-$(CONFIG_HIBIFUR) += hibifur/ diff --git a/drivers/net/ethernet/huawei/hibifur/Kconfig b/drivers/net/ethernet/huawei/hibifur/Kconfig new file mode 100644 index 000000000..99d7ecec5 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Huawei driver configuration +# + +config HIBIFUR + tristate "Huawei Intelligent Network Interface Card Bifur Driver" + depends on HINIC3 && PCI_MSI && NUMA && PCI_IOV && DCB && (X86 || ARM64) + help + This driver supports HIBIFUR PCIE Ethernet cards. + To compile this driver as part of the kernel, choose Y here. + If unsure, choose N. + The default is N. diff --git a/drivers/net/ethernet/huawei/hibifur/Makefile b/drivers/net/ethernet/huawei/hibifur/Makefile new file mode 100644 index 000000000..a4fd682e1 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/Makefile @@ -0,0 +1,26 @@ +EXPORT_SYMBOL := true + +KBUILD_EXTRA_SYMBOLS += $(srctree)/drivers/net/ethernet/huawei/hinic3/Module.symvers + +SYS_TIME=$(shell date +%Y-%m-%d_%H:%M:%S) +ccflags-y += -D __TIME_STR__=\"$(SYS_TIME)\" + +ccflags-y += -I$(srctree)/include/linux +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/public +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/cqm +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/bond +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/mpu +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/hw +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/bond +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hibifur/include +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hibifur/include/nic +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3 +ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include + +obj-$(CONFIG_HIBIFUR) += hibifur3.o + +hibifur3-objs := bifur_main.o \ + bifur_vf_mgr.o \ + bifur_pfile.o \ + bifur_event.o diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_common.h b/drivers/net/ethernet/huawei/hibifur/bifur_common.h new file mode 100644 index 000000000..145db9cd3 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_common.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ + +#ifndef BIFUR_COMMON_H__ +#define BIFUR_COMMON_H__ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/etherdevice.h> +#include <linux/proc_fs.h> +#include <linux/uaccess.h> +#include <linux/types.h> +#include <linux/cdev.h> +#include <linux/fs.h> +#include <linux/mm_types.h> +#include <linux/kdev_t.h> +#include <linux/netdevice.h> +#include <linux/notifier.h> +#include <net/net_namespace.h> +#include "asm-generic/int-ll64.h" +#include "linux/pci.h" + +#include "ossl_knl_linux.h" +#include "hinic3_nic_dev.h" +#include "ossl_knl.h" +#include "hinic3_nic_cfg.h" +#include "hinic3_srv_nic.h" + +#define BIFUR_VF_NUM 40 +#define BIFUR_FILE_PATH_SIZE 50 +#define BIFUR_RESOURCE_PF_SSID 0x5a1 + +#define BIFUR_ENABLED 1 +#define BIFUR_DISABLED 0 + +#define PCI_DBDF(dom, bus, dev, func) \ + ((((u32)(dom) << 16) | ((u32)(bus) << 8) | ((u32)(dev) << 3) | ((u32)(func) & 0x7))) +#define PCI_DBDF_DOM(dbdf) (((dbdf) >> 16) & 0xFFFF) +#define PCI_DBDF_BUS(dbdf) (((dbdf) >> 8) & 0xFF) +#define PCI_DBDF_DEVID(dbdf) (((dbdf) >> 3) & 0x1F) +#define PCI_DBDF_FUNCTION(dbdf) ((dbdf) & 0x7) +#define PCI_DBDF_DEVFN(dbdf) ((dbdf) & 0xFF) + +struct bifur_cdev { + struct cdev cdev; + dev_t cdev_id; + struct proc_dir_entry *proc_dir; +}; + +#define BIFUR_DEV_INFO(lld_dev, fmt, arg...) dev_info(&((lld_dev)->pdev->dev), "[BIFUR]" fmt, ##arg) + +#define BIFUR_DEV_WARN(lld_dev, fmt, arg...) dev_warn(&((lld_dev)->pdev->dev), "[BIFUR]" fmt, ##arg) + +#define BIFUR_DEV_ERR(lld_dev, fmt, arg...) dev_err(&((lld_dev)->pdev->dev), "[BIFUR]" fmt, ##arg) +#endif diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_event.c b/drivers/net/ethernet/huawei/hibifur/bifur_event.c new file mode 100644 index 000000000..397ee107f --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_event.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ +#include <net/bonding.h> +#include "hinic3_srv_nic.h" +#include "hinic3_lld.h" +#include "hinic3_bond.h" +#include "hinic3_mt.h" +#include "nic_mpu_cmd.h" +#include "hinic3_hw.h" +#include "hinic3_mgmt_interface.h" + +#include "bifur_common.h" +#include "bifur_vf_mgr.h" +#include "bifur_main.h" +#include "bifur_event.h" + +static int bifur_set_vf_bond_enable(struct bifur_lld_dev *bifur_dev, u16 vf_id, u8 bond_bifur_en) +{ + int err; + struct hinic3_bond_mask_cmd bond_info = { 0 }; + u16 out_size = sizeof(struct hinic3_bond_mask_cmd); + + bond_info.msg_head.status = 1; + bond_info.func_id = vf_id; + bond_info.bond_en = bond_bifur_en; + + err = hinic3_msg_to_mgmt_sync(bifur_dev->lld_dev->hwdev, HINIC3_MOD_L2NIC, + HINIC3_NIC_CMD_SET_BOND_MASK, &bond_info, + sizeof(bond_info), &bond_info, + &out_size, 0, HINIC3_CHANNEL_DEFAULT); + if (bond_info.msg_head.status != 0 || err != 0 || out_size == 0) { + BIFUR_DEV_ERR(bifur_dev->lld_dev, + "Failed to set VF forward id config. err(%d), sts(%u), out_size(%u)\n", + err, bond_info.msg_head.status, out_size); + return -EIO; + } + return 0; +} + +void bifur_set_bond_enable(u8 bond_bifur_en) +{ + int i, err; + struct bifur_vf_info *vf_info = NULL; + struct bifur_vf_mgr *vf_mgr = NULL; + struct bifur_lld_dev *bifur_src_dev = bifur_get_resource_dev(); + + if (!bifur_src_dev) { + pr_err("Bifur source pf didn't inited.\n"); + return; + } + vf_mgr = bifur_src_dev->vf_mgr; + + mutex_lock(&vf_mgr->vf_mgr_mutex); + for (i = 0; i < vf_mgr->vf_sum; ++i) { + vf_info = &vf_mgr->vf_info[i]; + err = bifur_set_vf_bond_enable(bifur_src_dev, vf_info->glb_func_id, bond_bifur_en); + if (err != 0) { + BIFUR_DEV_WARN(bifur_src_dev->lld_dev, + "Failed to set VF(0x%x) bond enable(%u).\n", + vf_info->glb_func_id, bond_bifur_en); + } + } + + mutex_unlock(&vf_mgr->vf_mgr_mutex); + bifur_dev_put(bifur_src_dev); +} + +static void bifur_attach_bond_work(struct work_struct *_work) +{ + int ret; + u16 bond_id; + struct bifur_bond_work *work = container_of(_work, struct bifur_bond_work, work); + struct bifur_adapter *adp = bifur_get_adp(); + + if (!adp) { + pr_err("Bifur driver init failed.\n"); + kfree(work); + return; + } + + ret = hinic3_bond_attach(work->name, HINIC3_BOND_USER_OVS, &bond_id); + if (ret) { + pr_info("%s: hinic3 bond attach failed, ret(%d).\n", __func__, ret); + kfree(work); + return; + } + + bifur_dev_list_lock(); + adp->bond_id = bond_id; + adp->bond_bifur_enabled = BIFUR_ENABLED; + bifur_dev_list_unlock(); + + pr_info("bifur_attach: %s: bond_name(%s), bond_id(%u)\n", __func__, work->name, bond_id); + bifur_set_bond_enable(BIFUR_ENABLED); + + kfree(work); +} + +static void bifur_queue_bond_work(struct bifur_adapter *adp, struct net_device *upper_netdev) +{ + struct bifur_bond_work *work; + struct bonding *bond = netdev_priv(upper_netdev); + + if (!bond) { + pr_info("%s: (name:%s) has no bond dev.\n", __func__, upper_netdev->name); + return; + } + + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (!work) + return; + + (void)strscpy(work->name, upper_netdev->name, strlen(upper_netdev->name)); + INIT_WORK(&work->work, bifur_attach_bond_work); + (void)queue_work(adp->event_workq, &work->work); +} + +static void bifur_detach_nic_bond_work(struct work_struct *work) +{ + struct bifur_bond_work *detach_work = container_of(work, struct bifur_bond_work, work); + struct bifur_adapter *adp = bifur_get_adp(); + u16 bond_id; + + if (!adp) { + pr_err("Bifur driver init failed.\n"); + kfree(detach_work); + return; + } + + bifur_dev_list_lock(); + bond_id = adp->bond_id; + adp->bond_bifur_enabled = BIFUR_DISABLED; + bifur_dev_list_unlock(); + + hinic3_bond_detach(bond_id, HINIC3_BOND_USER_OVS); + bifur_set_bond_enable(BIFUR_DISABLED); + kfree(detach_work); +} + +static void bifur_queue_detach_bond_work(struct bifur_adapter *adp) +{ + struct bifur_bond_work *work; + + work = kzalloc(sizeof(*work), GFP_KERNEL); + if (!work) + return; + + INIT_WORK(&work->work, bifur_detach_nic_bond_work); + + (void)queue_work(adp->event_workq, &work->work); +} + +static bool bifur_can_do_bond(struct bonding *bond) +{ + bool ret = false; + int slave_cnt = 0; + struct slave *slave = NULL; + struct list_head *iter = NULL; + struct hinic3_lld_dev *lld_dev = NULL; + struct hinic3_lld_dev *ppf_dev = NULL; + + if (!bond) + return ret; + + rcu_read_lock(); + bond_for_each_slave_rcu(bond, slave, iter) { + lld_dev = hinic3_get_lld_dev_by_netdev(slave->dev); + if (!lld_dev) + goto out; + + if (!hinic3_support_bifur(lld_dev->hwdev, NULL)) + goto out; + + if (!ppf_dev) { + ppf_dev = hinic3_get_ppf_lld_dev(lld_dev); + if (!ppf_dev) + goto out; + } + + slave_cnt++; + pr_info("%s:can do bond? slave_cnt(%d), slave_name(%s)", __func__, + slave_cnt, slave->dev->name); + } + + ret = (slave_cnt == BIFUR_BOND_2_FUNC_NUM); +out: + rcu_read_unlock(); + return ret; +} + +static int bifur_bond_netdev_event(struct bifur_adapter *adp, + struct netdev_notifier_changeupper_info *info, + struct net_device *net_dev) +{ + struct bonding *bond = NULL; + struct net_device *upper_netdev = info->upper_dev; + + if (net_eq(dev_net(net_dev), &init_net) == 0) + return NOTIFY_DONE; + + if (!upper_netdev) + return NOTIFY_DONE; + + if (!netif_is_lag_master(upper_netdev)) + return NOTIFY_DONE; + + bond = netdev_priv(upper_netdev); + if (!bifur_can_do_bond(bond)) { + bifur_queue_detach_bond_work(adp); + pr_info("%s: (name:%s) has no bond dev.\n", __func__, upper_netdev->name); + return NOTIFY_DONE; + } + + bifur_queue_bond_work(adp, upper_netdev); + + return NOTIFY_DONE; +} + +int bifur_bond_init(void) +{ + int ret = 0; + struct net_device *upper_netdev; + struct bifur_adapter *adp = bifur_get_adp(); + + if (!adp) { + pr_err("Bifur driver init failed.\n"); + return -EINVAL; + } + + rtnl_lock(); + for_each_netdev(&init_net, upper_netdev) { + if (netif_is_bond_master(upper_netdev) && + bifur_can_do_bond(netdev_priv(upper_netdev))) { + bifur_queue_bond_work(adp, upper_netdev); + break; + } + } + rtnl_unlock(); + + pr_info("%s: bond init exit.\n", __func__); + return ret; +} + +void bifur_bond_exit(void) +{ + struct bifur_adapter *adp = bifur_get_adp(); + + if (!adp) { + pr_err("Bifur driver init failed.\n"); + return; + } + bifur_queue_detach_bond_work(adp); +} + +void bifur_notify_vf_link_status(struct hinic3_lld_dev *lld_dev, u8 port_id, u16 vf_id, + u8 link_status) +{ + struct mag_cmd_get_link_status link; + u16 out_size = sizeof(link); + int err; + + (void)memset(&link, 0, sizeof(link)); + link.status = link_status; + link.port_id = port_id; + + err = hinic3_mbox_to_vf_no_ack(lld_dev->hwdev, vf_id, HINIC3_MOD_HILINK, + MAG_CMD_GET_LINK_STATUS, &link, sizeof(link), + &link, &out_size, HINIC3_CHANNEL_NIC); + if (err == MBOX_ERRCODE_UNKNOWN_DES_FUNC) { + pr_err("Vf%d not initialized, disconnect it\n", HW_VF_ID_TO_OS(vf_id)); + return; + } + + if (err || !out_size || link.head.status) { + pr_err("Send link change event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n", + HW_VF_ID_TO_OS(vf_id), err, link.head.status, out_size); + } +} + +void bifur_notify_all_vfs_link_changed(struct hinic3_lld_dev *lld_dev, u32 dbdf, u8 link_status) +{ + struct bifur_lld_dev *bifur_src_dev = NULL; + struct bifur_vf_mgr *vf_mgr = NULL; + struct bifur_vf_info *vf_info = NULL; + u16 i; + u8 port_id; + + bifur_src_dev = bifur_get_resource_dev(); + if (!bifur_src_dev) + return; + + vf_mgr = bifur_src_dev->vf_mgr; + port_id = hinic3_physical_port_id(lld_dev->hwdev); + + mutex_lock(&vf_mgr->vf_mgr_mutex); + for (i = 0; i < vf_mgr->vf_sum; ++i) { + vf_info = &vf_mgr->vf_info[i]; + if (vf_info->pf_dbdf == dbdf && vf_info->in_use) + bifur_notify_vf_link_status(bifur_src_dev->lld_dev, port_id, + OS_VF_ID_TO_HW(i), link_status); + } + mutex_unlock(&vf_mgr->vf_mgr_mutex); + + bifur_dev_put(bifur_src_dev); +} + +void bifur_netdev_event(struct work_struct *work) +{ + struct bifur_lld_dev *bifur_dev = container_of(work, struct bifur_lld_dev, netdev_link); + + bifur_notify_all_vfs_link_changed(bifur_dev->lld_dev, bifur_dev->dbdf, + bifur_dev->link_status); + + bifur_dev_put(bifur_dev); +} + +static int bifur_net_link_event(struct bifur_adapter *adp, unsigned long event, + struct net_device *dev) +{ + u32 dbdf; + struct pci_dev *pcidev = NULL; + struct bifur_lld_dev *bifur_dev = NULL; + struct hinic3_nic_dev *nic_dev = NULL; + + nic_dev = netdev_priv(dev); + pcidev = nic_dev->pdev; + dbdf = PCI_DBDF(pci_domain_nr(pcidev->bus), pcidev->bus->number, + PCI_DBDF_DEVID(pcidev->devfn), PCI_DBDF_FUNCTION(pcidev->devfn)); + + bifur_dev = bifur_get_shared_dev_by_dbdf(dbdf); + if (!bifur_dev) + return NOTIFY_DONE; + + bifur_dev->link_status = (event == NETDEV_UP ? 1 : 0); + (void)queue_work(adp->event_workq, &bifur_dev->netdev_link); + return NOTIFY_OK; +} + +int bifur_net_event_callback(struct notifier_block *nb, unsigned long event, void *ptr) +{ + struct net_device *dev = netdev_notifier_info_to_dev(ptr); + struct bifur_adapter *adp = bifur_get_adp(); + + if (unlikely(!dev)) { + pr_err("bifur notify dev null\n"); + return NOTIFY_DONE; + } + + /* only self-developed NICs can be processed */ + if (!hinic3_get_lld_dev_by_netdev(dev)) + return NOTIFY_DONE; + + switch (event) { + case NETDEV_UP: + case NETDEV_DOWN: + return bifur_net_link_event(adp, event, dev); + case NETDEV_CHANGEUPPER: + return bifur_bond_netdev_event(adp, (struct netdev_notifier_changeupper_info *)ptr, + dev); + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block g_bifur_event_nb = { + .notifier_call = bifur_net_event_callback +}; + +int bifur_register_net_event(void) +{ + return register_netdevice_notifier(&g_bifur_event_nb); +} + +void bifur_unregister_net_event(void) +{ + (void)unregister_netdevice_notifier(&g_bifur_event_nb); +} diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_event.h b/drivers/net/ethernet/huawei/hibifur/bifur_event.h new file mode 100644 index 000000000..b9068a10f --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_event.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ + +#ifndef BIFUR_EVENT_H__ +#define BIFUR_EVENT_H__ +#include <linux/workqueue.h> +#include <linux/notifier.h> +#include <linux/if.h> + +#define BIFUR_BOND_2_FUNC_NUM 2 + +struct bifur_bond_work { + char name[IFNAMSIZ]; + struct work_struct work; +}; + +void bifur_set_bond_enable(u8 bond_bifur_en); +int bifur_bond_init(void); +void bifur_bond_exit(void); +int bifur_register_net_event(void); +void bifur_unregister_net_event(void); +void bifur_netdev_event(struct work_struct *work); + +#endif diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_main.c b/drivers/net/ethernet/huawei/hibifur/bifur_main.c new file mode 100644 index 000000000..287ef2268 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_main.c @@ -0,0 +1,791 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ + +/* sdk include */ +#include "hinic3_crm.h" +#include "hinic3_hw.h" +#include "hinic3_cqm.h" +#include "hinic3_lld.h" +#include "hinic3_mt.h" + +#include "bifur_common.h" +#include "bifur_vf_mgr.h" +#include "bifur_pfile.h" +#include "bifur_event.h" +#include "bifur_main.h" +#define BIFUR_DRV_DESC "BIFUR Offload Driver" +#define BIFUR_DRV_VERSION "" + +#define BIFUR_WAIT_TIMES 1000 +#define BIFUR_REMOVE_TIMESTEP 10 +#define BIFUR_KWRITE_BUF_SIZE 20 +#define BIFUR_DPDK_KDRIVER_TYPE 3 + +#define BIFUR_SET_ENABLE 0xc0 +#define BIFUR_GET_ENABLE 0xc1 + +static char *g_bifur_dpdk_kdriver = "vfio-pci"; +module_param(g_bifur_dpdk_kdriver, charp, 0644); +MODULE_PARM_DESC(g_bifur_dpdk_kdriver, + "for dpdk kernel driver module (default:\"igb_uio\", options:\"vfio-pci\", \"uio_pci_generic\")"); +static const char *g_bifur_dpdk_kdriver_all[BIFUR_DPDK_KDRIVER_TYPE] = { + "igb_uio", + "vfio-pci", + "uio_pci_generic" +}; + +/* bifur global manager struct */ +static struct bifur_adapter *g_bifur_adapter; + +static void bifur_destroy_dev(struct bifur_lld_dev *bifur_dev); +static void wait_bifur_dev_unused(struct bifur_lld_dev *bifur_dev); + +struct bifur_adapter *bifur_get_adp(void) +{ + return g_bifur_adapter; +} + +void bifur_dev_hold(struct bifur_lld_dev *bifur_dev) +{ + atomic_inc(&bifur_dev->bifur_dev.bifur_dev_ref); +} + +void bifur_dev_put(struct bifur_lld_dev *bifur_dev) +{ + atomic_dec(&bifur_dev->bifur_dev.bifur_dev_ref); +} + +void bifur_dev_list_lock(void) +{ + mutex_lock(&g_bifur_adapter->bifur_dev_mutex); +} + +void bifur_dev_list_unlock(void) +{ + mutex_unlock(&g_bifur_adapter->bifur_dev_mutex); +} + +static int bifur_alloc_adapter(void) +{ + /* alloc driver global adapter struct */ + if (!g_bifur_adapter) { + g_bifur_adapter = kzalloc(sizeof(*g_bifur_adapter), GFP_KERNEL); + if (!g_bifur_adapter) + return -ENOMEM; + } + + /* init global adapter */ + INIT_LIST_HEAD(&g_bifur_adapter->lld_dev_head); + mutex_init(&g_bifur_adapter->bifur_dev_mutex); + + g_bifur_adapter->event_workq = create_singlethread_workqueue("bifur_eventq"); + if (!g_bifur_adapter->event_workq) { + kfree(g_bifur_adapter); + g_bifur_adapter = NULL; + pr_err("Create bifur event_workq fail"); + return -ENOMEM; + } + + pr_info("Alloc bifur adapter success\n"); + return 0; +} + +static void bifur_free_adapter(void) +{ + destroy_workqueue(g_bifur_adapter->event_workq); + + kfree(g_bifur_adapter); + g_bifur_adapter = NULL; + pr_info("Free adapter success\n"); +} + +static bool bifur_check_dpdk_kdriver(void) +{ + bool is_valid_driver = false; + int i; + + for (i = 0; i < BIFUR_DPDK_KDRIVER_TYPE; ++i) { + if (!strcmp(g_bifur_dpdk_kdriver, g_bifur_dpdk_kdriver_all[i])) + is_valid_driver = true; + } + + return is_valid_driver; +} + +static int bifur_open_and_write_file(const char *file_path, const char *buf, int open_flags, + umode_t open_mode) +{ + struct file *fp = NULL; + loff_t f_pos = 0; + int err = 0; + + fp = filp_open(file_path, open_flags, open_mode); + if (IS_ERR(fp)) { + pr_err("Open %s failed, err %ld\n", file_path, PTR_ERR(fp)); + return -ENOENT; + } + + err = kernel_write(fp, buf, strlen(buf), &f_pos); + if (err < 0) { + pr_err("Write %s to file %s failed, err %d\n", buf, file_path, err); + (void)filp_close(fp, NULL); + return err; + } + + (void)filp_close(fp, NULL); + + return 0; +} + +static int bifur_enable_disable_vfs(struct bifur_lld_dev *bifur_dev, u16 num_vfs) +{ + int err = 0; + char file_path[BIFUR_FILE_PATH_SIZE] = {}; + char buf[BIFUR_KWRITE_BUF_SIZE] = {}; + struct pci_dev *pdev = bifur_dev->lld_dev->pdev; + + /* write vf num to /sys/bus/pci/devices/%s/sriov_numvfs */ + err = snprintf(file_path, BIFUR_FILE_PATH_SIZE, + "/sys/bus/pci/devices/%s/sriov_numvfs", pci_name(pdev)); + if (err == -1) { + pr_err("Snprintf bifur pci dev sriov_numvfs file path, err %d!\n", err); + return err; + } + + err = snprintf(buf, BIFUR_KWRITE_BUF_SIZE, "%u", num_vfs); + if (err == -1) { + pr_err("Snprintf bifur numvfs str, err %d!\n", err); + return err; + } + + err = bifur_open_and_write_file(file_path, buf, O_WRONLY | O_TRUNC, 0); + if (err != 0) { + pr_info("Enable vf of pf failed, dbdf:0x%s, sriov_nums:%u\n", + pci_name(pdev), num_vfs); + return err; + } + + pr_info("Enable vf of pf success, dbdf:0x%s, sriov_nums:%u\n", pci_name(pdev), num_vfs); + + return 0; +} + +int bifur_enable_disable_vf_all(bool enable) +{ + int err = 0; + int num_vfs = enable ? BIFUR_VF_NUM : 0; + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *tmp_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + struct list_head *head = &adp->lld_dev_head; + + list_for_each_entry_safe(bifur_dev, tmp_dev, head, list) { + if (bifur_dev->pf_type != BIFUR_RESOURCE_PF) + continue; + + bifur_dev_hold(bifur_dev); + err = bifur_enable_disable_vfs(bifur_dev, num_vfs); + bifur_dev_put(bifur_dev); + if (err) + return err; + } + + return 0; +} + +static int bifur_one_unbind_driver(u32 dbdf, const char *driver) +{ + int err = 0; + char file_path[BIFUR_FILE_PATH_SIZE] = {}; + char buf[BIFUR_KWRITE_BUF_SIZE] = {}; + + /* write pci dbdf to /sys/bus/pci/drivers/%s/unbind */ + err = snprintf(file_path, BIFUR_FILE_PATH_SIZE, + "/sys/bus/pci/drivers/%s/unbind", driver); + if (err == -1) { + pr_err("Snprintf bifur driver unbind file path, err %d!\n", err); + return err; + } + + err = snprintf(buf, BIFUR_KWRITE_BUF_SIZE, "%.4x:%.2x:%.2x.%x", + PCI_DBDF_DOM(dbdf), PCI_DBDF_BUS(dbdf), + PCI_DBDF_DEVID(dbdf), PCI_DBDF_FUNCTION(dbdf)); + if (err == -1) { + pr_err("Snprintf bifur pci dev dbdf str, err %d!\n", err); + return err; + } + + err = bifur_open_and_write_file(file_path, buf, O_WRONLY | O_APPEND, 0); + if (err != 0) { + pr_info("Unbind vf from driver %s failed\n", driver); + return err; + } + + pr_info("Unbind vf from driver %s success\n", driver); + + return 0; +} + +static int bifur_one_bind_dpdk(u32 dbdf) +{ + int err = 0; + char file_path[BIFUR_FILE_PATH_SIZE] = {}; + char buf[BIFUR_KWRITE_BUF_SIZE] = {}; + const char *kernel_driver = "hisdk3"; + + bifur_one_unbind_driver(dbdf, kernel_driver); + + err = snprintf(file_path, BIFUR_FILE_PATH_SIZE, + "/sys/bus/pci/devices/%.4x:%.2x:%.2x.%x/driver_override", + PCI_DBDF_DOM(dbdf), PCI_DBDF_BUS(dbdf), + PCI_DBDF_DEVID(dbdf), PCI_DBDF_FUNCTION(dbdf)); + if (err == -1) { + pr_err("Snprintf bifur pci dev driver_override file path, err %d!\n", err); + return err; + } + + (void)strscpy(buf, g_bifur_dpdk_kdriver, sizeof(buf)); + + err = bifur_open_and_write_file(file_path, buf, O_WRONLY | O_TRUNC, 0); + if (err != 0) + return err; + + err = snprintf(file_path, BIFUR_FILE_PATH_SIZE, + "/sys/bus/pci/drivers/%s/bind", g_bifur_dpdk_kdriver); + if (err == -1) { + pr_err("Snprintf bifur dpdk driver bind file path, err %d!\n", err); + return err; + } + + err = snprintf(buf, BIFUR_KWRITE_BUF_SIZE, "%.4x:%.2x:%.2x.%x", + PCI_DBDF_DOM(dbdf), PCI_DBDF_BUS(dbdf), + PCI_DBDF_DEVID(dbdf), PCI_DBDF_FUNCTION(dbdf)); + if (err == -1) { + pr_err("Snprintf bifur pci dev dbdf str, err %d!\n", err); + return err; + } + + err = bifur_open_and_write_file(file_path, buf, O_WRONLY | O_APPEND, 0); + if (err != 0) + return err; + + return 0; +} + +static int bifur_bind_unbind_dpdk(struct bifur_lld_dev *bifur_dev, bool enable) +{ + int err = 0; + u32 dbdf = 0; + int i; + + for (i = 0; i < bifur_dev->vf_mgr->vf_sum; ++i) { + dbdf = bifur_dev->vf_mgr->vf_info[i].vf_dbdf; + if (enable) + err = bifur_one_bind_dpdk(dbdf); + else + err = bifur_one_unbind_driver(dbdf, g_bifur_dpdk_kdriver); + if (err) { + pr_err("Bind/Unbind failed for vf %08x\n", dbdf); + return err; + } + } + + return 0; +} + +static int bifur_bind_unbind_dpdk_all(bool enable) +{ + int err = 0; + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *tmp_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + struct list_head *head = &adp->lld_dev_head; + + list_for_each_entry_safe(bifur_dev, tmp_dev, head, list) { + if (bifur_dev->pf_type != BIFUR_RESOURCE_PF) + continue; + + bifur_dev_hold(bifur_dev); + err = bifur_bind_unbind_dpdk(bifur_dev, enable); + bifur_dev_put(bifur_dev); + if (err) + return err; + } + + return 0; +} + +static int bifur_probe_vf(struct hinic3_lld_dev *lld_dev) +{ + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_vf_mgr *vf_mgr = NULL; + struct bifur_vf_info *vf_info = NULL; + u32 vf_dbdf; + int ret; + + bifur_dev = bifur_get_resource_dev(); + if (!bifur_dev) + return -ENODEV; + + vf_mgr = bifur_dev->vf_mgr; + vf_dbdf = PCI_DBDF(pci_domain_nr(lld_dev->pdev->bus), lld_dev->pdev->bus->number, + PCI_DBDF_DEVID(lld_dev->pdev->devfn), + PCI_DBDF_FUNCTION(lld_dev->pdev->devfn)); + if (vf_mgr->vf_sum >= BIFUR_VF_NUM) { + bifur_dev_put(bifur_dev); + BIFUR_DEV_ERR(lld_dev, "current_vf_sum(%u) >= BIFUR_VF_NUM(%u)\n", + vf_mgr->vf_sum, BIFUR_VF_NUM); + return -ENOMEM; + } + + mutex_lock(&bifur_dev->vf_mgr->vf_mgr_mutex); + vf_info = &vf_mgr->vf_info[vf_mgr->vf_sum]; + vf_mgr->vf_sum++; + vf_info->vf_dbdf = vf_dbdf; + vf_info->glb_func_id = hinic3_global_func_id(lld_dev->hwdev); + vf_info->in_use = 0; + vf_info->vf_mgr = vf_mgr; + ret = snprintf(vf_info->name, (size_t)BIFURNAMSIZ, "bifur%04x", vf_dbdf); + if (ret < 0) { + mutex_unlock(&bifur_dev->vf_mgr->vf_mgr_mutex); + BIFUR_DEV_ERR(lld_dev, "set name failed, ret(%d)\n", ret); + bifur_dev_put(bifur_dev); + return ret; + } + bifur_vf_cdev_init(vf_info); + mutex_unlock(&bifur_dev->vf_mgr->vf_mgr_mutex); + + bifur_dev_put(bifur_dev); + + return 0; +} + +static int bifur_remove_vf(struct bifur_lld_dev *bifur_dev) +{ + struct bifur_vf_info *vf_info = NULL; + struct bifur_vf_mgr *vf_mgr = NULL; + int i; + + if (!bifur_dev) + return -ENODEV; + vf_mgr = bifur_dev->vf_mgr; + + mutex_lock(&vf_mgr->vf_mgr_mutex); + for (i = 0; i < vf_mgr->vf_sum; ++i) { + vf_info = &vf_mgr->vf_info[i]; + bifur_vf_cdev_uninit(vf_info); + } + mutex_unlock(&vf_mgr->vf_mgr_mutex); + return 0; +} + +static int bifur_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev, char *uld_dev_name) +{ + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + int err = 0; + + if (!uld_dev || !lld_dev || !lld_dev->pdev || !lld_dev->hwdev) { + pr_err("Bifur probe failed for invalid param, lld_dev or uld_dev\n"); + return -EINVAL; + } + + if (hinic3_func_type(lld_dev->hwdev) == TYPE_VF) { + *uld_dev = NULL; + if (hinic3_support_bifur(lld_dev->hwdev, NULL)) { + err = bifur_probe_vf(lld_dev); + return err; + } + return 0; + } + + bifur_dev = kzalloc(sizeof(*bifur_dev), GFP_KERNEL); + if (!bifur_dev) { + BIFUR_DEV_ERR(lld_dev, "Alloc bifur lld dev failed\n"); + return -ENOMEM; + } + + /* init bifur dev */ + bifur_dev->lld_dev = lld_dev; + + if (hinic3_support_bifur(lld_dev->hwdev, NULL)) { + if (lld_dev->pdev->subsystem_device == BIFUR_RESOURCE_PF_SSID) { + bifur_dev->pf_type = BIFUR_RESOURCE_PF; + err = bifur_alloc_vf_mgr(bifur_dev); + if (err) { + kfree(bifur_dev); + bifur_dev = NULL; + return err; + } + } else { + bifur_dev->pf_type = BIFUR_SHARED_PF; + } + } else { + bifur_dev->pf_type = BIFUR_EXCLUSIVE_PF; + } + pr_info("bifur_dev->pf_type: %d\n", bifur_dev->pf_type); + + INIT_WORK(&bifur_dev->netdev_link, bifur_netdev_event); + bifur_dev->dbdf = PCI_DBDF(pci_domain_nr(lld_dev->pdev->bus), lld_dev->pdev->bus->number, + PCI_DBDF_DEVID(lld_dev->pdev->devfn), + PCI_DBDF_FUNCTION(lld_dev->pdev->devfn)); + + atomic_set(&bifur_dev->bifur_dev.bifur_dev_ref, 0); + bifur_dev->bifur_dev.has_created = true; + + bifur_dev_list_lock(); + list_add_tail(&bifur_dev->list, &adp->lld_dev_head); + bifur_dev_list_unlock(); + + *uld_dev = bifur_dev; + + BIFUR_DEV_INFO(lld_dev, "bifur driver probe\n"); + + return 0; +} + +static void bifur_remove(struct hinic3_lld_dev *lld_dev, void *uld_dev) +{ + struct bifur_lld_dev *bifur_dev = (struct bifur_lld_dev *)uld_dev; + + if (!bifur_dev) + return; + + if (bifur_dev->pf_type == BIFUR_RESOURCE_PF) { + (void)bifur_remove_vf(bifur_dev); + bifur_free_vf_mgr(bifur_dev); + } + + /* delete bifur device */ + bifur_dev_list_lock(); + list_del(&bifur_dev->list); + bifur_dev_list_unlock(); + + (void)cancel_work_sync(&bifur_dev->netdev_link); + wait_bifur_dev_unused(bifur_dev); + + bifur_destroy_dev(bifur_dev); + + kfree(bifur_dev); + bifur_dev = NULL; + + BIFUR_DEV_INFO(lld_dev, "bifur driver remove\n"); +} + +static int get_bifur_drv_version(struct drv_version_info *ver_info, u32 *out_size) +{ + int err; + + if (*out_size != sizeof(*ver_info)) { + pr_err("Unexpected out buf size from user :%u, expect: %lu\n", + *out_size, sizeof(*ver_info)); + return -EINVAL; + } + + err = snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s", + BIFUR_DRV_VERSION, __TIME_STR__); + if (err == -1) { + pr_err("Snprintf bifur version err\n"); + return -EFAULT; + } + + return 0; +} + +static int bifur_enable_vfs(u8 bond_bifur_en) +{ + int err; + + err = bifur_enable_disable_vf_all(true); + if (err) { + pr_err("Enable bifur vf failed. err(%d)\n", err); + return err; + } + + err = bifur_bind_unbind_dpdk_all(true); + if (err) { + (void)bifur_enable_disable_vf_all(false); + pr_err("Bind bifur vf to dpdk failed. err(%d)\n", err); + return err; + } + + bifur_set_bond_enable(bond_bifur_en); + return 0; +} + +static int bifur_disable_vfs(void) +{ + int err; + + bifur_set_bond_enable(BIFUR_DISABLED); + + err = bifur_enable_disable_vf_all(false); + if (err) { + pr_err("Disable bifur vf failed. err(%d)\n", err); + return err; + } + return 0; +} + +static int bifur_set_vfs_enable_state(struct bifur_adapter *adp, int set_enable, + int *out_enable, u32 *out_size) +{ + int err; + u8 bond_bifur_en; + + if (set_enable != BIFUR_ENABLED && set_enable != BIFUR_DISABLED) { + pr_err("Input params invalid. set_enable(%d)\n", set_enable); + return -EINVAL; + } + + if (*out_size != sizeof(*out_enable)) { + pr_err("Unexpected out buf size from user :%u, expect: %lu\n", + *out_size, sizeof(*out_enable)); + return -EINVAL; + } + + bifur_dev_list_lock(); + if ((u8)set_enable == adp->bifur_enabled) { + *out_enable = adp->bifur_enabled; + bifur_dev_list_unlock(); + pr_info("Bifur enabled status has been set. set_enable(%d)\n", set_enable); + return 0; + } + bond_bifur_en = adp->bond_bifur_enabled; + adp->bifur_enabled = set_enable; + bifur_dev_list_unlock(); + + if (set_enable == BIFUR_ENABLED) + err = bifur_enable_vfs(bond_bifur_en); + else + err = bifur_disable_vfs(); + + bifur_dev_list_lock(); + if (err != 0) + adp->bifur_enabled = !set_enable; + *out_enable = adp->bifur_enabled; + bifur_dev_list_unlock(); + + return err; +} + +static int bifur_get_bifur_enabled(struct bifur_adapter *adp, int *enabled_status, u32 *out_size) +{ + if (*out_size != sizeof(*enabled_status)) { + pr_err("Unexpected out buf size from user :%u, expect: %lu\n", + *out_size, sizeof(*enabled_status)); + return -EINVAL; + } + + bifur_dev_list_lock(); + *enabled_status = adp->bifur_enabled; + bifur_dev_list_unlock(); + return 0; +} + +static int bifur_ioctl(void *uld_dev, u32 cmd, const void *buf_in, u32 in_size, + void *buf_out, u32 *out_size) +{ + struct bifur_adapter *adp = bifur_get_adp(); + struct bifur_lld_dev *bifur_dev = (struct bifur_lld_dev *)uld_dev; + + if (!uld_dev || !out_size || !buf_out) { + pr_err("[BIFUR] %s: Input params is null. out_size(%d), buf_out(%d)\n", + __func__, (int)(!out_size), (int)(!buf_out)); + return -EINVAL; + } + + if (!hinic3_support_bifur(bifur_dev->lld_dev->hwdev, NULL)) { + pr_err("[BIFUR] %s: %s Not support bifurcation\n", __func__, + pci_name(bifur_dev->lld_dev->pdev)); + return -EINVAL; + } + + if (cmd == GET_DRV_VERSION) + return get_bifur_drv_version((struct drv_version_info *)buf_out, out_size); + + if (cmd == BIFUR_SET_ENABLE) + return bifur_set_vfs_enable_state(adp, *(int *)buf_in, (int *)buf_out, out_size); + else if (cmd == BIFUR_GET_ENABLE) + return bifur_get_bifur_enabled(adp, (int *)buf_out, out_size); + + pr_err("Not support cmd %u for bifur\n", cmd); + return 0; +} + +static struct hinic3_uld_info bifur_uld_info = { + .probe = bifur_probe, + .remove = bifur_remove, + .suspend = NULL, + .resume = NULL, + .ioctl = bifur_ioctl, +}; + +static __init int hibifur_init(void) +{ + int err = 0; + + pr_info("%s - version %s, compile time:%s\n", BIFUR_DRV_DESC, + BIFUR_DRV_VERSION, __TIME_STR__); + + if (!bifur_check_dpdk_kdriver()) { + pr_err("Invalid dpdk kernel driver type: %s\n", g_bifur_dpdk_kdriver); + return -EINVAL; + } + + err = bifur_alloc_adapter(); + if (err != 0) + return -ENOMEM; + + err = hinic3_register_uld(SERVICE_T_BIFUR, &bifur_uld_info); + if (err != 0) { + pr_err("Register bifur uld failed\n"); + goto register_uld_err; + } + + err = bifur_global_dev_init(); + if (err) { + pr_err("Register bifur global cdev failed\n"); + goto global_dev_init_err; + } + + err = bifur_register_net_event(); + if (err) { + pr_err("Register bifur global cdev failed\n"); + goto register_event_err; + } + + err = bifur_bond_init(); + if (err != 0) { + pr_err("Bifur bond status init failed\n"); + goto bond_init_err; + } + + return 0; + +bond_init_err: + bifur_unregister_net_event(); +register_event_err: + bifur_global_dev_uninit(); +global_dev_init_err: + hinic3_unregister_uld(SERVICE_T_BIFUR); +register_uld_err: + bifur_free_adapter(); + return err; +} + +static __exit void hibifur_exit(void) +{ + struct bifur_adapter *adp = bifur_get_adp(); + u8 bifur_enabled = BIFUR_DISABLED; + + bifur_bond_exit(); + bifur_unregister_net_event(); + bifur_global_dev_uninit(); + + bifur_dev_list_lock(); + if (adp->bifur_enabled) { + bifur_enabled = adp->bifur_enabled; + adp->bifur_enabled = BIFUR_DISABLED; + } + bifur_dev_list_unlock(); + + if (bifur_enabled) { + (void)bifur_bind_unbind_dpdk_all(false); + (void)bifur_enable_disable_vf_all(false); + } + + hinic3_unregister_uld(SERVICE_T_BIFUR); + bifur_free_adapter(); + + pr_info("%s exit\n", BIFUR_DRV_DESC); +} + +struct bifur_lld_dev *bifur_get_resource_dev(void) +{ + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *tmp_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + struct list_head *head = &adp->lld_dev_head; + + bifur_dev_list_lock(); + + /* found the bifur_lld_dev of resource pf */ + list_for_each_entry_safe(bifur_dev, tmp_dev, head, list) { + if (bifur_dev->pf_type == BIFUR_RESOURCE_PF) { + bifur_dev_hold(bifur_dev); + bifur_dev_list_unlock(); + pr_info("Find resource pf DBDF 0x%08x\n", bifur_dev->dbdf); + return bifur_dev; + } + } + + bifur_dev_list_unlock(); + + pr_err("Can't find resource pf\n"); + return NULL; +} + +struct bifur_lld_dev *bifur_get_shared_dev_by_dbdf(u32 dbdf) +{ + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *tmp_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + struct list_head *head = &adp->lld_dev_head; + + bifur_dev_list_lock(); + + /* found the bifur_lld_dev of shared pf */ + list_for_each_entry_safe(bifur_dev, tmp_dev, head, list) { + if (bifur_dev->pf_type == BIFUR_SHARED_PF && dbdf == bifur_dev->dbdf) { + bifur_dev_hold(bifur_dev); + bifur_dev_list_unlock(); + pr_info("Find shared pf DBDF 0x%08x\n", bifur_dev->dbdf); + return bifur_dev; + } + } + + bifur_dev_list_unlock(); + + pr_err("Can't find shared pf 0x%x\n", dbdf); + return NULL; +} + +static void wait_bifur_dev_unused(struct bifur_lld_dev *bifur_dev) +{ + int i; + + for (i = 0; i < BIFUR_WAIT_TIMES; i++) { + if (!atomic_read(&bifur_dev->bifur_dev.bifur_dev_ref)) + break; + + msleep(BIFUR_REMOVE_TIMESTEP); + } + + if (i == BIFUR_WAIT_TIMES) { + BIFUR_DEV_WARN(bifur_dev->lld_dev, + "destroy BIFUR device failed, bifur_dev_ref(%d) can not be 0 after %d ms\n", + atomic_read(&bifur_dev->bifur_dev.bifur_dev_ref), + (BIFUR_WAIT_TIMES * BIFUR_REMOVE_TIMESTEP)); + } +} + +static void bifur_destroy_dev(struct bifur_lld_dev *bifur_dev) +{ + if (!bifur_dev->bifur_dev.has_created) + return; + + bifur_dev->bifur_dev.has_created = false; + + BIFUR_DEV_INFO(bifur_dev->lld_dev, "Destroy BIFUR device success\n"); +} + +module_init(hibifur_init); +module_exit(hibifur_exit); + +MODULE_AUTHOR("Huawei Technologies CO., Ltd"); +MODULE_DESCRIPTION(BIFUR_DRV_DESC); +MODULE_VERSION(BIFUR_DRV_VERSION); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_main.h b/drivers/net/ethernet/huawei/hibifur/bifur_main.h new file mode 100644 index 000000000..9daac17dd --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_main.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ + +#ifndef BIFUR_MAIN_H__ +#define BIFUR_MAIN_H__ + +#include "hinic3_lld.h" +#include "asm-generic/int-ll64.h" + +#include <linux/mutex.h> +#include <linux/types.h> +#include <linux/timer.h> + +enum bifur_func_type { + BIFUR_EXCLUSIVE_PF = 1, + BIFUR_SHARED_PF, + BIFUR_RESOURCE_PF, + BIFUR_RESOURCE_VF, + BIFUR_FUNC_TYPE_MAX +}; + +struct bifur_flow_dev { + atomic_t bifur_dev_ref; + bool has_created; /* bifur dev created or not */ +}; + +struct bifur_adapter { + struct list_head lld_dev_head; /* pcie device list head */ + struct mutex bifur_dev_mutex; /* lock for bifur dev list */ + struct workqueue_struct *event_workq; /* global work queue */ + u8 bifur_enabled; /* used for mark whether to enable traffic bifurcation */ + u8 bond_bifur_enabled; /* used for mark whether to enable bond status of bifurcation vfs */ + u16 bond_id; +}; + +struct bifur_vf_mgr; +struct bifur_lld_dev { + struct list_head list; + struct hinic3_lld_dev *lld_dev; + struct bifur_vf_mgr *vf_mgr; + struct bifur_flow_dev bifur_dev; /* bifur device */ + enum bifur_func_type pf_type; + struct work_struct netdev_link; + u8 link_status; + u32 dbdf; +}; + +void bifur_dev_hold(struct bifur_lld_dev *bifur_dev); +void bifur_dev_put(struct bifur_lld_dev *bifur_dev); +void bifur_dev_list_lock(void); +void bifur_dev_list_unlock(void); +struct bifur_lld_dev *bifur_get_resource_dev(void); +struct bifur_adapter *bifur_get_adp(void); +struct bifur_lld_dev *bifur_get_shared_dev_by_dbdf(u32 dbdf); +#endif diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_pfile.c b/drivers/net/ethernet/huawei/hibifur/bifur_pfile.c new file mode 100644 index 000000000..3621bb10d --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_pfile.c @@ -0,0 +1,545 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ + +#include <linux/kernel.h> +#include "nic_mpu_cmd.h" +#include "hinic3_hw.h" +#include "hinic3_mgmt_interface.h" +#include "hinic3_common.h" + +#include "bifur_common.h" +#include "bifur_vf_mgr.h" +#include "bifur_main.h" +#include "bifur_pfile.h" + +#define BIFUR_GLOBAL_CDEV_NAME "bifur_gdev" +struct bifur_cdev g_bifur_global_dev; +struct bifur_global_file_list_t g_bifur_global_file_list; + +struct class *g_bifur_class; + +void bifur_global_dev_uninit(void) +{ + struct bifur_proc_file_t *tmp = NULL; + struct bifur_proc_file_t *proc_file = NULL; + struct bifur_cdev *bdev = &g_bifur_global_dev; + + mutex_lock(&g_bifur_global_file_list.lock); + list_for_each_entry_safe(proc_file, tmp, &g_bifur_global_file_list.list, node) { + list_del(&proc_file->node); + } + mutex_unlock(&g_bifur_global_file_list.lock); + + device_destroy(g_bifur_class, bdev->cdev_id); + class_destroy(g_bifur_class); + g_bifur_class = NULL; + cdev_del(&bdev->cdev); + unregister_chrdev_region(bdev->cdev_id, 1); + pr_info("Bifur destroy global cdev(%s) succeed.", BIFUR_GLOBAL_CDEV_NAME); +} + +void bifur_global_file_del(struct bifur_proc_file_t *proc_file) +{ + mutex_lock(&g_bifur_global_file_list.lock); + list_del(&proc_file->node); + mutex_unlock(&g_bifur_global_file_list.lock); +} + +int bifur_global_dev_close(struct inode *inode, struct file *filp) +{ + struct bifur_proc_file_t *proc_file = filp->private_data; + + pr_info("Close global proc_file(%p), filp(%p).", proc_file, filp); + bifur_global_file_del(proc_file); // Direct chain removal without traversing + kfree(proc_file); + + return 0; +} + +/* One dpdk process has only one process_file. A unique file is added to the global list. */ +int bifur_global_file_add(struct bifur_proc_file_t *add_proc_file) +{ + struct bifur_proc_file_t *tmp = NULL; + struct bifur_proc_file_t *proc_file = NULL; + + mutex_lock(&g_bifur_global_file_list.lock); + + list_for_each_entry_safe(proc_file, tmp, &g_bifur_global_file_list.list, node) { + if (proc_file->pid == add_proc_file->pid) { + mutex_unlock(&g_bifur_global_file_list.lock); + pr_err("Process(%u) file is exist.", proc_file->pid); + return -EPERM; + } + } + + list_add_tail(&add_proc_file->node, &g_bifur_global_file_list.list); + mutex_unlock(&g_bifur_global_file_list.lock); + + return 0; +} + +struct bifur_proc_file_t *bifur_alloc_proc_file(void) +{ + struct bifur_proc_file_t *proc_file = kzalloc(sizeof(struct bifur_proc_file_t), GFP_KERNEL); + + if (!proc_file) + return NULL; + + proc_file->pid = current->pid; + + return proc_file; +} + +int bifur_global_dev_open(struct inode *inode, struct file *filp) +{ + int ret; + struct bifur_proc_file_t *proc_file = bifur_alloc_proc_file(); + + if (!proc_file) + return -ENOMEM; + + ret = bifur_global_file_add(proc_file); + if (ret != 0) { + pr_err("Duplicate processes(%u) open global char dev.", current->pid); + kfree(proc_file); + return -EEXIST; + } + filp->private_data = proc_file; + + pr_info("Open proc global proc file success, proc_file(%p), filp(%p) pid(%u).", + proc_file, filp, proc_file->pid); + + return nonseekable_open(inode, filp); +} + +static int bifur_drv_cmd_func_attr_get(struct file *filp, struct bifur_msg *cmd) +{ + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *tmp_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + struct list_head *head = &adp->lld_dev_head; + int i; + + struct bifur_func_attr_get_cmd_msg *query_cmd; + struct bifur_func_attr_get_cmd_rsp *query_resp; + + query_cmd = (struct bifur_func_attr_get_cmd_msg *)(cmd->in_buf); + query_resp = (struct bifur_func_attr_get_cmd_rsp *)(cmd->out_buf); + if ((!query_cmd) || (!query_resp) || + cmd->in_buf_len < sizeof(struct bifur_func_attr_get_cmd_msg) || + cmd->out_buf_len < sizeof(struct bifur_func_attr_get_cmd_rsp)) { + pr_err("Input param fail, in_buf_len(%u), out_buf_len(%u).", + cmd->in_buf_len, cmd->out_buf_len); + return -EPERM; + } + + query_resp->func_type = 0; + cmd->out_data_len = sizeof(struct bifur_func_attr_get_cmd_rsp); + + bifur_dev_list_lock(); + if (adp->bifur_enabled == BIFUR_DISABLED) { + bifur_dev_list_unlock(); + query_resp->func_type = BIFUR_EXCLUSIVE_PF; + pr_info("Didn't enable traffic bifurcation, functions are exclusive.\n"); + return 0; + } + bifur_dev_list_unlock(); + + list_for_each_entry_safe(bifur_dev, tmp_dev, head, list) { + if (bifur_dev->dbdf == query_cmd->dbdf) { + query_resp->func_type = bifur_dev->pf_type; + break; + } + + if (bifur_dev->pf_type == BIFUR_RESOURCE_PF) { + for (i = 0; i < bifur_dev->vf_mgr->vf_sum; ++i) { + if (bifur_dev->vf_mgr->vf_info[i].vf_dbdf == query_cmd->dbdf) { + query_resp->func_type = BIFUR_RESOURCE_VF; + break; + } + } + } + } + + pr_info("Do get func attr cmd success\n"); + return 0; +} + +static inline void bifur_release_vf(struct bifur_vf_mgr *vf_mgr, struct bifur_vf_info *vf_info) +{ + mutex_lock(&vf_mgr->vf_mgr_mutex); + vf_info->in_use = 0; + vf_mgr->vf_in_use--; + mutex_unlock(&vf_mgr->vf_mgr_mutex); +} + +static int get_global_func_id_by_dbdf(u32 dbdf, u16 *glb_func_id) +{ + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *tmp_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + struct list_head *head = &adp->lld_dev_head; + int i; + + list_for_each_entry_safe(bifur_dev, tmp_dev, head, list) { + if (bifur_dev->dbdf == dbdf) { + *glb_func_id = hinic3_global_func_id(bifur_dev->lld_dev->hwdev); + return 0; + } + + if (bifur_dev->pf_type == BIFUR_RESOURCE_PF) { + for (i = 0; i < bifur_dev->vf_mgr->vf_sum; ++i) { + if (bifur_dev->vf_mgr->vf_info[i].vf_dbdf == dbdf) { + *glb_func_id = bifur_dev->vf_mgr->vf_info[i].glb_func_id; + return 0; + } + } + } + } + return -ENODEV; +} + +static int bifur_set_vf_tx_port(struct bifur_lld_dev *bifur_dev, u32 src_dbdf, u32 dst_dbdf) +{ + int err; + struct hinic3_func_er_value_cmd vf_fwd_id_cfg = {0}; + u16 out_size = sizeof(struct hinic3_func_er_value_cmd); + + err = get_global_func_id_by_dbdf(src_dbdf, &vf_fwd_id_cfg.vf_id); + if (err != 0) { + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Do not exit this vf, vf(%u)\n", src_dbdf); + return err; + } + BIFUR_DEV_INFO(bifur_dev->lld_dev, "src_vf(0x%x), vf_id(%u)\n", + src_dbdf, vf_fwd_id_cfg.vf_id); + + err = get_global_func_id_by_dbdf(dst_dbdf, &vf_fwd_id_cfg.er_fwd_id); + if (err != 0) { + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Do not exit this port, port dbdf(%u)\n", + dst_dbdf); + return err; + } + BIFUR_DEV_INFO(bifur_dev->lld_dev, "dst_dbdf(0x%x), er_fwd_id(%u)\n", + dst_dbdf, vf_fwd_id_cfg.er_fwd_id); + + err = hinic3_msg_to_mgmt_sync(bifur_dev->lld_dev->hwdev, HINIC3_MOD_L2NIC, + HINIC3_NIC_CMD_SET_FUNC_ER_FWD_ID, &vf_fwd_id_cfg, + sizeof(vf_fwd_id_cfg), &vf_fwd_id_cfg, &out_size, 0, + HINIC3_CHANNEL_DEFAULT); + if (vf_fwd_id_cfg.msg_head.status != 0 || err != 0 || out_size == 0) { + BIFUR_DEV_ERR(bifur_dev->lld_dev, + "Failed to set VF forward id config. err(%d), sts(%u), out_size(%u)\n", + err, vf_fwd_id_cfg.msg_head.status, out_size); + return -EIO; + } + return 0; +} + +static int bifur_drv_cmd_vf_alloc(struct file *filp, struct bifur_msg *cmd) +{ + int err; + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_vf_info *vf_info = NULL; + struct bifur_vf_alloc_cmd_msg *query_cmd = (struct bifur_vf_alloc_cmd_msg *)(cmd->in_buf); + struct bifur_vf_alloc_cmd_rsp *query_resp = (struct bifur_vf_alloc_cmd_rsp *)(cmd->out_buf); + struct bifur_adapter *adp = bifur_get_adp(); + + if (!query_cmd || !query_resp || + cmd->in_buf_len < sizeof(struct bifur_vf_alloc_cmd_msg) || + cmd->out_buf_len < sizeof(struct bifur_vf_alloc_cmd_rsp)) { + pr_err("Input param fail, in_buf_len(%u), out_buf_len(%u).", + cmd->in_buf_len, cmd->out_buf_len); + return -EINVAL; + } + + bifur_dev_list_lock(); + if (adp->bifur_enabled == BIFUR_DISABLED) { + bifur_dev_list_unlock(); + pr_err("Didn't enable traffic bifurcation.\n"); + return -EPERM; + } + bifur_dev_list_unlock(); + + /* found the bifur device */ + bifur_dev = bifur_get_resource_dev(); + if (!bifur_dev) + return -EINVAL; + + vf_info = bifur_find_vf(bifur_dev->vf_mgr, query_cmd->dbdf); + if (!vf_info) { + bifur_dev_put(bifur_dev); + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Alloc vf failed, %u vf in use\n", + bifur_dev->vf_mgr->vf_in_use); + return -EFAULT; + } + + err = bifur_set_vf_tx_port(bifur_dev, vf_info->vf_dbdf, query_cmd->dbdf); + if (err) { + bifur_release_vf(bifur_dev->vf_mgr, vf_info); + bifur_dev_put(bifur_dev); + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Set vf forward id failed, vf(%u), dst_pf(%u)\n", + vf_info->vf_dbdf, query_cmd->dbdf); + return err; + } + query_resp->vf_dbdf = vf_info->vf_dbdf; + + BIFUR_DEV_INFO(bifur_dev->lld_dev, "pf_dbdf: 0x%x\n", query_cmd->dbdf); + BIFUR_DEV_INFO(bifur_dev->lld_dev, "alloc_vf_dbdf: 0x%x\n", query_resp->vf_dbdf); + + cmd->out_data_len = sizeof(struct bifur_vf_alloc_cmd_rsp); + bifur_dev_put(bifur_dev); + pr_info("Do vf alloc cmd success\n"); + return 0; +} + +static int bifur_drv_cmd_mac_get(struct file *filp, struct bifur_msg *cmd) +{ + int ret; + u32 pf_dbdf; + struct bifur_lld_dev *bifur_dev = NULL; + struct bifur_lld_dev *shared_bifur_dev = NULL; + struct net_device *net_dev = NULL; + struct bifur_adapter *adp = bifur_get_adp(); + + struct bifur_mac_get_cmd_msg *query_cmd = (struct bifur_mac_get_cmd_msg *)(cmd->in_buf); + struct bifur_mac_get_cmd_rsp *query_resp = (struct bifur_mac_get_cmd_rsp *)(cmd->out_buf); + + if (!query_cmd || !query_resp || + cmd->in_buf_len < sizeof(struct bifur_mac_get_cmd_msg) || + cmd->out_buf_len < sizeof(struct bifur_mac_get_cmd_rsp)) { + pr_err("Input param fail, in_buf_len(%u), out_buf_len(%u).", + cmd->in_buf_len, cmd->out_buf_len); + return -EINVAL; + } + + bifur_dev_list_lock(); + if (adp->bifur_enabled == BIFUR_DISABLED) { + bifur_dev_list_unlock(); + pr_err("Didn't enable traffic bifurcation.\n"); + return -EPERM; + } + bifur_dev_list_unlock(); + + bifur_dev = bifur_get_resource_dev(); + if (!bifur_dev) + return -EINVAL; + + ret = bifur_find_pf_by_vf(bifur_dev->vf_mgr, query_cmd->dbdf, &pf_dbdf); + if (ret != 0) { + bifur_dev_put(bifur_dev); + pr_err("Find pf dbdf failed, vf dbdf(0x%x)\n", query_cmd->dbdf); + return -EFAULT; + } + + /* found shared dev by pf dbdf */ + shared_bifur_dev = bifur_get_shared_dev_by_dbdf(pf_dbdf); + if (!shared_bifur_dev) { + bifur_dev_put(bifur_dev); + return -EINVAL; + } + + /* found net device by shared dev lld dev */ + net_dev = hinic3_get_netdev_by_lld(shared_bifur_dev->lld_dev); + if (!net_dev) { + bifur_dev_put(bifur_dev); + bifur_dev_put(shared_bifur_dev); + pr_err("Get net device by lld dev failed, pf_dbdf(0x%x)\n", pf_dbdf); + return -EINVAL; + } + + ether_addr_copy(query_resp->mac, net_dev->dev_addr); + bifur_dev_put(bifur_dev); + bifur_dev_put(shared_bifur_dev); + + cmd->out_data_len = sizeof(struct bifur_mac_get_cmd_rsp); + pr_info("DO Get mac cmd of vf success\n"); + return 0; +} + +struct { + enum bifur_cmd_m drv_cmd; + int (*cmd_handle)(struct file *filp, struct bifur_msg *msg); +} g_bifur_cmd_table[] = { + {BIFUR_DRV_CMD_FUNC_ATTR_GET, bifur_drv_cmd_func_attr_get}, + {BIFUR_DRV_CMD_VF_ALLOC, bifur_drv_cmd_vf_alloc}, + {BIFUR_DRV_CMD_MAC_GET, bifur_drv_cmd_mac_get}, +}; + +int bifur_cmd_exec(struct file *file, struct bifur_msg *msg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(g_bifur_cmd_table); i++) { + if (g_bifur_cmd_table[i].drv_cmd == msg->drv_cmd) + return g_bifur_cmd_table[i].cmd_handle(file, msg); + } + + pr_err("Cmd(%u) is not supported.", msg->drv_cmd); + return -EOPNOTSUPP; +} + +int bifur_msg_copy_from_usr(const char __user *ubuf, size_t size, struct bifur_msg *usr, + struct bifur_msg *knl) +{ + u64 ret = 0; + + ret = copy_from_user(usr, ubuf, size); + if (ret != 0) { + pr_err("Copy msg from user failed, ret(0x%llx).", ret); + return -EFAULT; + } + + if (usr->in_buf && (usr->in_buf_len == 0 || usr->in_buf_len > BIFUR_MAX_CMD_LEN)) { + pr_err("Invalid in buf param, cmd(%u) in_buf_len(%u).", + usr->drv_cmd, usr->in_buf_len); + return -EINVAL; + } + if (usr->out_buf && (usr->out_buf_len == 0 || usr->out_buf_len > BIFUR_MAX_CMD_LEN)) { + pr_err("Invalid out buf param, cmd(%u) out_buf_len(%u).", + usr->drv_cmd, usr->out_buf_len); + return -EINVAL; + } + knl->drv_cmd = usr->drv_cmd; + knl->in_buf_len = usr->in_buf_len; + knl->out_buf_len = usr->out_buf_len; + + if (usr->in_buf) { + knl->in_buf = kzalloc((size_t)usr->in_buf_len, GFP_KERNEL); + if (!knl->in_buf) + return -ENOMEM; + ret = copy_from_user(knl->in_buf, usr->in_buf, (size_t)usr->in_buf_len); + if (ret != 0) { + pr_err("Cmd(%u) copy in_buf from user failed, ret(0x%llx).", + usr->drv_cmd, ret); + BUFUR_CHECK_KFREE(knl->in_buf); + return -EFAULT; + } + } + + if (usr->out_buf) { + knl->out_buf = kzalloc((size_t)usr->out_buf_len, GFP_KERNEL); + if (!knl->out_buf) { + BUFUR_CHECK_KFREE(knl->in_buf); + return -ENOMEM; + } + } + return 0; +} + +void bifur_free_knl_msg_buf(struct bifur_msg *msg) +{ + BUFUR_CHECK_KFREE(msg->in_buf); + BUFUR_CHECK_KFREE(msg->out_buf); +} + +int bifur_msg_copy_to_usr(struct bifur_msg *usr, struct bifur_msg *knl) +{ + u64 ret; + u32 copy_len; + + if (!usr->out_buf || knl->out_data_len == 0) { + usr->out_data_len = 0; + return 0; + } + + copy_len = (usr->out_buf_len > knl->out_data_len) ? knl->out_data_len : usr->out_buf_len; + ret = copy_to_user(usr->out_buf, knl->out_buf, (ulong)copy_len); + if (ret != 0) { + pr_err("Cmd(%u) copy out_buf to user failed, ret(0x%llx).", usr->drv_cmd, ret); + return -EFAULT; + } + + return 0; +} + +ssize_t bifur_file_write(struct file *file, const char __user *ubuf, size_t size, loff_t *pos) +{ + int ret = 0; + struct bifur_msg usr_msg = { 0 }; + struct bifur_msg knl_msg = { 0 }; + + if (!ubuf || size < sizeof(struct bifur_msg) || size > BIFUR_MAX_CMD_LEN) { + pr_err("Invalid param, size(%lu).", size); + return -EINVAL; + } + + ret = bifur_msg_copy_from_usr(ubuf, size, &usr_msg, &knl_msg); + if (ret != 0) + return ret; + + ret = bifur_cmd_exec(file, &knl_msg); + if (ret != 0) { + bifur_free_knl_msg_buf(&knl_msg); + return (ret < 0) ? ret : -EFAULT; + } + + ret = bifur_msg_copy_to_usr(&usr_msg, &knl_msg); + if (ret != 0) { + bifur_free_knl_msg_buf(&knl_msg); + return ret; + } + bifur_free_knl_msg_buf(&knl_msg); + + return 0; +} + +ssize_t bifur_proc_write(struct file *file, const char __user *ubuf, size_t size, loff_t *pos) +{ + return bifur_file_write(file, ubuf, size, pos); +} + +static const struct file_operations g_bifur_global_cdev_fops = { + .owner = THIS_MODULE, + .open = bifur_global_dev_open, + .release = bifur_global_dev_close, + .write = bifur_proc_write, +}; + +/* When the module is initialized, prepare the global character device. */ +int bifur_global_dev_init(void) +{ + char *name = BIFUR_GLOBAL_CDEV_NAME; + struct device *device; + struct bifur_cdev *bdev = &g_bifur_global_dev; + + int ret = alloc_chrdev_region(&bdev->cdev_id, 0, 1, name); + + if (ret < 0) { + pr_err("Bifur cdev(%s) alloc card chrdev region fail, ret(%d).", name, ret); + return -EFAULT; + } + + cdev_init(&bdev->cdev, &g_bifur_global_cdev_fops); + + ret = cdev_add(&bdev->cdev, bdev->cdev_id, 1); + if (ret < 0) { + unregister_chrdev_region(bdev->cdev_id, 1); + pr_err("Bifur cdev(%s) add cdev fail, ret(%d).", name, ret); + return -EFAULT; + } + + g_bifur_class = class_create(BIFUR_MOD_NAME); + if (IS_ERR(g_bifur_class)) { + unregister_chrdev_region(bdev->cdev_id, 1); + cdev_del(&bdev->cdev); + pr_err("Bifur create class fail."); + return -EEXIST; + } + + device = device_create(g_bifur_class, NULL, bdev->cdev_id, NULL, "%s", name); + if (IS_ERR(device)) { + class_destroy(g_bifur_class); + unregister_chrdev_region(bdev->cdev_id, 1); + cdev_del(&bdev->cdev); + pr_err("Bifur cdev(%s) create device fail.", name); + return -EFAULT; + } + + mutex_init(&g_bifur_global_file_list.lock); + INIT_LIST_HEAD(&g_bifur_global_file_list.list); + pr_info("Bifur create global cdev(%s) succeed.", name); + + return 0; +} diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_pfile.h b/drivers/net/ethernet/huawei/hibifur/bifur_pfile.h new file mode 100644 index 000000000..396d76311 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_pfile.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ +#ifndef BIFUR_PFILE_H +#define BIFUR_PFILE_H + +#define BIFUR_MAX_CMD_LEN (1024 * 1024) + +#define BIFUR_MOD_NAME "bifur" +#define BIFUR_PROC_DIR_MOD 0550 + +#define BUFUR_CHECK_KFREE(m) \ +do { \ + kfree(m); \ + m = NULL; \ +} while (0) + +#define BIFUR_UNREF_PARAM(x) ((x)) + +struct bifur_msg { + u32 drv_cmd; + u32 in_buf_len; + u32 out_buf_len; + u32 out_data_len; + void *in_buf; + void *out_buf; + u8 rsvd[24]; +}; + +enum bifur_cmd_m { + BIFUR_DRV_CMD_FUNC_ATTR_GET = 1, + BIFUR_DRV_CMD_VF_ALLOC, + BIFUR_DRV_CMD_MAC_GET, + BIFUR_CMD_BUTT +}; + +struct bifur_vf_alloc_cmd_msg { + unsigned int dbdf; +}; + +struct bifur_vf_alloc_cmd_rsp { + u32 vf_dbdf; +}; + +struct bifur_func_attr_get_cmd_msg { + unsigned int dbdf; +}; + +struct bifur_func_attr_get_cmd_rsp { + u32 func_type; +}; + +struct bifur_mac_get_cmd_msg { + unsigned int dbdf; +}; + +struct bifur_mac_get_cmd_rsp { + u8 mac[6]; +}; + +struct bifur_global_file_list_t { + struct mutex lock; + struct list_head list; +}; + +struct bifur_proc_file_t { + struct list_head node; + pid_t pid; +}; + +int bifur_global_dev_init(void); +void bifur_global_dev_uninit(void); + +#endif // BIFUR_PFILE_H diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.c b/drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.c new file mode 100644 index 000000000..71974c85d --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.c @@ -0,0 +1,263 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ +#include "bifur_common.h" +#include "bifur_pfile.h" +#include "bifur_main.h" +#include "bifur_vf_mgr.h" + +#define PDE_DATA(inode) pde_data(inode) + +int bifur_alloc_vf_mgr(struct bifur_lld_dev *bifur_dev) +{ + struct bifur_vf_mgr *vf_mgr = NULL; + struct bifur_vf_info *vf_info = NULL; + + vf_mgr = kzalloc(sizeof(*vf_mgr), GFP_KERNEL); + if (!vf_mgr) { + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Alloc vf mgr failed\n"); + return -ENOMEM; + } + + bifur_dev->vf_mgr = vf_mgr; + vf_info = kzalloc(sizeof(*vf_info) * BIFUR_VF_NUM, GFP_KERNEL); + if (!vf_info) { + kfree(vf_mgr); + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Alloc vf info failed\n"); + return -ENOMEM; + } + + vf_mgr->vf_sum = 0; + vf_mgr->vf_in_use = 0; + vf_mgr->vf_info = vf_info; + mutex_init(&vf_mgr->vf_mgr_mutex); + if (!vf_mgr->bifur_proc_root) { + vf_mgr->bifur_proc_root = proc_mkdir_mode(BIFUR_MOD_NAME, BIFUR_PROC_DIR_MOD, + init_net.proc_net); + if (!vf_mgr->bifur_proc_root) { + kfree(vf_mgr); + kfree(vf_info); + bifur_dev->vf_mgr = NULL; + BIFUR_DEV_ERR(bifur_dev->lld_dev, "Bifur create dir failed."); + return -ENOMEM; + } + } + + BIFUR_DEV_INFO(bifur_dev->lld_dev, "Alloc vf mgr success\n"); + return 0; +} + +void bifur_free_vf_mgr(struct bifur_lld_dev *bifur_dev) +{ + if (bifur_dev->vf_mgr && bifur_dev->vf_mgr->vf_info) { + kfree(bifur_dev->vf_mgr->vf_info); + bifur_dev->vf_mgr->vf_info = NULL; + } + + if (bifur_dev->vf_mgr != NULL) { + kfree(bifur_dev->vf_mgr); + bifur_dev->vf_mgr = NULL; + } + + remove_proc_entry(BIFUR_MOD_NAME, init_net.proc_net); + BIFUR_DEV_INFO(bifur_dev->lld_dev, "Free vf mgr success\n"); +} + +struct bifur_vf_info *bifur_find_vf(struct bifur_vf_mgr *vf_mgr, u32 pf_dbdf) +{ + u32 i; + struct bifur_vf_info *vf_info = NULL; + + mutex_lock(&vf_mgr->vf_mgr_mutex); + for (i = 0; i < vf_mgr->vf_sum; ++i) { + vf_info = &vf_mgr->vf_info[i]; + if (!vf_info->in_use) { + vf_info->in_use = 1; + vf_info->pf_dbdf = pf_dbdf; + vf_mgr->vf_in_use++; + mutex_unlock(&vf_mgr->vf_mgr_mutex); + return vf_info; + } + } + mutex_unlock(&vf_mgr->vf_mgr_mutex); + + return NULL; +} + +void bifur_vf_info_hold(struct bifur_vf_info *dev) +{ + atomic_inc(&dev->refcount); +} + +void bifur_vf_info_put(struct bifur_vf_info *dev) +{ + if (atomic_dec_and_test(&dev->refcount)) + pr_info("Dev(%s) pci_bdf(0x%x) comp complete.", dev->name, dev->vf_dbdf); +} + +void bifur_dev_file_add(struct bifur_dev_file_t *dev_file) +{ + mutex_lock(&dev_file->dev->dev_file_mgt.lock); + list_add_tail(&dev_file->node, &dev_file->dev->dev_file_mgt.list); + mutex_unlock(&dev_file->dev->dev_file_mgt.lock); +} + +void bifur_dev_file_del(struct bifur_dev_file_t *dev_file) +{ + mutex_lock(&dev_file->dev->dev_file_mgt.lock); + list_del(&dev_file->node); + mutex_unlock(&dev_file->dev->dev_file_mgt.lock); +} + +int bifur_proc_open(struct inode *inode, struct file *filp) +{ + struct bifur_vf_info *dev = (struct bifur_vf_info *)PDE_DATA(file_inode(filp)); + struct bifur_dev_file_t *dev_file = kzalloc(sizeof(*dev_file), GFP_KERNEL); + + if (!dev_file) + return -ENOMEM; + + atomic_set(&dev_file->refcount, 1); + dev_file->dev = dev; + bifur_vf_info_hold(dev_file->dev); + + bifur_dev_file_add(dev_file); + filp->private_data = dev_file; + + pr_info("Open proc dev(%s) success, filp(%p).", dev->name, filp); + + return nonseekable_open(inode, filp); +} + +int bifur_proc_close(struct inode *inode, struct file *filp) +{ + struct bifur_dev_file_t *dev_file = filp->private_data; + struct bifur_vf_info *dev = dev_file->dev; + struct bifur_vf_mgr *vf_mgr = dev->vf_mgr; + + pr_info("Close proc dev(%s), pci_bdf(0x%x), filp(%p).", dev_file->dev->name, + dev_file->dev->vf_dbdf, filp); + + bifur_dev_file_del(dev_file); + mutex_lock(&vf_mgr->vf_mgr_mutex); + dev->in_use = 0; + dev->pf_dbdf = 0; + vf_mgr->vf_in_use--; + bifur_vf_info_put(dev_file->dev); + mutex_unlock(&vf_mgr->vf_mgr_mutex); + + memset(dev_file, 0, sizeof(*dev_file)); + kfree(dev_file); + filp->private_data = NULL; + + return 0; +} + +#ifdef HAVE_PROC_OPS +const struct proc_ops g_bifur_proc_fops = { + .proc_open = bifur_proc_open, + .proc_release = bifur_proc_close, +}; +#else +const struct file_operations g_bifur_proc_fops = { + .owner = THIS_MODULE, + .open = bifur_proc_open, + .llseek = NULL, + .release = bifur_proc_close, +}; +#endif + +int bifur_dev_proc_build(struct bifur_vf_info *dev) +{ + struct proc_dir_entry *dir = NULL; + char pci_dev_name[BIFURNAMSIZ] = { 0 }; + struct bifur_vf_mgr *vf_mgr = dev->vf_mgr; + + int ret = sprintf(pci_dev_name, "0x%x", dev->vf_dbdf); + + if (ret < 0) { + pr_err("Bifur dev(%s) proc dir create fail, bdf(0x%x).", dev->name, dev->vf_dbdf); + return -ENOEXEC; + } + + dev->cdev.proc_dir = proc_mkdir_mode(pci_dev_name, BIFUR_PROC_DIR_MOD, + vf_mgr->bifur_proc_root); + if (!dev->cdev.proc_dir) { + pr_err("Bifur dev(%s) proc dir create fail.", dev->name); + return -EINVAL; + } + + dir = proc_create_data(BIFUR_CDEV_PROC_NAME, BIFUR_PROC_FILE_MOD, + dev->cdev.proc_dir, &g_bifur_proc_fops, dev); + if (!dir) { + remove_proc_entry(pci_dev_name, vf_mgr->bifur_proc_root); + dev->cdev.proc_dir = NULL; + pr_err("Bifur dev(%s) create card file failed.", dev->name); + return -EPERM; + } + + pr_info("Bifur dev(%p) name(%s,%s) proc build success.", dev, dev->name, pci_dev_name); + return 0; +} + +int bifur_dev_proc_destroy(struct bifur_vf_info *dev) +{ + char pci_dev_name[BIFURNAMSIZ] = { 0 }; + struct bifur_vf_mgr *vf_mgr = dev->vf_mgr; + + int ret = sprintf(pci_dev_name, "0x%x", dev->vf_dbdf); + + if (ret < 0) { + pr_err("Bifur dev(%s) proc dir create fail, bdf(0x%x).", dev->name, dev->vf_dbdf); + return -ENOEXEC; + } + + remove_proc_entry(BIFUR_CDEV_PROC_NAME, dev->cdev.proc_dir); + remove_proc_entry(pci_dev_name, vf_mgr->bifur_proc_root); + dev->cdev.proc_dir = NULL; + + pr_info("Bifur dev(%s) proc destroy success, pci_dev_name(%s).", dev->name, pci_dev_name); + + return 0; +} + +int bifur_find_pf_by_vf(struct bifur_vf_mgr *vf_mgr, u32 vf_dbdf, u32 *pf_dbdf) +{ + u32 i; + struct bifur_vf_info *vf_info = NULL; + + mutex_lock(&vf_mgr->vf_mgr_mutex); + for (i = 0; i < vf_mgr->vf_sum; ++i) { + vf_info = vf_mgr->vf_info + i; + if (vf_info->vf_dbdf == vf_dbdf && vf_info->in_use) { + *pf_dbdf = vf_info->pf_dbdf; + mutex_unlock(&vf_mgr->vf_mgr_mutex); + return 0; + } + } + mutex_unlock(&vf_mgr->vf_mgr_mutex); + + return -EINVAL; +} + +int bifur_vf_cdev_init(struct bifur_vf_info *dev) +{ + int ret; + + mutex_init(&dev->dev_file_mgt.lock); + INIT_LIST_HEAD(&dev->dev_file_mgt.list); + + ret = bifur_dev_proc_build(dev); + if (ret != 0) { + pr_err("Init dev build failed, ret(%d).", ret); + return ret; + } + + return 0; +} + +void bifur_vf_cdev_uninit(struct bifur_vf_info *dev) +{ + (void)bifur_dev_proc_destroy(dev); +} diff --git a/drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.h b/drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.h new file mode 100644 index 000000000..7c4124495 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/bifur_vf_mgr.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved. + */ + +#ifndef BIFUR_VF_MGR_H__ +#define BIFUR_VF_MGR_H__ + +#define BIFURNAMSIZ 20 +#define BIFUR_PROC_FILE_MOD 0640 +#define BIFUR_CDEV_PROC_NAME "bifur_vdev" + +struct bifur_dev_file_mgt_t { + struct mutex lock; + struct list_head list; +}; +struct bifur_lld_dev; +struct bifur_vf_mgr; + +struct bifur_vf_info { + char name[BIFURNAMSIZ]; + u32 vf_dbdf; + u32 pf_dbdf; + u16 glb_func_id; + bool in_use; + struct bifur_cdev cdev; + struct bifur_dev_file_mgt_t dev_file_mgt; + struct bifur_vf_mgr *vf_mgr; + atomic_t refcount; +}; + +struct bifur_vf_mgr { + u32 vf_sum; + u32 vf_in_use; + struct bifur_vf_info *vf_info; + struct mutex vf_mgr_mutex; + struct proc_dir_entry *bifur_proc_root; +}; + +struct bifur_dev_file_t { + struct list_head node; + struct bifur_vf_info *dev; + + atomic_t refcount; +}; + +int bifur_alloc_vf_mgr(struct bifur_lld_dev *bifur_dev); + +void bifur_free_vf_mgr(struct bifur_lld_dev *bifur_dev); + +struct bifur_vf_info *bifur_find_vf(struct bifur_vf_mgr *vf_mgr, u32 dbdf); + +int bifur_find_pf_by_vf(struct bifur_vf_mgr *vf_mgr, u32 vf_dbdf, u32 *pf_dbdf); + +int bifur_vf_cdev_init(struct bifur_vf_info *dev); +void bifur_vf_cdev_uninit(struct bifur_vf_info *dev); + +#endif diff --git a/drivers/net/ethernet/huawei/hibifur/include/hinic3_hmm.h b/drivers/net/ethernet/huawei/hibifur/include/hinic3_hmm.h new file mode 100644 index 000000000..957220c13 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/include/hinic3_hmm.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Huawei Technologies Co., Ltd */ + +#ifndef HINIC_HMM_H__ +#define HINIC_HMM_H__ + +/* has no mpt entry */ +#define HMM_MPT_EN_SW 1 /* has mpt, state INVALID */ +#define HMM_MPT_EN_HW 2 /* has mpt, state FREE or VALID */ +#define HMM_MPT_DISABLED 0 /* has no mpt entry */ +#define HMM_MPT_FIX_BUG_LKEY 0 + +#include "hinic3_cqm.h" +#include "hinic3_hwdev.h" +#include "hmm_comp.h" +#include "hmm_mr.h" + +/* Prototype : hmm_reg_user_mr_update + * Description : Update the MR entry in the MPT and MTT tables + * Input: struct hinic3_hwdev *hwdev - Device structure pointer + * hmm_mr *mr - + * MR structure, containing the completed user-mode memory physical address + * acquisition umem + * u32 pdn - + * PD number, if the feature of the unsupported pd is directly filled with 0. + * u64 length - + * The length of the user-mode address that needs to be registered + * u64 virt_addr - + * The first virtual address of the IOV virtual address that needs to be registered + * int hmm_access - + * Fill in the value of enum rdma_ib_access, describing the access permission + * u32 service_type - + * The value of enum hinic3_service_type, describing the service type + * Output : None + */ +int hmm_reg_user_mr_update(struct hinic3_hwdev *hwdev, struct hmm_mr *mr, u32 pdn, u64 length, + u64 virt_addr, int access, u32 service_type, u16 channel); + +/* Prototype : hmm_reg_user_mr_update + * Description : Remove the MR entry from the MPT and MTT tables + * Input: struct hinic3_hwdev *hwdev - Device structure pointer + * rdma_mr *mr - MR structure + * u32 service_type - enum hinic3_service_type value, describes the service type + * Output : None + */ +int hmm_dereg_mr_update(struct hinic3_hwdev *hwdev, struct rdma_mr *mr, + u32 service_type, u16 channel); + +#ifndef ROCE_SERVICE +/* Prototype : hmm_reg_user_mr + * Description : Register an MR for the user + * Input: struct hinic3_hwdev *hwdev - Device structure pointer + * u64 start - The starting address of the memory region + * u32 pdn - PD number + * u64 length - The length of the memory region + * u64 virt_addr - The virtual address of the IOV + * int hmm_access - + * The access permission, filled in with the value of enum rdma_ib_access + * u32 service_type - + * The service type, filled in with the value of enum hinic3_service_type + * Output: struct hmm_mr * - Returns a pointer to the newly registered MR structure + */ +struct hmm_mr *hmm_reg_user_mr(struct hinic3_hwdev *hwdev, u64 start, u32 pdn, u64 length, + u64 virt_addr, int hmm_access, u32 service_type, u16 channel); + +/* Prototype : hmm_dereg_mr + * Description : Deregister DMA_MR, user_MR, or FRMR + * Input: struct hmm_mr *mr - MR structure + * u32 service_type - enum hinic3_service_type value, describes the service type + * Output : None + */ +int hmm_dereg_mr(struct hmm_mr *mr, u32 service_type, u16 channel); +#endif + +int hmm_rdma_write_mtt(void *hwdev, struct rdma_mtt *mtt, u32 start_index, u32 npages, + u64 *page_list, u32 service_type); + +int hmm_rdma_mtt_alloc(void *hwdev, u32 npages, u32 page_shift, + struct rdma_mtt *mtt, u32 service_type); + +void hmm_rdma_mtt_free(void *hwdev, struct rdma_mtt *mtt, u32 service_type); + +int hmm_init_mtt_table(struct hmm_comp_priv *comp_priv); + +void hmm_cleanup_mtt_table(struct hmm_comp_priv *comp_priv); + +#endif /* HINIC_RDMA_H__ */ diff --git a/drivers/net/ethernet/huawei/hibifur/include/hinic3_rdma.h b/drivers/net/ethernet/huawei/hibifur/include/hinic3_rdma.h new file mode 100644 index 000000000..1de8ba98f --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/include/hinic3_rdma.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Huawei Technologies Co., Ltd */ + +#ifndef HINIC_RDMA_H__ +#define HINIC_RDMA_H__ + +#define RDMA_ROCE_ENABLE 1 +#define RDMA_IWARP_ENABLE 1 +#define RDMA_ROCE_DISABLE 0 +#define RDMA_IWARP_DISABLE 0 + +#define RDMA_MPT_DISABLED 0 /* has no mpt entry */ +#define RDMA_MPT_EN_SW 1 /* has mpt, state INVALID */ +#define RDMA_MPT_EN_HW 2 /* has mpt, state FREE or VALID */ + +#define RDMA_MPT_FIX_BUG_LKEY 0 + +struct mutex; +struct tag_cqm_qpc_mpt; +struct tag_cqm_object; +struct net_device; +struct rdma_gid_entry; + +#include "hinic3_cqm.h" + +enum mtt_check_type_e { + MTT_CHECK_TYPE_0 = 0, + MTT_CHECK_TYPE_1 +}; + +enum mtt_data_type_e { + MTT_DMTT_TYPE = 0, + MTT_CMTT_TYPE +}; + +enum rdma_ib_access { + RDMA_IB_ACCESS_LOCAL_WRITE = 1, + RDMA_IB_ACCESS_REMOTE_WRITE = (1 << 1), + RDMA_IB_ACCESS_REMOTE_READ = (1 << 2), + RDMA_IB_ACCESS_REMOTE_ATOMIC = (1 << 3), + RDMA_IB_ACCESS_MW_BIND = (1 << 4), + RDMA_IB_ACCESS_ZERO_BASED = (1 << 5), + RDMA_IB_ACCESS_ON_DEMAND = (1 << 6), +}; + +struct rdma_gid_entry { + union { + u8 raw[16]; + struct { + __be64 subnet_prefix; + __be64 interface_id; + } global; + }; + union { + struct { + u32 rsvd : 7; + u32 is_vroce : 1; + u32 cvlan : 12; /* 内层vlan customer vlan */ + u32 svlan : 12; /* 外层vlan */ + } bs; + u32 value; + } dw4; + + union { + u32 hdr_len_value; + }; + + union { + struct { + /* 0:没有vlan; 1:一层vlan; 2: 2层vlan; 3:stag */ + u16 tag : 2; + u16 tunnel : 1; // rsvd for ppe, don't use. 'tunnel' + u16 gid_type : 2; + u16 ppe_rsvd1 : 1; + u16 outer_tag : 2; // rsvd for ppe, don't use. 'outer_tag' + u16 ppe_rsvd3 : 1; // rsvd for ppe, don't use. 'stag' + u16 gid_update : 1; + u16 rsvd : 6; + } bs; + u16 value; + } dw6_h; + + u8 smac[6]; +}; + +struct rdma_comp_resource { + struct mutex mutex; /* gid_entry使用的互斥量 */ + __be64 node_guid; /* 与ibdev中的node_guid一致 */ + struct rdma_gid_entry **gid_table; /* gid_entry在rdma组件初始化时分配内存 */ +}; + +struct rdma_mpt { + u32 mpt_index; /* 封装cqm提供的mpt_index */ + void *vaddr; /* 封装cqm提供的mpt_entry的虚拟地址 */ + void *mpt_object; /* 封装的cqm提供的指针 */ +}; + + +struct rdma_mtt_seg { + u32 offset; /* 分配连续索引的首个索引 */ + u32 order; /* mtt索引个数为1<<order,每个索引对应一个mtt entry */ + void *vaddr; /* mtt_seg第一个MTT的起始虚拟地址 */ + dma_addr_t paddr; /* mtt_seg第一个MTT的起始物理地址 */ +}; + +struct rdma_mtt { + /* mtt的级数,该值为0时表示不使用mtt做地址转换 */ + u32 mtt_layers; + u32 mtt_page_shift; /* MTT的页大小 */ + u32 buf_page_shift; /* buffer页大小 */ + dma_addr_t mtt_paddr; /* 写入context中的物理地址 */ + __be64 *mtt_vaddr; /* 写入context中的虚拟地址 */ + struct rdma_mtt_seg **mtt_seg; /* 指向多级mtt */ + enum mtt_data_type_e mtt_type; +}; + +enum rdma_mr_type { + RDMA_DMA_MR = 0, + RDMA_USER_MR = 1, + RDMA_FRMR = 2, + RDMA_FMR = 3, + RDMA_PHYS_MR = 4, + RDMA_RSVD_LKEY = 5, + RDMA_SIG_MR = 6, + RDMA_INDIRECT_MR = 8, + RDMA_ODP_IMPLICIT_MR = 9, + RDMA_ODP_EXPLICIT_MR = 10, +}; + +struct rdma_mr { + struct rdma_mpt mpt; + struct rdma_mtt mtt; + u64 iova; /* mr指向内存的起始地址(虚拟地址,ZBVA时为0) */ + u64 size; /* mr指向内存的大小 */ + u32 key; /* mr对应的key */ + u32 pdn; /* mr绑定的pdn */ + u32 access; /* mr的访问权限 */ + int enabled; /* mr的状态,DISABLE、EN_SW、EN_HW */ + int mr_type; /* mr类型 */ + u32 block_size; +}; + +enum rdma_mw_type { + RDMA_MW_TYPE_1 = 1, + RDMA_MW_TYPE_2 = 2 +}; + +struct rdma_mw { + struct rdma_mpt mpt; + u32 key; /* mw对应的key */ + u32 pdn; /* mw绑定的pdn */ + enum rdma_mw_type type; /* mw的类型,type1,type2 */ + int enabled; /* mw的状态 */ +}; + +struct rdma_fmr { + struct rdma_mr mr; + u32 max_pages; /* fmr的最大映射页个数 */ + u32 max_maps; /* fmr的最大映射次数 */ + u32 maps; /* fmr的当前映射次数 */ + u32 page_shift; /* fmr指定的页偏移 */ +}; + +struct rdma_rdmarc { + u32 offset; /* 分配连续索引的首个索引 */ + u32 order; /* 分配的rdmarc的order,代表了个数 */ + u32 ext_order; /* 包含rc表和扩展表的个数 */ + dma_addr_t dma_addr; + void *vaddr; +}; + +int roce3_rdma_pd_alloc(void *hwdev, u32 *pdn); + +void roce3_rdma_pd_free(void *hwdev, u32 pdn); + +int roce3_rdma_enable_mw_mpt(void *hwdev, struct rdma_mw *mw, u32 service_type); + +int roce3_rdma_disable_mw_mpt(void *hwdev, struct rdma_mw *mw, u32 service_type); + +int roce3_rdma_map_phys_fmr(void *hwdev, struct rdma_fmr *fmr, u64 *page_list, + int npages, u64 iova, u32 service_type); + +int roce3_rdma_unmap_fmr(void *hwdev, struct rdma_fmr *fmr, u32 service_type); + +int roce3_rdma_rdmarc_alloc(void *hwdev, u32 num, struct rdma_rdmarc *rdmarc); + +void roce3_rdma_rdmarc_free(void *hwdev, struct rdma_rdmarc *rdmarc); + +int roce3_rdma_update_gid_mac(void *hwdev, u32 port, struct rdma_gid_entry *gid_entry); +int roce3_rdma_update_gid(void *hwdev, u32 port, u32 update_index, + struct rdma_gid_entry *gid_entry); +int roce3_rdma_reset_gid_table(void *hwdev, u32 port); + +int roce3_rdma_get_gid(void *hwdev, u32 port, u32 gid_index, struct rdma_gid_entry *gid); + +/* 该接口在pf初始化时调用 */ +int roce3_rdma_init_resource(void *hwdev); + +/* 该接口在pf卸载时调用 */ +void roce3_rdma_cleanup_resource(void *hwdev); + +#endif /* HINIC_RDMA_H__ */ diff --git a/drivers/net/ethernet/huawei/hibifur/include/nic/nic_mpu_cmd.h b/drivers/net/ethernet/huawei/hibifur/include/nic/nic_mpu_cmd.h new file mode 100644 index 000000000..1a3c26d00 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/include/nic/nic_mpu_cmd.h @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Huawei Technologies Co., Ltd */ + +#ifndef NIC_MPU_CMD_H +#define NIC_MPU_CMD_H + +/** Commands between NIC to MPU + */ +enum hinic3_nic_cmd { + HINIC3_NIC_CMD_VF_REGISTER = 0, /**< Only for PFD and VFD @see > hinic3_cmd_register_vf */ + + /** FUNC CFG */ + HINIC3_NIC_CMD_SET_FUNC_TBL = 5, /**< Set function table @see > hinic3_cmd_set_func_tbl */ + HINIC3_NIC_CMD_SET_VPORT_ENABLE, /**< Enable a vport @see > hinic3_vport_state */ + HINIC3_NIC_CMD_SET_RX_MODE, /**< Set nic rx mode. @see > hinic3_rx_mode_config */ + HINIC3_NIC_CMD_SQ_CI_ATTR_SET, /**< Set SQ CI attr @see > hinic3_cmd_cons_idx_attr */ + /**< Get vport stat @see > hinic3_port_stats_info, < hinic3_cmd_vport_stats */ + HINIC3_NIC_CMD_GET_VPORT_STAT, + /**< Clean vport stat @see > hinic3_cmd_clear_vport_stats */ + HINIC3_NIC_CMD_CLEAN_VPORT_STAT, + /**< Clean queue pair resource @see > hinic3_cmd_clear_qp_resource */ + HINIC3_NIC_CMD_CLEAR_QP_RESOURCE, + HINIC3_NIC_CMD_CFG_FLEX_QUEUE, /**< Set flex queue @see > hinic3_cmd_cfg_qps */ + /** LRO CFG */ + HINIC3_NIC_CMD_CFG_RX_LRO, /**< Set rx LRO @see > hinic3_cmd_lro_config */ + HINIC3_NIC_CMD_CFG_LRO_TIMER, /**< Set LRO timer @see > hinic3_cmd_lro_timer */ + /**< negotiate features @see > hinic3_cmd_feature_nego */ + HINIC3_NIC_CMD_FEATURE_NEGO, + /**< Configure local LRO state @see > hinic3_cmd_local_lro_state */ + HINIC3_NIC_CMD_CFG_LOCAL_LRO_STATE, + + /**< Cache out queue pair resource @see > hinic3_cmd_cache_out_qp_resource */ + HINIC3_NIC_CMD_CACHE_OUT_QP_RES, + /**< Set nic er fwd id. @see > mpu_nic_cmd_set_func_er_fwd_id */ + HINIC3_NIC_CMD_SET_FUNC_ER_FWD_ID, + + /** MAC & VLAN CFG */ + HINIC3_NIC_CMD_GET_MAC = 20, /**< Get mac address @see > hinic3_port_mac_set */ + HINIC3_NIC_CMD_SET_MAC, /**< Set mac address @see > hinic3_port_mac_set */ + HINIC3_NIC_CMD_DEL_MAC, /**< Delete mac address @see > hinic3_port_mac_set */ + /**< Update mac address @see > hinic3_port_mac_update */ + HINIC3_NIC_CMD_UPDATE_MAC, + /**< Get all default mac address @see > cmd_mac_info_get_s */ + HINIC3_NIC_CMD_GET_ALL_DEFAULT_MAC, + + /**< Configure function vlan @see > hinic3_cmd_vlan_config */ + HINIC3_NIC_CMD_CFG_FUNC_VLAN, + /**< Enable vlan filter @see > hinic3_cmd_set_vlan_filter */ + HINIC3_NIC_CMD_SET_VLAN_FILTER_EN, + /**< Set rx vlan offload @see > hinic3_cmd_vlan_offload */ + HINIC3_NIC_CMD_SET_RX_VLAN_OFFLOAD, + HINIC3_NIC_CMD_SMAC_CHECK_STATE, + + /** SR-IOV */ + /**< Configure vf vlan @see > hinic3_cmd_vf_vlan_config */ + HINIC3_NIC_CMD_CFG_VF_VLAN = 40, + /**< Set snoopchk state @see > hinic3_cmd_spoofchk_set */ + HINIC3_NIC_CMD_SET_SPOOPCHK_STATE, + /* RATE LIMIT */ + /**< Set rate limit @see > HINIC3_NIC_CMD_SET_MAX_MIN_RATE */ + HINIC3_NIC_CMD_SET_MAX_MIN_RATE, + + /** RSS CFG */ + HINIC3_NIC_CMD_RSS_CFG = 60, /**< Set rss config @see > hinic3_cmd_rss_config */ + HINIC3_NIC_CMD_RSS_TEMP_MGR, /**< TODO: delete after implement nego cmd */ + HINIC3_NIC_CMD_GET_RSS_CTX_TBL, /**< TODO: delete: move to ucode cmd */ + /**< Set rss hash key @see > hinic3_cmd_rss_hash_key */ + HINIC3_NIC_CMD_CFG_RSS_HASH_KEY, + /**< Set rss hash engine type @see > hinic3_cmd_rss_engine_type */ + HINIC3_NIC_CMD_CFG_RSS_HASH_ENGINE, + /**< Set rss context table info @see > hinic3_rss_context_table */ + HINIC3_NIC_CMD_SET_RSS_CTX_TBL_INTO_FUNC, + /** IP checksum error packets, enable rss quadruple hash */ + /**< Set rss config @see > hinic3_ipcs_err_rss_enable_operation_s */ + HINIC3_NIC_CMD_IPCS_ERR_RSS_ENABLE_OP = 66, + + /** PPA/FDIR */ + HINIC3_NIC_CMD_ADD_TC_FLOW = 80, /**< Add tc flow @see > nic_cmd_fdir_add_rule */ + HINIC3_NIC_CMD_DEL_TC_FLOW, /**< Delete tc flow @see > nic_cmd_fdir_del_rules */ + HINIC3_NIC_CMD_GET_TC_FLOW, /**< Get tc flow @see > nic_cmd_fdir_get_rule */ + HINIC3_NIC_CMD_FLUSH_TCAM, /**< Flush TCAM @see > nic_cmd_flush_tcam_rules */ + /**< Configure TCAM block @see > nic_cmd_ctrl_tcam_block_out */ + HINIC3_NIC_CMD_CFG_TCAM_BLOCK, + /**< Enable TCAM @see > nic_cmd_set_tcam_enable */ + HINIC3_NIC_CMD_ENABLE_TCAM, + /**< Get TCAM block @see > nic_cmd_dfx_fdir_tcam_block_table */ + HINIC3_NIC_CMD_GET_TCAM_BLOCK, + /**< Configure PPA table id @see > hinic3_ppa_cfg_table_id_cmd */ + HINIC3_NIC_CMD_CFG_PPA_TABLE_ID, + /**< Set PPA enable @see > hinic3_ppa_cfg_ppa_en_cmd */ + HINIC3_NIC_CMD_SET_PPA_EN = 88, + /**< Configure PPA mode @see > hinic3_ppa_cfg_mode_cmd */ + HINIC3_NIC_CMD_CFG_PPA_MODE, + /**< Configure PPA flush @see > hinic3_ppa_cfg_flush_cmd */ + HINIC3_NIC_CMD_CFG_PPA_FLUSH, + /**< Set FDIR status @see > hinic3_set_fdir_ethertype_rule */ + HINIC3_NIC_CMD_SET_FDIR_STATUS, + /**< Get PPA counter @see > hinic3_ppa_fdir_query_cmd */ + HINIC3_NIC_CMD_GET_PPA_COUNTER, + /**< Set flow bifur status @see > cmd_flow_bifur_func_handle */ + HINIC3_NIC_CMD_SET_FUNC_FLOW_BIFUR_ENABLE, + /**< Set flow bifur bond @see > cmd_flow_bifur_bond_handle */ + HINIC3_NIC_CMD_SET_BOND_MASK, + /**< Get func tcam table @see > get_fdir_func_tcam_table */ + HINIC3_NIC_CMD_GET_BLOCK_TC_FLOWS, + /**< Get flow bifur bond @see > cmd_flow_bifur_bond_handle */ + HINIC3_NIC_CMD_GET_BOND_MASK, + + /** PORT CFG */ + HINIC3_NIC_CMD_SET_PORT_ENABLE = 100, /**< set port enable @see > hinic3_port_state */ + HINIC3_NIC_CMD_CFG_PAUSE_INFO, /**< Configure pause info @see > hinic3_cmd_pause_config */ + + HINIC3_NIC_CMD_SET_PORT_CAR, /**< Set port Car @see > hinic3_cmd_set_port_car */ + HINIC3_NIC_CMD_SET_ER_DROP_PKT, /**< Unused */ + + HINIC3_NIC_CMD_VF_COS, /**< Get vf CoS @see > hinic3_cmd_vf_dcb_state */ + HINIC3_NIC_CMD_SETUP_COS_MAPPING, /**< Unused */ + HINIC3_NIC_CMD_SET_ETS, /**< Unused */ + HINIC3_NIC_CMD_SET_PFC, /**< Unused */ + HINIC3_NIC_CMD_QOS_ETS, /**< Set QoS ETS @see > hinic3_cmd_ets_cfg */ + HINIC3_NIC_CMD_QOS_PFC, /**< Set QoS PFC @see > hinic3_cmd_set_pfc */ + HINIC3_NIC_CMD_QOS_DCB_STATE, /**< Get QoS DCB state @see > hinic3_cmd_set_dcb_state */ + HINIC3_NIC_CMD_QOS_PORT_CFG, /**< Get QoS port cfg @see > hinic3_cmd_qos_port_cfg */ + HINIC3_NIC_CMD_QOS_MAP_CFG, /**< Get QoS map cfg @see > hinic3_cmd_qos_map_cfg */ + HINIC3_NIC_CMD_FORCE_PKT_DROP, /**< Force pkt drop @see > hinic3_force_pkt_drop */ + /**< Configure nic tx promisc skip @see > hinic3_tx_promisc_cfg */ + HINIC3_NIC_CMD_CFG_TX_PROMISC_SKIP = 114, + /**< Set flow bifur port switch @see > cmd_flow_bifur_port_handle */ + HINIC3_NIC_CMD_SET_PORT_FLOW_BIFUR_ENABLE = 117, + /**< Set tx pause exc notice @see > nic_cmd_tx_pause_notice */ + HINIC3_NIC_CMD_TX_PAUSE_EXCP_NOTICE = 118, + /**< Inquirt pause cfg @see > nic_cmd_pause_inquiry_cfg_s */ + HINIC3_NIC_CMD_INQUIRT_PAUSE_CFG = 119, + + /** MISC */ + HINIC3_NIC_CMD_BIOS_CFG = 120, /**< Set QoS ETS @see > nic_cmd_bios_cfg */ + HINIC3_NIC_CMD_SET_FIRMWARE_CUSTOM_PACKETS_MSG, /**< Set QoS ETS @see > fault_msg_st */ + + /** BOND */ + /**< Create bond device @see > hinic3_cmd_create_bond */ + HINIC3_NIC_CMD_BOND_DEV_CREATE = 134, + HINIC3_NIC_CMD_BOND_DEV_DELETE, /**< Delete bond device @see > hinic3_cmd_delete_bond */ + /**<Open/close bond dev @see > hinic3_cmd_open_close_bond */ + HINIC3_NIC_CMD_BOND_DEV_OPEN_CLOSE, + HINIC3_NIC_CMD_BOND_INFO_GET, /**< Set QoS ETS @see > hinic3_bond_status_info */ + /**< Get bond active info @see > hinic3_bond_active_report_info */ + HINIC3_NIC_CMD_BOND_ACTIVE_INFO_GET, + /**< Bond active notice report @see > nic_cmd_bond_active_report_info */ + HINIC3_NIC_CMD_BOND_ACTIVE_NOTICE, + + /** DFX */ + HINIC3_NIC_CMD_GET_SM_TABLE = 140, /**< Get sm table @see > nic_cmd_dfx_sm_table */ + /**< Set RD line table @see > nic_mpu_lt_opera, < nic_mpu_lt_opera */ + HINIC3_NIC_CMD_RD_LINE_TBL, + + HINIC3_NIC_CMD_SET_UCAPTURE_OPT = 160, /**< TODO: move to roce */ + HINIC3_NIC_CMD_SET_VHD_CFG, /**< Set VHD configuration @see > hinic3_set_vhd_mode */ + + /** TODO: move to HILINK */ + /**< Get port stat @see > hinic3_port_stats_info, < hinic3_port_stats */ + HINIC3_NIC_CMD_GET_PORT_STAT = 200, + HINIC3_NIC_CMD_CLEAN_PORT_STAT, /**< Unused */ + HINIC3_NIC_CMD_CFG_LOOPBACK_MODE, /**< Unused */ + HINIC3_NIC_CMD_GET_SFP_QSFP_INFO, /**< Unused */ + HINIC3_NIC_CMD_SET_SFP_STATUS, /**< Unused */ + HINIC3_NIC_CMD_GET_LIGHT_MODULE_ABS, /**< Unused */ + HINIC3_NIC_CMD_GET_LINK_INFO, /**< Unused */ + HINIC3_NIC_CMD_CFG_AN_TYPE, /**< Unused */ + HINIC3_NIC_CMD_GET_PORT_INFO, /**< Get port info @see > hinic3_cmd_port_info */ + HINIC3_NIC_CMD_SET_LINK_SETTINGS, /**< Unused */ + HINIC3_NIC_CMD_ACTIVATE_BIOS_LINK_CFG, /**< Unused */ + HINIC3_NIC_CMD_RESTORE_LINK_CFG, /**< Unused */ + HINIC3_NIC_CMD_SET_LINK_FOLLOW, /**< Unused */ + HINIC3_NIC_CMD_GET_LINK_STATE, /**< Unused */ + HINIC3_NIC_CMD_LINK_STATUS_REPORT, /**< Unused */ + HINIC3_NIC_CMD_CABLE_PLUG_EVENT, /**< Unused */ + HINIC3_NIC_CMD_LINK_ERR_EVENT, /**< Unused */ + HINIC3_NIC_CMD_SET_LED_STATUS, /**< Unused */ + + HINIC3_NIC_CMD_MAX = 256, +}; + +#endif /* NIC_MPU_CMD_H */ diff --git a/drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd.h b/drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd.h new file mode 100644 index 000000000..65b243a0e --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Huawei Technologies Co., Ltd */ + +#ifndef NIC_NPU_CMD_H +#define NIC_NPU_CMD_H + +/* NIC CMDQ MODE */ +enum hinic3_ucode_cmd { + /**< Modify queue context. @see > hinic3_sq_ctxt_block */ + HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX = 0, + /**< Clean queue context. @see > hinic3_clean_queue_ctxt */ + HINIC3_UCODE_CMD_CLEAN_QUEUE_CONTEXT, + HINIC3_UCODE_CMD_ARM_SQ, /**< Unused */ + HINIC3_UCODE_CMD_ARM_RQ, /**< Unused */ + /**< Set RSS indir table. @see > nic_rss_indirect_tbl */ + HINIC3_UCODE_CMD_SET_RSS_INDIR_TABLE, + /**< Set RSS indir table. @see > nic_rss_context_tbl */ + HINIC3_UCODE_CMD_SET_RSS_CONTEXT_TABLE, + HINIC3_UCODE_CMD_GET_RSS_INDIR_TABLE, + HINIC3_UCODE_CMD_GET_RSS_CONTEXT_TABLE, /**< Unused */ + HINIC3_UCODE_CMD_SET_IQ_ENABLE, /**< Unused */ + HINIC3_UCODE_CMD_SET_RQ_FLUSH = 10, /**< Set RQ flush. @see > hinic3_cmd_set_rq_flush */ + HINIC3_UCODE_CMD_MODIFY_VLAN_CTX, /**< Get rxq info. @see > nic_vlan_ctx */ + HINIC3_UCODE_CMD_PPA_HASH_TABLE, + /**< Get rxq info. @see > hinic3_rxq_hw, < rxq_check_info */ + HINIC3_UCODE_CMD_RXQ_INFO_GET = 13, +}; + +#endif /* NIC_NPU_CMD_H */ diff --git a/drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd_defs.h b/drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd_defs.h new file mode 100644 index 000000000..b5461ad85 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/include/nic/nic_npu_cmd_defs.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Huawei Technologies Co., Ltd */ + + +#ifndef NIC_NPU_CMD_DEFS_H +#define NIC_NPU_CMD_DEFS_H + +#include "typedef.h" +#include "nic_cfg_comm.h" + +/* NIC Command Queue Header + * This header is used to indicate the start of a NIC command queue. + * All contexts that follow this header should be consecutive. + */ +struct nic_cmdq_header { + union { + struct { +#if (BYTE_ORDER == BIG_ENDIAN) + /* 0x0:SQ, 0x1:RQ */ + u16 queue_type; + /* queue number in buffer follow this header */ + u16 queue_num; +#else + u16 queue_num; + u16 queue_type; +#endif + } cmdq_ctx_dw0; + + u32 ctx_dw0; + }; + +#if (BYTE_ORDER == BIG_ENDIAN) + u16 rsvd; + u16 start_qid; +#else + u16 start_qid; + u16 rsvd; +#endif +}; + +struct nic_cmdq_context_modify_s { + struct nic_cmdq_header hdr; + u8 data[2016]; +}; + +struct nic_cmdq_clean_q_space { + /* queue_type = 0, TSO (TCP Segmentation Offload) + * queue_type = 1, LRO (Large Receive Offload) + */ + union { + struct { +#if (BYTE_ORDER == BIG_ENDIAN) + u16 queue_type; + u16 queue_num; +#else + u16 queue_num; + u16 queue_type; +#endif + } cmdq_space_dw0; + + u32 space_dw0; + }; + +#if (BYTE_ORDER == BIG_ENDIAN) + u16 rsvd; + u16 start_qid; +#else + u16 start_qid; + u16 rsvd; +#endif + + u32 rsvd1; +}; + +struct nic_cmdq_flush_rq_task { + union { + struct { +#if (BYTE_ORDER == BIG_ENDIAN) + u16 q_id; + u16 glb_rq_id; +#else + u16 glb_rq_id; + u16 q_id; +#endif + } bs; + + u32 value; + } dw0; +}; + +/* arm sq/rq */ +union nic_cmdq_arm { + struct cmdq_arm_dw0_s { +#if (BYTE_ORDER == BIG_ENDIAN) + u16 qpn; + u16 pi; +#else + u16 pi; + u16 qpn; +#endif + } dw0; + + u32 arm_dw0; +}; + +/* rss */ +struct nic_rss_indirect_tbl { + u32 rsvd[4]; // Make sure that 16B beyond entry[] + u16 entry[NIC_RSS_INDIR_SIZE]; +}; + +struct nic_rss_glb_qid_indirect_tbl { + u32 group_index; + u32 offset; + u32 size; + u32 rsvd; /* Make sure that 16B beyond entry[] */ + u16 entry[NIC_RSS_INDIR_SIZE]; +}; + +struct nic_rss_context_tbl { + u32 rsvd[4]; + u32 ctx; +}; + +struct nic_vlan_ctx { + u32 func_id; + u32 qid; /* if qid = 0xFFFF, config current function all queue */ + u32 vlan_id; + u32 vlan_mode; + u32 vlan_sel; +}; + +#endif /* NIC_NPU_CMD_DEFS_H */ diff --git a/drivers/net/ethernet/huawei/hibifur/include/node_id.h b/drivers/net/ethernet/huawei/hibifur/include/node_id.h new file mode 100644 index 000000000..84d276873 --- /dev/null +++ b/drivers/net/ethernet/huawei/hibifur/include/node_id.h @@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright(c) 2024 Huawei Technologies Co., Ltd */ +#ifndef NODE_ID_H +#define NODE_ID_H + +#ifdef __cplusplus +#if __cplusplus +extern "C"{ +#endif +#endif /* __cplusplus */ + +/** RING NODE ID */ +enum { + NODE_ID_CPI = 0, + NODE_ID_MQM = 1, + NODE_ID_QUF = 2, + NODE_ID_Reserved0 = 3, + NODE_ID_SMF0 = 4, + NODE_ID_TILE_F0 = 5, + NODE_ID_TILE_F1 = 6, + NODE_ID_SMF1 = 7, + NODE_ID_DP_NETWORK = 8, + NODE_ID_CPB = 9, + NODE_ID_QUL = 10, + NODE_ID_TS = 11, + NODE_ID_TILE_L1 = 12, + NODE_ID_SML1 = 13, + NODE_ID_SML0 = 14, + NODE_ID_TILE_L0 = 15, + NODE_ID_SMF2 = 16, + NODE_ID_TILE_F2 = 17, + NODE_ID_TILE_F3 = 18, + NODE_ID_SMF3 = 19, + NODE_ID_TILE_L3 = 20, + NODE_ID_SML3 = 21, + NODE_ID_SML2 = 22, + NODE_ID_TILE_L2 = 23, + NODE_ID_CRYPTO = 24, + NODE_ID_LCAM = 25, + NODE_ID_MPU = 26, + NODE_ID_DP_HOST = 27, + NODE_ID_UP_HOST = 31 /* Used for API chain function in the CPI */ +}; + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* NODE_ID_H */ + diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h b/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h index 14d409b02..64139c49a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h @@ -45,6 +45,7 @@ enum hinic3_service_type { SERVICE_T_CUSTOM, SERVICE_T_VROCE, SERVICE_T_CRYPT, + SERVICE_T_BIFUR, SERVICE_T_MAX, /* Only used for interruption resource management, @@ -76,6 +77,10 @@ struct ppa_service_cap { u16 rsvd1; }; +struct bifur_service_cap { + u8 rsvd; +}; + struct vbs_service_cap { u16 vbs_max_volq; u8 vbs_main_pf_enable; @@ -785,6 +790,15 @@ bool hinic3_support_toe(void *hwdev, struct toe_service_cap *cap); */ bool hinic3_support_ppa(void *hwdev, struct ppa_service_cap *cap); +/* * + * @brief hinic3_support_bifur - function support bifur + * @param hwdev: device pointer to hwdev + * @param cap: bifur service capbility + * @retval zero: success + * @retval non-zero: failure + */ +bool hinic3_support_bifur(void *hwdev, struct bifur_service_cap *cap); + /* * * @brief hinic3_support_migr - function support migrate * @param hwdev: device pointer to hwdev diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c index d07a1ba04..6f90c868a 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c @@ -89,6 +89,8 @@ enum hinic3_rx_buff_len { #define CONVERT_UNIT 1024 +#define BIFUR_RESOURCE_PF_SSID 0x5a1 + #ifdef HAVE_MULTI_VLAN_OFFLOAD_EN static int hinic3_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr); @@ -876,11 +878,13 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev, hinic3_register_notifier(nic_dev); #endif - err = register_netdev(netdev); - if (err) { - nic_err(&pdev->dev, "Failed to register netdev\n"); - err = -ENOMEM; - goto netdev_err; + if (pdev->subsystem_device != BIFUR_RESOURCE_PF_SSID) { + err = register_netdev(netdev); + if (err) { + nic_err(&pdev->dev, "Failed to register netdev\n"); + err = -ENOMEM; + goto netdev_err; + } } queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ); @@ -928,7 +932,9 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter) netdev = nic_dev->netdev; - unregister_netdev(netdev); + if (lld_dev->pdev->subsystem_device != BIFUR_RESOURCE_PF_SSID) + unregister_netdev(netdev); + #ifdef HAVE_MULTI_VLAN_OFFLOAD_EN hinic3_unregister_notifier(nic_dev); #endif diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h index 952133f10..18a85f489 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mgmt_interface.h @@ -1091,9 +1091,18 @@ struct hinic3_bond_mask_cmd { u8 rsvd[3]; }; +struct hinic3_func_er_value_cmd { + struct hinic3_mgmt_msg_head msg_head; + u16 vf_id; + u16 er_fwd_id; +}; + #define HINIC3_TX_SET_PROMISC_SKIP 0 #define HINIC3_TX_GET_PROMISC_SKIP 1 +#define HINIC3_GET_TRAFFIC_BIFUR_STATE 0 +#define HINIC3_SET_TRAFFIC_BIFUR_STATE 1 + struct hinic3_tx_promisc_cfg { struct hinic3_mgmt_msg_head msg_head; u8 port_id; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h index b5bcd8ae8..94e606e96 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h @@ -132,7 +132,8 @@ enum module_name { SEND_TO_MIGRATE_DRIVER, SEND_TO_PPA_DRIVER, SEND_TO_CUSTOM_DRIVER = SEND_TO_SRV_DRV_BASE + 11, - SEND_TO_DRIVER_MAX = SEND_TO_SRV_DRV_BASE + 15, /* reserved */ + SEND_TO_BIFUR_DRIVER = SEND_TO_SRV_DRV_BASE + 15, + SEND_TO_DRIVER_MAX = SEND_TO_SRV_DRV_BASE + 16, /* reserved */ }; enum driver_cmd_type { @@ -208,12 +209,16 @@ enum driver_cmd_type { GET_XSFP_PRESENT = 0x51, GET_XSFP_INFO = 0x52, DEV_NAME_TEST = 0x53, + GET_XSFP_INFO_COMP_CMIS = 0x54, GET_WIN_STAT = 0x60, WIN_CSR_READ = 0x61, WIN_CSR_WRITE = 0x62, WIN_API_CMD_RD = 0x63, + BIFUR_SET_ENABLE = 0xc0, + BIFUR_GET_ENABLE = 0xc1, + VM_COMPAT_TEST = 0xFF }; diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c index 9154a1d27..5e0139aa9 100644 --- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c +++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c @@ -622,6 +622,9 @@ void hinic3_get_card_info(const void *hwdev, void *bufin) if (hinic3_func_for_mgmt(fun_hwdev)) strscpy(info->pf[i].name, "FOR_MGMT", IFNAMSIZ); + if (dev->lld_dev.pdev->subsystem_device == BIFUR_RESOURCE_PF_SSID) + strscpy(info->pf[i].name, "bifur", IFNAMSIZ); + strscpy(info->pf[i].bus_info, pci_name(dev->pcidev), sizeof(info->pf[i].bus_info)); info->pf_num++; diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h index bb7f5bb67..5c7c7cdd8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h +++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h @@ -20,6 +20,8 @@ #define ULD_LOCK_MIN_USLEEP_TIME 900 #define ULD_LOCK_MAX_USLEEP_TIME 1000 +#define BIFUR_RESOURCE_PF_SSID 0x05a1 + #define HINIC3_IS_VF_DEV(pdev) ((pdev)->device == HINIC3_DEV_ID_VF) #define HINIC3_IS_SPU_DEV(pdev) ((pdev)->device == HINIC3_DEV_ID_SPU) diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c index 819c56f42..030ef6df7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c +++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c @@ -1172,6 +1172,20 @@ bool hinic3_support_ppa(void *hwdev, struct ppa_service_cap *cap) } EXPORT_SYMBOL(hinic3_support_ppa); +bool hinic3_support_bifur(void *hwdev, struct bifur_service_cap *cap) +{ + struct hinic3_hwdev *dev = (struct hinic3_hwdev *)hwdev; + + if (!hwdev) + return false; + + if (!IS_BIFUR_TYPE(dev)) + return false; + + return true; +} +EXPORT_SYMBOL(hinic3_support_bifur); + bool hinic3_support_migr(void *hwdev, struct migr_service_cap *cap) { struct hinic3_hwdev *dev = hwdev; diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h index db6e3cab6..671eed69c 100644 --- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h +++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h @@ -322,6 +322,8 @@ struct cfg_mgmt_info { (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SERVICE_MASK_PPA) #define IS_MIGR_TYPE(dev) \ (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SERVICE_MASK_MIGRATE) +#define IS_BIFUR_TYPE(dev) \ + (((u32)(dev)->cfg_mgmt->svc_cap.chip_svc_type) & CFG_SERVICE_MASK_BIFUR) int init_cfg_mgmt(struct hinic3_hwdev *dev); diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c index 0b1c995bd..6ab1b92e7 100644 --- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c +++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c @@ -73,7 +73,7 @@ void hinic3_uld_lock_init(void) static const char *s_uld_name[SERVICE_T_MAX] = { "nic", "ovs", "roce", "toe", "ioe", - "fc", "vbs", "ipsec", "virtio", "migrate", "ppa", "custom"}; + "fc", "vbs", "ipsec", "virtio", "migrate", "ppa", "bifur", "custom"}; const char **hinic3_get_uld_names(void) { diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c index 4cdc6f6ea..5e4804a96 100644 --- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c +++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c @@ -550,8 +550,17 @@ static struct hinic3_lld_dev *get_lld_dev_by_nt_msg(struct msg_module *nt_msg) { struct hinic3_lld_dev *lld_dev = NULL; - if (nt_msg->module >= SEND_TO_SRV_DRV_BASE && nt_msg->module < SEND_TO_DRIVER_MAX && - nt_msg->module != SEND_TO_HW_DRIVER && nt_msg->msg_formate != GET_DRV_VERSION) { + if (nt_msg->module == SEND_TO_NIC_DRIVER && (nt_msg->msg_formate == GET_XSFP_INFO || + nt_msg->msg_formate == GET_XSFP_PRESENT || + nt_msg->msg_formate == GET_XSFP_INFO_COMP_CMIS)) { + lld_dev = hinic3_get_lld_dev_by_chip_and_port(nt_msg->device_name, nt_msg->port_id); + } else if (nt_msg->module == SEND_TO_CUSTOM_DRIVER && + nt_msg->msg_formate == CMD_CUSTOM_BOND_GET_CHIP_NAME) { + lld_dev = hinic3_get_lld_dev_by_dev_name(nt_msg->device_name, SERVICE_T_MAX); + } else if (nt_msg->module == SEND_TO_VBS_DRIVER || nt_msg->module == SEND_TO_BIFUR_DRIVER) { + lld_dev = hinic3_get_lld_dev_by_chip_name(nt_msg->device_name); + } else if (nt_msg->module >= SEND_TO_SRV_DRV_BASE && nt_msg->module < SEND_TO_DRIVER_MAX && + nt_msg->msg_formate != GET_DRV_VERSION) { lld_dev = hinic3_get_lld_dev_by_dev_name(nt_msg->device_name, nt_msg->module - SEND_TO_SRV_DRV_BASE); } else { @@ -561,15 +570,6 @@ static struct hinic3_lld_dev *get_lld_dev_by_nt_msg(struct msg_module *nt_msg) SERVICE_T_MAX); } - if (nt_msg->module == SEND_TO_NIC_DRIVER && (nt_msg->msg_formate == GET_XSFP_INFO || - nt_msg->msg_formate == GET_XSFP_PRESENT)) - lld_dev = hinic3_get_lld_dev_by_chip_and_port(nt_msg->device_name, - nt_msg->port_id); - - if (nt_msg->module == SEND_TO_CUSTOM_DRIVER && - nt_msg->msg_formate == CMD_CUSTOM_BOND_GET_CHIP_NAME) - lld_dev = hinic3_get_lld_dev_by_dev_name(nt_msg->device_name, SERVICE_T_MAX); - return lld_dev; } diff --git a/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h index f56df083a..e7e16fca4 100644 --- a/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h +++ b/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h @@ -21,6 +21,7 @@ enum servic_bit_define { SERVICE_BIT_PPA = 11, SERVICE_BIT_MIGRATE = 12, SERVICE_BIT_VROCE = 13, + SERVICE_BIT_BIFUR = 14, SERVICE_BIT_MAX }; @@ -38,6 +39,7 @@ enum servic_bit_define { #define CFG_SERVICE_MASK_PPA (0x1 << SERVICE_BIT_PPA) #define CFG_SERVICE_MASK_MIGRATE (0x1 << SERVICE_BIT_MIGRATE) #define CFG_SERVICE_MASK_VROCE (0x1 << SERVICE_BIT_VROCE) +#define CFG_SERVICE_MASK_BIFUR (0x1 << SERVICE_BIT_BIFUR) /* Definition of the scenario ID in the cfg_data, which is used for SML memory allocation. */ enum scenes_id_define { -- 2.45.1.windows.1
2
1
0
0
[PATCH openEuler-22.03-LTS-SP1 0/2] CVE-2024-45009
by Wang Liang
02 Jan '25
02 Jan '25
Matthieu Baerts (NGI0) (2): mptcp: pm: only decrement add_addr_accepted for MPJ req mptcp: pm: fix UaF read in mptcp_pm_nl_rm_addr_or_subflow net/mptcp/pm_netlink.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) -- 2.34.1
2
3
0
0
[PATCH OLK-6.6 0/1] Fix CVE-2024-56744
by Hongbo Li
02 Jan '25
02 Jan '25
Fix CVE-2024-56744. Chao Yu (1): f2fs: fix to avoid potential deadlock in f2fs_record_stop_reason() fs/f2fs/checkpoint.c | 2 +- fs/f2fs/f2fs.h | 3 +-- fs/f2fs/super.c | 13 +++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) -- 2.34.1
2
2
0
0
[PATCH openEuler-1.0-LTS 0/1] CVE-2024-53158
by Lin Yujun
02 Jan '25
02 Jan '25
Dan Carpenter (1): soc: qcom: geni-se: fix array underflow in geni_se_clk_tbl_get() drivers/soc/qcom/qcom-geni-se.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) -- 2.34.1
2
2
0
0
[PATCH OLK-6.6 0/1] CVE-2024-56567
by Liao Chen
02 Jan '25
02 Jan '25
fix CVE-2024-56567 Zicheng Qu (1): [Backport] ad7780: fix division by zero in ad7780_write_raw() drivers/iio/adc/ad7780.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.34.1
2
6
0
0
[PATCH OLK-5.10 0/1] CVE-2024-56567
by Liao Chen
02 Jan '25
02 Jan '25
fix CVE-2024-56567 Zicheng Qu (1): [Backport] ad7780: fix division by zero in ad7780_write_raw() drivers/iio/adc/ad7780.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.34.1
2
6
0
0
[PATCH OLK-5.10 0/1] CVE-2024-56567
by Liao Chen
02 Jan '25
02 Jan '25
fix CVE-2024-56567 Zicheng Qu (1): [Backport] ad7780: fix division by zero in ad7780_write_raw() drivers/iio/adc/ad7780.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.34.1
2
6
0
0
← Newer
1
...
39
40
41
42
43
44
45
...
49
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Results per page:
10
25
50
100
200