Kernel
Threads by month
- ----- 2025 -----
- May
- April
- March
- February
- 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
- 24 participants
- 18017 discussions
各位开发者和用户,
经2025年5月9日 openEuler Kernel SIG 会议讨论,拟定继续使用 6.6 内核支撑 openEuler 2026 年 LTS 版本发布,
特此公示。
公示时间:2025-5-9 18:00 - 2025-5-23 18:00, 公示14天。
公示期间,如果您有任何意见,请邮件反馈至:xiexiuqi@huawei.com,jason.zeng@intel.com,sanglipeng1@jd.com.
如需反馈意见,请说明您所在的团队,您的联系方式,并详细描述原因。您的反馈意见可能会在社区会议中公开讨论,请
不要包含保密信息。
openEuler Kernel SIG
2025年5月9日
1
0

[PATCH OLK-5.10] [Backport] backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()
by Yuntao Liu 09 May '25
by Yuntao Liu 09 May '25
09 May '25
From: Herve Codina <herve.codina(a)bootlin.com>
stable inclusion
from stable-v5.10.237
commit 87d947a0607be384bfe7bb0935884a711e35ca07
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IC5BJZ
CVE: CVE-2025-23144
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit 276822a00db3c1061382b41e72cafc09d6a0ec30 ]
Lockdep detects the following issue on led-backlight removal:
[ 142.315935] ------------[ cut here ]------------
[ 142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80
...
[ 142.500725] Call trace:
[ 142.503176] led_sysfs_enable+0x54/0x80 (P)
[ 142.507370] led_bl_remove+0x80/0xa8 [led_bl]
[ 142.511742] platform_remove+0x30/0x58
[ 142.515501] device_remove+0x54/0x90
...
Indeed, led_sysfs_enable() has to be called with the led_access
lock held.
Hold the lock when calling led_sysfs_disable().
Fixes: ae232e45acf9 ("backlight: add led-backlight driver")
Cc: stable(a)vger.kernel.org
Signed-off-by: Herve Codina <herve.codina(a)bootlin.com>
Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com
Signed-off-by: Lee Jones <lee(a)kernel.org>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Yuntao Liu <liuyuntao12(a)huawei.com>
---
drivers/video/backlight/led_bl.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
index f54d256e2d54..1020e4405a4d 100644
--- a/drivers/video/backlight/led_bl.c
+++ b/drivers/video/backlight/led_bl.c
@@ -226,8 +226,11 @@ static int led_bl_remove(struct platform_device *pdev)
backlight_device_unregister(bl);
led_bl_power_off(priv);
- for (i = 0; i < priv->nb_leds; i++)
+ for (i = 0; i < priv->nb_leds; i++) {
+ mutex_lock(&priv->leds[i]->led_access);
led_sysfs_enable(priv->leds[i]);
+ mutex_unlock(&priv->leds[i]->led_access);
+ }
return 0;
}
--
2.34.1
2
1

[PATCH OLK-6.6] backlight: led_bl: Hold led_access lock when calling led_sysfs_disable()
by Yuntao Liu 09 May '25
by Yuntao Liu 09 May '25
09 May '25
From: Herve Codina <herve.codina(a)bootlin.com>
stable inclusion
from stable-v6.6.88
commit 1c82f5a393d8b9a5c1ea032413719862098afd4b
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IC5BJZ
CVE: CVE-2025-23144
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 276822a00db3c1061382b41e72cafc09d6a0ec30 upstream.
Lockdep detects the following issue on led-backlight removal:
[ 142.315935] ------------[ cut here ]------------
[ 142.315954] WARNING: CPU: 2 PID: 292 at drivers/leds/led-core.c:455 led_sysfs_enable+0x54/0x80
...
[ 142.500725] Call trace:
[ 142.503176] led_sysfs_enable+0x54/0x80 (P)
[ 142.507370] led_bl_remove+0x80/0xa8 [led_bl]
[ 142.511742] platform_remove+0x30/0x58
[ 142.515501] device_remove+0x54/0x90
...
Indeed, led_sysfs_enable() has to be called with the led_access
lock held.
Hold the lock when calling led_sysfs_disable().
Fixes: ae232e45acf9 ("backlight: add led-backlight driver")
Cc: stable(a)vger.kernel.org
Signed-off-by: Herve Codina <herve.codina(a)bootlin.com>
Link: https://lore.kernel.org/r/20250122091914.309533-1-herve.codina@bootlin.com
Signed-off-by: Lee Jones <lee(a)kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Signed-off-by: Yuntao Liu <liuyuntao12(a)huawei.com>
---
drivers/video/backlight/led_bl.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
index 032f8bddf872..0e53e427a91d 100644
--- a/drivers/video/backlight/led_bl.c
+++ b/drivers/video/backlight/led_bl.c
@@ -229,8 +229,11 @@ static void led_bl_remove(struct platform_device *pdev)
backlight_device_unregister(bl);
led_bl_power_off(priv);
- for (i = 0; i < priv->nb_leds; i++)
+ for (i = 0; i < priv->nb_leds; i++) {
+ mutex_lock(&priv->leds[i]->led_access);
led_sysfs_enable(priv->leds[i]);
+ mutex_unlock(&priv->leds[i]->led_access);
+ }
}
static const struct of_device_id led_bl_of_match[] = {
--
2.34.1
2
1

09 May '25
From: Qu Huang <qu.huang(a)linux.dev>
stable inclusion
from stable-v4.19.279
commit 5a3fb3b745af0ce46ec2e0c8e507bae45b937334
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IC5DF7
CVE: CVE-2023-53090
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit 4fc8fff378b2f2039f2a666d9f8c570f4e58352c ]
In the kfd_wait_on_events() function, the kfd_event_waiter structure is
allocated by alloc_event_waiters(), but the event field of the waiter
structure is not initialized; When copy_from_user() fails in the
kfd_wait_on_events() function, it will enter exception handling to
release the previously allocated memory of the waiter structure;
Due to the event field of the waiters structure being accessed
in the free_waiters() function, this results in illegal memory access
and system crash, here is the crash log:
localhost kernel: RIP: 0010:native_queued_spin_lock_slowpath+0x185/0x1e0
localhost kernel: RSP: 0018:ffffaa53c362bd60 EFLAGS: 00010082
localhost kernel: RAX: ff3d3d6bff4007cb RBX: 0000000000000282 RCX: 00000000002c0000
localhost kernel: RDX: ffff9e855eeacb80 RSI: 000000000000279c RDI: ffffe7088f6a21d0
localhost kernel: RBP: ffffe7088f6a21d0 R08: 00000000002c0000 R09: ffffaa53c362be64
localhost kernel: R10: ffffaa53c362bbd8 R11: 0000000000000001 R12: 0000000000000002
localhost kernel: R13: ffff9e7ead15d600 R14: 0000000000000000 R15: ffff9e7ead15d698
localhost kernel: FS: 0000152a3d111700(0000) GS:ffff9e855ee80000(0000) knlGS:0000000000000000
localhost kernel: CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
localhost kernel: CR2: 0000152938000010 CR3: 000000044d7a4000 CR4: 00000000003506e0
localhost kernel: Call Trace:
localhost kernel: _raw_spin_lock_irqsave+0x30/0x40
localhost kernel: remove_wait_queue+0x12/0x50
localhost kernel: kfd_wait_on_events+0x1b6/0x490 [hydcu]
localhost kernel: ? ftrace_graph_caller+0xa0/0xa0
localhost kernel: kfd_ioctl+0x38c/0x4a0 [hydcu]
localhost kernel: ? kfd_ioctl_set_trap_handler+0x70/0x70 [hydcu]
localhost kernel: ? kfd_ioctl_create_queue+0x5a0/0x5a0 [hydcu]
localhost kernel: ? ftrace_graph_caller+0xa0/0xa0
localhost kernel: __x64_sys_ioctl+0x8e/0xd0
localhost kernel: ? syscall_trace_enter.isra.18+0x143/0x1b0
localhost kernel: do_syscall_64+0x33/0x80
localhost kernel: entry_SYSCALL_64_after_hwframe+0x44/0xa9
localhost kernel: RIP: 0033:0x152a4dff68d7
Allocate the structure with kcalloc, and remove redundant 0-initialization
and a redundant loop condition check.
Signed-off-by: Qu Huang <qu.huang(a)linux.dev>
Signed-off-by: Felix Kuehling <Felix.Kuehling(a)amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling(a)amd.com>
Signed-off-by: Alex Deucher <alexander.deucher(a)amd.com>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Pu Lehui <pulehui(a)huawei.com>
---
drivers/gpu/drm/amd/amdkfd/kfd_events.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
index 892077377339..8f23192b6709 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c
@@ -529,16 +529,13 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events)
struct kfd_event_waiter *event_waiters;
uint32_t i;
- event_waiters = kmalloc_array(num_events,
- sizeof(struct kfd_event_waiter),
- GFP_KERNEL);
+ event_waiters = kcalloc(num_events, sizeof(struct kfd_event_waiter),
+ GFP_KERNEL);
if (!event_waiters)
return NULL;
- for (i = 0; (event_waiters) && (i < num_events) ; i++) {
+ for (i = 0; i < num_events; i++)
init_wait(&event_waiters[i].wait);
- event_waiters[i].activated = false;
- }
return event_waiters;
}
--
2.34.1
2
1
Fix CVE-2025-37830.
Henry Martin (1):
cpufreq: scmi: Fix null-ptr-deref in scmi_cpufreq_get_rate()
drivers/cpufreq/scmi-cpufreq.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
--
2.34.1
2
2

09 May '25
From: fuguiming <fuguiming(a)huawei.com>
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IC5K0L?from=project-issue
CVE: NA
--------------------------------
Add optical module type adaptation.
Add ethtool fec function.
Add NIC XDP PASS function.
Add QoS persistence.
Add NIC out-of-band VLAN configuration function.
Fix NIC bifur bugs.
Fix performance test bugs.
Fix NIC RX bugs.
Fix NIC VF bugs.
Fix the bug of exiting when probing NIC.
Fix bond bugs.
Fix the bug of MAC address configuration failure in OS 6.6.
Fix the bug of reading NIC status incorrectly.
Fix and add some statistics.
Signed-off-by: fuguiming <fuguiming(a)huawei.com>
---
drivers/net/ethernet/huawei/hinic3/Makefile | 1 +
drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c | 3 +-
drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c | 181 ++-
drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h | 1 +
drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h | 212 ---
drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h | 239 ---
drivers/net/ethernet/huawei/hinic3/comm_defs.h | 100 --
drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h | 103 --
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c | 38 +-
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h | 2 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c | 83 +-
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h | 1 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c | 29 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c | 22 +-
drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h | 1 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c | 4 +-
drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h | 185 ---
drivers/net/ethernet/huawei/hinic3/hinic3_common.h | 118 --
drivers/net/ethernet/huawei/hinic3/hinic3_crm.h | 16 +-
drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c | 298 ++--
drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c | 262 +--
drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h | 7 +-
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c | 247 ++-
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c | 459 +++---
drivers/net/ethernet/huawei/hinic3/hinic3_filter.c | 4 +-
drivers/net/ethernet/huawei/hinic3/hinic3_hw.h | 19 +
drivers/net/ethernet/huawei/hinic3/hinic3_irq.c | 39 +-
drivers/net/ethernet/huawei/hinic3/hinic3_lld.h | 205 ---
drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c | 833 +++++++++-
drivers/net/ethernet/huawei/hinic3/hinic3_main.c | 490 +++++-
drivers/net/ethernet/huawei/hinic3/hinic3_mt.h | 191 ++-
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c | 397 +++--
drivers/net/ethernet/huawei/hinic3/hinic3_nic.h | 49 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c | 557 +++++--
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h | 54 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c | 186 ++-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c | 10 +
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h | 112 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c | 105 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c | 50 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h | 2 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c | 2 +-
drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c | 15 +-
drivers/net/ethernet/huawei/hinic3/hinic3_profile.h | 4 +-
drivers/net/ethernet/huawei/hinic3/hinic3_rss.c | 137 +-
drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c | 41 +-
drivers/net/ethernet/huawei/hinic3/hinic3_rx.c | 311 +++-
drivers/net/ethernet/huawei/hinic3/hinic3_rx.h | 41 +-
drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h | 7 +-
drivers/net/ethernet/huawei/hinic3/hinic3_tx.c | 79 +-
drivers/net/ethernet/huawei/hinic3/hinic3_wq.h | 4 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c | 11 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c | 6 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h | 5 -
drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c | 1 -
drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c | 213 ++-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h | 18 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c | 3 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c | 14 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c | 42 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c | 79 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h | 7 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c | 155 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c | 115 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c | 85 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h | 31 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c | 40 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c | 1242 +++++++++++++-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c | 3 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c | 4 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c | 41 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c | 122 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h | 4 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h | 31 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c | 64 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h | 14 +-
drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c | 1 +
drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h | 4 +
.../include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h | 11 +-
drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h | 42 +-
drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h | 2 +
drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h | 4 +
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h | 70 +-
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h | 141 +-
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h | 5 +
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h | 88 +-
.../include/mpu/mpu_outband_ncsi_cmd_defs.h | 8 +
drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h | 4 +
drivers/net/ethernet/huawei/hinic3/include/vram_common.h | 25 +-
drivers/net/ethernet/huawei/hinic3/{mag_cmd.h => mag_mpu_cmd_defs.h} | 236 ++-
drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h | 27 -
drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h | 65 -
drivers/net/ethernet/huawei/hinic3/{hinic3_nic_cmd.h => nic_mpu_cmd.h} | 54 +-
drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h | 1440 +++++++++++++++++
drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h | 36 +
drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h | 28 +-
96 files changed, 8406 insertions(+), 2791 deletions(-)
delete mode 100644 drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/comm_defs.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/hinic3_common.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/hinic3_lld.h
rename drivers/net/ethernet/huawei/hinic3/{mag_cmd.h => mag_mpu_cmd_defs.h} (79%)
delete mode 100644 drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h
rename drivers/net/ethernet/huawei/hinic3/{hinic3_nic_cmd.h => nic_mpu_cmd.h} (77%)
create mode 100644 drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h
create mode 100644 drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h
diff --git a/drivers/net/ethernet/huawei/hinic3/Makefile b/drivers/net/ethernet/huawei/hinic3/Makefile
index 6f9ed3f..457c920 100644
--- a/drivers/net/ethernet/huawei/hinic3/Makefile
+++ b/drivers/net/ethernet/huawei/hinic3/Makefile
@@ -11,6 +11,7 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt/
ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/mpu/
ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/bond/
ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/vmsec/
+ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/bond/
obj-$(CONFIG_HINIC3) += hinic3.o
hinic3-objs := hw/hinic3_hwdev.o \
diff --git a/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c b/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c
index cc2e4b3..440fea6 100644
--- a/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_nic_cmdq.h"
#include "sw_cmdq_ops.h"
diff --git a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c
index e8c703b..dd0699b 100644
--- a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c
+++ b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c
@@ -9,6 +9,7 @@
#include <linux/net.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
+#include <linux/version.h>
#include "hinic3_lld.h"
#include "hinic3_srv_nic.h"
@@ -109,7 +110,8 @@ static struct hinic3_nic_dev *get_nic_dev_safe(struct net_device *ndev)
return netdev_priv(ndev);
}
-static u8 bond_get_slaves_bitmap(struct hinic3_bond_dev *bdev, struct bonding *bond)
+static u8 bond_get_slaves_bitmap(struct hinic3_bond_dev *bdev,
+ struct bonding *bond)
{
struct slave *slave = NULL;
struct list_head *iter = NULL;
@@ -203,7 +205,8 @@ static u8 bond_dev_track_port(struct hinic3_bond_dev *bdev,
bdev->tracker.netdev_state[port_id].tx_enabled = 0;
if (!bdev->ppf_hwdev)
bdev->ppf_hwdev = ppf_hwdev;
- pr_info("TRACK cnt: %d, slave_name(%s)\n", bdev->tracker.cnt, ndev->name);
+ pr_info("TRACK cnt: %d, slave_name(%s)\n",
+ bdev->tracker.cnt, ndev->name);
spin_unlock(&bdev->lock);
return port_id;
@@ -268,11 +271,16 @@ static void bond_master_event(struct hinic3_bond_dev *bdev,
queue_delayed_work(bdev->wq, &bdev->bond_work, 0);
}
-static struct hinic3_bond_dev *bond_get_bdev(const struct bonding *bond)
+static struct hinic3_bond_dev *bond_get_bdev(struct bonding *bond)
{
struct hinic3_bond_dev *bdev = NULL;
int bid;
+ if (!bond) {
+ pr_err("hinic3_bond: bond is NULL\n");
+ return NULL;
+ }
+
mutex_lock(&g_bond_mutex);
for (bid = BOND_FIRST_ID; bid <= BOND_MAX_ID; bid++) {
bdev = bond_mngr.bond_dev[bid];
@@ -283,38 +291,73 @@ static struct hinic3_bond_dev *bond_get_bdev(const struct bonding *bond)
mutex_unlock(&g_bond_mutex);
return bdev;
}
+
+ if (strncmp(bond->dev->name,
+ bdev->name, BOND_NAME_MAX_LEN) == 0) {
+ bdev->bond = bond;
+ return bdev;
+ }
}
mutex_unlock(&g_bond_mutex);
return NULL;
}
-static void bond_handle_rtnl_event(struct net_device *ndev)
+static struct bonding *get_bonding_by_netdev(struct net_device *ndev)
{
- struct hinic3_bond_dev *bdev = NULL;
struct bonding *bond = NULL;
struct slave *slave = NULL;
if (netif_is_bond_master(ndev)) {
bond = netdev_priv(ndev);
- bdev = bond_get_bdev(bond);
} else if (netif_is_bond_slave(ndev)) {
- /*lint -e(160) */
slave = bond_slave_get_rtnl(ndev);
if (slave) {
bond = bond_get_bond_by_slave(slave);
- bdev = bond_get_bdev(bond);
}
}
- if (!bond || !bdev)
+ return bond;
+}
+
+bool hinic3_is_bond_dev_status_actived(struct net_device *ndev)
+{
+ struct hinic3_bond_dev *bdev = NULL;
+ struct bonding *bond = NULL;
+
+ if (!ndev) {
+ pr_err("hinic3_bond: netdev is NULL\n");
+ return false;
+ }
+
+ bond = get_bonding_by_netdev(ndev);
+ bdev = bond_get_bdev(bond);
+ if (!bdev)
+ return false;
+
+ return bdev->status == BOND_DEV_STATUS_ACTIVATED;
+}
+EXPORT_SYMBOL(hinic3_is_bond_dev_status_actived);
+/*lint +e580 +e546*/
+
+static void bond_handle_rtnl_event(struct net_device *ndev)
+{
+ struct hinic3_bond_dev *bdev = NULL;
+ struct bonding *bond = NULL;
+ struct slave *slave = NULL;
+
+ bond = get_bonding_by_netdev(ndev);
+ bdev = bond_get_bdev(bond);
+ if (!bdev)
return;
bond_update_attr(bdev, bond);
- if (slave)
+ if (netif_is_bond_slave(ndev)) {
+ slave = bond_slave_get_rtnl(ndev);
bond_slave_event(bdev, slave);
- else
+ } else {
bond_master_event(bdev, bond);
+ }
}
static void bond_rtnl_data_ready(struct sock *sk)
@@ -368,7 +411,8 @@ static int bond_enable_netdev_event(void)
(*rtnl_sock)->sk->sk_data_ready = bond_rtnl_data_ready;
(*rtnl_sock)->sk->sk_allocation = GFP_KERNEL;
- err = kernel_bind(*rtnl_sock, (struct sockaddr *)(u8 *)&addr, sizeof(addr));
+ err = kernel_bind(*rtnl_sock, (struct sockaddr *)(u8 *)&addr,
+ sizeof(addr));
if (err) {
pr_err("hinic3_bond: Couldn't bind rtnl socket.\n");
sock_release(*rtnl_sock);
@@ -387,7 +431,7 @@ static void bond_disable_netdev_event(void)
static int bond_send_upcmd(struct hinic3_bond_dev *bdev, struct bond_attr *attr,
u8 cmd_type)
{
- int err, len;
+ int err, ret, len;
struct hinic3_bond_cmd cmd = {0};
u16 out_size = sizeof(cmd);
@@ -403,7 +447,9 @@ static int bond_send_upcmd(struct hinic3_bond_dev *bdev, struct bond_attr *attr,
len = sizeof(cmd.bond_name);
if (cmd_type == MPU_CMD_BOND_CREATE) {
- strscpy(cmd.bond_name, bdev->name, len);
+ ret = strscpy(cmd.bond_name, bdev->name, len);
+ if (ret < 0)
+ pr_err("strscpy bond name failed\n");
cmd.bond_name[sizeof(cmd.bond_name) - 1] = '\0';
}
@@ -478,7 +524,11 @@ static void bond_update_slave_info(struct hinic3_bond_dev *bdev,
continue;
}
+ if (!bdev->tracker.ndev[i])
+ continue;
+
bond_pf_bitmap_set(bdev, i);
+
if (!bdev->tracker.netdev_state[i].tx_enabled)
continue;
@@ -516,6 +566,7 @@ static int bond_upcmd_config(struct hinic3_bond_dev *bdev,
attr->active_slaves,
attr->lacp_collect_slaves);
pr_info("bond_pf_bitmap: 0x%x\n", attr->bond_pf_bitmap);
+ pr_info("bond user_bitmap 0x%x\n", attr->user_bitmap);
err = bond_send_upcmd(bdev, attr, MPU_CMD_BOND_SET_ATTR);
if (!err)
@@ -544,8 +595,10 @@ static int bond_upcmd_activate(struct hinic3_bond_dev *bdev,
return err;
}
-static void bond_call_service_func(struct hinic3_bond_dev *bdev, struct bond_attr *attr,
- enum bond_service_proc_pos pos, int bond_status)
+static void bond_call_service_func(struct hinic3_bond_dev *bdev,
+ struct bond_attr *attr,
+ enum bond_service_proc_pos pos,
+ int bond_status)
{
int i;
@@ -560,6 +613,18 @@ static void bond_call_service_func(struct hinic3_bond_dev *bdev, struct bond_att
mutex_unlock(&g_bond_service_func_mutex);
}
+static u32 bond_get_user_bitmap(struct hinic3_bond_dev *bdev)
+{
+ u32 user_bitmap = 0;
+ u8 user;
+
+ for (user = HINIC3_BOND_USER_OVS; user < HINIC3_BOND_USER_NUM; user++) {
+ if (bdev->slot_used[user] == 1)
+ BITMAP_SET(user_bitmap, user);
+ }
+ return user_bitmap;
+}
+
static void bond_do_work(struct hinic3_bond_dev *bdev)
{
bool is_bonded = 0;
@@ -570,7 +635,7 @@ static void bond_do_work(struct hinic3_bond_dev *bdev)
is_bonded = bdev->tracker.is_bonded;
attr = bdev->new_attr;
spin_unlock(&bdev->lock);
- attr.user_bitmap = 0;
+ attr.user_bitmap = bond_get_user_bitmap(bdev);
/* is_bonded indicates whether bond should be activated. */
if (is_bonded && !bond_dev_is_activated(bdev)) {
@@ -597,15 +662,22 @@ static void bond_try_do_work(struct work_struct *work)
struct delayed_work *delayed_work = to_delayed_work(work);
struct hinic3_bond_dev *bdev =
container_of(delayed_work, struct hinic3_bond_dev, bond_work);
+ int status;
- if (g_bond_service_func[HINIC3_BOND_USER_ROCE] && bdev->tracker.cnt < MIN_BOND_SLAVE_CNT)
+ status = mutex_trylock(&g_bond_mutex);
+ if (status == 0) {
+ /* Delay 1 sec and retry */
queue_delayed_work(bdev->wq, &bdev->bond_work, HZ);
- else
+ } else {
bond_do_work(bdev);
+ mutex_unlock(&g_bond_mutex);
+ }
}
static int bond_dev_init(struct hinic3_bond_dev *bdev, const char *name)
{
+ int err = 0;
+
bdev->wq = create_singlethread_workqueue("hinic3_bond_wq");
if (!bdev->wq) {
pr_err("hinic3_bond: Failed to create workqueue\n");
@@ -614,7 +686,13 @@ static int bond_dev_init(struct hinic3_bond_dev *bdev, const char *name)
INIT_DELAYED_WORK(&bdev->bond_work, bond_try_do_work);
bdev->status = BOND_DEV_STATUS_IDLE;
- strscpy(bdev->name, name, sizeof(bdev->name));
+ err = strscpy(bdev->name, name, strlen(name));
+ if (err < 0) {
+ pr_err("hinic3_bond: Failed to init bond dev\n");
+ cancel_delayed_work_sync(&bdev->bond_work);
+ destroy_workqueue(bdev->wq);
+ return err;
+ }
spin_lock_init(&bdev->lock);
@@ -630,6 +708,7 @@ static int bond_dev_release(struct hinic3_bond_dev *bdev)
err = bond_upcmd_deactivate(bdev);
if (err) {
pr_err("hinic3_bond: Failed to deactivate dev\n");
+ mutex_unlock(&g_bond_mutex);
return err;
}
@@ -637,7 +716,8 @@ static int bond_dev_release(struct hinic3_bond_dev *bdev)
if (bond_mngr.bond_dev[i] == bdev) {
bond_mngr.bond_dev[i] = NULL;
bond_mngr.cnt--;
- pr_info("hinic3_bond: Free bond, id: %u mngr_cnt:%u\n", i, bond_mngr.cnt);
+ pr_info("hinic3_bond: Free bond, id: %u mngr_cnt:%u\n",
+ i, bond_mngr.cnt);
break;
}
}
@@ -694,7 +774,8 @@ static struct hinic3_bond_dev *bond_dev_alloc(const char *name)
bdev->bond_attr.bond_id = i;
bond_mngr.bond_dev[i] = bdev;
bond_mngr.cnt++;
- pr_info("hinic3_bond: Create bond dev, id:%u cnt:%u\n", i, bond_mngr.cnt);
+ pr_info("hinic3_bond: Create bond dev, id:%u cnt:%u\n",
+ i, bond_mngr.cnt);
break;
}
}
@@ -764,20 +845,28 @@ static struct hinic3_bond_dev *bond_dev_by_name(const char *name)
static void bond_dev_user_attach(struct hinic3_bond_dev *bdev,
enum hinic3_bond_user user)
{
+ u32 user_bitmap;
+
+ if (user < 0 || user >= HINIC3_BOND_USER_NUM)
+ return;
+
if (bdev->slot_used[user])
return;
bdev->slot_used[user] = 1;
- if (!kref_get_unless_zero(&bdev->ref))
+ if (!kref_get_unless_zero(&bdev->ref)) {
kref_init(&bdev->ref);
+ } else {
+ user_bitmap = bond_get_user_bitmap(bdev);
+ pr_info("hinic3_bond: user %u attach bond %s, user_bitmap %#x\n",
+ user, bdev->name, user_bitmap);
+ queue_delayed_work(bdev->wq, &bdev->bond_work, 0);
+ }
}
static void bond_dev_user_detach(struct hinic3_bond_dev *bdev,
enum hinic3_bond_user user, bool *freed)
{
- if (user < 0 || user >= HINIC3_BOND_USER_NUM)
- return;
-
if (bdev->slot_used[user]) {
bdev->slot_used[user] = 0;
if (kref_read(&bdev->ref) == 1)
@@ -790,16 +879,20 @@ static struct bonding *bond_get_knl_bonding(const char *name)
{
struct net_device *ndev_tmp = NULL;
+ rcu_read_lock();
for_each_netdev(&init_net, ndev_tmp) {
if (netif_is_bond_master(ndev_tmp) &&
- !strcmp(ndev_tmp->name, name))
+ !strcmp(ndev_tmp->name, name)) {
+ rcu_read_unlock();
return netdev_priv(ndev_tmp);
+ }
}
-
+ rcu_read_unlock();
return NULL;
}
-void hinic3_bond_set_user_bitmap(struct bond_attr *attr, enum hinic3_bond_user user)
+void hinic3_bond_set_user_bitmap(struct bond_attr *attr,
+ enum hinic3_bond_user user)
{
if (!BITMAP_JUDGE(attr->user_bitmap, user))
BITMAP_SET(attr->user_bitmap, user);
@@ -852,8 +945,9 @@ int hinic3_bond_detach(u16 bond_id, enum hinic3_bond_user user)
int err = 0;
bool lock_freed = false;
- if (bond_id < BOND_FIRST_ID || bond_id > BOND_MAX_ID) {
- pr_warn("hinic3_bond: Invalid bond id:%u to delete\n", bond_id);
+ if (!BOND_ID_IS_VALID(bond_id) || user >= HINIC3_BOND_USER_NUM) {
+ pr_warn("hinic3_bond: Invalid bond id or user, bond_id: %u, user: %d\n",
+ bond_id, user);
return -EINVAL;
}
@@ -861,7 +955,8 @@ int hinic3_bond_detach(u16 bond_id, enum hinic3_bond_user user)
if (!bond_mngr.bond_dev[bond_id])
err = -ENODEV;
else
- bond_dev_user_detach(bond_mngr.bond_dev[bond_id], user, &lock_freed);
+ bond_dev_user_detach(bond_mngr.bond_dev[bond_id],
+ user, &lock_freed);
if (!lock_freed)
mutex_unlock(&g_bond_mutex);
@@ -877,7 +972,8 @@ void hinic3_bond_clean_user(enum hinic3_bond_user user)
mutex_lock(&g_bond_mutex);
for (i = BOND_FIRST_ID; i <= BOND_MAX_ID; i++) {
if (bond_mngr.bond_dev[i]) {
- bond_dev_user_detach(bond_mngr.bond_dev[i], user, &lock_freed);
+ bond_dev_user_detach(bond_mngr.bond_dev[i],
+ user, &lock_freed);
if (lock_freed) {
mutex_lock(&g_bond_mutex);
lock_freed = false;
@@ -891,7 +987,7 @@ EXPORT_SYMBOL(hinic3_bond_clean_user);
int hinic3_bond_get_uplink_id(u16 bond_id, u32 *uplink_id)
{
- if (bond_id < BOND_FIRST_ID || bond_id > BOND_MAX_ID || !uplink_id) {
+ if (!BOND_ID_IS_VALID(bond_id) || !uplink_id) {
pr_warn("hinic3_bond: Invalid args, id: %u, uplink: %d\n",
bond_id, !!uplink_id);
return -EINVAL;
@@ -941,7 +1037,7 @@ int hinic3_bond_get_slaves(u16 bond_id, struct hinic3_bond_info_s *info)
int i;
int len;
- if (!info || bond_id < BOND_FIRST_ID || bond_id > BOND_MAX_ID) {
+ if (!info || !BOND_ID_IS_VALID(bond_id)) {
pr_warn("hinic3_bond: Invalid args, info: %d,id: %u\n",
!!info, bond_id);
return -EINVAL;
@@ -962,7 +1058,8 @@ int hinic3_bond_get_slaves(u16 bond_id, struct hinic3_bond_info_s *info)
for (i = 0; i < BOND_PORT_MAX_NUM; i++) {
if (BITMAP_JUDGE(info->slaves, i) && tracker->ndev[i]) {
len = sizeof(info->slaves_name[0]);
- strscpy(info->slaves_name[info->cnt], tracker->ndev[i]->name, len);
+ strscpy(info->slaves_name[info->cnt],
+ tracker->ndev[i]->name, len);
info->cnt++;
}
}
@@ -972,7 +1069,8 @@ int hinic3_bond_get_slaves(u16 bond_id, struct hinic3_bond_info_s *info)
}
EXPORT_SYMBOL(hinic3_bond_get_slaves);
-struct net_device *hinic3_bond_get_netdev_by_portid(const char *bond_name, u8 port_id)
+struct net_device *hinic3_bond_get_netdev_by_portid(const char *bond_name,
+ u8 port_id)
{
struct hinic3_bond_dev *bdev = NULL;
@@ -989,7 +1087,8 @@ struct net_device *hinic3_bond_get_netdev_by_portid(const char *bond_name, u8 po
}
EXPORT_SYMBOL(hinic3_bond_get_netdev_by_portid);
-int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos, u16 channel)
+int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos,
+ u16 channel)
{
struct comm_cmd_hw_bond_infos bond_infos;
u16 out_size = sizeof(bond_infos);
@@ -1002,7 +1101,8 @@ int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos, u1
bond_infos.infos.bond_id = infos->bond_id;
- err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_COMM, COMM_MGMT_CMD_GET_HW_BOND,
+ err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_COMM,
+ COMM_MGMT_CMD_GET_HW_BOND,
&bond_infos, sizeof(bond_infos),
&bond_infos, &out_size, 0, channel);
if (bond_infos.head.status || err || !out_size) {
@@ -1018,7 +1118,8 @@ int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos, u1
}
EXPORT_SYMBOL(hinic3_get_hw_bond_infos);
-int hinic3_get_bond_tracker_by_name(const char *name, struct bond_tracker *tracker)
+int hinic3_get_bond_tracker_by_name(const char *name,
+ struct bond_tracker *tracker)
{
struct hinic3_bond_dev *bdev = NULL;
int i;
diff --git a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h
index 024de95..5ab36f7 100644
--- a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h
+++ b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h
@@ -82,6 +82,7 @@ struct hinic3_bond_cmd {
char bond_name[16];
};
+bool hinic3_is_bond_dev_status_actived(struct net_device *ndev);
void hinic3_bond_set_user_bitmap(struct bond_attr *attr, enum hinic3_bond_user user);
int hinic3_bond_attach(const char *name, enum hinic3_bond_user user, u16 *bond_id);
int hinic3_bond_detach(u16 bond_id, enum hinic3_bond_user user);
diff --git a/drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h b/drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h
deleted file mode 100644
index 557f326..0000000
--- a/drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2016-2022. All rights reserved.
- * File name: Cfg_mgt_comm_pub.h
- * Version No.: Draft
- * Generation date: 2016 year 05 month 07 day
- * Latest modification:
- * Function description: Header file for communication between the: Host and FW
- * Function list:
- * Modification history:
- * 1. Date: 2016 May 07
- * Modify content: Create a file.
- */
-#ifndef CFG_MGT_COMM_PUB_H
-#define CFG_MGT_COMM_PUB_H
-
-#include "mgmt_msg_base.h"
-
-enum servic_bit_define {
- SERVICE_BIT_NIC = 0,
- SERVICE_BIT_ROCE = 1,
- SERVICE_BIT_VBS = 2,
- SERVICE_BIT_TOE = 3,
- SERVICE_BIT_IPSEC = 4,
- SERVICE_BIT_FC = 5,
- SERVICE_BIT_VIRTIO = 6,
- SERVICE_BIT_OVS = 7,
- SERVICE_BIT_NVME = 8,
- SERVICE_BIT_ROCEAA = 9,
- SERVICE_BIT_CURRENET = 10,
- SERVICE_BIT_PPA = 11,
- SERVICE_BIT_MIGRATE = 12,
- SERVICE_BIT_MAX
-};
-
-#define CFG_SERVICE_MASK_NIC (0x1 << SERVICE_BIT_NIC)
-#define CFG_SERVICE_MASK_ROCE (0x1 << SERVICE_BIT_ROCE)
-#define CFG_SERVICE_MASK_VBS (0x1 << SERVICE_BIT_VBS)
-#define CFG_SERVICE_MASK_TOE (0x1 << SERVICE_BIT_TOE)
-#define CFG_SERVICE_MASK_IPSEC (0x1 << SERVICE_BIT_IPSEC)
-#define CFG_SERVICE_MASK_FC (0x1 << SERVICE_BIT_FC)
-#define CFG_SERVICE_MASK_VIRTIO (0x1 << SERVICE_BIT_VIRTIO)
-#define CFG_SERVICE_MASK_OVS (0x1 << SERVICE_BIT_OVS)
-#define CFG_SERVICE_MASK_NVME (0x1 << SERVICE_BIT_NVME)
-#define CFG_SERVICE_MASK_ROCEAA (0x1 << SERVICE_BIT_ROCEAA)
-#define CFG_SERVICE_MASK_CURRENET (0x1 << SERVICE_BIT_CURRENET)
-#define CFG_SERVICE_MASK_PPA (0x1 << SERVICE_BIT_PPA)
-#define CFG_SERVICE_MASK_MIGRATE (0x1 << SERVICE_BIT_MIGRATE)
-
-/* Definition of the scenario ID in the cfg_data, which is used for SML memory allocation. */
-enum scenes_id_define {
- SCENES_ID_FPGA_ETH = 0,
- SCENES_ID_FPGA_TIOE = 1, /* Discarded */
- SCENES_ID_STORAGE_ROCEAA_2x100 = 2,
- SCENES_ID_STORAGE_ROCEAA_4x25 = 3,
- SCENES_ID_CLOUD = 4,
- SCENES_ID_FC = 5,
- SCENES_ID_STORAGE_ROCE = 6,
- SCENES_ID_COMPUTE_ROCE = 7,
- SCENES_ID_STORAGE_TOE = 8,
- SCENES_ID_MAX
-};
-
-/* struct cfg_cmd_dev_cap.sf_svc_attr */
-enum {
- SF_SVC_FT_BIT = (1 << 0),
- SF_SVC_RDMA_BIT = (1 << 1),
-};
-
-enum cfg_cmd {
- CFG_CMD_GET_DEV_CAP = 0,
- CFG_CMD_GET_HOST_TIMER = 1,
-};
-
-struct cfg_cmd_host_timer {
- struct mgmt_msg_head head;
-
- u8 host_id;
- u8 rsvd1;
-
- u8 timer_pf_num;
- u8 timer_pf_id_start;
- u16 timer_vf_num;
- u16 timer_vf_id_start;
- u32 rsvd2[8];
-};
-
-struct cfg_cmd_dev_cap {
- struct mgmt_msg_head head;
-
- u16 func_id;
- u16 rsvd1;
-
- /* Public resources */
- u8 host_id;
- u8 ep_id;
- u8 er_id;
- u8 port_id;
-
- u16 host_total_func;
- u8 host_pf_num;
- u8 pf_id_start;
- u16 host_vf_num;
- u16 vf_id_start;
- u8 host_oq_id_mask_val;
- u8 timer_en;
- u8 host_valid_bitmap;
- u8 rsvd_host;
-
- u16 svc_cap_en;
- u16 max_vf;
- u8 flexq_en;
- u8 valid_cos_bitmap;
- /* Reserved for func_valid_cos_bitmap */
- u8 port_cos_valid_bitmap;
- u8 rsvd_func1;
- u32 rsvd_func2;
-
- u8 sf_svc_attr;
- u8 func_sf_en;
- u8 lb_mode;
- u8 smf_pg;
-
- u32 max_conn_num;
- u16 max_stick2cache_num;
- u16 max_bfilter_start_addr;
- u16 bfilter_len;
- u16 hash_bucket_num;
-
- /* shared resource */
- u8 host_sf_en;
- u8 master_host_id;
- u8 srv_multi_host_mode;
- u8 virtio_vq_size;
-
- u32 rsvd_func3[5];
-
- /* l2nic */
- u16 nic_max_sq_id;
- u16 nic_max_rq_id;
- u16 nic_default_num_queues;
- u16 rsvd1_nic;
- u32 rsvd2_nic[2];
-
- /* RoCE */
- u32 roce_max_qp;
- u32 roce_max_cq;
- u32 roce_max_srq;
- u32 roce_max_mpt;
- u32 roce_max_drc_qp;
-
- u32 roce_cmtt_cl_start;
- u32 roce_cmtt_cl_end;
- u32 roce_cmtt_cl_size;
-
- u32 roce_dmtt_cl_start;
- u32 roce_dmtt_cl_end;
- u32 roce_dmtt_cl_size;
-
- u32 roce_wqe_cl_start;
- u32 roce_wqe_cl_end;
- u32 roce_wqe_cl_size;
- u8 roce_srq_container_mode;
- u8 rsvd_roce1[3];
- u32 rsvd_roce2[5];
-
- /* IPsec */
- u32 ipsec_max_sactx;
- u16 ipsec_max_cq;
- u16 rsvd_ipsec1;
- u32 rsvd_ipsec[2];
-
- /* OVS */
- u32 ovs_max_qpc;
- u32 rsvd_ovs1[3];
-
- /* ToE */
- u32 toe_max_pctx;
- u32 toe_max_cq;
- u16 toe_max_srq;
- u16 toe_srq_id_start;
- u16 toe_max_mpt;
- u16 toe_max_cctxt;
- u32 rsvd_toe[2];
-
- /* FC */
- u32 fc_max_pctx;
- u32 fc_max_scq;
- u32 fc_max_srq;
-
- u32 fc_max_cctx;
- u32 fc_cctx_id_start;
-
- u8 fc_vp_id_start;
- u8 fc_vp_id_end;
- u8 rsvd_fc1[2];
- u32 rsvd_fc2[5];
-
- /* VBS */
- u16 vbs_max_volq;
- u16 rsvd0_vbs;
- u32 rsvd1_vbs[3];
-
- u16 fake_vf_start_id;
- u16 fake_vf_num;
- u32 fake_vf_max_pctx;
- u16 fake_vf_bfilter_start_addr;
- u16 fake_vf_bfilter_len;
- u32 rsvd_glb[8];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h b/drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h
deleted file mode 100644
index 59e20a1..0000000
--- a/drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
- ******************************************************************************
- File Name : comm_cmdq_intf.h
- Version : Initial Draft
- Description : common command queue interface
- Function List :
- History :
- Modification: Created file
-
-******************************************************************************/
-
-#ifndef COMM_CMDQ_INTF_H
-#define COMM_CMDQ_INTF_H
-
-/* Cmdq ack type */
-enum hinic3_ack_type {
- HINIC3_ACK_TYPE_CMDQ,
- HINIC3_ACK_TYPE_SHARE_CQN,
- HINIC3_ACK_TYPE_APP_CQN,
-
- HINIC3_MOD_ACK_MAX = 15,
-};
-
-/* Defines the queue type of the set arm bit. */
-enum {
- SET_ARM_BIT_FOR_CMDQ = 0,
- SET_ARM_BIT_FOR_L2NIC_SQ,
- SET_ARM_BIT_FOR_L2NIC_RQ,
- SET_ARM_BIT_TYPE_NUM
-};
-
-/* Defines the type. Each function supports a maximum of eight CMDQ types. */
-enum {
- CMDQ_0 = 0,
- CMDQ_1 = 1, /* dedicated and non-blocking queues */
- CMDQ_NUM
-};
-
-/* *******************cmd common command data structure ************************ */
-// Func->ucode, which is used to set arm bit data,
-// The microcode needs to perform big-endian conversion.
-struct comm_info_ucode_set_arm_bit {
- u32 q_type;
- u32 q_id;
-};
-
-/* *******************WQE data structure ************************ */
-union cmdq_wqe_cs_dw0 {
- struct {
- u32 err_status : 29;
- u32 error_code : 2;
- u32 rsvd : 1;
- } bs;
- u32 val;
-};
-
-union cmdq_wqe_cs_dw1 {
- // This structure is used when the driver writes the wqe.
- struct {
- u32 token : 16; // [15:0]
- u32 cmd : 8; // [23:16]
- u32 mod : 5; // [28:24]
- u32 ack_type : 2; // [30:29]
- u32 obit : 1; // [31]
- } drv_wr;
-
- /* The uCode writes back the structure of the CS_DW1. */
- /* The driver reads and uses the structure. */
- struct {
- u32 mod : 5; // [4:0]
- u32 ack_type : 3; // [7:5]
- u32 cmd : 8; // [15:8]
- u32 arm : 1; // [16]
- u32 rsvd : 14; // [30:17]
- u32 obit : 1; // [31]
- } wb;
- u32 val;
-};
-
-/* CmdQ BD information or write back buffer information */
-struct cmdq_sge {
- u32 pa_h; // Upper 32 bits of the physical address
- u32 pa_l; // Upper 32 bits of the physical address
- u32 len; // Invalid bit[31].
- u32 resv;
-};
-
-/* Ctrls section definition of WQE */
-struct cmdq_wqe_ctrls {
- union {
- struct {
- u32 bdsl : 8; // [7:0]
- u32 drvsl : 2; // [9:8]
- u32 rsv : 4; // [13:10]
- u32 wf : 1; // [14]
- u32 cf : 1; // [15]
- u32 tsl : 5; // [20:16]
- u32 va : 1; // [21]
- u32 df : 1; // [22]
- u32 cr : 1; // [23]
- u32 difsl : 3; // [26:24]
- u32 csl : 2; // [28:27]
- u32 ctrlsl : 2; // [30:29]
- u32 obit : 1; // [31]
- } bs;
- u32 val;
- } header;
- u32 qsf;
-};
-
-/* Complete section definition of WQE */
-struct cmdq_wqe_cs {
- union cmdq_wqe_cs_dw0 dw0;
- union cmdq_wqe_cs_dw1 dw1;
- union {
- struct cmdq_sge sge;
- u32 dw2_5[4];
- } ack;
-};
-
-/* Inline header in WQE inline, describing the length of inline data */
-union cmdq_wqe_inline_header {
- struct {
- u32 buf_len : 11; // [10:0] inline data len
- u32 rsv : 21; // [31:11]
- } bs;
- u32 val;
-};
-
-/* Definition of buffer descriptor section in WQE */
-union cmdq_wqe_bds {
- struct {
- struct cmdq_sge bds_sge;
- u32 rsvd[4]; /* Zwy is used to transfer the virtual address of the buffer. */
- } lcmd; /* Long command, non-inline, and SGE describe the buffer information. */
-};
-
-/* Definition of CMDQ WQE */
-/* (long cmd, 64B)
- * +----------------------------------------+
- * | ctrl section(8B) |
- * +----------------------------------------+
- * | |
- * | complete section(24B) |
- * | |
- * +----------------------------------------+
- * | |
- * | buffer descriptor section(16B) |
- * | |
- * +----------------------------------------+
- * | driver section(16B) |
- * +----------------------------------------+
- *
- *
- * (middle cmd, 128B)
- * +----------------------------------------+
- * | ctrl section(8B) |
- * +----------------------------------------+
- * | |
- * | complete section(24B) |
- * | |
- * +----------------------------------------+
- * | |
- * | buffer descriptor section(88B) |
- * | |
- * +----------------------------------------+
- * | driver section(8B) |
- * +----------------------------------------+
- *
- *
- * (short cmd, 64B)
- * +----------------------------------------+
- * | ctrl section(8B) |
- * +----------------------------------------+
- * | |
- * | complete section(24B) |
- * | |
- * +----------------------------------------+
- * | |
- * | buffer descriptor section(24B) |
- * | |
- * +----------------------------------------+
- * | driver section(8B) |
- * +----------------------------------------+
- */
-struct cmdq_wqe {
- struct cmdq_wqe_ctrls ctrls;
- struct cmdq_wqe_cs cs;
- union cmdq_wqe_bds bds;
-};
-
-/* Definition of ctrls section in inline WQE */
-struct cmdq_wqe_ctrls_inline {
- union {
- struct {
- u32 bdsl : 8; // [7:0]
- u32 drvsl : 2; // [9:8]
- u32 rsv : 4; // [13:10]
- u32 wf : 1; // [14]
- u32 cf : 1; // [15]
- u32 tsl : 5; // [20:16]
- u32 va : 1; // [21]
- u32 df : 1; // [22]
- u32 cr : 1; // [23]
- u32 difsl : 3; // [26:24]
- u32 csl : 2; // [28:27]
- u32 ctrlsl : 2; // [30:29]
- u32 obit : 1; // [31]
- } bs;
- u32 val;
- } header;
- u32 qsf;
- u64 db;
-};
-
-/* Buffer descriptor section definition of WQE */
-union cmdq_wqe_bds_inline {
- struct {
- union cmdq_wqe_inline_header header;
- u32 rsvd;
- u8 data_inline[80];
- } mcmd; /* Middle command, inline mode */
-
- struct {
- union cmdq_wqe_inline_header header;
- u32 rsvd;
- u8 data_inline[16];
- } scmd; /* Short command, inline mode */
-};
-
-struct cmdq_wqe_inline {
- struct cmdq_wqe_ctrls_inline ctrls;
- struct cmdq_wqe_cs cs;
- union cmdq_wqe_bds_inline bds;
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/comm_defs.h b/drivers/net/ethernet/huawei/hinic3/comm_defs.h
deleted file mode 100644
index c5b1913..0000000
--- a/drivers/net/ethernet/huawei/hinic3/comm_defs.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
- * File Name : comm_defs.h
- * Version : Initial Draft
- * Description : common definitions
- * Function List :
- * History :
- * Modification: Created file
- */
-
-#ifndef COMM_DEFS_H
-#define COMM_DEFS_H
-
-/* CMDQ MODULE_TYPE */
-enum hinic3_mod_type {
- HINIC3_MOD_COMM = 0, /* HW communication module */
- HINIC3_MOD_L2NIC = 1, /* L2NIC module */
- HINIC3_MOD_ROCE = 2,
- HINIC3_MOD_PLOG = 3,
- HINIC3_MOD_TOE = 4,
- HINIC3_MOD_FLR = 5,
- HINIC3_MOD_RSVD1 = 6,
- HINIC3_MOD_CFGM = 7, /* Configuration module */
- HINIC3_MOD_CQM = 8,
- HINIC3_MOD_VMSEC = 9,
- COMM_MOD_FC = 10,
- HINIC3_MOD_OVS = 11,
- HINIC3_MOD_DSW = 12,
- HINIC3_MOD_MIGRATE = 13,
- HINIC3_MOD_HILINK = 14,
- HINIC3_MOD_CRYPT = 15, /* secure crypto module */
- HINIC3_MOD_VIO = 16,
- HINIC3_MOD_IMU = 17,
- HINIC3_MOD_DFT = 18, /* DFT */
- HINIC3_MOD_HW_MAX = 19, /* hardware max module id */
- /* Software module id, for PF/VF and multi-host */
- HINIC3_MOD_SW_FUNC = 20,
- HINIC3_MOD_MAX,
-};
-
-/* func reset的flag ,用于指示清理哪种资源 */
-enum func_reset_flag {
- RES_TYPE_FLUSH_BIT = 0,
- RES_TYPE_MQM,
- RES_TYPE_SMF,
- RES_TYPE_PF_BW_CFG,
-
- RES_TYPE_COMM = 10,
- RES_TYPE_COMM_MGMT_CH, /* clear mbox and aeq, The RES_TYPE_COMM bit must be set */
- RES_TYPE_COMM_CMD_CH, /* clear cmdq and ceq, The RES_TYPE_COMM bit must be set */
- RES_TYPE_NIC,
- RES_TYPE_OVS,
- RES_TYPE_VBS,
- RES_TYPE_ROCE,
- RES_TYPE_FC,
- RES_TYPE_TOE,
- RES_TYPE_IPSEC,
- RES_TYPE_MAX,
-};
-
-#define HINIC3_COMM_RES \
- ((1 << RES_TYPE_COMM) | (1 << RES_TYPE_COMM_CMD_CH) | \
- (1 << RES_TYPE_FLUSH_BIT) | (1 << RES_TYPE_MQM) | \
- (1 << RES_TYPE_SMF) | (1 << RES_TYPE_PF_BW_CFG))
-
-#define HINIC3_NIC_RES BIT(RES_TYPE_NIC)
-#define HINIC3_OVS_RES BIT(RES_TYPE_OVS)
-#define HINIC3_VBS_RES BIT(RES_TYPE_VBS)
-#define HINIC3_ROCE_RES BIT(RES_TYPE_ROCE)
-#define HINIC3_FC_RES BIT(RES_TYPE_FC)
-#define HINIC3_TOE_RES BIT(RES_TYPE_TOE)
-#define HINIC3_IPSEC_RES BIT(RES_TYPE_IPSEC)
-
-/* MODE OVS、NIC、UNKNOWN */
-#define HINIC3_WORK_MODE_OVS 0
-#define HINIC3_WORK_MODE_UNKNOWN 1
-#define HINIC3_WORK_MODE_NIC 2
-
-#define DEVICE_TYPE_L2NIC 0
-#define DEVICE_TYPE_NVME 1
-#define DEVICE_TYPE_VIRTIO_NET 2
-#define DEVICE_TYPE_VIRTIO_BLK 3
-#define DEVICE_TYPE_VIRTIO_VSOCK 4
-#define DEVICE_TYPE_VIRTIO_NET_TRANSITION 5
-#define DEVICE_TYPE_VIRTIO_BLK_TRANSITION 6
-#define DEVICE_TYPE_VIRTIO_SCSI_TRANSITION 7
-#define DEVICE_TYPE_VIRTIO_HPC 8
-
-/* Common header control information of the COMM message
- * interaction command word between the driver and PF
- */
-struct comm_info_head {
- u8 status;
- u8 version;
- u8 rep_aeq_num;
- u8 rsvd[5];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h b/drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h
deleted file mode 100644
index ae998cf..0000000
--- a/drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
- * File Name : comm_msg_intf.h
- * Version : Initial Draft
- * Created : 2021/6/28
- * Last Modified :
- * Description : COMM Command interfaces between Driver and MPU
- * Function List :
- */
-
-#ifndef COMM_MSG_INTF_H
-#define COMM_MSG_INTF_H
-
-#include "comm_defs.h"
-#include "mgmt_msg_base.h"
-#include "mpu_cmd_base_defs.h"
-#include "mpu_inband_cmd_defs.h"
-
-struct spu_cmd_freq_operation {
- struct comm_info_head head;
-
- u8 op_code; /* 0: get 1: set 2: check */
- u8 rsvd[3];
- u32 freq;
-};
-
-struct spu_cmd_power_operation {
- struct comm_info_head head;
-
- u8 op_code; /* 0: get 1: set 2: init */
- u8 slave_addr;
- u8 cmd_id;
- u8 size;
- u32 value;
-};
-
-struct spu_cmd_tsensor_operation {
- struct comm_info_head head;
-
- u8 op_code;
- u8 rsvd[3];
- s16 fabric_tsensor_temp_avg;
- s16 fabric_tsensor_temp;
- s16 sys_tsensor_temp_avg;
- s16 sys_tsensor_temp;
-};
-
-enum cfg_msix_operation {
- CFG_MSIX_OPERATION_FREE = 0,
- CFG_MSIX_OPERATION_ALLOC = 1,
-};
-
-struct comm_cmd_ffm_info {
- struct mgmt_msg_head head;
-
- u8 node_id;
- /* error level of the interrupt source */
- u8 err_level;
- /* Classification by interrupt source properties */
- u16 err_type;
- u32 err_csr_addr;
- u32 err_csr_value;
- u32 rsvd1;
-};
-
-struct hinic3_cmd_update_firmware {
- struct mgmt_msg_head msg_head;
-
- struct {
- u32 sl : 1;
- u32 sf : 1;
- u32 flag : 1;
- u32 bit_signed : 1;
- u32 reserved : 12;
- u32 fragment_len : 16;
- } ctl_info;
-
- struct {
- u32 section_crc;
- u32 section_type;
- } section_info;
-
- u32 total_len;
- u32 section_len;
- u32 section_version;
- u32 section_offset;
- u32 data[384];
-};
-
-struct hinic3_cmd_activate_firmware {
- struct mgmt_msg_head msg_head;
- u8 index; /* 0 ~ 7 */
- u8 data[7];
-};
-
-struct hinic3_cmd_switch_config {
- struct mgmt_msg_head msg_head;
- u8 index; /* 0 ~ 7 */
- u8 data[7];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c
index 8c95032..aad3a97 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c
@@ -28,6 +28,8 @@
#include "cqm_npu_cmd.h"
#include "cqm_npu_cmd_defs.h"
+#include "vram_common.h"
+
static void cqm_bat_fill_cla_common_gpa(struct tag_cqm_handle *cqm_handle,
struct tag_cqm_cla_table *cla_table,
struct tag_cqm_bat_entry_standerd *bat_entry_standerd)
@@ -366,6 +368,13 @@ static s32 cqm_bat_update_cmd(struct tag_cqm_handle *cqm_handle, struct tag_cqm_
struct hinic3_hwdev *handle = cqm_handle->ex_handle;
struct tag_cqm_cmdq_bat_update *bat_update_cmd = NULL;
s32 ret = CQM_FAIL;
+ int is_in_kexec;
+
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ cqm_info(handle->dev_hdl, "Skip updating the cqm_bat to chip during kexec!\n");
+ return CQM_SUCCESS;
+ }
bat_update_cmd = (struct tag_cqm_cmdq_bat_update *)(buf_in->buf);
bat_update_cmd->offset = 0;
@@ -768,8 +777,10 @@ static s32 cqm_cla_xyz_lvl1(struct tag_cqm_handle *cqm_handle,
/* Applying for CLA_Z_BUF Space */
cla_z_buf = &cla_table->cla_z_buf;
cla_z_buf->buf_size = trunk_size;
- cla_z_buf->buf_number = (ALIGN(cla_table->max_buffer_size, trunk_size)) / trunk_size;
- cla_z_buf->page_number = cla_z_buf->buf_number << cla_table->trunk_order;
+ cla_z_buf->buf_number =
+ (ALIGN(cla_table->max_buffer_size, trunk_size)) / trunk_size;
+ cla_z_buf->page_number = cla_z_buf->buf_number <<
+ cla_table->trunk_order;
/* All buffer space must be statically allocated. */
if (cla_table->alloc_static) {
@@ -840,6 +851,7 @@ static s32 cqm_cla_xyz_lvl2_xyz_apply(struct tag_cqm_handle *cqm_handle,
cla_x_buf->buf_size = trunk_size;
cla_x_buf->buf_number = 1;
cla_x_buf->page_number = cla_x_buf->buf_number << cla_table->trunk_order;
+ cla_x_buf->buf_info.use_vram = get_use_vram_flag();
ret = cqm_buf_alloc(cqm_handle, cla_x_buf, false);
if (ret != CQM_SUCCESS)
return CQM_FAIL;
@@ -869,14 +881,20 @@ static s32 cqm_cla_xyz_vram_name_init(struct tag_cqm_cla_table *cla_table,
cla_x_buf = &cla_table->cla_x_buf;
cla_z_buf = &cla_table->cla_z_buf;
cla_y_buf = &cla_table->cla_y_buf;
+ cla_x_buf->buf_info.use_vram = get_use_vram_flag();
snprintf(cla_x_buf->buf_info.buf_vram_name,
- VRAM_NAME_MAX_LEN - 1, "%s%s", cla_table->name, VRAM_CQM_CLA_COORD_X);
+ VRAM_NAME_MAX_LEN, "%s%s", cla_table->name,
+ VRAM_CQM_CLA_COORD_X);
+ cla_y_buf->buf_info.use_vram = get_use_vram_flag();
snprintf(cla_y_buf->buf_info.buf_vram_name,
- VRAM_NAME_MAX_LEN - 1, "%s%s", cla_table->name, VRAM_CQM_CLA_COORD_Y);
+ VRAM_NAME_MAX_LEN, "%s%s", cla_table->name,
+ VRAM_CQM_CLA_COORD_Y);
+ cla_z_buf->buf_info.use_vram = get_use_vram_flag();
snprintf(cla_z_buf->buf_info.buf_vram_name,
- VRAM_NAME_MAX_LEN - 1, "%s%s", cla_table->name, VRAM_CQM_CLA_COORD_Z);
+ VRAM_NAME_MAX_LEN, "%s%s", cla_table->name,
+ VRAM_CQM_CLA_COORD_Z);
return CQM_SUCCESS;
}
@@ -1188,7 +1206,7 @@ static void cqm_cla_init_entry_extern(struct tag_cqm_handle *cqm_handle,
* exceed 128 x 4 KB. Otherwise, clearing the timer buffer of
* the function is complex.
*/
- cla_table->trunk_order = CQM_4K_PAGE_ORDER;
+ cla_table->trunk_order = CQM_8K_PAGE_ORDER;
cla_table->max_buffer_size = capability->timer_number *
capability->timer_basic_size;
cla_table->obj_size = capability->timer_basic_size;
@@ -1237,7 +1255,7 @@ static s32 cqm_cla_init_entry_condition(struct tag_cqm_handle *cqm_handle, u32 e
memcpy(cla_table_timer, cla_table, sizeof(struct tag_cqm_cla_table));
snprintf(cla_table_timer->name,
- VRAM_NAME_MAX_LEN - 1, "%s%s%01u", cla_table->name,
+ VRAM_NAME_MAX_LEN, "%s%s%01u", cla_table->name,
VRAM_CQM_CLA_SMF_BASE, i);
if (cqm_cla_xyz(cqm_handle, cla_table_timer) ==
@@ -1268,7 +1286,7 @@ static s32 cqm_cla_init_entry(struct tag_cqm_handle *cqm_handle,
for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
cla_table = &bat_table->entry[i];
cla_table->type = bat_table->bat_entry_type[i];
- snprintf(cla_table->name, VRAM_NAME_MAX_LEN - 1,
+ snprintf(cla_table->name, VRAM_NAME_MAX_LEN,
"%s%s%s%02u", cqm_handle->name, VRAM_CQM_CLA_BASE,
VRAM_CQM_CLA_TYPE_BASE, cla_table->type);
@@ -1485,11 +1503,11 @@ static s32 cqm_cla_update(struct tag_cqm_handle *cqm_handle,
spu_en = 0;
pa = ((buf_node_parent->pa + (child_index * sizeof(dma_addr_t))) |
- (u32)spu_en);
+ spu_en);
cmd.gpa_h = CQM_ADDR_HI(pa);
cmd.gpa_l = CQM_ADDR_LW(pa);
- pa = (buf_node_child->pa | (u32)spu_en);
+ pa = (buf_node_child->pa | spu_en);
cmd.value_h = CQM_ADDR_HI(pa);
cmd.value_l = CQM_ADDR_LW(pa);
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h
index dd0766e..a51c1dc 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h
@@ -9,6 +9,7 @@
#include "cqm_bitmap_table.h"
#include "cqm_object.h"
+#include "vram_common.h"
/* When the connection check is enabled, the maximum number of connections
* supported by the chip is 1M - 63, which cannot reach 1M
@@ -19,6 +20,7 @@
#define CLA_TABLE_PAGE_ORDER 0
#define CQM_4K_PAGE_ORDER 0
#define CQM_4K_PAGE_SIZE 4096
+#define CQM_8K_PAGE_ORDER 1
#define CQM_BAT_ENTRY_MAX 16
#define CQM_BAT_ENTRY_SIZE 16
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c
index d5fac94..61602e6 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c
@@ -273,6 +273,11 @@ s32 cqm_buf_alloc_direct(struct tag_cqm_handle *cqm_handle, struct tag_cqm_buf *
return CQM_SUCCESS;
}
+static bool check_use_vram(struct hinic3_hwdev *handle, struct tag_cqm_buf *buf)
+{
+ return buf->buf_info.use_vram ? true : false;
+}
+
static bool check_use_non_vram(struct hinic3_hwdev *handle, struct tag_cqm_buf *buf)
{
return buf->buf_info.use_vram ? false : true;
@@ -294,11 +299,46 @@ static bool check_for_nouse_node_alloc(struct hinic3_hwdev *handle, struct tag_c
return false;
}
+static s32 cqm_buf_vram_kalloc(struct hinic3_hwdev *handle, struct tag_cqm_buf *buf)
+{
+ void *vaddr = NULL;
+ int i;
+
+ vaddr = hi_vram_kalloc(buf->buf_info.buf_vram_name, (u64)buf->buf_size * buf->buf_number);
+ if (!vaddr) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
+ return CQM_FAIL;
+ }
+
+ for (i = 0; i < (s32)buf->buf_number; i++)
+ buf->buf_list[i].va = (void *)((char *)vaddr + i * (u64)buf->buf_size);
+
+ return CQM_SUCCESS;
+}
+
+static void cqm_buf_vram_free(struct tag_cqm_buf *buf)
+{
+ s32 i;
+
+ if (!buf->buf_list)
+ return;
+
+ if (buf->buf_list[0].va)
+ hi_vram_kfree(buf->buf_list[0].va, buf->buf_info.buf_vram_name,
+ (u64)buf->buf_size * buf->buf_number);
+
+ for (i = 0; i < (s32)buf->buf_number; i++)
+ buf->buf_list[i].va = NULL;
+}
+
static void cqm_buf_free_page_common(struct tag_cqm_buf *buf)
{
u32 order;
s32 i;
+ if (!buf->buf_list)
+ return;
+
order = (u32)get_order(buf->buf_size);
for (i = 0; i < (s32)buf->buf_number; i++) {
@@ -320,8 +360,10 @@ static s32 cqm_buf_use_node_alloc_page(struct hinic3_hwdev *handle, struct tag_c
node = dev_to_node(handle->dev_hdl);
for (i = 0; i < (s32)buf->buf_number; i++) {
newpage = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, order);
- if (!newpage)
+ if (!newpage) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
break;
+ }
va = (void *)page_address(newpage);
/* Initialize the page after the page is applied for.
* If hash entries are involved, the initialization
@@ -349,8 +391,10 @@ static s32 cqm_buf_unused_node_alloc_page(struct hinic3_hwdev *handle, struct ta
for (i = 0; i < (s32)buf->buf_number; i++) {
va = (void *)ossl_get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
- if (!va)
+ if (!va) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
break;
+ }
/* Initialize the page after the page is applied for.
* If hash entries are involved, the initialization
* value must be 0.
@@ -367,21 +411,21 @@ static s32 cqm_buf_unused_node_alloc_page(struct hinic3_hwdev *handle, struct ta
return CQM_SUCCESS;
}
-#define MALLOC_FUNCS_COUNT 2
-#define FREE_FUNCS_COUNT 1
-static const struct malloc_memory g_malloc_funcs[MALLOC_FUNCS_COUNT] = {
+static const struct malloc_memory g_malloc_funcs[] = {
+ {check_use_vram, cqm_buf_vram_kalloc},
{check_for_use_node_alloc, cqm_buf_use_node_alloc_page},
{check_for_nouse_node_alloc, cqm_buf_unused_node_alloc_page}
};
-static const struct free_memory g_free_funcs[FREE_FUNCS_COUNT] = {
+static const struct free_memory g_free_funcs[] = {
+ {check_use_vram, cqm_buf_vram_free},
{check_use_non_vram, cqm_buf_free_page_common}
};
static s32 cqm_buf_alloc_page(struct tag_cqm_handle *cqm_handle, struct tag_cqm_buf *buf)
{
struct hinic3_hwdev *handle = cqm_handle->ex_handle;
- u32 malloc_funcs_num = MALLOC_FUNCS_COUNT;
+ u32 malloc_funcs_num = ARRAY_SIZE(g_malloc_funcs);
u32 i;
for (i = 0; i < malloc_funcs_num; i++) {
@@ -398,7 +442,7 @@ static s32 cqm_buf_alloc_page(struct tag_cqm_handle *cqm_handle, struct tag_cqm_
static void cqm_buf_free_page(struct tag_cqm_buf *buf)
{
- u32 free_funcs_num = FREE_FUNCS_COUNT;
+ u32 free_funcs_num = ARRAY_SIZE(g_free_funcs);
u32 i;
for (i = 0; i < free_funcs_num; i++) {
@@ -447,8 +491,11 @@ static s32 cqm_buf_get_secure_mem_pages(struct tag_cqm_handle *cqm_handle, struc
cqm_get_secure_mem_pages(handle,
(u32)get_order(buf->buf_size),
&buf->buf_list[i].pa);
- if (!buf->buf_list[i].va)
+ if (!buf->buf_list[i].va) {
+ cqm_err(handle->dev_hdl,
+ CQM_ALLOC_FAIL(cqm_get_secure_mem_pages));
break;
+ }
}
if (i != buf->buf_number) {
@@ -777,7 +824,11 @@ static s32 cqm_single_bitmap_init(struct tag_cqm_bitmap *bitmap)
*/
bit_number = (ALIGN(bitmap->max_num, CQM_NUM_BIT_BYTE) >>
CQM_BYTE_BIT_SHIFT);
- bitmap->table = vmalloc(bit_number);
+ if (bitmap->bitmap_info.use_vram != 0)
+ bitmap->table = hi_vram_kalloc(bitmap->bitmap_info.buf_vram_name,
+ bit_number);
+ else
+ bitmap->table = vmalloc(bit_number);
if (!bitmap->table)
return CQM_FAIL;
memset(bitmap->table, 0, bit_number);
@@ -856,7 +907,7 @@ s32 cqm_bitmap_init(struct tag_cqm_handle *cqm_handle)
}
bitmap = &cla_table->bitmap;
- snprintf(bitmap->bitmap_info.buf_vram_name, VRAM_NAME_MAX_LEN - 1,
+ snprintf(bitmap->bitmap_info.buf_vram_name, VRAM_NAME_MAX_LEN,
"%s%s%02d", cla_table->name,
VRAM_CQM_BITMAP_BASE, cla_table->type);
@@ -866,6 +917,7 @@ s32 cqm_bitmap_init(struct tag_cqm_handle *cqm_handle)
bitmap->reserved_top = capability->qpc_reserved;
bitmap->reserved_back = capability->qpc_reserved_back;
bitmap->last = capability->qpc_reserved;
+ bitmap->bitmap_info.use_vram = get_use_vram_flag();
cqm_info(handle->dev_hdl,
"Bitmap init: cla_table_type=%u, max_num=0x%x\n",
cla_table->type, bitmap->max_num);
@@ -945,7 +997,14 @@ void cqm_bitmap_uninit(struct tag_cqm_handle *cqm_handle)
if (cla_table->type != CQM_BAT_ENTRY_T_INVALID &&
bitmap->table) {
spin_lock_deinit(&bitmap->lock);
- vfree(bitmap->table);
+ if (bitmap->bitmap_info.use_vram != 0)
+ hi_vram_kfree(bitmap->table,
+ bitmap->bitmap_info.buf_vram_name,
+ ALIGN(bitmap->max_num,
+ CQM_NUM_BIT_BYTE) >>
+ CQM_BYTE_BIT_SHIFT);
+ else
+ vfree(bitmap->table);
bitmap->table = NULL;
}
}
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h
index 7febf76..06b8661 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h
@@ -9,6 +9,7 @@
#include <linux/spinlock.h>
#include "cqm_object.h"
+#include "vram_common.h"
struct tag_cqm_bitmap {
ulong *table;
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c
index 9a13ae0..2a24e4a 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c
@@ -196,6 +196,13 @@ void *cqm_get_db_addr(void *ex_handle, u32 service_type)
pr_err("[CQM]%s: ex_handle is null\n", __func__);
return NULL;
}
+
+ if (service_type >= CQM_SERVICE_T_MAX) {
+ pr_err("%s service_type = %d state is error\n", __func__,
+ service_type);
+ return NULL;
+ }
+
handle = (struct hinic3_hwdev *)ex_handle;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
service = &cqm_handle->service[service_type];
@@ -218,6 +225,17 @@ s32 cqm_ring_hardware_db(void *ex_handle, u32 service_type, u8 db_count, u64 db)
struct tag_cqm_service *service = NULL;
struct hinic3_hwdev *handle = NULL;
+ if (unlikely(!ex_handle)) {
+ pr_err("[CQM]%s: ex_handle is null\n", __func__);
+ return CQM_FAIL;
+ }
+
+ if (service_type >= CQM_SERVICE_T_MAX) {
+ pr_err("%s service_type = %d state is error\n", __func__,
+ service_type);
+ return CQM_FAIL;
+ }
+
handle = (struct hinic3_hwdev *)ex_handle;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
service = &cqm_handle->service[service_type];
@@ -278,6 +296,17 @@ s32 cqm_ring_direct_wqe_db(void *ex_handle, u32 service_type, u8 db_count,
u64 *tmp = (u64 *)direct_wqe;
int i;
+ if (unlikely(!ex_handle)) {
+ pr_err("[CQM]%s: ex_handle is null\n", __func__);
+ return CQM_FAIL;
+ }
+
+ if (service_type >= CQM_SERVICE_T_MAX) {
+ pr_err("%s service_type = %d state is error\n", __func__,
+ service_type);
+ return CQM_FAIL;
+ }
+
handle = (struct hinic3_hwdev *)ex_handle;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
service = &cqm_handle->service[service_type];
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c
index 19a8b56..1f1235c 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c
@@ -23,6 +23,8 @@
#include "cqm_memsec.h"
#include "cqm_main.h"
+#include "vram_common.h"
+
static unsigned char roce_qpc_rsv_mode = CQM_QPC_ROCE_NORMAL;
module_param(roce_qpc_rsv_mode, byte, 0644);
MODULE_PARM_DESC(roce_qpc_rsv_mode,
@@ -98,10 +100,17 @@ static s32 cqm_set_timer_enable(void *ex_handle)
{
struct hinic3_hwdev *handle = (struct hinic3_hwdev *)ex_handle;
struct tag_cqm_handle *cqm_handle = NULL;
+ int is_in_kexec;
if (!ex_handle)
return CQM_FAIL;
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ cqm_info(handle->dev_hdl, "Skip starting cqm timer during kexec\n");
+ return CQM_SUCCESS;
+ }
+
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_PARENT &&
cqm_set_fake_vf_timer(cqm_handle) != CQM_SUCCESS)
@@ -473,7 +482,8 @@ static void cqm_service_capability_init_roce(struct tag_cqm_handle *cqm_handle,
func_cap->qpc_number += roce_own_cap->max_qps;
func_cap->qpc_basic_size = GET_MAX(roce_own_cap->qpc_entry_sz,
func_cap->qpc_basic_size);
- if (cqm_handle->func_attribute.func_type == CQM_PF && (IS_MASTER_HOST(handle))) {
+ if (cqm_handle->func_attribute.func_type == CQM_PF &&
+ (IS_MASTER_HOST(handle))) {
func_cap->hash_number = roce_own_cap->max_qps;
func_cap->hash_basic_size = CQM_HASH_BUCKET_SIZE_64;
}
@@ -1129,8 +1139,9 @@ static s32 cqm_fake_mem_init(struct tag_cqm_handle *cqm_handle)
for (i = 0; i < (u32)child_func_number; i++) {
fake_cqm_handle = cqm_handle->fake_cqm_handle[i];
- snprintf(fake_cqm_handle->name, VRAM_NAME_MAX_LEN - 1,
- "%s%s%02u", cqm_handle->name, VRAM_CQM_FAKE_MEM_BASE, i);
+ snprintf(fake_cqm_handle->name, VRAM_NAME_MAX_LEN,
+ "%s%s%02u", cqm_handle->name,
+ VRAM_CQM_FAKE_MEM_BASE, i);
if (cqm_bat_init(fake_cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl,
@@ -1174,8 +1185,9 @@ s32 cqm_mem_init(void *ex_handle)
struct tag_cqm_handle *cqm_handle = NULL;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
- snprintf(cqm_handle->name, VRAM_NAME_MAX_LEN - 1,
- "%s%02u", VRAM_CQM_GLB_FUNC_BASE, hinic3_global_func_id(handle));
+ snprintf(cqm_handle->name, VRAM_NAME_MAX_LEN,
+ "%s%02u", VRAM_CQM_GLB_FUNC_BASE,
+ hinic3_global_func_id(handle));
if (cqm_fake_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fake_init));
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h
index 4f87bd1..8d1e481 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h
@@ -362,6 +362,7 @@ s32 cqm_fake_vf_num_set(void *ex_handle, u16 fake_vf_num_cfg);
#define CQM_LOG_ID 0
#define CQM_PTR_NULL(x) "%s: " #x " is null\n", __func__
+#define CQM_ALLOC_FAIL(x) "%s: " #x " alloc fail\n", __func__
#define CQM_MAP_FAIL(x) "%s: " #x " map fail\n", __func__
#define CQM_FUNCTION_FAIL(x) "%s: " #x " return failure\n", __func__
#define CQM_WRONG_VALUE(x) "%s: " #x " %u is wrong\n", __func__, (u32)(x)
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c
index 213803f..f5fce8f 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c
@@ -378,7 +378,7 @@ static int hinic3_secure_mem_proc_node_remove(void *hwdev)
atomic_dec(&g_memsec_proc_refcnt);
- snprintf(pci_name, PCI_PROC_NAME_LEN - 1,
+ snprintf(pci_name, PCI_PROC_NAME_LEN,
"%02x:%02x:%x", pdev->bus->number, pdev->slot->number,
PCI_FUNC(pdev->devfn));
@@ -401,7 +401,7 @@ static int hinic3_secure_mem_proc_node_add(void *hwdev)
atomic_inc(&g_memsec_proc_refcnt);
- snprintf(pci_name, PCI_PROC_NAME_LEN - 1,
+ snprintf(pci_name, PCI_PROC_NAME_LEN,
"%02x:%02x:%x", pdev->bus->number, pdev->slot->number,
PCI_FUNC(pdev->devfn));
/* 0400 Read by owner */
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h b/drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h
deleted file mode 100644
index ad732c3..0000000
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2019-2022. All rights reserved.
- * File Name : hinic3_comm_cmd.h
- * Version : Initial Draft
- * Created : 2019/4/25
- * Last Modified :
- * Description : COMM Commands between Driver and MPU
- * Function List :
- */
-
-#ifndef HINIC3_COMMON_CMD_H
-#define HINIC3_COMMON_CMD_H
-
-/* COMM Commands between Driver to MPU */
-enum hinic3_mgmt_cmd {
- /* flr及资源清理相关命令 */
- COMM_MGMT_CMD_FUNC_RESET = 0,
- COMM_MGMT_CMD_FEATURE_NEGO,
- COMM_MGMT_CMD_FLUSH_DOORBELL,
- COMM_MGMT_CMD_START_FLUSH,
- COMM_MGMT_CMD_SET_FUNC_FLR,
- COMM_MGMT_CMD_GET_GLOBAL_ATTR,
- COMM_MGMT_CMD_SET_PPF_FLR_TYPE,
- COMM_MGMT_CMD_SET_FUNC_SVC_USED_STATE,
-
- /* 分配msi-x中断资源 */
- COMM_MGMT_CMD_CFG_MSIX_NUM = 10,
-
- /* 驱动相关配置命令 */
- COMM_MGMT_CMD_SET_CMDQ_CTXT = 20,
- COMM_MGMT_CMD_SET_VAT,
- COMM_MGMT_CMD_CFG_PAGESIZE,
- COMM_MGMT_CMD_CFG_MSIX_CTRL_REG,
- COMM_MGMT_CMD_SET_CEQ_CTRL_REG,
- COMM_MGMT_CMD_SET_DMA_ATTR,
-
- /* INFRA配置相关命令字 */
- COMM_MGMT_CMD_GET_MQM_FIX_INFO = 40,
- COMM_MGMT_CMD_SET_MQM_CFG_INFO,
- COMM_MGMT_CMD_SET_MQM_SRCH_GPA,
- COMM_MGMT_CMD_SET_PPF_TMR,
- COMM_MGMT_CMD_SET_PPF_HT_GPA,
- COMM_MGMT_CMD_SET_FUNC_TMR_BITMAT,
- COMM_MGMT_CMD_SET_MBX_CRDT,
- COMM_MGMT_CMD_CFG_TEMPLATE,
- COMM_MGMT_CMD_SET_MQM_LIMIT,
-
- /* 信息获取相关命令字 */
- COMM_MGMT_CMD_GET_FW_VERSION = 60,
- COMM_MGMT_CMD_GET_BOARD_INFO,
- COMM_MGMT_CMD_SYNC_TIME,
- COMM_MGMT_CMD_GET_HW_PF_INFOS,
- COMM_MGMT_CMD_SEND_BDF_INFO,
- COMM_MGMT_CMD_GET_VIRTIO_BDF_INFO,
- COMM_MGMT_CMD_GET_SML_TABLE_INFO,
- COMM_MGMT_CMD_GET_SDI_INFO,
-
- /* 升级相关命令字 */
- COMM_MGMT_CMD_UPDATE_FW = 80,
- COMM_MGMT_CMD_ACTIVE_FW,
- COMM_MGMT_CMD_HOT_ACTIVE_FW,
- COMM_MGMT_CMD_HOT_ACTIVE_DONE_NOTICE,
- COMM_MGMT_CMD_SWITCH_CFG,
- COMM_MGMT_CMD_CHECK_FLASH,
- COMM_MGMT_CMD_CHECK_FLASH_RW,
- COMM_MGMT_CMD_RESOURCE_CFG,
- COMM_MGMT_CMD_UPDATE_BIOS, /* TODO: merge to COMM_MGMT_CMD_UPDATE_FW */
- COMM_MGMT_CMD_MPU_GIT_CODE,
-
- /* chip reset相关 */
- COMM_MGMT_CMD_FAULT_REPORT = 100,
- COMM_MGMT_CMD_WATCHDOG_INFO,
- COMM_MGMT_CMD_MGMT_RESET,
- COMM_MGMT_CMD_FFM_SET, /* TODO: check if needed */
-
- /* chip info/log 相关 */
- COMM_MGMT_CMD_GET_LOG = 120,
- COMM_MGMT_CMD_TEMP_OP,
- COMM_MGMT_CMD_EN_AUTO_RST_CHIP,
- COMM_MGMT_CMD_CFG_REG,
- COMM_MGMT_CMD_GET_CHIP_ID,
- COMM_MGMT_CMD_SYSINFO_DFX,
- COMM_MGMT_CMD_PCIE_DFX_NTC,
- COMM_MGMT_CMD_DICT_LOG_STATUS, /* LOG STATUS 127 */
- COMM_MGMT_CMD_MSIX_INFO,
- COMM_MGMT_CMD_CHANNEL_DETECT,
- COMM_MGMT_CMD_DICT_COUNTER_STATUS,
-
- /* switch workmode 相关 */
- COMM_MGMT_CMD_CHECK_IF_SWITCH_WORKMODE = 140,
- COMM_MGMT_CMD_SWITCH_WORKMODE,
-
- /* mpu 相关 */
- COMM_MGMT_CMD_MIGRATE_DFX_HPA = 150,
- COMM_MGMT_CMD_BDF_INFO,
- COMM_MGMT_CMD_NCSI_CFG_INFO_GET_PROC,
-
- /* rsvd0 section */
- COMM_MGMT_CMD_SECTION_RSVD_0 = 160,
-
- /* rsvd1 section */
- COMM_MGMT_CMD_SECTION_RSVD_1 = 170,
-
- /* rsvd2 section */
- COMM_MGMT_CMD_SECTION_RSVD_2 = 180,
-
- /* rsvd3 section */
- COMM_MGMT_CMD_SECTION_RSVD_3 = 190,
-
- /* TODO: move to DFT mode */
- COMM_MGMT_CMD_GET_DIE_ID = 200,
- COMM_MGMT_CMD_GET_EFUSE_TEST,
- COMM_MGMT_CMD_EFUSE_INFO_CFG,
- COMM_MGMT_CMD_GPIO_CTL,
- COMM_MGMT_CMD_HI30_SERLOOP_START, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_HI30_SERLOOP_STOP, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_HI30_MBIST_SET_FLAG, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_HI30_MBIST_GET_RESULT, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_ECC_TEST,
- COMM_MGMT_CMD_FUNC_BIST_TEST, /* 209 */
-
- COMM_MGMT_CMD_VPD_SET = 210,
- COMM_MGMT_CMD_VPD_GET,
-
- COMM_MGMT_CMD_ERASE_FLASH,
- COMM_MGMT_CMD_QUERY_FW_INFO,
- COMM_MGMT_CMD_GET_CFG_INFO,
- COMM_MGMT_CMD_GET_UART_LOG,
- COMM_MGMT_CMD_SET_UART_CMD,
- COMM_MGMT_CMD_SPI_TEST,
-
- /* TODO: ALL reg read/write merge to COMM_MGMT_CMD_CFG_REG */
- COMM_MGMT_CMD_UP_REG_GET,
- COMM_MGMT_CMD_UP_REG_SET, /* 219 */
-
- COMM_MGMT_CMD_REG_READ = 220,
- COMM_MGMT_CMD_REG_WRITE,
- COMM_MGMT_CMD_MAG_REG_WRITE,
- COMM_MGMT_CMD_ANLT_REG_WRITE,
-
- COMM_MGMT_CMD_HEART_EVENT, /* TODO: delete */
- COMM_MGMT_CMD_NCSI_OEM_GET_DRV_INFO, /* TODO: delete */
- COMM_MGMT_CMD_LASTWORD_GET,
- COMM_MGMT_CMD_READ_BIN_DATA, /* TODO: delete */
- /* COMM_MGMT_CMD_WWPN_GET, TODO: move to FC? */
- /* COMM_MGMT_CMD_WWPN_SET, TODO: move to FC? */ /* 229 */
-
- /* TODO: check if needed */
- COMM_MGMT_CMD_SET_VIRTIO_DEV = 230,
- COMM_MGMT_CMD_SET_MAC,
- /* MPU patch cmd */
- COMM_MGMT_CMD_LOAD_PATCH,
- COMM_MGMT_CMD_REMOVE_PATCH,
- COMM_MGMT_CMD_PATCH_ACTIVE,
- COMM_MGMT_CMD_PATCH_DEACTIVE,
- COMM_MGMT_CMD_PATCH_SRAM_OPTIMIZE,
- /* container host process */
- COMM_MGMT_CMD_CONTAINER_HOST_PROC,
- /* nsci counter */
- COMM_MGMT_CMD_NCSI_COUNTER_PROC,
- COMM_MGMT_CMD_CHANNEL_STATUS_CHECK, /* 239 */
-
- /* hot patch rsvd cmd */
- COMM_MGMT_CMD_RSVD_0 = 240,
- COMM_MGMT_CMD_RSVD_1,
- COMM_MGMT_CMD_RSVD_2,
- COMM_MGMT_CMD_RSVD_3,
- COMM_MGMT_CMD_RSVD_4,
- /* 无效字段,版本收编删除,编译使用 */
- COMM_MGMT_CMD_SEND_API_ACK_BY_UP,
-
- /* 注:添加cmd,不能修改已有命令字的值,请在前方rsvd
- * section中添加;原则上所有分支cmd表完全一致
- */
- COMM_MGMT_CMD_MAX = 255,
-};
-
-/* CmdQ Common subtype */
-enum comm_cmdq_cmd {
- COMM_CMD_UCODE_ARM_BIT_SET = 2,
- COMM_CMD_SEND_NPU_DFT_CMD,
-};
-
-#endif /* HINIC3_COMMON_CMD_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h
deleted file mode 100644
index 9ce908e..0000000
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
-
-#ifndef HINIC3_COMMON_H
-#define HINIC3_COMMON_H
-
-#include <linux/types.h>
-
-struct hinic3_dma_addr_align {
- u32 real_size;
-
- void *ori_vaddr;
- dma_addr_t ori_paddr;
-
- void *align_vaddr;
- dma_addr_t align_paddr;
-};
-
-enum hinic3_wait_return {
- WAIT_PROCESS_CPL = 0,
- WAIT_PROCESS_WAITING = 1,
- WAIT_PROCESS_ERR = 2,
-};
-
-struct hinic3_sge {
- u32 hi_addr;
- u32 lo_addr;
- u32 len;
-};
-
-#ifdef static
-#undef static
-#define LLT_STATIC_DEF_SAVED
-#endif
-
-/* *
- * hinic_cpu_to_be32 - convert data to big endian 32 bit format
- * @data: the data to convert
- * @len: length of data to convert, must be Multiple of 4B
- */
-static inline void hinic3_cpu_to_be32(void *data, int len)
-{
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = cpu_to_be32(*mem);
- mem++;
- }
-}
-
-/* *
- * hinic3_cpu_to_be32 - convert data from big endian 32 bit format
- * @data: the data to convert
- * @len: length of data to convert
- */
-static inline void hinic3_be32_to_cpu(void *data, int len)
-{
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = be32_to_cpu(*mem);
- mem++;
- }
-}
-
-/* *
- * hinic3_set_sge - set dma area in scatter gather entry
- * @sge: scatter gather entry
- * @addr: dma address
- * @len: length of relevant data in the dma address
- */
-static inline void hinic3_set_sge(struct hinic3_sge *sge, dma_addr_t addr,
- int len)
-{
- sge->hi_addr = upper_32_bits(addr);
- sge->lo_addr = lower_32_bits(addr);
- sge->len = len;
-}
-
-#define hinic3_hw_be32(val) (val)
-#define hinic3_hw_cpu32(val) (val)
-#define hinic3_hw_cpu16(val) (val)
-
-static inline void hinic3_hw_be32_len(void *data, int len)
-{
-}
-
-static inline void hinic3_hw_cpu32_len(void *data, int len)
-{
-}
-
-int hinic3_dma_zalloc_coherent_align(void *dev_hdl, u64 size, u64 align,
- unsigned int flag,
- struct hinic3_dma_addr_align *mem_align);
-
-void hinic3_dma_free_coherent_align(void *dev_hdl,
- struct hinic3_dma_addr_align *mem_align);
-
-typedef enum hinic3_wait_return (*wait_cpl_handler)(void *priv_data);
-
-int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler,
- u32 wait_total_ms, u32 wait_once_us);
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h b/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h
index 64139c4..4f5792f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h
@@ -8,7 +8,7 @@
#include "mpu_cmd_base_defs.h"
-#define HINIC3_DRV_VERSION "15.17.1.2"
+#define HINIC3_DRV_VERSION "17.7.8.1"
#define HINIC3_DRV_DESC "Intelligent Network Interface Card Driver"
#define HIUDK_DRV_DESC "Intelligent Network Unified Driver"
@@ -45,6 +45,7 @@ enum hinic3_service_type {
SERVICE_T_CUSTOM,
SERVICE_T_VROCE,
SERVICE_T_CRYPT,
+ SERVICE_T_VSOCK,
SERVICE_T_BIFUR,
SERVICE_T_MAX,
@@ -64,6 +65,9 @@ struct nic_service_cap {
u16 max_sqs;
u16 max_rqs;
u16 default_num_queues;
+ u16 outband_vlan_cfg_en;
+ u8 lro_enable;
+ u8 rsvd1[3];
};
struct ppa_service_cap {
@@ -909,6 +913,13 @@ int hinic3_get_mgmt_version(void *hwdev, u8 *mgmt_ver, u8 version_size,
int hinic3_get_fw_version(void *hwdev, struct hinic3_fw_version *fw_ver,
u16 channel);
+/* *
+ * @brief hinic3_get_bond_create_mode - get bond create mode
+ * @param hwdev: device pointer to hwdev
+ * @retval global function id
+ */
+u8 hinic3_get_bond_create_mode(void *udkdev);
+
/* *
* @brief hinic3_global_func_id - get global function id
* @param hwdev: device pointer to hwdev
@@ -1263,4 +1274,7 @@ int hinic3_mbox_to_host_sync(void *hwdev, enum hinic3_mod_type mod,
int hinic3_get_func_vroce_enable(void *hwdev, u16 glb_func_idx, u8 *en);
+void hinic3_module_get(void *hwdev, enum hinic3_service_type type);
+void hinic3_module_put(void *hwdev, enum hinic3_service_type type);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c
index 40ff473..1191653 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c
@@ -18,9 +18,10 @@
#include "hinic3_tx.h"
#include "hinic3_dcb.h"
#include "hinic3_nic.h"
-#include "hinic3_mgmt_interface.h"
+#include "hinic3_bond.h"
+#include "nic_mpu_cmd_defs.h"
#include "mag_mpu_cmd.h"
-#include "mag_cmd.h"
+#include "mag_mpu_cmd_defs.h"
typedef int (*nic_driv_module)(struct hinic3_nic_dev *nic_dev,
const void *buf_in, u32 in_size,
@@ -34,7 +35,6 @@ struct nic_drv_module_handle {
static int get_nic_drv_version(void *buf_out, const u32 *out_size)
{
struct drv_version_info *ver_info = buf_out;
- int err;
if (!buf_out) {
pr_err("Buf_out is NULL.\n");
@@ -47,10 +47,8 @@ static int get_nic_drv_version(void *buf_out, const u32 *out_size)
return -EINVAL;
}
- err = snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s",
- HINIC3_NIC_DRV_VERSION, "2023-05-17_19:56:38");
- if (err < 0)
- return -EINVAL;
+ snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s",
+ HINIC3_NIC_DRV_VERSION, "2025-05-08_00:00:08");
return 0;
}
@@ -126,7 +124,8 @@ static int get_tx_wqe_info(struct hinic3_nic_dev *nic_dev,
}
if (!buf_in || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Buf_in or buf_out is NULL.\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_in or buf_out is NULL.\n");
return -EINVAL;
}
@@ -178,7 +177,8 @@ static int get_rx_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
}
rq_info->delta = (u16)nic_dev->rxqs[q_id].delta;
- rq_info->ci = (u16)(nic_dev->rxqs[q_id].cons_idx & nic_dev->rxqs[q_id].q_mask);
+ rq_info->ci = (u16)(nic_dev->rxqs[q_id].cons_idx &
+ nic_dev->rxqs[q_id].q_mask);
rq_info->sw_pi = nic_dev->rxqs[q_id].next_to_update;
rq_info->msix_vector = nic_dev->rxqs[q_id].irq_id;
@@ -201,7 +201,8 @@ static int get_rx_wqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
}
if (!buf_in || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Buf_in or buf_out is NULL.\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_in or buf_out is NULL.\n");
return -EINVAL;
}
@@ -230,7 +231,7 @@ static int get_rx_cqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return -EFAULT;
}
- if (!buf_in || !buf_out) {
+ if (!buf_in || !buf_out || !out_size) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Buf_in or buf_out is NULL.\n");
return -EINVAL;
@@ -243,7 +244,7 @@ static int get_rx_cqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return -EINVAL;
}
- if (!out_size || *out_size != sizeof(struct hinic3_rq_cqe)) {
+ if (*out_size != sizeof(struct hinic3_rq_cqe)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%u, expect: %lu\n",
*out_size, sizeof(struct hinic3_rq_cqe));
@@ -252,10 +253,12 @@ static int get_rx_cqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
q_id = (u16)info->q_id;
idx = (u16)info->wqe_id;
- if (q_id >= nic_dev->q_params.num_qps || idx >= nic_dev->rxqs[q_id].q_depth) {
+ if (q_id >= nic_dev->q_params.num_qps ||
+ idx >= nic_dev->rxqs[q_id].q_depth) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid q_id[%u] >= %u, or wqe idx[%u] >= %u.\n",
- q_id, nic_dev->q_params.num_qps, idx, nic_dev->rxqs[q_id].q_depth);
+ q_id, nic_dev->q_params.num_qps, idx,
+ nic_dev->rxqs[q_id].q_depth);
return -EFAULT;
}
@@ -338,7 +341,8 @@ static int set_loopback_mode(struct hinic3_nic_dev *nic_dev, const void *buf_in,
err = hinic3_set_loopback_mode(nic_dev->hwdev, (u8)mode->loop_mode,
(u8)mode->loop_ctrl);
if (err == 0)
- nicif_info(nic_dev, drv, nic_dev->netdev, "Set loopback mode %u en %u succeed\n",
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "Set loopback mode %u en %u succeed\n",
mode->loop_mode, mode->loop_ctrl);
return err;
@@ -417,6 +421,59 @@ static int set_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
{
u32 pf_bw_limit;
int err;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct net_device *net_dev = nic_dev->netdev;
+
+ if (hinic3_support_roce(nic_dev->hwdev, NULL) &&
+ hinic3_is_bond_dev_status_actived(net_dev)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "The rate limit func is not supported when RoCE bonding is enabled\n");
+ return -EINVAL;
+ }
+
+ if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "To set VF bandwidth rate, please use ip link cmd\n");
+ return -EINVAL;
+ }
+
+ if (!buf_in || !buf_out || in_size != sizeof(u32) ||
+ !out_size || *out_size != sizeof(u8))
+ return -EINVAL;
+
+ nic_io = hinic3_get_service_adapter(nic_dev->hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+ nic_io->direct = HINIC3_NIC_TX;
+ pf_bw_limit = *((u32 *)buf_in);
+
+ err = hinic3_set_pf_bw_limit(nic_dev->hwdev, pf_bw_limit);
+ if (err) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to set pf bandwidth limit to %u%%\n",
+ pf_bw_limit);
+ if (err < 0)
+ return err;
+ }
+
+ *((u8 *)buf_out) = (u8)err;
+
+ return 0;
+}
+
+static int set_rx_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ u32 pf_bw_limit;
+ int err;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct net_device *net_dev = nic_dev->netdev;
+
+ if (hinic3_support_roce(nic_dev->hwdev, NULL) &&
+ hinic3_is_bond_dev_status_actived(net_dev)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "The rate limit func is not supported when RoCE bonding is enabled\n");
+ return -EINVAL;
+ }
if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
nicif_err(nic_dev, drv, nic_dev->netdev, "To set VF bandwidth rate, please use ip link cmd\n");
@@ -426,11 +483,16 @@ static int set_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (!buf_in || !buf_out || in_size != sizeof(u32) || !out_size || *out_size != sizeof(u8))
return -EINVAL;
+ nic_io = hinic3_get_service_adapter(nic_dev->hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+ nic_io->direct = HINIC3_NIC_RX;
pf_bw_limit = *((u32 *)buf_in);
err = hinic3_set_pf_bw_limit(nic_dev->hwdev, pf_bw_limit);
if (err) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to set pf bandwidth limit to %d%%\n",
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to set pf bandwidth limit to %d%%\n",
pf_bw_limit);
if (err < 0)
return err;
@@ -445,19 +507,21 @@ static int get_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
struct hinic3_nic_io *nic_io = NULL;
+ u32 *rate_limit = (u32 *)buf_out;
if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "To get VF bandwidth rate, please use ip link cmd\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "To get VF bandwidth rate, please use ip link cmd\n");
return -EINVAL;
}
if (!buf_out || !out_size)
return -EINVAL;
- if (*out_size != sizeof(u32)) {
+ if (*out_size != sizeof(u32) * 2) { // 2:Stored in an array, TX and RX, both length are u32
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user: %d, expect: %lu\n",
- *out_size, sizeof(u32));
+ *out_size, sizeof(u32) * 2);
return -EFAULT;
}
@@ -465,8 +529,12 @@ static int get_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (!nic_io)
return -EINVAL;
- *((u32 *)buf_out) = nic_io->nic_cfg.pf_bw_limit;
+ rate_limit[HINIC3_NIC_RX] = nic_io->nic_cfg.pf_bw_rx_limit;
+ rate_limit[HINIC3_NIC_TX] = nic_io->nic_cfg.pf_bw_tx_limit;
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "read rate cfg success rx rate is: %u, tx rate is : %u\n",
+ rate_limit[HINIC3_NIC_RX], rate_limit[HINIC3_NIC_TX]);
return 0;
}
@@ -477,8 +545,8 @@ static int get_sset_count(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (!buf_in || in_size != sizeof(u32) || !out_size ||
*out_size != sizeof(u32) || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n",
- in_size);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Invalid parameters, in_size: %u\n", in_size);
return -EINVAL;
}
@@ -504,16 +572,16 @@ static int get_sset_stats(struct hinic3_nic_dev *nic_dev, const void *buf_in,
int err;
if (!buf_in || in_size != sizeof(u32) || !out_size || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n",
- in_size);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Invalid parameters, in_size: %u\n", in_size);
return -EINVAL;
}
size = sizeof(u32);
err = get_sset_count(nic_dev, buf_in, in_size, &count, &size);
if (err) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Get sset count failed, ret=%d\n",
- err);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Get sset count failed, ret=%d\n", err);
return -EINVAL;
}
if (count * sizeof(*items) != *out_size) {
@@ -527,12 +595,14 @@ static int get_sset_stats(struct hinic3_nic_dev *nic_dev, const void *buf_in,
switch (sset) {
case HINIC3_SHOW_SSET_IO_STATS:
- hinic3_get_io_stats(nic_dev, items);
+ err = hinic3_get_io_stats(nic_dev, items);
+ if (err < 0)
+ return -EINVAL;
break;
default:
- nicif_err(nic_dev, drv, nic_dev->netdev, "Unknown %u to get stats\n",
- sset);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Unknown %u to get stats\n", sset);
err = -EINVAL;
break;
}
@@ -544,15 +614,18 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
struct hinic3_dcb_config *wanted_dcb_cfg,
const struct hinic3_mt_qos_dev_cfg *qos_in)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int i;
u8 cos_num = 0, valid_cos_bitmap = 0;
if (qos_in->cfg_bitmap & CMD_QOS_DEV_PCP2COS) {
for (i = 0; i < NIC_DCB_UP_MAX; i++) {
- if (!(nic_dev->func_dft_cos_bitmap & BIT(qos_in->pcp2cos[i]))) {
+ if (!(dcb->func_dft_cos_bitmap &
+ BIT(qos_in->pcp2cos[i]))) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid cos=%u, func cos valid map is %u",
- qos_in->pcp2cos[i], nic_dev->func_dft_cos_bitmap);
+ qos_in->pcp2cos[i],
+ dcb->func_dft_cos_bitmap);
return -EINVAL;
}
@@ -562,7 +635,8 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
}
}
- memcpy(wanted_dcb_cfg->pcp2cos, qos_in->pcp2cos, sizeof(qos_in->pcp2cos));
+ memcpy(wanted_dcb_cfg->pcp2cos, qos_in->pcp2cos,
+ sizeof(qos_in->pcp2cos));
wanted_dcb_cfg->pcp_user_cos_num = cos_num;
wanted_dcb_cfg->pcp_valid_cos_map = valid_cos_bitmap;
}
@@ -572,12 +646,14 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
valid_cos_bitmap = 0;
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++) {
u8 cos = qos_in->dscp2cos[i] == DBG_DFLT_DSCP_VAL ?
- nic_dev->wanted_dcb_cfg.dscp2cos[i] : qos_in->dscp2cos[i];
+ dcb->wanted_dcb_cfg.dscp2cos[i] :
+ qos_in->dscp2cos[i];
- if (cos >= NIC_DCB_UP_MAX || !(nic_dev->func_dft_cos_bitmap & BIT(cos))) {
+ if (cos >= NIC_DCB_UP_MAX ||
+ !(dcb->func_dft_cos_bitmap & BIT(cos))) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid cos=%u, func cos valid map is %u",
- cos, nic_dev->func_dft_cos_bitmap);
+ cos, dcb->func_dft_cos_bitmap);
return -EINVAL;
}
@@ -588,8 +664,10 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
}
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++)
- wanted_dcb_cfg->dscp2cos[i] = qos_in->dscp2cos[i] == DBG_DFLT_DSCP_VAL ?
- nic_dev->hw_dcb_cfg.dscp2cos[i] : qos_in->dscp2cos[i];
+ wanted_dcb_cfg->dscp2cos[i] =
+ qos_in->dscp2cos[i] == DBG_DFLT_DSCP_VAL ?
+ dcb->hw_dcb_cfg.dscp2cos[i] :
+ qos_in->dscp2cos[i];
wanted_dcb_cfg->dscp_user_cos_num = cos_num;
wanted_dcb_cfg->dscp_valid_cos_map = valid_cos_bitmap;
}
@@ -601,11 +679,12 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
struct hinic3_dcb_config *wanted_dcb_cfg,
const struct hinic3_mt_qos_dev_cfg *qos_in)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int ret;
u8 cos_num, valid_cos_bitmap;
if (qos_in->cfg_bitmap & CMD_QOS_DEV_TRUST) {
- if (qos_in->trust > DCB_DSCP) {
+ if (qos_in->trust > HINIC3_DCB_DSCP) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid trust=%u\n", qos_in->trust);
return -EINVAL;
@@ -615,7 +694,7 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
}
if (qos_in->cfg_bitmap & CMD_QOS_DEV_DFT_COS) {
- if (!(BIT(qos_in->dft_cos) & nic_dev->func_dft_cos_bitmap)) {
+ if (!(BIT(qos_in->dft_cos) & dcb->func_dft_cos_bitmap)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid dft_cos=%u\n", qos_in->dft_cos);
return -EINVAL;
@@ -628,7 +707,7 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
if (ret)
return ret;
- if (wanted_dcb_cfg->trust == DCB_PCP) {
+ if (wanted_dcb_cfg->trust == HINIC3_DCB_PCP) {
cos_num = wanted_dcb_cfg->pcp_user_cos_num;
valid_cos_bitmap = wanted_dcb_cfg->pcp_valid_cos_map;
} else {
@@ -636,18 +715,11 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
valid_cos_bitmap = wanted_dcb_cfg->dscp_valid_cos_map;
}
- if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
- if (cos_num > nic_dev->q_params.num_qps) {
- nicif_err(nic_dev, drv, nic_dev->netdev,
- "DCB is on, cos num should not more than channel num:%u\n",
- nic_dev->q_params.num_qps);
- return -EOPNOTSUPP;
- }
- }
-
if (!(BIT(wanted_dcb_cfg->default_cos) & valid_cos_bitmap)) {
- nicif_info(nic_dev, drv, nic_dev->netdev, "Current default_cos=%u, change to %u\n",
- wanted_dcb_cfg->default_cos, (u8)fls(valid_cos_bitmap) - 1);
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "Current default_cos=%u, change to %u\n",
+ wanted_dcb_cfg->default_cos,
+ (u8)fls(valid_cos_bitmap) - 1);
wanted_dcb_cfg->default_cos = (u8)fls(valid_cos_bitmap) - 1;
}
@@ -657,6 +729,7 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
static int dcb_mt_qos_map(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
const struct hinic3_mt_qos_dev_cfg *qos_in = buf_in;
struct hinic3_mt_qos_dev_cfg *qos_out = buf_out;
u8 i;
@@ -675,9 +748,10 @@ static int dcb_mt_qos_map(struct hinic3_nic_dev *nic_dev, const void *buf_in,
memcpy(qos_out, qos_in, sizeof(*qos_in));
qos_out->head.status = 0;
if (qos_in->op_code & MT_DCB_OPCODE_WR) {
- memcpy(&nic_dev->wanted_dcb_cfg, &nic_dev->hw_dcb_cfg,
+ memcpy(&dcb->wanted_dcb_cfg, &dcb->hw_dcb_cfg,
sizeof(struct hinic3_dcb_config));
- err = update_wanted_qos_cfg(nic_dev, &nic_dev->wanted_dcb_cfg, qos_in);
+ err = update_wanted_qos_cfg(nic_dev, &dcb->wanted_dcb_cfg,
+ qos_in);
if (err) {
qos_out->head.status = MT_EINVAL;
return 0;
@@ -687,12 +761,12 @@ static int dcb_mt_qos_map(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (err)
qos_out->head.status = MT_EIO;
} else {
- qos_out->dft_cos = nic_dev->hw_dcb_cfg.default_cos;
- qos_out->trust = nic_dev->hw_dcb_cfg.trust;
+ qos_out->dft_cos = dcb->hw_dcb_cfg.default_cos;
+ qos_out->trust = dcb->hw_dcb_cfg.trust;
for (i = 0; i < NIC_DCB_UP_MAX; i++)
- qos_out->pcp2cos[i] = nic_dev->hw_dcb_cfg.pcp2cos[i];
+ qos_out->pcp2cos[i] = dcb->hw_dcb_cfg.pcp2cos[i];
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++)
- qos_out->dscp2cos[i] = nic_dev->hw_dcb_cfg.dscp2cos[i];
+ qos_out->dscp2cos[i] = dcb->hw_dcb_cfg.dscp2cos[i];
}
return 0;
@@ -721,27 +795,17 @@ static int dcb_mt_dcb_state(struct hinic3_nic_dev *nic_dev, const void *buf_in,
memcpy(dcb_out, dcb_in, sizeof(*dcb_in));
dcb_out->head.status = 0;
if (dcb_in->op_code & MT_DCB_OPCODE_WR) {
- if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) == dcb_in->state)
+ if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ==
+ dcb_in->state)
return 0;
- if (dcb_in->state) {
- if (user_cos_num > nic_dev->q_params.num_qps) {
- nicif_err(nic_dev, drv, nic_dev->netdev,
- "cos num %u should not more than channel num %u\n",
- user_cos_num,
- nic_dev->q_params.num_qps);
-
- return -EOPNOTSUPP;
- }
- }
-
- rtnl_lock();
if (netif_running(nic_dev->netdev)) {
netif_run = 1;
hinic3_vport_down(nic_dev);
}
- err = hinic3_setup_cos(nic_dev->netdev, dcb_in->state ? user_cos_num : 0,
+ err = hinic3_setup_cos(nic_dev->netdev,
+ dcb_in->state ? user_cos_num : 0,
netif_run);
if (err)
goto setup_cos_fail;
@@ -751,7 +815,6 @@ static int dcb_mt_dcb_state(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (err)
goto vport_up_fail;
}
- rtnl_unlock();
} else {
dcb_out->state = !!test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
}
@@ -759,12 +822,12 @@ static int dcb_mt_dcb_state(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return 0;
vport_up_fail:
- hinic3_setup_cos(nic_dev->netdev, dcb_in->state ? 0 : user_cos_num, netif_run);
+ hinic3_setup_cos(nic_dev->netdev, dcb_in->state ? 0 : user_cos_num,
+ netif_run);
setup_cos_fail:
if (netif_run)
hinic3_vport_up(nic_dev);
- rtnl_unlock();
return err;
}
@@ -772,13 +835,15 @@ setup_cos_fail:
static int dcb_mt_hw_qos_get(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
const struct hinic3_mt_qos_cos_cfg *cos_cfg_in = buf_in;
struct hinic3_mt_qos_cos_cfg *cos_cfg_out = buf_out;
if (!buf_in || !buf_out || !out_size)
return -EINVAL;
- if (*out_size != sizeof(*cos_cfg_out) || in_size != sizeof(*cos_cfg_in)) {
+ if (*out_size != sizeof(*cos_cfg_out) ||
+ in_size != sizeof(*cos_cfg_in)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n",
in_size, *out_size, sizeof(*cos_cfg_in));
@@ -789,9 +854,9 @@ static int dcb_mt_hw_qos_get(struct hinic3_nic_dev *nic_dev, const void *buf_in,
cos_cfg_out->head.status = 0;
cos_cfg_out->port_id = hinic3_physical_port_id(nic_dev->hwdev);
- cos_cfg_out->func_cos_bitmap = (u8)nic_dev->func_dft_cos_bitmap;
- cos_cfg_out->port_cos_bitmap = (u8)nic_dev->port_dft_cos_bitmap;
- cos_cfg_out->func_max_cos_num = nic_dev->cos_config_num_max;
+ cos_cfg_out->func_cos_bitmap = (u8)dcb->func_dft_cos_bitmap;
+ cos_cfg_out->port_cos_bitmap = (u8)dcb->port_dft_cos_bitmap;
+ cos_cfg_out->func_max_cos_num = dcb->cos_config_num_max;
return 0;
}
@@ -803,7 +868,13 @@ static int get_inter_num(struct hinic3_nic_dev *nic_dev, const void *buf_in,
intr_num = hinic3_intr_num(nic_dev->hwdev);
- if (!buf_out || !out_size || *out_size != sizeof(u16)) {
+ if (!buf_out || !out_size) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_out or out_size is NULL.\n");
+ return -EINVAL;
+ }
+
+ if (*out_size != sizeof(u16)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%u, expect: %lu\n",
*out_size, sizeof(u16));
@@ -817,7 +888,13 @@ static int get_inter_num(struct hinic3_nic_dev *nic_dev, const void *buf_in,
static int get_netdev_name(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
- if (!buf_out || !out_size || *out_size != IFNAMSIZ) {
+ if (!buf_out || !out_size) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_out or out_size is NULL.\n");
+ return -EINVAL;
+ }
+
+ if (*out_size != IFNAMSIZ) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%u, expect: %u\n",
*out_size, IFNAMSIZ);
@@ -829,8 +906,9 @@ static int get_netdev_name(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return 0;
}
-static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf_in,
- u32 in_size, void *buf_out, u32 *out_size)
+static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev,
+ const void *buf_in, u32 in_size,
+ void *buf_out, u32 *out_size)
{
struct net_device *net_dev = nic_dev->netdev;
int *tx_timeout = buf_out;
@@ -839,7 +917,8 @@ static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf
return -EINVAL;
if (*out_size != sizeof(int)) {
- nicif_err(nic_dev, drv, net_dev, "Unexpect buf size from user, out_size: %u, expect: %lu\n",
+ nicif_err(nic_dev, drv, net_dev,
+ "Unexpect buf size from user, out_size: %u, expect: %lu\n",
*out_size, sizeof(int));
return -EINVAL;
}
@@ -849,8 +928,9 @@ static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf
return 0;
}
-static int set_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf_in,
- u32 in_size, void *buf_out, u32 *out_size)
+static int set_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev,
+ const void *buf_in, u32 in_size,
+ void *buf_out, u32 *out_size)
{
struct net_device *net_dev = nic_dev->netdev;
const int *tx_timeout = buf_in;
@@ -859,13 +939,15 @@ static int set_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf
return -EINVAL;
if (in_size != sizeof(int)) {
- nicif_err(nic_dev, drv, net_dev, "Unexpect buf size from user, in_size: %u, expect: %lu\n",
+ nicif_err(nic_dev, drv, net_dev,
+ "Unexpect buf size from user, in_size: %u, expect: %lu\n",
in_size, sizeof(int));
return -EINVAL;
}
net_dev->watchdog_timeo = *tx_timeout * HZ;
- nicif_info(nic_dev, drv, net_dev, "Set tx timeout check period to %ds\n", *tx_timeout);
+ nicif_info(nic_dev, drv, net_dev,
+ "Set tx timeout check period to %ds\n", *tx_timeout);
return 0;
}
@@ -891,6 +973,34 @@ static int get_xsfp_present(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return 0;
}
+static int get_xsfp_tlv_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp *sfp_tlv_info = buf_out;
+ const struct tag_mag_cmd_get_xsfp_tlv_req *sfp_tlv_info_req = buf_in;
+ int err;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ if (*out_size != sizeof(*sfp_tlv_info) ||
+ in_size != sizeof(*sfp_tlv_info_req)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n",
+ in_size, *out_size, sizeof(*sfp_tlv_info));
+ return -EINVAL;
+ }
+
+ err = hinic3_get_sfp_tlv_info(nic_dev->hwdev,
+ sfp_tlv_info, sfp_tlv_info_req);
+ if (err != 0) {
+ sfp_tlv_info->head.status = MT_EIO;
+ return 0;
+ }
+
+ return 0;
+}
+
static int get_xsfp_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
@@ -928,7 +1038,7 @@ static const struct nic_drv_module_handle nic_driv_module_cmd_handle[] = {
{GET_LOOPBACK_MODE, get_loopback_mode},
{SET_LOOPBACK_MODE, set_loopback_mode},
{SET_LINK_MODE, set_link_mode},
- {SET_PF_BW_LIMIT, set_pf_bw_limit},
+ {SET_TX_PF_BW_LIMIT, set_pf_bw_limit},
{GET_PF_BW_LIMIT, get_pf_bw_limit},
{GET_SSET_COUNT, get_sset_count},
{GET_SSET_ITEMS, get_sset_stats},
@@ -940,17 +1050,22 @@ static const struct nic_drv_module_handle nic_driv_module_cmd_handle[] = {
{SET_TX_TIMEOUT, set_netdev_tx_timeout},
{GET_XSFP_PRESENT, get_xsfp_present},
{GET_XSFP_INFO, get_xsfp_info},
+ {GET_XSFP_INFO_COMP_CMIS, get_xsfp_tlv_info},
+ {SET_RX_PF_BW_LIMIT, set_rx_pf_bw_limit}
};
static int send_to_nic_driver(struct hinic3_nic_dev *nic_dev,
u32 cmd, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
- int index, num_cmds = sizeof(nic_driv_module_cmd_handle) /
- sizeof(nic_driv_module_cmd_handle[0]);
+ int index, num_cmds = (int)(sizeof(nic_driv_module_cmd_handle) /
+ sizeof(nic_driv_module_cmd_handle[0]));
enum driver_cmd_type cmd_type = (enum driver_cmd_type)cmd;
int err = 0;
+ if (cmd_type == DCB_STATE || cmd_type == QOS_DEV)
+ rtnl_lock();
+
mutex_lock(&nic_dev->nic_mutex);
for (index = 0; index < num_cmds; index++) {
if (cmd_type ==
@@ -963,6 +1078,9 @@ static int send_to_nic_driver(struct hinic3_nic_dev *nic_dev,
}
mutex_unlock(&nic_dev->nic_mutex);
+ if (cmd_type == DCB_STATE || cmd_type == QOS_DEV)
+ rtnl_unlock();
+
if (index == num_cmds) {
pr_err("Can't find callback for %d\n", cmd_type);
return -EINVAL;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c
index a1fb4af..603a2ab 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c
@@ -24,82 +24,80 @@
u8 hinic3_get_dev_user_cos_num(struct hinic3_nic_dev *nic_dev)
{
- if (nic_dev->hw_dcb_cfg.trust == 0)
- return nic_dev->hw_dcb_cfg.pcp_user_cos_num;
- if (nic_dev->hw_dcb_cfg.trust == 1)
- return nic_dev->hw_dcb_cfg.dscp_user_cos_num;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_PCP)
+ return dcb->hw_dcb_cfg.pcp_user_cos_num;
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_DSCP)
+ return dcb->hw_dcb_cfg.dscp_user_cos_num;
return 0;
}
u8 hinic3_get_dev_valid_cos_map(struct hinic3_nic_dev *nic_dev)
{
- if (nic_dev->hw_dcb_cfg.trust == 0)
- return nic_dev->hw_dcb_cfg.pcp_valid_cos_map;
- if (nic_dev->hw_dcb_cfg.trust == 1)
- return nic_dev->hw_dcb_cfg.dscp_valid_cos_map;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_PCP)
+ return dcb->hw_dcb_cfg.pcp_valid_cos_map;
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_DSCP)
+ return dcb->hw_dcb_cfg.dscp_valid_cos_map;
return 0;
}
void hinic3_update_qp_cos_cfg(struct hinic3_nic_dev *nic_dev, u8 num_cos)
{
- struct hinic3_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg;
- u8 i, remainder, num_sq_per_cos, cur_cos_num = 0;
+ struct hinic3_dcb_config *hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
+ struct hinic3_dcb_config *wanted_dcb_cfg =
+ &nic_dev->dcb->wanted_dcb_cfg;
u8 valid_cos_map = hinic3_get_dev_valid_cos_map(nic_dev);
+ u8 cos_qp_num, cos_qp_offset = 0;
+ u8 i, remainder, num_qp_per_cos;
- if (num_cos == 0)
- return;
-
- num_sq_per_cos = (u8)(nic_dev->q_params.num_qps / num_cos);
- if (num_sq_per_cos == 0)
+ if (num_cos == 0 || nic_dev->q_params.num_qps == 0)
return;
- remainder = nic_dev->q_params.num_qps % num_sq_per_cos;
+ num_qp_per_cos = (u8)(nic_dev->q_params.num_qps / num_cos);
+ remainder = nic_dev->q_params.num_qps % num_cos;
- memset(dcb_cfg->cos_qp_offset, 0, sizeof(dcb_cfg->cos_qp_offset));
- memset(dcb_cfg->cos_qp_num, 0, sizeof(dcb_cfg->cos_qp_num));
+ memset(hw_dcb_cfg->cos_qp_offset, 0, sizeof(hw_dcb_cfg->cos_qp_offset));
+ memset(hw_dcb_cfg->cos_qp_num, 0, sizeof(hw_dcb_cfg->cos_qp_num));
for (i = 0; i < PCP_MAX_UP; i++) {
if (BIT(i) & valid_cos_map) {
- u8 cos_qp_num = num_sq_per_cos;
- u8 cos_qp_offset = (u8)(cur_cos_num * num_sq_per_cos);
-
- if (cur_cos_num < remainder) {
- cos_qp_num++;
- cos_qp_offset += cur_cos_num;
- } else {
- cos_qp_offset += remainder;
- }
-
- cur_cos_num++;
- valid_cos_map -= (u8)BIT(i);
+ cos_qp_num = num_qp_per_cos + ((remainder > 0) ?
+ (remainder--, 1) : 0);
- dcb_cfg->cos_qp_offset[i] = cos_qp_offset;
- dcb_cfg->cos_qp_num[i] = cos_qp_num;
+ hw_dcb_cfg->cos_qp_offset[i] = cos_qp_offset;
+ hw_dcb_cfg->cos_qp_num[i] = cos_qp_num;
hinic3_info(nic_dev, drv, "cos %u, cos_qp_offset=%u cos_qp_num=%u\n",
i, cos_qp_offset, cos_qp_num);
+
+ cos_qp_offset += cos_qp_num;
+ valid_cos_map -= (u8)BIT(i);
}
}
- memcpy(nic_dev->wanted_dcb_cfg.cos_qp_offset, dcb_cfg->cos_qp_offset,
- sizeof(dcb_cfg->cos_qp_offset));
- memcpy(nic_dev->wanted_dcb_cfg.cos_qp_num, dcb_cfg->cos_qp_num,
- sizeof(dcb_cfg->cos_qp_num));
+ memcpy(wanted_dcb_cfg->cos_qp_offset, hw_dcb_cfg->cos_qp_offset,
+ sizeof(hw_dcb_cfg->cos_qp_offset));
+ memcpy(wanted_dcb_cfg->cos_qp_num, hw_dcb_cfg->cos_qp_num,
+ sizeof(hw_dcb_cfg->cos_qp_num));
}
void hinic3_update_tx_db_cos(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
{
+ struct hinic3_dcb_config *hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
u8 i;
u16 start_qid, q_num;
hinic3_set_txq_cos(nic_dev, 0, nic_dev->q_params.num_qps,
- nic_dev->hw_dcb_cfg.default_cos);
+ hw_dcb_cfg->default_cos);
if (!dcb_en)
return;
for (i = 0; i < NIC_DCB_COS_MAX; i++) {
- q_num = (u16)nic_dev->hw_dcb_cfg.cos_qp_num[i];
+ q_num = (u16)hw_dcb_cfg->cos_qp_num[i];
if (q_num) {
- start_qid = (u16)nic_dev->hw_dcb_cfg.cos_qp_offset[i];
+ start_qid = (u16)hw_dcb_cfg->cos_qp_offset[i];
hinic3_set_txq_cos(nic_dev, start_qid, q_num, i);
hinic3_info(nic_dev, drv, "update tx db cos, start_qid %u, q_num=%u cos=%u\n",
@@ -110,30 +108,28 @@ void hinic3_update_tx_db_cos(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
static int hinic3_set_tx_cos_state(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
{
- struct hinic3_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+ struct hinic3_dcb_config *hw_dcb_cfg = &dcb->hw_dcb_cfg;
struct hinic3_dcb_state dcb_state = {0};
u8 i;
int err;
-
- if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- /* VF does not support DCB, use the default cos */
- dcb_cfg->default_cos = (u8)fls(nic_dev->func_dft_cos_bitmap) - 1;
-
- return 0;
- }
+ u32 pcp2cos_size = sizeof(dcb_state.pcp2cos);
+ u32 dscp2cos_size = sizeof(dcb_state.dscp2cos);
dcb_state.dcb_on = dcb_en;
- dcb_state.default_cos = dcb_cfg->default_cos;
- dcb_state.trust = dcb_cfg->trust;
+ dcb_state.default_cos = hw_dcb_cfg->default_cos;
+ dcb_state.trust = hw_dcb_cfg->trust;
if (dcb_en) {
for (i = 0; i < NIC_DCB_COS_MAX; i++)
- dcb_state.pcp2cos[i] = dcb_cfg->pcp2cos[i];
+ dcb_state.pcp2cos[i] = hw_dcb_cfg->pcp2cos[i];
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++)
- dcb_state.dscp2cos[i] = dcb_cfg->dscp2cos[i];
+ dcb_state.dscp2cos[i] = hw_dcb_cfg->dscp2cos[i];
} else {
- memset(dcb_state.pcp2cos, dcb_cfg->default_cos, sizeof(dcb_state.pcp2cos));
- memset(dcb_state.dscp2cos, dcb_cfg->default_cos, sizeof(dcb_state.dscp2cos));
+ memset(dcb_state.pcp2cos, hw_dcb_cfg->default_cos,
+ pcp2cos_size);
+ memset(dcb_state.dscp2cos, hw_dcb_cfg->default_cos,
+ dscp2cos_size);
}
err = hinic3_set_dcb_state(nic_dev->hwdev, &dcb_state);
@@ -143,7 +139,7 @@ static int hinic3_set_tx_cos_state(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
return err;
}
-static int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
+int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
{
int err;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
@@ -169,11 +165,13 @@ static int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
goto rx_configure_fail;
}
- if (dcb_en)
+ if (dcb_en) {
set_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
- else
+ set_bit(HINIC3_DCB_ENABLE, &nic_dev->nic_vram->flags);
+ } else {
clear_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
-
+ clear_bit(HINIC3_DCB_ENABLE, &nic_dev->nic_vram->flags);
+ }
return 0;
rx_configure_fail:
hinic3_set_tx_cos_state(nic_dev, dcb_en ? 0 : 1);
@@ -188,6 +186,7 @@ set_tx_cos_fail:
int hinic3_setup_cos(struct net_device *netdev, u8 cos, u8 netif_run)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int err;
if (cos && test_bit(HINIC3_SAME_RXTX, &nic_dev->flags)) {
@@ -195,9 +194,10 @@ int hinic3_setup_cos(struct net_device *netdev, u8 cos, u8 netif_run)
return -EOPNOTSUPP;
}
- if (cos > nic_dev->cos_config_num_max) {
- nicif_err(nic_dev, drv, netdev, "Invalid num_tc: %u, max cos: %u\n",
- cos, nic_dev->cos_config_num_max);
+ if (cos > dcb->cos_config_num_max) {
+ nicif_err(nic_dev, drv, netdev,
+ "Invalid num_tc: %u, max cos: %u\n",
+ cos, dcb->cos_config_num_max);
return -EINVAL;
}
@@ -223,36 +223,48 @@ static u8 get_cos_num(u8 hw_valid_cos_bitmap)
static void hinic3_sync_dcb_cfg(struct hinic3_nic_dev *nic_dev,
const struct hinic3_dcb_config *dcb_cfg)
{
- struct hinic3_dcb_config *hw_cfg = &nic_dev->hw_dcb_cfg;
+ struct hinic3_dcb_config *hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
- memcpy(hw_cfg, dcb_cfg, sizeof(struct hinic3_dcb_config));
+ memcpy(hw_dcb_cfg, dcb_cfg, sizeof(struct hinic3_dcb_config));
}
static int init_default_dcb_cfg(struct hinic3_nic_dev *nic_dev,
struct hinic3_dcb_config *dcb_cfg)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u8 i, hw_dft_cos_map, port_cos_bitmap, dscp_ind;
int err;
+ int is_in_kexec;
- err = hinic3_cos_valid_bitmap(nic_dev->hwdev, &hw_dft_cos_map, &port_cos_bitmap);
+ err = hinic3_cos_valid_bitmap(nic_dev->hwdev,
+ &hw_dft_cos_map, &port_cos_bitmap);
if (err) {
hinic3_err(nic_dev, drv, "None cos supported\n");
return -EFAULT;
}
- nic_dev->func_dft_cos_bitmap = hw_dft_cos_map;
- nic_dev->port_dft_cos_bitmap = port_cos_bitmap;
- nic_dev->cos_config_num_max = get_cos_num(hw_dft_cos_map);
+ is_in_kexec = vram_get_kexec_flag();
- dcb_cfg->trust = DCB_PCP;
- dcb_cfg->pcp_user_cos_num = nic_dev->cos_config_num_max;
- dcb_cfg->dscp_user_cos_num = nic_dev->cos_config_num_max;
- dcb_cfg->default_cos = (u8)fls(nic_dev->func_dft_cos_bitmap) - 1;
+ dcb->func_dft_cos_bitmap = hw_dft_cos_map;
+ dcb->port_dft_cos_bitmap = port_cos_bitmap;
+
+ dcb->cos_config_num_max = get_cos_num(hw_dft_cos_map);
+
+ if (is_in_kexec == 0) {
+ dcb_cfg->trust = HINIC3_DCB_PCP;
+ dcb_cfg->default_cos = (u8)fls(dcb->func_dft_cos_bitmap) - 1;
+ } else {
+ dcb_cfg->trust = nic_dev->dcb->hw_dcb_cfg.trust;
+ dcb_cfg->default_cos = nic_dev->dcb->hw_dcb_cfg.default_cos;
+ }
+ dcb_cfg->pcp_user_cos_num = dcb->cos_config_num_max;
+ dcb_cfg->dscp_user_cos_num = dcb->cos_config_num_max;
dcb_cfg->pcp_valid_cos_map = hw_dft_cos_map;
dcb_cfg->dscp_valid_cos_map = hw_dft_cos_map;
for (i = 0; i < NIC_DCB_COS_MAX; i++) {
- dcb_cfg->pcp2cos[i] = hw_dft_cos_map & BIT(i) ? i : dcb_cfg->default_cos;
+ dcb_cfg->pcp2cos[i] = hw_dft_cos_map & BIT(i) ?
+ i : (u8)fls(dcb->func_dft_cos_bitmap) - 1;
for (dscp_ind = 0; dscp_ind < NIC_DCB_COS_MAX; dscp_ind++)
dcb_cfg->dscp2cos[i * NIC_DCB_DSCP_NUM + dscp_ind] = dcb_cfg->pcp2cos[i];
}
@@ -276,58 +288,115 @@ int hinic3_configure_dcb(struct net_device *netdev)
int err;
err = hinic3_sync_dcb_state(nic_dev->hwdev, 1,
- test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ? 1 : 0);
+ test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)
+ ? 1 : 0);
if (err) {
hinic3_err(nic_dev, drv, "Set dcb state failed\n");
return err;
}
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
- hinic3_sync_dcb_cfg(nic_dev, &nic_dev->wanted_dcb_cfg);
+ hinic3_sync_dcb_cfg(nic_dev, &nic_dev->dcb->wanted_dcb_cfg);
else
hinic3_dcb_reset_hw_config(nic_dev);
return 0;
}
+static int hinic3_dcb_alloc(struct hinic3_nic_dev *nic_dev)
+{
+ u16 func_id;
+ int is_use_vram;
+
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram) {
+ func_id = hinic3_global_func_id(nic_dev->hwdev);
+ snprintf(nic_dev->dcb_name, VRAM_NAME_MAX_LEN,
+ "%s%hu%s", VRAM_CQM_GLB_FUNC_BASE, func_id,
+ VRAM_NIC_DCB);
+
+ nic_dev->dcb = (struct hinic3_dcb *)hi_vram_kalloc(nic_dev->dcb_name,
+ sizeof(*nic_dev->dcb));
+ if (!nic_dev->dcb) {
+ hinic3_err(nic_dev, drv, "Failed to vram alloc dcb.\n");
+ return -EFAULT;
+ }
+ } else {
+ nic_dev->dcb = kzalloc(sizeof(*nic_dev->dcb), GFP_KERNEL);
+ if (!nic_dev->dcb)
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void hinic3_dcb_free(struct hinic3_nic_dev *nic_dev)
+{
+ int is_use_vram;
+
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram)
+ hi_vram_kfree((void *)nic_dev->dcb, nic_dev->dcb_name,
+ sizeof(*nic_dev->dcb));
+ else
+ kfree(nic_dev->dcb);
+ nic_dev->dcb = NULL;
+}
+
+void hinic3_dcb_deinit(struct hinic3_nic_dev *nic_dev)
+{
+ if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
+ hinic3_sync_dcb_state(nic_dev->hwdev, 1, 0);
+
+ hinic3_dcb_free(nic_dev);
+}
+
int hinic3_dcb_init(struct hinic3_nic_dev *nic_dev)
{
- struct hinic3_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg;
+ struct hinic3_dcb_config *hw_dcb_cfg = NULL;
int err;
u8 dcb_en = test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ? 1 : 0;
- if (HINIC3_FUNC_IS_VF(nic_dev->hwdev))
- return hinic3_set_tx_cos_state(nic_dev, dcb_en);
+ err = hinic3_dcb_alloc(nic_dev);
+ if (err != 0) {
+ hinic3_err(nic_dev, drv, "Dcb alloc failed.\n");
+ return err;
+ }
- err = init_default_dcb_cfg(nic_dev, dcb_cfg);
+ hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
+ err = init_default_dcb_cfg(nic_dev, hw_dcb_cfg);
if (err) {
- hinic3_err(nic_dev, drv, "Initialize dcb configuration failed\n");
+ hinic3_err(nic_dev, drv,
+ "Initialize dcb configuration failed\n");
+ hinic3_dcb_free(nic_dev);
return err;
}
- memcpy(&nic_dev->wanted_dcb_cfg, &nic_dev->hw_dcb_cfg, sizeof(struct hinic3_dcb_config));
+ memcpy(&nic_dev->dcb->wanted_dcb_cfg, hw_dcb_cfg,
+ sizeof(struct hinic3_dcb_config));
hinic3_info(nic_dev, drv, "Support num cos %u, default cos %u\n",
- nic_dev->cos_config_num_max, dcb_cfg->default_cos);
+ nic_dev->dcb->cos_config_num_max, hw_dcb_cfg->default_cos);
err = hinic3_set_tx_cos_state(nic_dev, dcb_en);
if (err) {
hinic3_err(nic_dev, drv, "Set tx cos state failed\n");
+ hinic3_dcb_free(nic_dev);
return err;
}
- sema_init(&nic_dev->dcb_sem, 1);
-
return 0;
}
-static int change_qos_cfg(struct hinic3_nic_dev *nic_dev, const struct hinic3_dcb_config *dcb_cfg)
+static int change_qos_cfg(struct hinic3_nic_dev *nic_dev,
+ const struct hinic3_dcb_config *dcb_cfg)
{
struct net_device *netdev = nic_dev->netdev;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int err = 0;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
- if (test_and_set_bit(HINIC3_DCB_UP_COS_SETTING, &nic_dev->dcb_flags)) {
+ if (test_and_set_bit(HINIC3_DCB_UP_COS_SETTING, &dcb->dcb_flags)) {
nicif_warn(nic_dev, drv, netdev,
"Cos_up map setting in inprocess, please try again later\n");
return -EFAULT;
@@ -337,40 +406,44 @@ static int change_qos_cfg(struct hinic3_nic_dev *nic_dev, const struct hinic3_dc
hinic3_update_qp_cos_cfg(nic_dev, user_cos_num);
- clear_bit(HINIC3_DCB_UP_COS_SETTING, &nic_dev->dcb_flags);
+ clear_bit(HINIC3_DCB_UP_COS_SETTING, &dcb->dcb_flags);
return err;
}
int hinic3_dcbcfg_set_up_bitmap(struct hinic3_nic_dev *nic_dev)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int err, rollback_err;
u8 netif_run = 0;
struct hinic3_dcb_config old_dcb_cfg;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
- memcpy(&old_dcb_cfg, &nic_dev->hw_dcb_cfg, sizeof(struct hinic3_dcb_config));
+ memcpy(&old_dcb_cfg, &dcb->hw_dcb_cfg,
+ sizeof(struct hinic3_dcb_config));
- if (!memcmp(&nic_dev->wanted_dcb_cfg, &old_dcb_cfg, sizeof(struct hinic3_dcb_config))) {
+ if (!memcmp(&dcb->wanted_dcb_cfg, &old_dcb_cfg,
+ sizeof(struct hinic3_dcb_config))) {
nicif_info(nic_dev, drv, nic_dev->netdev,
"Same valid up bitmap, don't need to change anything\n");
return 0;
}
- rtnl_lock();
if (netif_running(nic_dev->netdev)) {
netif_run = 1;
hinic3_vport_down(nic_dev);
}
- err = change_qos_cfg(nic_dev, &nic_dev->wanted_dcb_cfg);
+ err = change_qos_cfg(nic_dev, &dcb->wanted_dcb_cfg);
if (err) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Set cos_up map to hw failed\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Set cos_up map to hw failed\n");
goto change_qos_cfg_fail;
}
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
- err = hinic3_setup_cos(nic_dev->netdev, user_cos_num, netif_run);
+ err = hinic3_setup_cos(nic_dev->netdev,
+ user_cos_num, netif_run);
if (err)
goto set_err;
}
@@ -381,13 +454,12 @@ int hinic3_dcbcfg_set_up_bitmap(struct hinic3_nic_dev *nic_dev)
goto vport_up_fail;
}
- rtnl_unlock();
-
return 0;
vport_up_fail:
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
- hinic3_setup_cos(nic_dev->netdev, user_cos_num ? 0 : user_cos_num, netif_run);
+ hinic3_setup_cos(nic_dev->netdev, user_cos_num
+ ? 0 : user_cos_num, netif_run);
set_err:
rollback_err = change_qos_cfg(nic_dev, &old_dcb_cfg);
@@ -399,7 +471,5 @@ change_qos_cfg_fail:
if (netif_run)
hinic3_vport_up(nic_dev);
- rtnl_unlock();
-
return err;
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h
index 7987f56..e0b35cb 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h
@@ -24,11 +24,6 @@ struct hinic3_tc_cfg {
u16 rsvd;
};
-enum HINIC3_DCB_TRUST {
- DCB_PCP,
- DCB_DSCP,
-};
-
#define PCP_MAX_UP 8
#define DSCP_MAC_UP 64
#define DBG_DFLT_DSCP_VAL 0xFF
@@ -50,6 +45,7 @@ struct hinic3_dcb_config {
u8 hinic3_get_dev_user_cos_num(struct hinic3_nic_dev *nic_dev);
u8 hinic3_get_dev_valid_cos_map(struct hinic3_nic_dev *nic_dev);
int hinic3_dcb_init(struct hinic3_nic_dev *nic_dev);
+void hinic3_dcb_deinit(struct hinic3_nic_dev *nic_dev);
void hinic3_dcb_reset_hw_config(struct hinic3_nic_dev *nic_dev);
int hinic3_configure_dcb(struct net_device *netdev);
int hinic3_setup_cos(struct net_device *netdev, u8 cos, u8 netif_run);
@@ -75,4 +71,5 @@ void hinic3_update_tx_db_cos(struct hinic3_nic_dev *nic_dev, u8 dcb_en);
void hinic3_update_qp_cos_cfg(struct hinic3_nic_dev *nic_dev, u8 num_cos);
void hinic3_vport_down(struct hinic3_nic_dev *nic_dev);
int hinic3_vport_up(struct hinic3_nic_dev *nic_dev);
+int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
index 5a19959..e5e5578 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
@@ -56,9 +56,8 @@ static void hinic3_get_drvinfo(struct net_device *netdev,
return;
}
- err = snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);
- if (err < 0)
- nicif_err(nic_dev, drv, netdev, "Failed to snprintf fw version\n");
+ snprintf(info->fw_version, sizeof(info->fw_version),
+ "%s", mgmt_ver);
}
static u32 hinic3_get_msglevel(struct net_device *netdev)
@@ -86,7 +85,8 @@ static int hinic3_nway_reset(struct net_device *netdev)
while (test_and_set_bit(HINIC3_AUTONEG_RESET, &nic_dev->flags))
msleep(100); /* sleep 100 ms, waiting for another autoneg restart progress done */
- err = hinic3_get_port_info(nic_dev->hwdev, &port_info, HINIC3_CHANNEL_NIC);
+ err = hinic3_get_port_info(nic_dev->hwdev, &port_info,
+ HINIC3_CHANNEL_NIC);
if (err) {
nicif_err(nic_dev, drv, netdev, "Get port info failed\n");
err = -EFAULT;
@@ -273,7 +273,7 @@ static int get_coalesce(struct net_device *netdev,
static int set_queue_coalesce(struct hinic3_nic_dev *nic_dev, u16 q_id,
struct hinic3_intr_coal_info *coal)
{
- struct hinic3_intr_coal_info *intr_coal;
+ struct hinic3_intr_coal_info *intr_coal = NULL;
struct interrupt_info info = {0};
struct net_device *netdev = nic_dev->netdev;
int err;
@@ -367,24 +367,11 @@ static int is_coalesce_exceed_limit(struct net_device *netdev,
return 0;
}
-static int is_coalesce_legal(struct net_device *netdev,
- const struct ethtool_coalesce *coal)
+static int is_coalesce_allowed_change(struct net_device *netdev,
+ const struct ethtool_coalesce *coal)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
struct ethtool_coalesce tmp_coal = {0};
- int err;
-
- if (coal->rx_coalesce_usecs != coal->tx_coalesce_usecs) {
- nicif_err(nic_dev, drv, netdev,
- "tx-usecs must be equal to rx-usecs\n");
- return -EINVAL;
- }
-
- if (coal->rx_max_coalesced_frames != coal->tx_max_coalesced_frames) {
- nicif_err(nic_dev, drv, netdev,
- "tx-frames must be equal to rx-frames\n");
- return -EINVAL;
- }
tmp_coal.cmd = coal->cmd;
tmp_coal.rx_coalesce_usecs = coal->rx_coalesce_usecs;
@@ -409,6 +396,31 @@ static int is_coalesce_legal(struct net_device *netdev,
return -EOPNOTSUPP;
}
+ return 0;
+}
+
+static int is_coalesce_legal(struct net_device *netdev,
+ const struct ethtool_coalesce *coal)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ int err;
+
+ if (coal->rx_coalesce_usecs != coal->tx_coalesce_usecs) {
+ nicif_err(nic_dev, drv, netdev,
+ "tx-usecs must be equal to rx-usecs\n");
+ return -EINVAL;
+ }
+
+ if (coal->rx_max_coalesced_frames != coal->tx_max_coalesced_frames) {
+ nicif_err(nic_dev, drv, netdev,
+ "tx-frames must be equal to rx-frames\n");
+ return -EINVAL;
+ }
+
+ err = is_coalesce_allowed_change(netdev, coal);
+ if (err)
+ return err;
+
err = is_coalesce_exceed_limit(netdev, coal);
if (err)
return err;
@@ -444,8 +456,9 @@ static int is_coalesce_legal(struct net_device *netdev,
return 0;
}
-static inline void check_coalesce_align(struct hinic3_nic_dev *nic_dev, struct net_device *netdev,
- u32 item, u32 unit, char *str)
+static inline void check_coalesce_aligned(struct hinic3_nic_dev *nic_dev,
+ struct net_device *netdev,
+ u32 item, u32 unit, char *str)
{
if (item % unit)
nicif_warn(nic_dev, drv, netdev, "%s in %d units, change to %u\n",
@@ -453,10 +466,12 @@ static inline void check_coalesce_align(struct hinic3_nic_dev *nic_dev, struct n
}
#define CHECK_COALESCE_ALIGN(member, unit) \
- check_coalesce_align(nic_dev, netdev, member, unit, #member)
+ check_coalesce_aligned(nic_dev, netdev, member, unit, #member)
-static inline void check_coalesce_changed(struct hinic3_nic_dev *nic_dev, struct net_device *netdev,
- u32 item, u32 unit, u32 ori_val, char *obj_str, char *str)
+static inline void check_coalesce_changed(struct hinic3_nic_dev *nic_dev,
+ struct net_device *netdev,
+ u32 item, u32 unit, u32 ori_val,
+ char *obj_str, char *str)
{
if ((item / unit) != ori_val)
nicif_info(nic_dev, drv, netdev, "Change %s from %d to %u %s\n",
@@ -466,8 +481,10 @@ static inline void check_coalesce_changed(struct hinic3_nic_dev *nic_dev, struct
#define CHECK_COALESCE_CHANGED(member, unit, ori_val, obj_str) \
check_coalesce_changed(nic_dev, netdev, member, unit, ori_val, obj_str, #member)
-static inline void check_pkt_rate_changed(struct hinic3_nic_dev *nic_dev, struct net_device *netdev,
- u32 item, u32 ori_val, char *obj_str, char *str)
+static inline void check_pkt_rate_changed(struct hinic3_nic_dev *nic_dev,
+ struct net_device *netdev,
+ u32 item, u32 ori_val, char *obj_str,
+ char *str)
{
if (item != ori_val)
nicif_info(nic_dev, drv, netdev, "Change %s from %d to %u %s\n",
@@ -497,19 +514,10 @@ static int set_hw_coal_param(struct hinic3_nic_dev *nic_dev,
return 0;
}
-static int set_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *coal, u16 queue)
+static void check_coalesce_align(struct net_device *netdev,
+ struct ethtool_coalesce *coal)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
- struct hinic3_intr_coal_info intr_coal = {0};
- struct hinic3_intr_coal_info *ori_intr_coal = NULL;
- u32 last_adaptive_rx;
- char obj_str[32] = {0};
- int err = 0;
-
- err = is_coalesce_legal(netdev, coal);
- if (err)
- return err;
CHECK_COALESCE_ALIGN(coal->rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT);
CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames,
@@ -522,6 +530,14 @@ static int set_coalesce(struct net_device *netdev,
COALESCE_TIMER_CFG_UNIT);
CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames_low,
COALESCE_PENDING_LIMIT_UNIT);
+}
+
+static int check_coalesce_change(struct net_device *netdev,
+ u16 queue, struct ethtool_coalesce *coal)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_intr_coal_info *ori_intr_coal = NULL;
+ char obj_str[32] = {0};
if (queue == COALESCE_ALL_QUEUE) {
ori_intr_coal = &nic_dev->intr_coalesce[0];
@@ -552,27 +568,54 @@ static int set_coalesce(struct net_device *netdev,
COALESCE_PENDING_LIMIT_UNIT,
ori_intr_coal->rx_pending_limt_low, obj_str);
- intr_coal.coalesce_timer_cfg =
+ return 0;
+}
+
+static void init_intr_coal_params(struct hinic3_intr_coal_info *intr_coal,
+ struct ethtool_coalesce *coal)
+{
+ intr_coal->coalesce_timer_cfg =
(u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
- intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames /
+ intr_coal->pending_limt = (u8)(coal->rx_max_coalesced_frames /
COALESCE_PENDING_LIMIT_UNIT);
- last_adaptive_rx = nic_dev->adaptive_rx_coal;
- nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
-
- intr_coal.pkt_rate_high = coal->pkt_rate_high;
- intr_coal.rx_usecs_high =
+ intr_coal->pkt_rate_high = coal->pkt_rate_high;
+ intr_coal->rx_usecs_high =
(u8)(coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT);
- intr_coal.rx_pending_limt_high =
+ intr_coal->rx_pending_limt_high =
(u8)(coal->rx_max_coalesced_frames_high /
COALESCE_PENDING_LIMIT_UNIT);
- intr_coal.pkt_rate_low = coal->pkt_rate_low;
- intr_coal.rx_usecs_low =
+ intr_coal->pkt_rate_low = coal->pkt_rate_low;
+ intr_coal->rx_usecs_low =
(u8)(coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT);
- intr_coal.rx_pending_limt_low =
+ intr_coal->rx_pending_limt_low =
(u8)(coal->rx_max_coalesced_frames_low /
COALESCE_PENDING_LIMIT_UNIT);
+}
+
+static int set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *coal, u16 queue)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_intr_coal_info intr_coal = {0};
+ u32 last_adaptive_rx;
+ int err = 0;
+
+ err = is_coalesce_legal(netdev, coal);
+ if (err)
+ return err;
+
+ check_coalesce_align(netdev, coal);
+
+ err = check_coalesce_change(netdev, queue, coal);
+ if (err)
+ return err;
+
+ init_intr_coal_params(&intr_coal, coal);
+
+ last_adaptive_rx = nic_dev->adaptive_rx_coal;
+ nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
/* coalesce timer or pending set to zero will disable coalesce */
if (!nic_dev->adaptive_rx_coal &&
@@ -709,14 +752,16 @@ static int hinic3_set_pauseparam(struct net_device *netdev,
return -EFAULT;
}
- auto_neg = port_info.autoneg_state == PORT_CFG_AN_ON ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ auto_neg = port_info.autoneg_state == PORT_CFG_AN_ON ?
+ AUTONEG_ENABLE : AUTONEG_DISABLE;
if (pause->autoneg != auto_neg) {
nicif_err(nic_dev, drv, netdev,
"To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
return -EOPNOTSUPP;
}
- nic_pause.auto_neg = pause->autoneg == AUTONEG_ENABLE ? PORT_CFG_AN_ON : PORT_CFG_AN_OFF;
+ nic_pause.auto_neg = pause->autoneg == AUTONEG_ENABLE ?
+ PORT_CFG_AN_ON : PORT_CFG_AN_OFF;
nic_pause.rx_pause = (u8)pause->rx_pause;
nic_pause.tx_pause = (u8)pause->tx_pause;
@@ -768,6 +813,14 @@ static int hinic3_get_module_info(struct net_device *netdev,
modinfo->type = ETH_MODULE_SFF_8636;
modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
break;
+ case MODULE_TYPE_DSFP:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
+ break;
+ case MODULE_TYPE_QSFP_CMIS:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
+ break;
default:
nicif_warn(nic_dev, drv, netdev,
"Optical module unknown: 0x%x\n", sfp_type);
@@ -790,6 +843,11 @@ static int hinic3_get_module_eeprom(struct net_device *netdev,
memset(data, 0, ee->len);
err = hinic3_get_sfp_eeprom(nic_dev->hwdev, (u8 *)sfp_data, ee->len);
+ if (err == HINIC3_MGMT_CMD_UNSUPPORTED)
+ err = hinic3_get_tlv_xsfp_eeprom(nic_dev->hwdev,
+ (u8 *)sfp_data,
+ sizeof(sfp_data));
+
if (err)
return err;
@@ -832,7 +890,8 @@ int hinic3_set_rxq_recovery_flag(struct net_device *netdev, u32 priv_flags)
if (test_and_set_bit(HINIC3_RXQ_RECOVERY, &nic_dev->flags))
return 0;
- queue_delayed_work(nic_dev->workq, &nic_dev->rxq_check_work, HZ);
+ queue_delayed_work(nic_dev->workq,
+ &nic_dev->rxq_check_work, HZ);
nicif_info(nic_dev, drv, netdev, "open rxq recovery\n");
} else {
if (!test_and_clear_bit(HINIC3_RXQ_RECOVERY, &nic_dev->flags))
@@ -888,7 +947,8 @@ static int hinic3_set_force_link_flag(struct net_device *netdev, u32 priv_flags)
nicif_info(nic_dev, link, netdev, "Set link up\n");
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
- hinic3_notify_all_vfs_link_changed(nic_dev->hwdev, nic_dev->link_status);
+ hinic3_notify_all_vfs_link_changed(nic_dev->hwdev,
+ nic_dev->link_status);
} else {
if (!test_and_clear_bit(HINIC3_FORCE_LINK_UP, &nic_dev->flags))
return 0;
@@ -919,7 +979,8 @@ static int hinic3_set_force_link_flag(struct net_device *netdev, u32 priv_flags)
}
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
- hinic3_notify_all_vfs_link_changed(nic_dev->hwdev, nic_dev->link_status);
+ hinic3_notify_all_vfs_link_changed(nic_dev->hwdev,
+ nic_dev->link_status);
}
return 0;
@@ -942,7 +1003,6 @@ static int hinic3_set_priv_flags(struct net_device *netdev, u32 priv_flags)
#define PORT_DOWN_ERR_IDX 0
#define LP_DEFAULT_TIME 5 /* seconds */
-#define LP_PKT_LEN 60
#define TEST_TIME_MULTIPLE 5
static int hinic3_run_lp_test(struct hinic3_nic_dev *nic_dev, u32 test_time)
@@ -1086,7 +1146,8 @@ static int do_lp_test(struct hinic3_nic_dev *nic_dev, u32 *flags, u32 test_time,
return err;
}
-static void hinic3_lp_test(struct net_device *netdev, struct ethtool_test *eth_test,
+static void hinic3_lp_test(struct net_device *netdev,
+ struct ethtool_test *eth_test,
u64 *data, u32 test_time)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
@@ -1109,7 +1170,8 @@ static void hinic3_lp_test(struct net_device *netdev, struct ethtool_test *eth_t
netif_carrier_off(netdev);
netif_tx_disable(netdev);
- err = do_lp_test(nic_dev, ð_test->flags, test_time_real, &test_index);
+ err = do_lp_test(nic_dev, ð_test->flags,
+ test_time_real, &test_index);
if (err) {
eth_test->flags |= ETH_TEST_FL_FAILED;
data[test_index] = 1;
@@ -1130,10 +1192,65 @@ static void hinic3_diag_test(struct net_device *netdev,
hinic3_lp_test(netdev, eth_test, data, 0);
}
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+static int hinic3_get_fecparam(struct net_device *netdev,
+ struct ethtool_fecparam *fecparam)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ u8 advertised_fec = 0;
+ u8 supported_fec = 0;
+ int err;
+
+ if (fecparam->cmd != ETHTOOL_GFECPARAM) {
+ nicif_err(nic_dev, drv, netdev,
+ "get fecparam cmd err.exp:0x%x,real:0x%x\n",
+ ETHTOOL_GFECPARAM, fecparam->cmd);
+ return -EINVAL;
+ }
+
+ err = get_fecparam(nic_dev->hwdev, &advertised_fec, &supported_fec);
+ if (err) {
+ nicif_err(nic_dev, drv, netdev, "Get fec param failed\n");
+ return err;
+ }
+ fecparam->active_fec = (u32)advertised_fec;
+ fecparam->fec = (u32)supported_fec;
+
+ nicif_info(nic_dev, drv, netdev, "Get fec param success\n");
+ return 0;
+}
+
+static int hinic3_set_fecparam(struct net_device *netdev,
+ struct ethtool_fecparam *fecparam)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ int err;
+
+ if (fecparam->cmd != ETHTOOL_SFECPARAM) {
+ nicif_err(nic_dev, drv, netdev,
+ "Set fecparam cmd err.exp:0x%x,real:0x%x\n",
+ ETHTOOL_SFECPARAM, fecparam->cmd);
+ return -EINVAL;
+ }
+
+ err = set_fecparam(nic_dev->hwdev, (u8)fecparam->fec);
+ if (err) {
+ nicif_err(nic_dev, drv, netdev, "Set fec param failed\n");
+ return err;
+ }
+
+ nicif_info(nic_dev, drv, netdev, "Set fec param success\n");
+ return 0;
+}
+#endif
+
static const struct ethtool_ops hinic3_ethtool_ops = {
#ifdef SUPPORTED_COALESCE_PARAMS
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
- ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
+ ETHTOOL_COALESCE_PKT_RATE_RX_USECS |
+ ETHTOOL_COALESCE_MAX_FRAMES |
+ ETHTOOL_COALESCE_USECS_LOW_HIGH |
+ ETHTOOL_COALESCE_MAX_FRAMES_LOW_HIGH,
#endif
#ifdef ETHTOOL_GLINKSETTINGS
#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
@@ -1180,6 +1297,10 @@ static const struct ethtool_ops hinic3_ethtool_ops = {
.set_per_queue_coalesce = hinic3_set_per_queue_coalesce,
#endif
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+ .get_fecparam = hinic3_get_fecparam,
+ .set_fecparam = hinic3_set_fecparam,
+#endif
.get_rxnfc = hinic3_get_rxnfc,
.set_rxnfc = hinic3_set_rxnfc,
.get_priv_flags = hinic3_get_priv_flags,
@@ -1240,7 +1361,10 @@ static const struct ethtool_ops_ext hinic3_ethtool_ops_ext = {
static const struct ethtool_ops hinic3vf_ethtool_ops = {
#ifdef SUPPORTED_COALESCE_PARAMS
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
- ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
+ ETHTOOL_COALESCE_PKT_RATE_RX_USECS |
+ ETHTOOL_COALESCE_MAX_FRAMES |
+ ETHTOOL_COALESCE_USECS_LOW_HIGH |
+ ETHTOOL_COALESCE_MAX_FRAMES_LOW_HIGH,
#endif
#ifdef ETHTOOL_GLINKSETTINGS
#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
@@ -1267,6 +1391,11 @@ static const struct ethtool_ops hinic3vf_ethtool_ops = {
.set_per_queue_coalesce = hinic3_set_per_queue_coalesce,
#endif
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+ .get_fecparam = hinic3_get_fecparam,
+ .set_fecparam = hinic3_set_fecparam,
+#endif
+
.get_rxnfc = hinic3_get_rxnfc,
.set_rxnfc = hinic3_set_rxnfc,
.get_priv_flags = hinic3_get_priv_flags,
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c
index b0e6aad..7f2537a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c
@@ -24,11 +24,29 @@
#include "hinic3_tx.h"
#include "hinic3_rx.h"
-#define FPGA_PORT_COUNTER 0
-#define EVB_PORT_COUNTER 1
-u16 mag_support_mode = EVB_PORT_COUNTER;
-module_param(mag_support_mode, ushort, 0444);
-MODULE_PARM_DESC(mag_support_mode, "Set mag port counter support mode, 0:FPGA 1:EVB, default is 1");
+#define HINIC_SET_LINK_STR_LEN 128
+#define HINIC_ETHTOOL_FEC_INFO_LEN 6
+#define HINIC_SUPPORTED_FEC_CMD 0
+#define HINIC_ADVERTISED_FEC_CMD 1
+
+struct hinic3_ethtool_fec {
+ u8 hinic_fec_offset;
+ u8 ethtool_bit_offset;
+};
+
+static struct hinic3_ethtool_fec
+ hinic3_ethtool_fec_info[HINIC_ETHTOOL_FEC_INFO_LEN] = {
+ /* The ethtool does not have the corresponding enumeration variable */
+ {PORT_FEC_NOT_SET, 0xFF},
+ {PORT_FEC_RSFEC, 0x32}, /* ETHTOOL_LINK_MODE_FEC_RS_BIT */
+ /* ETHTOOL_LINK_MODE_FEC_BASER_BIT */
+ {PORT_FEC_BASEFEC, 0x33},
+ {PORT_FEC_NOFEC, 0x31}, /* ETHTOOL_LINK_MODE_FEC_NONE_BIT */
+ /* ETHTOOL_LINK_MODE_FEC_LLRS_BIT: Available only in later versions */
+ {PORT_FEC_LLRSFEC, 0x4A},
+ /* The ethtool does not have the corresponding enumeration variable */
+ {PORT_FEC_AUTO, 0XFF}
+};
struct hinic3_stats {
char name[ETH_GSTRING_LEN];
@@ -36,9 +54,23 @@ struct hinic3_stats {
int offset;
};
+struct hinic3_netdev_link_count_str {
+ u64 link_down_events_phy;
+};
+
+#define HINIC3_NETDEV_LINK_COUNT(_stat_item) { \
+ .name = #_stat_item, \
+ .size = FIELD_SIZEOF(struct hinic3_netdev_link_count_str, _stat_item), \
+ .offset = offsetof(struct hinic3_netdev_link_count_str, _stat_item) \
+}
+
+static struct hinic3_stats hinic3_netdev_link_count[] = {
+ HINIC3_NETDEV_LINK_COUNT(link_down_events_phy),
+};
+
#define HINIC3_NETDEV_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct rtnl_link_stats64, _stat_item), \
+ .size = FIELD_SIZEOF(struct rtnl_link_stats64, _stat_item), \
.offset = offsetof(struct rtnl_link_stats64, _stat_item) \
}
@@ -67,7 +99,7 @@ static struct hinic3_stats hinic3_netdev_stats[] = {
#define HINIC3_NIC_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct hinic3_nic_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_nic_stats, _stat_item), \
.offset = offsetof(struct hinic3_nic_stats, _stat_item) \
}
@@ -84,17 +116,16 @@ static struct hinic3_stats hinic3_nic_dev_stats_extern[] = {
#define HINIC3_RXQ_STAT(_stat_item) { \
.name = "rxq%d_"#_stat_item, \
- .size = sizeof_field(struct hinic3_rxq_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_rxq_stats, _stat_item), \
.offset = offsetof(struct hinic3_rxq_stats, _stat_item) \
}
#define HINIC3_TXQ_STAT(_stat_item) { \
.name = "txq%d_"#_stat_item, \
- .size = sizeof_field(struct hinic3_txq_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_txq_stats, _stat_item), \
.offset = offsetof(struct hinic3_txq_stats, _stat_item) \
}
-/*lint -save -e786*/
static struct hinic3_stats hinic3_rx_queue_stats[] = {
HINIC3_RXQ_STAT(packets),
HINIC3_RXQ_STAT(bytes),
@@ -135,11 +166,9 @@ static struct hinic3_stats hinic3_tx_queue_stats_extern[] = {
HINIC3_TXQ_STAT(rsvd2),
};
-/*lint -restore*/
-
#define HINIC3_FUNC_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct hinic3_vport_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_vport_stats, _stat_item), \
.offset = offsetof(struct hinic3_vport_stats, _stat_item) \
}
@@ -166,7 +195,7 @@ static struct hinic3_stats hinic3_function_stats[] = {
#define HINIC3_PORT_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct mag_cmd_port_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct mag_cmd_port_stats, _stat_item), \
.offset = offsetof(struct mag_cmd_port_stats, _stat_item) \
}
@@ -260,49 +289,22 @@ static struct hinic3_stats hinic3_port_stats[] = {
HINIC3_PORT_STAT(mac_rx_unfilter_pkt_num),
};
-#define HINIC3_FGPA_PORT_STAT(_stat_item) { \
+#define HINIC3_RSFEC_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct hinic3_phy_fpga_port_stats, _stat_item), \
- .offset = offsetof(struct hinic3_phy_fpga_port_stats, _stat_item) \
+ .size = FIELD_SIZEOF(struct mag_cmd_rsfec_stats, _stat_item), \
+ .offset = offsetof(struct mag_cmd_rsfec_stats, _stat_item) \
}
-static struct hinic3_stats g_hinic3_fpga_port_stats[] = {
- HINIC3_FGPA_PORT_STAT(mac_rx_total_octs_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_total_octs_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_under_frame_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_frag_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_64_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_127_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_255_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_511_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_1023_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_max_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_over_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_64_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_127_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_255_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_511_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_1023_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_max_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_over_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_good_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_crc_error_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_broadcast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_multicast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_mac_frame_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_length_err_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_vlan_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_pause_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_unknown_mac_frame_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_good_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_broadcast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_multicast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_underrun_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_mac_frame_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_vlan_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_pause_pkts_port),
+static struct hinic3_stats g_hinic3_rsfec_stats[] = {
+ HINIC3_RSFEC_STAT(rx_err_lane_phy),
};
+#define HINIC3_FGPA_PORT_STAT(_stat_item) { \
+ .name = #_stat_item, \
+ .size = FIELD_SIZEOF(struct hinic3_phy_fpga_port_stats, _stat_item), \
+ .offset = offsetof(struct hinic3_phy_fpga_port_stats, _stat_item) \
+}
+
static char g_hinic_priv_flags_strings[][ETH_GSTRING_LEN] = {
"Symmetric-RSS",
"Force-Link-up",
@@ -318,8 +320,7 @@ u32 hinic3_get_io_stats_size(const struct hinic3_nic_dev *nic_dev)
(ARRAY_LEN(hinic3_tx_queue_stats) +
ARRAY_LEN(hinic3_tx_queue_stats_extern) +
ARRAY_LEN(hinic3_rx_queue_stats) +
- ARRAY_LEN(hinic3_rx_queue_stats_extern)) *
- nic_dev->max_qps;
+ ARRAY_LEN(hinic3_rx_queue_stats_extern)) * nic_dev->max_qps;
return count;
}
@@ -343,72 +344,89 @@ static int dev_stats_pack(struct hinic3_show_item *items, int len,
memcpy(items[item_idx].name, array[j].name,
HINIC3_SHOW_ITEM_LEN);
items[item_idx].hexadecimal = 0;
- items[item_idx].value = get_value_of_ptr(array[j].size,
- stats_ptr + array[j].offset);
+ items[item_idx].value =
+ get_value_of_ptr(array[j].size,
+ stats_ptr + array[j].offset);
item_idx++;
}
return item_idx;
}
-static int queue_stats_pack(struct hinic3_show_item *items, int len,
- struct hinic3_stats *array, void *stats_ptr,
- u16 qid)
+int hinic3_rx_queue_stat_pack(struct hinic3_show_item *item,
+ struct hinic3_stats *stat,
+ struct hinic3_rxq_stats *rxq_stats, u16 qid)
{
- int j;
- int item_idx = 0;
+ snprintf(item->name, HINIC3_SHOW_ITEM_LEN, stat->name, qid);
- for (j = 0; j < len; j++) {
- memcpy(items[item_idx].name, array[j].name,
- HINIC3_SHOW_ITEM_LEN);
- snprintf(items[item_idx].name, HINIC3_SHOW_ITEM_LEN,
- array[j].name, qid);
- items[item_idx].hexadecimal = 0;
- items[item_idx].value = get_value_of_ptr(array[j].size,
- stats_ptr + array[j].offset);
- item_idx++;
- }
+ item->hexadecimal = 0;
+ item->value = get_value_of_ptr(stat->size, (char *)(rxq_stats) +
+ stat->offset);
- return item_idx;
+ return 0;
}
-void hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats)
+int hinic3_tx_queue_stat_pack(struct hinic3_show_item *item,
+ struct hinic3_stats *stat,
+ struct hinic3_txq_stats *txq_stats, u16 qid)
+{
+ snprintf(item->name, HINIC3_SHOW_ITEM_LEN, stat->name, qid);
+
+ item->hexadecimal = 0;
+ item->value = get_value_of_ptr(stat->size, (char *)(txq_stats) +
+ stat->offset);
+
+ return 0;
+}
+
+int hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats)
{
struct hinic3_show_item *items = stats;
int item_idx = 0;
u16 qid;
+ int idx;
+ int ret;
- item_idx += dev_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_nic_dev_stats),
- hinic3_nic_dev_stats, &nic_dev->stats);
- item_idx += dev_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_nic_dev_stats_extern),
- hinic3_nic_dev_stats_extern,
- &nic_dev->stats);
+ dev_stats_pack(items, item_idx, hinic3_nic_dev_stats, &nic_dev->stats);
+ dev_stats_pack(items, item_idx, hinic3_nic_dev_stats_extern, &nic_dev->stats);
for (qid = 0; qid < nic_dev->max_qps; qid++) {
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_tx_queue_stats),
- hinic3_tx_queue_stats,
- &nic_dev->txqs[qid].txq_stats,
- qid);
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_tx_queue_stats_extern),
- hinic3_tx_queue_stats_extern,
- &nic_dev->txqs[qid].txq_stats, qid);
+ for (idx = 0; idx < ARRAY_LEN(hinic3_tx_queue_stats); idx++) {
+ ret = hinic3_tx_queue_stat_pack(&items[item_idx++],
+ &hinic3_tx_queue_stats[idx],
+ &nic_dev->txqs[qid].txq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
+ }
+ }
+
+ for (idx = 0; idx < ARRAY_LEN(hinic3_tx_queue_stats_extern); idx++) {
+ ret = hinic3_tx_queue_stat_pack(&items[item_idx++],
+ &hinic3_tx_queue_stats_extern[idx],
+ &nic_dev->txqs[qid].txq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
}
for (qid = 0; qid < nic_dev->max_qps; qid++) {
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_rx_queue_stats),
- hinic3_rx_queue_stats,
- &nic_dev->rxqs[qid].rxq_stats,
- qid);
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_rx_queue_stats_extern),
- hinic3_rx_queue_stats_extern,
- &nic_dev->rxqs[qid].rxq_stats, qid);
+ for (idx = 0; idx < ARRAY_LEN(hinic3_rx_queue_stats); idx++) {
+ ret = hinic3_rx_queue_stat_pack(&items[item_idx++],
+ &hinic3_rx_queue_stats[idx],
+ &nic_dev->rxqs[qid].rxq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
+ }
+
+ for (idx = 0; idx < ARRAY_LEN(hinic3_rx_queue_stats_extern); idx++) {
+ ret = hinic3_rx_queue_stat_pack(&items[item_idx++],
+ &hinic3_rx_queue_stats_extern[idx],
+ &nic_dev->rxqs[qid].rxq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
+ }
}
+
+ return 0;
}
static char g_hinic3_test_strings[][ETH_GSTRING_LEN] = {
@@ -428,16 +446,14 @@ int hinic3_get_sset_count(struct net_device *netdev, int sset)
q_num = nic_dev->q_params.num_qps;
count = ARRAY_LEN(hinic3_netdev_stats) +
ARRAY_LEN(hinic3_nic_dev_stats) +
+ ARRAY_LEN(hinic3_netdev_link_count) +
ARRAY_LEN(hinic3_function_stats) +
(ARRAY_LEN(hinic3_tx_queue_stats) +
- ARRAY_LEN(hinic3_rx_queue_stats)) *
- q_num;
+ ARRAY_LEN(hinic3_rx_queue_stats)) * q_num;
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- if (mag_support_mode == FPGA_PORT_COUNTER)
- count += ARRAY_LEN(g_hinic3_fpga_port_stats);
- else
- count += ARRAY_LEN(hinic3_port_stats);
+ count += ARRAY_LEN(hinic3_port_stats);
+ count += ARRAY_LEN(g_hinic3_rsfec_stats);
}
return count;
@@ -486,9 +502,9 @@ static void get_drv_queue_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
}
}
-static u16 get_fpga_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
+static u16 get_ethtool_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
{
- struct hinic3_phy_fpga_port_stats *port_stats = NULL;
+ struct mag_cmd_port_stats *port_stats = NULL;
char *p = NULL;
u16 i = 0, j = 0;
int err;
@@ -496,19 +512,19 @@ static u16 get_fpga_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
if (!port_stats) {
memset(&data[i], 0,
- ARRAY_LEN(g_hinic3_fpga_port_stats) * sizeof(*data));
- i += ARRAY_LEN(g_hinic3_fpga_port_stats);
+ ARRAY_LEN(hinic3_port_stats) * sizeof(*data));
+ i += ARRAY_LEN(hinic3_port_stats);
return i;
}
- err = hinic3_get_fpga_phy_port_stats(nic_dev->hwdev, port_stats);
+ err = hinic3_get_phy_port_stats(nic_dev->hwdev, port_stats);
if (err)
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to get port stats from fw\n");
- for (j = 0; j < ARRAY_LEN(g_hinic3_fpga_port_stats); j++, i++) {
- p = (char *)(port_stats) + g_hinic3_fpga_port_stats[j].offset;
- data[i] = (g_hinic3_fpga_port_stats[j].size == sizeof(u64)) ?
+ for (j = 0; j < ARRAY_LEN(hinic3_port_stats); j++, i++) {
+ p = (char *)(port_stats) + hinic3_port_stats[j].offset;
+ data[i] = (hinic3_port_stats[j].size == sizeof(u64)) ?
*(u64 *)p :
*(u32 *)p;
}
@@ -518,34 +534,32 @@ static u16 get_fpga_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
return i;
}
-static u16 get_ethtool_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
+static u16 get_ethtool_rsfec_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
{
- struct mag_cmd_port_stats *port_stats = NULL;
+ struct mag_cmd_rsfec_stats *port_stats = NULL;
char *p = NULL;
u16 i = 0, j = 0;
int err;
- if (mag_support_mode == FPGA_PORT_COUNTER)
- return get_fpga_port_stats(nic_dev, data);
-
port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
if (!port_stats) {
- memset(&data[i], 0,
- ARRAY_LEN(hinic3_port_stats) * sizeof(*data));
- i += ARRAY_LEN(hinic3_port_stats);
- return i;
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to malloc port stats\n");
+ memset(&data[i], 0,
+ ARRAY_LEN(g_hinic3_rsfec_stats) * sizeof(*data));
+ i += ARRAY_LEN(g_hinic3_rsfec_stats);
+ return i;
}
- err = hinic3_get_phy_port_stats(nic_dev->hwdev, port_stats);
+ err = hinic3_get_phy_rsfec_stats(nic_dev->hwdev, port_stats);
if (err)
nicif_err(nic_dev, drv, nic_dev->netdev,
- "Failed to get port stats from fw\n");
+ "Failed to get rsfec stats from fw\n");
- for (j = 0; j < ARRAY_LEN(hinic3_port_stats); j++, i++) {
- p = (char *)(port_stats) + hinic3_port_stats[j].offset;
- data[i] = (hinic3_port_stats[j].size == sizeof(u64)) ?
- *(u64 *)p :
- *(u32 *)p;
+ for (j = 0; j < ARRAY_LEN(g_hinic3_rsfec_stats); j++, i++) {
+ p = (char *)(port_stats) + g_hinic3_rsfec_stats[j].offset;
+ data[i] = (g_hinic3_rsfec_stats[j].size ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
kfree(port_stats);
@@ -569,6 +583,8 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
u16 i = 0, j = 0;
char *p = NULL;
int err;
+ int link_down_events_phy_tmp = 0;
+ struct hinic3_netdev_link_count_str link_count = {0};
#ifdef HAVE_NDO_GET_STATS64
net_stats = dev_get_stats(netdev, &temp);
@@ -586,6 +602,15 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
data[i] = get_value_of_ptr(hinic3_nic_dev_stats[j].size, p);
}
+ err = hinic3_get_link_event_stats(nic_dev->hwdev,
+ &link_down_events_phy_tmp);
+
+ link_count.link_down_events_phy = (u64)link_down_events_phy_tmp;
+ for (j = 0; j < ARRAY_LEN(hinic3_netdev_link_count); j++, i++) {
+ p = (char *)(&link_count) + hinic3_netdev_link_count[j].offset;
+ data[i] = get_value_of_ptr(hinic3_netdev_link_count[j].size, p);
+ }
+
err = hinic3_get_vport_stats(nic_dev->hwdev,
hinic3_global_func_id(nic_dev->hwdev),
&vport_stats);
@@ -598,8 +623,10 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
data[i] = get_value_of_ptr(hinic3_function_stats[j].size, p);
}
- if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
i += get_ethtool_port_stats(nic_dev, data + i);
+ i += get_ethtool_rsfec_stats(nic_dev, data + i);
+ }
get_drv_queue_stats(nic_dev, data + i);
}
@@ -620,6 +647,12 @@ static u16 get_drv_dev_strings(struct hinic3_nic_dev *nic_dev, char *p)
cnt++;
}
+ for (i = 0; i < ARRAY_LEN(hinic3_netdev_link_count); i++) {
+ memcpy(p, hinic3_netdev_link_count[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ cnt++;
+ }
+
return cnt;
}
@@ -634,21 +667,16 @@ static u16 get_hw_stats_strings(struct hinic3_nic_dev *nic_dev, char *p)
}
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- if (mag_support_mode == FPGA_PORT_COUNTER) {
- for (i = 0; i < ARRAY_LEN(g_hinic3_fpga_port_stats);
- i++) {
- memcpy(p, g_hinic3_fpga_port_stats[i].name,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- cnt++;
- }
- } else {
- for (i = 0; i < ARRAY_LEN(hinic3_port_stats); i++) {
- memcpy(p, hinic3_port_stats[i].name,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- cnt++;
- }
+ for (i = 0; i < ARRAY_LEN(hinic3_port_stats); i++) {
+ memcpy(p, hinic3_port_stats[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ cnt++;
+ }
+ for (i = 0; i < ARRAY_LEN(g_hinic3_rsfec_stats); i++) {
+ memcpy(p, g_hinic3_rsfec_stats[i].name,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ cnt++;
}
}
@@ -664,7 +692,8 @@ static u16 get_qp_stats_strings(const struct hinic3_nic_dev *nic_dev, char *p)
for (j = 0; j < ARRAY_LEN(hinic3_tx_queue_stats); j++) {
err = sprintf(p, hinic3_tx_queue_stats[j].name, i);
if (err < 0)
- nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to sprintf tx queue stats name, idx_qps: %u, idx_stats: %u\n",
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to sprintf tx queue stats name, idx_qps: %u, idx_stats: %u\n",
i, j);
p += ETH_GSTRING_LEN;
cnt++;
@@ -675,7 +704,8 @@ static u16 get_qp_stats_strings(const struct hinic3_nic_dev *nic_dev, char *p)
for (j = 0; j < ARRAY_LEN(hinic3_rx_queue_stats); j++) {
err = sprintf(p, hinic3_rx_queue_stats[j].name, i);
if (err < 0)
- nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to sprintf rx queue stats name, idx_qps: %u, idx_stats: %u\n",
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to sprintf rx queue stats name, idx_qps: %u, idx_stats: %u\n",
i, j);
p += ETH_GSTRING_LEN;
cnt++;
@@ -791,7 +821,6 @@ struct hw2ethtool_link_mode {
u32 speed;
};
-/*lint -save -e26 */
static const struct hw2ethtool_link_mode
hw2ethtool_link_mode_table[LINK_MODE_MAX_NUMBERS] = {
[LINK_MODE_GE] = {
@@ -851,8 +880,6 @@ static const struct hw2ethtool_link_mode
},
};
-/*lint -restore */
-
#define GET_SUPPORTED_MODE 0
#define GET_ADVERTISED_MODE 1
@@ -867,21 +894,35 @@ struct cmd_link_settings {
};
#define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \
- set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->supported)
+ set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->supported)
#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \
- set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->advertising)
+ set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->advertising)
-static void ethtool_add_speed_link_mode(__ETHTOOL_DECLARE_LINK_MODE_MASK(bitmap), u32 mode)
+static void ethtool_add_supported_speed_link_mode(struct cmd_link_settings *link_settings,
+ u32 mode)
{
u32 i;
for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) {
if (hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i] >=
- __ETHTOOL_LINK_MODE_MASK_NBITS)
+ __ETHTOOL_LINK_MODE_MASK_NBITS)
continue;
+ set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i],
+ link_settings->supported);
+ }
+}
+static void ethtool_add_advertised_speed_link_mode(struct cmd_link_settings *link_settings,
+ u32 mode)
+{
+ u32 i;
+
+ for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) {
+ if (hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i] >=
+ __ETHTOOL_LINK_MODE_MASK_NBITS)
+ continue;
set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i],
- bitmap);
+ link_settings->advertising);
}
}
@@ -912,9 +953,11 @@ hinic3_add_ethtool_link_mode(struct cmd_link_settings *link_settings,
for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) {
if (hw_link_mode & BIT(link_mode)) {
if (name == GET_SUPPORTED_MODE)
- ethtool_add_speed_link_mode(link_settings->supported, link_mode);
+ ethtool_add_supported_speed_link_mode(link_settings,
+ link_mode);
else
- ethtool_add_speed_link_mode(link_settings->advertising, link_mode);
+ ethtool_add_advertised_speed_link_mode(
+ link_settings, link_mode);
}
}
}
@@ -937,10 +980,15 @@ static int hinic3_link_speed_set(struct hinic3_nic_dev *nic_dev,
err = hinic3_get_link_state(nic_dev->hwdev, &link_state);
if (!err && link_state) {
- link_settings->speed =
- port_info->speed < ARRAY_LEN(hw_to_ethtool_speed) ?
+ if (hinic3_get_bond_create_mode(nic_dev->hwdev)) {
+ link_settings->speed = port_info->bond_speed;
+ } else {
+ link_settings->speed =
+ port_info->speed <
+ ARRAY_LEN(hw_to_ethtool_speed) ?
hw_to_ethtool_speed[port_info->speed] :
(u32)SPEED_UNKNOWN;
+ }
link_settings->duplex = port_info->duplex;
} else {
@@ -956,28 +1004,28 @@ static void hinic3_link_port_type(struct cmd_link_settings *link_settings,
{
switch (port_type) {
case MAG_CMD_WIRE_TYPE_ELECTRIC:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_TP);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_TP);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP);
link_settings->port = PORT_TP;
break;
case MAG_CMD_WIRE_TYPE_AOC:
case MAG_CMD_WIRE_TYPE_MM:
case MAG_CMD_WIRE_TYPE_SM:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
link_settings->port = PORT_FIBRE;
break;
case MAG_CMD_WIRE_TYPE_COPPER:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
link_settings->port = PORT_DA;
break;
case MAG_CMD_WIRE_TYPE_BACKPLANE:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Backplane);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Backplane);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane);
link_settings->port = PORT_NONE;
break;
@@ -1000,19 +1048,56 @@ static int get_link_pause_settings(struct hinic3_nic_dev *nic_dev,
return err;
}
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Pause);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Pause);
if (nic_pause.rx_pause && nic_pause.tx_pause) {
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause);
} else if (nic_pause.tx_pause) {
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Asym_Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause);
} else if (nic_pause.rx_pause) {
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Asym_Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause);
}
return 0;
}
+static bool is_bit_offset_defined(u8 bit_offset)
+{
+ if (bit_offset < __ETHTOOL_LINK_MODE_MASK_NBITS)
+ return true;
+ return false;
+}
+
+static void ethtool_add_supported_advertised_fec(struct cmd_link_settings *link_settings,
+ u32 fec, u8 cmd)
+{
+ u8 i;
+
+ for (i = 0; i < HINIC_ETHTOOL_FEC_INFO_LEN; i++) {
+ if ((fec & BIT(hinic3_ethtool_fec_info[i].hinic_fec_offset)) == 0)
+ continue;
+ if (is_bit_offset_defined(hinic3_ethtool_fec_info[i].ethtool_bit_offset) == true &&
+ cmd == HINIC_ADVERTISED_FEC_CMD) {
+ set_bit(hinic3_ethtool_fec_info[i].ethtool_bit_offset,
+ link_settings->advertising);
+ return; /* There can be only one advertised fec mode. */
+ }
+ if (is_bit_offset_defined(hinic3_ethtool_fec_info[i].ethtool_bit_offset) == true &&
+ cmd == HINIC_SUPPORTED_FEC_CMD)
+ set_bit(hinic3_ethtool_fec_info[i].ethtool_bit_offset,
+ link_settings->supported);
+ }
+}
+
+static void hinic3_link_fec_type(struct cmd_link_settings *link_settings,
+ u32 fec, u32 supported_fec)
+{
+ ethtool_add_supported_advertised_fec(link_settings, supported_fec,
+ HINIC_SUPPORTED_FEC_CMD);
+ ethtool_add_supported_advertised_fec(link_settings, fec,
+ HINIC_ADVERTISED_FEC_CMD);
+}
+
static int get_link_settings(struct net_device *netdev,
struct cmd_link_settings *link_settings)
{
@@ -1033,13 +1118,19 @@ static int get_link_settings(struct net_device *netdev,
hinic3_link_port_type(link_settings, port_info.port_type);
+ /* port_info.fec is bit offset, value is BIT(port_info.fec);
+ * but port_info.supported_fec_mode is bit value
+ */
+ hinic3_link_fec_type(link_settings, BIT(port_info.fec),
+ port_info.supported_fec_mode);
+
link_settings->autoneg = port_info.autoneg_state == PORT_CFG_AN_ON ?
AUTONEG_ENABLE :
AUTONEG_DISABLE;
if (port_info.autoneg_cap)
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Autoneg);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Autoneg);
if (port_info.autoneg_state == PORT_CFG_AN_ON)
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Autoneg);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Autoneg);
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
err = get_link_pause_settings(nic_dev, link_settings);
@@ -1163,23 +1254,18 @@ static int hinic3_set_settings_to_hw(struct hinic3_nic_dev *nic_dev,
struct net_device *netdev = nic_dev->netdev;
struct hinic3_link_ksettings settings = { 0 };
int speed_level = 0;
- char set_link_str[128] = { 0 };
+ char set_link_str[HINIC_SET_LINK_STR_LEN] = {0};
+ char link_info[HINIC_SET_LINK_STR_LEN] = {0};
int err = 0;
- err = snprintf(set_link_str, sizeof(set_link_str) - 1, "%s",
- (bool)(set_settings & HILINK_LINK_SET_AUTONEG) ?
- ((bool)autoneg ? "autong enable " :
- "autong disable ") :
- "");
- if (err < 0)
- return -EINVAL;
+ snprintf(link_info, sizeof(link_info), "%s",
+ (bool)(set_settings & HILINK_LINK_SET_AUTONEG) ?
+ ((bool)autoneg ? "autong enable " : "autong disable ") : "");
if (set_settings & HILINK_LINK_SET_SPEED) {
speed_level = hinic3_ethtool_to_hw_speed_level(speed);
- err = snprintf(set_link_str, sizeof(set_link_str) - 1,
- "%sspeed %u ", set_link_str, speed);
- if (err < 0)
- return -EINVAL;
+ snprintf(set_link_str, sizeof(set_link_str),
+ "%sspeed %u ", link_info, speed);
}
settings.valid_bitmap = set_settings;
@@ -1218,7 +1304,8 @@ static int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed)
#ifdef ETHTOOL_GLINKSETTINGS
#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
int hinic3_set_link_ksettings(struct net_device *netdev,
- const struct ethtool_link_ksettings *link_settings)
+ const
+ struct ethtool_link_ksettings *link_settings)
{
/* Only support to set autoneg and speed */
return set_link_settings(netdev, link_settings->base.autoneg,
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c b/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
index 70346d6..2daa7f9 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
@@ -82,7 +82,7 @@ static struct hinic3_mac_filter *hinic3_add_filter(struct hinic3_nic_dev *nic_de
struct list_head *mac_filter_list,
u8 *addr)
{
- struct hinic3_mac_filter *f;
+ struct hinic3_mac_filter *f = NULL;
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f)
@@ -117,7 +117,7 @@ static void hinic3_del_filter(struct hinic3_nic_dev *nic_dev,
static struct hinic3_mac_filter *hinic3_mac_filter_entry_clone(const struct hinic3_mac_filter *src)
{
- struct hinic3_mac_filter *f;
+ struct hinic3_mac_filter *f = NULL;
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f)
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h b/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h
index ef8c62b..a3136ce 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h
@@ -40,6 +40,7 @@ enum hinic3_channel_id {
HINIC3_CHANNEL_DSW,
HINIC3_CHANNEL_MIG,
HINIC3_CHANNEL_CRYPT,
+ HINIC3_CHANNEL_VROCE,
HINIC3_CHANNEL_MAX = 32,
};
@@ -397,6 +398,16 @@ void hinic3_free_cmd_buf(void *hwdev, struct hinic3_cmd_buf *cmd_buf);
**/
int hinic3_sm_ctr_rd16(void *hwdev, u8 node, u8 instance, u32 ctr_id, u16 *value);
+/**
+ * hinic3_sm_ctr_rd16_clear - small single 16 counter read clear
+ * @hwdev: the hardware device
+ * @node: the node id
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ **/
+int hinic3_sm_ctr_rd16_clear(void *hwdev, u8 node, u8 instance, u32 ctr_id, u16 *value);
+
/**
* @brief hinic3_sm_ctr_rd32 - small single 32 counter read
* @param hwdev: device pointer to hwdev
@@ -810,6 +821,13 @@ int hinic3_dbg_lt_wr_16byte_mask(void *hwdev, u8 dest, u8 instance,
*/
void hinic3_link_event_stats(void *dev, u8 link);
+/**
+ * @brief hinic3_get_link_event_stats - link event stats
+ * @param hwdev: device pointer to hwdev
+ * @param link: link status
+ */
+int hinic3_get_link_event_stats(void *dev, int *link_state);
+
/**
* @brief hinic3_get_hw_pf_infos - get pf infos
* @param hwdev: device pointer to hwdev
@@ -856,4 +874,5 @@ void hinic3_set_api_stop(void *hwdev);
int hinic3_activate_firmware(void *hwdev, u8 cfg_index);
int hinic3_switch_config(void *hwdev, u8 cfg_index);
+bool hinic3_is_optical_module_mode(void *hwdev);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c b/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
index 7e59c81..6525b76 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
@@ -47,12 +47,16 @@ static void qp_add_napi(struct hinic3_irq *irq_cfg)
netif_napi_add_weight(nic_dev->netdev, &irq_cfg->napi,
hinic3_poll, nic_dev->poll_weight);
napi_enable(&irq_cfg->napi);
+ irq_cfg->napi_reign = NAPI_IS_REGIN;
}
-static void qp_del_napi(struct hinic3_irq *irq_cfg)
+void qp_del_napi(struct hinic3_irq *irq_cfg)
{
- napi_disable(&irq_cfg->napi);
- netif_napi_del(&irq_cfg->napi);
+ if (irq_cfg->napi_reign == NAPI_IS_REGIN) {
+ napi_disable(&irq_cfg->napi);
+ netif_napi_del(&irq_cfg->napi);
+ irq_cfg->napi_reign = NAPI_NOT_REGIN;
+ }
}
static irqreturn_t qp_irq(int irq, void *data)
@@ -60,7 +64,8 @@ static irqreturn_t qp_irq(int irq, void *data)
struct hinic3_irq *irq_cfg = (struct hinic3_irq *)data;
struct hinic3_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev);
- hinic3_misx_intr_clear_resend_bit(nic_dev->hwdev, irq_cfg->msix_entry_idx, 1);
+ hinic3_misx_intr_clear_resend_bit(nic_dev->hwdev,
+ irq_cfg->msix_entry_idx, 1);
napi_schedule(&irq_cfg->napi);
@@ -95,7 +100,8 @@ static int hinic3_request_irq(struct hinic3_irq *irq_cfg, u16 q_id)
return err;
}
- err = request_irq(irq_cfg->irq_id, &qp_irq, 0, irq_cfg->irq_name, irq_cfg);
+ err = request_irq(irq_cfg->irq_id, &qp_irq, 0,
+ irq_cfg->irq_name, irq_cfg);
if (err) {
nicif_err(nic_dev, drv, irq_cfg->netdev, "Failed to request Rx irq\n");
qp_del_napi(irq_cfg);
@@ -138,12 +144,8 @@ int hinic3_qps_irq_init(struct hinic3_nic_dev *nic_dev)
local_cpu = cpumask_local_spread(q_id, dev_to_node(&pdev->dev));
cpumask_set_cpu(local_cpu, &irq_cfg->affinity_mask);
- err = snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name),
- "%s_qp%u", nic_dev->netdev->name, q_id);
- if (err < 0) {
- err = -EINVAL;
- goto req_tx_irq_err;
- }
+ snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name),
+ "%s_qp%u", nic_dev->netdev->name, q_id);
err = hinic3_request_irq(irq_cfg, q_id);
if (err) {
@@ -151,20 +153,25 @@ int hinic3_qps_irq_init(struct hinic3_nic_dev *nic_dev)
goto req_tx_irq_err;
}
- hinic3_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
+ irq_cfg->msix_entry_idx,
HINIC3_SET_MSIX_AUTO_MASK);
- hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, HINIC3_MSIX_ENABLE);
+ hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ HINIC3_MSIX_ENABLE);
}
- INIT_DELAYED_WORK(&nic_dev->moderation_task, hinic3_auto_moderation_work);
+ INIT_DELAYED_WORK(&nic_dev->moderation_task,
+ hinic3_auto_moderation_work);
return 0;
req_tx_irq_err:
for (i = 0; i < q_id; i++) {
irq_cfg = &nic_dev->q_params.irq_cfg[i];
- hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, HINIC3_MSIX_DISABLE);
- hinic3_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ HINIC3_MSIX_DISABLE);
+ hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
+ irq_cfg->msix_entry_idx,
HINIC3_CLR_MSIX_AUTO_MASK);
hinic3_release_irq(irq_cfg);
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.h b/drivers/net/ethernet/huawei/hinic3/hinic3_lld.h
deleted file mode 100644
index 2482c5f..0000000
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
-
-#ifndef HINIC3_LLD_H
-#define HINIC3_LLD_H
-
-#include "hinic3_crm.h"
-
-struct hinic3_lld_dev {
- struct pci_dev *pdev;
- void *hwdev;
-};
-
-struct hinic3_uld_info {
- /* When the function does not need to initialize the corresponding uld,
- * @probe needs to return 0 and uld_dev is set to NULL;
- * if uld_dev is NULL, @remove will not be called when uninstalling
- */
- int (*probe)(struct hinic3_lld_dev *lld_dev, void **uld_dev, char *uld_dev_name);
- void (*remove)(struct hinic3_lld_dev *lld_dev, void *uld_dev);
- int (*suspend)(struct hinic3_lld_dev *lld_dev, void *uld_dev, pm_message_t state);
- int (*resume)(struct hinic3_lld_dev *lld_dev, void *uld_dev);
- void (*event)(struct hinic3_lld_dev *lld_dev, void *uld_dev,
- struct hinic3_event_info *event);
- int (*ioctl)(void *uld_dev, u32 cmd, const void *buf_in, u32 in_size,
- void *buf_out, u32 *out_size);
-};
-
-/* hinic3_register_uld - register an upper-layer driver
- * @type: uld service type
- * @uld_info: uld callback
- *
- * Registers an upper-layer driver.
- * Traverse existing devices and call @probe to initialize the uld device.
- */
-int hinic3_register_uld(enum hinic3_service_type type, struct hinic3_uld_info *uld_info);
-
-/**
- * hinic3_unregister_uld - unregister an upper-layer driver
- * @type: uld service type
- *
- * Traverse existing devices and call @remove to uninstall the uld device.
- * Unregisters an existing upper-layer driver.
- */
-void hinic3_unregister_uld(enum hinic3_service_type type);
-
-void lld_hold(void);
-void lld_put(void);
-
-/**
- * @brief hinic3_get_lld_dev_by_chip_name - get lld device by chip name
- * @param chip_name: chip name
- *
- * The value of lld_dev reference increases when lld_dev is obtained. The caller needs
- * to release the reference by calling lld_dev_put.
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_chip_name(const char *chip_name);
-
-/**
- * @brief lld_dev_hold - get reference to lld_dev
- * @param dev: lld device
- *
- * Hold reference to device to keep it from being freed
- **/
-void lld_dev_hold(struct hinic3_lld_dev *dev);
-
-/**
- * @brief lld_dev_put - release reference to lld_dev
- * @param dev: lld device
- *
- * Release reference to device to allow it to be freed
- **/
-void lld_dev_put(struct hinic3_lld_dev *dev);
-
-/**
- * @brief hinic3_get_lld_dev_by_dev_name - get lld device by uld device name
- * @param dev_name: uld device name
- * @param type: uld service type, When the type is SERVICE_T_MAX, try to match
- * all ULD names to get uld_dev
- *
- * The value of lld_dev reference increases when lld_dev is obtained. The caller needs
- * to release the reference by calling lld_dev_put.
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_dev_name(const char *dev_name,
- enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_lld_dev_by_dev_name_unsafe - get lld device by uld device name
- * @param dev_name: uld device name
- * @param type: uld service type, When the type is SERVICE_T_MAX, try to match
- * all ULD names to get uld_dev
- *
- * hinic3_get_lld_dev_by_dev_name_unsafe() is completely analogous to
- * hinic3_get_lld_dev_by_dev_name(), The only difference is that the reference
- * of lld_dev is not increased when lld_dev is obtained.
- *
- * The caller must ensure that lld_dev will not be freed during the remove process
- * when using lld_dev.
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_dev_name_unsafe(const char *dev_name,
- enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_lld_dev_by_chip_and_port - get lld device by chip name and port id
- * @param chip_name: chip name
- * @param port_id: port id
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_chip_and_port(const char *chip_name, u8 port_id);
-
-/**
- * @brief hinic3_get_ppf_lld_dev - get ppf lld device by current function's lld device
- * @param lld_dev: current function's lld device
- *
- * The value of lld_dev reference increases when lld_dev is obtained. The caller needs
- * to release the reference by calling lld_dev_put.
- **/
-struct hinic3_lld_dev *hinic3_get_ppf_lld_dev(struct hinic3_lld_dev *lld_dev);
-
-/**
- * @brief hinic3_get_ppf_lld_dev_unsafe - get ppf lld device by current function's lld device
- * @param lld_dev: current function's lld device
- *
- * hinic3_get_ppf_lld_dev_unsafe() is completely analogous to hinic3_get_ppf_lld_dev(),
- * The only difference is that the reference of lld_dev is not increased when lld_dev is obtained.
- *
- * The caller must ensure that ppf's lld_dev will not be freed during the remove process
- * when using ppf lld_dev.
- **/
-struct hinic3_lld_dev *hinic3_get_ppf_lld_dev_unsafe(struct hinic3_lld_dev *lld_dev);
-
-/**
- * @brief uld_dev_hold - get reference to uld_dev
- * @param lld_dev: lld device
- * @param type: uld service type
- *
- * Hold reference to uld device to keep it from being freed
- **/
-void uld_dev_hold(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief uld_dev_put - release reference to lld_dev
- * @param dev: lld device
- * @param type: uld service type
- *
- * Release reference to uld device to allow it to be freed
- **/
-void uld_dev_put(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_uld_dev - get uld device by lld device
- * @param lld_dev: lld device
- * @param type: uld service type
- *
- * The value of uld_dev reference increases when uld_dev is obtained. The caller needs
- * to release the reference by calling uld_dev_put.
- **/
-void *hinic3_get_uld_dev(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_uld_dev_unsafe - get uld device by lld device
- * @param lld_dev: lld device
- * @param type: uld service type
- *
- * hinic3_get_uld_dev_unsafe() is completely analogous to hinic3_get_uld_dev(),
- * The only difference is that the reference of uld_dev is not increased when uld_dev is obtained.
- *
- * The caller must ensure that uld_dev will not be freed during the remove process
- * when using uld_dev.
- **/
-void *hinic3_get_uld_dev_unsafe(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_chip_name - get chip name by lld device
- * @param lld_dev: lld device
- * @param chip_name: String for storing the chip name
- * @param max_len: Maximum number of characters to be copied for chip_name
- **/
-int hinic3_get_chip_name(struct hinic3_lld_dev *lld_dev, char *chip_name, u16 max_len);
-
-struct card_node *hinic3_get_chip_node_by_lld(struct hinic3_lld_dev *lld_dev);
-
-struct hinic3_hwdev *hinic3_get_sdk_hwdev_by_lld(struct hinic3_lld_dev *lld_dev);
-
-bool hinic3_get_vf_service_load(struct pci_dev *pdev, u16 service);
-
-int hinic3_set_vf_service_load(struct pci_dev *pdev, u16 service,
- bool vf_srv_load);
-
-int hinic3_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id,
- u16 service, bool en);
-
-bool hinic3_get_vf_load_state(struct pci_dev *pdev);
-
-int hinic3_set_vf_load_state(struct pci_dev *pdev, bool vf_load_state);
-
-int hinic3_attach_nic(struct hinic3_lld_dev *lld_dev);
-
-void hinic3_detach_nic(const struct hinic3_lld_dev *lld_dev);
-
-int hinic3_attach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-void hinic3_detach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-const char **hinic3_get_uld_names(void);
-int hinic3_lld_init(void);
-void hinic3_lld_exit(void);
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c
index 2fe808b..688bb7d 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c
@@ -17,11 +17,22 @@
#include "ossl_knl.h"
#include "hinic3_crm.h"
#include "hinic3_hw.h"
+#include "mag_mpu_cmd.h"
+#include "mag_mpu_cmd_defs.h"
#include "hinic3_nic_io.h"
#include "hinic3_nic_cfg.h"
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
#include "hinic3_common.h"
+#include "mag_mpu_cmd_defs.h"
+
+#define BIFUR_RESOURCE_PF_SSID 0x5a1
+#define CAP_INFO_MAX_LEN 512
+#define DEVICE_VENDOR_MAX_LEN 17
+#define READ_RSFEC_REGISTER_DELAY_TIME_MS 500
+
+struct parse_tlv_info g_page_info = {0};
+struct drv_tag_mag_cmd_get_xsfp_tlv_rsp g_xsfp_tlv_info = {0};
static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
@@ -78,8 +89,10 @@ int hinic3_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats)
return -ENOMEM;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (!nic_io)
- return -EINVAL;
+ if (!nic_io) {
+ err = -EINVAL;
+ goto out;
+ }
memset(&stats_info, 0, sizeof(stats_info));
stats_info.port_id = hinic3_physical_port_id(hwdev);
@@ -104,6 +117,64 @@ out:
}
EXPORT_SYMBOL(hinic3_get_phy_port_stats);
+int hinic3_get_phy_rsfec_stats(void *hwdev, struct mag_cmd_rsfec_stats *stats)
+{
+ struct mag_cmd_get_mag_cnt *port_stats = NULL;
+ struct mag_cmd_get_mag_cnt stats_info;
+ u16 out_size = sizeof(*port_stats);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err;
+
+ if (!hwdev || !stats)
+ return -EINVAL;
+
+ port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
+ if (!port_stats)
+ return -ENOMEM;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memset(&stats_info, 0, sizeof(stats_info));
+ stats_info.port_id = hinic3_physical_port_id(hwdev);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_MAG_CNT,
+ &stats_info, sizeof(stats_info),
+ port_stats, &out_size);
+ if (err || !out_size || port_stats->head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get rsfec statistics, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, port_stats->head.status, out_size);
+ err = -EIO;
+ goto out;
+ }
+ /* 读2遍, 清除误码残留 */
+ msleep(READ_RSFEC_REGISTER_DELAY_TIME_MS);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_MAG_CNT, &stats_info,
+ sizeof(stats_info),
+ port_stats, &out_size);
+ if (err || !out_size || port_stats->head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get rsfec statistics, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, port_stats->head.status, out_size);
+ err = -EIO;
+ goto out;
+ }
+
+ memcpy(stats, &port_stats->mag_csr[MAG_RX_RSFEC_ERR_CW_CNT],
+ sizeof(u32));
+
+out:
+ kfree(port_stats);
+
+ return err;
+}
+EXPORT_SYMBOL(hinic3_get_phy_rsfec_stats);
+
int hinic3_set_port_funcs_state(void *hwdev, bool enable)
{
return 0;
@@ -180,6 +251,8 @@ int hinic3_get_loopback_mode(void *hwdev, u8 *mode, u8 *enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
return hinic3_cfg_loopback_mode(nic_io, MGMT_MSG_CMD_OP_GET, mode,
enable);
@@ -195,6 +268,8 @@ int hinic3_set_loopback_mode(void *hwdev, u8 mode, u8 enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) {
nic_err(nic_io->dev_hdl, "Invalid loopback mode %u to set\n",
@@ -218,6 +293,9 @@ int hinic3_set_led_status(void *hwdev, enum mag_led_type type,
return -EFAULT;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memset(&led_info, 0, sizeof(led_info));
led_info.function_id = hinic3_global_func_id(hwdev);
@@ -249,6 +327,8 @@ int hinic3_get_port_info(void *hwdev, struct nic_port_info *port_info,
memset(&port_msg, 0, sizeof(port_msg));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
port_msg.port_id = hinic3_physical_port_id(hwdev);
@@ -268,9 +348,12 @@ int hinic3_get_port_info(void *hwdev, struct nic_port_info *port_info,
port_info->port_type = port_msg.wire_type;
port_info->speed = port_msg.speed;
port_info->fec = port_msg.fec;
+ port_info->lanes = port_msg.lanes;
port_info->supported_mode = port_msg.supported_mode;
port_info->advertised_mode = port_msg.advertised_mode;
-
+ port_info->supported_fec_mode = port_msg.supported_fec_mode;
+ /* switch Gbps to Mbps */
+ port_info->bond_speed = (u32)port_msg.bond_speed * RATE_MBPS_TO_GBPS;
return 0;
}
@@ -306,6 +389,8 @@ int hinic3_set_link_settings(void *hwdev,
memset(&info, 0, sizeof(info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
info.port_id = hinic3_physical_port_id(hwdev);
info.config_bitmap = settings->valid_bitmap;
@@ -335,6 +420,8 @@ int hinic3_get_link_state(void *hwdev, u8 *link_state)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&get_link, 0, sizeof(get_link));
get_link.port_id = hinic3_physical_port_id(hwdev);
@@ -364,10 +451,11 @@ void hinic3_notify_vf_link_status(struct hinic3_nic_io *nic_io,
if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) {
link.status = link_status;
link.port_id = hinic3_physical_port_id(nic_io->hwdev);
- err = hinic3_mbox_to_vf(nic_io->hwdev, vf_id, HINIC3_MOD_HILINK,
- MAG_CMD_GET_LINK_STATUS, &link,
- sizeof(link), &link, &out_size, 0,
- HINIC3_CHANNEL_NIC);
+ err = hinic3_mbox_to_vf_no_ack(nic_io->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) {
nic_warn(nic_io->dev_hdl, "VF%d not initialized, disconnect it\n",
HW_VF_ID_TO_OS(vf_id));
@@ -387,6 +475,8 @@ void hinic3_notify_all_vfs_link_changed(void *hwdev, u8 link_status)
u16 i;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
nic_io->link_status = link_status;
for (i = 1; i <= nic_io->max_vfs; i++) {
if (!nic_io->vf_infos[HW_VF_ID_TO_OS(i)].link_forced)
@@ -394,6 +484,165 @@ void hinic3_notify_all_vfs_link_changed(void *hwdev, u8 link_status)
}
}
+static char *g_hw_to_char_fec[HILINK_FEC_MAX_TYPE] = {
+ "not set", "rsfec", "basefec",
+ "nofec", "llrsfec"};
+static char *g_hw_to_speed_info[PORT_SPEED_UNKNOWN] = {
+ "not set", "10MB", "100MB", "1GB", "10GB",
+ "25GB", "40GB", "50GB", "100GB", "200GB"};
+static char *g_hw_to_an_state_info[PORT_CFG_AN_OFF + 1] = {
+ "not set", "on", "off"};
+
+struct port_type_table {
+ u32 port_type;
+ char *port_type_name;
+};
+
+static const struct port_type_table port_optical_type_table_s[] = {
+ {LINK_PORT_UNKNOWN, "UNKNOWN"},
+ {LINK_PORT_OPTICAL_MM, "optical_sr"},
+ {LINK_PORT_OPTICAL_SM, "optical_lr"},
+ {LINK_PORT_PAS_COPPER, "copper"},
+ {LINK_PORT_ACC, "ACC"},
+ {LINK_PORT_BASET, "baset"},
+ {LINK_PORT_AOC, "AOC"},
+ {LINK_PORT_ELECTRIC, "electric"},
+ {LINK_PORT_BACKBOARD_INTERFACE, "interface"},
+};
+
+static char *get_port_type_name(u32 type)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(port_optical_type_table_s); i++) {
+ if (type == port_optical_type_table_s[i].port_type)
+ return port_optical_type_table_s[i].port_type_name;
+ }
+ return "UNKNOWN TYPE";
+}
+
+static void get_port_type(struct hinic3_nic_io *nic_io,
+ struct mag_cmd_event_port_info *info,
+ char **port_type)
+{
+ if (info->port_type <= LINK_PORT_BACKBOARD_INTERFACE)
+ *port_type = get_port_type_name(info->port_type);
+ else
+ sdk_info(nic_io->dev_hdl, "Unknown port type: %u\n", info->port_type);
+}
+
+static int get_port_temperature_power(struct mag_cmd_event_port_info *info,
+ char *str)
+{
+ char cap_info[CAP_INFO_MAX_LEN];
+
+ memset(cap_info, 0, sizeof(cap_info));
+ snprintf(cap_info, CAP_INFO_MAX_LEN, "%s, %s, Temperature: %u", str,
+ info->sfp_type ? "QSFP" : "SFP", info->cable_temp);
+
+ if (info->sfp_type)
+ snprintf(str, CAP_INFO_MAX_LEN, "%s, rx power: %uuw %uuW %uuW %uuW",
+ cap_info, info->power[0x0], info->power[0x1],
+ info->power[0x2], info->power[0x3]);
+ else
+ snprintf(str, CAP_INFO_MAX_LEN, "%s, rx power: %uuW, tx power: %uuW",
+ cap_info, info->power[0x0], info->power[0x1]);
+
+ return 0;
+}
+
+static void print_cable_info(struct hinic3_nic_io *nic_io, struct mag_cmd_event_port_info *info)
+{
+ char tmp_str[CAP_INFO_MAX_LEN] = {0};
+ char tmp_vendor[DEVICE_VENDOR_MAX_LEN] = {0};
+ char *port_type = "Unknown port type";
+ int i;
+ int err = 0;
+
+ if (info->gpio_insert) {
+ sdk_info(nic_io->dev_hdl, "Cable unpresent\n");
+ return;
+ }
+
+ get_port_type(nic_io, info, &port_type);
+
+ for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) {
+ if (info->vendor_name[i] == ' ')
+ info->vendor_name[i] = '\0';
+ else
+ break;
+ }
+
+ memcpy(tmp_vendor, info->vendor_name, sizeof(info->vendor_name));
+ snprintf(tmp_str, CAP_INFO_MAX_LEN, "Vendor: %s, %s, length: %um, max_speed: %uGbps",
+ tmp_vendor, port_type, info->cable_length, info->max_speed);
+
+ if (info->port_type == LINK_PORT_OPTICAL_MM ||
+ info->port_type == LINK_PORT_AOC) {
+ err = get_port_temperature_power(info, tmp_str);
+ if (err)
+ return;
+ }
+
+ sdk_info(nic_io->dev_hdl, "Cable information: %s\n", tmp_str);
+}
+
+static void print_link_info(struct hinic3_nic_io *nic_io,
+ struct mag_cmd_event_port_info *info,
+ enum hinic3_nic_event_type type)
+{
+ char *fec = "None";
+ char *speed = "None";
+ char *an_state = "None";
+
+ if (info->fec < HILINK_FEC_MAX_TYPE)
+ fec = g_hw_to_char_fec[info->fec];
+ else
+ sdk_info(nic_io->dev_hdl, "Unknown fec type: %u\n", info->fec);
+
+ if (info->an_state > PORT_CFG_AN_OFF) {
+ sdk_info(nic_io->dev_hdl, "an_state %d is invalid",
+ info->an_state);
+ return;
+ }
+
+ an_state = g_hw_to_an_state_info[info->an_state];
+
+ if (info->speed >= PORT_SPEED_UNKNOWN) {
+ sdk_info(nic_io->dev_hdl, "speed %u is invalid", info->speed);
+ return;
+ }
+
+ speed = g_hw_to_speed_info[info->speed];
+ sdk_info(nic_io->dev_hdl, "Link information: speed %s, %s, autoneg %s",
+ speed, fec, an_state);
+}
+
+void print_port_info(struct hinic3_nic_io *nic_io,
+ struct mag_cmd_event_port_info *port_info,
+ enum hinic3_nic_event_type type)
+{
+ print_cable_info(nic_io, port_info);
+
+ print_link_info(nic_io, port_info, type);
+
+ if (type == EVENT_NIC_LINK_UP)
+ return;
+
+ sdk_info(nic_io->dev_hdl, "PMA ctrl: %s, tx %s, rx %s, PMA fifo reg: 0x%x, PMA signal ok reg: 0x%x, RF/LF status reg: 0x%x\n",
+ port_info->pma_ctrl == 1 ? "off" : "on",
+ port_info->tx_enable ? "enable" : "disable",
+ port_info->rx_enable ? "enable" : "disable", port_info->pma_fifo_reg,
+ port_info->pma_signal_ok_reg, port_info->rf_lf);
+ sdk_info(nic_io->dev_hdl, "alos: %u, rx_los: %u, PCS 64 66b reg: 0x%x, PCS link: 0x%x, MAC link: 0x%x PCS_err_cnt: 0x%x\n",
+ port_info->alos, port_info->rx_los, port_info->pcs_64_66b_reg,
+ port_info->pcs_link, port_info->pcs_mac_link,
+ port_info->pcs_err_cnt);
+ sdk_info(nic_io->dev_hdl, "his_link_machine_state = 0x%08x, cur_link_machine_state = 0x%08x\n",
+ port_info->his_link_machine_state,
+ port_info->cur_link_machine_state);
+}
+
static int hinic3_get_vf_link_status_msg_handler(struct hinic3_nic_io *nic_io,
u16 vf_id, void *buf_in,
u16 in_size, void *buf_out,
@@ -433,6 +682,10 @@ static void get_port_info(void *hwdev,
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
if (hinic3_func_type(hwdev) != TYPE_VF && link_status->status) {
err = hinic3_get_port_info(hwdev, &port_info, HINIC3_CHANNEL_NIC);
if (err) {
@@ -457,8 +710,18 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
struct hinic3_event_info event_info = {0};
struct hinic3_event_link_info *link_info = (void *)event_info.event_data;
struct hinic3_nic_io *nic_io = NULL;
+#ifndef __UEFI__
+ struct pci_dev *pdev = NULL;
+#endif
+ /* Ignore link change event */
+ if (hinic3_is_bm_slave_host(hwdev))
+ return;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
link_status = buf_in;
sdk_info(nic_io->dev_hdl, "Link status report received, func_id: %u, status: %u\n",
@@ -475,6 +738,15 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
hinic3_event_callback(hwdev, &event_info);
+#ifndef __UEFI__
+ if (nic_io->pcidev_hdl) {
+ pdev = nic_io->pcidev_hdl;
+ if (pdev->subsystem_device == BIFUR_RESOURCE_PF_SSID) {
+ return;
+ }
+ }
+#endif
+
if (hinic3_func_type(hwdev) != TYPE_VF) {
hinic3_notify_all_vfs_link_changed(hwdev, link_status->status);
ret_link_status = buf_out;
@@ -483,20 +755,142 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
}
}
+static void port_info_event_printf(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct mag_cmd_event_port_info *port_info = buf_in;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct hinic3_event_info event_info;
+ enum hinic3_nic_event_type type;
+
+ if (!hwdev) {
+ pr_err("hwdev is NULL\n");
+ return;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
+
+ if (in_size != sizeof(*port_info)) {
+ sdk_info(nic_io->dev_hdl, "Invalid port info message size %d, should be %ld\n",
+ in_size, sizeof(*port_info));
+ return;
+ }
+
+ ((struct mag_cmd_event_port_info *)buf_out)->head.status = 0;
+
+ type = port_info->event_type;
+ if (type < EVENT_NIC_LINK_DOWN || type > EVENT_NIC_LINK_UP) {
+ sdk_info(nic_io->dev_hdl, "Invalid hilink info report, type: %d\n",
+ type);
+ return;
+ }
+
+ print_port_info(nic_io, port_info, type);
+
+ memset(&event_info, 0, sizeof(event_info));
+ event_info.service = EVENT_SRV_NIC;
+ event_info.type = type;
+
+ *out_size = sizeof(*port_info);
+
+ hinic3_event_callback(hwdev, &event_info);
+}
+
+void hinic3_notify_vf_bond_status(struct hinic3_nic_io *nic_io,
+ u16 vf_id, u8 bond_status)
+{
+ struct mag_cmd_get_bond_status bond;
+ struct vf_data_storage *vf_infos = nic_io->vf_infos;
+ u16 out_size = sizeof(bond);
+ int err;
+
+ memset(&bond, 0, sizeof(bond));
+ if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) {
+ bond.status = bond_status;
+ err = hinic3_mbox_to_vf_no_ack(nic_io->hwdev, vf_id,
+ HINIC3_MOD_HILINK,
+ MAG_CMD_GET_BOND_STATUS, &bond,
+ sizeof(bond), &bond, &out_size,
+ HINIC3_CHANNEL_NIC);
+ if (err == MBOX_ERRCODE_UNKNOWN_DES_FUNC) {
+ nic_warn(nic_io->dev_hdl, "VF %u not initialized, disconnect it\n",
+ HW_VF_ID_TO_OS(vf_id));
+ hinic3_unregister_vf(nic_io, vf_id);
+ return;
+ }
+ if (err || !out_size || bond.head.status)
+ nic_err(nic_io->dev_hdl,
+ "Send bond change event to VF %hu failed, err: %d, status: 0x%x, out_size: 0x%x\n",
+ HW_VF_ID_TO_OS(vf_id), err, bond.head.status,
+ out_size);
+ }
+}
+
+void hinic3_notify_all_vfs_bond_changed(void *hwdev, u8 bond_status)
+{
+ struct hinic3_nic_io *nic_io = NULL;
+ u16 i;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ nic_io->link_status = bond_status;
+ for (i = 1; i <= nic_io->max_vfs; i++)
+ hinic3_notify_vf_bond_status(nic_io, i, bond_status);
+}
+
+static void bond_status_event_handler(void *hwdev, void *buf_in,
+ u16 in_size, void *buf_out, u16 *out_size)
+{
+ struct mag_cmd_get_bond_status *bond_status = NULL;
+ struct hinic3_event_info event_info = {};
+ struct hinic3_nic_io *nic_io = NULL;
+ struct mag_cmd_get_bond_status *ret_bond_status = NULL;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+
+ bond_status = (struct mag_cmd_get_bond_status *)buf_in;
+ sdk_info(nic_io->dev_hdl, "bond status report received, func_id: %u, status: %u\n",
+ hinic3_global_func_id(hwdev), bond_status->status);
+
+ event_info.service = EVENT_SRV_NIC;
+ event_info.type = bond_status->status ?
+ EVENT_NIC_BOND_UP : EVENT_NIC_BOND_DOWN;
+
+ hinic3_event_callback(hwdev, &event_info);
+
+ if (hinic3_func_type(hwdev) != TYPE_VF) {
+ hinic3_notify_all_vfs_bond_changed(hwdev, bond_status->status);
+ ret_bond_status = buf_out;
+ ret_bond_status->head.status = 0;
+ *out_size = sizeof(*ret_bond_status);
+ }
+}
+
static void cable_plug_event(void *hwdev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
struct mag_cmd_wire_event *plug_event = buf_in;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
struct hinic3_nic_io *nic_io = NULL;
struct hinic3_event_info event_info;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
+
rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
rt_cmd->mpu_send_sfp_abs = false;
rt_cmd->mpu_send_sfp_info = false;
+ rt_cmd_ext->mpu_send_xsfp_tlv_info = false;
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
memset(&event_info, 0, sizeof(event_info));
@@ -518,9 +912,12 @@ static void port_sfp_info_event(void *hwdev, void *buf_in, u16 in_size,
{
struct mag_cmd_get_xsfp_info *sfp_info = buf_in;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
if (in_size != sizeof(*sfp_info)) {
sdk_err(nic_io->dev_hdl, "Invalid sfp info cmd, length: %u, should be %ld\n",
in_size, sizeof(*sfp_info));
@@ -528,10 +925,41 @@ static void port_sfp_info_event(void *hwdev, void *buf_in, u16 in_size,
}
rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
memcpy(&rt_cmd->std_sfp_info, sfp_info,
sizeof(struct mag_cmd_get_xsfp_info));
rt_cmd->mpu_send_sfp_info = true;
+ rt_cmd_ext->mpu_send_xsfp_tlv_info = false;
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+}
+
+static void port_xsfp_tlv_info_event(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp *xsfp_tlv_info = buf_in;
+ struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
+ size_t cpy_len = in_size - sizeof(struct mgmt_msg_head) -
+ XSFP_TLV_PRE_INFO_LEN;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
+
+ if (cpy_len > XSFP_CMIS_INFO_MAX_SIZE) {
+ sdk_err(nic_io->dev_hdl, "invalid cpy_len(%lu)\n", cpy_len);
+ return;
+ }
+ rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
+ mutex_lock(&nic_io->nic_cfg.sfp_mutex);
+ rt_cmd_ext->std_xsfp_tlv_info.port_id = xsfp_tlv_info->port_id;
+ memcpy(&rt_cmd_ext->std_xsfp_tlv_info.tlv_buf[0],
+ &xsfp_tlv_info->tlv_buf[0], cpy_len);
+ rt_cmd->mpu_send_sfp_info = false;
+ rt_cmd_ext->mpu_send_xsfp_tlv_info = true;
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
}
@@ -543,6 +971,8 @@ static void port_sfp_abs_event(void *hwdev, void *buf_in, u16 in_size,
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
if (in_size != sizeof(*sfp_abs)) {
sdk_err(nic_io->dev_hdl, "Invalid sfp absent cmd, length: %u, should be %ld\n",
in_size, sizeof(*sfp_abs));
@@ -564,9 +994,11 @@ bool hinic3_if_sfp_absent(void *hwdev)
u8 port_id = hinic3_physical_port_id(hwdev);
u16 out_size = sizeof(sfp_abs);
int err;
- bool sfp_abs_status;
+ bool sfp_abs_status = 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return true;
memset(&sfp_abs, 0, sizeof(sfp_abs));
rt_cmd = &nic_io->nic_cfg.rt_cmd;
@@ -597,10 +1029,184 @@ bool hinic3_if_sfp_absent(void *hwdev)
return (sfp_abs.abs_status == 0 ? false : true);
}
+int hinic3_get_sfp_tlv_info(void *hwdev, struct drv_tag_mag_cmd_get_xsfp_tlv_rsp
+ *sfp_tlv_info,
+ const struct tag_mag_cmd_get_xsfp_tlv_req
+ *sfp_tlv_info_req)
+{
+ struct hinic3_nic_io *nic_io = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
+ u16 out_size = sizeof(*sfp_tlv_info);
+ int err;
+
+ if (!hwdev || !sfp_tlv_info)
+ return -EINVAL;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
+ mutex_lock(&nic_io->nic_cfg.sfp_mutex);
+ if (rt_cmd_ext->mpu_send_xsfp_tlv_info) {
+ if (rt_cmd_ext->std_xsfp_tlv_info.head.status != 0) {
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+ return -EIO;
+ }
+
+ memcpy(sfp_tlv_info, &rt_cmd_ext->std_xsfp_tlv_info,
+ sizeof(*sfp_tlv_info));
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+ return 0;
+ }
+
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_TLV_INFO,
+ (void *)sfp_tlv_info_req,
+ sizeof(*sfp_tlv_info_req),
+ sfp_tlv_info, &out_size);
+ if (sfp_tlv_info->head.status != 0 || err != 0 || out_size == 0) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get port%u tlv sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
+ hinic3_physical_port_id(hwdev), err,
+ sfp_tlv_info->head.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int hinic3_trans_cmis_get_page_pos(u32 page_id, u32 content_len, u32 *pos)
+{
+ if (page_id <= QSFP_CMIS_PAGE_03H) {
+ *pos = (page_id * content_len);
+ return 0;
+ }
+
+ if (page_id == QSFP_CMIS_PAGE_11H) {
+ *pos = (QSFP_CMIS_PAGE_04H * content_len);
+ return 0;
+ }
+
+ if (page_id == QSFP_CMIS_PAGE_12H) {
+ *pos = (QSFP_CMIS_PAGE_05H * content_len);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int hinic3_get_page_key_info(struct mgmt_tlv_info *tlv_info,
+ struct parse_tlv_info *page_info, u8 idx,
+ u32 *total_len)
+{
+ u8 *src_addr = NULL;
+ u8 *dst_addr = NULL;
+ u8 *tmp_addr = NULL;
+ u32 page_id = 0;
+ u32 content_len = 0;
+ u32 src_pos = 0;
+ int ret;
+
+ page_id = MGMT_TLV_GET_U32(tlv_info->value);
+ content_len = tlv_info->length - MGMT_TLV_U32_SIZE;
+ if (page_id == QSFP_CMIS_PAGE_00H) {
+ tmp_addr = (u8 *)(tlv_info + 1);
+ page_info->id = *(tmp_addr + MGMT_TLV_U32_SIZE);
+ }
+
+ ret = hinic3_trans_cmis_get_page_pos(page_id, content_len, &src_pos);
+ if (ret != 0)
+ return ret;
+
+ src_addr = page_info->tlv_page_info + src_pos;
+ tmp_addr = (u8 *)(tlv_info + 1);
+ dst_addr = tmp_addr + MGMT_TLV_U32_SIZE;
+ memcpy(src_addr, dst_addr, content_len);
+
+ if (idx < XSFP_CMIS_PARSE_PAGE_NUM)
+ page_info->tlv_page_num[idx] = page_id;
+
+ *total_len += content_len;
+
+ return 0;
+}
+
+static int hinic3_trans_cmis_tlv_info_to_buf(u8 *sfp_tlv_info,
+ struct parse_tlv_info *page_info)
+{
+ struct mgmt_tlv_info *tlv_info = NULL;
+ u8 *tlv_buf = sfp_tlv_info;
+ u8 idx = 0;
+ u32 total_len = 0;
+ int ret = 0;
+ bool need_continue = true;
+
+ if (!sfp_tlv_info || !page_info)
+ return -EIO;
+
+ while (need_continue) {
+ tlv_info = (struct mgmt_tlv_info *)tlv_buf;
+ switch (tlv_info->type) {
+ case MAG_XSFP_TYPE_PAGE:
+ ret = hinic3_get_page_key_info(tlv_info, page_info,
+ idx, &total_len);
+ if (ret != 0) {
+ pr_err("lib_get_page_key_info fail,ret:0x%x.\n",
+ ret);
+ break;
+ }
+ idx++;
+ break;
+
+ case MAG_XSFP_TYPE_WIRE_TYPE:
+ page_info->wire_type = MGMT_TLV_GET_U32(&tlv_info->value);
+ break;
+
+ case MAG_XSFP_TYPE_END:
+ need_continue = false;
+ break;
+
+ default:
+ break;
+ }
+
+ tlv_buf += (sizeof(struct mgmt_tlv_info) + tlv_info->length);
+ }
+
+ page_info->tlv_page_info_len = total_len;
+
+ return 0;
+}
+
+int hinic3_get_tlv_xsfp_eeprom(void *hwdev, u8 *data, u32 len)
+{
+ int err = 0;
+ struct tag_mag_cmd_get_xsfp_tlv_req xsfp_tlv_info_req = {0};
+
+ xsfp_tlv_info_req.rsp_buf_len = XSFP_CMIS_INFO_MAX_SIZE;
+ xsfp_tlv_info_req.port_id = hinic3_physical_port_id(hwdev);
+ err = hinic3_get_sfp_tlv_info(hwdev, &g_xsfp_tlv_info,
+ &xsfp_tlv_info_req);
+ if (err != 0)
+ return err;
+
+ err = hinic3_trans_cmis_tlv_info_to_buf(g_xsfp_tlv_info.tlv_buf,
+ &g_page_info);
+ if (err)
+ return -ENOMEM;
+
+ memcpy(data, g_page_info.tlv_page_info, len);
+
+ return (err == 0) ? 0 : -ENOMEM;
+}
+
int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info)
{
struct hinic3_nic_io *nic_io = NULL;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ u8 sfp_info_status = 0;
u16 out_size = sizeof(*sfp_info);
int err;
@@ -608,13 +1214,17 @@ int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ sfp_info_status = rt_cmd->std_sfp_info.head.status;
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
if (rt_cmd->mpu_send_sfp_info) {
- if (rt_cmd->std_sfp_info.head.status) {
+ if (sfp_info_status != 0) {
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
- return -EIO;
+ return (sfp_info_status == HINIC3_MGMT_CMD_UNSUPPORTED)
+ ? HINIC3_MGMT_CMD_UNSUPPORTED : -EIO;
}
memcpy(sfp_info, &rt_cmd->std_sfp_info, sizeof(*sfp_info));
@@ -626,7 +1236,12 @@ int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info)
sfp_info->port_id = hinic3_physical_port_id(hwdev);
err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_INFO, sfp_info,
sizeof(*sfp_info), sfp_info, &out_size);
- if (sfp_info->head.status || err || !out_size) {
+ if (sfp_info->head.status == HINIC3_MGMT_CMD_UNSUPPORTED)
+ return HINIC3_MGMT_CMD_UNSUPPORTED;
+
+ if (sfp_info->head.status == HINIC3_MGMT_CMD_UNSUPPORTED)
+ return -EOPNOTSUPP;
+ if (sfp_info->head.status != 0 || err != 0 || out_size == 0) {
nic_err(nic_io->dev_hdl,
"Failed to get port%u sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
hinic3_physical_port_id(hwdev), err,
@@ -642,7 +1257,7 @@ int hinic3_get_sfp_eeprom(void *hwdev, u8 *data, u32 len)
struct mag_cmd_get_xsfp_info sfp_info;
int err;
- if (!hwdev || !data)
+ if (!hwdev || !data || len > PAGE_SIZE)
return -EINVAL;
if (hinic3_if_sfp_absent(hwdev))
@@ -654,7 +1269,7 @@ int hinic3_get_sfp_eeprom(void *hwdev, u8 *data, u32 len)
if (err)
return err;
- memcpy(data, sfp_info.sfp_info, len);
+ memcpy(data, sfp_info.sfp_info, sizeof(sfp_info.sfp_info));
return 0;
}
@@ -664,7 +1279,7 @@ int hinic3_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext)
struct hinic3_nic_io *nic_io = NULL;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
- int err;
+ int err = 0;
if (!hwdev || !sfp_type || !sfp_type_ext)
return -EINVAL;
@@ -677,20 +1292,35 @@ int hinic3_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext)
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
if (rt_cmd->mpu_send_sfp_info) {
- if (rt_cmd->std_sfp_info.head.status) {
+ if (rt_cmd->std_sfp_info.head.status == 0) {
+ *sfp_type = rt_cmd->std_sfp_info.sfp_info[0];
+ *sfp_type_ext = rt_cmd->std_sfp_info.sfp_info[1];
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+ return 0;
+ }
+
+ if (rt_cmd->std_sfp_info.head.status != HINIC3_MGMT_CMD_UNSUPPORTED) {
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
return -EIO;
}
- *sfp_type = rt_cmd->std_sfp_info.sfp_info[0];
- *sfp_type_ext = rt_cmd->std_sfp_info.sfp_info[1];
- mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
- return 0;
+ err = HINIC3_MGMT_CMD_UNSUPPORTED; /* cmis */
}
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
- err = hinic3_get_sfp_eeprom(hwdev, (u8 *)sfp_data,
- STD_SFP_INFO_MAX_SIZE);
+ if (err == 0) {
+ err = hinic3_get_sfp_eeprom(hwdev, (u8 *)sfp_data,
+ STD_SFP_INFO_MAX_SIZE);
+ } else {
+ /* mpu_send_sfp_info is false */
+ err = hinic3_get_tlv_xsfp_eeprom(hwdev, (u8 *)sfp_data,
+ STD_SFP_INFO_MAX_SIZE);
+ }
+
+ if (err == HINIC3_MGMT_CMD_UNSUPPORTED)
+ err = hinic3_get_tlv_xsfp_eeprom(hwdev, (u8 *)sfp_data,
+ STD_SFP_INFO_MAX_SIZE);
+
if (err)
return err;
@@ -796,16 +1426,23 @@ int hinic3_set_pf_bw_limit(void *hwdev, u32 bw_limit)
return -EINVAL;
}
- old_bw_limit = nic_io->nic_cfg.pf_bw_limit;
- nic_io->nic_cfg.pf_bw_limit = bw_limit;
+ if (nic_io->direct == HINIC3_NIC_TX) {
+ old_bw_limit = nic_io->nic_cfg.pf_bw_tx_limit;
+ nic_io->nic_cfg.pf_bw_tx_limit = bw_limit;
+ } else {
+ old_bw_limit = nic_io->nic_cfg.pf_bw_rx_limit;
+ nic_io->nic_cfg.pf_bw_rx_limit = bw_limit;
+ }
err = hinic3_update_pf_bw(hwdev);
if (err) {
- nic_io->nic_cfg.pf_bw_limit = old_bw_limit;
- return err;
+ if (nic_io->direct == HINIC3_NIC_TX)
+ nic_io->nic_cfg.pf_bw_tx_limit = old_bw_limit;
+ else
+ nic_io->nic_cfg.pf_bw_rx_limit = old_bw_limit;
}
- return 0;
+ return err;
}
static const struct vf_msg_handler vf_mag_cmd_handler[] = {
@@ -828,6 +1465,9 @@ int hinic3_pf_mag_mbox_handler(void *hwdev, u16 vf_id,
return -EFAULT;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
for (index = 0; index < cmd_size; index++) {
handler = &vf_mag_cmd_handler[index];
@@ -848,6 +1488,11 @@ static struct nic_event_handler mag_cmd_handler[] = {
.handler = link_status_event_handler,
},
+ {
+ .cmd = MAG_CMD_EVENT_PORT_INFO,
+ .handler = port_info_event_printf,
+ },
+
{
.cmd = MAG_CMD_WIRE_EVENT,
.handler = cable_plug_event,
@@ -862,6 +1507,16 @@ static struct nic_event_handler mag_cmd_handler[] = {
.cmd = MAG_CMD_GET_XSFP_PRESENT,
.handler = port_sfp_abs_event,
},
+
+ {
+ .cmd = MAG_CMD_GET_BOND_STATUS,
+ .handler = bond_status_event_handler,
+ },
+
+ {
+ .cmd = MAG_CMD_GET_XSFP_TLV_INFO,
+ .handler = port_xsfp_tlv_info_event,
+ },
};
static int hinic3_mag_event_handler(void *hwdev, u16 cmd,
@@ -877,6 +1532,9 @@ static int hinic3_mag_event_handler(void *hwdev, u16 cmd,
*out_size = 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
for (i = 0; i < size; i++) {
if (cmd == mag_cmd_handler[i].cmd) {
mag_cmd_handler[i].handler(hwdev, buf_in, in_size,
@@ -917,7 +1575,8 @@ static int _mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in,
u32 i, cmd_cnt = ARRAY_LEN(vf_mag_cmd_handler);
bool cmd_to_pf = false;
- if (hinic3_func_type(hwdev) == TYPE_VF) {
+ if (hinic3_func_type(hwdev) == TYPE_VF &&
+ !hinic3_is_slave_host(hwdev)) {
for (i = 0; i < cmd_cnt; i++) {
if (cmd == vf_mag_cmd_handler[i].cmd) {
cmd_to_pf = true;
@@ -949,3 +1608,123 @@ static int mag_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in,
return _mag_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out,
out_size, channel);
}
+
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+struct fecparam_value_map {
+ u8 hinic3_fec_offset;
+ u8 hinic3_fec_value;
+ u8 ethtool_fec_value;
+};
+
+static void fecparam_convert(u32 opcode, u8 in_fec_param, u8 *out_fec_param)
+{
+ u8 i;
+ u8 fec_value_table_lenth;
+ struct fecparam_value_map fec_value_table[] = {
+ {PORT_FEC_NOT_SET, BIT(PORT_FEC_NOT_SET), ETHTOOL_FEC_NONE},
+ {PORT_FEC_RSFEC, BIT(PORT_FEC_RSFEC), ETHTOOL_FEC_RS},
+ {PORT_FEC_BASEFEC, BIT(PORT_FEC_BASEFEC), ETHTOOL_FEC_BASER},
+ {PORT_FEC_NOFEC, BIT(PORT_FEC_NOFEC), ETHTOOL_FEC_OFF},
+#ifdef ETHTOOL_FEC_LLRS
+ {PORT_FEC_LLRSFEC, BIT(PORT_FEC_LLRSFEC), ETHTOOL_FEC_LLRS},
+#endif
+ {PORT_FEC_AUTO, BIT(PORT_FEC_AUTO), ETHTOOL_FEC_AUTO}
+ };
+
+ *out_fec_param = 0;
+ fec_value_table_lenth = (u8)(sizeof(fec_value_table) / sizeof(struct fecparam_value_map));
+
+ if (opcode == MAG_CMD_OPCODE_SET) {
+ for (i = 0; i < fec_value_table_lenth; i++) {
+ if ((in_fec_param &
+ fec_value_table[i].ethtool_fec_value) != 0)
+ /* The MPU uses the offset to determine the FEC mode. */
+ *out_fec_param =
+ fec_value_table[i].hinic3_fec_offset;
+ }
+ }
+
+ if (opcode == MAG_CMD_OPCODE_GET) {
+ for (i = 0; i < fec_value_table_lenth; i++) {
+ if ((in_fec_param &
+ fec_value_table[i].hinic3_fec_value) != 0)
+ *out_fec_param |=
+ fec_value_table[i].ethtool_fec_value;
+ }
+ }
+}
+
+/* When the ethtool is used to set the FEC mode */
+static bool check_fecparam_is_valid(u8 fec_param)
+{
+ if (fec_param == ETHTOOL_FEC_RS ||
+#ifdef ETHTOOL_FEC_LLRS
+ fec_param == ETHTOOL_FEC_LLRS ||
+#endif
+ fec_param == ETHTOOL_FEC_BASER ||
+ fec_param == ETHTOOL_FEC_OFF) {
+ return true;
+ }
+ return false;
+}
+
+int set_fecparam(void *hwdev, u8 fecparam)
+{
+ struct mag_cmd_cfg_fec_mode fec_msg = {0};
+ struct hinic3_nic_io *nic_io = NULL;
+ u16 out_size = sizeof(fec_msg);
+ u8 advertised_fec = 0;
+ int err;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ if (check_fecparam_is_valid(fecparam) == false) {
+ nic_err(nic_io->dev_hdl, "fec param is invalid, failed to set fec param\n");
+ return -EINVAL;
+ }
+ fecparam_convert(MAG_CMD_OPCODE_SET, fecparam, &advertised_fec);
+ fec_msg.opcode = MAG_CMD_OPCODE_SET;
+ fec_msg.port_id = hinic3_physical_port_id(hwdev);
+ fec_msg.advertised_fec = advertised_fec;
+ err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_CFG_FEC_MODE,
+ &fec_msg, sizeof(fec_msg),
+ &fec_msg, &out_size, HINIC3_CHANNEL_NIC);
+ if (err != 0 || fec_msg.head.status != 0)
+ return -EINVAL;
+ return 0;
+}
+
+int get_fecparam(void *hwdev, u8 *advertised_fec, u8 *supported_fec)
+{
+ struct mag_cmd_cfg_fec_mode fec_msg = {0};
+ struct hinic3_nic_io *nic_io = NULL;
+ u16 out_size = sizeof(fec_msg);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ fec_msg.opcode = MAG_CMD_OPCODE_GET;
+ fec_msg.port_id = hinic3_physical_port_id(hwdev);
+ err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_CFG_FEC_MODE,
+ &fec_msg, sizeof(fec_msg),
+ &fec_msg, &out_size, HINIC3_CHANNEL_NIC);
+ if (err != 0 || fec_msg.head.status != 0)
+ return -EINVAL;
+
+ /* fec_msg.advertised_fec: bit offset,
+ *value is BIT(fec_msg.advertised_fec); fec_msg.supported_fec: value
+ */
+ fecparam_convert(MAG_CMD_OPCODE_GET, BIT(fec_msg.advertised_fec),
+ advertised_fec);
+ fecparam_convert(MAG_CMD_OPCODE_GET, fec_msg.supported_fec,
+ supported_fec);
+ return 0;
+}
+#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
index 6f90c86..7327ee5 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
@@ -20,6 +20,9 @@
#include <linux/debugfs.h>
#include "ossl_knl.h"
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+#include <net/udp_tunnel.h>
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
#include "hinic3_hw.h"
#include "hinic3_crm.h"
#include "hinic3_mt.h"
@@ -35,8 +38,8 @@
#include "hinic3_dcb.h"
#include "hinic3_nic_prof.h"
#include "hinic3_profile.h"
+#include "hinic3_bond.h"
-/*lint -e806*/
#define DEFAULT_POLL_WEIGHT 64
static unsigned int poll_weight = DEFAULT_POLL_WEIGHT;
module_param(poll_weight, uint, 0444);
@@ -68,7 +71,9 @@ static unsigned char set_link_status_follow = HINIC3_LINK_FOLLOW_STATUS_MAX;
module_param(set_link_status_follow, byte, 0444);
MODULE_PARM_DESC(set_link_status_follow, "Set link status follow port status (0=default,1=follow,2=separate,3=unset");
-/*lint +e806*/
+static bool page_pool_enabled = true;
+module_param(page_pool_enabled, bool, 0444);
+MODULE_PARM_DESC(page_pool_enabled, "enable/disable page_pool feature for rxq page management (default enable)");
#define HINIC3_NIC_DEV_WQ_NAME "hinic3_nic_dev_wq"
@@ -80,6 +85,8 @@ MODULE_PARM_DESC(set_link_status_follow, "Set link status follow port status (0=
#define HINIC3_SQ_DEPTH 1024
#define HINIC3_RQ_DEPTH 1024
+#define LRO_ENABLE 1
+
enum hinic3_rx_buff_len {
RX_BUFF_VALID_2KB = 2,
RX_BUFF_VALID_4KB = 4,
@@ -87,12 +94,15 @@ enum hinic3_rx_buff_len {
RX_BUFF_VALID_16KB = 16,
};
+#define NIC_MAX_PF_NUM 32
+
#define CONVERT_UNIT 1024
-#define BIFUR_RESOURCE_PF_SSID 0x5a1
+#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);
+static int hinic3_netdev_event(struct notifier_block *notifier,
+ unsigned long event, void *ptr);
/* used for netdev notifier register/unregister */
static DEFINE_MUTEX(hinic3_netdev_notifiers_mutex);
@@ -101,6 +111,17 @@ static struct notifier_block hinic3_netdev_notifier = {
.notifier_call = hinic3_netdev_event,
};
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+static const struct udp_tunnel_nic_info hinic3_udp_tunnels = {
+ .set_port = hinic3_udp_tunnel_set_port,
+ .unset_port = hinic3_udp_tunnel_unset_port,
+ .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP,
+ .tables = {
+ { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
+ },
+};
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
static void hinic3_register_notifier(struct hinic3_nic_dev *nic_dev)
{
int err;
@@ -134,7 +155,8 @@ static void hinic3_unregister_notifier(struct hinic3_nic_dev *nic_dev)
NETIF_F_SCTP_CRC | NETIF_F_RXCSUM | \
NETIF_F_ALL_TSO)
-static int hinic3_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr)
+static int hinic3_netdev_event(struct notifier_block *notifier,
+ unsigned long event, void *ptr)
{
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
struct net_device *real_dev = NULL;
@@ -266,6 +288,11 @@ static void netdev_feature_init(struct net_device *netdev)
netdev->features |= dft_fts | cso_fts | tso_fts | vlan_fts;
netdev->vlan_features |= dft_fts | cso_fts | tso_fts;
+ if (nic_dev->nic_cap.lro_enable == LRO_ENABLE) {
+ netdev->features |= NETIF_F_LRO;
+ netdev->vlan_features |= NETIF_F_LRO;
+ }
+
#ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
hw_features |= get_netdev_hw_features(netdev);
#else
@@ -306,7 +333,8 @@ static void init_intr_coal_param(struct hinic3_nic_dev *nic_dev)
info->pending_limt = qp_pending_limit;
info->coalesce_timer_cfg = qp_coalesc_timer_cfg;
- info->resend_timer_cfg = HINIC3_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
+ info->resend_timer_cfg =
+ HINIC3_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
info->pkt_rate_high = HINIC3_RX_RATE_HIGH;
info->rx_usecs_high = HINIC3_RX_COAL_TIME_HIGH;
@@ -350,6 +378,7 @@ static int hinic3_init_intr_coalesce(struct hinic3_nic_dev *nic_dev)
static void hinic3_free_intr_coalesce(struct hinic3_nic_dev *nic_dev)
{
kfree(nic_dev->intr_coalesce);
+ nic_dev->intr_coalesce = NULL;
}
static int hinic3_alloc_txrxqs(struct hinic3_nic_dev *nic_dev)
@@ -396,15 +425,18 @@ static void hinic3_free_txrxqs(struct hinic3_nic_dev *nic_dev)
static void hinic3_tx_rx_ops_init(struct hinic3_nic_dev *nic_dev)
{
if (HINIC3_SUPPORT_TX_COMPACT_WQE_OL(nic_dev->hwdev)) {
- nic_dev->tx_rx_ops.tx_set_wqebb_cnt = hinic3_tx_set_compact_offload_wqebb_cnt;
- nic_dev->tx_rx_ops.tx_set_wqe_task = hinic3_tx_set_compact_offload_wqe_task;
+ nic_dev->tx_rx_ops.tx_set_wqebb_cnt =
+ hinic3_tx_set_compact_offload_wqebb_cnt;
+ nic_dev->tx_rx_ops.tx_set_wqe_task =
+ hinic3_tx_set_compact_offload_wqe_task;
} else {
nic_dev->tx_rx_ops.tx_set_wqebb_cnt = hinic3_tx_set_wqebb_cnt;
nic_dev->tx_rx_ops.tx_set_wqe_task = hinic3_tx_set_wqe_task;
}
if (HINIC3_SUPPORT_RX_COMPACT_CQE(nic_dev->hwdev))
- nic_dev->tx_rx_ops.rx_get_cqe_info = hinic3_rx_get_compact_cqe_info;
+ nic_dev->tx_rx_ops.rx_get_cqe_info =
+ hinic3_rx_get_compact_cqe_info;
else
nic_dev->tx_rx_ops.rx_get_cqe_info = hinic3_rx_get_cqe_info;
}
@@ -420,53 +452,47 @@ static void hinic3_sw_deinit(struct hinic3_nic_dev *nic_dev)
HINIC3_CHANNEL_NIC);
hinic3_clear_rss_config(nic_dev);
- if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
- hinic3_sync_dcb_state(nic_dev->hwdev, 1, 0);
+
+ hinic3_dcb_deinit(nic_dev);
}
-static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
+static void hinic3_netdev_mtu_init(struct net_device *netdev)
+{
+ /* MTU range: 384 - 9600 */
+#ifdef HAVE_NETDEVICE_MIN_MAX_MTU
+ netdev->min_mtu = HINIC3_MIN_MTU_SIZE;
+ netdev->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
+#endif
+
+#ifdef HAVE_NETDEVICE_EXTENDED_MIN_MAX_MTU
+ netdev->extended->min_mtu = HINIC3_MIN_MTU_SIZE;
+ netdev->extended->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
+#endif
+}
+
+static int hinic3_set_default_mac(struct hinic3_nic_dev *nic_dev)
{
struct net_device *netdev = nic_dev->netdev;
u8 mac_addr[ETH_ALEN];
- u64 nic_features;
int err = 0;
- nic_features = hinic3_get_feature_cap(nic_dev->hwdev);
- /* You can update the features supported by the driver according to the
- * scenario here
- */
- nic_features &= NIC_DRV_DEFAULT_FEATURE;
- hinic3_update_nic_feature(nic_dev->hwdev, nic_features);
-
- sema_init(&nic_dev->port_state_sem, 1);
-
- err = hinic3_dcb_init(nic_dev);
- if (err) {
- nic_err(&nic_dev->pdev->dev, "Failed to init dcb\n");
- return -EFAULT;
- }
-
- nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH;
- nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH;
-
- hinic3_try_to_enable_rss(nic_dev);
-
err = hinic3_get_default_mac(nic_dev->hwdev, mac_addr);
if (err) {
nic_err(&nic_dev->pdev->dev, "Failed to get MAC address\n");
- goto get_mac_err;
+ return err;
}
+
eth_hw_addr_set(netdev, mac_addr);
if (!is_valid_ether_addr(netdev->dev_addr)) {
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
nic_err(&nic_dev->pdev->dev, "Invalid MAC address %pM\n",
- netdev->dev_addr);
- err = -EIO;
- goto err_mac;
- }
+ netdev->dev_addr);
+ return -EIO;
+ }
- nic_info(&nic_dev->pdev->dev, "Invalid MAC address %pM, using random\n",
+ nic_info(&nic_dev->pdev->dev,
+ "Invalid MAC address %pM, using random\n",
netdev->dev_addr);
eth_hw_addr_random(netdev);
}
@@ -478,21 +504,62 @@ static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
* MAC, and we can't consider this condition is error status during
* driver probe procedure.
*/
- if (err && err != HINIC3_PF_SET_VF_ALREADY) {
+ if (err && err != HINIC3_PF_SET_VF_ALREADY)
nic_err(&nic_dev->pdev->dev, "Failed to set default MAC\n");
- goto set_mac_err;
+
+ if (err == HINIC3_PF_SET_VF_ALREADY)
+ return 0;
+
+ return err;
+}
+
+static void hinic3_outband_cfg_init(struct hinic3_nic_dev *nic_dev)
+{
+ u16 outband_default_vid = 0;
+ int err = 0;
+
+ if (!nic_dev->nic_cap.outband_vlan_cfg_en)
+ return;
+
+ err = hinic3_get_outband_vlan_cfg(nic_dev->hwdev, &outband_default_vid);
+ if (err) {
+ nic_err(&nic_dev->pdev->dev,
+ "Failed to get_outband_cfg, err: %d\n", err);
+ return;
}
- /* MTU range: 384 - 9600 */
-#ifdef HAVE_NETDEVICE_MIN_MAX_MTU
- netdev->min_mtu = HINIC3_MIN_MTU_SIZE;
- netdev->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
-#endif
+ nic_dev->outband_cfg.outband_default_vid = outband_default_vid;
+}
-#ifdef HAVE_NETDEVICE_EXTENDED_MIN_MAX_MTU
- netdev->extended->min_mtu = HINIC3_MIN_MTU_SIZE;
- netdev->extended->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
-#endif
+static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
+{
+ struct net_device *netdev = nic_dev->netdev;
+ u64 nic_features;
+ int err = 0;
+
+ nic_features = hinic3_get_feature_cap(nic_dev->hwdev);
+ /* You can update the features supported by the driver according to the
+ * scenario here
+ */
+ nic_features &= NIC_DRV_DEFAULT_FEATURE;
+ hinic3_update_nic_feature(nic_dev->hwdev, nic_features);
+
+ err = hinic3_dcb_init(nic_dev);
+ if (err) {
+ nic_err(&nic_dev->pdev->dev, "Failed to init dcb\n");
+ return -EFAULT;
+ }
+
+ nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH;
+ nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH;
+
+ hinic3_try_to_enable_rss(nic_dev);
+
+ err = hinic3_set_default_mac(nic_dev);
+ if (err)
+ goto set_mac_err;
+
+ hinic3_netdev_mtu_init(netdev);
err = hinic3_alloc_txrxqs(nic_dev);
if (err) {
@@ -500,6 +567,8 @@ static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
goto alloc_qps_err;
}
+ hinic3_outband_cfg_init(nic_dev);
+
hinic3_tx_rx_ops_init(nic_dev);
return 0;
@@ -510,8 +579,6 @@ alloc_qps_err:
HINIC3_CHANNEL_NIC);
set_mac_err:
-err_mac:
-get_mac_err:
hinic3_clear_rss_config(nic_dev);
return err;
@@ -623,7 +690,8 @@ static void calc_coal_para(struct hinic3_nic_dev *nic_dev,
*pending_limt =
(u8)((rx_rate - q_coal->pkt_rate_low) *
- (q_coal->rx_pending_limt_high - q_coal->rx_pending_limt_low) /
+ (q_coal->rx_pending_limt_high -
+ q_coal->rx_pending_limt_low) /
(q_coal->pkt_rate_high - q_coal->pkt_rate_low) +
q_coal->rx_pending_limt_low);
}
@@ -637,8 +705,10 @@ static void update_queue_coal(struct hinic3_nic_dev *nic_dev, u16 qid,
q_coal = &nic_dev->intr_coalesce[qid];
- if (rx_rate > HINIC3_RX_RATE_THRESH && avg_pkt_size > HINIC3_AVG_PKT_SMALL) {
- calc_coal_para(nic_dev, q_coal, rx_rate, &coalesc_timer_cfg, &pending_limt);
+ if (rx_rate > HINIC3_RX_RATE_THRESH &&
+ avg_pkt_size > HINIC3_AVG_PKT_SMALL) {
+ calc_coal_para(nic_dev, q_coal, rx_rate,
+ &coalesc_timer_cfg, &pending_limt);
} else {
coalesc_timer_cfg = HINIC3_LOWEST_LATENCY;
pending_limt = q_coal->rx_pending_limt_low;
@@ -701,20 +771,55 @@ void hinic3_auto_moderation_work(struct work_struct *work)
static void hinic3_periodic_work_handler(struct work_struct *work)
{
struct delayed_work *delay = to_delayed_work(work);
- struct hinic3_nic_dev *nic_dev = container_of(delay, struct hinic3_nic_dev, periodic_work);
+ struct hinic3_nic_dev *nic_dev =
+ container_of(delay, struct hinic3_nic_dev, periodic_work);
if (test_and_clear_bit(EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag))
- hinic3_fault_event_report(nic_dev->hwdev, HINIC3_FAULT_SRC_TX_TIMEOUT,
+ hinic3_fault_event_report(nic_dev->hwdev,
+ HINIC3_FAULT_SRC_TX_TIMEOUT,
FAULT_LEVEL_SERIOUS_FLR);
queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ);
}
+static void hinic3_vport_stats_work_handler(struct work_struct *work)
+{
+ int err;
+ struct hinic3_vport_stats vport_stats = {0};
+ struct delayed_work *delay = to_delayed_work(work);
+ struct hinic3_nic_dev *nic_dev = container_of(delay,
+ struct hinic3_nic_dev,
+ vport_stats_work);
+ err = hinic3_get_vport_stats(nic_dev->hwdev,
+ hinic3_global_func_id(nic_dev->hwdev),
+ &vport_stats);
+ if (err)
+ nic_err(&nic_dev->pdev->dev, "Failed to get dropped stats from fw\n");
+ else
+ nic_dev->vport_stats.rx_discard_vport =
+ vport_stats.rx_discard_vport;
+ queue_delayed_work(nic_dev->workq, &nic_dev->vport_stats_work, HZ);
+}
+
+static void free_nic_dev_vram(struct hinic3_nic_dev *nic_dev)
+{
+ int is_use_vram = get_use_vram_flag();
+
+ if (is_use_vram != 0)
+ hi_vram_kfree((void *)nic_dev->nic_vram, nic_dev->nic_vram_name,
+ sizeof(struct hinic3_vram));
+ else
+ kfree(nic_dev->nic_vram);
+ nic_dev->nic_vram = NULL;
+}
+
static void free_nic_dev(struct hinic3_nic_dev *nic_dev)
{
hinic3_deinit_nic_prof_adapter(nic_dev);
destroy_workqueue(nic_dev->workq);
kfree(nic_dev->vlan_bitmap);
+ nic_dev->vlan_bitmap = NULL;
+ free_nic_dev_vram(nic_dev);
}
static int setup_nic_dev(struct net_device *netdev,
@@ -724,6 +829,10 @@ static int setup_nic_dev(struct net_device *netdev,
struct hinic3_nic_dev *nic_dev;
char *netdev_name_fmt;
u32 page_num;
+ u16 func_id;
+ int ret;
+ int is_in_kexec = vram_get_kexec_flag();
+ int is_use_vram = get_use_vram_flag();
nic_dev = (struct hinic3_nic_dev *)netdev_priv(netdev);
nic_dev->netdev = netdev;
@@ -738,22 +847,58 @@ static int setup_nic_dev(struct net_device *netdev,
nic_dev->dma_rx_buff_size = RX_BUFF_NUM_PER_PAGE * nic_dev->rx_buff_len;
page_num = nic_dev->dma_rx_buff_size / PAGE_SIZE;
nic_dev->page_order = page_num > 0 ? ilog2(page_num) : 0;
+ nic_dev->page_pool_enabled = page_pool_enabled;
+ nic_dev->outband_cfg.outband_default_vid = 0;
+
+ // value other than 0 indicates hot replace
+ if (is_use_vram != 0) {
+ func_id = hinic3_global_func_id(nic_dev->hwdev);
+ snprintf(nic_dev->nic_vram_name, VRAM_NAME_MAX_LEN,
+ "%s%hu", VRAM_NIC_VRAM, func_id);
+
+ nic_dev->nic_vram = (struct hinic3_vram *)hi_vram_kalloc(nic_dev->nic_vram_name,
+ sizeof(struct hinic3_vram));
+ if (!nic_dev->nic_vram) {
+ nic_err(&pdev->dev, "Failed to allocate nic vram\n");
+ return -ENOMEM;
+ }
+
+ if (is_in_kexec == 0)
+ nic_dev->nic_vram->vram_mtu = netdev->mtu;
+ else
+ netdev->mtu = nic_dev->nic_vram->vram_mtu;
+ } else {
+ nic_dev->nic_vram = kzalloc(sizeof(*nic_dev->nic_vram),
+ GFP_KERNEL);
+ if (!nic_dev->nic_vram)
+ return -ENOMEM;
+
+ nic_dev->nic_vram->vram_mtu = netdev->mtu;
+ }
mutex_init(&nic_dev->nic_mutex);
nic_dev->vlan_bitmap = kzalloc(VLAN_BITMAP_SIZE(nic_dev), GFP_KERNEL);
- if (!nic_dev->vlan_bitmap)
- return -ENOMEM;
+ if (!nic_dev->vlan_bitmap) {
+ nic_err(&pdev->dev, "Failed to allocate vlan bitmap\n");
+ ret = -ENOMEM;
+ goto vlan_bitmap_error;
+ }
nic_dev->workq = create_singlethread_workqueue(HINIC3_NIC_DEV_WQ_NAME);
if (!nic_dev->workq) {
nic_err(&pdev->dev, "Failed to initialize nic workqueue\n");
- kfree(nic_dev->vlan_bitmap);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto create_workq_error;
}
- INIT_DELAYED_WORK(&nic_dev->periodic_work, hinic3_periodic_work_handler);
- INIT_DELAYED_WORK(&nic_dev->rxq_check_work, hinic3_rxq_check_work_handler);
+ INIT_DELAYED_WORK(&nic_dev->periodic_work,
+ hinic3_periodic_work_handler);
+ INIT_DELAYED_WORK(&nic_dev->rxq_check_work,
+ hinic3_rxq_check_work_handler);
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ INIT_DELAYED_WORK(&nic_dev->vport_stats_work,
+ hinic3_vport_stats_work_handler);
INIT_LIST_HEAD(&nic_dev->uc_filter_list);
INIT_LIST_HEAD(&nic_dev->mc_filter_list);
@@ -766,10 +911,23 @@ static int setup_nic_dev(struct net_device *netdev,
hinic3_init_nic_prof_adapter(nic_dev);
netdev_name_fmt = hinic3_get_dft_netdev_name_fmt(nic_dev);
- if (netdev_name_fmt)
- strscpy(netdev->name, netdev_name_fmt, IFNAMSIZ);
+ if (netdev_name_fmt) {
+ ret = strscpy(netdev->name, netdev_name_fmt, IFNAMSIZ);
+ if (ret < 0)
+ goto get_netdev_name_error;
+ }
return 0;
+
+get_netdev_name_error:
+ hinic3_deinit_nic_prof_adapter(nic_dev);
+ destroy_workqueue(nic_dev->workq);
+create_workq_error:
+ kfree(nic_dev->vlan_bitmap);
+ nic_dev->vlan_bitmap = NULL;
+vlan_bitmap_error:
+ free_nic_dev_vram(nic_dev);
+ return ret;
}
static int hinic3_set_default_hw_feature(struct hinic3_nic_dev *nic_dev)
@@ -808,6 +966,31 @@ static int hinic3_set_default_hw_feature(struct hinic3_nic_dev *nic_dev)
return 0;
}
+static void hinic3_bond_init(struct hinic3_nic_dev *nic_dev)
+{
+ u32 bond_id = HINIC3_INVALID_BOND_ID;
+ int err = hinic3_create_bond(nic_dev->hwdev, &bond_id);
+
+ if (err != 0)
+ goto bond_init_failed;
+
+ /* bond id does not change, means this pf is not bond active pf, no log is generated */
+ if (bond_id == HINIC3_INVALID_BOND_ID)
+ return;
+
+ err = hinic3_open_close_bond(nic_dev->hwdev, true);
+ if (err != 0) {
+ hinic3_delete_bond(nic_dev->hwdev);
+ goto bond_init_failed;
+ }
+
+ nic_info(&nic_dev->pdev->dev, "Bond %d init success\n", bond_id);
+ return;
+
+bond_init_failed:
+ nic_err(&nic_dev->pdev->dev, "Bond init failed\n");
+}
+
static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
char *uld_dev_name)
{
@@ -838,6 +1021,12 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
goto err_out;
}
+ err = hinic3_get_dev_cap(lld_dev->hwdev);
+ if (err != 0) {
+ nic_err(&pdev->dev, "Failed to get dev cap\n");
+ goto err_out;
+ }
+
max_qps = hinic3_func_max_nic_qnum(lld_dev->hwdev);
netdev = alloc_etherdev_mq(sizeof(*nic_dev), max_qps);
if (!netdev) {
@@ -870,10 +1059,17 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
hinic3_assign_netdev_ops(nic_dev);
netdev_feature_init(netdev);
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+ netdev->udp_tunnel_nic_info = &hinic3_udp_tunnels;
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
err = hinic3_set_default_hw_feature(nic_dev);
if (err)
goto set_features_err;
+ if (hinic3_get_bond_create_mode(lld_dev->hwdev) != 0)
+ hinic3_bond_init(nic_dev);
+
#ifdef HAVE_MULTI_VLAN_OFFLOAD_EN
hinic3_register_notifier(nic_dev);
#endif
@@ -888,6 +1084,9 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
}
queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ);
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ queue_delayed_work(nic_dev->workq,
+ &nic_dev->vport_stats_work, HZ);
netif_carrier_off(netdev);
*uld_dev = nic_dev;
@@ -920,6 +1119,25 @@ err_out:
return err;
}
+static void hinic3_bond_deinit(struct hinic3_nic_dev *nic_dev)
+{
+ int ret = 0;
+
+ ret = hinic3_open_close_bond(nic_dev->hwdev, false);
+ if (ret != 0)
+ goto bond_deinit_failed;
+
+ ret = hinic3_delete_bond(nic_dev->hwdev);
+ if (ret != 0)
+ goto bond_deinit_failed;
+
+ nic_info(&nic_dev->pdev->dev, "Bond deinit success\n");
+ return;
+
+bond_deinit_failed:
+ nic_err(&nic_dev->pdev->dev, "Bond deinit failed\n");
+}
+
static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
{
struct hinic3_nic_dev *nic_dev = adapter;
@@ -939,6 +1157,8 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
hinic3_unregister_notifier(nic_dev);
#endif
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ cancel_delayed_work_sync(&nic_dev->vport_stats_work);
cancel_delayed_work_sync(&nic_dev->periodic_work);
cancel_delayed_work_sync(&nic_dev->rxq_check_work);
cancel_work_sync(&nic_dev->rx_mode_work);
@@ -946,6 +1166,9 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
hinic3_flush_rx_flow_rule(nic_dev);
+ if (hinic3_get_bond_create_mode(lld_dev->hwdev) != 0)
+ hinic3_bond_deinit(nic_dev);
+
hinic3_update_nic_feature(nic_dev->hwdev, 0);
hinic3_set_nic_feature_to_hw(nic_dev->hwdev);
@@ -955,6 +1178,7 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
hinic3_deinit_nic_prof_adapter(nic_dev);
kfree(nic_dev->vlan_bitmap);
+ nic_dev->vlan_bitmap = NULL;
free_netdev(netdev);
@@ -971,8 +1195,10 @@ static void sriov_state_change(struct hinic3_nic_dev *nic_dev,
static void hinic3_port_module_event_handler(struct hinic3_nic_dev *nic_dev,
struct hinic3_event_info *event)
{
- const char *g_hinic3_module_link_err[LINK_ERR_NUM] = { "Unrecognized module" };
- struct hinic3_port_module_event *module_event = (void *)event->event_data;
+ const char *g_hinic3_module_link_err[LINK_ERR_NUM] = {
+ "Unrecognized module" };
+ struct hinic3_port_module_event *module_event =
+ (void *)event->event_data;
enum port_module_event_type type = module_event->type;
enum link_err_type err_type = module_event->err_type;
@@ -1003,6 +1229,116 @@ static void hinic3_port_module_event_handler(struct hinic3_nic_dev *nic_dev,
}
}
+bool hinic3_need_proc_link_event(struct hinic3_lld_dev *lld_dev)
+{
+ int ret = 0;
+ u16 func_id;
+ u8 roce_enable = false;
+ bool is_slave_func = false;
+ struct hinic3_hw_bond_infos hw_bond_infos = {0};
+
+ if (!lld_dev)
+ return false;
+
+ /* 非slave设备需要处理link down事件 */
+ ret = hinic3_is_slave_func(lld_dev->hwdev, &is_slave_func);
+ if (ret != 0) {
+ nic_err(&lld_dev->pdev->dev, "NIC get info, lld_dev is null\n");
+ return true;
+ }
+
+ if (!is_slave_func)
+ return true;
+
+ /* 未使能了vroce功能,需处理link down事件 */
+ func_id = hinic3_global_func_id(lld_dev->hwdev);
+ ret = hinic3_get_func_vroce_enable(lld_dev->hwdev, func_id, &roce_enable);
+ if (ret != 0)
+ return true;
+
+ if (!roce_enable)
+ return true;
+
+ /* 未创建bond,需要处理link down事件 */
+ hw_bond_infos.bond_id = HINIC_OVS_BOND_DEFAULT_ID;
+
+ ret = hinic3_get_hw_bond_infos(lld_dev->hwdev, &hw_bond_infos, HINIC3_CHANNEL_COMM);
+ if (ret != 0) {
+ pr_err("[ROCE, ERR] Get chipf bond info failed (%d)\n", ret);
+ return true;
+ }
+
+ if (!hw_bond_infos.valid)
+ return true;
+
+ return false;
+}
+
+bool hinic3_need_proc_bond_event(struct hinic3_lld_dev *lld_dev)
+{
+ return !hinic3_need_proc_link_event(lld_dev);
+}
+
+static void hinic_porc_bond_state_change(struct hinic3_lld_dev *lld_dev, void *adapter,
+ struct hinic3_event_info *event)
+{
+ struct hinic3_nic_dev *nic_dev = adapter;
+
+ if (!nic_dev || !event || !hinic3_support_nic(lld_dev->hwdev, NULL))
+ return;
+
+ switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_DOWN):
+ if (!hinic3_need_proc_bond_event(lld_dev)) {
+ nic_info(&lld_dev->pdev->dev, "NIC don't need proc bond event\n");
+ return;
+ }
+ nic_info(&lld_dev->pdev->dev, "NIC proc bond down\n");
+ hinic3_link_status_change(nic_dev, false);
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_UP):
+ if (!hinic3_need_proc_bond_event(lld_dev)) {
+ nic_info(&lld_dev->pdev->dev, "NIC don't need proc bond event\n");
+ return;
+ }
+ nic_info(&lld_dev->pdev->dev, "NIC proc bond up\n");
+ hinic3_link_status_change(nic_dev, true);
+ break;
+ default:
+ break;
+ }
+}
+
+static void hinic3_outband_cfg_event_handler(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_outband_cfg_info *info)
+{
+ int err = 0;
+
+ if (!nic_dev || !info || !hinic3_support_nic(nic_dev->hwdev, NULL)) {
+ pr_err("Outband cfg event invalid param\n");
+ return;
+ }
+
+ if (hinic3_func_type(nic_dev->hwdev) != TYPE_VF &&
+ info->func_id >= NIC_MAX_PF_NUM) {
+ err = hinic3_notify_vf_outband_cfg(nic_dev->hwdev,
+ info->func_id,
+ info->outband_default_vid);
+ if (err) {
+ nic_err(&nic_dev->pdev->dev,
+ "Outband cfg event notify vf err: %d, func_id: 0x%x, vid: 0x%x\n",
+ err, info->func_id, info->outband_default_vid);
+ return;
+ }
+ }
+
+ nic_info(&nic_dev->pdev->dev, "Change outband default vid from %u to %u\n",
+ nic_dev->outband_cfg.outband_default_vid,
+ info->outband_default_vid);
+
+ nic_dev->outband_cfg.outband_default_vid = info->outband_default_vid;
+}
+
static void nic_event(struct hinic3_lld_dev *lld_dev, void *adapter,
struct hinic3_event_info *event)
{
@@ -1014,21 +1350,35 @@ static void nic_event(struct hinic3_lld_dev *lld_dev, void *adapter,
switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_LINK_DOWN):
+ if (!hinic3_need_proc_link_event(lld_dev)) {
+ nic_info(&lld_dev->pdev->dev, "NIC don't need proc link event\n");
+ return;
+ }
hinic3_link_status_change(nic_dev, false);
break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_LINK_UP):
hinic3_link_status_change(nic_dev, true);
break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_DOWN):
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_UP):
+ hinic_porc_bond_state_change(lld_dev, adapter, event);
+ break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_PORT_MODULE_EVENT):
hinic3_port_module_event_handler(nic_dev, event);
break;
- case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_SRIOV_STATE_CHANGE):
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_OUTBAND_CFG):
+ hinic3_outband_cfg_event_handler(nic_dev,
+ (void *)event->event_data);
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM,
+ EVENT_COMM_SRIOV_STATE_CHANGE):
sriov_state_change(nic_dev, (void *)event->event_data);
break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_FAULT):
fault = (void *)event->event_data;
if (fault->fault_level == FAULT_LEVEL_SERIOUS_FLR &&
- fault->event.chip.func_id == hinic3_global_func_id(lld_dev->hwdev))
+ fault->event.chip.func_id ==
+ hinic3_global_func_id(lld_dev->hwdev))
hinic3_link_status_change(nic_dev, false);
break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_PCIE_LINK_DOWN):
@@ -1081,7 +1431,7 @@ struct hinic3_uld_info g_nic_uld_info = {
.resume = NULL,
.event = nic_event,
.ioctl = nic_ioctl,
-}; /*lint -e766*/
+};
struct hinic3_uld_info *get_nic_uld_info(void)
{
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h
index 94e606e..5bd4c3d 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h
@@ -9,6 +9,7 @@
/* Interrupt at most records, interrupt will be recorded in the FFM */
#define NICTOOL_CMD_TYPE (0x18)
+#define HINIC3_CARD_NAME_MAX_LEN (128)
struct api_cmd_rd {
u32 pf_id;
@@ -110,7 +111,8 @@ enum dbgtool_cmd {
DBGTOOL_CMD_NUM
};
-#define PF_MAX_SIZE (16)
+#define HINIC_PF_MAX_SIZE (16)
+#define HINIC_VF_MAX_SIZE (4096)
#define BUSINFO_LEN (32)
enum module_name {
@@ -132,7 +134,8 @@ enum module_name {
SEND_TO_MIGRATE_DRIVER,
SEND_TO_PPA_DRIVER,
SEND_TO_CUSTOM_DRIVER = SEND_TO_SRV_DRV_BASE + 11,
- SEND_TO_BIFUR_DRIVER = SEND_TO_SRV_DRV_BASE + 15,
+ SEND_TO_VSOCK_DRIVER = SEND_TO_SRV_DRV_BASE + 14,
+ SEND_TO_BIFUR_DRIVER,
SEND_TO_DRIVER_MAX = SEND_TO_SRV_DRV_BASE + 16, /* reserved */
};
@@ -160,7 +163,7 @@ enum driver_cmd_type {
GET_CHIP_FAULT_STATS,
NIC_RSVD1,
NIC_RSVD2,
- NIC_RSVD3,
+ GET_OS_HOT_REPLACE_INFO,
GET_CHIP_ID,
GET_SINGLE_CARD_INFO,
GET_FIRMWARE_ACTIVE_STATUS,
@@ -171,7 +174,7 @@ enum driver_cmd_type {
GET_LOOPBACK_MODE = 32,
SET_LOOPBACK_MODE,
SET_LINK_MODE,
- SET_PF_BW_LIMIT,
+ SET_TX_PF_BW_LIMIT,
GET_PF_BW_LIMIT,
ROCE_CMD,
GET_POLL_WEIGHT,
@@ -189,6 +192,7 @@ enum driver_cmd_type {
GET_NIC_STATS_STRING,
GET_NIC_STATS_INFO,
GET_PF_ID,
+ GET_MBOX_CNT,
NIC_RSVD4,
NIC_RSVD5,
DCB_QOS_INFO,
@@ -205,6 +209,8 @@ enum driver_cmd_type {
RSS_INDIR,
PORT_ID,
+ SET_RX_PF_BW_LIMIT = 0x43,
+
GET_FUNC_CAP = 0x50,
GET_XSFP_PRESENT = 0x51,
GET_XSFP_INFO = 0x52,
@@ -216,6 +222,10 @@ enum driver_cmd_type {
WIN_CSR_WRITE = 0x62,
WIN_API_CMD_RD = 0x63,
+ GET_FUSION_Q = 0x64,
+
+ ROCE_CMD_BOND_HASH_TYPE_SET = 0xb2,
+
BIFUR_SET_ENABLE = 0xc0,
BIFUR_GET_ENABLE = 0xc1,
@@ -234,7 +244,8 @@ enum sm_cmd_type {
SM_CTR_RD64,
SM_CTR_RD32_CLEAR,
SM_CTR_RD64_PAIR_CLEAR,
- SM_CTR_RD64_CLEAR
+ SM_CTR_RD64_CLEAR,
+ SM_CTR_RD16_CLEAR,
};
struct cqm_stats {
@@ -321,10 +332,22 @@ struct pf_info {
};
struct card_info {
- struct pf_info pf[PF_MAX_SIZE];
+ struct pf_info pf[HINIC_PF_MAX_SIZE];
u32 pf_num;
};
+struct func_mbox_cnt_info {
+ char bus_info[BUSINFO_LEN];
+ u64 send_cnt;
+ u64 ack_cnt;
+};
+
+struct card_mbox_cnt_info {
+ struct func_mbox_cnt_info func_info[HINIC_PF_MAX_SIZE +
+ HINIC_VF_MAX_SIZE];
+ u32 func_num;
+};
+
struct hinic3_nic_loop_mode {
u32 loop_mode;
u32 loop_ctrl;
@@ -665,6 +688,162 @@ struct get_card_bond_msg_s {
struct bond_all_msg_s all_msg[MAX_BONDING_CNT_PER_CARD];
};
+#define MAX_FUSION_Q_STATS_STR_LEN 16
+#define MAX_FUSION_Q_NUM 256
+struct queue_status_s {
+ pid_t tgid;
+ char status[MAX_FUSION_Q_STATS_STR_LEN];
+};
+
+struct fusion_q_status_s {
+ u16 queue_num;
+ struct queue_status_s queue[MAX_FUSION_Q_NUM];
+};
+
+struct fusion_q_tx_hw_page {
+ u64 phy_addr;
+ u64 *map_addr;
+};
+
+struct fusion_sq_info {
+ u16 q_id;
+ u16 pi;
+ u16 ci; /* sw_ci */
+ u16 fi; /* hw_ci */
+ u32 q_depth;
+ u16 pi_reverse;
+ u16 wqebb_size;
+ u8 priority;
+ u16 *ci_addr;
+ u64 cla_addr;
+ void *slq_handle;
+ struct fusion_q_tx_hw_page direct_wqe;
+ struct fusion_q_tx_hw_page doorbell;
+ u32 page_idx;
+ u32 glb_sq_id;
+};
+
+struct fusion_q_tx_wqe {
+ u32 data[4];
+};
+
+struct fusion_rq_info {
+ u16 q_id;
+ u16 delta;
+ u16 hw_pi;
+ u16 ci; /* sw_ci */
+ u16 sw_pi;
+ u16 wqebb_size;
+ u16 q_depth;
+ u16 buf_len;
+
+ void *slq_handle;
+ u64 ci_wqe_page_addr;
+ u64 ci_cla_tbl_addr;
+
+ u8 coalesc_timer_cfg;
+ u8 pending_limt;
+ u16 msix_idx;
+ u32 msix_vector;
+};
+
+struct fusion_q_rx_wqe {
+ u32 data[8];
+};
+
+struct fusion_q_rx_cqe {
+ union {
+ struct {
+ unsigned int checksum_err : 16;
+ unsigned int lro_num : 8;
+ unsigned int rsvd1 : 7;
+ unsigned int rx_done : 1;
+ } bs;
+ unsigned int value;
+ } dw0;
+
+ union {
+ struct {
+ unsigned int vlan : 16;
+ unsigned int length : 16;
+ } bs;
+ unsigned int value;
+ } dw1;
+
+ union {
+ struct {
+ unsigned int pkt_types : 12;
+ unsigned int rsvd : 4;
+ unsigned int udp_0 : 1;
+ unsigned int ipv6_ex_add : 1;
+ unsigned int loopback : 1;
+ unsigned int umbcast : 2;
+ unsigned int vlan_offload_en : 1;
+ unsigned int tag_num : 2;
+ unsigned int rss_type : 8;
+ } bs;
+ unsigned int value;
+ } dw2;
+
+ union {
+ struct {
+ unsigned int rss_hash_value;
+ } bs;
+ unsigned int value;
+ } dw3;
+
+ union {
+ struct {
+ unsigned int tx_ts_seq : 16;
+ unsigned int message_1588_offset : 8;
+ unsigned int message_1588_type : 4;
+ unsigned int rsvd : 1;
+ unsigned int if_rx_ts : 1;
+ unsigned int if_tx_ts : 1;
+ unsigned int if_1588 : 1;
+ } bs;
+ unsigned int value;
+ } dw4;
+
+ union {
+ struct {
+ unsigned int ts;
+ } bs;
+ unsigned int value;
+ } dw5;
+
+ union {
+ struct {
+ unsigned int lro_ts;
+ } bs;
+ unsigned int value;
+ } dw6;
+
+ union {
+ struct {
+ unsigned int rsvd0;
+ } bs;
+ unsigned int value;
+ } dw7; /* 16Bytes Align */
+};
+
+struct os_hot_repalce_func_info {
+ char card_name[HINIC3_CARD_NAME_MAX_LEN];
+ u32 bus_num;
+ u32 valid;
+ u32 bdf;
+ int partition;
+ u16 backup_pf;
+ u16 pf_idx;
+ int port_id;
+};
+
+#define ALL_CARD_PF_NUM 2048 /* 64 card * 32 pf */
+struct os_hot_replace_info {
+ struct os_hot_repalce_func_info func_infos[ALL_CARD_PF_NUM];
+ u32 func_cnt;
+};
+
int alloc_buff_in(void *hwdev, struct msg_module *nt_msg, u32 in_size, void **buf_in);
int alloc_buff_out(void *hwdev, struct msg_module *nt_msg, u32 out_size, void **buf_out);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
index ea1d506..c4b3d5b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
@@ -15,6 +15,9 @@
#include <linux/ip.h>
#include "ossl_knl.h"
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+#include <net/udp_tunnel.h>
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
#ifdef HAVE_XDP_SUPPORT
#include <linux/bpf.h>
#endif
@@ -28,6 +31,10 @@
#include "hinic3_dcb.h"
#include "hinic3_nic_prof.h"
+#include "nic_npu_cmd.h"
+
+#include "vram_common.h"
+
#define HINIC3_DEFAULT_RX_CSUM_OFFLOAD 0xFFF
#define HINIC3_LRO_DEFAULT_COAL_PKT_SIZE 32
@@ -47,8 +54,62 @@ static void hinic3_nic_set_rx_mode(struct net_device *netdev)
queue_work(nic_dev->workq, &nic_dev->rx_mode_work);
}
+static void hinic3_free_irq_vram(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_dyna_txrxq_params *in_q_params)
+{
+ u32 size;
+ int is_use_vram = get_use_vram_flag();
+ struct hinic3_dyna_txrxq_params q_params = nic_dev->q_params;
+
+ if (!q_params.irq_cfg)
+ return;
+
+ size = sizeof(struct hinic3_irq) * (q_params.num_qps);
+
+ if (is_use_vram != 0) {
+ hi_vram_kfree((void *)q_params.irq_cfg, q_params.irq_cfg_vram_name, size);
+ q_params.irq_cfg = NULL;
+ } else {
+ kfree(in_q_params->irq_cfg);
+ in_q_params->irq_cfg = NULL;
+ }
+}
+
+static int hinic3_alloc_irq_vram(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_dyna_txrxq_params *q_params,
+ bool is_up_eth)
+{
+ u32 size;
+ int is_use_vram = get_use_vram_flag();
+ u16 func_id;
+
+ size = sizeof(struct hinic3_irq) * q_params->num_qps;
+
+ if (is_use_vram != 0) {
+ func_id = hinic3_global_func_id(nic_dev->hwdev);
+ snprintf(q_params->irq_cfg_vram_name, VRAM_NAME_MAX_LEN,
+ "%s%hu", VRAM_NIC_IRQ_VRAM, func_id);
+ q_params->irq_cfg = (struct hinic3_irq *)hi_vram_kalloc(q_params->irq_cfg_vram_name,
+ size);
+ if (!q_params->irq_cfg) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "NIC irq vram alloc failed.\n");
+ return -ENOMEM;
+ }
+ /* in order to clear napi stored in vram, irq need to init when eth up */
+ if (is_up_eth)
+ memset(q_params->irq_cfg, 0, size);
+ } else {
+ q_params->irq_cfg = kzalloc(size, GFP_KERNEL);
+ if (!q_params->irq_cfg)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static int hinic3_alloc_txrxq_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_txrxq_params *q_params)
+ struct hinic3_dyna_txrxq_params *q_params,
+ bool is_up_eth)
{
u32 size;
int err;
@@ -70,12 +131,9 @@ static int hinic3_alloc_txrxq_resources(struct hinic3_nic_dev *nic_dev,
goto alloc_rxqs_res_arr_err;
}
- size = sizeof(*q_params->irq_cfg) * q_params->num_qps;
- q_params->irq_cfg = kzalloc(size, GFP_KERNEL);
- if (!q_params->irq_cfg) {
- nicif_err(nic_dev, drv, nic_dev->netdev,
- "Failed to alloc irq resource array\n");
- err = -ENOMEM;
+ err = hinic3_alloc_irq_vram(nic_dev, q_params, is_up_eth);
+ if (err != 0) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc irq resource array\n");
goto alloc_irq_cfg_err;
}
@@ -102,8 +160,7 @@ alloc_rxqs_res_err:
q_params->txqs_res);
alloc_txqs_res_err:
- kfree(q_params->irq_cfg);
- q_params->irq_cfg = NULL;
+ hinic3_free_irq_vram(nic_dev, q_params);
alloc_irq_cfg_err:
kfree(q_params->rxqs_res);
@@ -117,15 +174,17 @@ alloc_rxqs_res_arr_err:
}
static void hinic3_free_txrxq_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_txrxq_params *q_params)
+ struct hinic3_dyna_txrxq_params *q_params)
{
+ int is_in_kexec = vram_get_kexec_flag();
+
hinic3_free_rxqs_res(nic_dev, q_params->num_qps, q_params->rq_depth,
q_params->rxqs_res);
hinic3_free_txqs_res(nic_dev, q_params->num_qps, q_params->sq_depth,
q_params->txqs_res);
- kfree(q_params->irq_cfg);
- q_params->irq_cfg = NULL;
+ if (is_in_kexec == 0)
+ hinic3_free_irq_vram(nic_dev, q_params);
kfree(q_params->rxqs_res);
q_params->rxqs_res = NULL;
@@ -161,6 +220,7 @@ static int hinic3_configure_txrxqs(struct hinic3_nic_dev *nic_dev,
static void config_dcb_qps_map(struct hinic3_nic_dev *nic_dev)
{
struct net_device *netdev = nic_dev->netdev;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u8 num_cos;
if (!test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
@@ -171,12 +231,13 @@ static void config_dcb_qps_map(struct hinic3_nic_dev *nic_dev)
num_cos = hinic3_get_dev_user_cos_num(nic_dev);
hinic3_update_qp_cos_cfg(nic_dev, num_cos);
/* For now, we don't support to change num_cos */
- if (num_cos > nic_dev->cos_config_num_max ||
+ if (num_cos > dcb->cos_config_num_max ||
nic_dev->q_params.num_qps < num_cos) {
nicif_err(nic_dev, drv, netdev, "Invalid num_cos: %u or num_qps: %u, disable DCB\n",
num_cos, nic_dev->q_params.num_qps);
nic_dev->q_params.num_cos = 0;
clear_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
+ clear_bit(HINIC3_DCB_ENABLE, &nic_dev->nic_vram->flags);
/* if we can't enable rss or get enough num_qps,
* need to sync default configure to hw
*/
@@ -190,17 +251,22 @@ static int hinic3_configure(struct hinic3_nic_dev *nic_dev)
{
struct net_device *netdev = nic_dev->netdev;
int err;
+ int is_in_kexec = vram_get_kexec_flag();
- err = hinic3_set_port_mtu(nic_dev->hwdev, (u16)netdev->mtu);
- if (err) {
- nicif_err(nic_dev, drv, netdev, "Failed to set mtu\n");
- return err;
+ if (is_in_kexec == 0) {
+ err = hinic3_set_port_mtu(nic_dev->hwdev, (u16)netdev->mtu);
+ if (err != 0) {
+ nicif_err(nic_dev, drv, netdev, "Failed to set mtu\n");
+ return err;
+ }
}
config_dcb_qps_map(nic_dev);
/* rx rss init */
- err = hinic3_rx_configure(netdev, test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ? 1 : 0);
+ err = hinic3_rx_configure(netdev,
+ test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)
+ ? 1 : 0);
if (err) {
nicif_err(nic_dev, drv, netdev, "Failed to configure rx\n");
return err;
@@ -256,10 +322,11 @@ static void config_dcb_num_qps(struct hinic3_nic_dev *nic_dev,
const struct hinic3_dyna_txrxq_params *q_params,
u16 max_qps)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u8 num_cos = q_params->num_cos;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
- if (!num_cos || num_cos > nic_dev->cos_config_num_max || num_cos > max_qps)
+ if (!num_cos || num_cos > dcb->cos_config_num_max || num_cos > max_qps)
return; /* will disable DCB in config_dcb_qps_map() */
hinic3_update_qp_cos_cfg(nic_dev, user_cos_num);
@@ -332,57 +399,10 @@ static void hinic3_destroy_num_qps(struct hinic3_nic_dev *nic_dev)
kfree(nic_dev->qps_irq_info);
}
-int hinic3_force_port_disable(struct hinic3_nic_dev *nic_dev)
-{
- int err;
-
- down(&nic_dev->port_state_sem);
-
- err = hinic3_set_port_enable(nic_dev->hwdev, false, HINIC3_CHANNEL_NIC);
- if (!err)
- nic_dev->force_port_disable = true;
-
- up(&nic_dev->port_state_sem);
-
- return err;
-}
-
-int hinic3_force_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable)
-{
- int err = 0;
-
- down(&nic_dev->port_state_sem);
-
- nic_dev->force_port_disable = false;
- err = hinic3_set_port_enable(nic_dev->hwdev, enable,
- HINIC3_CHANNEL_NIC);
-
- up(&nic_dev->port_state_sem);
-
- return err;
-}
-
int hinic3_maybe_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable)
{
- int err;
-
- down(&nic_dev->port_state_sem);
-
- /* Do nothing when force disable
- * Port will disable when call force port disable
- * and should not enable port when in force mode
- */
- if (nic_dev->force_port_disable) {
- up(&nic_dev->port_state_sem);
- return 0;
- }
-
- err = hinic3_set_port_enable(nic_dev->hwdev, enable,
- HINIC3_CHANNEL_NIC);
-
- up(&nic_dev->port_state_sem);
-
- return err;
+ return hinic3_set_port_enable(nic_dev->hwdev, enable,
+ HINIC3_CHANNEL_NIC);
}
static void hinic3_print_link_message(struct hinic3_nic_dev *nic_dev,
@@ -398,8 +418,8 @@ static void hinic3_print_link_message(struct hinic3_nic_dev *nic_dev,
}
static int hinic3_alloc_channel_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_qp_params *qp_params,
- struct hinic3_dyna_txrxq_params *trxq_params)
+ struct hinic3_dyna_qp_params *qp_params,
+ struct hinic3_dyna_txrxq_params *trxq_params, bool is_up_eth)
{
int err;
@@ -414,7 +434,7 @@ static int hinic3_alloc_channel_resources(struct hinic3_nic_dev *nic_dev,
return err;
}
- err = hinic3_alloc_txrxq_resources(nic_dev, trxq_params);
+ err = hinic3_alloc_txrxq_resources(nic_dev, trxq_params, is_up_eth);
if (err) {
nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc txrxq resources\n");
hinic3_free_qps(nic_dev->hwdev, qp_params);
@@ -425,8 +445,8 @@ static int hinic3_alloc_channel_resources(struct hinic3_nic_dev *nic_dev,
}
static void hinic3_free_channel_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_qp_params *qp_params,
- struct hinic3_dyna_txrxq_params *trxq_params)
+ struct hinic3_dyna_qp_params *qp_params,
+ struct hinic3_dyna_txrxq_params *trxq_params)
{
mutex_lock(&nic_dev->nic_mutex);
hinic3_free_txrxq_resources(nic_dev, trxq_params);
@@ -521,7 +541,8 @@ int hinic3_vport_up(struct hinic3_nic_dev *nic_dev)
queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task,
HINIC3_MODERATONE_DELAY);
if (test_bit(HINIC3_RXQ_RECOVERY, &nic_dev->flags))
- queue_delayed_work(nic_dev->workq, &nic_dev->rxq_check_work, HZ);
+ queue_delayed_work(nic_dev->workq,
+ &nic_dev->rxq_check_work, HZ);
hinic3_print_link_message(nic_dev, link_status);
@@ -542,9 +563,52 @@ vport_enable_err:
return err;
}
+static int hinic3_flush_rq_and_check(struct hinic3_nic_dev *nic_dev, u16 glb_func_id)
+{
+ struct hinic3_flush_rq *rq_flush_msg = NULL;
+ struct hinic3_cmd_buf *cmd_buf = NULL;
+ int out_buf_len = sizeof(struct hinic3_flush_rq);
+ u16 rq_id;
+ u64 out_param = 0;
+ int ret;
+
+ cmd_buf = hinic3_alloc_cmd_buf(nic_dev->hwdev);
+ if (!cmd_buf) {
+ nic_err(&nic_dev->pdev->dev, "Failed to allocate cmd buf\n");
+ return -ENOMEM;
+ }
+
+ cmd_buf->size = sizeof(struct hinic3_flush_rq);
+ rq_flush_msg = (struct hinic3_flush_rq *)cmd_buf->buf;
+ rq_flush_msg->dw.bs.func_id = glb_func_id;
+ for (rq_id = 0; rq_id < nic_dev->q_params.num_qps; rq_id++) {
+ rq_flush_msg->dw.bs.rq_id = rq_id;
+ hinic3_cpu_to_be32(rq_flush_msg, out_buf_len);
+ ret = hinic3_cmdq_direct_resp(nic_dev->hwdev, HINIC3_MOD_L2NIC,
+ HINIC3_UCODE_CHK_RQ_STOP,
+ cmd_buf, &out_param, 0,
+ HINIC3_CHANNEL_NIC);
+ if (ret != 0 || out_param != 0) {
+ nic_err(&nic_dev->pdev->dev, "Failed to flush rq, ret:%d, func:%u, rq:%u\n",
+ ret, glb_func_id, rq_id);
+ goto err;
+ }
+ hinic3_be32_to_cpu(rq_flush_msg, out_buf_len);
+ }
+
+ nic_info(&nic_dev->pdev->dev, "Func:%u rq_num:%u flush rq success\n",
+ glb_func_id, nic_dev->q_params.num_qps);
+ hinic3_free_cmd_buf(nic_dev->hwdev, cmd_buf);
+ return 0;
+err:
+ hinic3_free_cmd_buf(nic_dev->hwdev, cmd_buf);
+ return -1;
+}
+
void hinic3_vport_down(struct hinic3_nic_dev *nic_dev)
{
u16 glb_func_id;
+ int is_in_kexec = vram_get_kexec_flag();
netif_carrier_off(nic_dev->netdev);
netif_tx_disable(nic_dev->netdev);
@@ -557,18 +621,21 @@ void hinic3_vport_down(struct hinic3_nic_dev *nic_dev)
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
hinic3_notify_all_vfs_link_changed(nic_dev->hwdev, 0);
- hinic3_maybe_set_port_state(nic_dev, false);
+ if (is_in_kexec != 0)
+ nicif_info(nic_dev, drv, nic_dev->netdev, "Skip changing mag status!\n");
+ else
+ hinic3_maybe_set_port_state(nic_dev, false);
glb_func_id = hinic3_global_func_id(nic_dev->hwdev);
hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false,
HINIC3_CHANNEL_NIC);
hinic3_flush_txqs(nic_dev->netdev);
- /* After set vport disable 100ms,
- * no packets will be send to host
- * FPGA set 2000ms
- */
- msleep(HINIC3_WAIT_FLUSH_QP_RESOURCE_TIMEOUT);
+
+ if (is_in_kexec == 0)
+ msleep(HINIC3_WAIT_FLUSH_QP_RESOURCE_TIMEOUT);
+ else
+ (void)hinic3_flush_rq_and_check(nic_dev, glb_func_id);
hinic3_flush_qps_res(nic_dev->hwdev);
}
}
@@ -581,11 +648,12 @@ int hinic3_change_channel_settings(struct hinic3_nic_dev *nic_dev,
struct hinic3_dyna_qp_params new_qp_params = {0};
struct hinic3_dyna_qp_params cur_qp_params = {0};
int err;
+ bool is_free_resources = false;
hinic3_config_num_qps(nic_dev, trxq_params);
err = hinic3_alloc_channel_resources(nic_dev, &new_qp_params,
- trxq_params);
+ trxq_params, false);
if (err) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc channel resources\n");
@@ -597,10 +665,19 @@ int hinic3_change_channel_settings(struct hinic3_nic_dev *nic_dev,
hinic3_close_channel(nic_dev, &cur_qp_params);
hinic3_free_channel_resources(nic_dev, &cur_qp_params,
&nic_dev->q_params);
+ is_free_resources = true;
}
if (nic_dev->num_qp_irq > trxq_params->num_qps)
hinic3_qp_irq_change(nic_dev, trxq_params->num_qps);
+
+ if (is_free_resources) {
+ err = hinic3_alloc_irq_vram(nic_dev, trxq_params, false);
+ if (err != 0) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "Change chl alloc irq failed\n");
+ goto alloc_irq_err;
+ }
+ }
nic_dev->q_params = *trxq_params;
if (reopen_handler)
@@ -621,7 +698,7 @@ int hinic3_change_channel_settings(struct hinic3_nic_dev *nic_dev,
vport_up_err:
hinic3_close_channel(nic_dev, &new_qp_params);
-
+alloc_irq_err:
open_channel_err:
hinic3_free_channel_resources(nic_dev, &new_qp_params, trxq_params);
@@ -652,7 +729,7 @@ int hinic3_open(struct net_device *netdev)
}
err = hinic3_alloc_channel_resources(nic_dev, &qp_params,
- &nic_dev->q_params);
+ &nic_dev->q_params, true);
if (err)
goto alloc_channel_res_err;
@@ -691,12 +768,31 @@ setup_qps_err:
return err;
}
+static void hinic3_delete_napi(struct hinic3_nic_dev *nic_dev)
+{
+ u16 q_id;
+ int is_in_kexec = vram_get_kexec_flag();
+ struct hinic3_irq *irq_cfg = NULL;
+
+ if (is_in_kexec == 0 || !nic_dev->q_params.irq_cfg)
+ return;
+
+ for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) {
+ irq_cfg = &nic_dev->q_params.irq_cfg[q_id];
+ qp_del_napi(irq_cfg);
+ }
+
+ hinic3_free_irq_vram(nic_dev, &nic_dev->q_params);
+}
+
int hinic3_close(struct net_device *netdev)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
struct hinic3_dyna_qp_params qp_params = {0};
if (!test_and_clear_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
+ /* delete napi in os hotreplace rollback */
+ hinic3_delete_napi(nic_dev);
nicif_info(nic_dev, drv, netdev, "Netdev already close, do nothing\n");
return 0;
}
@@ -776,7 +872,8 @@ static u8 parse_ipv6_info(struct sk_buff *skb, u32 *rss_tunple,
return 0;
}
-static u16 select_queue_by_hash_func(struct net_device *dev, struct sk_buff *skb,
+static u16 select_queue_by_hash_func(struct net_device *dev,
+ struct sk_buff *skb,
unsigned int num_tx_queues)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(dev);
@@ -831,17 +928,20 @@ static u16 select_queue_by_hash_func(struct net_device *dev, struct sk_buff *skb
}
#define GET_DSCP_PRI_OFFSET 2
-static u8 hinic3_get_dscp_up(struct hinic3_nic_dev *nic_dev, struct sk_buff *skb)
+static u8 hinic3_get_dscp_up(struct hinic3_nic_dev *nic_dev,
+ struct sk_buff *skb)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int dscp_cp;
if (skb->protocol == htons(ETH_P_IP))
dscp_cp = ipv4_get_dsfield(ip_hdr(skb)) >> GET_DSCP_PRI_OFFSET;
else if (skb->protocol == htons(ETH_P_IPV6))
- dscp_cp = ipv6_get_dsfield(ipv6_hdr(skb)) >> GET_DSCP_PRI_OFFSET;
+ dscp_cp = ipv6_get_dsfield(ipv6_hdr(skb)) >>
+ GET_DSCP_PRI_OFFSET;
else
- return nic_dev->hw_dcb_cfg.default_cos;
- return nic_dev->hw_dcb_cfg.dscp2cos[dscp_cp];
+ return dcb->hw_dcb_cfg.default_cos;
+ return dcb->hw_dcb_cfg.dscp2cos[dscp_cp];
}
#if defined(HAVE_NDO_SELECT_QUEUE_SB_DEV_ONLY)
@@ -867,11 +967,13 @@ static u16 hinic3_select_queue(struct net_device *netdev, struct sk_buff *skb)
#endif /* end of HAVE_NDO_SELECT_QUEUE_ACCEL_FALLBACK */
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u16 txq;
u8 cos, qp_num;
if (test_bit(HINIC3_SAME_RXTX, &nic_dev->flags))
- return select_queue_by_hash_func(netdev, skb, netdev->real_num_tx_queues);
+ return select_queue_by_hash_func(netdev, skb,
+ netdev->real_num_tx_queues);
txq =
#if defined(HAVE_NDO_SELECT_QUEUE_SB_DEV_ONLY)
@@ -887,18 +989,19 @@ static u16 hinic3_select_queue(struct net_device *netdev, struct sk_buff *skb)
#endif
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
- if (nic_dev->hw_dcb_cfg.trust == DCB_PCP) {
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_PCP) {
if (skb->vlan_tci)
- cos = nic_dev->hw_dcb_cfg.pcp2cos[skb->vlan_tci >> VLAN_PRIO_SHIFT];
+ cos = dcb->hw_dcb_cfg.pcp2cos[skb->vlan_tci >>
+ VLAN_PRIO_SHIFT];
else
- cos = nic_dev->hw_dcb_cfg.default_cos;
+ cos = dcb->hw_dcb_cfg.default_cos;
} else {
cos = hinic3_get_dscp_up(nic_dev, skb);
}
- qp_num = nic_dev->hw_dcb_cfg.cos_qp_num[cos] ?
- txq % nic_dev->hw_dcb_cfg.cos_qp_num[cos] : 0;
- txq = nic_dev->hw_dcb_cfg.cos_qp_offset[cos] + qp_num;
+ qp_num = dcb->hw_dcb_cfg.cos_qp_num[cos] ?
+ txq % dcb->hw_dcb_cfg.cos_qp_num[cos] : 0;
+ txq = dcb->hw_dcb_cfg.cos_qp_offset[cos] + qp_num;
}
return txq;
@@ -976,7 +1079,7 @@ static struct net_device_stats *hinic3_get_stats(struct net_device *netdev)
stats->rx_packets = packets;
stats->rx_bytes = bytes;
stats->rx_errors = errors;
- stats->rx_dropped = dropped;
+ stats->rx_dropped = dropped + nic_dev->vport_stats.rx_discard_vport;
#ifndef HAVE_VOID_NDO_GET_STATS64
return stats;
@@ -1023,10 +1126,18 @@ static int hinic3_change_mtu(struct net_device *netdev, int new_mtu)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
u32 mtu = (u32)new_mtu;
int err = 0;
+ int is_in_kexec = vram_get_kexec_flag();
#ifdef HAVE_XDP_SUPPORT
u32 xdp_max_mtu;
+#endif
+
+ if (is_in_kexec != 0) {
+ nicif_info(nic_dev, drv, netdev, "Hotreplace skip change mtu\n");
+ return err;
+ }
+#ifdef HAVE_XDP_SUPPORT
if (hinic3_is_xdp_enable(nic_dev)) {
xdp_max_mtu = hinic3_xdp_max_mtu(nic_dev);
if (mtu > xdp_max_mtu) {
@@ -1045,6 +1156,7 @@ static int hinic3_change_mtu(struct net_device *netdev, int new_mtu)
nicif_info(nic_dev, drv, nic_dev->netdev, "Change mtu from %u to %d\n",
netdev->mtu, new_mtu);
netdev->mtu = mtu;
+ nic_dev->nic_vram->vram_mtu = mtu;
}
return err;
@@ -1078,6 +1190,76 @@ static int hinic3_set_mac_addr(struct net_device *netdev, void *addr)
return 0;
}
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+static int hinic3_udp_tunnel_port_config(struct net_device *netdev,
+ struct udp_tunnel_info *ti,
+ u8 action)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ u16 func_id = hinic3_global_func_id(nic_dev->hwdev);
+ u16 dst_port;
+ int ret = 0;
+
+ switch (ti->type) {
+ case UDP_TUNNEL_TYPE_VXLAN:
+ dst_port = ntohs(ti->port);
+ ret = hinic3_vlxan_port_config(nic_dev->hwdev,
+ func_id, dst_port, action);
+ if (ret != 0) {
+ nicif_warn(nic_dev, drv, netdev,
+ "Failed to set vxlan port %u to device\n",
+ dst_port);
+ break;
+ }
+ nicif_info(nic_dev, link, netdev, "Vxlan dst port set to %u\n",
+ action == HINIC3_CMD_OP_ADD ?
+ dst_port : ntohs(VXLAN_OFFLOAD_PORT_LE));
+ break;
+ default:
+ nicif_err(nic_dev, drv, netdev, "Failed to add port, only vxlan dst port is supported\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
+#ifdef HAVE_NDO_UDP_TUNNEL_ADD
+static void hinic3_udp_tunnel_add(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
+{
+ if (ti->sa_family != AF_INET && ti->sa_family != AF_INET6)
+ return;
+
+ hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_ADD);
+}
+
+static void hinic3_udp_tunnel_del(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
+{
+ if (ti->sa_family != AF_INET && ti->sa_family != AF_INET6)
+ return;
+
+ hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_DEL);
+}
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD */
+
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+int hinic3_udp_tunnel_set_port(struct net_device *netdev,
+ __always_unused unsigned int table,
+ __always_unused unsigned int entry,
+ struct udp_tunnel_info *ti)
+{
+ return hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_ADD);
+}
+
+int hinic3_udp_tunnel_unset_port(struct net_device *netdev,
+ __always_unused unsigned int table,
+ __always_unused unsigned int entry,
+ struct udp_tunnel_info *ti)
+{
+ return hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_DEL);
+}
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
static int
hinic3_vlan_rx_add_vid(struct net_device *netdev,
__always_unused __be16 proto,
@@ -1124,7 +1306,7 @@ hinic3_vlan_rx_kill_vid(struct net_device *netdev,
int err = 0;
col = VID_COL(nic_dev, vid);
- line = VID_LINE(nic_dev, vid);
+ line = (int)VID_LINE(nic_dev, vid);
/* In the broadcast scenario, ucode finds the corresponding function
* based on VLAN 0 of vlan table. If we delete VLAN 0, the VLAN function
@@ -1163,14 +1345,12 @@ static int hinic3_vlan_restore(struct net_device *netdev)
return -EFAULT;
rcu_read_lock();
for (i = 0; i < VLAN_N_VID; i++) {
-/* lint -e778 */
#ifdef HAVE_VLAN_FIND_DEV_DEEP_RCU
vlandev =
__vlan_find_dev_deep_rcu(netdev, htons(ETH_P_8021Q), i);
#else
vlandev = __vlan_find_dev_deep(netdev, htons(ETH_P_8021Q), i);
#endif
-/* lint +e778 */
col = VID_COL(nic_dev, i);
line = VID_LINE(nic_dev, i);
if (!vlandev && (vlan_bitmap[line] & (1UL << col)) != 0) {
@@ -1328,12 +1508,17 @@ static int set_feature_vlan_filter(struct hinic3_nic_dev *nic_dev,
return 0;
#ifdef NEED_VLAN_RESTORE
- if (en)
+ if (en) {
err = hinic3_vlan_restore(nic_dev->netdev);
+ if (err) {
+ hinic3_err(nic_dev, drv, "vlan restore failed\n");
+ *failed_features |= vlan_filter_feature;
+ return err;
+ }
+ }
#endif
- if (err == 0)
- err = hinic3_set_vlan_fliter(nic_dev->hwdev, en);
+ err = hinic3_set_vlan_fliter(nic_dev->hwdev, en);
if (err) {
hinic3_err(nic_dev, drv, "%s rx vlan filter failed\n",
SET_FEATURES_OP_STR(en));
@@ -1427,8 +1612,8 @@ static int hinic3_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
struct hinic3_nic_dev *adapter = netdev_priv(netdev);
int err;
- if (is_multicast_ether_addr(mac) || /*lint !e574*/
- vf >= pci_num_vf(adapter->pdev)) /*lint !e574*/
+ if (is_multicast_ether_addr(mac) ||
+ vf >= pci_num_vf(adapter->pdev))
return -EINVAL;
err = hinic3_set_vf_mac(adapter->hwdev, OS_VF_ID_TO_HW(vf), mac);
@@ -1446,7 +1631,6 @@ static int hinic3_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
return 0;
}
-/*lint -save -e574 -e734*/
#ifdef IFLA_VF_MAX
static int set_hw_vf_vlan(void *hwdev, u16 cur_vlanprio, int vf,
u16 vlan, u8 qos)
@@ -1529,7 +1713,8 @@ static int hinic3_ndo_set_vf_spoofchk(struct net_device *netdev, int vf,
#endif
#ifdef HAVE_NDO_SET_VF_TRUST
-static int hinic3_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
+static int hinic3_ndo_set_vf_trust(struct net_device *netdev, int vf,
+ bool setting)
{
struct hinic3_nic_dev *adapter = netdev_priv(netdev);
int err;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h
index 11c1731..d8c5419 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h
@@ -10,6 +10,8 @@
#include "hinic3_common.h"
#include "hinic3_nic_io.h"
#include "hinic3_nic_cfg.h"
+#include "mag_mpu_cmd.h"
+#include "mag_mpu_cmd_defs.h"
/* ************************ array index define ********************* */
#define ARRAY_INDEX_0 0
@@ -21,6 +23,35 @@
#define ARRAY_INDEX_6 6
#define ARRAY_INDEX_7 7
+#define XSFP_TLV_PRE_INFO_LEN 4
+
+enum hinic3_link_port_type {
+ LINK_PORT_UNKNOWN,
+ LINK_PORT_OPTICAL_MM,
+ LINK_PORT_OPTICAL_SM,
+ LINK_PORT_PAS_COPPER,
+ LINK_PORT_ACC,
+ LINK_PORT_BASET,
+ LINK_PORT_AOC = 0x40,
+ LINK_PORT_ELECTRIC,
+ LINK_PORT_BACKBOARD_INTERFACE,
+};
+
+enum hilink_fibre_subtype {
+ FIBRE_SUBTYPE_SR = 1,
+ FIBRE_SUBTYPE_LR,
+ FIBRE_SUBTYPE_MAX,
+};
+
+enum hilink_fec_type {
+ HILINK_FEC_NOT_SET,
+ HILINK_FEC_RSFEC,
+ HILINK_FEC_BASEFEC,
+ HILINK_FEC_NOFEC,
+ HILINK_FEC_LLRSFE,
+ HILINK_FEC_MAX_TYPE,
+};
+
#define SQ_CI_ADDR_SHIFT 2
#define RQ_CI_ADDR_SHIFT 4
@@ -71,6 +102,12 @@ struct hinic3_port_routine_cmd {
struct mag_cmd_get_xsfp_present abs;
};
+struct hinic3_port_routine_cmd_extern {
+ bool mpu_send_xsfp_tlv_info;
+
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp std_xsfp_tlv_info;
+};
+
struct hinic3_nic_cfg {
struct semaphore cfg_lock;
@@ -84,11 +121,13 @@ struct hinic3_nic_cfg {
struct nic_port_info port_info;
/* percentage of pf link bandwidth */
- u32 pf_bw_limit;
- u32 rsvd2;
+ u32 pf_bw_tx_limit;
+ u32 pf_bw_rx_limit;
- struct hinic3_port_routine_cmd rt_cmd;
- struct mutex sfp_mutex; /* mutex used for copy sfp info */
+ struct hinic3_port_routine_cmd rt_cmd;
+ struct hinic3_port_routine_cmd_extern rt_cmd_ext;
+ /* mutex used for copy sfp info */
+ struct mutex sfp_mutex;
};
struct hinic3_nic_cmdq_ops;
@@ -98,7 +137,7 @@ struct hinic3_nic_io {
void *dev_hdl;
u8 link_status;
- u8 rsvd1;
+ u8 direct;
u32 rsvd2;
struct hinic3_io_queue *sq;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
index 747ac03..fc3c90a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
@@ -21,11 +21,133 @@
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
#include "hinic3_nic_cmdq.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_common.h"
#include "hinic3_nic_cfg.h"
-int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_sq_attr *attr)
+#include "vram_common.h"
+
+int hinic3_delete_bond(void *hwdev)
+{
+ struct hinic3_cmd_delete_bond cmd_delete_bond;
+ u16 out_size = sizeof(cmd_delete_bond);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err = 0;
+
+ if (!hwdev) {
+ pr_err("hwdev is null.\n");
+ return -EINVAL;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is null.\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd_delete_bond, 0, sizeof(cmd_delete_bond));
+ cmd_delete_bond.bond_id = HINIC3_INVALID_BOND_ID;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BOND_DEV_DELETE,
+ &cmd_delete_bond, sizeof(cmd_delete_bond),
+ &cmd_delete_bond, &out_size);
+ if (err || !out_size || cmd_delete_bond.head.status) {
+ nic_err(nic_io->dev_hdl, "Failed to delete bond, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, cmd_delete_bond.head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (cmd_delete_bond.bond_id != HINIC3_INVALID_BOND_ID)
+ nic_info(nic_io->dev_hdl, "Delete bond success\n");
+
+ return 0;
+}
+
+int hinic3_open_close_bond(void *hwdev, u32 bond_en)
+{
+ struct hinic3_cmd_open_close_bond cmd_open_close_bond;
+ u16 out_size = sizeof(cmd_open_close_bond);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err = 0;
+
+ if (!hwdev) {
+ pr_err("hwdev is null.\n");
+ return -EINVAL;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is null.\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd_open_close_bond, 0, sizeof(cmd_open_close_bond));
+ cmd_open_close_bond.open_close_bond_info.bond_id =
+ HINIC3_INVALID_BOND_ID;
+ cmd_open_close_bond.open_close_bond_info.open_close_flag = bond_en;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BOND_DEV_OPEN_CLOSE,
+ &cmd_open_close_bond,
+ sizeof(cmd_open_close_bond),
+ &cmd_open_close_bond, &out_size);
+ if (err || !out_size || cmd_open_close_bond.head.status) {
+ nic_err(nic_io->dev_hdl, "Failed to %s bond, err: %d, status: 0x%x, out_size: 0x%x\n",
+ bond_en ? "open" : "close", err,
+ cmd_open_close_bond.head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (cmd_open_close_bond.open_close_bond_info.bond_id !=
+ HINIC3_INVALID_BOND_ID) {
+ nic_info(nic_io->dev_hdl, "%s bond success\n",
+ bond_en ? "Open" : "Close");
+ }
+
+ return 0;
+}
+
+int hinic3_create_bond(void *hwdev, u32 *bond_id)
+{
+ struct hinic3_cmd_create_bond cmd_create_bond;
+ u16 out_size = sizeof(cmd_create_bond);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err = 0;
+
+ if (!hwdev) {
+ pr_err("hwdev is null.\n");
+ return -EINVAL;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is null.\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd_create_bond, 0, sizeof(cmd_create_bond));
+ cmd_create_bond.create_bond_info.default_param_flag = true;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BOND_DEV_CREATE,
+ &cmd_create_bond, sizeof(cmd_create_bond),
+ &cmd_create_bond, &out_size);
+ if (err || !out_size || cmd_create_bond.head.status) {
+ nic_err(nic_io->dev_hdl, "Failed to create default bond, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, cmd_create_bond.head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (cmd_create_bond.create_bond_info.bond_id !=
+ HINIC3_INVALID_BOND_ID) {
+ *bond_id = cmd_create_bond.create_bond_info.bond_id;
+ nic_info(nic_io->dev_hdl, "Create bond success\n");
+ }
+
+ return 0;
+}
+
+int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io,
+ struct hinic3_sq_attr *attr)
{
struct hinic3_cmd_cons_idx_attr cons_idx_attr;
u16 out_size = sizeof(cons_idx_attr);
@@ -48,7 +170,8 @@ int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_sq_attr *at
cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
cons_idx_attr.ci_addr = attr->ci_dma_base >> SQ_CI_ADDR_SHIFT;
- err = l2nic_msg_to_mgmt_sync(nic_io->hwdev, HINIC3_NIC_CMD_SQ_CI_ATTR_SET,
+ err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
+ HINIC3_NIC_CMD_SQ_CI_ATTR_SET,
&cons_idx_attr, sizeof(cons_idx_attr),
&cons_idx_attr, &out_size);
if (err || !out_size || cons_idx_attr.msg_head.status) {
@@ -61,7 +184,8 @@ int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_sq_attr *at
return 0;
}
-int hinic3_set_rq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_rq_attr *attr)
+int hinic3_set_rq_ci_ctx(struct hinic3_nic_io *nic_io,
+ struct hinic3_rq_attr *attr)
{
struct hinic3_rq_cqe_ctx cons_idx_ctx;
u16 out_size = sizeof(cons_idx_ctx);
@@ -76,15 +200,19 @@ int hinic3_set_rq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_rq_attr *at
cons_idx_ctx.timer_loop = attr->coalescing_time;
cons_idx_ctx.threshold_cqe_num = attr->pending_limit;
cons_idx_ctx.msix_entry_idx = attr->intr_idx;
- cons_idx_ctx.ci_addr_hi = upper_32_bits(attr->ci_dma_base >> RQ_CI_ADDR_SHIFT);
- cons_idx_ctx.ci_addr_lo = lower_32_bits(attr->ci_dma_base >> RQ_CI_ADDR_SHIFT);
+ cons_idx_ctx.ci_addr_hi = upper_32_bits(attr->ci_dma_base >>
+ RQ_CI_ADDR_SHIFT);
+ cons_idx_ctx.ci_addr_lo = lower_32_bits(attr->ci_dma_base >>
+ RQ_CI_ADDR_SHIFT);
- err = l2nic_msg_to_mgmt_sync(nic_io->hwdev, HINIC3_NIC_CMD_SET_RQ_CI_CTX,
+ err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
+ HINIC3_NIC_CMD_SET_RQ_CI_CTX,
&cons_idx_ctx, sizeof(cons_idx_ctx),
&cons_idx_ctx, &out_size);
if (err || !out_size || cons_idx_ctx.msg_head.status) {
nic_err(nic_io->dev_hdl, "Set rq cqe ctx fail, qid: %d, err: %d, status: 0x%x, out_size: 0x%x",
- attr->l2nic_rqn, err, cons_idx_ctx.msg_head.status, out_size);
+ attr->l2nic_rqn, err,
+ cons_idx_ctx.msg_head.status, out_size);
return -EFAULT;
}
@@ -142,8 +270,8 @@ int hinic3_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id,
&mac_info, sizeof(mac_info),
&mac_info, &out_size, channel);
if (err || !out_size ||
- hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
- mac_info.vlan_id)) {
+ (hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
+ mac_info.vlan_id) != 0)) {
nic_err(nic_io->dev_hdl,
"Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n",
err, mac_info.msg_head.status, out_size, channel);
@@ -178,6 +306,8 @@ int hinic3_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id,
memset(&mac_info, 0, sizeof(mac_info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) {
nic_err(nic_io->dev_hdl, "Invalid VLAN number: %d\n",
@@ -193,7 +323,8 @@ int hinic3_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id,
&mac_info, sizeof(mac_info), &mac_info,
&out_size, channel);
if (err || !out_size ||
- (mac_info.msg_head.status && !PF_SET_VF_MAC(hwdev, mac_info.msg_head.status))) {
+ (mac_info.msg_head.status &&
+ !PF_SET_VF_MAC(hwdev, mac_info.msg_head.status))) {
nic_err(nic_io->dev_hdl,
"Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n",
err, mac_info.msg_head.status, out_size, channel);
@@ -223,6 +354,8 @@ int hinic3_update_mac(void *hwdev, const u8 *old_mac, u8 *new_mac, u16 vlan_id,
memset(&mac_info, 0, sizeof(mac_info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) {
nic_err(nic_io->dev_hdl, "Invalid VLAN number: %d\n",
@@ -239,8 +372,8 @@ int hinic3_update_mac(void *hwdev, const u8 *old_mac, u8 *new_mac, u16 vlan_id,
&mac_info, sizeof(mac_info),
&mac_info, &out_size);
if (err || !out_size ||
- hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
- mac_info.vlan_id)) {
+ (hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
+ mac_info.vlan_id) != 0)) {
nic_err(nic_io->dev_hdl,
"Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n",
err, mac_info.msg_head.status, out_size);
@@ -273,6 +406,8 @@ int hinic3_get_default_mac(void *hwdev, u8 *mac_addr)
memset(&mac_info, 0, sizeof(mac_info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
mac_info.func_id = hinic3_global_func_id(hwdev);
@@ -318,6 +453,45 @@ static int hinic3_config_vlan(struct hinic3_nic_io *nic_io, u8 opcode,
return 0;
}
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+int hinic3_vlxan_port_config(void *hwdev, u16 func_id, u16 port, u8 action)
+{
+ struct hinic3_cmd_vxlan_port_info vxlan_port_info;
+ u16 out_size = sizeof(vxlan_port_info);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ memset(&vxlan_port_info, 0, sizeof(vxlan_port_info));
+ vxlan_port_info.opcode = action;
+ vxlan_port_info.cfg_mode = 0; // other tool set
+ vxlan_port_info.func_id = func_id;
+ vxlan_port_info.vxlan_port = port;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_CFG_VXLAN_PORT,
+ &vxlan_port_info, sizeof(vxlan_port_info),
+ &vxlan_port_info, &out_size);
+ if (err || !out_size || vxlan_port_info.msg_head.status) {
+ if (vxlan_port_info.msg_head.status == 0x2) // other tool set failed
+ nic_warn(nic_io->dev_hdl,
+ "Failed to %s vxlan dst port because it has already been set by hinicadm\n",
+ action == HINIC3_CMD_OP_ADD
+ ? "add" : "delete");
+ else
+ nic_err(nic_io->dev_hdl,
+ "Failed to %s vxlan dst port, err: %d, status: 0x%x, out size: 0x%x\n",
+ action == HINIC3_CMD_OP_ADD ? "add" : "delete",
+ err, vxlan_port_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
+
int hinic3_add_vlan(void *hwdev, u16 vlan_id, u16 func_id)
{
struct hinic3_nic_io *nic_io = NULL;
@@ -326,6 +500,8 @@ int hinic3_add_vlan(void *hwdev, u16 vlan_id, u16 func_id)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
return hinic3_config_vlan(nic_io, HINIC3_CMD_OP_ADD, vlan_id, func_id);
}
@@ -337,6 +513,8 @@ int hinic3_del_vlan(void *hwdev, u16 vlan_id, u16 func_id)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
return hinic3_config_vlan(nic_io, HINIC3_CMD_OP_DEL, vlan_id, func_id);
}
@@ -380,6 +558,8 @@ int hinic3_set_dcb_state(void *hwdev, struct hinic3_dcb_state *dcb_state)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (!memcmp(&nic_io->dcb_state, dcb_state, sizeof(nic_io->dcb_state)))
return 0;
@@ -423,7 +603,8 @@ int hinic3_get_cos_by_pri(void *hwdev, u8 pri, u8 *cos)
if (pri >= NIC_DCB_UP_MAX && nic_io->dcb_state.trust == HINIC3_DCB_PCP)
return -EINVAL;
- if (pri >= NIC_DCB_IP_PRI_MAX && nic_io->dcb_state.trust == HINIC3_DCB_DSCP)
+ if (pri >= NIC_DCB_IP_PRI_MAX &&
+ nic_io->dcb_state.trust == HINIC3_DCB_DSCP)
return -EINVAL;
/*lint -e662*/
@@ -541,13 +722,15 @@ int hinic3_set_pause_info(void *hwdev, struct nic_pause_config nic_pause)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
nic_cfg = &nic_io->nic_cfg;
down(&nic_cfg->cfg_lock);
err = hinic3_cfg_hw_pause(nic_io, HINIC3_CMD_OP_SET, &nic_pause);
- if (err) {
+ if (err != 0) {
up(&nic_cfg->cfg_lock);
return err;
}
@@ -566,7 +749,6 @@ int hinic3_set_pause_info(void *hwdev, struct nic_pause_config nic_pause)
int hinic3_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
{
- struct hinic3_nic_cfg *nic_cfg = NULL;
struct hinic3_nic_io *nic_io = NULL;
int err = 0;
@@ -574,17 +756,13 @@ int hinic3_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- nic_cfg = &nic_io->nic_cfg;
+ if (!nic_io)
+ return -EINVAL;
err = hinic3_cfg_hw_pause(nic_io, HINIC3_CMD_OP_GET, nic_pause);
- if (err)
+ if (err != 0)
return err;
- if (nic_cfg->pause_set || !nic_pause->auto_neg) {
- nic_pause->rx_pause = nic_cfg->nic_pause.rx_pause;
- nic_pause->tx_pause = nic_cfg->nic_pause.tx_pause;
- }
-
return 0;
}
@@ -599,6 +777,8 @@ int hinic3_sync_dcb_state(void *hwdev, u8 op_code, u8 state)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&dcb_state, 0, sizeof(dcb_state));
@@ -607,7 +787,8 @@ int hinic3_sync_dcb_state(void *hwdev, u8 op_code, u8 state)
dcb_state.func_id = hinic3_global_func_id(hwdev);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_QOS_DCB_STATE,
- &dcb_state, sizeof(dcb_state), &dcb_state, &out_size);
+ &dcb_state, sizeof(dcb_state),
+ &dcb_state, &out_size);
if (err || dcb_state.head.status || !out_size) {
nic_err(nic_io->dev_hdl,
"Failed to set dcb state, err: %d, status: 0x%x, out size: 0x%x\n",
@@ -675,7 +856,8 @@ int hinic3_cache_out_qps_res(void *hwdev)
qp_res.func_id = hinic3_global_func_id(hwdev);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_CACHE_OUT_QP_RES,
- &qp_res, sizeof(qp_res), &qp_res, &out_size);
+ &qp_res, sizeof(qp_res),
+ &qp_res, &out_size);
if (err || !out_size || qp_res.msg_head.status) {
nic_err(nic_io->dev_hdl, "Failed to cache out qp resources, err: %d, status: 0x%x, out size: 0x%x\n",
err, qp_res.msg_head.status, out_size);
@@ -685,45 +867,8 @@ int hinic3_cache_out_qps_res(void *hwdev)
return 0;
}
-int hinic3_get_fpga_phy_port_stats(void *hwdev, struct hinic3_phy_fpga_port_stats *stats)
-{
- struct hinic3_port_stats *port_stats = NULL;
- struct hinic3_port_stats_info stats_info;
- u16 out_size = sizeof(*port_stats);
- struct hinic3_nic_io *nic_io = NULL;
- int err;
-
- port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
- if (!port_stats)
- return -ENOMEM;
-
- nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (!nic_io)
- return -EINVAL;
-
- memset(&stats_info, 0, sizeof(stats_info));
-
- err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_GET_PORT_STAT,
- &stats_info, sizeof(stats_info),
- port_stats, &out_size);
- if (err || !out_size || port_stats->msg_head.status) {
- nic_err(nic_io->dev_hdl,
- "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
- err, port_stats->msg_head.status, out_size);
- err = -EIO;
- goto out;
- }
-
- memcpy(stats, &port_stats->stats, sizeof(*stats));
-
-out:
- kfree(port_stats);
-
- return err;
-}
-EXPORT_SYMBOL(hinic3_get_fpga_phy_port_stats);
-
-int hinic3_get_vport_stats(void *hwdev, u16 func_id, struct hinic3_vport_stats *stats)
+int hinic3_get_vport_stats(void *hwdev, u16 func_id,
+ struct hinic3_vport_stats *stats)
{
struct hinic3_port_stats_info stats_info;
struct hinic3_cmd_vport_stats vport_stats;
@@ -738,6 +883,8 @@ int hinic3_get_vport_stats(void *hwdev, u16 func_id, struct hinic3_vport_stats *
memset(&vport_stats, 0, sizeof(vport_stats));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
stats_info.func_id = func_id;
@@ -756,7 +903,8 @@ int hinic3_get_vport_stats(void *hwdev, u16 func_id, struct hinic3_vport_stats *
return 0;
}
-static int hinic3_set_function_table(struct hinic3_nic_io *nic_io, u32 cfg_bitmap,
+static int hinic3_set_function_table(struct hinic3_nic_io *nic_io,
+ u32 cfg_bitmap,
const struct hinic3_func_tbl_cfg *cfg)
{
struct hinic3_cmd_set_func_tbl cmd_func_tbl;
@@ -804,6 +952,8 @@ int hinic3_set_port_mtu(void *hwdev, u16 new_mtu)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (new_mtu < HINIC3_MIN_MTU_SIZE) {
nic_err(nic_io->dev_hdl,
@@ -834,6 +984,8 @@ static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&feature_nego, 0, sizeof(feature_nego));
feature_nego.func_id = hinic3_global_func_id(hwdev);
feature_nego.opcode = opcode;
@@ -855,29 +1007,24 @@ static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size)
return 0;
}
-static int hinic3_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit)
+static int hinic3_get_bios_pf_bw_tx_limit(void *hwdev,
+ struct hinic3_nic_io *nic_io,
+ u16 func_id, u32 *pf_rate)
{
- struct hinic3_nic_io *nic_io = NULL;
+ int err = 0; // default success
struct nic_cmd_bios_cfg cfg = {{0}};
u16 out_size = sizeof(cfg);
- int err;
-
- if (!hwdev || !pf_bw_limit)
- return -EINVAL;
-
- if (hinic3_func_type(hwdev) == TYPE_VF || !HINIC3_SUPPORT_RATE_LIMIT(hwdev))
- return 0;
- nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- cfg.bios_cfg.func_id = (u8)hinic3_global_func_id(hwdev);
+ cfg.bios_cfg.func_id = (u8)func_id;
cfg.bios_cfg.func_valid = 1;
- cfg.op_code = 0 | NIC_NVM_DATA_PF_SPEED_LIMIT;
+ cfg.op_code = 0 | NIC_NVM_DATA_PF_TX_SPEED_LIMIT;
- err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BIOS_CFG, &cfg, sizeof(cfg),
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BIOS_CFG,
+ &cfg, sizeof(cfg),
&cfg, &out_size);
if (err || !out_size || cfg.head.status) {
nic_err(nic_io->dev_hdl,
- "Failed to get bios pf bandwidth limit, err: %d, status: 0x%x, out size: 0x%x\n",
+ "Failed to get bios pf bandwidth tx limit, err: %d, status: 0x%x, out size: 0x%x\n",
err, cfg.head.status, out_size);
return -EIO;
}
@@ -887,13 +1034,86 @@ static int hinic3_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit)
nic_warn(nic_io->dev_hdl, "Invalid bios configuration data, signature: 0x%x\n",
cfg.bios_cfg.signature);
- if (cfg.bios_cfg.pf_bw > MAX_LIMIT_BW) {
+ if (cfg.bios_cfg.pf_tx_bw > MAX_LIMIT_BW) {
+ nic_err(nic_io->dev_hdl, "Invalid bios cfg pf bandwidth limit: %u\n",
+ cfg.bios_cfg.pf_tx_bw);
+ return -EINVAL;
+ }
+
+ (*pf_rate) = cfg.bios_cfg.pf_tx_bw;
+ return err;
+}
+
+static int hinic3_get_bios_pf_bw_rx_limit(void *hwdev,
+ struct hinic3_nic_io *nic_io,
+ u16 func_id, u32 *pf_rate)
+{
+ int err = 0; // default success
+ struct nic_rx_rate_bios_cfg rx_bios_conf = {{0}};
+ u16 out_size = sizeof(rx_bios_conf);
+
+ rx_bios_conf.func_id = (u8)func_id;
+ rx_bios_conf.op_code = 0; /* 1-save, 0-read */
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_RX_RATE_CFG,
+ &rx_bios_conf, sizeof(rx_bios_conf),
+ &rx_bios_conf, &out_size);
+ if (rx_bios_conf.msg_head.status == HINIC3_MGMT_CMD_UNSUPPORTED &&
+ err == 0) { // Compatible older firmware
+ nic_warn(nic_io->dev_hdl, "Not support get bios pf bandwidth rx limit\n");
+ return 0;
+ } else if (err || !out_size || rx_bios_conf.msg_head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get bios pf bandwidth rx limit, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, rx_bios_conf.msg_head.status, out_size);
+ return -EIO;
+ }
+ if (rx_bios_conf.rx_rate_limit > MAX_LIMIT_BW) {
nic_err(nic_io->dev_hdl, "Invalid bios cfg pf bandwidth limit: %u\n",
- cfg.bios_cfg.pf_bw);
+ rx_bios_conf.rx_rate_limit);
return -EINVAL;
}
- *pf_bw_limit = cfg.bios_cfg.pf_bw;
+ (*pf_rate) = rx_bios_conf.rx_rate_limit;
+ return err;
+}
+
+static int hinic3_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit, u8 direct)
+{
+ struct hinic3_nic_io *nic_io = NULL;
+ u32 pf_rate = 0;
+ int err = 0;
+ u16 func_id;
+
+ func_id = hinic3_global_func_id(hwdev);
+
+ if (!hwdev || !pf_bw_limit)
+ return -EINVAL;
+
+ if (hinic3_func_type(hwdev) == TYPE_VF ||
+ !HINIC3_SUPPORT_RATE_LIMIT(hwdev))
+ return 0;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ if (direct == HINIC3_NIC_TX)
+ err = hinic3_get_bios_pf_bw_tx_limit(hwdev, nic_io,
+ func_id, &pf_rate);
+ else if (direct == HINIC3_NIC_RX)
+ err = hinic3_get_bios_pf_bw_rx_limit(hwdev, nic_io,
+ func_id, &pf_rate);
+
+ if (err != 0)
+ return err;
+
+ if (pf_rate > MAX_LIMIT_BW) {
+ nic_err(nic_io->dev_hdl,
+ "Invalid bios cfg pf bandwidth limit: %u\n", pf_rate);
+ return -EINVAL;
+ }
+
+ *pf_bw_limit = pf_rate;
return 0;
}
@@ -902,8 +1122,9 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level)
{
struct hinic3_cmd_tx_rate_cfg rate_cfg = {{0}};
struct hinic3_nic_io *nic_io = NULL;
+ u32 rate_limit;
u16 out_size = sizeof(rate_cfg);
- u32 pf_rate;
+ u32 pf_rate = 0;
int err;
u32 speed_convert[PORT_SPEED_UNKNOWN] = {
0, 10, 100, 1000, 10000, 25000, 40000, 50000, 100000, 200000
@@ -914,15 +1135,16 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level)
return -EINVAL;
if (speed_level >= PORT_SPEED_UNKNOWN) {
- nic_err(nic_io->dev_hdl, "Invalid speed level: %u\n", speed_level);
+ nic_err(nic_io->dev_hdl,
+ "Invalid speed level: %u\n", speed_level);
return -EINVAL;
}
- if (nic_io->nic_cfg.pf_bw_limit == MAX_LIMIT_BW) {
- pf_rate = 0;
- } else {
+ rate_limit = (nic_io->direct == HINIC3_NIC_TX) ?
+ nic_io->nic_cfg.pf_bw_tx_limit : nic_io->nic_cfg.pf_bw_rx_limit;
+ if (rate_limit != MAX_LIMIT_BW) {
/* divided by 100 to convert to percentage */
- pf_rate = (speed_convert[speed_level] / 100) * nic_io->nic_cfg.pf_bw_limit;
+ pf_rate = (speed_convert[speed_level] / 100) * rate_limit;
/* bandwidth limit is very small but not unlimit in this case */
if (pf_rate == 0 && speed_level != PORT_SPEED_NOT_SET)
pf_rate = 1;
@@ -931,13 +1153,16 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level)
rate_cfg.func_id = hinic3_global_func_id(hwdev);
rate_cfg.min_rate = 0;
rate_cfg.max_rate = pf_rate;
+ rate_cfg.direct = nic_io->direct;
- err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_SET_MAX_MIN_RATE, &rate_cfg,
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_SET_MAX_MIN_RATE,
+ &rate_cfg,
sizeof(rate_cfg), &rate_cfg, &out_size);
if (err || !out_size || rate_cfg.msg_head.status) {
nic_err(nic_io->dev_hdl, "Failed to set rate(%u), err: %d, status: 0x%x, out size: 0x%x\n",
pf_rate, err, rate_cfg.msg_head.status, out_size);
- return rate_cfg.msg_head.status ? rate_cfg.msg_head.status : -EIO;
+ return rate_cfg.msg_head.status
+ ? rate_cfg.msg_head.status : -EIO;
}
return 0;
@@ -954,7 +1179,8 @@ int hinic3_set_nic_feature_to_hw(void *hwdev)
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- return nic_feature_nego(hwdev, HINIC3_CMD_OP_SET, &nic_io->feature_cap, 1);
+ return nic_feature_nego(hwdev, HINIC3_CMD_OP_SET,
+ &nic_io->feature_cap, 1);
}
u64 hinic3_get_feature_cap(void *hwdev)
@@ -962,6 +1188,8 @@ u64 hinic3_get_feature_cap(void *hwdev)
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return 0;
return nic_io->feature_cap;
}
@@ -971,12 +1199,17 @@ void hinic3_update_nic_feature(void *hwdev, u64 s_feature)
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
nic_io->feature_cap = s_feature;
- nic_info(nic_io->dev_hdl, "Update nic feature to 0x%llx\n", nic_io->feature_cap);
+ nic_info(nic_io->dev_hdl,
+ "Update nic feature to 0x%llx\n",
+ nic_io->feature_cap);
}
-static inline int init_nic_hwdev_param_valid(const void *hwdev, const void *pcidev_hdl,
+static inline int init_nic_hwdev_param_valid(const void *hwdev,
+ const void *pcidev_hdl,
const void *dev_hdl)
{
if (!hwdev || !pcidev_hdl || !dev_hdl)
@@ -1004,6 +1237,7 @@ static int hinic3_init_nic_io(void *hwdev, void *pcidev_hdl, void *dev_hdl,
(*nic_io)->nic_cfg.rt_cmd.mpu_send_sfp_abs = false;
(*nic_io)->nic_cfg.rt_cmd.mpu_send_sfp_info = false;
+ (*nic_io)->nic_cfg.rt_cmd_ext.mpu_send_xsfp_tlv_info = false;
return 0;
}
@@ -1020,27 +1254,34 @@ int hinic3_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl,
{
struct hinic3_nic_io *nic_io = NULL;
int err;
+ int is_in_kexec = vram_get_kexec_flag();
err = hinic3_init_nic_io(hwdev, pcidev_hdl, dev_hdl, &nic_io);
- if (err)
+ if (err != 0)
return err;
+ nic_io->rx_buff_len = rx_buff_len;
+
err = hinic3_register_service_adapter(hwdev, nic_io, SERVICE_T_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to register service adapter\n");
goto register_sa_err;
}
- err = hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC, 1, HINIC3_CHANNEL_NIC);
- if (err) {
+ err = hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC,
+ 1, HINIC3_CHANNEL_NIC);
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set function svc used state\n");
goto set_used_state_err;
}
- err = hinic3_init_function_table(nic_io);
- if (err) {
- nic_err(nic_io->dev_hdl, "Failed to init function table\n");
- goto err_out;
+ if (is_in_kexec == 0) {
+ err = hinic3_init_function_table(nic_io);
+ if (err != 0) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to init function table\n");
+ goto err_out;
+ }
}
err = hinic3_get_nic_feature_from_hw(hwdev, &nic_io->feature_cap, 1);
@@ -1052,24 +1293,35 @@ int hinic3_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl,
sdk_info(dev_hdl, "nic features: 0x%llx\n", nic_io->feature_cap);
hinic3_nic_cmdq_adapt_init(nic_io);
- err = hinic3_get_bios_pf_bw_limit(hwdev, &nic_io->nic_cfg.pf_bw_limit);
- if (err) {
- nic_err(nic_io->dev_hdl, "Failed to get pf bandwidth limit\n");
+ err = hinic3_get_bios_pf_bw_limit(hwdev,
+ &nic_io->nic_cfg.pf_bw_tx_limit,
+ HINIC3_NIC_TX);
+ if (err != 0) {
+ nic_err(nic_io->dev_hdl, "Failed to get pf tx bandwidth limit\n");
+ goto err_out;
+ }
+
+ err = hinic3_get_bios_pf_bw_limit(hwdev,
+ &nic_io->nic_cfg.pf_bw_rx_limit,
+ HINIC3_NIC_RX);
+ if (err != 0) {
+ nic_err(nic_io->dev_hdl, "Failed to get pf rx bandwidth limit\n");
goto err_out;
}
err = hinic3_vf_func_init(nic_io);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to init vf info\n");
goto err_out;
}
- nic_io->rx_buff_len = rx_buff_len;
-
return 0;
err_out:
- hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC, 0, HINIC3_CHANNEL_NIC);
+ if (hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC,
+ 0, HINIC3_CHANNEL_NIC) != 0) {
+ nic_err(nic_io->dev_hdl, "Failed to set function svc used state\n");
+ }
set_used_state_err:
hinic3_unregister_service_adapter(hwdev, SERVICE_T_NIC);
@@ -1119,6 +1371,8 @@ int hinic3_force_drop_tx_pkt(void *hwdev)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&pkt_drop, 0, sizeof(pkt_drop));
pkt_drop.port = hinic3_physical_port_id(hwdev);
@@ -1147,6 +1401,8 @@ int hinic3_set_rx_mode(void *hwdev, u32 enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
rx_mode_cfg.func_id = hinic3_global_func_id(hwdev);
@@ -1175,6 +1431,8 @@ int hinic3_set_rx_vlan_offload(void *hwdev, u8 en)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&vlan_cfg, 0, sizeof(vlan_cfg));
vlan_cfg.func_id = hinic3_global_func_id(hwdev);
@@ -1192,7 +1450,8 @@ int hinic3_set_rx_vlan_offload(void *hwdev, u8 en)
return 0;
}
-int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
+int hinic3_update_mac_vlan(void *hwdev, const u16 old_vlan,
+ u16 new_vlan, int vf_id)
{
struct vf_data_storage *vf_info = NULL;
struct hinic3_nic_io *nic_io = NULL;
@@ -1203,6 +1462,8 @@ int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
if (!nic_io->vf_infos || is_zero_ether_addr(vf_info->drv_mac_addr))
return 0;
@@ -1211,7 +1472,7 @@ int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
err = hinic3_del_mac(nic_io->hwdev, vf_info->drv_mac_addr,
old_vlan, func_id, HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to delete VF %d MAC %pM vlan %u\n",
HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, old_vlan);
return err;
@@ -1219,7 +1480,7 @@ int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
err = hinic3_set_mac(nic_io->hwdev, vf_info->drv_mac_addr,
new_vlan, func_id, HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to add VF %d MAC %pM vlan %u\n",
HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, new_vlan);
hinic3_set_mac(nic_io->hwdev, vf_info->drv_mac_addr,
@@ -1242,6 +1503,8 @@ static int hinic3_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en,
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&lro_cfg, 0, sizeof(lro_cfg));
lro_cfg.func_id = hinic3_global_func_id(hwdev);
@@ -1273,6 +1536,8 @@ static int hinic3_set_rx_lro_timer(void *hwdev, u32 timer_value)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&lro_timer, 0, sizeof(lro_timer));
lro_timer.opcode = HINIC3_CMD_OP_SET;
@@ -1305,12 +1570,14 @@ int hinic3_set_rx_lro_state(void *hwdev, u8 lro_en, u32 lro_timer,
ipv6_en = lro_en ? 1 : 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
nic_info(nic_io->dev_hdl, "Set LRO max coalesce packet size to %uK\n",
lro_max_pkt_len);
err = hinic3_set_rx_lro(hwdev, ipv4_en, ipv6_en, (u8)lro_max_pkt_len);
- if (err)
+ if (err != 0)
return err;
/* we don't set LRO timer for VF */
@@ -1333,6 +1600,8 @@ int hinic3_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&vlan_filter, 0, sizeof(vlan_filter));
vlan_filter.func_id = hinic3_global_func_id(hwdev);
@@ -1352,7 +1621,6 @@ int hinic3_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl)
int hinic3_set_func_capture_en(void *hwdev, u16 func_id, bool cap_en)
{
- // struct hinic_hwdev *dev = hwdev;
struct nic_cmd_capture_info cap_info = {{0}};
u16 out_size = sizeof(cap_info);
int err;
@@ -1361,7 +1629,6 @@ int hinic3_set_func_capture_en(void *hwdev, u16 func_id, bool cap_en)
return -EINVAL;
/* 2 function capture types */
- // cap_info.op_type = UP_UCAPTURE_OP_TYPE_FUNC;
cap_info.is_en_trx = cap_en;
cap_info.func_port = func_id;
@@ -1386,6 +1653,8 @@ int hinic3_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (tcam_rule->index >= HINIC3_MAX_TCAM_RULES_NUM) {
nic_err(nic_io->dev_hdl, "Tcam rules num to add is invalid\n");
return -EINVAL;
@@ -1421,6 +1690,8 @@ int hinic3_del_tcam_rule(void *hwdev, u32 index)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (index >= HINIC3_MAX_TCAM_RULES_NUM) {
nic_err(nic_io->dev_hdl, "Tcam rules num to del is invalid\n");
return -EINVAL;
@@ -1470,6 +1741,8 @@ static int hinic3_mgmt_tcam_block(void *hwdev, u8 alloc_en, u16 *index)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&tcam_block_info, 0,
sizeof(struct nic_cmd_ctrl_tcam_block_out));
@@ -1515,6 +1788,8 @@ int hinic3_set_fdir_tcam_rule_filter(void *hwdev, bool enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
port_tcam_cmd.func_id = hinic3_global_func_id(hwdev);
port_tcam_cmd.tcam_enable = (u8)enable;
@@ -1543,6 +1818,8 @@ int hinic3_flush_tcam_rule(void *hwdev)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&tcam_flush, 0, sizeof(struct nic_cmd_flush_tcam_rules));
tcam_flush.func_id = hinic3_global_func_id(hwdev);
@@ -1560,7 +1837,8 @@ int hinic3_flush_tcam_rule(void *hwdev)
return 0;
}
-int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num_qps, u16 wqe_type)
+int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info,
+ u16 num_qps, u16 wqe_type)
{
struct hinic3_cmd_buf *cmd_buf = NULL;
struct hinic3_nic_io *nic_io = NULL;
@@ -1573,6 +1851,8 @@ int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
cmd_buf = hinic3_alloc_cmd_buf(hwdev);
if (!cmd_buf) {
nic_err(nic_io->dev_hdl, "Failed to allocate cmd_buf.\n");
@@ -1587,9 +1867,11 @@ int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num
cmd_buf->size = sizeof(struct hinic3_rxq_hw);
- err = hinic3_cmdq_detail_resp(hwdev, HINIC3_MOD_L2NIC, HINIC3_UCODE_CMD_RXQ_INFO_GET,
- cmd_buf, cmd_buf, NULL, 0, HINIC3_CHANNEL_NIC);
- if (err)
+ err = hinic3_cmdq_detail_resp(hwdev, HINIC3_MOD_L2NIC,
+ HINIC3_UCODE_CMD_RXQ_INFO_GET,
+ cmd_buf, cmd_buf, NULL, 0,
+ HINIC3_CHANNEL_NIC);
+ if (err != 0)
goto get_rxq_info_failed;
rxq_info_out = cmd_buf->buf;
@@ -1604,7 +1886,8 @@ get_rxq_info_failed:
return err;
}
-int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced, bool link_state)
+int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced,
+ bool link_state)
{
struct hinic3_nic_io *nic_io = NULL;
struct vf_data_storage *vf_infos = NULL;
@@ -1615,8 +1898,10 @@ int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced, bool link_stat
return -EINVAL;
}
- if (hinic3_func_type(hwdev) == TYPE_VF)
+ if (hinic3_func_type(hwdev) == TYPE_VF) {
+ pr_err("VF are not supported to set link state.\n");
return -EINVAL;
+ }
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
if (!nic_io) {
@@ -1633,3 +1918,35 @@ int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced, bool link_stat
return 0;
}
EXPORT_SYMBOL(hinic3_pf_set_vf_link_state);
+
+int hinic3_get_outband_vlan_cfg(void *hwdev, u16 *outband_default_vid)
+{
+ struct hinic3_outband_cfg_info outband_cfg_info;
+ u16 out_size = sizeof(outband_cfg_info);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err;
+
+ if (!hwdev || !outband_default_vid)
+ return -EINVAL;
+
+ memset(&outband_cfg_info, 0, sizeof(outband_cfg_info));
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_GET_OUTBAND_CFG,
+ &outband_cfg_info,
+ sizeof(outband_cfg_info),
+ &outband_cfg_info, &out_size);
+ if (err || !out_size || outband_cfg_info.msg_head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get outband cfg, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, outband_cfg_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ *outband_default_vid = outband_cfg_info.outband_default_vid;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
index dd2c2fd..60caf68 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
@@ -7,9 +7,10 @@
#include <linux/types.h>
#include <linux/netdevice.h>
-#include "hinic3_mgmt_interface.h"
#include "mag_mpu_cmd.h"
-#include "mag_cmd.h"
+#include "mag_mpu_cmd_defs.h"
+#include "nic_cfg_comm.h"
+#include "nic_mpu_cmd_defs.h"
#define OS_VF_ID_TO_HW(os_vf_id) ((os_vf_id) + 1)
#define HW_VF_ID_TO_OS(hw_vf_id) ((hw_vf_id) - 1)
@@ -54,6 +55,8 @@
#define MAX_LIMIT_BW 100
+#define HINIC3_INVALID_BOND_ID 0xffffffff
+
enum hinic3_valid_link_settings {
HILINK_LINK_SET_SPEED = 0x1,
HILINK_LINK_SET_AUTONEG = 0x2,
@@ -67,6 +70,11 @@ enum hinic3_link_follow_status {
HINIC3_LINK_FOLLOW_STATUS_MAX,
};
+enum hinic3_nic_pf_direct {
+ HINIC3_NIC_RX = 0,
+ HINIC3_NIC_TX,
+};
+
struct hinic3_link_ksettings {
u32 valid_bitmap;
u8 speed; /* enum nic_speed_level */
@@ -152,8 +160,12 @@ struct nic_port_info {
u8 duplex;
u8 speed;
u8 fec;
+ u8 lanes;
+ u8 rsvd;
u32 supported_mode;
u32 advertised_mode;
+ u32 supported_fec_mode;
+ u32 bond_speed;
};
struct nic_pause_config {
@@ -178,11 +190,17 @@ struct hinic3_rxq_hw {
#define MODULE_TYPE_QSFP28 0x11
#define MODULE_TYPE_QSFP 0x0C
#define MODULE_TYPE_QSFP_PLUS 0x0D
+#define MODULE_TYPE_DSFP 0x1B
+#define MODULE_TYPE_QSFP_CMIS 0x1E
#define TCAM_IP_TYPE_MASK 0x1
#define TCAM_TUNNEL_TYPE_MASK 0xF
#define TCAM_FUNC_ID_MASK 0x7FFF
+int hinic3_delete_bond(void *hwdev);
+int hinic3_open_close_bond(void *hwdev, u32 bond_en);
+int hinic3_create_bond(void *hwdev, u32 *bond_id);
+
int hinic3_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule);
int hinic3_del_tcam_rule(void *hwdev, u32 index);
@@ -335,7 +353,7 @@ int hinic3_kill_vf_vlan(void *hwdev, int vf_id);
* @retval zero: success
* @retval non-zero: failure
*/
-int hinic3_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr);
+int hinic3_set_vf_mac(void *hwdev, int vf_id, const unsigned char *mac_addr);
/* *
* @brief hinic3_vf_info_vlanprio - get vf vlan priority
@@ -510,7 +528,14 @@ int hinic3_rss_get_indir_tbl(void *hwdev, u32 *indir_table);
*/
int hinic3_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats);
-int hinic3_get_fpga_phy_port_stats(void *hwdev, struct hinic3_phy_fpga_port_stats *stats);
+/* *
+ * @brief hinic3_get_phy_rsfec_stats - get rsfec stats
+ * @param hwdev: device pointer to hwdev
+ * @param stats: rsfec(Reed-Solomon Forward Error Correction) stats
+ * @retval zero: success
+ * @retval non-zero: failure
+ */
+int hinic3_get_phy_rsfec_stats(void *hwdev, struct mag_cmd_rsfec_stats *stats);
int hinic3_set_port_funcs_state(void *hwdev, bool enable);
@@ -546,6 +571,8 @@ int hinic3_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl);
void hinic3_clear_vfs_info(void *hwdev);
+int hinic3_notify_vf_outband_cfg(void *hwdev, u16 func_id, u16 vlan_id);
+
int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id);
int hinic3_set_led_status(void *hwdev, enum mag_led_type type,
@@ -565,9 +592,13 @@ int hinic3_set_autoneg(void *hwdev, bool enable);
int hinic3_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext);
int hinic3_get_sfp_eeprom(void *hwdev, u8 *data, u32 len);
+int hinic3_get_tlv_xsfp_eeprom(void *hwdev, u8 *data, u32 len);
bool hinic3_if_sfp_absent(void *hwdev);
int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info);
+int hinic3_get_sfp_tlv_info(void *hwdev,
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp *sfp_tlv_info,
+ const struct tag_mag_cmd_get_xsfp_tlv_req *sfp_tlv_info_req);
/* *
* @brief hinic3_set_nic_feature_to_hw - sync nic feature to hardware
@@ -620,4 +651,19 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level);
int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num_qps, u16 wqe_type);
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+/* *
+ * @brief hinic3_vlxan_port_config - add/del vxlan dst port
+ * @param hwdev: device pointer to hwdev
+ * @param func_id: function id
+ * @param port: vxlan dst port
+ * @param action: add or del, del will set to default value (0x12B5)
+ * @retval zero: success
+ * @retval non-zero: failure
+ */
+int hinic3_vlxan_port_config(void *hwdev, u16 func_id, u16 port, u8 action);
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
+
+int hinic3_get_outband_vlan_cfg(void *hwdev, u16 *outband_default_vid);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c
index 15d081b..c0e0a61 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c
@@ -22,7 +22,8 @@
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
#include "hinic3_nic_cmdq.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
/*lint -e806*/
static unsigned char set_vf_link_state;
@@ -59,7 +60,8 @@ static int hinic3_set_vlan_ctx(struct hinic3_nic_io *nic_io, u16 func_id,
vlan_tag, q_id, vlan_mode);
err = hinic3_cmdq_direct_resp(nic_io->hwdev, HINIC3_MOD_L2NIC,
- cmd, cmd_buf, &out_param, 0, HINIC3_CHANNEL_NIC);
+ cmd, cmd_buf, &out_param,
+ 0, HINIC3_CHANNEL_NIC);
hinic3_free_cmd_buf(nic_io->hwdev, cmd_buf);
@@ -108,7 +110,7 @@ int hinic3_cfg_vf_vlan(struct hinic3_nic_io *nic_io, u8 opcode, u16 vid,
err = hinic3_set_vlan_ctx(nic_io, glb_func_id, vlan_tag,
NIC_CONFIG_ALL_QUEUE_VLAN_CTX,
opcode == HINIC3_CMD_OP_ADD);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set VF %d vlan ctx, err: %d\n",
HW_VF_ID_TO_OS(vf_id), err);
@@ -129,12 +131,15 @@ int hinic3_cfg_vf_vlan(struct hinic3_nic_io *nic_io, u8 opcode, u16 vid,
/* this function just be called by hinic3_ndo_set_vf_mac,
* others are not permitted.
*/
-int hinic3_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr)
+int hinic3_set_vf_mac(void *hwdev, int vf_id, const unsigned char *mac_addr)
{
- struct vf_data_storage *vf_info;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vf_info = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
#ifndef __VMWARE__
/* duplicate request, so just return success */
@@ -152,13 +157,15 @@ int hinic3_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr)
int hinic3_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos)
{
- struct hinic3_nic_io *nic_io;
+ struct hinic3_nic_io *nic_io = NULL;
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
err = hinic3_cfg_vf_vlan(nic_io, HINIC3_CMD_OP_ADD, vlan, qos, vf_id);
- if (err)
+ if (err != 0)
return err;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan;
@@ -172,17 +179,19 @@ int hinic3_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos)
int hinic3_kill_vf_vlan(void *hwdev, int vf_id)
{
- struct vf_data_storage *vf_infos;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vf_infos = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
vf_infos = nic_io->vf_infos;
err = hinic3_cfg_vf_vlan(nic_io, HINIC3_CMD_OP_DEL,
vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,
vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos, vf_id);
- if (err)
+ if (err != 0)
return err;
nic_info(nic_io->dev_hdl, "Remove VLAN %u on VF %d\n",
@@ -197,11 +206,13 @@ int hinic3_kill_vf_vlan(void *hwdev, int vf_id)
u16 hinic3_vf_info_vlanprio(void *hwdev, int vf_id)
{
- struct hinic3_nic_io *nic_io;
+ struct hinic3_nic_io *nic_io = NULL;
u16 pf_vlan, vlanprio;
u8 pf_qos;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return 0;
pf_vlan = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan;
pf_qos = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos;
@@ -214,9 +225,14 @@ int hinic3_set_vf_link_state(void *hwdev, u16 vf_id, int link)
{
struct hinic3_nic_io *nic_io =
hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- struct vf_data_storage *vf_infos = nic_io->vf_infos;
+ struct vf_data_storage *vf_infos = NULL;
u8 link_status = 0;
+ if (!nic_io)
+ return -EINVAL;
+
+ vf_infos = nic_io->vf_infos;
+
switch (link) {
case HINIC3_IFLA_VF_LINK_STATE_AUTO:
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false;
@@ -256,6 +272,8 @@ int hinic3_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
vf_infos = nic_io->vf_infos;
memset(&spoofchk_cfg, 0, sizeof(spoofchk_cfg));
@@ -280,9 +298,11 @@ int hinic3_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk)
bool hinic3_vf_info_spoofchk(void *hwdev, int vf_id)
{
- struct hinic3_nic_io *nic_io;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return false;
return nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk;
}
@@ -296,7 +316,7 @@ int hinic3_set_vf_trust(void *hwdev, u16 vf_id, bool trust)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (vf_id > nic_io->max_vfs)
+ if (!nic_io || vf_id > nic_io->max_vfs)
return -EINVAL;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust = trust;
@@ -309,11 +329,11 @@ bool hinic3_get_vf_trust(void *hwdev, int vf_id)
struct hinic3_nic_io *nic_io = NULL;
if (!hwdev)
- return -EINVAL;
+ return false;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (vf_id > nic_io->max_vfs)
- return -EINVAL;
+ if (!nic_io || vf_id > nic_io->max_vfs)
+ return false;
return nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust;
}
@@ -331,6 +351,7 @@ static int hinic3_set_vf_tx_rate_max_min(struct hinic3_nic_io *nic_io,
rate_cfg.func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf_id;
rate_cfg.max_rate = max_rate;
rate_cfg.min_rate = min_rate;
+ rate_cfg.direct = HINIC3_NIC_TX;
err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
HINIC3_NIC_CMD_SET_MAX_MIN_RATE,
&rate_cfg, sizeof(rate_cfg), &rate_cfg,
@@ -351,13 +372,15 @@ int hinic3_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate)
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (!HINIC3_SUPPORT_RATE_LIMIT(hwdev)) {
nic_err(nic_io->dev_hdl, "Current function doesn't support to set vf rate limit\n");
return -EOPNOTSUPP;
}
err = hinic3_set_vf_tx_rate_max_min(nic_io, vf_id, max_rate, min_rate);
- if (err)
+ if (err != 0)
return err;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate;
@@ -368,12 +391,16 @@ int hinic3_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate)
void hinic3_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi)
{
- struct vf_data_storage *vfinfo;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vfinfo = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
vfinfo = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+ if (!vfinfo)
+ return;
ivi->vf = HW_VF_ID_TO_OS(vf_id);
ether_addr_copy(ivi->mac, vfinfo->user_mac_addr);
@@ -446,13 +473,15 @@ static int vf_func_register(struct hinic3_nic_io *nic_io)
int err;
err = hinic3_register_vf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC,
- nic_io->hwdev, hinic3_vf_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_vf_event_handler);
+ if (err != 0)
return err;
err = hinic3_register_vf_mbox_cb(nic_io->hwdev, HINIC3_MOD_HILINK,
- nic_io->hwdev, hinic3_vf_mag_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_vf_mag_event_handler);
+ if (err != 0)
goto reg_hilink_err;
memset(®ister_info, 0, sizeof(register_info));
@@ -464,6 +493,11 @@ static int vf_func_register(struct hinic3_nic_io *nic_io)
®ister_info, &out_size, 0,
HINIC3_CHANNEL_NIC);
if (err || !out_size || register_info.msg_head.status) {
+ if (hinic3_is_slave_host(nic_io->hwdev)) {
+ nic_warn(nic_io->dev_hdl, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, register_info.msg_head.status, out_size);
+ return 0;
+ }
nic_err(nic_io->dev_hdl, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",
err, register_info.msg_head.status, out_size);
err = -EIO;
@@ -498,18 +532,20 @@ static int pf_init_vf_infos(struct hinic3_nic_io *nic_io)
for (i = 0; i < nic_io->max_vfs; i++) {
err = hinic3_init_vf_infos(nic_io, i);
- if (err)
+ if (err != 0)
goto init_vf_infos_err;
}
err = hinic3_register_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC,
- nic_io->hwdev, hinic3_pf_mbox_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_mbox_handler);
+ if (err != 0)
goto register_pf_mbox_cb_err;
err = hinic3_register_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_HILINK,
- nic_io->hwdev, hinic3_pf_mag_mbox_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_mag_mbox_handler);
+ if (err != 0)
goto register_pf_mag_mbox_cb_err;
return 0;
@@ -531,17 +567,19 @@ int hinic3_vf_func_init(struct hinic3_nic_io *nic_io)
return vf_func_register(nic_io);
err = hinic3_register_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_L2NIC,
- nic_io->hwdev, hinic3_pf_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_event_handler);
+ if (err != 0)
return err;
err = hinic3_register_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_HILINK,
- nic_io->hwdev, hinic3_pf_mag_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_mag_event_handler);
+ if (err != 0)
goto register_mgmt_msg_cb_err;
err = pf_init_vf_infos(nic_io);
- if (err)
+ if (err != 0)
goto pf_init_vf_infos_err;
return 0;
@@ -568,17 +606,24 @@ void hinic3_vf_func_free(struct hinic3_nic_io *nic_io)
&unregister, sizeof(unregister),
&unregister, &out_size, 0,
HINIC3_CHANNEL_NIC);
- if (err || !out_size || unregister.msg_head.status)
- nic_err(nic_io->dev_hdl, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n",
- err, unregister.msg_head.status, out_size);
-
+ if (err || !out_size || unregister.msg_head.status) {
+ if (hinic3_is_slave_host(nic_io->hwdev)) {
+ nic_info(nic_io->dev_hdl, "vRoCE VF notify PF unsuccessful is allowed");
+ } else {
+ nic_err(nic_io->dev_hdl, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, unregister.msg_head.status, out_size);
+ }
+ }
hinic3_unregister_vf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC);
} else {
if (nic_io->vf_infos) {
- hinic3_unregister_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_HILINK);
- hinic3_unregister_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC);
+ hinic3_unregister_pf_mbox_cb(nic_io->hwdev,
+ HINIC3_MOD_HILINK);
+ hinic3_unregister_pf_mbox_cb(nic_io->hwdev,
+ HINIC3_MOD_L2NIC);
hinic3_clear_vfs_info(nic_io->hwdev);
kfree(nic_io->vf_infos);
+ nic_io->vf_infos = NULL;
}
hinic3_unregister_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_HILINK);
hinic3_unregister_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_L2NIC);
@@ -587,11 +632,15 @@ void hinic3_vf_func_free(struct hinic3_nic_io *nic_io)
static void clear_vf_infos(void *hwdev, u16 vf_id)
{
- struct vf_data_storage *vf_infos;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vf_infos = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
u16 func_id;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
func_id = hinic3_glb_pf_vf_offset(hwdev) + vf_id;
vf_infos = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
@@ -620,10 +669,59 @@ static void clear_vf_infos(void *hwdev, u16 vf_id)
void hinic3_clear_vfs_info(void *hwdev)
{
+ u16 i;
struct hinic3_nic_io *nic_io =
hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- u16 i;
+
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
for (i = 0; i < nic_io->max_vfs; i++)
clear_vf_infos(hwdev, OS_VF_ID_TO_HW(i));
}
+
+int hinic3_notify_vf_outband_cfg(void *hwdev, u16 func_id, u16 vlan_id)
+{
+ int err = 0;
+ struct hinic3_outband_cfg_info outband_cfg_info;
+ struct vf_data_storage *vf_infos = NULL;
+ u16 out_size = sizeof(outband_cfg_info);
+ u16 vf_id;
+ struct hinic3_nic_io *nic_io =
+ hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return 0;
+ }
+
+ vf_id = func_id - hinic3_glb_pf_vf_offset(nic_io->hwdev);
+ vf_infos = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+
+ memset(&outband_cfg_info, 0, sizeof(outband_cfg_info));
+ if (vf_infos->registered) {
+ outband_cfg_info.func_id = func_id;
+ outband_cfg_info.outband_default_vid = vlan_id;
+ err = hinic3_mbox_to_vf_no_ack(nic_io->hwdev, vf_id,
+ HINIC3_MOD_L2NIC,
+ HINIC3_NIC_CMD_OUTBAND_CFG_NOTICE,
+ &outband_cfg_info,
+ sizeof(outband_cfg_info),
+ &outband_cfg_info, &out_size,
+ HINIC3_CHANNEL_NIC);
+ if (err == MBOX_ERRCODE_UNKNOWN_DES_FUNC) {
+ nic_warn(nic_io->dev_hdl, "VF%d not initialized, disconnect it\n",
+ HW_VF_ID_TO_OS(vf_id));
+ hinic3_unregister_vf(nic_io, vf_id);
+ return 0;
+ }
+ if (err || !out_size || outband_cfg_info.msg_head.status)
+ nic_err(nic_io->dev_hdl,
+ "outband cfg event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n",
+ HW_VF_ID_TO_OS(vf_id), err,
+ outband_cfg_info.msg_head.status, out_size);
+ }
+
+ return err;
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c
index 0ec4b32..b45c875 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c
@@ -30,6 +30,8 @@ int hinic3_dbg_get_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt,
}
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (q_id >= nic_io->num_qps) {
pr_err("q_id[%u] > num_qps_cfg[%u].\n", q_id, nic_io->num_qps);
return -EINVAL;
@@ -69,6 +71,8 @@ int hinic3_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info,
}
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (q_id >= nic_io->num_qps) {
nic_err(nic_io->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n",
q_id);
@@ -82,6 +86,8 @@ int hinic3_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info,
}
sq = &nic_io->sq[q_id];
+ if (!sq)
+ return -EINVAL;
sq_info->q_id = q_id;
sq_info->pi = hinic3_get_sq_local_pi(sq);
@@ -112,6 +118,8 @@ int hinic3_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info,
}
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (q_id >= nic_io->num_qps) {
nic_err(nic_io->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n",
q_id);
@@ -125,6 +133,8 @@ int hinic3_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info,
}
rq = &nic_io->rq[q_id];
+ if (!rq)
+ return -EINVAL;
rq_info->q_id = q_id;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
index e76a66b..c219452 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
@@ -15,9 +15,10 @@
#include "hinic3_tx.h"
#include "hinic3_rx.h"
#include "hinic3_dcb.h"
+#include "vram_common.h"
#define HINIC3_NIC_DRV_NAME "hinic3"
-#define HINIC3_NIC_DRV_VERSION HINIC3_DRV_VERSION
+#define HINIC3_NIC_DRV_VERSION "17.7.8.1"
#define HINIC3_FUNC_IS_VF(hwdev) (hinic3_func_type(hwdev) == TYPE_VF)
@@ -25,6 +26,10 @@
#define HINIC3_MODERATONE_DELAY HZ
#define LP_PKT_CNT 64
+#define LP_PKT_LEN 60
+
+#define NAPI_IS_REGIN 1
+#define NAPI_NOT_REGIN 0
enum hinic3_flags {
HINIC3_INTF_UP,
@@ -91,6 +96,8 @@ struct hinic3_irq {
u16 rsvd1;
u32 irq_id; /* The IRQ number from OS */
+ u32 napi_reign;
+
char irq_name[IFNAMSIZ + 16];
struct napi_struct napi;
cpumask_t affinity_mask;
@@ -123,6 +130,41 @@ struct hinic3_dyna_txrxq_params {
struct hinic3_dyna_txq_res *txqs_res;
struct hinic3_dyna_rxq_res *rxqs_res;
struct hinic3_irq *irq_cfg;
+ char irq_cfg_vram_name[VRAM_NAME_MAX_LEN];
+};
+
+struct hinic3_flush_rq {
+ union {
+ struct {
+#if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
+ u32 lb_proc : 1;
+ u32 rsvd : 10;
+ u32 rq_id : 8;
+ u32 func_id : 13;
+#else
+ u32 func_id : 13;
+ u32 rq_id : 8;
+ u32 rsvd : 10;
+ u32 lb_proc : 1;
+#endif
+ } bs;
+ u32 value;
+ } dw;
+
+ union {
+ struct {
+#if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
+ u32 rsvd2 : 2;
+ u32 src_chnl : 12;
+ u32 pkt_len : 18;
+#else
+ u32 pkt_len : 18;
+ u32 src_chnl : 12;
+ u32 rsvd2 : 2;
+#endif
+ } bs;
+ u32 value;
+ } lb_info0; /* loop back information, used by uCode */
};
#define HINIC3_NIC_STATS_INC(nic_dev, field) \
@@ -147,6 +189,10 @@ struct hinic3_nic_stats {
#endif
};
+struct hinic3_nic_vport_stats {
+ u64 rx_discard_vport;
+};
+
#define HINIC3_TCAM_DYNAMIC_BLOCK_SIZE 16
#define HINIC3_MAX_TCAM_FILTERS 512
@@ -185,6 +231,28 @@ struct hinic3_tcam_info {
struct hinic3_tcam_dynamic_block_info tcam_dynamic_info;
};
+struct hinic3_dcb {
+ u8 cos_config_num_max;
+ u8 func_dft_cos_bitmap;
+ /* used to tool validity check */
+ u16 port_dft_cos_bitmap;
+
+ struct hinic3_dcb_config hw_dcb_cfg;
+ struct hinic3_dcb_config wanted_dcb_cfg;
+ unsigned long dcb_flags;
+};
+
+struct hinic3_vram {
+ u32 vram_mtu;
+ u16 vram_num_qps;
+ unsigned long flags;
+};
+
+struct hinic3_outband_cfg {
+ u16 outband_default_vid;
+ u16 rsvd;
+};
+
struct hinic3_nic_dev {
struct pci_dev *pdev;
struct net_device *netdev;
@@ -204,6 +272,7 @@ struct hinic3_nic_dev {
u32 dma_rx_buff_size;
u16 rx_buff_len;
u32 page_order;
+ bool page_pool_enabled;
/* Rss related varibles */
u8 rss_hash_engine;
@@ -213,17 +282,13 @@ struct hinic3_nic_dev {
u32 *rss_hkey_be;
u32 *rss_indir;
- u8 cos_config_num_max;
- u8 func_dft_cos_bitmap;
- u16 port_dft_cos_bitmap; /* used to tool validity check */
+ struct hinic3_dcb *dcb;
+ char dcb_name[VRAM_NAME_MAX_LEN];
+
+ struct hinic3_vram *nic_vram;
+ char nic_vram_name[VRAM_NAME_MAX_LEN];
- struct hinic3_dcb_config hw_dcb_cfg;
- struct hinic3_dcb_config wanted_dcb_cfg;
- struct hinic3_dcb_config dcb_cfg;
- unsigned long dcb_flags;
int disable_port_cnt;
- /* lock for disable or enable traffic flow */
- struct semaphore dcb_sem;
struct hinic3_intr_coal_info *intr_coalesce;
unsigned long last_moder_jiffies;
@@ -235,11 +300,10 @@ struct hinic3_nic_dev {
#endif
struct hinic3_nic_stats stats;
+ struct hinic3_nic_vport_stats vport_stats;
/* lock for nic resource */
struct mutex nic_mutex;
- bool force_port_disable;
- struct semaphore port_state_sem;
u8 link_status;
struct nic_service_cap nic_cap;
@@ -281,9 +345,10 @@ struct hinic3_nic_dev {
struct hinic3_nic_prof_attr *prof_attr;
struct hinic3_prof_adapter *prof_adap;
u64 rsvd8[7];
- u32 rsvd9;
+ struct hinic3_outband_cfg outband_cfg;
u32 rxq_get_err_times;
struct delayed_work rxq_check_work;
+ struct delayed_work vport_stats_work;
struct hinic3_tx_rx_ops tx_rx_ops;
};
@@ -312,7 +377,7 @@ struct hinic3_uld_info *get_nic_uld_info(void);
u32 hinic3_get_io_stats_size(const struct hinic3_nic_dev *nic_dev);
-void hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats);
+int hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats);
int hinic3_open(struct net_device *netdev);
@@ -331,6 +396,8 @@ int hinic3_qps_irq_init(struct hinic3_nic_dev *nic_dev);
void hinic3_qps_irq_deinit(struct hinic3_nic_dev *nic_dev);
+void qp_del_napi(struct hinic3_irq *irq_cfg);
+
void hinic3_set_netdev_ops(struct hinic3_nic_dev *nic_dev);
bool hinic3_is_netdev_ops_match(const struct net_device *netdev);
@@ -348,10 +415,6 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
int hinic3_get_sset_count(struct net_device *netdev, int sset);
-int hinic3_force_port_disable(struct hinic3_nic_dev *nic_dev);
-
-int hinic3_force_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable);
-
int hinic3_maybe_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable);
#ifdef ETHTOOL_GLINKSETTINGS
@@ -386,5 +449,18 @@ bool hinic3_is_xdp_enable(struct hinic3_nic_dev *nic_dev);
int hinic3_xdp_max_mtu(struct hinic3_nic_dev *nic_dev);
#endif
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+int hinic3_udp_tunnel_set_port(struct net_device *netdev, unsigned int table,
+ unsigned int entry, struct udp_tunnel_info *ti);
+int hinic3_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table,
+ unsigned int entry,
+ struct udp_tunnel_info *ti);
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+int set_fecparam(void *hwdev, u8 fecparam);
+int get_fecparam(void *hwdev, u8 *advertised_fec, u8 *supported_fec);
+#endif
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c
index 57cf07c..87b5aa6 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c
@@ -21,11 +21,12 @@
#include "hinic3_nic_cfg.h"
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
{
- struct vf_data_storage *vf_info;
+ struct vf_data_storage *vf_info = NULL;
u16 func_id;
int err = 0;
@@ -38,7 +39,7 @@ static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
err = hinic3_set_mac(nic_io->hwdev, vf_info->drv_mac_addr,
vf_info->pf_vlan, func_id,
HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set VF %d MAC\n",
HW_VF_ID_TO_OS(vf_id));
return err;
@@ -51,7 +52,7 @@ static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
err = hinic3_cfg_vf_vlan(nic_io, HINIC3_CMD_OP_ADD,
vf_info->pf_vlan, vf_info->pf_qos,
vf_id);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to add VF %d VLAN_QOS\n",
HW_VF_ID_TO_OS(vf_id));
return err;
@@ -62,7 +63,7 @@ static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
err = hinic3_set_vf_tx_rate(nic_io->hwdev, vf_id,
vf_info->max_rate,
vf_info->min_rate);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set VF %d max rate %u, min rate %u\n",
HW_VF_ID_TO_OS(vf_id), vf_info->max_rate,
vf_info->min_rate);
@@ -84,7 +85,7 @@ static int register_vf_msg_handler(struct hinic3_nic_io *nic_io, u16 vf_id)
}
err = hinic3_init_vf_config(nic_io, vf_id);
- if (err)
+ if (err != 0)
return err;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true;
@@ -137,6 +138,9 @@ static int hinic3_register_vf_msg_handler(struct hinic3_nic_io *nic_io,
struct vf_data_storage *vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
int err;
+ if (!vf_info)
+ return -EINVAL;
+
if (register_vf->op_register) {
vf_info->support_extra_feature = register_vf->support_extra_feature;
err = register_vf_msg_handler(nic_io, vf_id);
@@ -145,7 +149,7 @@ static int hinic3_register_vf_msg_handler(struct hinic3_nic_io *nic_io,
vf_info->support_extra_feature = 0;
}
- if (err)
+ if (err != 0)
register_info->msg_head.status = EFAULT;
*out_size = sizeof(*register_info);
@@ -157,6 +161,8 @@ void hinic3_unregister_vf(struct hinic3_nic_io *nic_io, u16 vf_id)
{
struct vf_data_storage *vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+ if (!vf_info)
+ return;
unregister_vf_msg_handler(nic_io, vf_id);
vf_info->support_extra_feature = 0;
}
@@ -181,14 +187,21 @@ static int hinic3_get_vf_mac_msg_handler(struct hinic3_nic_io *nic_io, u16 vf,
void *buf_out, u16 *out_size)
{
struct vf_data_storage *vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf);
+ struct hinic3_port_mac_set *mac_in =
+ (struct hinic3_port_mac_set *)buf_in;
struct hinic3_port_mac_set *mac_info = buf_out;
int err;
+ if (!mac_info || !vf_info)
+ return -EINVAL;
+
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
+
if (HINIC3_SUPPORT_VF_MAC(nic_io->hwdev)) {
err = l2nic_msg_to_mgmt_sync(nic_io->hwdev, HINIC3_NIC_CMD_GET_MAC, buf_in,
in_size, buf_out, out_size);
- if (!err) {
+ if (err == 0) {
if (is_zero_ether_addr(mac_info->mac))
ether_addr_copy(mac_info->mac, vf_info->drv_mac_addr);
}
@@ -211,6 +224,11 @@ static int hinic3_set_vf_mac_msg_handler(struct hinic3_nic_io *nic_io, u16 vf,
struct hinic3_port_mac_set *mac_out = buf_out;
int err;
+ if (!vf_info)
+ return -EINVAL;
+
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
+
if (vf_info->use_specified_mac && !vf_info->trust &&
is_valid_ether_addr(mac_in->mac)) {
nic_warn(nic_io->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n",
@@ -247,6 +265,10 @@ static int hinic3_del_vf_mac_msg_handler(struct hinic3_nic_io *nic_io, u16 vf,
struct hinic3_port_mac_set *mac_out = buf_out;
int err;
+ if (!vf_info)
+ return -EINVAL;
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
+
if (vf_info->use_specified_mac && !vf_info->trust &&
is_valid_ether_addr(mac_in->mac)) {
nic_warn(nic_io->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n",
@@ -283,10 +305,13 @@ static int hinic3_update_vf_mac_msg_handler(struct hinic3_nic_io *nic_io,
struct hinic3_port_mac_update *mac_out = buf_out;
int err;
+ if (!vf_info)
+ return -EINVAL;
if (!is_valid_ether_addr(mac_in->new_mac)) {
nic_err(nic_io->dev_hdl, "Update VF MAC is invalid.\n");
return -EINVAL;
}
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
#ifndef __VMWARE__
if (vf_info->use_specified_mac && !vf_info->trust) {
@@ -301,7 +326,7 @@ static int hinic3_update_vf_mac_msg_handler(struct hinic3_nic_io *nic_io,
HW_VF_ID_TO_OS(vf),
HINIC_CFG_VF_MAC_CHANGED,
(void *)mac_in->new_mac);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to config VF %d MAC request, err: %d\n",
HW_VF_ID_TO_OS(vf), err);
return err;
@@ -359,10 +384,11 @@ static int _l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size,
u16 channel)
{
- u32 i, cmd_cnt = ARRAY_LEN(vf_cmd_handler);
+ int i, cmd_cnt = ARRAY_LEN(vf_cmd_handler);
bool cmd_to_pf = false;
- if (hinic3_func_type(hwdev) == TYPE_VF) {
+ if (hinic3_func_type(hwdev) == TYPE_VF &&
+ !hinic3_is_slave_host(hwdev)) {
for (i = 0; i < cmd_cnt; i++) {
if (cmd == vf_cmd_handler[i].cmd)
cmd_to_pf = true;
@@ -397,13 +423,15 @@ int hinic3_pf_mbox_handler(void *hwdev,
u16 vf_id, u16 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
- u32 index, cmd_size = ARRAY_LEN(vf_cmd_handler);
+ int index, cmd_size = ARRAY_LEN(vf_cmd_handler);
struct hinic3_nic_io *nic_io = NULL;
if (!hwdev)
return -EFAULT;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
for (index = 0; index < cmd_size; index++) {
if (cmd == vf_cmd_handler[index].cmd)
@@ -460,10 +488,14 @@ void hinic3_notify_dcb_state_event(struct hinic3_nic_io *nic_io,
static void dcb_state_event(void *hwdev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
- struct hinic3_cmd_vf_dcb_state *vf_dcb;
- struct hinic3_nic_io *nic_io;
+ struct hinic3_cmd_vf_dcb_state *vf_dcb = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
vf_dcb = buf_in;
if (!vf_dcb)
@@ -479,6 +511,10 @@ static void tx_pause_excp_event_handler(void *hwdev, void *buf_in, u16 in_size,
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
if (in_size != sizeof(*excp_info)) {
nic_err(nic_io->dev_hdl, "Invalid in_size: %u, should be %ld\n",
@@ -501,6 +537,10 @@ static void bond_active_event_handler(void *hwdev, void *buf_in, u16 in_size,
struct hinic3_event_info event_info = {0};
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
if (in_size != sizeof(*active_info)) {
nic_err(nic_io->dev_hdl, "Invalid in_size: %u, should be %ld\n",
@@ -515,6 +555,36 @@ static void bond_active_event_handler(void *hwdev, void *buf_in, u16 in_size,
hinic3_event_callback(nic_io->hwdev, &event_info);
}
+static void outband_vlan_cfg_event_handler(void *hwdev, void *buf_in,
+ u16 in_size, void *buf_out,
+ u16 *out_size)
+{
+ struct hinic3_outband_cfg_info *outband_cfg_info = buf_in;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct hinic3_event_info event_info = {0};
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
+
+ nic_info(nic_io->dev_hdl, "outband vlan cfg event received\n");
+
+ if (in_size != sizeof(*outband_cfg_info)) {
+ nic_err(nic_io->dev_hdl, "outband cfg info invalid in_size: %u, should be %lu\n",
+ in_size, sizeof(*outband_cfg_info));
+ return;
+ }
+
+ event_info.service = EVENT_SRV_NIC;
+ event_info.type = EVENT_NIC_OUTBAND_CFG;
+ memcpy((void *)event_info.event_data,
+ outband_cfg_info, sizeof(*outband_cfg_info));
+
+ hinic3_event_callback(nic_io->hwdev, &event_info);
+}
+
static const struct nic_event_handler nic_cmd_handler[] = {
{
.cmd = HINIC3_NIC_CMD_VF_COS,
@@ -529,6 +599,11 @@ static const struct nic_event_handler nic_cmd_handler[] = {
.cmd = HINIC3_NIC_CMD_BOND_ACTIVE_NOTICE,
.handler = bond_active_event_handler,
},
+
+ {
+ .cmd = HINIC3_NIC_CMD_OUTBAND_CFG_NOTICE,
+ .handler = outband_vlan_cfg_event_handler,
+ },
};
static int _event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
@@ -543,6 +618,8 @@ static int _event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
*out_size = 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
for (i = 0; i < size; i++) {
if (cmd == nic_cmd_handler[i].cmd) {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c
index a827f44..f3bb4c5 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c
@@ -16,9 +16,10 @@
#include "hinic3_nic_cfg.h"
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
-#include "hinic3_nic_cmd.h"
-#include "hinic3_nic_io.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_nic_cmdq.h"
+#include "hinic3_nic_io.h"
#define HINIC3_DEAULT_TX_CI_PENDING_LIMIT 1
#define HINIC3_DEAULT_TX_CI_COALESCING_TIME 1
@@ -35,7 +36,7 @@ MODULE_PARM_DESC(tx_coalescing_time, "TX CI coalescing parameter coalescing_time
static unsigned char rq_wqe_type = HINIC3_NORMAL_RQ_WQE;
module_param(rq_wqe_type, byte, 0444);
-MODULE_PARM_DESC(rq_wqe_type, "RQ WQE type 0-8Bytes, 1-16Bytes, 2-32Bytes (default=1)");
+MODULE_PARM_DESC(rq_wqe_type, "RQ WQE type 1-16Bytes, 2-32Bytes (default=2)");
/*lint +e806*/
static u32 tx_drop_thd_on = HINIC3_DEAULT_DROP_THD_ON;
@@ -46,7 +47,7 @@ static u32 tx_drop_thd_off = HINIC3_DEAULT_DROP_THD_OFF;
module_param(tx_drop_thd_off, uint, 0644);
MODULE_PARM_DESC(tx_drop_thd_off, "TX parameter drop_thd_off (default=0)");
/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */
-#define HINIC3_CI_Q_ADDR_SIZE (64)
+#define HINIC3_CI_Q_ADDR_SIZE (64U)
#define CI_TABLE_SIZE(num_qps, pg_sz) \
(ALIGN((num_qps) * HINIC3_CI_Q_ADDR_SIZE, pg_sz))
@@ -255,7 +256,7 @@ static int hinic3_create_sq(struct hinic3_nic_io *nic_io, struct hinic3_io_queue
err = hinic3_wq_create(nic_io->hwdev, &sq->wq, sq_depth,
(u16)BIT(HINIC3_SQ_WQEBB_SHIFT));
- if (err) {
+ if (err != 0) {
sdk_err(nic_io->dev_hdl, "Failed to create tx queue(%u) wq\n",
q_id);
return err;
@@ -291,13 +292,22 @@ static int hinic3_create_rq(struct hinic3_nic_io *nic_io, struct hinic3_io_queue
{
int err;
- rq->wqe_type = (u8)(hinic3_get_rq_wqe_type(nic_io->hwdev));
+ /* rq_wqe_type Only support type 1-16Bytes, 2-32Bytes */
+ if (rq_wqe_type != HINIC3_NORMAL_RQ_WQE &&
+ rq_wqe_type != HINIC3_EXTEND_RQ_WQE) {
+ sdk_warn(nic_io->dev_hdl, "Module Parameter rq_wqe_type value %d is out of range: [%d, %d].",
+ rq_wqe_type, HINIC3_NORMAL_RQ_WQE,
+ HINIC3_EXTEND_RQ_WQE);
+ rq_wqe_type = HINIC3_NORMAL_RQ_WQE;
+ }
+
+ rq->wqe_type = rq_wqe_type;
rq->q_id = q_id;
rq->msix_entry_idx = rq_msix_idx;
err = hinic3_wq_create(nic_io->hwdev, &rq->wq, rq_depth,
(u16)BIT(HINIC3_RQ_WQEBB_SHIFT + rq->wqe_type));
- if (err) {
+ if (err != 0) {
sdk_err(nic_io->dev_hdl, "Failed to create rx queue(%u) wq\n",
q_id);
return err;
@@ -318,14 +328,14 @@ static int create_qp(struct hinic3_nic_io *nic_io, struct hinic3_io_queue *sq,
int err;
err = hinic3_create_sq(nic_io, sq, q_id, sq_depth, qp_msix_idx);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to create sq, qid: %u\n",
q_id);
return err;
}
err = hinic3_create_rq(nic_io, rq, q_id, rq_depth, qp_msix_idx);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to create rq, qid: %u\n",
q_id);
goto create_rq_err;
@@ -364,14 +374,14 @@ int hinic3_init_nicio_res(void *hwdev)
nic_io->max_qps = hinic3_func_max_qnum(hwdev);
err = hinic3_alloc_db_addr(hwdev, &db_base, NULL);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to allocate doorbell for sqs\n");
goto alloc_sq_db_fail;
}
nic_io->sqs_db_addr = (u8 *)db_base;
err = hinic3_alloc_db_addr(hwdev, &db_base, NULL);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to allocate doorbell for rqs\n");
goto alloc_rq_db_fail;
}
@@ -474,7 +484,7 @@ int hinic3_alloc_qps(void *hwdev, struct irq_info *qps_msix_arry,
for (q_id = 0; q_id < num_qps; q_id++) {
err = create_qp(nic_io, &sqs[q_id], &rqs[q_id], q_id, qp_params->sq_depth,
qp_params->rq_depth, qps_msix_arry[q_id].msix_entry_idx);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to allocate qp %u, err: %d\n", q_id, err);
goto create_qp_err;
}
@@ -599,14 +609,14 @@ int hinic3_create_qps(void *hwdev, u16 num_qp, u32 sq_depth, u32 rq_depth,
}
err = hinic3_init_nicio_res(hwdev);
- if (err)
+ if (err != 0)
return err;
qp_params.num_qps = num_qp;
qp_params.sq_depth = sq_depth;
qp_params.rq_depth = rq_depth;
err = hinic3_alloc_qps(hwdev, qps_msix_arry, &qp_params);
- if (err) {
+ if (err != 0) {
hinic3_deinit_nicio_res(hwdev);
nic_err(nic_io->dev_hdl,
"Failed to allocate qps, err: %d\n", err);
@@ -906,11 +916,11 @@ static int init_qp_ctxts(struct hinic3_nic_io *nic_io)
int err;
err = init_sq_ctxts(nic_io);
- if (err)
+ if (err != 0)
return err;
err = init_rq_ctxts(nic_io);
- if (err)
+ if (err != 0)
return err;
return 0;
@@ -1026,14 +1036,14 @@ int hinic3_init_qp_ctxts(void *hwdev)
return -EFAULT;
err = init_qp_ctxts(nic_io);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to init QP ctxts\n");
return err;
}
/* clean LRO/TSO context space */
err = clean_qp_offload_ctxt(nic_io);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to clean qp offload ctxts\n");
return err;
}
@@ -1042,13 +1052,13 @@ int hinic3_init_qp_ctxts(void *hwdev)
err = hinic3_set_root_ctxt(hwdev, rq_depth, nic_io->sq[0].wq.q_depth,
nic_io->rx_buff_len, HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set root context\n");
return err;
}
err = init_sq_ci_ctxts(nic_io);
- if (err)
+ if (err != 0)
goto clean_root_ctxt;
if (HINIC3_SUPPORT_RX_COMPACT_CQE(hwdev)) {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
index 37f923d..c5e02ad 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
@@ -317,7 +317,7 @@ static inline void hinic3_write_db(struct hinic3_io_queue *queue, int cos,
wmb(); /* Write all before the doorbell */
- writeq(*((u64 *)&db), DB_ADDR(queue, pi));
+ writeq(*((u64 *)(u8 *)&db), DB_ADDR(queue, pi));
}
struct hinic3_dyna_qp_params {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c
index 78d943d..9ea93a0 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c
@@ -32,7 +32,7 @@ struct hinic3_prof_adapter nic_prof_adap_objs[] = {
void hinic3_init_nic_prof_adapter(struct hinic3_nic_dev *nic_dev)
{
- u16 num_adap = ARRAY_SIZE(nic_prof_adap_objs);
+ int num_adap = ARRAY_LEN(nic_prof_adap_objs);
nic_dev->prof_adap = hinic3_prof_init(nic_dev, nic_prof_adap_objs, num_adap,
(void *)&nic_dev->prof_attr);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c
index 6302fb8..dc4bb9e 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c
@@ -430,7 +430,8 @@ hinic3_dynamic_lookup_tcam_filter(struct hinic3_nic_dev *nic_dev,
list_for_each_entry(tmp,
&tcam_info->tcam_dynamic_info.tcam_dynamic_list,
block_list)
- if (tmp->dynamic_index_cnt < HINIC3_TCAM_DYNAMIC_BLOCK_SIZE)
+ if (tmp->dynamic_index_cnt < HINIC3_TCAM_DYNAMIC_BLOCK_SIZE ||
+ !tmp)
break;
if (!tmp || tmp->dynamic_index_cnt >= HINIC3_TCAM_DYNAMIC_BLOCK_SIZE) {
@@ -512,7 +513,7 @@ static int hinic3_add_tcam_filter(struct hinic3_nic_dev *nic_dev,
}
nicif_info(nic_dev, drv, nic_dev->netdev,
- "Add fdir tcam rule, function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, queue: %d, tcam_rule_nums: %d succeed\n",
+ "Add fdir tcam rule, function_id: 0x%x, tcam_block_id: %u, local_index: %u, global_index: %u, queue: %u, tcam_rule_nums: %u succeed\n",
hinic3_global_func_id(nic_dev->hwdev),
tcam_filter->dynamic_block_id, index, fdir_tcam_rule->index,
fdir_tcam_rule->data.qid, tcam_info->tcam_rule_nums + 1);
@@ -579,7 +580,7 @@ static int hinic3_del_tcam_filter(struct hinic3_nic_dev *nic_dev,
}
nicif_info(nic_dev, drv, nic_dev->netdev,
- "Del fdir_tcam_dynamic_rule function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, local_rules_nums: %d, global_rule_nums: %d succeed\n",
+ "Del fdir_tcam_dynamic_rule function_id: 0x%x, tcam_block_id: %u, local_index: %u, global_index: %u, local_rules_nums: %u, global_rule_nums: %u succeed\n",
hinic3_global_func_id(nic_dev->hwdev), dynamic_block_id,
tcam_filter->index, index, tmp->dynamic_index_cnt - 1,
tcam_info->tcam_rule_nums - 1);
@@ -605,7 +606,7 @@ static inline struct hinic3_tcam_filter *
hinic3_tcam_filter_lookup(const struct list_head *filter_list,
struct tag_tcam_key *key)
{
- struct hinic3_tcam_filter *iter;
+ struct hinic3_tcam_filter *iter = NULL;
list_for_each_entry(iter, filter_list, tcam_filter_list) {
if (memcmp(key, &iter->tcam_key,
@@ -630,7 +631,7 @@ static int hinic3_remove_one_rule(struct hinic3_nic_dev *nic_dev,
struct hinic3_ethtool_rx_flow_rule *eth_rule)
{
struct hinic3_tcam_info *tcam_info = &nic_dev->tcam;
- struct hinic3_tcam_filter *tcam_filter;
+ struct hinic3_tcam_filter *tcam_filter = NULL;
struct nic_tcam_cfg_rule fdir_tcam_rule;
struct tag_tcam_key tcam_key;
int err;
@@ -751,7 +752,7 @@ static int validate_flow(struct hinic3_nic_dev *nic_dev,
{
if (fs->location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) {
nicif_err(nic_dev, drv, nic_dev->netdev, "loc exceed limit[0,%lu]\n",
- MAX_NUM_OF_ETHTOOL_NTUPLE_RULES);
+ MAX_NUM_OF_ETHTOOL_NTUPLE_RULES - 1);
return -EINVAL;
}
@@ -872,7 +873,7 @@ int hinic3_ethtool_get_flow(const struct hinic3_nic_dev *nic_dev,
int hinic3_ethtool_get_all_flows(const struct hinic3_nic_dev *nic_dev,
struct ethtool_rxnfc *info, u32 *rule_locs)
{
- int idx = 0;
+ u32 idx = 0;
struct hinic3_ethtool_rx_flow_rule *eth_rule = NULL;
if (!HINIC3_SUPPORT_FDIR(nic_dev->hwdev)) {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h b/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h
index a93f3b6..9202218 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h
@@ -38,13 +38,12 @@ struct hinic3_prof_adapter {
#define LLT_STATIC_DEF_SAVED
#endif
-/*lint -save -e661 */
static inline struct hinic3_prof_adapter *
hinic3_prof_init(void *device, struct hinic3_prof_adapter *adap_objs, int num_adap,
void **prof_attr)
{
struct hinic3_prof_adapter *prof_obj = NULL;
- u16 i;
+ int i;
for (i = 0; i < num_adap; i++) {
prof_obj = &adap_objs[i];
@@ -68,7 +67,6 @@ static inline void hinic3_prof_deinit(struct hinic3_prof_adapter *prof_obj, void
prof_obj->deinit(prof_attr);
}
-/*lint -restore*/
/* module-level interface */
#ifdef CONFIG_MODULE_PROF
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
index e4705c2..dcd79ee 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/dcbnl.h>
+#include <linux/init.h>
#include "ossl_knl.h"
#include "hinic3_crm.h"
@@ -23,7 +24,6 @@
#include "hinic3_hw.h"
#include "hinic3_rss.h"
-/*lint -e806*/
static u16 num_qps;
module_param(num_qps, ushort, 0444);
MODULE_PARM_DESC(num_qps, "Number of Queue Pairs (default=0)");
@@ -104,88 +104,83 @@ static int hinic3_get_rq2iq_map(struct hinic3_nic_dev *nic_dev,
return 0;
}
-static void hinic3_fillout_indir_tbl(struct hinic3_nic_dev *nic_dev, u8 num_cos, u32 *indir)
+static void hinic3_fillout_indir_tbl(struct hinic3_nic_dev *nic_dev,
+ u8 group_num, u32 *indir)
{
- u16 k, group_size, start_qid = 0, qp_num = 0;
- int i = 0;
- u8 j, cur_cos = 0, default_cos;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+ u16 k, group_size, start_qid = 0, cur_cos_qnum = 0;
+ u32 i = 0;
+ u8 j, cur_cos = 0, group = 0;
u8 valid_cos_map = hinic3_get_dev_valid_cos_map(nic_dev);
- if (num_cos == 0) {
+ if (group_num == 0) {
for (i = 0; i < NIC_RSS_INDIR_SIZE; i++)
indir[i] = i % nic_dev->q_params.num_qps;
} else {
- group_size = NIC_RSS_INDIR_SIZE / num_cos;
-
- for (j = 0; j < num_cos; j++) {
- while (cur_cos < NIC_DCB_COS_MAX &&
- nic_dev->hw_dcb_cfg.cos_qp_num[cur_cos] == 0)
- cur_cos++;
-
- if (cur_cos >= NIC_DCB_COS_MAX) {
- if (BIT(nic_dev->hw_dcb_cfg.default_cos) & valid_cos_map)
- default_cos = nic_dev->hw_dcb_cfg.default_cos;
- else
- default_cos = (u8)fls(valid_cos_map) - 1;
+ group_size = NIC_RSS_INDIR_SIZE / group_num;
+
+ for (group = 0; group < group_num; group++) {
+ cur_cos = dcb->hw_dcb_cfg.default_cos;
+ for (j = 0; j < NIC_DCB_COS_MAX; j++) {
+ if ((BIT(j) & valid_cos_map) != 0) {
+ cur_cos = j;
+ valid_cos_map -= (u8)BIT(j);
+ break;
+ }
+ }
- start_qid = nic_dev->hw_dcb_cfg.cos_qp_offset[default_cos];
- qp_num = nic_dev->hw_dcb_cfg.cos_qp_num[default_cos];
+ cur_cos_qnum = dcb->hw_dcb_cfg.cos_qp_num[cur_cos];
+ if (cur_cos_qnum > 0) {
+ start_qid =
+ dcb->hw_dcb_cfg.cos_qp_offset[cur_cos];
} else {
- start_qid = nic_dev->hw_dcb_cfg.cos_qp_offset[cur_cos];
- qp_num = nic_dev->hw_dcb_cfg.cos_qp_num[cur_cos];
+ start_qid = cur_cos % nic_dev->q_params.num_qps;
+ /* Ensure that the offset of start_id is 0. */
+ cur_cos_qnum = 1;
}
for (k = 0; k < group_size; k++)
- indir[i++] = start_qid + k % qp_num;
-
- cur_cos++;
+ indir[i++] = start_qid + k % cur_cos_qnum;
}
}
}
-/*lint -e528*/
int hinic3_rss_init(struct hinic3_nic_dev *nic_dev, u8 *rq2iq_map, u32 map_size, u8 dcb_en)
{
struct net_device *netdev = nic_dev->netdev;
- u8 i, cos_num;
- u8 cos_map[NIC_DCB_UP_MAX] = {0};
- u8 cfg_map[NIC_DCB_UP_MAX] = {0};
+ u8 i, group_num, cos_bitmap, group = 0;
+ u8 cos_group[NIC_DCB_UP_MAX] = {0};
int err;
- if (dcb_en) {
- cos_num = hinic3_get_dev_user_cos_num(nic_dev);
-
- if (nic_dev->hw_dcb_cfg.trust == 0) {
- memcpy(cfg_map, nic_dev->hw_dcb_cfg.pcp2cos, sizeof(cfg_map));
- } else if (nic_dev->hw_dcb_cfg.trust == 1) {
- for (i = 0; i < NIC_DCB_UP_MAX; i++)
- cfg_map[i] = nic_dev->hw_dcb_cfg.dscp2cos[i * NIC_DCB_DSCP_NUM];
- }
-#define COS_CHANGE_OFFSET 4
- for (i = 0; i < COS_CHANGE_OFFSET; i++)
- cos_map[COS_CHANGE_OFFSET + i] = cfg_map[i];
+ if (dcb_en != 0) {
+ group_num = (u8)roundup_pow_of_two(hinic3_get_dev_user_cos_num(nic_dev));
- for (i = 0; i < COS_CHANGE_OFFSET; i++)
- cos_map[i] = cfg_map[NIC_DCB_UP_MAX - (i + 1)];
+ cos_bitmap = hinic3_get_dev_valid_cos_map(nic_dev);
- while (cos_num & (cos_num - 1))
- cos_num++;
+ for (i = 0; i < NIC_DCB_UP_MAX; i++) {
+ if ((BIT(i) & cos_bitmap) != 0)
+ cos_group[NIC_DCB_UP_MAX - i - 1] = group++;
+ else
+ cos_group[NIC_DCB_UP_MAX - i - 1] =
+ group_num - 1;
+ }
} else {
- cos_num = 0;
+ group_num = 0;
}
- err = hinic3_set_hw_rss_parameters(netdev, 1, cos_num, cos_map, dcb_en);
+ err = hinic3_set_hw_rss_parameters(netdev, 1, group_num,
+ cos_group, dcb_en);
if (err)
return err;
- err = hinic3_get_rq2iq_map(nic_dev, nic_dev->q_params.num_qps, cos_num, cos_map,
- NIC_DCB_UP_MAX, nic_dev->rss_indir, rq2iq_map, map_size);
+ err = hinic3_get_rq2iq_map(nic_dev, nic_dev->q_params.num_qps,
+ group_num, cos_group, NIC_DCB_UP_MAX,
+ nic_dev->rss_indir, rq2iq_map, map_size);
if (err)
nicif_err(nic_dev, drv, netdev, "Failed to get rq map\n");
return err;
}
-/*lint -e528*/
void hinic3_rss_deinit(struct hinic3_nic_dev *nic_dev)
{
u8 cos_map[NIC_DCB_UP_MAX] = {0};
@@ -246,11 +241,29 @@ discard_user_rss_indir:
hinic3_set_default_rss_indir(netdev);
}
+#ifdef HAVE_HOT_REPLACE_FUNC
+bool partition_slave_doing_hotupgrade(void)
+{
+ return get_partition_role() && partition_doing_hotupgrade();
+}
+#endif
+
static void decide_num_qps(struct hinic3_nic_dev *nic_dev)
{
u16 tmp_num_qps = nic_dev->max_qps;
u16 num_cpus = 0;
+ u16 max_num_cpus;
int i, node;
+ int is_in_kexec = vram_get_kexec_flag();
+
+ if (is_in_kexec != 0) {
+ nic_dev->q_params.num_qps = nic_dev->nic_vram->vram_num_qps;
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "Os hotreplace use vram to init num qps 1:%u 2:%u\n",
+ nic_dev->q_params.num_qps,
+ nic_dev->nic_vram->vram_num_qps);
+ return;
+ }
if (nic_dev->nic_cap.default_num_queues != 0 &&
nic_dev->nic_cap.default_num_queues < nic_dev->max_qps)
@@ -258,16 +271,29 @@ static void decide_num_qps(struct hinic3_nic_dev *nic_dev)
MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, tmp_num_qps);
- for (i = 0; i < (int)num_online_cpus(); i++) {
+#ifdef HAVE_HOT_REPLACE_FUNC
+ if (partition_slave_doing_hotupgrade())
+ max_num_cpus = (u16)num_present_cpus();
+ else
+ max_num_cpus = (u16)num_online_cpus();
+#else
+ max_num_cpus = (u16)num_online_cpus();
+#endif
+
+ for (i = 0; i < max_num_cpus; i++) {
node = (int)cpu_to_node(i);
if (node == dev_to_node(&nic_dev->pdev->dev))
num_cpus++;
}
if (!num_cpus)
- num_cpus = (u16)num_online_cpus();
+ num_cpus = max_num_cpus;
nic_dev->q_params.num_qps = (u16)min_t(u16, tmp_num_qps, num_cpus);
+ nic_dev->nic_vram->vram_num_qps = nic_dev->q_params.num_qps;
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "init num qps 1:%u 2:%u\n",
+ nic_dev->q_params.num_qps, nic_dev->nic_vram->vram_num_qps);
}
static void copy_value_to_rss_hkey(struct hinic3_nic_dev *nic_dev,
@@ -322,7 +348,6 @@ static int alloc_rss_resource(struct hinic3_nic_dev *nic_dev)
return 0;
}
-/*lint -e528*/
void hinic3_try_to_enable_rss(struct hinic3_nic_dev *nic_dev)
{
u8 cos_map[NIC_DCB_UP_MAX] = {0};
@@ -361,6 +386,7 @@ void hinic3_try_to_enable_rss(struct hinic3_nic_dev *nic_dev)
set_q_params:
clear_bit(HINIC3_RSS_ENABLE, &nic_dev->flags);
nic_dev->q_params.num_qps = nic_dev->max_qps;
+ nic_dev->nic_vram->vram_num_qps = nic_dev->max_qps;
}
static int hinic3_config_rss_hw_resource(struct hinic3_nic_dev *nic_dev,
@@ -754,6 +780,7 @@ int hinic3_set_channels(struct net_device *netdev,
nic_dev->q_params.num_qps = (u16)count;
}
+ nic_dev->nic_vram->vram_num_qps = nic_dev->q_params.num_qps;
return 0;
}
@@ -814,7 +841,7 @@ int hinic3_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
int err = 0;
if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Rss is disable\n");
+ netdev_warn_once(nic_dev->netdev, "Rss is disable\n");
return -EOPNOTSUPP;
}
@@ -921,7 +948,7 @@ int hinic3_get_rxfh_indir(struct net_device *netdev, u32 *indir)
indir = indir1->ring_index;
#endif
if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Rss is disable\n");
+ netdev_warn_once(nic_dev->netdev, "Rss is disable\n");
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c
index 071418d..4f4b18c 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c
@@ -15,14 +15,15 @@
#include "ossl_knl.h"
#include "hinic3_crm.h"
#include "hinic3_nic_cfg.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_hw.h"
#include "hinic3_nic.h"
#include "hinic3_nic_cmdq.h"
#include "hinic3_common.h"
static int hinic3_rss_cfg_hash_key(struct hinic3_nic_io *nic_io, u8 opcode,
- u8 *key)
+ u8 *key, u16 key_size)
{
struct hinic3_cmd_rss_hash_key hash_key;
u16 out_size = sizeof(hash_key);
@@ -33,7 +34,7 @@ static int hinic3_rss_cfg_hash_key(struct hinic3_nic_io *nic_io, u8 opcode,
hash_key.opcode = opcode;
if (opcode == HINIC3_CMD_OP_SET)
- memcpy(hash_key.key, key, NIC_RSS_KEY_SIZE);
+ memcpy(hash_key.key, key, key_size);
err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
HINIC3_NIC_CMD_CFG_RSS_HASH_KEY,
@@ -47,7 +48,7 @@ static int hinic3_rss_cfg_hash_key(struct hinic3_nic_io *nic_io, u8 opcode,
}
if (opcode == HINIC3_CMD_OP_GET)
- memcpy(key, hash_key.key, NIC_RSS_KEY_SIZE);
+ memcpy(key, hash_key.key, key_size);
return 0;
}
@@ -61,8 +62,12 @@ int hinic3_rss_set_hash_key(void *hwdev, const u8 *key)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memcpy(hash_key, key, NIC_RSS_KEY_SIZE);
- return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_SET, hash_key);
+ return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_SET,
+ hash_key, NIC_RSS_KEY_SIZE);
}
int hinic3_rss_get_hash_key(void *hwdev, u8 *key)
@@ -73,7 +78,11 @@ int hinic3_rss_get_hash_key(void *hwdev, u8 *key)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_GET, key);
+ if (!nic_io)
+ return -EINVAL;
+
+ return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_GET,
+ key, NIC_RSS_KEY_SIZE);
}
int hinic3_rss_get_indir_tbl(void *hwdev, u32 *indir_table)
@@ -89,6 +98,7 @@ int hinic3_rss_get_indir_tbl(void *hwdev, u32 *indir_table)
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
if (nic_io == NULL)
return -EINVAL;
+
cmd_buf = hinic3_alloc_cmd_buf(hwdev);
if (cmd_buf == NULL) {
nic_err(nic_io->dev_hdl, "Failed to allocate cmd_buf.\n");
@@ -159,6 +169,8 @@ static int hinic3_cmdq_set_rss_type(void *hwdev, struct nic_rss_type rss_type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
cmd_buf = hinic3_alloc_cmd_buf(hwdev);
if (!cmd_buf) {
@@ -210,6 +222,9 @@ static int hinic3_mgmt_set_rss_type(void *hwdev, struct nic_rss_type rss_type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memset(&ctx_tbl, 0, sizeof(ctx_tbl));
ctx_tbl.func_id = hinic3_global_func_id(hwdev);
ctx |= HINIC3_RSS_TYPE_SET(1, VALID) |
@@ -259,6 +274,8 @@ int hinic3_get_rss_type(void *hwdev, struct nic_rss_type *rss_type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&ctx_tbl, 0, sizeof(struct hinic3_rss_context_table));
ctx_tbl.func_id = hinic3_global_func_id(hwdev);
@@ -292,6 +309,9 @@ static int hinic3_rss_cfg_hash_engine(struct hinic3_nic_io *nic_io, u8 opcode,
u16 out_size = sizeof(hash_type);
int err;
+ if (!nic_io)
+ return -EINVAL;
+
memset(&hash_type, 0, sizeof(struct hinic3_cmd_rss_engine_type));
hash_type.func_id = hinic3_global_func_id(nic_io->hwdev);
@@ -325,6 +345,9 @@ int hinic3_rss_set_hash_engine(void *hwdev, u8 type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
return hinic3_rss_cfg_hash_engine(nic_io, HINIC3_CMD_OP_SET, &type);
}
@@ -336,6 +359,9 @@ int hinic3_rss_get_hash_engine(void *hwdev, u8 *type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
return hinic3_rss_cfg_hash_engine(nic_io, HINIC3_CMD_OP_GET, type);
}
@@ -351,6 +377,9 @@ int hinic3_rss_cfg(void *hwdev, u8 rss_en, u8 cos_num, u8 *prio_tc, u16 num_qps)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memset(&rss_cfg, 0, sizeof(struct hinic3_cmd_rss_config));
rss_cfg.func_id = hinic3_global_func_id(hwdev);
rss_cfg.rss_en = rss_en;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
index f8a866d..936258c 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
@@ -21,6 +21,7 @@
#include <linux/ipv6.h>
#include <linux/module.h>
#include <linux/compiler.h>
+#include <linux/filter.h>
#include "ossl_knl.h"
#include "hinic3_crm.h"
@@ -63,19 +64,31 @@ static bool rx_alloc_mapped_page(struct hinic3_nic_dev *nic_dev,
struct pci_dev *pdev = nic_dev->pdev;
struct page *page = rx_info->page;
dma_addr_t dma = rx_info->buf_dma_addr;
+ u32 page_offset = 0;
if (likely(dma))
return true;
/* alloc new page for storage */
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ page = page_pool_alloc_frag(rx_info->page_pool, &page_offset,
+ nic_dev->rx_buff_len,
+ GFP_ATOMIC | __GFP_COLD | __GFP_COMP);
+ if (unlikely(!page))
+ return false;
+ dma = page_pool_get_dma_addr(page);
+ goto set_rx_info;
+ }
+#endif
page = alloc_pages_node(NUMA_NO_NODE, GFP_ATOMIC | __GFP_COLD |
__GFP_COMP, nic_dev->page_order);
if (unlikely(!page))
return false;
/* map page for use */
- dma = dma_map_page(&pdev->dev, page, 0, nic_dev->dma_rx_buff_size,
- DMA_FROM_DEVICE);
+ dma = dma_map_page(&pdev->dev, page, page_offset,
+ nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE);
/* if mapping failed free memory back to system since
* there isn't much point in holding memory we can't use
*/
@@ -83,10 +96,12 @@ static bool rx_alloc_mapped_page(struct hinic3_nic_dev *nic_dev,
__free_pages(page, nic_dev->page_order);
return false;
}
+ goto set_rx_info;
+set_rx_info:
rx_info->page = page;
rx_info->buf_dma_addr = dma;
- rx_info->page_offset = 0;
+ rx_info->page_offset = page_offset;
return true;
}
@@ -108,7 +123,7 @@ static u32 hinic3_rx_fill_wqe(struct hinic3_rxq *rxq)
/* unit of cqe length is 16B */
hinic3_set_sge(&rq_wqe->extend_wqe.cqe_sect.sge,
rx_info->cqe_dma,
- (sizeof(struct hinic3_rq_cqe) >>
+ (HINIC3_CQE_LEN >>
HINIC3_CQE_SIZE_SHIFT));
/* use fixed len */
rq_wqe->extend_wqe.buf_desc.sge.len =
@@ -169,7 +184,7 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
if (likely(i)) {
hinic3_write_db(rxq->rq,
- rxq->q_id & 3,
+ rxq->q_id & (NIC_RX_DB_COS_MAX - 1),
RQ_CFLAG_DP,
(u16)((u32)rxq->next_to_update <<
rxq->rq->wqe_type));
@@ -206,6 +221,18 @@ static void hinic3_rx_free_buffers(struct hinic3_nic_dev *nic_dev, u32 q_depth,
for (i = 0; i < q_depth; i++) {
rx_info = &rx_info_arr[i];
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ if (rx_info->page) {
+ page_pool_put_full_page(rx_info->page_pool,
+ rx_info->page, false);
+ rx_info->buf_dma_addr = 0;
+ rx_info->page = NULL;
+ }
+ continue;
+ }
+#endif
+
if (rx_info->buf_dma_addr) {
dma_unmap_page(&nic_dev->pdev->dev,
rx_info->buf_dma_addr,
@@ -265,8 +292,15 @@ static bool hinic3_add_rx_frag(struct hinic3_rxq *rxq,
DMA_FROM_DEVICE);
if (size <= HINIC3_RX_HDR_SIZE && !skb_is_nonlinear(skb)) {
- memcpy(__skb_put(skb, size), va + offset,
- ALIGN(size, sizeof(long))); /*lint !e666*/
+ __skb_put_data(skb, va + offset, size);
+
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ page_pool_put_full_page(rx_info->page_pool,
+ page, false);
+ return false;
+ }
+#endif
/* page is not reserved, we can reuse buffer as-is */
if (likely(page_to_nid(page) == numa_node_id()))
@@ -274,25 +308,38 @@ static bool hinic3_add_rx_frag(struct hinic3_rxq *rxq,
/* this page cannot be reused so discard it */
put_page(page);
- return false;
+ goto discard_page;
}
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
- (int)(rx_info->page_offset + offset), (int)size, rxq->buf_len);
+ (int)(rx_info->page_offset + offset), (int)size,
+ rxq->buf_len);
+
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ skb_mark_for_recycle(skb);
+ return false;
+ }
+#endif
/* avoid re-using remote pages */
if (unlikely(page_to_nid(page) != numa_node_id()))
- return false;
+ goto discard_page;
/* if we are only owner of page we can reuse it */
if (unlikely(page_count(page) != 1))
- return false;
+ goto discard_page;
/* flip page offset to other buffer */
rx_info->page_offset ^= rxq->buf_len;
get_page(page);
return true;
+
+discard_page:
+ dma_unmap_page(rxq->dev, rx_info->buf_dma_addr,
+ rxq->dma_rx_buff_size, DMA_FROM_DEVICE);
+ return false;
}
static void packaging_skb(struct hinic3_rxq *rxq, struct sk_buff *head_skb,
@@ -338,10 +385,6 @@ static void packaging_skb(struct hinic3_rxq *rxq, struct sk_buff *head_skb,
if (likely(hinic3_add_rx_frag(rxq, rx_info, skb, frag_size, tmp_pkt_offset))) {
hinic3_reuse_rx_page(rxq, rx_info);
- } else {
- /* we are not reusing the buffer so unmap it */
- dma_unmap_page(rxq->dev, rx_info->buf_dma_addr,
- rxq->dma_rx_buff_size, DMA_FROM_DEVICE);
}
/* clear contents of buffer_info */
rx_info->buf_dma_addr = 0;
@@ -486,9 +529,8 @@ static unsigned int hinic3_eth_get_headlen(unsigned char *data, unsigned int max
protocol = hdr.eth->h_proto;
/* L2 header */
- /*lint -save -e778*/
if (protocol == htons(ETH_P_8021_AD) ||
- protocol == htons(ETH_P_8021_Q)) { /*lint -restore*/
+ protocol == htons(ETH_P_8021_Q)) {
if (unlikely(max_len < ETH_HLEN + VLAN_HLEN))
return max_len;
@@ -500,9 +542,8 @@ static unsigned int hinic3_eth_get_headlen(unsigned char *data, unsigned int max
}
/* L3 header */
- /*lint -save -e778*/
switch (protocol) {
- case htons(ETH_P_IP): /*lint -restore*/
+ case htons(ETH_P_IP):
if ((int)(hdr.data - data) >
(int)(max_len - sizeof(struct iphdr)))
return max_len;
@@ -713,7 +754,10 @@ static inline void hinic3_lro_set_gso_params(struct sk_buff *skb, u16 num_lro)
}
#ifdef HAVE_XDP_SUPPORT
-enum hinic3_xdp_pkt {
+enum hinic3_xdp_status {
+ // bpf_prog status
+ HINIC3_XDP_PROG_EMPTY,
+ // pkt action
HINIC3_XDP_PKT_PASS,
HINIC3_XDP_PKT_DROP,
};
@@ -724,9 +768,15 @@ static void update_drop_rx_info(struct hinic3_rxq *rxq, u16 weqbb_num)
while (weqbb_num) {
rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask];
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool)
+ goto discard_direct;
+#endif
if (likely(page_to_nid(rx_info->page) == numa_node_id()))
hinic3_reuse_rx_page(rxq, rx_info);
+ goto discard_direct;
+discard_direct:
rx_info->buf_dma_addr = 0;
rx_info->page = NULL;
rxq->cons_idx++;
@@ -736,11 +786,11 @@ static void update_drop_rx_info(struct hinic3_rxq *rxq, u16 weqbb_num)
}
}
-int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len)
+int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len, struct xdp_buff *xdp)
{
struct bpf_prog *xdp_prog = NULL;
struct hinic3_rx_info *rx_info = NULL;
- struct xdp_buff xdp;
+ struct net_device *netdev = rxq->netdev;
int result = HINIC3_XDP_PKT_PASS;
u16 weqbb_num = 1; /* xdp can only use one rx_buff */
u8 *va = NULL;
@@ -748,13 +798,14 @@ int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len)
rcu_read_lock();
xdp_prog = READ_ONCE(rxq->xdp_prog);
- if (!xdp_prog)
+ if (!xdp_prog) {
+ result = HINIC3_XDP_PROG_EMPTY;
goto unlock_rcu;
+ }
if (unlikely(pkt_len > rxq->buf_len)) {
RXQ_STATS_INC(rxq, xdp_large_pkt);
- weqbb_num = (u16)(pkt_len >> rxq->rx_buff_shift) +
- ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0);
+ weqbb_num = HINIC3_GET_SGE_NUM(pkt_len, rxq);
result = HINIC3_XDP_PKT_DROP;
goto xdp_out;
}
@@ -765,26 +816,27 @@ int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len)
dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr,
rx_info->page_offset,
rxq->buf_len, DMA_FROM_DEVICE);
- xdp.data = va;
- xdp.data_hard_start = xdp.data;
- xdp.data_end = xdp.data + pkt_len;
+ xdp->data = va;
+ xdp->data_hard_start = xdp->data;
+ xdp->data_end = xdp->data + pkt_len;
#ifdef HAVE_XDP_FRAME_SZ
- xdp.frame_sz = rxq->buf_len;
+ xdp->frame_sz = rxq->buf_len;
#endif
#ifdef HAVE_XDP_DATA_META
- xdp_set_data_meta_invalid(&xdp);
+ xdp_set_data_meta_invalid(xdp);
#endif
- prefetchw(xdp.data_hard_start);
- act = bpf_prog_run_xdp(xdp_prog, &xdp);
+ prefetchw(xdp->data_hard_start);
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
switch (act) {
case XDP_PASS:
+ result = HINIC3_XDP_PKT_PASS;
break;
case XDP_DROP:
result = HINIC3_XDP_PKT_DROP;
break;
default:
result = HINIC3_XDP_PKT_DROP;
- bpf_warn_invalid_xdp_action(rxq->netdev, xdp_prog, act);
+ bpf_warn_invalid_xdp_action(netdev, xdp_prog, act);
}
xdp_out:
@@ -798,9 +850,86 @@ unlock_rcu:
return result;
}
+
+static bool hinic3_add_rx_frag_with_xdp(struct hinic3_rxq *rxq, u32 pkt_len,
+ struct hinic3_rx_info *rx_info,
+ struct sk_buff *skb, struct xdp_buff *xdp)
+{
+ struct page *page = rx_info->page;
+
+ if (pkt_len <= HINIC3_RX_HDR_SIZE) {
+ __skb_put_data(skb, xdp->data, pkt_len);
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ page_pool_put_full_page(rx_info->page_pool, page, false);
+ return false;
+ }
+#endif
+ if (likely(page_to_nid(page) == numa_node_id()))
+ return true;
+
+ put_page(page);
+ goto umap_page;
+ }
+
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+ (int)(rx_info->page_offset +
+ (xdp->data - xdp->data_hard_start)),
+ (int)pkt_len, rxq->buf_len);
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ skb_mark_for_recycle(skb);
+ return false;
+ }
+#endif
+ if (unlikely(page_to_nid(page) != numa_node_id()))
+ goto umap_page;
+ if (unlikely(page_count(page) != 1))
+ goto umap_page;
+
+ rx_info->page_offset ^= rxq->buf_len;
+ get_page(page);
+
+ return true;
+umap_page:
+ dma_unmap_page(rxq->dev, rx_info->buf_dma_addr,
+ rxq->dma_rx_buff_size, DMA_FROM_DEVICE);
+ return false;
+}
+
+static struct sk_buff *hinic3_fetch_rx_buffer_xdp(struct hinic3_rxq *rxq,
+ u32 pkt_len,
+ struct xdp_buff *xdp)
+{
+ struct sk_buff *skb;
+ struct hinic3_rx_info *rx_info;
+ u32 sw_ci;
+ bool reuse;
+
+ sw_ci = rxq->cons_idx & rxq->q_mask;
+ rx_info = &rxq->rx_info[sw_ci];
+
+ skb = netdev_alloc_skb_ip_align(rxq->netdev, HINIC3_RX_HDR_SIZE);
+ if (unlikely(!skb))
+ return NULL;
+
+ reuse = hinic3_add_rx_frag_with_xdp(rxq, pkt_len, rx_info, skb, xdp);
+ if (likely(reuse))
+ hinic3_reuse_rx_page(rxq, rx_info);
+
+ rx_info->buf_dma_addr = 0;
+ rx_info->page = NULL;
+
+ rxq->cons_idx += 1;
+ rxq->delta += 1;
+
+ return skb;
+}
+
#endif
-static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_cqe_info *cqe_info)
+static int recv_one_pkt(struct hinic3_rxq *rxq,
+ struct hinic3_cqe_info *cqe_info)
{
struct sk_buff *skb = NULL;
struct net_device *netdev = rxq->netdev;
@@ -808,13 +937,25 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_cqe_info *cqe_info
#ifdef HAVE_XDP_SUPPORT
u32 xdp_status;
+ struct xdp_buff xdp = { 0 };
- xdp_status = (u32)(hinic3_run_xdp(rxq, cqe_info->pkt_len));
+ xdp_status = (u32)(hinic3_run_xdp(rxq, cqe_info->pkt_len, &xdp));
if (xdp_status == HINIC3_XDP_PKT_DROP)
return 0;
-#endif
+ // build skb
+ if (xdp_status != HINIC3_XDP_PROG_EMPTY) {
+ // xdp_prog configured, build skb with xdp
+ skb = hinic3_fetch_rx_buffer_xdp(rxq, cqe_info->pkt_len, &xdp);
+ } else {
+ // xdp_prog not configured, build skb
+ skb = hinic3_fetch_rx_buffer(rxq, cqe_info);
+ }
+#else
+
+ // xdp is not supported
skb = hinic3_fetch_rx_buffer(rxq, cqe_info);
+#endif
if (unlikely(!skb)) {
RXQ_STATS_INC(rxq, alloc_skb_err);
return -ENOMEM;
@@ -842,7 +983,7 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_cqe_info *cqe_info
if (unlikely(test_bit(HINIC3_LP_TEST, &nic_dev->flags)))
hinic3_copy_lp_data(nic_dev, skb);
- if (cqe_info->lro_num)
+ if (cqe_info->lro_num > 1)
hinic3_lro_set_gso_params(skb, cqe_info->lro_num);
skb_record_rx_queue(skb, rxq->q_id);
@@ -1021,12 +1162,39 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)
return pkts;
}
+#ifdef HAVE_PAGE_POOL_SUPPORT
+static struct page_pool *hinic3_create_page_pool(struct hinic3_nic_dev *nic_dev,
+ u32 rq_depth,
+ struct hinic3_rx_info *rx_info_arr)
+{
+ struct page_pool_params pp_params = {
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_SYNC_DEV,
+ .order = nic_dev->page_order,
+ .pool_size = rq_depth * nic_dev->rx_buff_len /
+ (PAGE_SIZE << nic_dev->page_order),
+ .nid = dev_to_node(&nic_dev->pdev->dev),
+ .dev = &nic_dev->pdev->dev,
+ .dma_dir = DMA_FROM_DEVICE,
+ .offset = 0,
+ .max_len = PAGE_SIZE << nic_dev->page_order,
+ };
+ struct page_pool *page_pool;
+ int i;
+
+ page_pool = nic_dev->page_pool_enabled ?
+ page_pool_create(&pp_params) : NULL;
+ for (i = 0; i < rq_depth; i++)
+ rx_info_arr[i].page_pool = page_pool;
+ return page_pool;
+}
+#endif
+
int hinic3_alloc_rxqs_res(struct hinic3_nic_dev *nic_dev, u16 num_rq,
u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res)
{
struct hinic3_dyna_rxq_res *rqres = NULL;
u64 cqe_mem_size = sizeof(struct hinic3_rq_cqe) * rq_depth;
- int idx, i;
+ int idx;
u32 pkts;
u64 size;
@@ -1045,51 +1213,53 @@ int hinic3_alloc_rxqs_res(struct hinic3_nic_dev *nic_dev, u16 num_rq,
if (!rqres->rx_info) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc rxq%d rx info\n", idx);
- goto err_out;
+ goto err_alloc_rx_info;
}
-
if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
rqres->cqe_start_vaddr =
- dma_zalloc_coherent(&nic_dev->pdev->dev, cqe_mem_size,
+ dma_zalloc_coherent(&nic_dev->pdev->dev,
+ cqe_mem_size,
&rqres->cqe_start_paddr,
GFP_KERNEL);
if (!rqres->cqe_start_vaddr) {
- kfree(rqres->rx_info);
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc rxq%d cqe\n", idx);
- goto err_out;
+ goto err_alloc_cqe;
}
}
+
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ rqres->page_pool = hinic3_create_page_pool(nic_dev, rq_depth,
+ rqres->rx_info);
+ if (nic_dev->page_pool_enabled && !rqres->page_pool) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to create rxq%d page pool\n", idx);
+ goto err_create_page_pool;
+ }
+#endif
pkts = hinic3_rx_alloc_buffers(nic_dev, rq_depth,
rqres->rx_info);
if (!pkts) {
- if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
- dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
- rqres->cqe_start_vaddr,
- rqres->cqe_start_paddr);
- }
- kfree(rqres->rx_info);
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc rxq%d rx buffers\n", idx);
- goto err_out;
+ goto err_alloc_buffers;
}
rqres->next_to_alloc = (u16)pkts;
}
return 0;
-err_out:
- for (i = 0; i < idx; i++) {
- rqres = &rxqs_res[i];
-
- hinic3_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info);
- if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
- dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
- rqres->cqe_start_vaddr,
- rqres->cqe_start_paddr);
- }
- kfree(rqres->rx_info);
- }
-
+err_alloc_buffers:
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ page_pool_destroy(rqres->page_pool);
+err_create_page_pool:
+#endif
+ dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
+ rqres->cqe_start_vaddr,
+ rqres->cqe_start_paddr);
+err_alloc_cqe:
+ kfree(rqres->rx_info);
+err_alloc_rx_info:
+ hinic3_free_rxqs_res(nic_dev, idx, rq_depth, rxqs_res);
return -ENOMEM;
}
@@ -1104,6 +1274,10 @@ void hinic3_free_rxqs_res(struct hinic3_nic_dev *nic_dev, u16 num_rq,
rqres = &rxqs_res[idx];
hinic3_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info);
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rqres->page_pool)
+ page_pool_destroy(rqres->page_pool);
+#endif
if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
rqres->cqe_start_vaddr,
@@ -1191,6 +1365,7 @@ void hinic3_free_rxqs(struct net_device *netdev)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
kfree(nic_dev->rxqs);
+ nic_dev->rxqs = NULL;
}
int hinic3_alloc_rxqs(struct net_device *netdev)
@@ -1312,6 +1487,14 @@ int rxq_restore(struct hinic3_nic_dev *nic_dev, u16 q_id, u16 hw_ci)
nic_info(&nic_dev->pdev->dev, "rxq %u restore_buf_num:%u\n", q_id, rxq->restore_buf_num);
rx_info = &rxq->rx_info[(hw_ci + rxq->q_depth - 1) & rxq->q_mask];
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool && rx_info->page) {
+ page_pool_put_full_page(rx_info->page_pool, rx_info->page, false);
+ rx_info->buf_dma_addr = 0;
+ rx_info->page = NULL;
+ goto reset_rxq;
+ }
+#endif
if (rx_info->buf_dma_addr) {
dma_unmap_page(&nic_dev->pdev->dev, rx_info->buf_dma_addr,
nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE);
@@ -1322,7 +1505,9 @@ int rxq_restore(struct hinic3_nic_dev *nic_dev, u16 q_id, u16 hw_ci)
__free_pages(rx_info->page, nic_dev->page_order);
rx_info->page = NULL;
}
+ goto reset_rxq;
+reset_rxq:
rxq->delta = 1;
rxq->next_to_update = (u16)((hw_ci + rxq->q_depth - 1) & rxq->q_mask);
rxq->cons_idx = (u16)((rxq->next_to_update + 1) & rxq->q_mask);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
index 586a221..480f787 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
@@ -4,6 +4,10 @@
#ifndef HINIC3_RX_H
#define HINIC3_RX_H
+#ifdef HAVE_PAGE_POOL_SUPPORT
+#include <net/page_pool/helpers.h>
+#endif
+
#include <linux/types.h>
#include <linux/device.h>
#include <linux/mm_types.h>
@@ -27,6 +31,7 @@
#define HINIC3_RX_CSUM_IPSU_OTHER_ERR BIT(8)
#define HINIC3_HEADER_DATA_UNIT 2
+#define HINIC3_CQE_LEN 32
#define HINIC3_COMPACT_CQE_8B 8
#define HINIC3_COMPACT_CQE_16B 16
@@ -35,20 +40,20 @@
#define HINIC3_RQ_CQE_INTEGRATE 1
struct hinic3_rxq_stats {
- u64 packets;
- u64 bytes;
- u64 errors;
- u64 csum_errors;
- u64 other_errors;
- u64 dropped;
- u64 xdp_dropped;
- u64 rx_buf_empty;
-
- u64 alloc_skb_err;
- u64 alloc_rx_buf_err;
- u64 xdp_large_pkt;
- u64 restore_drop_sge;
- u64 rsvd2;
+ u64 packets;
+ u64 bytes;
+ u64 errors;
+ u64 csum_errors;
+ u64 other_errors;
+ u64 dropped;
+ u64 xdp_dropped;
+ u64 rx_buf_empty;
+
+ u64 alloc_skb_err;
+ u64 alloc_rx_buf_err;
+ u64 xdp_large_pkt;
+ u64 restore_drop_sge;
+ u64 rsvd2;
#ifdef HAVE_NDO_GET_STATS64
struct u64_stats_sync syncp;
#else
@@ -62,6 +67,9 @@ struct hinic3_rx_info {
struct hinic3_rq_cqe *cqe;
dma_addr_t cqe_dma;
struct page *page;
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ struct page_pool *page_pool;
+#endif
u32 page_offset;
u32 rsvd1;
struct hinic3_rq_wqe *rq_wqe;
@@ -102,7 +110,7 @@ struct hinic3_rxq {
u16 next_to_update;
struct device *dev; /* device for DMA mapping */
- unsigned long status;
+ u64 status;
dma_addr_t cqe_start_paddr;
void *cqe_start_vaddr;
@@ -130,6 +138,9 @@ struct hinic3_dyna_rxq_res {
struct hinic3_rx_info *rx_info;
dma_addr_t cqe_start_paddr;
void *cqe_start_vaddr;
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ struct page_pool *page_pool;
+#endif
};
int hinic3_alloc_rxqs(struct net_device *netdev);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h b/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h
index bdd5a8e..d816609 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h
@@ -11,10 +11,12 @@
#ifndef HINIC3_SRV_NIC_H
#define HINIC3_SRV_NIC_H
-#include "hinic3_mgmt_interface.h"
+#include <linux/netdevice.h>
#include "mag_mpu_cmd.h"
-#include "mag_cmd.h"
+#include "mag_mpu_cmd_defs.h"
#include "hinic3_lld.h"
+#include "nic_cfg_comm.h"
+#include "nic_mpu_cmd_defs.h"
enum hinic3_queue_type {
HINIC3_SQ,
@@ -64,6 +66,7 @@ enum hinic3_nic_event_type {
EVENT_NIC_DCB_STATE_CHANGE,
EVENT_NIC_BOND_DOWN,
EVENT_NIC_BOND_UP,
+ EVENT_NIC_OUTBAND_CFG,
};
/* *
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
index bc1a8ef..99264c7 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
@@ -223,24 +223,72 @@ static void get_inner_l3_l4_type(struct sk_buff *skb, union hinic3_ip *ip,
enum sq_l3_type *l3_type, u8 *l4_proto)
{
unsigned char *exthdr = NULL;
- __be16 frag_off = 0;
if (ip->v4->version == IP4_VERSION) {
*l3_type = IPV4_PKT_WITH_CHKSUM_OFFLOAD;
*l4_proto = ip->v4->protocol;
+
+#ifdef HAVE_OUTER_IPV6_TUNNEL_OFFLOAD
+ /* inner_transport_header is wrong in centos7.0 and suse12.1 */
+ l4->hdr = ip->hdr + ((u8)ip->v4->ihl << IP_HDR_IHL_UNIT_SHIFT);
+#endif
} else if (ip->v4->version == IP6_VERSION) {
*l3_type = IPV6_PKT;
exthdr = ip->hdr + sizeof(*ip->v6);
*l4_proto = ip->v6->nexthdr;
- if (exthdr != l4->hdr)
+ if (exthdr != l4->hdr) {
+ __be16 frag_off = 0;
+#ifndef HAVE_OUTER_IPV6_TUNNEL_OFFLOAD
ipv6_skip_exthdr(skb, (int)(exthdr - skb->data),
- l4_proto, &frag_off);
+ l4_proto, &frag_off);
+#else
+ int pld_off = 0;
+
+ pld_off = ipv6_skip_exthdr(skb,
+ (int)(exthdr - skb->data),
+ l4_proto, &frag_off);
+ l4->hdr = skb->data + pld_off;
+#endif
+ }
} else {
*l3_type = UNKNOWN_L3TYPE;
*l4_proto = 0;
}
}
+static u8 hinic3_get_inner_l4_type(struct sk_buff *skb)
+{
+ enum sq_l3_type l3_type;
+ u8 l4_proto;
+ union hinic3_ip ip;
+ union hinic3_l4 l4;
+
+ ip.hdr = skb_inner_network_header(skb);
+ l4.hdr = skb_inner_transport_header(skb);
+
+ get_inner_l3_l4_type(skb, &ip, &l4, &l3_type, &l4_proto);
+
+ return l4_proto;
+}
+
+static void hinic3_set_unknown_tunnel_csum(struct sk_buff *skb)
+{
+ int csum_offset;
+ __sum16 skb_csum;
+ u8 l4_proto;
+
+ l4_proto = hinic3_get_inner_l4_type(skb);
+ /* Unsupport tunnel packet, disable csum offload */
+ skb_checksum_help(skb);
+ /* The value of csum is changed from 0xffff to 0 according to RFC1624. */
+ if (skb->ip_summed == CHECKSUM_NONE && l4_proto != IPPROTO_UDP) {
+ csum_offset = skb_checksum_start_offset(skb) + skb->csum_offset;
+ skb_csum = *(__sum16 *)(skb->data + csum_offset);
+ if (skb_csum == 0xffff)
+ *(__sum16 *)(skb->data + csum_offset) = 0;
+ }
+}
+
static int hinic3_tx_csum(struct hinic3_txq *txq, struct sk_buff *skb,
struct hinic3_offload_info *offload_info,
struct hinic3_queue_info *queue_info)
@@ -276,10 +324,9 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct sk_buff *skb,
if (l4_proto == IPPROTO_UDP)
queue_info->udp_dp_en = 1;
- if (l4_proto != IPPROTO_UDP ||
- ((struct udphdr *)skb_transport_header(skb))->dest != VXLAN_OFFLOAD_PORT_LE) {
+ if (l4_proto != IPPROTO_UDP) {
TXQ_STATS_INC(txq, unknown_tunnel_pkt);
- skb_checksum_help(skb);
+ hinic3_set_unknown_tunnel_csum(skb);
return 0;
}
}
@@ -682,6 +729,14 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
+ /* l2nic outband vlan cfg enable */
+ if (!skb_vlan_tag_present(skb) &&
+ nic_dev->nic_cap.outband_vlan_cfg_en == 1 &&
+ nic_dev->outband_cfg.outband_default_vid != 0) {
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ (u16)nic_dev->outband_cfg.outband_default_vid);
+ }
+
offload = hinic3_tx_offload(skb, &offload_info, &queue_info, txq);
if (unlikely(offload == TX_OFFLOAD_INVALID)) {
TXQ_STATS_INC(txq, offload_cow_skb_err);
@@ -880,6 +935,7 @@ int hinic3_alloc_txqs_res(struct hinic3_nic_dev *nic_dev, u16 num_sq,
tqres->bds = kzalloc(size, GFP_KERNEL);
if (!tqres->bds) {
kfree(tqres->tx_info);
+ tqres->tx_info = NULL;
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc txq%d bds info\n", idx);
goto err_out;
@@ -893,7 +949,9 @@ err_out:
tqres = &txqs_res[i];
kfree(tqres->bds);
+ tqres->bds = NULL;
kfree(tqres->tx_info);
+ tqres->tx_info = NULL;
}
return -ENOMEM;
@@ -910,7 +968,9 @@ void hinic3_free_txqs_res(struct hinic3_nic_dev *nic_dev, u16 num_sq,
free_all_tx_skbs(nic_dev, sq_depth, tqres->tx_info);
kfree(tqres->bds);
+ tqres->bds = NULL;
kfree(tqres->tx_info);
+ tqres->tx_info = NULL;
}
}
@@ -982,6 +1042,7 @@ void hinic3_free_txqs(struct net_device *netdev)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
kfree(nic_dev->txqs);
+ nic_dev->txqs = NULL;
}
static bool is_hw_complete_sq_process(struct hinic3_io_queue *sq)
@@ -998,7 +1059,7 @@ static bool is_hw_complete_sq_process(struct hinic3_io_queue *sq)
static int hinic3_stop_sq(struct hinic3_txq *txq)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(txq->netdev);
- unsigned long timeout;
+ u64 timeout;
int err;
timeout = msecs_to_jiffies(HINIC3_FLUSH_QUEUE_TIMEOUT) + jiffies;
@@ -1007,7 +1068,7 @@ static int hinic3_stop_sq(struct hinic3_txq *txq)
return 0;
usleep_range(900, 1000); /* sleep 900 us ~ 1000 us */
- } while (time_before(jiffies, timeout));
+ } while (time_before(jiffies, (unsigned long)timeout));
/* force hardware to drop packets */
timeout = msecs_to_jiffies(HINIC3_FLUSH_QUEUE_TIMEOUT) + jiffies;
@@ -1020,7 +1081,7 @@ static int hinic3_stop_sq(struct hinic3_txq *txq)
break;
usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
- } while (time_before(jiffies, timeout));
+ } while (time_before(jiffies, (unsigned long)timeout));
/* Avoid msleep takes too long and get a fake result */
if (is_hw_complete_sq_process(txq->sq))
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h b/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h
index 1b9e509..7ae029b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h
@@ -29,7 +29,7 @@ struct hinic3_wq {
#define WQ_MASK_IDX(wq, idx) ((idx) & (wq)->idx_mask)
#define WQ_MASK_PAGE(wq, pg_idx) \
- ((pg_idx) < (wq)->num_wq_pages ? (pg_idx) : 0)
+ (((pg_idx) < ((wq)->num_wq_pages)) ? (pg_idx) : 0)
#define WQ_PAGE_IDX(wq, idx) ((idx) >> (wq)->wqebbs_per_page_shift)
#define WQ_OFFSET_IN_PAGE(wq, idx) ((idx) & (wq)->wqebbs_per_page_mask)
#define WQ_GET_WQEBB_ADDR(wq, pg_idx, idx_in_pg) \
@@ -75,7 +75,7 @@ static inline void *hinic3_wq_get_multi_wqebbs(struct hinic3_wq *wq,
pg_idx = WQ_PAGE_IDX(wq, *prod_idx);
off_in_page = WQ_OFFSET_IN_PAGE(wq, *prod_idx);
- if (off_in_page + num_wqebbs > wq->wqebbs_per_page) {
+ if ((off_in_page + num_wqebbs) > wq->wqebbs_per_page) {
/* wqe across wq page boundary */
*second_part_wqebbs_addr =
WQ_GET_WQEBB_ADDR(wq, WQ_MASK_PAGE(wq, pg_idx + 1), 0);
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c
index 597d3fe..468351f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c
@@ -400,12 +400,15 @@ static int wait_for_status_poll(struct hinic3_api_cmd_chain *chain)
API_CMD_STATUS_TIMEOUT, 100); /* wait 100 us once */
}
-static void copy_resp_data(struct hinic3_api_cmd_cell_ctxt *ctxt, void *ack,
+static void copy_resp_data(struct hinic3_api_cmd_chain *chain,
+ struct hinic3_api_cmd_cell_ctxt *ctxt, void *ack,
u16 ack_size)
{
struct hinic3_api_cmd_resp_fmt *resp = ctxt->resp;
+ int rsp_size_align = chain->rsp_size_align - 0x8;
+ int rsp_size = (ack_size > rsp_size_align) ? rsp_size_align : ack_size;
- memcpy(ack, &resp->resp_data, ack_size);
+ memcpy(ack, &resp->resp_data, rsp_size);
ctxt->status = 0;
}
@@ -464,7 +467,7 @@ static int wait_for_api_cmd_completion(struct hinic3_api_cmd_chain *chain,
case HINIC3_API_CMD_POLL_READ:
err = wait_for_resp_polling(ctxt);
if (err == 0)
- copy_resp_data(ctxt, ack, ack_size);
+ copy_resp_data(chain, ctxt, ack, ack_size);
else
sdk_err(dev, "API CMD poll response timeout\n");
break;
@@ -1054,13 +1057,11 @@ alloc_cells_buf_err:
alloc_wb_status_err:
kfree(chain->cell_ctxt);
-/*lint -save -e548*/
alloc_cell_ctxt_err:
if (chain->chain_type == HINIC3_API_CMD_WRITE_ASYNC_TO_MGMT_CPU)
spin_lock_deinit(&chain->async_lock);
else
sema_deinit(&chain->sem);
-/*lint -restore*/
return err;
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c
index 38474ba..9f10131 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c
@@ -801,7 +801,7 @@ static int cmdq_sync_cmd(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
hinic3_cmdq_fill_completion_info(cmd_info, &cmpt_code, &done, &errcode, out_param);
cmdq_set_cmd_buf(cmd_info, cmdq->hwdev, buf_in, buf_out);
- memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info));
+ memcpy(&saved_cmd_info, cmd_info, sizeof(struct hinic3_cmdq_cmd_info));
cmdq_sync_wqe_prepare(cmdq, mod, cmd, buf_in, buf_out, curr_wqe, curr_pi, nic_cmd_type);
@@ -1075,6 +1075,7 @@ int hinic3_cmdq_async(void *hwdev, u8 mod, u8 cmd, struct hinic3_cmd_buf *buf_in
return cmdq_async_cmd(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod,
cmd, buf_in, channel);
}
+EXPORT_SYMBOL(hinic3_cmdq_async);
int hinic3_cmdq_async_cos(void *hwdev, u8 mod, u8 cmd,
u8 cos_id, struct hinic3_cmd_buf *buf_in, u16 channel)
@@ -1320,6 +1321,7 @@ cmd_infos_err:
static void free_cmdq(struct hinic3_cmdq *cmdq)
{
kfree(cmdq->cmd_infos);
+ cmdq->cmd_infos = NULL;
spin_lock_deinit(&cmdq->cmdq_lock);
}
@@ -1530,7 +1532,7 @@ static int create_cmdq_wq(struct hinic3_cmdqs *cmdqs)
type = HINIC3_CMDQ_SYNC;
for (; type < cmdqs->cmdq_num; type++)
memcpy((u8 *)cmdqs->wq_block_vaddr +
- CMDQ_WQ_CLA_SIZE * type,
+ ((u64)type * CMDQ_WQ_CLA_SIZE),
cmdqs->cmdq[type].wq.wq_block_vaddr,
cmdqs->cmdq[type].wq.num_wq_pages * sizeof(u64));
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h
index b9b884f..4f4639d 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h
@@ -15,11 +15,6 @@
#include "hinic3_common.h"
#include "hinic3_hwdev.h"
-struct dma_pool {
- unsigned int size;
- void *dev_hdl;
-};
-
#define HINIC3_SCMD_DATA_LEN 16
#define HINIC3_CMDQ_DEPTH 4096
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c
index c212bcc..d7e4985 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c
@@ -16,7 +16,6 @@
#include "ossl_knl.h"
#include "npu_cmdq_base_defs.h"
-#include "comm_defs.h"
#include "hinic3_crm.h"
#include "hinic3_hw.h"
#include "hinic3_hwdev.h"
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 5e0139a..0981d94 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c
@@ -22,11 +22,15 @@
#include "hinic3_sriov.h"
#include "hinic3_nictool.h"
#include "hinic3_pci_id_tbl.h"
+#include "hinic3_hwdev.h"
+#include "cfg_mgmt_mpu_cmd_defs.h"
+#include "mpu_cmd_base_defs.h"
#include "hinic3_dev_mgmt.h"
#define HINIC3_WAIT_TOOL_CNT_TIMEOUT 10000
#define HINIC3_WAIT_TOOL_MIN_USLEEP_TIME 9900
#define HINIC3_WAIT_TOOL_MAX_USLEEP_TIME 10000
+#define HIGHT_BDF 8
static unsigned long card_bit_map;
@@ -60,14 +64,24 @@ void lld_dev_cnt_init(struct hinic3_pcidev *pci_adapter)
void lld_dev_hold(struct hinic3_lld_dev *dev)
{
- struct hinic3_pcidev *pci_adapter = pci_get_drvdata(dev->pdev);
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!dev)
+ return;
+
+ pci_adapter = pci_get_drvdata(dev->pdev);
atomic_inc(&pci_adapter->ref_cnt);
}
void lld_dev_put(struct hinic3_lld_dev *dev)
{
- struct hinic3_pcidev *pci_adapter = pci_get_drvdata(dev->pdev);
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!dev)
+ return;
+
+ pci_adapter = pci_get_drvdata(dev->pdev);
atomic_dec(&pci_adapter->ref_cnt);
}
@@ -236,6 +250,40 @@ void hinic3_get_all_chip_id(void *id_info)
card_id->num = (u32)i;
}
+int hinic3_bar_mmap_param_valid(phys_addr_t phy_addr, unsigned long vmsize)
+{
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *dev = NULL;
+ u64 bar1_phy_addr = 0;
+ u64 bar3_phy_addr = 0;
+ u64 bar1_size = 0;
+ u64 bar3_size = 0;
+
+ lld_hold();
+
+ /* get PF bar1 or bar3 physical address to verify */
+ list_for_each_entry(chip_node, &g_hinic3_chip_list, node) {
+ list_for_each_entry(dev, &chip_node->func_list, node) {
+ if (hinic3_func_type(dev->hwdev) == TYPE_VF)
+ continue;
+
+ bar1_phy_addr = pci_resource_start(dev->pcidev, HINIC3_PF_PCI_CFG_REG_BAR);
+ bar1_size = pci_resource_len(dev->pcidev, HINIC3_PF_PCI_CFG_REG_BAR);
+
+ bar3_phy_addr = pci_resource_start(dev->pcidev, HINIC3_PCI_MGMT_REG_BAR);
+ bar3_size = pci_resource_len(dev->pcidev, HINIC3_PCI_MGMT_REG_BAR);
+ if ((phy_addr == bar1_phy_addr && vmsize <= bar1_size) ||
+ (phy_addr == bar3_phy_addr && vmsize <= bar3_size)) {
+ lld_put();
+ return 0;
+ }
+ }
+ }
+
+ lld_put();
+ return -EINVAL;
+}
+
void hinic3_get_card_func_info_by_card_name(const char *chip_name,
struct hinic3_card_func_info *card_func)
{
@@ -422,6 +470,29 @@ struct hinic3_lld_dev *hinic3_get_lld_dev_by_chip_and_port(const char *chip_name
return NULL;
}
+void *hinic3_get_ppf_dev(void)
+{
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct list_head *chip_list = NULL;
+
+ lld_hold();
+ chip_list = get_hinic3_chip_list();
+
+ list_for_each_entry(chip_node, chip_list, node)
+ list_for_each_entry(pci_adapter, &chip_node->func_list, node)
+ if (hinic3_func_type(pci_adapter->hwdev) == TYPE_PPF) {
+ pr_info("Get ppf_func_id:%u",
+ hinic3_global_func_id(pci_adapter->hwdev));
+ lld_put();
+ return pci_adapter->lld_dev.hwdev;
+ }
+
+ lld_put();
+ return NULL;
+}
+EXPORT_SYMBOL(hinic3_get_ppf_dev);
+
struct hinic3_lld_dev *hinic3_get_lld_dev_by_dev_name(const char *dev_name,
enum hinic3_service_type type)
{
@@ -518,6 +589,7 @@ EXPORT_SYMBOL(hinic3_get_ppf_lld_dev_unsafe);
int hinic3_get_chip_name(struct hinic3_lld_dev *lld_dev, char *chip_name, u16 max_len)
{
struct hinic3_pcidev *pci_adapter = NULL;
+ int ret = 0;
if (!lld_dev || !chip_name || !max_len)
return -EINVAL;
@@ -527,12 +599,18 @@ int hinic3_get_chip_name(struct hinic3_lld_dev *lld_dev, char *chip_name, u16 ma
return -EFAULT;
lld_hold();
- strscpy(chip_name, pci_adapter->chip_node->chip_name, max_len);
+ if (strscpy(chip_name, pci_adapter->chip_node->chip_name, max_len) < 0)
+ goto RELEASE;
chip_name[max_len - 1] = '\0';
lld_put();
return 0;
+
+RELEASE:
+ lld_put();
+
+ return ret;
}
EXPORT_SYMBOL(hinic3_get_chip_name);
@@ -541,6 +619,87 @@ struct hinic3_hwdev *hinic3_get_sdk_hwdev_by_lld(struct hinic3_lld_dev *lld_dev)
return lld_dev->hwdev;
}
+void hinic3_write_oshr_info(struct os_hot_replace_info *out_oshr_info,
+ struct hw_pf_info *info,
+ struct hinic3_board_info *board_info,
+ struct card_node *chip_node, u32 serivce_enable,
+ u32 func_info_idx)
+{
+ out_oshr_info->func_infos[func_info_idx].pf_idx = info->glb_func_idx;
+ out_oshr_info->func_infos[func_info_idx].backup_pf =
+ (((info->glb_func_idx) / (board_info->port_num)) %
+ HOT_REPLACE_PARTITION_NUM == 0) ?
+ ((info->glb_func_idx) + (board_info->port_num)) :
+ ((info->glb_func_idx) - (board_info->port_num));
+ out_oshr_info->func_infos[func_info_idx].partition =
+ ((info->glb_func_idx) / (board_info->port_num)) %
+ HOT_REPLACE_PARTITION_NUM;
+ out_oshr_info->func_infos[func_info_idx].port_id = info->port_id;
+ out_oshr_info->func_infos[func_info_idx].bdf =
+ (info->bus_num << HIGHT_BDF) + info->glb_func_idx;
+ out_oshr_info->func_infos[func_info_idx].bus_num = chip_node->bus_num;
+ out_oshr_info->func_infos[func_info_idx].valid = serivce_enable;
+ memcpy(out_oshr_info->func_infos[func_info_idx].card_name,
+ chip_node->chip_name, IFNAMSIZ);
+}
+
+void hinic3_get_os_hot_replace_info(void *oshr_info)
+{
+ struct os_hot_replace_info *out_oshr_info =
+ (struct os_hot_replace_info *)oshr_info;
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *dst_dev = NULL;
+ struct hinic3_board_info *board_info = NULL;
+ struct hw_pf_info *infos = NULL;
+ struct hinic3_hw_pf_infos *pf_infos = NULL;
+ struct hinic3_hwdev *hwdev = NULL;
+ u32 func_info_idx = 0, func_id = 0, func_num, serivce_enable = 0;
+ struct list_head *hinic3_chip_list = get_hinic3_chip_list();
+ int err;
+
+ lld_hold();
+ pf_infos = kzalloc(sizeof(*pf_infos), GFP_KERNEL);
+ if (!pf_infos) {
+ pr_err("kzalloc pf_infos fail\n");
+ lld_put();
+ return;
+ }
+ list_for_each_entry(chip_node, hinic3_chip_list, node) {
+ list_for_each_entry(dst_dev, &chip_node->func_list, node) {
+ err = hinic3_get_hw_pf_infos(dst_dev->hwdev,
+ pf_infos,
+ HINIC3_CHANNEL_COMM);
+ if (err != 0) {
+ pr_err("get pf info failed\n");
+ break;
+ }
+ hwdev = (struct hinic3_hwdev *)dst_dev->hwdev;
+ serivce_enable = 0;
+ infos = pf_infos->infos;
+ board_info = &hwdev->board_info;
+ if (hwdev->hot_replace_mode == HOT_REPLACE_ENABLE)
+ serivce_enable = 1;
+ break;
+ }
+
+ func_num = pf_infos->num_pfs;
+ if (func_num <= 0) {
+ pr_err("get pf num failed\n");
+ break;
+ }
+
+ for (func_id = 0; func_id < func_num; func_id++) {
+ hinic3_write_oshr_info(out_oshr_info, &infos[func_id],
+ board_info, chip_node,
+ serivce_enable, func_info_idx);
+ func_info_idx++;
+ }
+ }
+ out_oshr_info->func_cnt = func_info_idx;
+ kfree(pf_infos);
+ lld_put();
+}
+
struct card_node *hinic3_get_chip_node_by_lld(struct hinic3_lld_dev *lld_dev)
{
struct hinic3_pcidev *pci_adapter = pci_get_drvdata(lld_dev->pdev);
@@ -608,21 +767,24 @@ void hinic3_get_card_info(const void *hwdev, void *bufin)
if (hinic3_support_nic(fun_hwdev, NULL)) {
if (dev->uld_dev[SERVICE_T_NIC]) {
info->pf[i].pf_type |= (u32)BIT(SERVICE_T_NIC);
- get_dynamic_uld_dev_name(dev, SERVICE_T_NIC, info->pf[i].name);
+ get_dynamic_uld_dev_name(dev, SERVICE_T_NIC,
+ info->pf[i].name);
}
}
if (hinic3_support_ppa(fun_hwdev, NULL)) {
if (dev->uld_dev[SERVICE_T_PPA]) {
info->pf[i].pf_type |= (u32)BIT(SERVICE_T_PPA);
- get_dynamic_uld_dev_name(dev, SERVICE_T_PPA, info->pf[i].name);
+ get_dynamic_uld_dev_name(dev, SERVICE_T_PPA,
+ info->pf[i].name);
}
}
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)
+ 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),
@@ -721,6 +883,7 @@ int alloc_chip_node(struct hinic3_pcidev *pci_adapter)
struct card_node *chip_node = NULL;
unsigned char i;
unsigned char bus_number = 0;
+ int err;
if (chip_node_is_exist(pci_adapter, &bus_number))
return 0;
@@ -746,7 +909,10 @@ int alloc_chip_node(struct hinic3_pcidev *pci_adapter)
/* bus number */
chip_node->bus_num = bus_number;
- if (snprintf(chip_node->chip_name, IFNAMSIZ, "%s%u", HINIC3_CHIP_NAME, i) < 0) {
+ snprintf(chip_node->chip_name, IFNAMSIZ, "%s%u", HINIC3_CHIP_NAME, i);
+
+ err = sscanf(chip_node->chip_name, HINIC3_CHIP_NAME "%d", &chip_node->chip_id);
+ if (err <= 0) {
clear_bit(i, &card_bit_map);
kfree(chip_node);
return -EINVAL;
@@ -803,3 +969,36 @@ int hinic3_get_pf_id(struct card_node *chip_node, u32 port_id, u32 *pf_id, u32 *
return 0;
}
+
+void hinic3_get_mbox_cnt(const void *hwdev, void *bufin)
+{
+ struct card_node *chip_node = NULL;
+ struct card_mbox_cnt_info *info = (struct card_mbox_cnt_info *)bufin;
+ struct hinic3_pcidev *dev = NULL;
+ struct hinic3_hwdev *func_hwdev = NULL;
+ u32 i = 0;
+
+ info->func_num = 0;
+ chip_node = hinic3_get_chip_node_by_hwdev(hwdev);
+ if (!chip_node)
+ return;
+
+ lld_hold();
+
+ list_for_each_entry(dev, &chip_node->func_list, node) {
+ func_hwdev = (struct hinic3_hwdev *)dev->hwdev;
+ strscpy(info->func_info[i].bus_info, pci_name(dev->pcidev),
+ sizeof(info->func_info[i].bus_info));
+
+ info->func_info[i].send_cnt = func_hwdev->mbox_send_cnt;
+ info->func_info[i].ack_cnt = func_hwdev->mbox_ack_cnt;
+ info->func_num++;
+ i = info->func_num;
+ if (i >= ARRAY_SIZE(info->func_info)) {
+ sdk_err(&dev->pcidev->dev, "chip_node->func_list bigger than pf_max + vf_max\n");
+ break;
+ }
+ }
+
+ lld_put();
+}
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 5c7c7cd..9815082 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h
@@ -22,8 +22,13 @@
#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)
+#define HINIC3_IS_VF_DEV(pdev) \
+ ((pdev)->device == HINIC3_DEV_ID_VF || \
+ (pdev)->device == HINIC3_DEV_SDI_5_1_ID_VF)
+#define HINIC3_IS_SPU_DEV(pdev) \
+ (((pdev)->device == HINIC3_DEV_ID_SPU) || \
+ ((pdev)->device == HINIC3_DEV_ID_SDI_5_0_PF) || \
+ (((pdev)->device == HINIC3_DEV_ID_DPU_PF)))
enum {
HINIC3_NOT_PROBE = 1,
@@ -79,6 +84,13 @@ struct hinic3_pcidev {
u16 probe_fault_level;
u16 rsvd2;
u64 rsvd4;
+
+ struct workqueue_struct *multi_host_mgmt_workq;
+ struct work_struct slave_nic_work;
+ struct work_struct slave_vroce_work;
+
+ struct workqueue_struct *migration_probe_workq;
+ struct delayed_work migration_probe_dwork;
};
struct hinic_chip_info {
@@ -104,4 +116,6 @@ void wait_lld_dev_unused(struct hinic3_pcidev *pci_adapter);
void *hinic3_get_hwdev_by_pcidev(struct pci_dev *pdev);
+int hinic3_bar_mmap_param_valid(phys_addr_t phy_addr, unsigned long vmsize);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c
index 11561a0..59ff722 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c
@@ -101,7 +101,8 @@ static bool check_image_device_type(struct hinic3_hwdev *hwdev, u32 device_type)
static void encapsulate_update_cmd(struct hinic3_cmd_update_firmware *msg,
struct firmware_section *section_info,
- int *remain_len, u32 *send_len, u32 *send_pos)
+ const int *remain_len, u32 *send_len,
+ u32 *send_pos)
{
memset(msg->data, 0, sizeof(msg->data));
msg->ctl_info.sf = (*remain_len == section_info->section_len) ? true : false;
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c
index 937d699..be7c82b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c
@@ -26,6 +26,8 @@
#include "hinic3_prof_adap.h"
#include "hinic3_eqs.h"
+#include "vram_common.h"
+
#define HINIC3_EQS_WQ_NAME "hinic3_eqs"
#define AEQ_CTRL_0_INTR_IDX_SHIFT 0
@@ -66,7 +68,6 @@
#define HINIC3_TASK_PROCESS_EQE_LIMIT 1024
#define HINIC3_EQ_UPDATE_CI_STEP 64
-/*lint -e806*/
static uint g_aeq_len = HINIC3_DEFAULT_AEQ_LEN;
module_param(g_aeq_len, uint, 0444);
MODULE_PARM_DESC(g_aeq_len,
@@ -83,7 +84,6 @@ static uint g_num_ceqe_in_tasklet = HINIC3_TASK_PROCESS_EQE_LIMIT;
module_param(g_num_ceqe_in_tasklet, uint, 0444);
MODULE_PARM_DESC(g_num_ceqe_in_tasklet,
"The max number of ceqe can be processed in tasklet, default = 1024");
-/*lint +e806*/
#define CEQ_CTRL_0_INTR_IDX_SHIFT 0
#define CEQ_CTRL_0_DMA_ATTR_SHIFT 12
@@ -819,18 +819,22 @@ static int alloc_eq_pages(struct hinic3_eq *eq)
u32 reg, init_val;
u16 pg_idx, i;
int err;
+ gfp_t gfp_vram;
eq->eq_pages = kcalloc(eq->num_pages, sizeof(*eq->eq_pages),
GFP_KERNEL);
if (!eq->eq_pages)
return -ENOMEM;
+ gfp_vram = hi_vram_get_gfp_vram();
+
for (pg_idx = 0; pg_idx < eq->num_pages; pg_idx++) {
eq_page = &eq->eq_pages[pg_idx];
err = hinic3_dma_zalloc_coherent_align(eq->hwdev->dev_hdl,
eq->page_size,
HINIC3_MIN_EQ_PAGE_SIZE,
- GFP_KERNEL, eq_page);
+ GFP_KERNEL | gfp_vram,
+ eq_page);
if (err) {
sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq page, page index: %u\n",
pg_idx);
@@ -881,6 +885,7 @@ static void free_eq_pages(struct hinic3_eq *eq)
&eq->eq_pages[pg_idx]);
kfree(eq->eq_pages);
+ eq->eq_pages = NULL;
}
static inline u32 get_page_size(const struct hinic3_eq *eq)
@@ -1120,7 +1125,8 @@ int hinic3_aeqs_init(struct hinic3_hwdev *hwdev, u16 num_aeqs,
hwdev->aeqs = aeqs;
aeqs->hwdev = hwdev;
aeqs->num_aeqs = num_aeqs;
- aeqs->workq = alloc_workqueue(HINIC3_EQS_WQ_NAME, WQ_MEM_RECLAIM,
+ aeqs->workq = alloc_workqueue(HINIC3_EQS_WQ_NAME,
+ WQ_MEM_RECLAIM | WQ_HIGHPRI,
HINIC3_MAX_AEQS);
if (!aeqs->workq) {
sdk_err(hwdev->dev_hdl, "Failed to initialize aeq workqueue\n");
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c
index a4cbac8..6b96b87 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c
@@ -82,6 +82,48 @@ int hinic3_sm_ctr_rd16(void *hwdev, u8 node, u8 instance, u32 ctr_id,
return 0;
}
+/**
+ * hinic3_sm_ctr_rd16_clear - small single 16 counter read and clear to zero
+ * @hwdev: the hardware device
+ * @node: the node id
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ **/
+int hinic3_sm_ctr_rd16_clear(void *hwdev, u8 node, u8 instance, u32 ctr_id,
+ u16 *value)
+{
+ struct chipif_sml_ctr_rd_req req;
+ union ctr_rd_rsp rsp;
+ int ret;
+
+ if (!hwdev || !value)
+ return -EFAULT;
+
+ if (!COMM_SUPPORT_API_CHAIN((struct hinic3_hwdev *)hwdev))
+ return -EPERM;
+
+ memset(&req, 0, sizeof(req));
+
+ hinic3_sml_ctr_read_build_req(&req, instance,
+ CHIPIF_SM_CTR_OP_READ_CLEAR,
+ CHIPIF_ACK, ctr_id, 0);
+
+ ret = hinic3_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req),
+ (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+ if (ret) {
+ sdk_err(((struct hinic3_hwdev *)hwdev)->dev_hdl,
+ "Sm 16bit counter clear fail, err(%d)\n", ret);
+ return ret;
+ }
+ sml_ctr_htonl_n((u32 *)&rsp, sizeof(rsp) / sizeof(u32));
+ *value = rsp.bs_ss16_rsp.value1;
+
+ return 0;
+}
+
/**
* hinic3_sm_ctr_rd32 - small single 32 counter read
* @hwdev: the hardware device
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 030ef6d..41c439a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c
@@ -34,13 +34,18 @@ static void parse_pub_res_cap_dfx(struct hinic3_hwdev *hwdev,
cap->max_vf);
sdk_info(hwdev->dev_hdl, "Host_pf_num: 0x%x, pf_id_start: 0x%x, host_vf_num: 0x%x, vf_id_start: 0x%x\n",
cap->pf_num, cap->pf_id_start, cap->vf_num, cap->vf_id_start);
- sdk_info(hwdev->dev_hdl, "host_valid_bitmap: 0x%x, master_host_id: 0x%x, srv_multi_host_mode: 0x%x\n",
- cap->host_valid_bitmap, cap->master_host_id, cap->srv_multi_host_mode);
sdk_info(hwdev->dev_hdl,
- "fake_vf_start_id: 0x%x, fake_vf_num: 0x%x, fake_vf_max_pctx: 0x%x\n",
- cap->fake_vf_start_id, cap->fake_vf_num, cap->fake_vf_max_pctx);
- sdk_info(hwdev->dev_hdl, "fake_vf_bfilter_start_addr: 0x%x, fake_vf_bfilter_len: 0x%x\n",
- cap->fake_vf_bfilter_start_addr, cap->fake_vf_bfilter_len);
+ "host_valid_bitmap: 0x%x, master_host_id: 0x%x, srv_multi_host_mode: 0x%x, hot_plug_disable: 0x%x\n",
+ cap->host_valid_bitmap, cap->master_host_id,
+ cap->srv_multi_host_mode, cap->hot_plug_disable);
+ sdk_info(hwdev->dev_hdl,
+ "os_hot_replace: 0x%x, fake_vf_start_id: 0x%x, fake_vf_num: 0x%x, fake_vf_max_pctx: 0x%x\n",
+ cap->os_hot_replace, cap->fake_vf_start_id,
+ cap->fake_vf_num, cap->fake_vf_max_pctx);
+ sdk_info(hwdev->dev_hdl,
+ "fake_vf_bfilter_start_addr: 0x%x, fake_vf_bfilter_len: 0x%x, bond_create_mode: 0x%x\n",
+ cap->fake_vf_bfilter_start_addr, cap->fake_vf_bfilter_len,
+ cap->bond_create_mode);
}
static void parse_cqm_res_cap(struct hinic3_hwdev *hwdev, struct service_cap *cap,
@@ -109,6 +114,9 @@ static void parse_pub_res_cap(struct hinic3_hwdev *hwdev,
cap->host_valid_bitmap = dev_cap->host_valid_bitmap;
cap->master_host_id = dev_cap->master_host_id;
cap->srv_multi_host_mode = dev_cap->srv_multi_host_mode;
+ cap->hot_plug_disable = dev_cap->hot_plug_disable;
+ cap->bond_create_mode = dev_cap->bond_create_mode;
+ cap->os_hot_replace = dev_cap->os_hot_replace;
cap->fake_vf_en = dev_cap->fake_vf_en;
cap->fake_vf_start_bit = dev_cap->fake_vf_start_bit;
cap->fake_vf_end_bit = dev_cap->fake_vf_end_bit;
@@ -148,18 +156,27 @@ static void parse_l2nic_res_cap(struct hinic3_hwdev *hwdev,
nic_cap->max_sqs = dev_cap->nic_max_sq_id + 1;
nic_cap->max_rqs = dev_cap->nic_max_rq_id + 1;
nic_cap->default_num_queues = dev_cap->nic_default_num_queues;
+ nic_cap->outband_vlan_cfg_en = dev_cap->outband_vlan_cfg_en;
+ nic_cap->lro_enable = dev_cap->lro_enable;
sdk_info(hwdev->dev_hdl, "L2nic resource capbility, max_sqs: 0x%x, max_rqs: 0x%x\n",
nic_cap->max_sqs, nic_cap->max_rqs);
/* Check parameters from firmware */
- if (nic_cap->max_sqs > HINIC3_CFG_MAX_QP ||
- nic_cap->max_rqs > HINIC3_CFG_MAX_QP) {
- sdk_info(hwdev->dev_hdl, "Number of qp exceed limit[1-%d]: sq: %u, rq: %u\n",
- HINIC3_CFG_MAX_QP, nic_cap->max_sqs, nic_cap->max_rqs);
+ if (nic_cap->max_sqs > HINIC3_CFG_MAX_QP) {
+ sdk_info(hwdev->dev_hdl, "Number of sq exceed limit[1-%d]: sq: %u\n",
+ HINIC3_CFG_MAX_QP, nic_cap->max_sqs);
nic_cap->max_sqs = HINIC3_CFG_MAX_QP;
+ }
+
+ if (nic_cap->max_rqs > HINIC3_CFG_MAX_QP) {
+ sdk_info(hwdev->dev_hdl, "Number of rq exceed limit[1-%d]: rq: %u\n",
+ HINIC3_CFG_MAX_QP, nic_cap->max_rqs);
nic_cap->max_rqs = HINIC3_CFG_MAX_QP;
}
+
+ if (nic_cap->outband_vlan_cfg_en)
+ sdk_info(hwdev->dev_hdl, "L2nic outband vlan cfg enabled\n");
}
static void parse_fc_res_cap(struct hinic3_hwdev *hwdev,
@@ -333,6 +350,28 @@ static void parse_ipsec_res_cap(struct hinic3_hwdev *hwdev,
dev_cap->ipsec_max_sactx, dev_cap->ipsec_max_cq);
}
+static void parse_vbs_res_cap(struct hinic3_hwdev *hwdev,
+ struct service_cap *cap,
+ struct cfg_cmd_dev_cap *dev_cap,
+ enum func_type type)
+{
+ struct vbs_service_cap *vbs_cap = &cap->vbs_cap;
+
+ vbs_cap->vbs_max_volq = dev_cap->vbs_max_volq;
+ vbs_cap->vbs_main_pf_enable = dev_cap->vbs_main_pf_enable;
+ vbs_cap->vbs_vsock_pf_enable = dev_cap->vbs_vsock_pf_enable;
+ vbs_cap->vbs_fushion_queue_pf_enable = dev_cap->vbs_fushion_queue_pf_enable;
+
+ sdk_info(hwdev->dev_hdl,
+ "Get VBS resource capbility, vbs_max_volq: 0x%x\n",
+ dev_cap->vbs_max_volq);
+ sdk_info(hwdev->dev_hdl,
+ "Get VBS pf info, vbs_main_pf_enable: 0x%x, vbs_vsock_pf_enable: 0x%x, vbs_fushion_queue_pf_enable: 0x%x\n",
+ dev_cap->vbs_main_pf_enable,
+ dev_cap->vbs_vsock_pf_enable,
+ dev_cap->vbs_fushion_queue_pf_enable);
+}
+
static void parse_dev_cap(struct hinic3_hwdev *dev,
struct cfg_cmd_dev_cap *dev_cap, enum func_type type)
{
@@ -375,6 +414,9 @@ static void parse_dev_cap(struct hinic3_hwdev *dev,
if (IS_PPA_TYPE(dev))
parse_ppa_res_cap(dev, cap, dev_cap, type);
+
+ if (IS_VBS_TYPE(dev))
+ parse_vbs_res_cap(dev, cap, dev_cap, type);
}
static int get_cap_from_fw(struct hinic3_hwdev *dev, enum func_type type)
@@ -404,6 +446,23 @@ static int get_cap_from_fw(struct hinic3_hwdev *dev, enum func_type type)
return 0;
}
+u8 hinic3_get_bond_create_mode(void *dev)
+{
+ struct hinic3_hwdev *hwdev = NULL;
+ struct service_cap *cap = NULL;
+
+ if (!dev) {
+ pr_err("pointer dev is NULL\n");
+ return -EINVAL;
+ }
+
+ hwdev = (struct hinic3_hwdev *)dev;
+ cap = &hwdev->cfg_mgmt->svc_cap;
+
+ return cap->bond_create_mode;
+}
+EXPORT_SYMBOL(hinic3_get_bond_create_mode);
+
int hinic3_get_dev_cap(void *dev)
{
enum func_type type;
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 671eed6..2f2310a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h
@@ -166,6 +166,11 @@ struct service_cap {
u8 srv_multi_host_mode;
u16 virtio_vq_size;
+ u8 hot_plug_disable;
+ u8 bond_create_mode;
+ u8 os_hot_replace;
+ u8 rsvd1;
+
u8 timer_pf_num;
u8 timer_pf_id_start;
u16 timer_vf_num;
@@ -335,5 +340,7 @@ void free_capability(struct hinic3_hwdev *dev);
int hinic3_init_vf_dev_cap(void *hwdev);
+u8 hinic3_get_bond_create_mode(void *dev);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c
index 8a87d25..8659e0b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c
@@ -21,6 +21,7 @@
#include "hinic3_hw_cfg.h"
#include "hinic3_cmdq.h"
#include "mpu_inband_cmd_defs.h"
+#include "vram_common.h"
#include "hinic3_hw_comm.h"
#define HINIC3_MSIX_CNT_LLI_TIMER_SHIFT 0
@@ -242,12 +243,19 @@ int hinic3_func_reset(void *dev, u16 func_id, u64 reset_flag, u16 channel)
struct hinic3_hwdev *hwdev = dev;
u16 out_size = sizeof(func_reset);
int err = 0;
+ int is_in_kexec;
if (!dev) {
pr_err("Invalid para: dev is null.\n");
return -EINVAL;
}
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ sdk_info(hwdev->dev_hdl, "Skip function reset!\n");
+ return 0;
+ }
+
sdk_info(hwdev->dev_hdl, "Function is reset, flag: 0x%llx, channel:0x%x\n",
reset_flag, channel);
@@ -554,7 +562,7 @@ EXPORT_SYMBOL(hinic3_set_ppf_flr_type);
int hinic3_set_ppf_tbl_hotreplace_flag(void *hwdev, u8 flag)
{
- struct comm_cmd_ppf_tbl_htrp_config htr_info = {0};
+ struct comm_cmd_ppf_tbl_htrp_config htr_info = {};
u16 out_size = sizeof(struct comm_cmd_ppf_tbl_htrp_config);
struct hinic3_hwdev *dev = hwdev;
int ret;
@@ -899,11 +907,19 @@ static int set_ppf_tmr_status(struct hinic3_hwdev *hwdev,
int hinic3_ppf_tmr_start(void *hwdev)
{
+ int is_in_kexec;
+
if (!hwdev) {
pr_err("Hwdev pointer is NULL for starting ppf timer\n");
return -EINVAL;
}
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ pr_info("Skip starting ppt timer during kexec");
+ return 0;
+ }
+
return set_ppf_tmr_status(hwdev, HINIC_PPF_TMR_FLAG_START);
}
EXPORT_SYMBOL(hinic3_ppf_tmr_start);
@@ -919,18 +935,114 @@ int hinic3_ppf_tmr_stop(void *hwdev)
}
EXPORT_SYMBOL(hinic3_ppf_tmr_stop);
+static int hi_vram_kalloc_align(struct hinic3_hwdev *hwdev, char *name,
+ u32 page_size, u32 page_num,
+ struct hinic3_dma_addr_align *mem_align)
+{
+ void *vaddr = NULL, *align_vaddr = NULL;
+ dma_addr_t paddr, align_paddr;
+ u64 real_size = page_size;
+ u64 align = page_size;
+
+ vaddr = (void *)hi_vram_kalloc(name, real_size);
+ if (!vaddr) {
+ sdk_err(hwdev->dev_hdl, "vram kalloc failed, name:%s.\n", name);
+ return -ENOMEM;
+ }
+
+ paddr = (dma_addr_t)virt_to_phys(vaddr);
+ align_paddr = ALIGN(paddr, align);
+ /* align */
+ if (align_paddr == paddr) {
+ align_vaddr = vaddr;
+ goto out;
+ }
+
+ hi_vram_kfree((void *)vaddr, name, real_size);
+
+ /* realloc memory for align */
+ real_size = page_size + align;
+ vaddr = (void *)hi_vram_kalloc(name, real_size);
+ if (!vaddr) {
+ sdk_err(hwdev->dev_hdl, "vram kalloc align failed, name:%s.\n", name);
+ return -ENOMEM;
+ }
+
+ paddr = (dma_addr_t)virt_to_phys(vaddr);
+ align_paddr = ALIGN(paddr, align);
+ align_vaddr = (void *)((u64)vaddr + (align_paddr - paddr));
+
+out:
+ mem_align->real_size = (u32)real_size;
+ mem_align->ori_vaddr = vaddr;
+ mem_align->ori_paddr = paddr;
+ mem_align->align_vaddr = align_vaddr;
+ mem_align->align_paddr = align_paddr;
+
+ return 0;
+}
+
+static void mqm_eqm_free_page_mem(struct hinic3_hwdev *hwdev)
+{
+ u32 i;
+ struct hinic3_dma_addr_align *page_addr;
+ int is_use_vram = get_use_vram_flag();
+ struct mqm_eqm_vram_name_s *mqm_eqm_vram_name = hwdev->mqm_eqm_vram_name;
+
+ page_addr = hwdev->mqm_att.brm_srch_page_addr;
+
+ for (i = 0; i < hwdev->mqm_att.page_num; i++) {
+ if (is_use_vram != 0) {
+ hi_vram_kfree(page_addr->ori_vaddr,
+ mqm_eqm_vram_name[i].vram_name,
+ page_addr->real_size);
+ } else {
+ hinic3_dma_free_coherent_align(hwdev->dev_hdl, page_addr);
+ }
+ page_addr->ori_vaddr = NULL;
+ page_addr++;
+ }
+
+ kfree(mqm_eqm_vram_name);
+ hwdev->mqm_eqm_vram_name = NULL;
+}
+
static int mqm_eqm_try_alloc_mem(struct hinic3_hwdev *hwdev, u32 page_size,
u32 page_num)
{
struct hinic3_dma_addr_align *page_addr = hwdev->mqm_att.brm_srch_page_addr;
+ int is_use_vram = get_use_vram_flag();
+ struct mqm_eqm_vram_name_s *mqm_eqm_vram_name = NULL;
u32 valid_num = 0;
u32 flag = 1;
u32 i = 0;
int err;
+ u16 func_id;
+
+ mqm_eqm_vram_name = kcalloc(page_num, sizeof(struct mqm_eqm_vram_name_s), GFP_KERNEL);
+ if (!mqm_eqm_vram_name)
+ return -ENOMEM;
+
+ hwdev->mqm_eqm_vram_name = mqm_eqm_vram_name;
+ func_id = hinic3_global_func_id(hwdev);
for (i = 0; i < page_num; i++) {
- err = hinic3_dma_zalloc_coherent_align(hwdev->dev_hdl, page_size,
- page_size, GFP_KERNEL, page_addr);
+ if (is_use_vram != 0) {
+ snprintf(mqm_eqm_vram_name[i].vram_name,
+ VRAM_NAME_MAX_LEN, "%s%hu%s%u",
+ VRAM_CQM_GLB_FUNC_BASE, func_id,
+ VRAM_NIC_MQM, i);
+ err = hi_vram_kalloc_align(hwdev,
+ mqm_eqm_vram_name[i].vram_name,
+ page_size, page_num,
+ page_addr);
+ } else {
+ err = hinic3_dma_zalloc_coherent_align(hwdev->dev_hdl,
+ page_size,
+ page_size,
+ GFP_KERNEL,
+ page_addr);
+ }
if (err) {
flag = 0;
break;
@@ -939,15 +1051,12 @@ static int mqm_eqm_try_alloc_mem(struct hinic3_hwdev *hwdev, u32 page_size,
page_addr++;
}
+ hwdev->mqm_att.page_num = valid_num;
+
if (flag == 1) {
hwdev->mqm_att.page_size = page_size;
- hwdev->mqm_att.page_num = page_num;
} else {
- page_addr = hwdev->mqm_att.brm_srch_page_addr;
- for (i = 0; i < valid_num; i++) {
- hinic3_dma_free_coherent_align(hwdev->dev_hdl, page_addr);
- page_addr++;
- }
+ mqm_eqm_free_page_mem(hwdev);
return -EFAULT;
}
@@ -986,19 +1095,6 @@ static int mqm_eqm_alloc_page_mem(struct hinic3_hwdev *hwdev)
return ret;
}
-static void mqm_eqm_free_page_mem(struct hinic3_hwdev *hwdev)
-{
- u32 i;
- struct hinic3_dma_addr_align *page_addr;
-
- page_addr = hwdev->mqm_att.brm_srch_page_addr;
-
- for (i = 0; i < hwdev->mqm_att.page_num; i++) {
- hinic3_dma_free_coherent_align(hwdev->dev_hdl, page_addr);
- page_addr++;
- }
-}
-
static int mqm_eqm_set_cfg_2_hw(struct hinic3_hwdev *hwdev, u8 valid)
{
struct comm_cmd_eqm_cfg info_eqm_cfg;
@@ -1129,6 +1225,7 @@ static int mqm_eqm_init(struct hinic3_hwdev *hwdev)
{
struct comm_cmd_get_eqm_num info_eqm_fix;
int ret;
+ int is_in_kexec;
if (hwdev->hwif->attr.func_type != TYPE_PPF)
return 0;
@@ -1158,10 +1255,16 @@ static int mqm_eqm_init(struct hinic3_hwdev *hwdev)
goto err_page;
}
- ret = mqm_eqm_set_page_2_hw(hwdev);
- if (ret) {
- sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n");
- goto err_ecmd;
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec == 0) {
+ ret = mqm_eqm_set_page_2_hw(hwdev);
+ if (ret) {
+ sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n");
+ goto err_ecmd;
+ }
+ } else {
+ sdk_info(hwdev->dev_hdl,
+ "Mqm db don't set to chip when os hot replace.\r\n");
}
ret = mqm_eqm_set_cfg_2_hw(hwdev, 1);
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c
index e8aa7ef..722fecd 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c
@@ -252,97 +252,6 @@ static u32 get_up_timeout_val(enum hinic3_mod_type mod, u16 cmd)
return 0; /* use default mbox/apichain timeout time */
}
-static int api_csr_read(void *hwdev, struct msg_module *nt_msg,
- void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
-{
- struct up_log_msg_st *up_log_msg = (struct up_log_msg_st *)buf_in;
- u8 *buf_out_tmp = (u8 *)buf_out;
- int ret = 0;
- u32 rd_len;
- u32 rd_addr;
- u32 rd_cnt = 0;
- u32 offset = 0;
- u8 node_id;
- u32 i;
-
- if (!buf_in || !buf_out || in_size != sizeof(*up_log_msg) ||
- *out_size != up_log_msg->rd_len || up_log_msg->rd_len % DW_WIDTH != 0)
- return -EINVAL;
-
- rd_len = up_log_msg->rd_len;
- rd_addr = up_log_msg->addr;
- node_id = (u8)nt_msg->mpu_cmd.mod;
-
- rd_cnt = rd_len / DW_WIDTH;
-
- for (i = 0; i < rd_cnt; i++) {
- ret = hinic3_api_csr_rd32(hwdev, node_id,
- rd_addr + offset,
- (u32 *)(buf_out_tmp + offset));
- if (ret) {
- pr_err("Csr rd fail, err: %d, node_id: %u, csr addr: 0x%08x\n",
- ret, node_id, rd_addr + offset);
- return ret;
- }
- offset += DW_WIDTH;
- }
- *out_size = rd_len;
-
- return ret;
-}
-
-static int api_csr_write(void *hwdev, struct msg_module *nt_msg,
- void *buf_in, u32 in_size, void *buf_out,
- u32 *out_size)
-{
- struct csr_write_st *csr_write_msg = (struct csr_write_st *)buf_in;
- int ret = 0;
- u32 rd_len;
- u32 rd_addr;
- u32 rd_cnt = 0;
- u32 offset = 0;
- u8 node_id;
- u32 i;
- u8 *data = NULL;
-
- if (!buf_in || in_size != sizeof(*csr_write_msg) || csr_write_msg->rd_len == 0 ||
- csr_write_msg->rd_len > API_CSR_MAX_RD_LEN || csr_write_msg->rd_len % DW_WIDTH != 0)
- return -EINVAL;
-
- rd_len = csr_write_msg->rd_len;
- rd_addr = csr_write_msg->addr;
- node_id = (u8)nt_msg->mpu_cmd.mod;
-
- rd_cnt = rd_len / DW_WIDTH;
-
- data = kzalloc(rd_len, GFP_KERNEL);
- if (!data)
- return -EFAULT;
-
- if (copy_from_user(data, (void *)csr_write_msg->data, rd_len)) {
- pr_err("Copy information from user failed\n");
- kfree(data);
- return -EFAULT;
- }
-
- for (i = 0; i < rd_cnt; i++) {
- ret = hinic3_api_csr_wr32(hwdev, node_id,
- rd_addr + offset,
- *((u32 *)(data + offset)));
- if (ret) {
- pr_err("Csr wr fail, ret: %d, node_id: %u, csr addr: 0x%08x\n",
- ret, rd_addr + offset, node_id);
- kfree(data);
- return ret;
- }
- offset += DW_WIDTH;
- }
-
- *out_size = 0;
- kfree(data);
- return ret;
-}
-
int send_to_mpu(void *hwdev, struct msg_module *nt_msg,
void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
{
@@ -369,10 +278,8 @@ int send_to_mpu(void *hwdev, struct msg_module *nt_msg,
return ret;
}
} else if (nt_msg->mpu_cmd.api_type == API_TYPE_API_CHAIN_BYPASS) {
- if (nt_msg->mpu_cmd.cmd == API_CSR_WRITE)
- return api_csr_write(hwdev, nt_msg, buf_in, in_size, buf_out, out_size);
-
- ret = api_csr_read(hwdev, nt_msg, buf_in, in_size, buf_out, out_size);
+ pr_err("Unsupported api_type %u\n", nt_msg->mpu_cmd.api_type);
+ return -EINVAL;
} else if (nt_msg->mpu_cmd.api_type == API_TYPE_API_CHAIN_TO_MPU) {
timeout = get_up_timeout_val(mod, cmd);
if (hinic3_pcie_itf_id(hwdev) != SPU_HOST_ID)
@@ -439,6 +346,23 @@ static int sm_rd16(void *hwdev, u32 id, u8 instance,
return ret;
}
+static int sm_rd16_clear(void *hwdev, u32 id, u8 instance,
+ u8 node, struct sm_out_st *buf_out)
+{
+ u16 val1;
+ int ret;
+
+ ret = hinic3_sm_ctr_rd16_clear(hwdev, node, instance, id, &val1);
+ if (ret != 0) {
+ pr_err("Get sm ctr clear information (16 bits)failed!\n");
+ val1 = 0xffff;
+ }
+
+ buf_out->val1 = val1;
+
+ return ret;
+}
+
static int sm_rd32(void *hwdev, u32 id, u8 instance,
u8 node, struct sm_out_st *buf_out)
{
@@ -558,6 +482,7 @@ const struct sm_module_handle sm_module_cmd_handle[] = {
{SM_CTR_RD32, sm_rd32},
{SM_CTR_RD64_PAIR, sm_rd64_pair},
{SM_CTR_RD64, sm_rd64},
+ {SM_CTR_RD16_CLEAR, sm_rd16_clear},
{SM_CTR_RD32_CLEAR, sm_rd32_clear},
{SM_CTR_RD64_PAIR_CLEAR, sm_rd64_pair_clear},
{SM_CTR_RD64_CLEAR, sm_rd64_clear}
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c
index 83e7b63..c317f4a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c
@@ -101,6 +101,12 @@ enum hinic3_pcie_tph {
#define SLAVE_HOST_STATUS_SET(host_id, enable) (((u8)(enable) & 1U) << (host_id))
#define SLAVE_HOST_STATUS_GET(host_id, val) (!!((val) & (1U << (host_id))))
+#ifdef HAVE_HOT_REPLACE_FUNC
+ extern int get_partition_id(void);
+#else
+ static int get_partition_id(void) {return 0; }
+#endif
+
void set_slave_host_enable(void *hwdev, u8 host_id, bool enable)
{
u32 reg_val;
@@ -207,6 +213,27 @@ static void hinic3_init_host_mode_pre(struct hinic3_hwdev *hwdev)
}
}
+static void hinic3_init_hot_plug_status(struct hinic3_hwdev *hwdev)
+{
+ struct service_cap *cap = &hwdev->cfg_mgmt->svc_cap;
+
+ if (cap->hot_plug_disable)
+ hwdev->hot_plug_mode = HOT_PLUG_DISABLE;
+ else
+ hwdev->hot_plug_mode = HOT_PLUG_ENABLE;
+}
+
+static void hinic3_init_os_hot_replace(struct hinic3_hwdev *hwdev)
+{
+ struct service_cap *cap = &hwdev->cfg_mgmt->svc_cap;
+
+ if (cap->os_hot_replace) {
+ hwdev->hot_replace_mode = HOT_REPLACE_ENABLE;
+ } else {
+ hwdev->hot_replace_mode = HOT_REPLACE_DISABLE;
+ }
+}
+
static u8 hinic3_nic_sw_aeqe_handler(void *hwdev, u8 event, u8 *data)
{
struct hinic3_hwdev *dev = hwdev;
@@ -270,14 +297,20 @@ static void chip_fault_show(struct hinic3_hwdev *hwdev,
"fatal", "reset", "host", "flr", "general", "suggestion"};
char level_str[FAULT_SHOW_STR_LEN + 1];
u8 level;
+ int ret;
memset(level_str, 0, FAULT_SHOW_STR_LEN + 1);
level = event->event.chip.err_level;
- if (level < FAULT_LEVEL_MAX)
- strscpy(level_str, fault_level[level],
- FAULT_SHOW_STR_LEN);
- else
- strscpy(level_str, "Unknown", FAULT_SHOW_STR_LEN);
+ if (level < FAULT_LEVEL_MAX) {
+ ret = strscpy(level_str, fault_level[level],
+ FAULT_SHOW_STR_LEN);
+ if (ret < 0)
+ return;
+ } else {
+ ret = strscpy(level_str, "Unknown", FAULT_SHOW_STR_LEN);
+ if (ret < 0)
+ return;
+ }
if (level == FAULT_LEVEL_SERIOUS_FLR)
dev_err(hwdev->dev_hdl, "err_level: %u [%s], flr func_id: %u\n",
@@ -299,6 +332,7 @@ static void fault_report_show(struct hinic3_hwdev *hwdev,
"reg rd timeout", "reg wr timeout", "phy fault", "tsensor fault"};
char type_str[FAULT_SHOW_STR_LEN + 1] = {0};
struct fault_event_stats *fault = NULL;
+ int ret;
sdk_err(hwdev->dev_hdl, "Fault event report received, func_id: %u\n",
hinic3_global_func_id(hwdev));
@@ -306,10 +340,14 @@ static void fault_report_show(struct hinic3_hwdev *hwdev,
fault = &hwdev->hw_stats.fault_event_stats;
if (event->type < FAULT_TYPE_MAX) {
- strscpy(type_str, fault_type[event->type], sizeof(type_str));
+ ret = strscpy(type_str, fault_type[event->type], sizeof(type_str));
+ if (ret < 0)
+ return;
atomic_inc(&fault->fault_type_stat[event->type]);
} else {
- strscpy(type_str, "Unknown", sizeof(type_str));
+ ret = strscpy(type_str, "Unknown", sizeof(type_str));
+ if (ret < 0)
+ return;
}
sdk_err(hwdev->dev_hdl, "Fault type: %u [%s]\n", event->type, type_str);
@@ -1536,15 +1574,29 @@ int hinic3_init_hwdev(struct hinic3_init_para *para)
hinic3_init_host_mode_pre(hwdev);
+ hinic3_init_hot_plug_status(hwdev);
+
+ hinic3_init_os_hot_replace(hwdev);
+
err = hinic3_multi_host_mgmt_init(hwdev);
if (err != 0) {
sdk_err(hwdev->dev_hdl, "Failed to init function mode\n");
goto init_multi_host_fail;
}
- err = hinic3_init_ppf_work(hwdev);
- if (err != 0)
- goto init_ppf_work_fail;
+ // hot_replace_mode is enable, run ppf function only when partition_id is 0
+ // or run ppf function directly
+ if (hwdev->hot_replace_mode == HOT_REPLACE_ENABLE) {
+ if (get_partition_id() == 0) {
+ err = hinic3_init_ppf_work(hwdev);
+ if (err != 0)
+ goto init_ppf_work_fail;
+ }
+ } else {
+ err = hinic3_init_ppf_work(hwdev);
+ if (err != 0)
+ goto init_ppf_work_fail;
+ }
err = hinic3_set_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD);
if (err != 0) {
@@ -1948,6 +2000,19 @@ void hinic3_link_event_stats(void *dev, u8 link)
}
EXPORT_SYMBOL(hinic3_link_event_stats);
+int hinic3_get_link_event_stats(void *dev, int *link_state)
+{
+ struct hinic3_hwdev *hwdev = dev;
+
+ if (!hwdev || !link_state)
+ return -EINVAL;
+
+ *link_state = hwdev->hw_stats.link_event_stats.link_down_stats.counter;
+
+ return 0;
+}
+EXPORT_SYMBOL(hinic3_get_link_event_stats);
+
u8 hinic3_max_pf_num(void *hwdev)
{
if (!hwdev)
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h
index b8a3356..0ca639f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h
@@ -10,6 +10,7 @@
#include "hinic3_hw.h"
#include "mpu_inband_cmd_defs.h"
#include "hinic3_profile.h"
+#include "vram_common.h"
struct cfg_mgmt_info;
@@ -82,6 +83,22 @@ enum hinic3_host_mode_e {
HINIC3_SDI_MODE_MAX,
};
+enum hinic3_hot_plug_mode {
+ HOT_PLUG_ENABLE,
+ HOT_PLUG_DISABLE,
+};
+
+enum hinic3_os_hot_replace_mode {
+ HOT_REPLACE_DISABLE,
+ HOT_REPLACE_ENABLE,
+};
+
+#define UNSUPPORT_HOT_PLUG(hwdev) \
+ ((hwdev)->hot_plug_mode == HOT_PLUG_DISABLE)
+
+#define SUPPORT_HOT_PLUG(hwdev) \
+ ((hwdev)->hot_plug_mode == HOT_PLUG_ENABLE)
+
#define MULTI_HOST_CHIP_MODE_SHIFT 0
#define MULTI_HOST_MASTER_MBX_STS_SHIFT 17
#define MULTI_HOST_PRIV_DATA_SHIFT 0x8
@@ -100,6 +117,10 @@ enum hinic3_host_mode_e {
((val) & (~(MULTI_HOST_##member##_MASK \
<< MULTI_HOST_##member##_SHIFT)))
+struct mqm_eqm_vram_name_s {
+ char vram_name[VRAM_NAME_MAX_LEN];
+};
+
struct hinic3_hwdev {
void *adapter_hdl; /* pointer to hinic3_pcidev or NDIS_Adapter */
void *pcidev_hdl; /* pointer to pcidev or Handler */
@@ -138,6 +159,9 @@ struct hinic3_hwdev {
u32 rsvd2;
struct hinic3_multi_host_mgmt *mhost_mgmt;
+ char mhost_mgmt_name[VRAM_NAME_MAX_LEN];
+
+ struct mqm_eqm_vram_name_s *mqm_eqm_vram_name;
struct mutex stateful_mutex; /* protect cqm init and deinit */
@@ -170,6 +194,8 @@ struct hinic3_hwdev {
struct hinic3_devlink *devlink_dev;
enum hinic3_func_mode func_mode;
+ enum hinic3_hot_plug_mode hot_plug_mode;
+ enum hinic3_os_hot_replace_mode hot_replace_mode;
u32 rsvd3;
DECLARE_BITMAP(func_probe_in_host, MAX_FUNCTION_NUM);
@@ -179,7 +205,10 @@ struct hinic3_hwdev {
u64 last_recv_aeq_cnt;
u16 aeq_busy_cnt;
- u64 rsvd4[8];
+ u64 mbox_send_cnt;
+ u64 mbox_ack_cnt;
+
+ u64 rsvd4[5];
u8 cmdq_mode;
};
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c
index 33f1210..8590f70 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c
@@ -544,6 +544,7 @@ static void free_db_area(struct hinic3_free_db_area *free_db_area)
{
spin_lock_deinit(&free_db_area->idx_lock);
kfree(free_db_area->db_bitmap_array);
+ free_db_area->db_bitmap_array = NULL;
}
static int get_db_idx(struct hinic3_hwif *hwif, u32 *idx)
@@ -841,6 +842,7 @@ void hinic3_free_hwif(struct hinic3_hwdev *hwdev)
free_db_area(&hwdev->hwif->free_db_area);
enable_all_msix(hwdev);
kfree(hwdev->hwif);
+ hwdev->hwif = NULL;
}
u16 hinic3_global_func_id(void *hwdev)
@@ -856,6 +858,44 @@ u16 hinic3_global_func_id(void *hwdev)
}
EXPORT_SYMBOL(hinic3_global_func_id);
+/**
+ * get function id from register,used by sriov hot migration process
+ * @hwdev: the pointer to hw device
+ */
+u16 hinic3_global_func_id_hw(void *hwdev)
+{
+ u32 addr, attr0;
+ struct hinic3_hwdev *dev;
+
+ dev = (struct hinic3_hwdev *)hwdev;
+ addr = HINIC3_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hinic3_hwif_read_reg(dev->hwif, addr);
+
+ return HINIC3_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+}
+
+/**
+ * get function id, used by sriov hot migratition process.
+ * @hwdev: the pointer to hw device
+ * @func_id: function id
+ */
+int hinic3_global_func_id_get(void *hwdev, u16 *func_id)
+{
+ struct hinic3_hwdev *dev = (struct hinic3_hwdev *)hwdev;
+
+ if (!hwdev || !func_id)
+ return -EINVAL;
+
+ /* only vf get func_id from chip reg for sriov migrate */
+ if (!HINIC3_IS_VF(dev)) {
+ *func_id = hinic3_global_func_id(hwdev);
+ return 0;
+ }
+
+ *func_id = hinic3_global_func_id_hw(dev);
+ return 0;
+}
+
u16 hinic3_intr_num(void *hwdev)
{
struct hinic3_hwif *hwif = NULL;
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c
index 6ab1b92..b7f9db5 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c
@@ -16,6 +16,7 @@
#include <linux/rtc.h>
#include <linux/aer.h>
#include <linux/debugfs.h>
+#include <linux/notifier.h>
#include "ossl_knl.h"
#include "hinic3_mt.h"
@@ -26,13 +27,38 @@
#include "hinic3_dev_mgmt.h"
#include "hinic3_nictool.h"
#include "hinic3_hw.h"
+#include "hinic3_multi_host_mgmt.h"
+#include "hinic3_hw_cfg.h"
#include "hinic3_lld.h"
#include "hinic3_profile.h"
#include "hinic3_hwdev.h"
#include "hinic3_prof_adap.h"
-#include "comm_msg_intf.h"
+#include "hinic3_devlink.h"
+#include "vram_common.h"
+
+enum partition_dev_type {
+ PARTITION_DEV_NONE = 0,
+ PARTITION_DEV_SHARED,
+ PARTITION_DEV_EXCLUSIVE,
+ PARTITION_DEV_BACKUP,
+};
+
+#ifdef HAVE_HOT_REPLACE_FUNC
+static int vpci_set_partition_attrs(struct pci_dev *dev, unsigned int dev_type,
+ unsigned int partition_id);
+static int get_partition_id(void);
+#else
+static int vpci_set_partition_attrs(struct pci_dev *dev, unsigned int dev_type,
+ unsigned int partition_id)
+{
+ return 0;
+}
+static int get_partition_id(void) { return 0; }
+#endif
+
+static bool g_is_pf_migrated;
static bool disable_vf_load;
module_param(disable_vf_load, bool, 0444);
MODULE_PARM_DESC(disable_vf_load,
@@ -44,10 +70,12 @@ MODULE_PARM_DESC(disable_attach, "disable_attach or not - default is false");
#define HINIC3_WAIT_SRIOV_CFG_TIMEOUT 15000
-MODULE_AUTHOR("Huawei Technologies CO., Ltd");
-MODULE_DESCRIPTION(HINIC3_DRV_DESC);
-MODULE_VERSION(HINIC3_DRV_VERSION);
-MODULE_LICENSE("GPL");
+#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
+static DEVICE_ATTR_RW(sriov_numvfs, 0644,
+ sriov_numvfs_show, sriov_numvfs_store);
+static DEVICE_ATTR_RO(sriov_totalvfs, 0444,
+ sriov_totalvfs_show, NULL);
+#endif /* !(HAVE_SRIOV_CONFIGURE || HAVE_RHEL6_SRIOV_CONFIGURE) */
static struct attribute *hinic3_attributes[] = {
#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
@@ -64,7 +92,18 @@ static const struct attribute_group hinic3_attr_group = {
struct hinic3_uld_info g_uld_info[SERVICE_T_MAX] = { {0} };
#define HINIC3_EVENT_PROCESS_TIMEOUT 10000
+#define HINIC3_WAIT_EVENT_PROCESS_TIMEOUT 100
struct mutex g_uld_mutex; /* g_uld_info lock */
+#define BUS_MAX_DEV_NUM 256
+#define HINIC3_SLAVE_WORK_MAX_NUM 20
+
+struct vf_offset_info {
+ u8 valid;
+ u16 vf_offset_from_pf[CMD_MAX_MAX_PF_NUM];
+};
+
+static struct vf_offset_info g_vf_offset;
+DEFINE_MUTEX(g_vf_offset_lock);
void hinic3_uld_lock_init(void)
{
@@ -73,13 +112,23 @@ 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", "bifur", "custom"};
+ "fc", "vbs", "ipsec", "virtio", "migrate",
+ "ppa", "custom", "vroce", "crypt", "vsock", "bifur"};
const char **hinic3_get_uld_names(void)
{
return s_uld_name;
}
+#ifdef CONFIG_PCI_IOV
+static int hinic3_get_pf_device_id(struct pci_dev *pdev)
+{
+ struct pci_dev *pf_dev = pci_physfn(pdev);
+
+ return pf_dev->device;
+}
+#endif
+
static int attach_uld(struct hinic3_pcidev *dev, enum hinic3_service_type type,
const struct hinic3_uld_info *uld_info)
{
@@ -98,6 +147,10 @@ static int attach_uld(struct hinic3_pcidev *dev, enum hinic3_service_type type,
atomic_set(&dev->uld_ref_cnt[type], 0);
+ if (!uld_info->probe) {
+ err = 0;
+ goto out_unlock;
+ }
err = uld_info->probe(&dev->lld_dev, &uld_dev, dev->uld_dev_name[type]);
if (err) {
sdk_err(&dev->pcidev->dev,
@@ -166,6 +219,10 @@ static void detach_uld(struct hinic3_pcidev *dev,
wait_uld_unused(dev, type);
+ if (!uld_info->remove) {
+ mutex_unlock(&dev->pdev_mutex);
+ return;
+ }
uld_info->remove(&dev->lld_dev, dev->uld_dev[type]);
dev->uld_dev[type] = NULL;
@@ -182,11 +239,14 @@ static void attach_ulds(struct hinic3_pcidev *dev)
{
enum hinic3_service_type type;
struct pci_dev *pdev = dev->pcidev;
+ int is_in_kexec = vram_get_kexec_flag();
+
+ if (is_in_kexec == 0)
+ lld_hold();
- lld_hold();
mutex_lock(&g_uld_mutex);
- for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) {
+ for (type = SERVICE_T_OVS; type < SERVICE_T_MAX; type++) {
if (g_uld_info[type].probe) {
if (pdev->is_virtfn &&
(!hinic3_get_vf_service_load(pdev, (u16)type))) {
@@ -198,7 +258,9 @@ static void attach_ulds(struct hinic3_pcidev *dev)
}
}
mutex_unlock(&g_uld_mutex);
- lld_put();
+
+ if (is_in_kexec == 0)
+ lld_put();
}
static void detach_ulds(struct hinic3_pcidev *dev)
@@ -305,7 +367,7 @@ void hinic3_unregister_uld(enum hinic3_service_type type)
}
uld_info = &g_uld_info[type];
- memset(uld_info, 0, sizeof(*uld_info));
+ memset(uld_info, 0, sizeof(struct hinic3_uld_info));
mutex_unlock(&g_uld_mutex);
lld_put();
}
@@ -359,6 +421,26 @@ void hinic3_detach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_ser
}
EXPORT_SYMBOL(hinic3_detach_service);
+void hinic3_module_get(void *hwdev, enum hinic3_service_type type)
+{
+ struct hinic3_hwdev *dev = hwdev;
+
+ if (!dev || type >= SERVICE_T_MAX)
+ return;
+ __module_get(THIS_MODULE);
+}
+EXPORT_SYMBOL(hinic3_module_get);
+
+void hinic3_module_put(void *hwdev, enum hinic3_service_type type)
+{
+ struct hinic3_hwdev *dev = hwdev;
+
+ if (!dev || type >= SERVICE_T_MAX)
+ return;
+ module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL(hinic3_module_put);
+
static void hinic3_sync_time_to_fmw(struct hinic3_pcidev *pdev_pri)
{
struct timeval tv = {0};
@@ -441,23 +523,445 @@ static void send_event_to_all_pf(struct hinic3_pcidev *dev,
lld_put();
}
+u32 hinic3_pdev_is_virtfn(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PCI_IOV
+ return pdev->is_virtfn;
+#else
+ return 0;
+#endif
+}
+
+static int hinic3_get_function_enable(struct pci_dev *pdev, bool *en)
+{
+ struct pci_dev *pf_pdev = pdev->physfn;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ void *pf_hwdev = NULL;
+ u16 global_func_id;
+ int err;
+
+ /* PF in host os or function in guest os, probe sdk in default */
+ if (!hinic3_pdev_is_virtfn(pdev) || !pf_pdev) {
+ *en = true;
+ return 0;
+ }
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter || !pci_adapter->hwdev) {
+ /* vf in host and pf sdk not probed */
+ return -EFAULT;
+ }
+ pf_hwdev = pci_adapter->hwdev;
+
+ err = hinic3_get_vfid_by_vfpci(NULL, pdev, &global_func_id);
+ if (err) {
+ sdk_err(&pci_adapter->pcidev->dev,
+ "Func hinic3_get_vfid_by_vfpci fail %d\n", err);
+ return err;
+ }
+
+ err = hinic3_get_func_nic_enable(pf_hwdev, global_func_id, en);
+ if (!!err) {
+ sdk_info(&pdev->dev, "Failed to get function nic status, err %d.\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+int hinic3_set_func_probe_in_host(void *hwdev, u16 func_id, bool probe)
+{
+ struct hinic3_hwdev *dev = hwdev;
+
+ if (hinic3_func_type(hwdev) != TYPE_PPF)
+ return -EINVAL;
+
+ if (probe)
+ set_bit(func_id, dev->func_probe_in_host);
+ else
+ clear_bit(func_id, dev->func_probe_in_host);
+
+ return 0;
+}
+
+bool hinic3_get_func_probe_in_host(void *hwdev, u16 func_id)
+{
+ struct hinic3_hwdev *dev = hwdev;
+ struct hinic3_hwdev *ppf_dev = NULL;
+ bool probed = false;
+
+ if (!hwdev)
+ return false;
+
+ down(&dev->ppf_sem);
+ ppf_dev = hinic3_get_ppf_hwdev_by_pdev(dev->pcidev_hdl);
+ if (!ppf_dev || hinic3_func_type(ppf_dev) != TYPE_PPF) {
+ up(&dev->ppf_sem);
+ return false;
+ }
+
+ probed = !!test_bit(func_id, ppf_dev->func_probe_in_host);
+ up(&dev->ppf_sem);
+
+ return probed;
+}
+
+void *hinic3_get_ppf_hwdev_by_pdev(struct pci_dev *pdev)
+{
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *dev = NULL;
+
+ if (!pdev)
+ return NULL;
+
+ pci_adapter = pci_get_drvdata(pdev);
+ if (!pci_adapter)
+ return NULL;
+
+ chip_node = pci_adapter->chip_node;
+ lld_dev_hold(&pci_adapter->lld_dev);
+ list_for_each_entry(dev, &chip_node->func_list, node) {
+ if (dev->lld_state == HINIC3_IN_REMOVE)
+ continue;
+
+ if (dev->hwdev && hinic3_func_type(dev->hwdev) == TYPE_PPF) {
+ lld_dev_put(&pci_adapter->lld_dev);
+ return dev->hwdev;
+ }
+ }
+ lld_dev_put(&pci_adapter->lld_dev);
+
+ return NULL;
+}
+
+static int hinic3_set_vf_nic_used_state(void *hwdev, u16 func_id, bool opened)
+{
+ struct hinic3_hwdev *dev = hwdev;
+ struct hinic3_hwdev *ppf_dev = NULL;
+
+ if (!dev || func_id >= MAX_FUNCTION_NUM)
+ return -EINVAL;
+
+ down(&dev->ppf_sem);
+ ppf_dev = hinic3_get_ppf_hwdev_by_pdev(dev->pcidev_hdl);
+ if (!ppf_dev || hinic3_func_type(ppf_dev) != TYPE_PPF) {
+ up(&dev->ppf_sem);
+ return -EINVAL;
+ }
+
+ if (opened)
+ set_bit(func_id, ppf_dev->netdev_setup_state);
+ else
+ clear_bit(func_id, ppf_dev->netdev_setup_state);
+
+ up(&dev->ppf_sem);
+
+ return 0;
+}
+
+static void set_vf_func_in_use(struct pci_dev *pdev, bool in_use)
+{
+ struct pci_dev *pf_pdev = pdev->physfn;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ void *pf_hwdev = NULL;
+ u16 global_func_id;
+
+ /* only need to be set when VF is on the host */
+ if (!hinic3_pdev_is_virtfn(pdev) || !pf_pdev)
+ return;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter || !pci_adapter->hwdev)
+ return;
+
+ pf_hwdev = pci_adapter->hwdev;
+
+ global_func_id = (u16)pdev->devfn + hinic3_glb_pf_vf_offset(pf_hwdev);
+ (void)hinic3_set_vf_nic_used_state(pf_hwdev, global_func_id, in_use);
+}
+
+static int hinic3_pf_get_vf_offset_info(struct hinic3_pcidev *des_dev, u16 *vf_offset)
+{
+ int err, i;
+ struct hinic3_hw_pf_infos *pf_infos = NULL;
+ u16 pf_func_id;
+ struct hinic3_pcidev *pf_pci_adapter = NULL;
+
+ pf_pci_adapter = (hinic3_pdev_is_virtfn(des_dev->pcidev)) ?
+ pci_get_drvdata(des_dev->pcidev->physfn) : des_dev;
+ pf_func_id = hinic3_global_func_id(pf_pci_adapter->hwdev);
+ if (pf_func_id >= CMD_MAX_MAX_PF_NUM || !vf_offset)
+ return -EINVAL;
+
+ mutex_lock(&g_vf_offset_lock);
+ if (g_vf_offset.valid == 0) {
+ pf_infos = kzalloc(sizeof(*pf_infos), GFP_KERNEL);
+ if (!pf_infos) {
+ err = -ENOMEM;
+ goto err_malloc;
+ }
+
+ err = hinic3_get_hw_pf_infos(pf_pci_adapter->hwdev,
+ pf_infos, HINIC3_CHANNEL_COMM);
+ if (err) {
+ sdk_warn(&pf_pci_adapter->pcidev->dev,
+ "Hinic3_get_hw_pf_infos fail err %d\n", err);
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ g_vf_offset.valid = 1;
+ for (i = 0; i < CMD_MAX_MAX_PF_NUM; i++)
+ g_vf_offset.vf_offset_from_pf[i] = pf_infos->infos[i].vf_offset;
+
+ kfree(pf_infos);
+ }
+
+ *vf_offset = g_vf_offset.vf_offset_from_pf[pf_func_id];
+
+ mutex_unlock(&g_vf_offset_lock);
+
+ return 0;
+
+err_out:
+ kfree(pf_infos);
+err_malloc:
+ mutex_unlock(&g_vf_offset_lock);
+ return err;
+}
+
+static struct pci_dev *get_vf_pdev_by_pf(struct hinic3_pcidev *des_dev,
+ u16 func_id)
+{
+ int err;
+ u16 bus_num;
+ u16 vf_start, vf_end;
+ u16 des_fn, pf_func_id, vf_offset;
+
+ vf_start = hinic3_glb_pf_vf_offset(des_dev->hwdev);
+ vf_end = vf_start + hinic3_func_max_vf(des_dev->hwdev);
+ pf_func_id = hinic3_global_func_id(des_dev->hwdev);
+ if (func_id <= vf_start || func_id > vf_end || pf_func_id >= CMD_MAX_MAX_PF_NUM)
+ return NULL;
+
+ err = hinic3_pf_get_vf_offset_info(des_dev, &vf_offset);
+ if (err) {
+ sdk_warn(&des_dev->pcidev->dev, "Hinic3_pf_get_vf_offset_info fail\n");
+ return NULL;
+ }
+
+ des_fn = ((func_id - vf_start) - 1) + pf_func_id + vf_offset;
+ bus_num = des_dev->pcidev->bus->number + des_fn / BUS_MAX_DEV_NUM;
+
+ return pci_get_domain_bus_and_slot(0, bus_num, (des_fn % BUS_MAX_DEV_NUM));
+}
+
+static struct hinic3_pcidev *get_des_pci_adapter(struct hinic3_pcidev *des_dev,
+ u16 func_id)
+{
+ struct pci_dev *des_pdev = NULL;
+ u16 vf_start, vf_end;
+ bool probe_in_host = false;
+
+ if (hinic3_global_func_id(des_dev->hwdev) == func_id)
+ return des_dev;
+
+ vf_start = hinic3_glb_pf_vf_offset(des_dev->hwdev);
+ vf_end = vf_start + hinic3_func_max_vf(des_dev->hwdev);
+ if (func_id <= vf_start || func_id > vf_end)
+ return NULL;
+
+ des_pdev = get_vf_pdev_by_pf(des_dev, func_id);
+ if (!des_pdev)
+ return NULL;
+
+ pci_dev_put(des_pdev);
+
+ probe_in_host = hinic3_get_func_probe_in_host(des_dev->hwdev, func_id);
+ if (!probe_in_host)
+ return NULL;
+
+ return pci_get_drvdata(des_pdev);
+}
+
+int __set_vroce_func_state(struct hinic3_pcidev *pci_adapter)
+{
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ u16 func_id;
+ int err;
+ u8 enable_vroce = false;
+
+ func_id = hinic3_global_func_id(pci_adapter->hwdev);
+
+ err = hinic3_get_func_vroce_enable(pci_adapter->hwdev,
+ func_id, &enable_vroce);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Failed to get vroce state.\n");
+ return err;
+ }
+
+ mutex_lock(&g_uld_mutex);
+
+ if (!!enable_vroce) {
+ if (!g_uld_info[SERVICE_T_ROCE].probe) {
+ sdk_info(&pdev->dev, "Uld(roce_info) has not been registered!\n");
+ mutex_unlock(&g_uld_mutex);
+ return 0;
+ }
+
+ err = attach_uld(pci_adapter, SERVICE_T_ROCE,
+ &g_uld_info[SERVICE_T_ROCE]);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Failed to initialize VROCE.\n");
+ mutex_unlock(&g_uld_mutex);
+ return err;
+ }
+ } else {
+ sdk_info(&pdev->dev, "Func %u vroce state: disable.\n", func_id);
+ if (g_uld_info[SERVICE_T_ROCE].remove)
+ detach_uld(pci_adapter, SERVICE_T_ROCE);
+ }
+
+ mutex_unlock(&g_uld_mutex);
+
+ return 0;
+}
+
+void slave_host_mgmt_vroce_work(struct work_struct *work)
+{
+#ifndef __HIFC__
+ struct hinic3_pcidev *pci_adapter =
+ container_of(work, struct hinic3_pcidev, slave_vroce_work);
+
+ __set_vroce_func_state(pci_adapter);
+#endif
+}
+
+void *hinic3_get_roce_uld_by_pdev(struct pci_dev *pdev)
+{
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!pdev)
+ return NULL;
+
+ pci_adapter = pci_get_drvdata(pdev);
+ if (!pci_adapter)
+ return NULL;
+
+ return pci_adapter->uld_dev[SERVICE_T_ROCE];
+}
+
+static int func_service_state_process(struct hinic3_pcidev *event_dev,
+ struct hinic3_pcidev *des_dev,
+ struct hinic3_mhost_nic_func_state *state,
+ u16 cmd)
+{
+ int err = 0;
+ struct hinic3_hwdev *dev = (struct hinic3_hwdev *)event_dev->hwdev;
+
+ switch (cmd) {
+ case HINIC3_MHOST_GET_VROCE_STATE:
+ state->enable = hinic3_get_roce_uld_by_pdev(des_dev->pcidev) ? 1 : 0;
+ break;
+ case HINIC3_MHOST_NIC_STATE_CHANGE:
+ sdk_info(&des_dev->pcidev->dev, "Receive nic[%u] state changed event, state: %u\n",
+ state->func_idx, state->enable);
+ if (event_dev->multi_host_mgmt_workq) {
+ queue_work(event_dev->multi_host_mgmt_workq,
+ &des_dev->slave_nic_work);
+ } else {
+ sdk_err(&des_dev->pcidev->dev, "Can not schedule slave nic work\n");
+ err = -EFAULT;
+ }
+ break;
+ case HINIC3_MHOST_VROCE_STATE_CHANGE:
+ sdk_info(&des_dev->pcidev->dev, "Receive vroce[%u] state changed event, state: %u\n",
+ state->func_idx, state->enable);
+ queue_work_on(hisdk3_get_work_cpu_affinity(dev, WORK_TYPE_MBOX),
+ event_dev->multi_host_mgmt_workq,
+ &des_dev->slave_vroce_work);
+ break;
+ default:
+ sdk_warn(&des_dev->pcidev->dev,
+ "Service state process with unknown cmd: %u\n", cmd);
+ err = -EFAULT;
+ break;
+ }
+
+ return err;
+}
+
+static void multi_host_mgmt(struct hinic3_pcidev *dev,
+ struct hinic3_multi_host_mgmt_event *mhost_mgmt)
+{
+ struct hinic3_pcidev *cur_dev = NULL;
+ struct hinic3_pcidev *des_dev = NULL;
+ struct hinic3_mhost_nic_func_state *nic_state = NULL;
+ u16 sub_cmd = mhost_mgmt->sub_cmd;
+
+ switch (sub_cmd) {
+ case HINIC3_MHOST_GET_VROCE_STATE:
+ case HINIC3_MHOST_VROCE_STATE_CHANGE:
+ case HINIC3_MHOST_NIC_STATE_CHANGE:
+ nic_state = mhost_mgmt->data;
+ nic_state->status = 0;
+ if (!dev->hwdev)
+ return;
+
+ if (!IS_BMGW_SLAVE_HOST((struct hinic3_hwdev *)dev->hwdev))
+ return;
+
+ /* find func_idx pci_adapter and disable or enable nic */
+ lld_dev_hold(&dev->lld_dev);
+ list_for_each_entry(cur_dev, &dev->chip_node->func_list, node) {
+ if (cur_dev->lld_state == HINIC3_IN_REMOVE ||
+ hinic3_pdev_is_virtfn(cur_dev->pcidev))
+ continue;
+
+ des_dev = get_des_pci_adapter(cur_dev, nic_state->func_idx);
+ if (!des_dev)
+ continue;
+
+ if (func_service_state_process(dev, des_dev, nic_state, sub_cmd))
+ nic_state->status = 1;
+ break;
+ }
+ lld_dev_put(&dev->lld_dev);
+ break;
+ default:
+ sdk_warn(&dev->pcidev->dev, "Received unknown multi-host mgmt event: %u\n",
+ mhost_mgmt->sub_cmd);
+ break;
+ }
+}
+
static void hinic3_event_process(void *adapter, struct hinic3_event_info *event)
{
struct hinic3_pcidev *dev = adapter;
struct hinic3_fault_event *fault = (void *)event->event_data;
+ struct hinic3_multi_host_mgmt_event *mhost_event =
+ (void *)event->event_data;
u16 func_id;
- if ((event->service == EVENT_SRV_COMM && event->type == EVENT_COMM_FAULT) &&
- fault->fault_level == FAULT_LEVEL_SERIOUS_FLR &&
- fault->event.chip.func_id < hinic3_max_pf_num(dev->hwdev)) {
- func_id = fault->event.chip.func_id;
- return send_event_to_dst_pf(adapter, func_id, event);
- }
-
- if (event->type == EVENT_COMM_MGMT_WATCHDOG)
+ switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_MULTI_HOST_MGMT):
+ multi_host_mgmt(dev, mhost_event);
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_FAULT):
+ if (fault->fault_level == FAULT_LEVEL_SERIOUS_FLR &&
+ fault->event.chip.func_id < hinic3_max_pf_num(dev->hwdev)) {
+ func_id = fault->event.chip.func_id;
+ return send_event_to_dst_pf(adapter, func_id, event);
+ }
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_MGMT_WATCHDOG):
send_event_to_all_pf(adapter, event);
- else
+ break;
+ default:
send_uld_dev_event(adapter, event);
+ break;
+ }
}
static void uld_def_init(struct hinic3_pcidev *pci_adapter)
@@ -605,31 +1109,70 @@ static void hinic3_pci_deinit(struct pci_dev *pdev)
kfree(pci_adapter);
}
-#ifdef CONFIG_X86
-/**
- * cfg_order_reg - when cpu model is haswell or broadwell, should configure dma
- * order register to zero
- * @pci_adapter: pci_adapter
- **/
-/*lint -save -e40 */
-static void cfg_order_reg(struct hinic3_pcidev *pci_adapter)
+static void set_vf_load_state(struct pci_dev *pdev, struct hinic3_pcidev *pci_adapter)
{
- u8 cpu_model[] = {0x3c, 0x3f, 0x45, 0x46, 0x3d, 0x47, 0x4f, 0x56};
- struct cpuinfo_x86 *cpuinfo = NULL;
- u32 i;
+ /* In bm mode, slave host will load vfs in default */
+ if (IS_BMGW_SLAVE_HOST(((struct hinic3_hwdev *)pci_adapter->hwdev)) &&
+ hinic3_func_type(pci_adapter->hwdev) != TYPE_VF)
+ hinic3_set_vf_load_state(pdev, false);
- if (hinic3_func_type(pci_adapter->hwdev) == TYPE_VF)
- return;
+ if (!disable_attach) {
+ if ((hinic3_func_type(pci_adapter->hwdev) != TYPE_VF) &&
+ hinic3_is_bm_slave_host(pci_adapter->hwdev)) {
+ if (hinic3_func_max_vf(pci_adapter->hwdev) == 0) {
+ sdk_warn(&pdev->dev, "The sriov enabling process is skipped, vfs_num: 0.\n");
+ return;
+ }
+ hinic3_pci_sriov_enable(pdev,
+ hinic3_func_max_vf(pci_adapter->hwdev));
+ }
+ }
+}
- cpuinfo = &cpu_data(0);
- for (i = 0; i < sizeof(cpu_model); i++) {
- if (cpu_model[i] == cpuinfo->x86_model)
- hinic3_set_pcie_order_cfg(pci_adapter->hwdev);
+static void hinic3_init_ppf_hwdev(struct hinic3_hwdev *hwdev)
+{
+ if (!hwdev) {
+ pr_err("[%s:%d] null hwdev pointer\n", __FILE__, __LINE__);
+ return;
}
+
+ hwdev->ppf_hwdev = hinic3_get_ppf_hwdev_by_pdev(hwdev->pcidev_hdl);
}
-/*lint -restore*/
-#endif
+static int set_nic_func_state(struct hinic3_pcidev *pci_adapter)
+{
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ u16 func_id;
+ int err;
+ bool enable_nic = false;
+
+ func_id = hinic3_global_func_id(pci_adapter->hwdev);
+
+ err = hinic3_get_func_nic_enable(pci_adapter->hwdev, func_id, &enable_nic);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Failed to get nic state.\n");
+ return err;
+ }
+
+ if (!enable_nic) {
+ sdk_info(&pdev->dev, "Func %u nic state: disable.\n", func_id);
+ detach_uld(pci_adapter, SERVICE_T_NIC);
+ return 0;
+ }
+
+ if (IS_BMGW_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev))
+ (void)hinic3_init_vf_dev_cap(pci_adapter->hwdev);
+
+ if (g_uld_info[SERVICE_T_NIC].probe) {
+ err = attach_uld(pci_adapter, SERVICE_T_NIC, &g_uld_info[SERVICE_T_NIC]);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Initialize NIC failed\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adapter)
{
@@ -689,7 +1232,16 @@ static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adap
list_add_tail(&pci_adapter->node, &pci_adapter->chip_node->func_list);
lld_unlock_chip_node();
+ hinic3_init_ppf_hwdev((struct hinic3_hwdev *)pci_adapter->hwdev);
+
+ set_vf_load_state(pdev, pci_adapter);
+
if (!disable_attach) {
+ /* NIC is base driver, probe firstly */
+ err = set_nic_func_state(pci_adapter);
+ if (err)
+ goto set_nic_func_state_err;
+
attach_ulds(pci_adapter);
if (hinic3_func_type(pci_adapter->hwdev) != TYPE_VF) {
@@ -700,10 +1252,6 @@ static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adap
goto create_sysfs_err;
}
}
-
-#ifdef CONFIG_X86
- cfg_order_reg(pci_adapter);
-#endif
}
return 0;
@@ -711,6 +1259,7 @@ static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adap
create_sysfs_err:
detach_ulds(pci_adapter);
+set_nic_func_state_err:
lld_lock_chip_node();
list_del(&pci_adapter->node);
lld_unlock_chip_node();
@@ -759,6 +1308,7 @@ static void hinic3_func_deinit(struct pci_dev *pdev)
hinic3_free_stateful(pci_adapter->hwdev);
hinic3_free_hwdev(pci_adapter->hwdev);
+ pci_adapter->hwdev = NULL;
}
static void wait_sriov_cfg_complete(struct hinic3_pcidev *pci_adapter)
@@ -766,18 +1316,61 @@ static void wait_sriov_cfg_complete(struct hinic3_pcidev *pci_adapter)
struct hinic3_sriov_info *sriov_info;
unsigned long end;
- sriov_info = &pci_adapter->sriov_info;
- clear_bit(HINIC3_FUNC_PERSENT, &sriov_info->state);
- usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
+ sriov_info = &pci_adapter->sriov_info;
+ clear_bit(HINIC3_FUNC_PERSENT, &sriov_info->state);
+ usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
+
+ end = jiffies + msecs_to_jiffies(HINIC3_WAIT_SRIOV_CFG_TIMEOUT);
+ do {
+ if (!test_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state) &&
+ !test_bit(HINIC3_SRIOV_DISABLE, &sriov_info->state))
+ return;
+
+ usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
+ } while (time_before(jiffies, end));
+}
+
+static bool hinic3_get_vf_nic_en_status(struct pci_dev *pdev)
+{
+ bool nic_en = false;
+ u16 global_func_id;
+ struct pci_dev *pf_pdev = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!pdev) {
+ pr_err("pdev is null.\n");
+ return false;
+ }
+
+ if (pdev->is_virtfn)
+ pf_pdev = pdev->physfn;
+ else
+ return false;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_err(&pdev->dev, "pci_adapter is null.\n");
+ return false;
+ }
+
+ if (!IS_BMGW_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev))
+ return false;
+
+ if (hinic3_get_vfid_by_vfpci(NULL, pdev, &global_func_id)) {
+ sdk_err(&pdev->dev, "Get vf id by vfpci failed\n");
+ return false;
+ }
+
+ if (hinic3_get_mhost_func_nic_enable(pci_adapter->hwdev,
+ global_func_id, &nic_en)) {
+ sdk_err(&pdev->dev, "Get function nic status failed\n");
+ return false;
+ }
- end = jiffies + msecs_to_jiffies(HINIC3_WAIT_SRIOV_CFG_TIMEOUT);
- do {
- if (!test_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state) &&
- !test_bit(HINIC3_SRIOV_DISABLE, &sriov_info->state))
- return;
+ sdk_info(&pdev->dev, "Func %hu %s default probe in host\n",
+ global_func_id, (nic_en) ? "enable" : "disable");
- usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
- } while (time_before(jiffies, end));
+ return nic_en;
}
bool hinic3_get_vf_load_state(struct pci_dev *pdev)
@@ -897,6 +1490,32 @@ int hinic3_set_vf_service_load(struct pci_dev *pdev, u16 service,
}
EXPORT_SYMBOL(hinic3_set_vf_service_load);
+static bool hinic3_is_host_vmsec_enable(struct pci_dev *pdev)
+{
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct pci_dev *pf_pdev = NULL;
+
+ if (pdev->is_virtfn)
+ pf_pdev = pdev->physfn;
+ else
+ pf_pdev = pdev;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ pr_err("Pci_adapter is null.\n");
+ return false;
+ }
+
+ /* pf/vf used in host */
+ if (IS_VM_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev) &&
+ (hinic3_func_type(pci_adapter->hwdev) == TYPE_PF) &&
+ IS_RDMA_TYPE((struct hinic3_hwdev *)pci_adapter->hwdev)) {
+ return true;
+ }
+
+ return false;
+}
+
static int hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
{
struct pci_dev *pdev = pci_adapter->pcidev;
@@ -910,6 +1529,13 @@ static int hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
pci_adapter->lld_state = HINIC3_IN_REMOVE;
mutex_unlock(&pci_adapter->pdev_mutex);
+ if (!(pdev->is_virtfn) && (hinic3_is_host_vmsec_enable(pdev) == true) &&
+ (hinic3_func_type((struct hinic3_hwdev *)pci_adapter->hwdev) == TYPE_PF)) {
+ cancel_delayed_work_sync(&pci_adapter->migration_probe_dwork);
+ flush_workqueue(pci_adapter->migration_probe_workq);
+ destroy_workqueue(pci_adapter->migration_probe_workq);
+ }
+
hinic3_detect_hw_present(pci_adapter->hwdev);
hisdk3_remove_pre_process(pci_adapter->hwdev);
@@ -934,23 +1560,127 @@ static int hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
sdk_info(&pdev->dev, "Pcie device removed function\n");
+ set_vf_func_in_use(pdev, false);
+
+ return 0;
+}
+
+int hinic3_get_vfid_by_vfpci(void *hwdev, struct pci_dev *pdev, u16 *global_func_id)
+{
+ struct pci_dev *pf_pdev = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ u16 pf_bus, vf_bus, vf_offset;
+ int err;
+
+ if (!pdev || !global_func_id || !hinic3_pdev_is_virtfn(pdev))
+ return -EINVAL;
+ (void)hwdev;
+ pf_pdev = pdev->physfn;
+
+ vf_bus = pdev->bus->number;
+ pf_bus = pf_pdev->bus->number;
+
+ if (pdev->vendor == HINIC3_VIRTIO_VNEDER_ID)
+ return -EPERM;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_err(&pdev->dev, "pci_adapter is null.\n");
+ return -EINVAL;
+ }
+
+ err = hinic3_pf_get_vf_offset_info(pci_adapter, &vf_offset);
+ if (err) {
+ sdk_err(&pdev->dev, "Func hinic3_pf_get_vf_offset_info fail\n");
+ return -EFAULT;
+ }
+
+ *global_func_id = (u16)((vf_bus - pf_bus) * BUS_MAX_DEV_NUM) + (u16)pdev->devfn +
+ (u16)(CMD_MAX_MAX_PF_NUM - g_vf_offset.vf_offset_from_pf[0]);
+
return 0;
}
+EXPORT_SYMBOL(hinic3_get_vfid_by_vfpci);
+
+static void hinic3_set_vf_status_in_host(struct pci_dev *pdev, bool status)
+{
+ struct pci_dev *pf_pdev = pdev->physfn;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ void *pf_hwdev = NULL;
+ void *ppf_hwdev = NULL;
+ u16 global_func_id;
+ int ret;
+
+ if (!pf_pdev)
+ return;
+
+ if (!hinic3_pdev_is_virtfn(pdev))
+ return;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ pf_hwdev = pci_adapter->hwdev;
+ ppf_hwdev = hinic3_get_ppf_hwdev_by_pdev(pf_pdev);
+ if (!pf_hwdev || !ppf_hwdev)
+ return;
+
+ ret = hinic3_get_vfid_by_vfpci(NULL, pdev, &global_func_id);
+ if (ret) {
+ sdk_err(&pci_adapter->pcidev->dev,
+ "Func hinic3_get_vfid_by_vfpci fail %d\n", ret);
+ return;
+ }
+
+ ret = hinic3_set_func_probe_in_host(ppf_hwdev, global_func_id, status);
+ if (ret)
+ sdk_err(&pci_adapter->pcidev->dev,
+ "Set the function probe status in host failed\n");
+}
+
+#ifdef CONFIG_PCI_IOV
+/* Check whether pdev is a VF and whether it belongs to the PF of the SDI card */
+static bool check_pdev_type_and_state(struct pci_dev *pdev)
+{
+ if (!(pdev->is_virtfn))
+ return false;
+
+ if ((hinic3_get_pf_device_id(pdev) != HINIC3_DEV_ID_SDI_5_1_PF) &&
+ (hinic3_get_pf_device_id(pdev) != HINIC3_DEV_ID_SDI_5_0_PF)) {
+ return false;
+ }
+
+ if (!hinic3_get_vf_load_state(pdev))
+ return false;
+
+ return true;
+}
+#endif
static void hinic3_remove(struct pci_dev *pdev)
{
struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
+ sdk_info(&pdev->dev, "Pcie device remove begin\n");
+
if (!pci_adapter)
- return;
+ goto out;
- sdk_info(&pdev->dev, "Pcie device remove begin\n");
+#ifdef CONFIG_PCI_IOV
+ if (check_pdev_type_and_state(pdev))
+ goto out;
+#endif
+ cancel_work_sync(&pci_adapter->slave_nic_work);
+ cancel_work_sync(&pci_adapter->slave_vroce_work);
hinic3_remove_func(pci_adapter);
+ if (!pci_adapter->pcidev->is_virtfn &&
+ pci_adapter->multi_host_mgmt_workq)
+ destroy_workqueue(pci_adapter->multi_host_mgmt_workq);
hinic3_pci_deinit(pdev);
hinic3_probe_pre_unprocess(pdev);
+out:
+ hinic3_set_vf_status_in_host(pdev, false);
sdk_info(&pdev->dev, "Pcie device removed\n");
}
@@ -969,7 +1699,7 @@ static int probe_func_param_init(struct hinic3_pcidev *pci_adapter)
if (pci_adapter->lld_state >= HINIC3_PROBE_START) {
sdk_warn(&pdev->dev, "Don not probe repeat\n");
mutex_unlock(&pci_adapter->pdev_mutex);
- return 0;
+ return -EEXIST;
}
pci_adapter->lld_state = HINIC3_PROBE_START;
mutex_unlock(&pci_adapter->pdev_mutex);
@@ -977,15 +1707,28 @@ static int probe_func_param_init(struct hinic3_pcidev *pci_adapter)
return 0;
}
+static void hinic3_probe_success_process(struct hinic3_pcidev *pci_adapter)
+{
+ hinic3_probe_success(pci_adapter->hwdev);
+
+ mutex_lock(&pci_adapter->pdev_mutex);
+ pci_adapter->lld_state = HINIC3_PROBE_OK;
+ mutex_unlock(&pci_adapter->pdev_mutex);
+}
+
static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)
{
struct pci_dev *pdev = pci_adapter->pcidev;
int err;
err = probe_func_param_init(pci_adapter);
- if (err)
+ if (err == -EEXIST)
+ return 0;
+ else if (err)
return err;
+ set_vf_func_in_use(pdev, true);
+
err = mapping_bar(pdev, pci_adapter);
if (err) {
sdk_err(&pdev->dev, "Failed to map bar\n");
@@ -1017,11 +1760,7 @@ static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)
}
}
- hinic3_probe_success(pci_adapter->hwdev);
-
- mutex_lock(&pci_adapter->pdev_mutex);
- pci_adapter->lld_state = HINIC3_PROBE_OK;
- mutex_unlock(&pci_adapter->pdev_mutex);
+ hinic3_probe_success_process(pci_adapter);
return 0;
@@ -1037,18 +1776,299 @@ alloc_chip_node_fail:
unmapping_bar(pci_adapter);
map_bar_failed:
+ set_vf_func_in_use(pdev, false);
sdk_err(&pdev->dev, "Pcie device probe function failed\n");
return err;
}
+void hinic3_set_func_state(struct hinic3_pcidev *pci_adapter)
+{
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ int err;
+ bool enable_func = false;
+
+ err = hinic3_get_function_enable(pdev, &enable_func);
+ if (err) {
+ sdk_info(&pdev->dev, "Get function enable failed\n");
+ return;
+ }
+
+ sdk_info(&pdev->dev, "%s function resource start\n",
+ enable_func ? "Initialize" : "Free");
+ if (enable_func) {
+ err = hinic3_probe_func(pci_adapter);
+ if (err)
+ sdk_info(&pdev->dev, "Function probe failed\n");
+ } else {
+ hinic3_remove_func(pci_adapter);
+ }
+ if (err == 0)
+ sdk_info(&pdev->dev, "%s function resource end\n",
+ enable_func ? "Initialize" : "Free");
+}
+
+void slave_host_mgmt_work(struct work_struct *work)
+{
+ struct hinic3_pcidev *pci_adapter =
+ container_of(work, struct hinic3_pcidev, slave_nic_work);
+
+ if (hinic3_pdev_is_virtfn(pci_adapter->pcidev))
+ hinic3_set_func_state(pci_adapter);
+ else
+ set_nic_func_state(pci_adapter);
+}
+
+static int pci_adapter_assign_val(struct hinic3_pcidev **ppci_adapter,
+ struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ *ppci_adapter = pci_get_drvdata(pdev);
+ (*ppci_adapter)->disable_vf_load = disable_vf_load;
+ (*ppci_adapter)->id = *id;
+ (*ppci_adapter)->lld_state = HINIC3_NOT_PROBE;
+ (*ppci_adapter)->probe_fault_level = FAULT_LEVEL_SERIOUS_FLR;
+ lld_dev_cnt_init(*ppci_adapter);
+
+ (*ppci_adapter)->multi_host_mgmt_workq = alloc_workqueue("hinic_mhost_mgmt",
+ WQ_UNBOUND,
+ HINIC3_SLAVE_WORK_MAX_NUM);
+ if (!(*ppci_adapter)->multi_host_mgmt_workq) {
+ hinic3_pci_deinit(pdev);
+ sdk_err(&pdev->dev, "Alloc multi host mgmt workqueue failed\n");
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&(*ppci_adapter)->slave_nic_work, slave_host_mgmt_work);
+ INIT_WORK(&(*ppci_adapter)->slave_vroce_work,
+ slave_host_mgmt_vroce_work);
+
+ return 0;
+}
+
+static void slave_host_vfio_probe_delay_work(struct work_struct *work)
+{
+ struct delayed_work *delay = to_delayed_work(work);
+ struct hinic3_pcidev *pci_adapter = container_of(delay, struct hinic3_pcidev,
+ migration_probe_dwork);
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ int (*dev_migration_probe)(struct pci_dev *pdev);
+ int rc;
+
+ if (hinic3_func_type((struct hinic3_hwdev *)pci_adapter->hwdev) != TYPE_PF)
+ return;
+
+ dev_migration_probe = __symbol_get("migration_dev_migration_probe");
+ if (!(dev_migration_probe)) {
+ sdk_err(&pdev->dev,
+ "Failed to find: migration_dev_migration_probe");
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &pci_adapter->migration_probe_dwork,
+ WAIT_TIME * HZ);
+ } else {
+ rc = dev_migration_probe(pdev);
+ __symbol_put("migration_dev_migration_probe");
+ if (rc) {
+ sdk_err(&pdev->dev,
+ "Failed to __dev_migration_probe, rc:0x%x, pf migrated(%d).\n",
+ rc, g_is_pf_migrated);
+ } else {
+ g_is_pf_migrated = true;
+ sdk_info(&pdev->dev,
+ "Succeeded in __dev_migration_probe, pf migrated(%d).\n",
+ g_is_pf_migrated);
+ }
+ }
+}
+
+struct vf_add_delaywork {
+ struct pci_dev *vf_pdev;
+ struct delayed_work migration_vf_add_dwork;
+};
+
+static void slave_host_migration_vf_add_delay_work(struct work_struct *work)
+{
+ struct delayed_work *delay = to_delayed_work(work);
+ struct vf_add_delaywork *vf_add = container_of(delay, struct vf_add_delaywork,
+ migration_vf_add_dwork);
+ struct pci_dev *vf_pdev = vf_add->vf_pdev;
+ struct pci_dev *pf_pdev = NULL;
+ int (*migration_dev_add_vf)(struct pci_dev *vf_pdev);
+ int ret;
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!vf_pdev) {
+ pr_err("vf pdev is null.\n");
+ goto err1;
+ }
+ if (!vf_pdev->is_virtfn) {
+ sdk_err(&vf_pdev->dev, "Pdev is not virtfn.\n");
+ goto err1;
+ }
+
+ pf_pdev = vf_pdev->physfn;
+ if (!pf_pdev) {
+ sdk_err(&vf_pdev->dev, "pf_pdev is null.\n");
+ goto err1;
+ }
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_err(&vf_pdev->dev, "Pci_adapter is null.\n");
+ goto err1;
+ }
+
+ if (!g_is_pf_migrated) {
+ sdk_info(&vf_pdev->dev, "pf is not migrated yet, so vf continues to try again.\n");
+ goto delay_work;
+ }
+
+ migration_dev_add_vf = __symbol_get("migration_dev_add_vf");
+ if (migration_dev_add_vf) {
+ ret = migration_dev_add_vf(vf_pdev);
+ __symbol_put("migration_dev_add_vf");
+ if (ret)
+ sdk_err(&vf_pdev->dev, "vf get migration symbol succeeded, but dev add vf failed, ret:%d.\n",
+ ret);
+ else
+ sdk_info(&vf_pdev->dev, "vf get migration symbol succeeded, and dev add vf success.\n");
+ goto err1;
+ }
+ sdk_info(&vf_pdev->dev, "pf is migrated, but vf get migration symbol failed.\n");
+
+delay_work:
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &vf_add->migration_vf_add_dwork, WAIT_TIME * HZ);
+ return;
+
+err1:
+ kfree(vf_add);
+}
+
+static void hinic3_probe_vf_add_dwork(struct pci_dev *pdev)
+{
+ struct pci_dev *pf_pdev = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct vf_add_delaywork *vf_add = NULL;
+
+ if (!hinic3_is_host_vmsec_enable(pdev))
+ return;
+
+#if defined(CONFIG_SP_VID_DID)
+ if (pdev->vendor == PCI_VENDOR_ID_SPNIC && pdev->device == HINIC3_DEV_SDI_5_1_ID_VF) {
+#elif defined(CONFIG_NF_VID_DID)
+ if (pdev->vendor == PCI_VENDOR_ID_NF && pdev->device == NFNIC_DEV_ID_VF) {
+#else
+ if (pdev->vendor == PCI_VENDOR_ID_HUAWEI && pdev->device == HINIC3_DEV_SDI_5_0_ID_VF) {
+#endif
+ vf_add = kmalloc(sizeof(*vf_add), GFP_ATOMIC);
+
+ if (!vf_add)
+ return;
+
+ vf_add->vf_pdev = pdev;
+
+ pf_pdev = pdev->physfn;
+
+ if (!pf_pdev) {
+ sdk_info(&pdev->dev, "Vf-pf_pdev is null.\n");
+ kfree(vf_add);
+ return;
+ }
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_info(&pdev->dev, "Pci_adapter is null.\n");
+ kfree(vf_add);
+ return;
+ }
+
+ INIT_DELAYED_WORK(&vf_add->migration_vf_add_dwork,
+ slave_host_migration_vf_add_delay_work);
+
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &vf_add->migration_vf_add_dwork,
+ WAIT_TIME * HZ);
+ }
+}
+
+static int hinic3_probe_migration_dwork(struct pci_dev *pdev, struct hinic3_pcidev *pci_adapter)
+{
+ if (!hinic3_is_host_vmsec_enable(pdev)) {
+ sdk_info(&pdev->dev, "Probe_migration : hinic3_is_host_vmsec_enable is (0).\n");
+ return 0;
+ }
+
+ if (IS_VM_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev) &&
+ hinic3_func_type((struct hinic3_hwdev *)pci_adapter->hwdev) == TYPE_PF) {
+ pci_adapter->migration_probe_workq =
+ create_singlethread_workqueue("hinic3_migration_probe_delay");
+ if (!pci_adapter->migration_probe_workq) {
+ sdk_err(&pdev->dev, "Failed to create work queue:%s\n",
+ "hinic3_migration_probe_delay");
+ return -EINVAL;
+ }
+
+ INIT_DELAYED_WORK(&pci_adapter->migration_probe_dwork,
+ slave_host_vfio_probe_delay_work);
+
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &pci_adapter->migration_probe_dwork,
+ WAIT_TIME * HZ);
+ }
+
+ return 0;
+}
+
+static bool hinic3_os_hot_replace_allow(struct hinic3_pcidev *pci_adapter)
+{
+ struct hinic3_hwdev *hwdev = (struct hinic3_hwdev *)pci_adapter->hwdev;
+ // check service enable and dev is not VF
+ if (hinic3_func_type(hwdev) == TYPE_VF || hwdev->hot_replace_mode == HOT_REPLACE_DISABLE)
+ return false;
+
+ return true;
+}
+
+static bool hinic3_os_hot_replace_process(struct hinic3_pcidev *pci_adapter)
+{
+ struct hinic3_board_info *board_info;
+ u16 cur_pf_id = hinic3_global_func_id(pci_adapter->hwdev);
+ u8 cur_partion_id;
+
+ board_info = &((struct hinic3_hwdev *)(pci_adapter->hwdev))->board_info;
+ // probe to os
+ vpci_set_partition_attrs(pci_adapter->pcidev, PARTITION_DEV_EXCLUSIVE,
+ get_function_partition(cur_pf_id,
+ board_info->port_num));
+
+ // check pf_id is in the right partition_id
+ cur_partion_id = get_partition_id();
+ if (get_function_partition(cur_pf_id, board_info->port_num) ==
+ cur_partion_id)
+ return true;
+
+ pci_adapter->probe_fault_level = FAULT_LEVEL_SUGGESTION;
+ return false;
+}
+
static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct hinic3_pcidev *pci_adapter = NULL;
u16 probe_fault_level = FAULT_LEVEL_SERIOUS_FLR;
+ u32 device_id, function_id;
int err;
sdk_info(&pdev->dev, "Pcie device probe begin\n");
+#ifdef CONFIG_PCI_IOV
+ hinic3_set_vf_status_in_host(pdev, true);
+ if (check_pdev_type_and_state(pdev)) {
+ sdk_info(&pdev->dev, "VFs are not binded to hinic\n");
+ hinic3_probe_vf_add_dwork(pdev);
+ return -EINVAL;
+ }
+#endif
+
err = hinic3_probe_pre_process(pdev);
if (err != 0 && err != HINIC3_NOT_PROBE)
goto out;
@@ -1060,26 +2080,48 @@ static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto pci_init_err;
- pci_adapter = pci_get_drvdata(pdev);
- pci_adapter->disable_vf_load = disable_vf_load;
- pci_adapter->id = *id;
- pci_adapter->lld_state = HINIC3_NOT_PROBE;
- pci_adapter->probe_fault_level = probe_fault_level;
- lld_dev_cnt_init(pci_adapter);
+ err = pci_adapter_assign_val(&pci_adapter, pdev, id);
+ if (err)
+ goto allco_queue_err;
- if (pdev->is_virtfn && (!hinic3_get_vf_load_state(pdev))) {
+ if (pdev->is_virtfn && (!hinic3_get_vf_load_state(pdev)) &&
+ (!hinic3_get_vf_nic_en_status(pdev))) {
sdk_info(&pdev->dev, "VF device disable load in host\n");
return 0;
}
- err = hinic3_probe_func(pci_adapter);
- if (err)
+ if (hinic3_probe_func(pci_adapter))
+ goto hinic3_probe_func_fail;
+
+ if (hinic3_os_hot_replace_allow(pci_adapter)) {
+ if (!hinic3_os_hot_replace_process(pci_adapter)) {
+ device_id = PCI_SLOT(pdev->devfn);
+ function_id = PCI_FUNC(pdev->devfn);
+ sdk_info(&pdev->dev,
+ "os hot replace: skip function %d:%d for partition %d",
+ device_id, function_id, get_partition_id());
+ goto os_hot_repalce_not_allow;
+ }
+ }
+
+ if (hinic3_probe_migration_dwork(pdev, pci_adapter))
goto hinic3_probe_func_fail;
sdk_info(&pdev->dev, "Pcie device probed\n");
return 0;
+os_hot_repalce_not_allow:
+ hinic3_func_deinit(pdev);
+ lld_lock_chip_node();
+ free_chip_node(pci_adapter);
+ lld_unlock_chip_node();
+ unmapping_bar(pci_adapter);
+ set_vf_func_in_use(pdev, false);
hinic3_probe_func_fail:
+ destroy_workqueue(pci_adapter->multi_host_mgmt_workq);
+ cancel_work_sync(&pci_adapter->slave_nic_work);
+ cancel_work_sync(&pci_adapter->slave_vroce_work);
+allco_queue_err:
probe_fault_level = pci_adapter->probe_fault_level;
hinic3_pci_deinit(pdev);
@@ -1105,6 +2147,11 @@ static int hinic3_get_pf_info(struct pci_dev *pdev, u16 service,
}
*pf_infos = kzalloc(sizeof(*pf_infos), GFP_KERNEL);
+ if (*pf_infos == NULL) {
+ sdk_err(&pdev->dev, "pf_infos kzalloc failed\n");
+ return -EFAULT;
+ }
+
err = hinic3_get_hw_pf_infos(dev->hwdev, *pf_infos, HINIC3_CHANNEL_COMM);
if (err) {
kfree(*pf_infos);
@@ -1120,6 +2167,7 @@ static int hinic3_set_func_en(struct pci_dev *des_pdev, struct hinic3_pcidev *ds
{
int err;
+ mutex_lock(&dst_dev->pdev_mutex);
/* unload invalid vf func id */
if (!en && vf_func_id != hinic3_global_func_id(dst_dev->hwdev) &&
!strcmp(des_pdev->driver->name, HINIC3_DRV_NAME)) {
@@ -1137,6 +2185,8 @@ static int hinic3_set_func_en(struct pci_dev *des_pdev, struct hinic3_pcidev *ds
err = hinic3_probe_func(dst_dev);
if (err)
return -EFAULT;
+ } else {
+ mutex_unlock(&dst_dev->pdev_mutex);
}
return 0;
@@ -1161,7 +2211,6 @@ static int get_vf_service_state_param(struct pci_dev *pdev, struct hinic3_pcidev
return 0;
}
-#define BUS_MAX_DEV_NUM 256
static int hinic3_dst_pdev_valid(struct hinic3_pcidev *dst_dev, struct pci_dev **des_pdev_ptr,
u16 vf_devfn, bool en)
{
@@ -1243,7 +2292,6 @@ int hinic3_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id, u16 servic
if (en)
pci_dev_put(des_pdev);
- mutex_lock(&dst_dev->pdev_mutex);
find_dst_dev = true;
break;
}
@@ -1263,19 +2311,30 @@ free_pf_info:
}
EXPORT_SYMBOL(hinic3_set_vf_service_state);
-/*lint -save -e133 -e10*/
static const struct pci_device_id hinic3_pci_table[] = {
+#if defined(CONFIG_SP_VID_DID)
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_STANDARD), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_SDI_5_1_PF), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_SDI_5_0_PF), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_SPN120), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_VF), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_SDI_5_1_ID_VF), 0},
+#elif defined(CONFIG_NF_VID_DID)
+ {PCI_VDEVICE(NF, NFNIC_DEV_ID_STANDARD), 0},
+ {PCI_VDEVICE(NF, NFNIC_DEV_ID_VF), 0},
+#else
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SPU), 0},
{PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_STANDARD), 0},
- {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_DPU_PF), 0},
- {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SDI_5_0_PF), 0},
{PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SDI_5_1_PF), 0},
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SDI_5_0_PF), 0},
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_DPU_PF), 0},
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_SDI_5_1_ID_VF), 0},
{PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_VF), 0},
+#endif
{0, 0}
};
-/*lint -restore*/
-
MODULE_DEVICE_TABLE(pci, hinic3_pci_table);
/**
@@ -1307,14 +2366,27 @@ static pci_ers_result_t hinic3_io_error_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_CAN_RECOVER;
}
+static void hinic3_timer_disable(void *hwdev)
+{
+ if (!hwdev)
+ return;
+
+ if (hinic3_get_stateful_enable(hwdev) && hinic3_get_timer_enable(hwdev))
+ (void)hinic3_func_tmr_bitmap_set(hwdev,
+ hinic3_global_func_id(hwdev),
+ false);
+}
+
static void hinic3_shutdown(struct pci_dev *pdev)
{
struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
sdk_info(&pdev->dev, "Shutdown device\n");
- if (pci_adapter)
+ if (pci_adapter) {
+ hinic3_timer_disable(pci_adapter->hwdev);
hinic3_shutdown_hwdev(pci_adapter->hwdev);
+ }
pci_disable_device(pdev);
@@ -1341,6 +2413,9 @@ static struct pci_driver hinic3_driver = {
.probe = hinic3_probe,
.remove = hinic3_remove,
.shutdown = hinic3_shutdown,
+#ifdef CONFIG_PARTITION_DEVICE
+ .driver.probe_concurrency = true,
+#endif
#if defined(HAVE_SRIOV_CONFIGURE)
.sriov_configure = hinic3_pci_sriov_configure,
#elif defined(HAVE_RHEL6_SRIOV_CONFIGURE)
@@ -1362,16 +2437,21 @@ int hinic3_lld_init(void)
err = hinic3_module_pre_init();
if (err) {
pr_err("Init custom failed\n");
- return err;
+ goto module_pre_init_err;
}
err = pci_register_driver(&hinic3_driver);
if (err) {
- hinic3_module_post_exit();
- return err;
+ pr_err("sdk3 pci register driver failed\n");
+ goto register_pci_driver_err;
}
return 0;
+
+register_pci_driver_err:
+ hinic3_module_post_exit();
+module_pre_init_err:
+ return err;
}
void hinic3_lld_exit(void)
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c
index b2851c6..3626262 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c
@@ -584,6 +584,7 @@ static void free_recv_mbox(struct hinic3_recv_mbox *recv_msg)
kfree(recv_msg->resp_buff);
kfree(recv_msg->msg);
kfree(recv_msg);
+ recv_msg = NULL;
}
static void recv_func_mbox_work_handler(struct work_struct *work)
@@ -1232,6 +1233,7 @@ int hinic3_mbox_to_func(struct hinic3_mbox *func_to_func, u8 mod, u16 cmd,
set_mbox_to_func_event(func_to_func, EVENT_FAIL);
goto send_err;
}
+ func_to_func->hwdev->mbox_send_cnt++;
if (wait_mbox_msg_completion(func_to_func, timeout) != 0) {
sdk_err(func_to_func->hwdev->dev_hdl,
@@ -1240,6 +1242,7 @@ int hinic3_mbox_to_func(struct hinic3_mbox *func_to_func, u8 mod, u16 cmd,
err = -ETIMEDOUT;
goto send_err;
}
+ func_to_func->hwdev->mbox_ack_cnt++;
if (mod != msg_desc->mod || cmd != msg_desc->cmd) {
sdk_err(func_to_func->hwdev->dev_hdl,
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c
index 2bd63f1..4718458 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c
@@ -861,6 +861,7 @@ static int alloc_recv_msg(struct hinic3_recv_msg *recv_msg)
static void free_recv_msg(struct hinic3_recv_msg *recv_msg)
{
kfree(recv_msg->msg);
+ recv_msg->msg = NULL;
}
/**
@@ -932,6 +933,9 @@ static void free_msg_buf(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt)
free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+ pf_to_mgmt->mgmt_ack_buf = NULL;
+ pf_to_mgmt->sync_msg_buf = NULL;
+ pf_to_mgmt->async_msg_buf = NULL;
}
/**
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c
index 3548410..a0f5e73 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c
@@ -676,6 +676,9 @@ static int hinic3_register_slave_ppf(struct hinic3_hwdev *hwdev, bool registered
if (!IS_SLAVE_HOST(hwdev))
return -EINVAL;
+ if (UNSUPPORT_HOT_PLUG((struct hinic3_hwdev *)hwdev))
+ return 0;
+
host_info = kcalloc(1, sizeof(struct register_slave_host), GFP_KERNEL);
if (!host_info)
return -ENOMEM;
@@ -1075,7 +1078,8 @@ int hinic3_get_func_nic_enable(void *hwdev, u16 glb_func_idx, bool *en)
return -EINVAL;
/* if single host, return true. */
- if (!IS_MULTI_HOST((struct hinic3_hwdev *)hwdev)) {
+ if (!IS_MULTI_HOST((struct hinic3_hwdev *)hwdev) ||
+ UNSUPPORT_HOT_PLUG((struct hinic3_hwdev *)hwdev)) {
*en = true;
return 0;
}
@@ -1145,11 +1149,21 @@ int hinic3_multi_host_mgmt_init(struct hinic3_hwdev *hwdev)
{
int err;
struct service_cap *cap = &hwdev->cfg_mgmt->svc_cap;
+ int is_use_vram, is_in_kexec;
if (!IS_MULTI_HOST(hwdev) || !HINIC3_IS_PPF(hwdev))
return 0;
- hwdev->mhost_mgmt = kcalloc(1, sizeof(*hwdev->mhost_mgmt), GFP_KERNEL);
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram != 0) {
+ snprintf(hwdev->mhost_mgmt_name, VRAM_NAME_MAX_LEN, "%s",
+ VRAM_NIC_MHOST_MGMT);
+ hwdev->mhost_mgmt = hi_vram_kalloc(hwdev->mhost_mgmt_name,
+ sizeof(*hwdev->mhost_mgmt));
+ } else {
+ hwdev->mhost_mgmt = kcalloc(1, sizeof(*hwdev->mhost_mgmt), GFP_KERNEL);
+ }
+
if (!hwdev->mhost_mgmt)
return -ENOMEM;
@@ -1165,8 +1179,11 @@ int hinic3_multi_host_mgmt_init(struct hinic3_hwdev *hwdev)
hinic3_register_ppf_mbox_cb(hwdev, HINIC3_MOD_HILINK, hwdev, hilink_ppf_mbox_handler);
hinic3_register_ppf_mbox_cb(hwdev, HINIC3_MOD_SW_FUNC, hwdev, sw_func_ppf_mbox_handler);
- bitmap_zero(hwdev->mhost_mgmt->func_nic_en, HINIC3_MAX_MGMT_FUNCTIONS);
- bitmap_zero(hwdev->mhost_mgmt->func_vroce_en, HINIC3_MAX_MGMT_FUNCTIONS);
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec == 0) {
+ bitmap_zero(hwdev->mhost_mgmt->func_nic_en, HINIC3_MAX_MGMT_FUNCTIONS);
+ bitmap_zero(hwdev->mhost_mgmt->func_vroce_en, HINIC3_MAX_MGMT_FUNCTIONS);
+ }
/* Slave host:
* register slave host ppf functions
@@ -1179,7 +1196,11 @@ int hinic3_multi_host_mgmt_init(struct hinic3_hwdev *hwdev)
return 0;
out_free_mhost_mgmt:
- kfree(hwdev->mhost_mgmt);
+ if (is_use_vram != 0)
+ hi_vram_kfree((void *)hwdev->mhost_mgmt, hwdev->mhost_mgmt_name,
+ sizeof(*hwdev->mhost_mgmt));
+ else
+ kfree(hwdev->mhost_mgmt);
hwdev->mhost_mgmt = NULL;
return err;
@@ -1187,6 +1208,8 @@ out_free_mhost_mgmt:
int hinic3_multi_host_mgmt_free(struct hinic3_hwdev *hwdev)
{
+ int is_use_vram;
+
if (!IS_MULTI_HOST(hwdev) || !HINIC3_IS_PPF(hwdev))
return 0;
@@ -1203,7 +1226,13 @@ int hinic3_multi_host_mgmt_free(struct hinic3_hwdev *hwdev)
hinic3_unregister_ppf_mbox_cb(hwdev, HINIC3_MOD_HILINK);
hinic3_unregister_ppf_mbox_cb(hwdev, HINIC3_MOD_SW_FUNC);
- kfree(hwdev->mhost_mgmt);
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram != 0)
+ hi_vram_kfree((void *)hwdev->mhost_mgmt, hwdev->mhost_mgmt_name,
+ sizeof(*hwdev->mhost_mgmt));
+ else
+ kfree(hwdev->mhost_mgmt);
+
hwdev->mhost_mgmt = NULL;
return 0;
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c
index 5e4804a..5a5ea53 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c
@@ -17,14 +17,13 @@
#include "hinic3_hwdev.h"
#include "hinic3_lld.h"
#include "hinic3_hw_mt.h"
+#include "hinic3_dev_mgmt.h"
#include "hinic3_nictool.h"
static int g_nictool_ref_cnt;
static dev_t g_dev_id = {0};
-/*lint -save -e104 -e808*/
static struct class *g_nictool_class;
-/*lint -restore*/
static struct cdev g_nictool_cdev;
#define HINIC3_MAX_BUF_SIZE (2048 * 1024)
@@ -92,6 +91,23 @@ static int get_all_chip_id_cmd(struct hinic3_lld_dev *lld_dev, const void *buf_i
return 0;
}
+#ifndef __HIFC__
+static int get_os_hot_replace_info(struct hinic3_lld_dev *lld_dev,
+ const void *buf_in, u32 in_size,
+ void *buf_out, u32 *out_size)
+{
+ if (*out_size != sizeof(struct os_hot_replace_info) || !buf_out) {
+ pr_err("Invalid parameter: out_buf_size %u, expect %lu\n",
+ *out_size, sizeof(struct os_hot_replace_info));
+ return -EFAULT;
+ }
+
+ hinic3_get_os_hot_replace_info(buf_out);
+
+ return 0;
+}
+#endif
+
static int get_card_usr_api_chain_mem(int card_idx)
{
unsigned char *tmp = NULL;
@@ -166,7 +182,7 @@ static int get_pf_dev_info(struct hinic3_lld_dev *lld_dev, const void *buf_in, u
if (!buf_out || *out_size != sizeof(struct pf_dev_info) * PF_DEV_INFO_NUM) {
pr_err("Invalid parameter: out_buf_size %u, expect %lu\n",
- *out_size, sizeof(dev_info) * PF_DEV_INFO_NUM);
+ *out_size, sizeof(*dev_info) * PF_DEV_INFO_NUM);
return -EFAULT;
}
@@ -193,13 +209,18 @@ static int get_pf_dev_info(struct hinic3_lld_dev *lld_dev, const void *buf_in, u
return 0;
}
-static long dbgtool_knl_free_mem(int id)
+static void dbgtool_knl_free_mem(int id)
{
unsigned char *tmp = NULL;
int i;
+ if (id < 0 || id >= MAX_CARD_NUM) {
+ pr_err("Invalid card id\n");
+ return;
+ }
+
if (!g_card_vir_addr[id])
- return 0;
+ return;
tmp = g_card_vir_addr[id];
for (i = 0; i < (1 << DBGTOOL_PAGE_ORDER); i++) {
@@ -211,7 +232,6 @@ static long dbgtool_knl_free_mem(int id)
g_card_vir_addr[id] = NULL;
g_card_phy_addr[id] = 0;
- return 0;
}
static int free_knl_mem(struct hinic3_lld_dev *lld_dev, const void *buf_in, u32 in_size,
@@ -337,7 +357,6 @@ static int get_hw_drv_version(struct hinic3_lld_dev *lld_dev, const void *buf_in
void *buf_out, u32 *out_size)
{
struct drv_version_info *ver_info = buf_out;
- int err;
if (!buf_out) {
pr_err("Buf_out is NULL.\n");
@@ -350,10 +369,8 @@ static int get_hw_drv_version(struct hinic3_lld_dev *lld_dev, const void *buf_in
return -EINVAL;
}
- err = snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s", HINIC3_DRV_VERSION,
- "2023-05-17_19:56:38");
- if (err < 0)
- return -EINVAL;
+ snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s", HINIC3_DRV_VERSION,
+ "2025-05-08_00:00:08");
return 0;
}
@@ -386,6 +403,22 @@ static int get_pf_id(struct hinic3_lld_dev *lld_dev, const void *buf_in, u32 in_
return 0;
}
+#ifndef __HIFC__
+/* not support fc yet */
+static int get_mbox_cnt(struct hinic3_lld_dev *lld_dev, const void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ if (!buf_out || *out_size != sizeof(struct card_mbox_cnt_info)) {
+ pr_err("buf_out is NULL, or out_size != %lu\n", sizeof(struct card_info));
+ return -EINVAL;
+ }
+
+ hinic3_get_mbox_cnt(hinic3_get_sdk_hwdev_by_lld(lld_dev), buf_out);
+
+ return 0;
+}
+#endif
+
struct hw_drv_module_handle hw_driv_module_cmd_handle[] = {
{FUNC_TYPE, get_func_type},
{GET_FUNC_IDX, get_func_id},
@@ -402,6 +435,10 @@ struct hw_drv_module_handle hw_driv_module_cmd_handle[] = {
{GET_FUNC_CAP, get_pf_cap_info},
{GET_DRV_VERSION, get_hw_drv_version},
{GET_PF_ID, get_pf_id},
+#ifndef __HIFC__
+ {GET_OS_HOT_REPLACE_INFO, get_os_hot_replace_info},
+ {GET_MBOX_CNT, (hw_driv_module)get_mbox_cnt},
+#endif
};
static int alloc_tmp_buf(void *hwdev, struct msg_module *nt_msg, u32 in_size,
@@ -439,8 +476,8 @@ static void free_tmp_buf(void *hwdev, struct msg_module *nt_msg,
static int send_to_hw_driver(struct hinic3_lld_dev *lld_dev, struct msg_module *nt_msg,
const void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
{
- int index, num_cmds = sizeof(hw_driv_module_cmd_handle) /
- sizeof(hw_driv_module_cmd_handle[0]);
+ int index, num_cmds = (int)(sizeof(hw_driv_module_cmd_handle) /
+ sizeof(hw_driv_module_cmd_handle[0]));
enum driver_cmd_type cmd_type =
(enum driver_cmd_type)(nt_msg->msg_formate);
int err = 0;
@@ -482,8 +519,8 @@ static int send_to_service_driver(struct hinic3_lld_dev *lld_dev, struct msg_mod
if (nt_msg->msg_formate == GET_DRV_VERSION)
return 0;
- pr_err("Can not get the uld dev correctly: %s, %s driver may be not register\n",
- nt_msg->device_name, service_name[type]);
+ pr_err("Can not get the uld dev correctly: %s driver may be not register\n",
+ service_name[type]);
return -EINVAL;
}
@@ -597,8 +634,10 @@ static long hinicadm_k_unlocked_ioctl(struct file *pfile, unsigned long arg)
return -ENODEV;
}
- if (nt_msg.msg_formate == DEV_NAME_TEST)
+ if (nt_msg.msg_formate == DEV_NAME_TEST) {
+ lld_dev_put(lld_dev);
return 0;
+ }
ret = alloc_tmp_buf(hinic3_get_sdk_hwdev_by_lld(lld_dev), &nt_msg,
in_size, &buf_in, out_size_expect, &buf_out);
@@ -642,6 +681,9 @@ out_free_lock:
static long dbgtool_knl_ffm_info_rd(struct dbgtool_param *para,
struct dbgtool_k_glb_info *dbgtool_info)
{
+ if (!para->param.ffm_rd || !dbgtool_info->ffm)
+ return -EINVAL;
+
/* Copy the ffm_info to user mode */
if (copy_to_user(para->param.ffm_rd, dbgtool_info->ffm,
(unsigned int)sizeof(struct ffm_record_info))) {
@@ -674,13 +716,14 @@ static long dbgtool_k_unlocked_ioctl(struct file *pfile,
card_info = (struct card_node *)g_card_node_array[i];
if (!card_info)
continue;
- if (!strncmp(param.chip_name, card_info->chip_name, IFNAMSIZ))
+ if (memcmp(param.chip_name, card_info->chip_name,
+ strlen(card_info->chip_name) + 1) == 0)
break;
}
if (i == MAX_CARD_NUM || !card_info) {
lld_put();
- pr_err("Can't find this card %s\n", param.chip_name);
+ pr_err("Can't find this card.\n");
return -EFAULT;
}
@@ -697,10 +740,10 @@ static long dbgtool_k_unlocked_ioctl(struct file *pfile,
pr_err("Not suppose to use this cmd(0x%x).\n", real_cmd);
ret = 0;
break;
-
default:
pr_err("Dbgtool cmd(0x%x) not support now\n", real_cmd);
ret = -EFAULT;
+ break;
}
up(&dbgtool_info->dbgtool_sem);
@@ -746,9 +789,11 @@ static long nictool_k_unlocked_ioctl(struct file *pfile,
static int hinic3_mem_mmap(struct file *filp, struct vm_area_struct *vma)
{
+ pgprot_t vm_page_prot;
unsigned long vmsize = vma->vm_end - vma->vm_start;
phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
phys_addr_t phy_addr;
+ int err = 0;
if (vmsize > (PAGE_SIZE * (1 << DBGTOOL_PAGE_ORDER))) {
pr_err("Map size = %lu is bigger than alloc\n", vmsize);
@@ -758,13 +803,18 @@ static int hinic3_mem_mmap(struct file *filp, struct vm_area_struct *vma)
/* old version of tool set vma->vm_pgoff to 0 */
phy_addr = offset ? offset : g_card_phy_addr[card_id];
- if (!phy_addr) {
- pr_err("Card_id = %d physical address is 0\n", card_id);
- return -EAGAIN;
+ /* check phy_addr valid */
+ if (phy_addr != g_card_phy_addr[card_id]) {
+ err = hinic3_bar_mmap_param_valid(phy_addr, vmsize);
+ if (err != 0) {
+ pr_err("mmap param invalid, err: %d\n", err);
+ return err;
+ }
}
/* Disable cache and write buffer in the mapping area */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = vm_page_prot;
if (remap_pfn_range(vma, vma->vm_start, (phy_addr >> PAGE_SHIFT),
vmsize, vma->vm_page_prot)) {
pr_err("Remap pfn range failed.\n");
@@ -787,7 +837,6 @@ static const struct file_operations fifo_operations = {
static void free_dbgtool_info(void *hwdev, struct card_node *chip_info)
{
struct dbgtool_k_glb_info *dbgtool_info = NULL;
- int err, id;
if (hinic3_func_type(hwdev) != TYPE_VF)
chip_info->func_handle_array[hinic3_global_func_id(hwdev)] = NULL;
@@ -795,23 +844,22 @@ static void free_dbgtool_info(void *hwdev, struct card_node *chip_info)
if (--chip_info->func_num)
return;
- err = sscanf(chip_info->chip_name, HINIC3_CHIP_NAME "%d", &id);
- if (err < 0)
- pr_err("Failed to get card id\n");
-
- if (id < MAX_CARD_NUM)
- g_card_node_array[id] = NULL;
+ if (chip_info->chip_id >= 0 && chip_info->chip_id < MAX_CARD_NUM)
+ g_card_node_array[chip_info->chip_id] = NULL;
dbgtool_info = chip_info->dbgtool_info;
/* FFM deinit */
- kfree(dbgtool_info->ffm);
- dbgtool_info->ffm = NULL;
+ if (dbgtool_info && dbgtool_info->ffm) {
+ kfree(dbgtool_info->ffm);
+ dbgtool_info->ffm = NULL;
+ }
kfree(dbgtool_info);
+
chip_info->dbgtool_info = NULL;
- if (id < MAX_CARD_NUM)
- (void)dbgtool_knl_free_mem(id);
+ if (chip_info->chip_id >= 0 && chip_info->chip_id < MAX_CARD_NUM)
+ dbgtool_knl_free_mem(chip_info->chip_id);
}
static int alloc_dbgtool_info(void *hwdev, struct card_node *chip_info)
@@ -872,7 +920,7 @@ dbgtool_info_fail:
* nictool_k_init - initialize the hw interface
**/
/* temp for dbgtool_info */
-/*lint -e438*/
+
int nictool_k_init(void *hwdev, void *chip_node)
{
struct card_node *chip_info = (struct card_node *)chip_node;
@@ -895,9 +943,7 @@ int nictool_k_init(void *hwdev, void *chip_node)
}
/* Create equipment */
- /*lint -save -e160*/
g_nictool_class = class_create(HIADM3_DEV_CLASS);
- /*lint -restore*/
if (IS_ERR(g_nictool_class)) {
pr_err("Create nictool_class fail\n");
err = -EFAULT;
@@ -944,7 +990,7 @@ alloc_chdev_fail:
free_dbgtool_info(hwdev, chip_info);
return err;
-} /*lint +e438*/
+}
void nictool_k_uninit(void *hwdev, void *chip_node)
{
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h
index f368133..c943dfc 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h
@@ -18,6 +18,8 @@
int nictool_k_init(void *hwdev, void *chip_node);
void nictool_k_uninit(void *hwdev, void *chip_node);
+void hinic3_get_os_hot_replace_info(void *oshr_info);
+
void hinic3_get_all_chip_id(void *id_info);
void hinic3_get_card_func_info_by_card_name
@@ -29,6 +31,8 @@ bool hinic3_is_in_host(void);
int hinic3_get_pf_id(struct card_node *chip_node, u32 port_id, u32 *pf_id, u32 *isvalid);
+void hinic3_get_mbox_cnt(const void *hwdev, void *bufin);
+
extern struct hinic3_uld_info g_uld_info[SERVICE_T_MAX];
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h
index 2d5423e..e961ef7 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h
@@ -19,6 +19,20 @@
#define HINIC3_DEV_ID_SPU 0xAC00
#define HINIC3_DEV_SDI_5_1_SSDID_VF 0x1000
#define HINIC3_DEV_SDI_V100_SSDID_MASK (3 << 12)
+#elif defined(CONFIG_NF_VID_DID)
+#define PCI_VENDOR_ID_NF 0x2036
+#define NFNIC_DEV_ID_STANDARD 0x1618
+#define NFNIC_DEV_ID_SDI_5_1_PF 0x0226
+#define NFNIC_DEV_ID_SDI_5_0_PF 0x0225
+#define NFNIC_DEV_ID_DPU_PF 0x0224
+#define NFNIC_DEV_ID_VF 0x1619
+#define NFNIC_DEV_ID_VF_HV 0x379F
+#define NFNIC_DEV_SDI_5_1_ID_VF 0x375F
+#define NFNIC_DEV_SDI_5_0_ID_VF 0x375F
+#define NFNIC_DEV_SDI_5_1_ID_VF_HV 0x379F
+#define NFNIC_DEV_ID_SPU 0xAC00
+#define NFNIC_DEV_SDI_5_1_SSDID_VF 0x1000
+#define NFNIC_DEV_SDI_V100_SSDID_MASK (3 << 12)
#else
#define PCI_VENDOR_ID_HUAWEI 0x19e5
#define HINIC3_DEV_ID_STANDARD 0x0222
@@ -28,16 +42,33 @@
#define HINIC3_DEV_ID_VF 0x375F
#define HINIC3_DEV_ID_VF_HV 0x379F
#define HINIC3_DEV_SDI_5_1_ID_VF 0x375F
+#define HINIC3_DEV_SDI_5_0_ID_VF 0x375F
#define HINIC3_DEV_SDI_5_1_ID_VF_HV 0x379F
#define HINIC3_DEV_ID_SPU 0xAC00
#define HINIC3_DEV_SDI_5_1_SSDID_VF 0x1000
#define HINIC3_DEV_SDI_V100_SSDID_MASK (3 << 12)
#endif
+#define NFNIC_DEV_SSID_2X25G_NF 0x0860
+#define NFNIC_DEV_SSID_4X25G_NF 0x0861
+#define NFNIC_DEV_SSID_2x100G_NF 0x0862
+#define NFNIC_DEV_SSID_2x200G_NF 0x0863
+
+#define HINIC3_DEV_SSID_2X10G 0x0035
#define HINIC3_DEV_SSID_2X25G 0x0051
#define HINIC3_DEV_SSID_4X25G 0x0052
+#define HINIC3_DEV_SSID_4X25G_BD 0x0252
+#define HINIC3_DEV_SSID_4X25G_SMARTNIC 0x0152
+#define HINIC3_DEV_SSID_6X25G_VL 0x0356
#define HINIC3_DEV_SSID_2X100G 0x00A1
+#define HINIC3_DEV_SSID_2X100G_SMARTNIC 0x01A1
+#define HINIC3_DEV_SSID_2X200G 0x04B1
#define HINIC3_DEV_SSID_2X100G_VF 0x1000
+#define HINIC3_DEV_SSID_HPC_4_HOST_NIC 0x005A
+#define HINIC3_DEV_SSID_2X200G_VL 0x00B1
+#define HINIC3_DEV_SSID_1X100G 0x02A4
+
+#define BIFUR_RESOURCE_PF_SSID 0x05a1
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c
index b23b69f..461272e 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c
@@ -52,26 +52,25 @@ static int hinic3_deinit_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id)
}
#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
-ssize_t hinic3_sriov_totalvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ssize_t sriov_totalvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%d\n", pci_sriov_get_totalvfs(pdev));
}
-ssize_t hinic3_sriov_numvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ssize_t sriov_numvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%d\n", pci_num_vf(pdev));
}
-/*lint -save -e713*/
-ssize_t hinic3_sriov_numvfs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ssize_t sriov_numvfs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
int ret;
@@ -116,7 +115,6 @@ ssize_t hinic3_sriov_numvfs_store(struct device *dev,
return count;
}
-/*lint -restore*/
#endif /* !(HAVE_SRIOV_CONFIGURE || HAVE_RHEL6_SRIOV_CONFIGURE) */
int hinic3_pci_sriov_disable(struct pci_dev *dev)
@@ -174,24 +172,15 @@ int hinic3_pci_sriov_disable(struct pci_dev *dev)
return 0;
}
-int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
-{
#ifdef CONFIG_PCI_IOV
- struct hinic3_sriov_info *sriov_info = NULL;
- struct hinic3_event_info event = {0};
- void *hwdev = NULL;
- int pre_existing_vfs = 0;
- int err = 0;
-
- sriov_info = hinic3_get_sriov_info_by_pcidev(dev);
- hwdev = hinic3_get_hwdev_by_pcidev(dev);
- if (!hwdev) {
- sdk_err(&dev->dev, "SR-IOV enable is not permitted, please wait...\n");
- return -EPERM;
- }
+int hinic3_pci_sriov_check(struct hinic3_sriov_info *sriov_info, struct pci_dev *dev, int num_vfs)
+{
+ int pre_existing_vfs;
+ int err;
if (test_and_set_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state)) {
- sdk_err(&dev->dev, "SR-IOV enable in process, please wait, num_vfs %d\n",
+ sdk_err(&dev->dev,
+ "SR-IOV enable in process, please wait, num_vfs %d\n",
num_vfs);
return -EPERM;
}
@@ -202,6 +191,7 @@ int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
clear_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state);
return -ERANGE;
}
+
if (pre_existing_vfs && pre_existing_vfs != num_vfs) {
err = hinic3_pci_sriov_disable(dev);
if (err) {
@@ -213,6 +203,29 @@ int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
return num_vfs;
}
+ return 0;
+}
+#endif
+
+int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
+{
+#ifdef CONFIG_PCI_IOV
+ struct hinic3_sriov_info *sriov_info = NULL;
+ struct hinic3_event_info event = {0};
+ void *hwdev = NULL;
+ int err = 0;
+
+ sriov_info = hinic3_get_sriov_info_by_pcidev(dev);
+ hwdev = hinic3_get_hwdev_by_pcidev(dev);
+ if (!hwdev) {
+ sdk_err(&dev->dev, "SR-IOV enable is not permitted, please wait...\n");
+ return -EPERM;
+ }
+
+ err = hinic3_pci_sriov_check(sriov_info, dev, num_vfs);
+ if (err != 0)
+ return err;
+
err = hinic3_init_vf_hw(hwdev, 1, (u16)num_vfs);
if (err) {
sdk_err(&dev->dev, "Failed to init vf in hardware before enable sriov, error %d\n",
@@ -262,6 +275,3 @@ int hinic3_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
else
return hinic3_pci_sriov_enable(dev, num_vfs);
}
-
-/*lint -restore*/
-
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h
index 4a640ad..becb5c7 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h
@@ -7,13 +7,13 @@
#include <linux/pci.h>
#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
-ssize_t hinic3_sriov_totalvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-ssize_t hinic3_sriov_numvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-ssize_t hinic3_sriov_numvfs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count);
+ssize_t sriov_totalvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ssize_t sriov_numvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ssize_t sriov_numvfs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
#endif /* !(HAVE_SRIOV_CONFIGURE || HAVE_RHEL6_SRIOV_CONFIGURE) */
enum hinic3_sriov_state {
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c b/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c
index f8aea696..be83022 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c
@@ -117,3 +117,4 @@ u64 ossl_get_real_time(void)
tv_msec = (u64)tv.tv_sec * MSEC_PER_SEC + (u64)tv.tv_usec / USEC_PER_MSEC;
return tv_msec;
}
+
diff --git a/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h b/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h
index 9e8fc75..01ab739 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h
@@ -10,6 +10,10 @@
#define OVS_PORT_NUM_MAX BOND_PORT_MAX_NUM
#define DEFAULT_ROCE_BOND_FUNC 0xFFFFFFFF
+#define BOND_ID_IS_VALID(_id) \
+ (((_id) >= BOND_FIRST_ID) && ((_id) <= BOND_MAX_ID))
+#define BOND_ID_IS_INVALID(_id) (!(BOND_ID_IS_VALID(_id)))
+
enum bond_group_id {
BOND_FIRST_ID = 1,
BOND_MAX_ID = 4,
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 e7e16fc..f9737ea 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
@@ -52,6 +52,8 @@ enum scenes_id_define {
SCENES_ID_STORAGE_ROCE = 6,
SCENES_ID_COMPUTE_ROCE = 7,
SCENES_ID_STORAGE_TOE = 8,
+ SCENES_ID_COMPUTE_DPU = 100,
+ SCENES_ID_COMPUTE_SMART_NIC = 101,
SCENES_ID_MAX
};
@@ -122,13 +124,18 @@ struct cfg_cmd_dev_cap {
u8 srv_multi_host_mode;
u8 virtio_vq_size;
- u32 rsvd_func3[5];
+ u8 hot_plug_disable;
+ u8 bond_create_mode;
+ u8 lro_enable;
+ u8 os_hot_replace;
+
+ u32 rsvd_func3[4];
/* l2nic */
u16 nic_max_sq_id;
u16 nic_max_rq_id;
u16 nic_default_num_queues;
- u16 rsvd1_nic;
+ u16 outband_vlan_cfg_en;
u32 rsvd2_nic[2];
/* RoCE */
diff --git a/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h b/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h
index d9f67e2..6c5b995 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h
@@ -37,7 +37,7 @@ static inline void hinic3_cpu_to_be32(void *data, int len)
{
int i, chunk_sz = sizeof(u32);
int data_len = len;
- u32 *mem = data;
+ u32 *mem = (u32 *)data;
if (!data)
return;
@@ -59,7 +59,7 @@ static inline void hinic3_be32_to_cpu(void *data, int len)
{
int i, chunk_sz = sizeof(u32);
int data_len = len;
- u32 *mem = data;
+ u32 *mem = (u32 *)data;
if (!data)
return;
@@ -86,52 +86,16 @@ static inline void hinic3_set_sge(struct hinic3_sge *sge, dma_addr_t addr,
sge->len = (u32)len;
}
-#ifdef HW_CONVERT_ENDIAN
#define hinic3_hw_be32(val) (val)
#define hinic3_hw_cpu32(val) (val)
#define hinic3_hw_cpu16(val) (val)
-#else
-#define hinic3_hw_be32(val) cpu_to_be32(val)
-#define hinic3_hw_cpu32(val) be32_to_cpu(val)
-#define hinic3_hw_cpu16(val) be16_to_cpu(val)
-#endif
static inline void hinic3_hw_be32_len(void *data, int len)
{
-#ifndef HW_CONVERT_ENDIAN
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = hinic3_hw_be32(*mem);
- mem++;
- }
-#endif
}
static inline void hinic3_hw_cpu32_len(void *data, int len)
{
-#ifndef HW_CONVERT_ENDIAN
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = hinic3_hw_cpu32(*mem);
- mem++;
- }
-#endif
}
int hinic3_dma_zalloc_coherent_align(void *dev_hdl, u64 size, u64 align,
@@ -149,6 +113,8 @@ int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler,
/* func_attr.glb_func_idx, global function index */
u16 hinic3_global_func_id(void *hwdev);
+int hinic3_global_func_id_get(void *hwdev, u16 *func_id);
+
/* func_attr.p2p_idx, belongs to which pf */
u8 hinic3_pf_id_of_vf(void *hwdev);
diff --git a/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h b/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h
index 9a9bfe2..e36ba1d 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h
@@ -219,5 +219,7 @@ void hinic3_detach_nic(const struct hinic3_lld_dev *lld_dev);
int hinic3_attach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
void hinic3_detach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
const char **hinic3_get_uld_names(void);
+int hinic3_lld_init(void);
+void hinic3_lld_exit(void);
#endif
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h
index 97d34f0..4cd6f94 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h
@@ -43,6 +43,10 @@ enum mag_cmd {
MAG_CMD_GET_XSFP_PRESENT = 62, /* get xsfp present status @see mag_cmd_get_xsfp_present */
MAG_CMD_SET_XSFP_RW = 63, /* sfp/qsfp single byte read/write, @see mag_cmd_set_xsfp_rw */
MAG_CMD_CFG_XSFP_TEMPERATURE = 64, /* get xsfp temp @see mag_cmd_sfp_temp_out_info */
+ /**< set xsfp tlv info @see struct mag_cmd_set_xsfp_tlv_req */
+ MAG_CMD_SET_XSFP_TLV_INFO = 65,
+ /**< get xsfp tlv info @see struct drv_tag_mag_cmd_get_xsfp_tlv_rsp */
+ MAG_CMD_GET_XSFP_TLV_INFO = 66,
/* Event reported 100-149 */
MAG_CMD_WIRE_EVENT = 100,
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h
index caaba5d..d33b9f4 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h
@@ -31,17 +31,28 @@ enum board_type_define_e {
BOARD_TYPE_STRG_2X100G_ROCE_AA = 42, /* 2X100G SmartIO ROCE_AA Card */
BOARD_TYPE_CAL_2X25G_NIC_75MPPS = 100, /* 2X25G ETH Standard card 75MPPS */
BOARD_TYPE_CAL_2X25G_NIC_40MPPS = 101, /* 2X25G ETH Standard card 40MPPS */
- BOARD_TYPE_CAL_2X100G_DPU = 102, /* 2x100G DPU Card */
+ BOARD_TYPE_CAL_2X100G_DPU_VL = 102, /* 2x100G DPU Card */
BOARD_TYPE_CAL_4X25G_NIC_120MPPS = 105, /* 4X25G ETH Standard card 120MPPS */
BOARD_TYPE_CAL_4X25G_COMSTORAGE = 106, /* 4X25GE compute storage Onboard Card */
BOARD_TYPE_CAL_2X32G_FC_HBA = 110, /* 2X32G FC HBA card */
BOARD_TYPE_CAL_2X16G_FC_HBA = 111, /* 2X16G FC HBA card */
BOARD_TYPE_CAL_2X100G_NIC_120MPPS = 115, /* 2X100G ETH Standard card 120MPPS */
- BOARD_TYPE_CAL_2X25G_DPU = 116, /* 2x25G DPU Card */
- BOARD_TYPE_CAL_4X25G_DPU = 118, /* 4x25G DPU Card */
+ BOARD_TYPE_CAL_2X25G_DPU_BD = 116, /* 2x25G DPU Card */
+ BOARD_TYPE_CAL_2X100G_TCE_BACKPLANE = 117,
+ BOARD_TYPE_CAL_4X25G_DPU_VL = 118, /* 4x25G DPU Card */
+ BOARD_TYPE_CAL_4X25G_SMARTNIC_120MPPS = 119,
+ BOARD_TYPE_CAL_2X100G_SMARTNIC_120MPPS = 120,
+ BOARD_TYPE_CAL_6X25G_DPU_VL = 121, /* 6x25G DPU Card */
+ BOARD_TYPE_CAL_4X25G_DPU_BD = 122,
+ BOARD_TYPE_CAL_2X25G_NIC_4HOST = 123,
+ BOARD_TYPE_CAL_2X10G_LOW_POWER = 125,
+ BOARD_TYPE_CAL_2X200G_NIC_INTERNET = 127,
+ BOARD_TYPE_CAL_1X100GR2_OCP = 129, /* 1X100G ETH Standard card */
+ BOARD_TYPE_CAL_2X200G_DPU_VL = 130,
BOARD_TYPE_CLD_2X100G_SDI5_1 = 170, /* 2X100G SDI 5.1 Card */
BOARD_TYPE_CLD_2X25G_SDI5_0_LITE = 171, /* 2x25G SDI5.0 Lite Card */
BOARD_TYPE_CLD_2X100G_SDI5_0 = 172, /* 2x100G SDI5.0 Card */
+ BOARD_TYPE_CLD_4X25G_SDI5_0_C = 175,
BOARD_TYPE_MAX_INDEX = 0xFF
};
@@ -49,23 +60,62 @@ static inline u32 spu_board_type_valid(u32 board_type)
{
return ((board_type) == BOARD_TYPE_CLD_2X25G_SDI5_0_LITE) ||
((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_0) ||
- ((board_type) == BOARD_TYPE_CAL_2X25G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_2X100G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_4X25G_DPU);
+ ((board_type) == BOARD_TYPE_CLD_4X25G_SDI5_0_C) ||
+ ((board_type) == BOARD_TYPE_CAL_2X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_DPU_VL);
}
static inline int board_type_is_sdi(u32 board_type)
{
return ((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_1) ||
((board_type) == BOARD_TYPE_CLD_2X25G_SDI5_0_LITE) ||
- ((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_0);
+ ((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_0) ||
+ ((board_type) == BOARD_TYPE_CLD_4X25G_SDI5_0_C);
+}
+
+static inline int board_type_is_dpu_spu(u32 board_type)
+{
+ return ((board_type) == BOARD_TYPE_CAL_2X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_DPU_VL);
}
static inline int board_type_is_dpu(u32 board_type)
{
- return ((board_type) == BOARD_TYPE_CAL_2X25G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_2X100G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_4X25G_DPU);
+ return ((board_type) == BOARD_TYPE_CAL_2X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_6X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_DPU_VL);
+}
+
+/* 此接口判断是否是分布式存储的标卡以及计算的标卡(含ROCE特性),
+ * 仅用于LLDP TX功能冲突命令字处理的判断
+ */
+static inline int board_type_is_compute(u32 board_type)
+{
+ return ((board_type) == BOARD_TYPE_CAL_2X25G_NIC_75MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_2X25G_NIC_40MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_NIC_120MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_COMSTORAGE) ||
+ ((board_type) == BOARD_TYPE_CAL_2X10G_LOW_POWER) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_NIC_INTERNET) ||
+ ((board_type) == BOARD_TYPE_CAL_1X100GR2_OCP) ||
+ ((board_type) == BOARD_TYPE_CAL_2X25G_NIC_4HOST) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_SMARTNIC_120MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_NIC_120MPPS);
+}
+
+/* 此接口判断服务器输入reboot网卡是否需要复位 */
+static inline int board_type_is_multi_socket(u32 board_type)
+{
+ return ((board_type) == BOARD_TYPE_CAL_1X100GR2_OCP);
}
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h
index 291e475..4d4d543 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h
@@ -4,8 +4,95 @@
#ifndef MPU_CMD_BASE_DEFS_H
#define MPU_CMD_BASE_DEFS_H
-#include "mgmt_msg_base.h"
-#include "comm_defs.h"
+/** MPU CMD MODULE TYPE */
+enum hinic3_mod_type {
+ HINIC3_MOD_COMM = 0, /* HW communication module */
+ HINIC3_MOD_L2NIC = 1, /* L2NIC module */
+ HINIC3_MOD_ROCE = 2,
+ HINIC3_MOD_PLOG = 3,
+ HINIC3_MOD_TOE = 4,
+ HINIC3_MOD_FLR = 5,
+ HINIC3_MOD_VROCE = 6,
+ HINIC3_MOD_CFGM = 7, /* Configuration management */
+ HINIC3_MOD_CQM = 8,
+ HINIC3_MOD_VMSEC = 9,
+ COMM_MOD_FC = 10,
+ HINIC3_MOD_OVS = 11,
+ HINIC3_MOD_DSW = 12,
+ HINIC3_MOD_MIGRATE = 13,
+ HINIC3_MOD_HILINK = 14,
+ HINIC3_MOD_CRYPT = 15, /* secure crypto module */
+ HINIC3_MOD_VIO = 16,
+ HINIC3_MOD_IMU = 17,
+ HINIC3_MOD_DFX = 18, /* DFX */
+ HINIC3_MOD_HW_MAX = 19, /* hardware max module id */
+ /* Software module id, for PF/VF and multi-host */
+ HINIC3_MOD_SW_FUNC = 20,
+ HINIC3_MOD_MAX,
+};
+
+/* func reset的flag ,用于指示清理哪种资源 */
+enum func_reset_flag_e {
+ RES_TYPE_FLUSH_BIT = 0,
+ RES_TYPE_MQM,
+ RES_TYPE_SMF,
+ RES_TYPE_PF_BW_CFG,
+
+ RES_TYPE_COMM = 10,
+ RES_TYPE_COMM_MGMT_CH, /* clear mbox and aeq, The RES_TYPE_COMM bit must be set */
+ RES_TYPE_COMM_CMD_CH, /* clear cmdq and ceq, The RES_TYPE_COMM bit must be set */
+ RES_TYPE_NIC,
+ RES_TYPE_OVS,
+ RES_TYPE_VBS,
+ RES_TYPE_ROCE,
+ RES_TYPE_FC,
+ RES_TYPE_TOE,
+ RES_TYPE_IPSEC,
+ RES_TYPE_MAX,
+};
+
+#define HINIC3_COMM_RES \
+ ((1 << RES_TYPE_COMM) | (1 << RES_TYPE_COMM_CMD_CH) | \
+ (1 << RES_TYPE_FLUSH_BIT) | (1 << RES_TYPE_MQM) | \
+ (1 << RES_TYPE_SMF) | (1 << RES_TYPE_PF_BW_CFG))
+
+#define HINIC3_NIC_RES (1 << RES_TYPE_NIC)
+#define HINIC3_OVS_RES (1 << RES_TYPE_OVS)
+#define HINIC3_VBS_RES (1 << RES_TYPE_VBS)
+#define HINIC3_ROCE_RES (1 << RES_TYPE_ROCE)
+#define HINIC3_FC_RES (1 << RES_TYPE_FC)
+#define HINIC3_TOE_RES (1 << RES_TYPE_TOE)
+#define HINIC3_IPSEC_RES (1 << RES_TYPE_IPSEC)
+
+/* MODE OVS、NIC、UNKNOWN */
+#define HINIC3_WORK_MODE_OVS 0
+#define HINIC3_WORK_MODE_UNKNOWN 1
+#define HINIC3_WORK_MODE_NIC 2
+
+#define DEVICE_TYPE_L2NIC 0
+#define DEVICE_TYPE_NVME 1
+#define DEVICE_TYPE_VIRTIO_NET 2
+#define DEVICE_TYPE_VIRTIO_BLK 3
+#define DEVICE_TYPE_VIRTIO_VSOCK 4
+#define DEVICE_TYPE_VIRTIO_NET_TRANSITION 5
+#define DEVICE_TYPE_VIRTIO_BLK_TRANSITION 6
+#define DEVICE_TYPE_VIRTIO_SCSI_TRANSITION 7
+#define DEVICE_TYPE_VIRTIO_HPC 8
+#define DEVICE_TYPE_VIRTIO_FS 9
+
+#define IS_STORAGE_DEVICE_TYPE(dev_type) \
+ ((dev_type) == DEVICE_TYPE_VIRTIO_BLK || \
+ (dev_type) == DEVICE_TYPE_VIRTIO_BLK_TRANSITION || \
+ (dev_type) == DEVICE_TYPE_VIRTIO_SCSI_TRANSITION || \
+ (dev_type) == DEVICE_TYPE_VIRTIO_FS)
+
+#define MGMT_MSG_CMD_OP_SET 1
+#define MGMT_MSG_CMD_OP_GET 0
+
+#define MGMT_MSG_CMD_OP_START 1
+#define MGMT_MSG_CMD_OP_STOP 0
+
+#define HOT_REPLACE_PARTITION_NUM 2
enum hinic3_svc_type {
SVC_T_COMM = 0,
@@ -23,4 +110,54 @@ enum hinic3_svc_type {
SVC_T_MAX,
};
+/**
+ * Common header control information of the COMM message interaction
+ * command word between the driver and PF
+ * struct mgmt_msg_head and struct comm_info_head are the same structure
+ */
+struct mgmt_msg_head {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+};
+
+/**
+ * Common header control information of the COMM message interaction
+ * command word between the driver and PF
+ */
+struct comm_info_head {
+ /** response status code, 0: success, others: error code */
+ u8 status;
+
+ /** firmware version for command */
+ u8 version;
+
+ /** response aeq number, unused for now */
+ u8 rep_aeq_num;
+ u8 rsvd[5];
+};
+
+static inline u32 get_function_partition(u32 function_id, u32 port_num)
+{
+ return (function_id / port_num) % HOT_REPLACE_PARTITION_NUM;
+}
+
+static inline u32 is_primary_function(u32 function_id, u32 port_num)
+{
+ return (function_id / port_num) % HOT_REPLACE_PARTITION_NUM == 0;
+}
+
+static inline u32 mpu_nic_get_primary_function(u32 function_id, u32 port_num)
+{
+ return ((function_id / port_num) % HOT_REPLACE_PARTITION_NUM == 0) ?
+ function_id : (function_id - port_num);
+}
+
+// when func_id is in partition 0/1, it will get its another func_id in partition 1/0
+static inline u32 mpu_nic_get_backup_function(u32 function_id, u32 port_num)
+{
+ return ((function_id / port_num) % HOT_REPLACE_PARTITION_NUM == 0) ?
+ (function_id + port_num) : (function_id - port_num);
+}
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h
index a8e2d63..3841bb5 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h
@@ -91,6 +91,10 @@ enum hinic3_mgmt_cmd {
* @see comm_read_ucode_sm_resp
*/
COMM_MGMT_CMD_CLEAR_LOG, /**< clear log @see comm_cmd_clear_log_s */
+ COMM_MGMT_CMD_UCODE_SM_COUNTER_PER,
+ /**< get ucode sm counter @see struct comm_read_ucode_sm_per_req
+ * @see struct comm_read_ucode_sm_per_resp
+ */
COMM_MGMT_CMD_CHECK_IF_SWITCH_WORKMODE = 140, /* check if switch workmode reserved
* @see comm_cmd_check_if_switch_workmode
@@ -103,6 +107,7 @@ enum hinic3_mgmt_cmd {
COMM_MGMT_CMD_CPI_TCAM_DBG, /* enable or disable the scheduled cpi tcam task,
* set task interval time @see comm_cmd_cpi_tcam_dbg_s
*/
+ COMM_MGMT_CMD_LLDP_TX_FUNC_SET,
COMM_MGMT_CMD_SECTION_RSVD_0 = 160, /**< rsvd0 section */
COMM_MGMT_CMD_SECTION_RSVD_1 = 170, /**< rsvd1 section */
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h
index 674603d..698730f 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h
@@ -338,7 +338,8 @@ struct comm_cmd_get_fw_version {
struct mgmt_msg_head head;
u16 fw_type; /**< firmware type @see enum hinic3_fw_ver_type */
- u16 rsvd1;
+ u16 fw_dfx_vld : 1; /**< 0: release, 1: debug */
+ u16 rsvd1 : 15;
u8 ver[HINIC3_FW_VERSION_LEN]; /**< firmware version */
u8 time[HINIC3_FW_COMPILE_TIME_LEN]; /**< firmware compile time */
};
@@ -430,6 +431,22 @@ struct comm_cmd_bdf_info {
u8 rsvd2[5];
};
+struct mpu_pcie_pf_info {
+ u32 device_id; /**< device id */
+ u32 vendor_id; /**< vendor id */
+};
+
+struct mpu_pcie_device_info {
+ u8 status;
+ u8 version;
+ u8 rep_aeq_num;
+ u8 rsvd[5];
+
+ struct mpu_pcie_pf_info pf_info[32];
+ u32 bus_id; /**< bus id */
+ u32 pf_num; /**< pf index */
+};
+
#define TABLE_INDEX_MAX 129
struct sml_table_id_info {
u8 node_id;
@@ -446,6 +463,13 @@ struct comm_cmd_sdi_info {
u32 cfg_sdi_mode; /**< host mode, 0:normal 1:virtual machine 2:bare metal */
};
+struct comm_cmd_root_ctx_load_req {
+ struct comm_info_head head;
+ u32 func_id; /**< function id */
+ u32 smf_id; /**< smf id */
+ u32 queue_id; /**< queue id */
+};
+
#define HINIC_OVS_BOND_DEFAULT_ID 1
struct hinic3_hw_bond_infos {
u8 bond_id;
@@ -685,6 +709,28 @@ struct comm_read_ucode_sm_resp {
u64 val2;
};
+#define PER_REQ_MAX_DATA_LEN 0x600
+
+struct comm_read_ucode_sm_per_req {
+ struct mgmt_msg_head msg_head;
+
+ u32 tbl_type;
+ u32 count_id;
+};
+
+struct comm_read_ucode_sm_per_resp {
+ struct mgmt_msg_head msg_head;
+
+ u8 data[PER_REQ_MAX_DATA_LEN];
+};
+
+struct ucode_sm_counter_get_info {
+ u32 width_type;
+ u32 tbl_type;
+ unsigned int base_count;
+ unsigned int count_num;
+};
+
enum log_type {
MPU_LOG_CLEAR = 0,
SMU_LOG_CLEAR = 1,
@@ -693,6 +739,11 @@ enum log_type {
ALL_LOG_CLEAR = 4,
};
+struct comm_cmd_clear_log {
+ struct comm_info_head head;
+ u32 type; /**< log type @see enum log_type */
+};
+
#define ABLESWITCH 1
#define IMABLESWITCH 2
enum switch_workmode_op {
@@ -717,6 +768,14 @@ struct comm_cmd_check_if_switch_workmode {
u32 rsvd3[3];
};
+struct comm_cmd_switch_workmode {
+ struct mgmt_msg_head head;
+ u8 operation;
+ u8 work_mode;
+ u16 rsvd1[3];
+ u32 rsvd2[3];
+};
+
#define MIG_NOR_VM_ONE_MAX_SGE_MEM (64 * 8)
#define MIG_NOR_VM_ONE_MAX_MEM (MIG_NOR_VM_ONE_MAX_SGE_MEM + 16)
#define MIG_VM_MAX_SML_ENTRY_NUM 24
@@ -755,6 +814,15 @@ struct cmd_get_bdf_info_s {
#define CPI_TCAM_DBG_CMD_TYPE_SET 0
#define CPI_TCAM_DBG_CMD_TYPE_GET 1
+struct comm_cmd_cpi_tcam_dbg {
+ struct comm_info_head head;
+ u8 type;
+ u8 set_bitmap;
+ u8 enable;
+ u8 rsvd;
+ u32 time_interval;
+};
+
#define UDIE_ID_DATA_LEN 8
#define TDIE_ID_DATA_LEN 18
struct comm_cmd_get_die_id {
@@ -808,6 +876,12 @@ struct cmd_query_fw {
u32 len; /**< length */
};
+struct comm_cmd_get_cfg_info_t {
+ struct comm_info_head head;
+ u8 rsvd[8];
+ u8 info[64]; /**< flash config info */
+};
+
struct nic_cmd_get_uart_log_info {
struct comm_info_head head;
struct {
@@ -969,6 +1043,7 @@ enum comm_virtio_dev_type {
COMM_VIRTIO_NET_TYPE = 0,
COMM_VIRTIO_BLK_TYPE = 1,
COMM_VIRTIO_SCSI_TYPE = 4,
+ COMM_VIRTIO_FS_TYPE = 5,
};
struct comm_virtio_dev_cmd {
@@ -1030,6 +1105,13 @@ struct cmd_patch_sram_optimize {
u32 data[4]; /**< reserved */
};
+struct comm_cmd_con_sel_sta {
+ struct comm_info_head head;
+ u8 valid;
+ u8 host_id; /**< host id, range[0,3] */
+ u8 rsvd[2];
+};
+
/* ncsi counter */
struct nsci_counter_in_info_s {
struct comm_info_head head;
@@ -1082,7 +1164,9 @@ struct comm_cmd_ncsi_settings {
u8 lldp_over_ncsi_enable;
u8 lldp_over_mctp_enable;
u32 magicwd;
- u8 rsvd[8];
+ u8 lldp_tx_enable;
+ u8 rsvd[3];
+ u32 crc;
struct tag_ncsi_chan_info ncsi_chan_info;
};
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h
index fde8617..1ee44a8 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h
@@ -114,6 +114,14 @@ struct tag_ncsi_client_info {
#define AEN_CTRL_CONFIG_REQ_SHIFT 1
#define AEN_CTRL_DRV_CHANGE_SHIFT 2
+/* AEN Type */
+enum aen_type_e {
+ AEN_LINK_STATUS_CHANGE_TYPE = 0x0,
+ AEN_CONFIG_REQUIRED_TYPE = 0x1,
+ OEM_AEN_CONFIG_REQUEST_TYPE = 0x80,
+ AEN_TYPE_MAX = 0x100
+};
+
/* get link status 0x0A */
#define GET_LINK_STATUS_REQ_LEN 0
#define GET_LINK_STATUS_RSP_LEN 16
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h
index 0bd168c..5b2bdc8 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h
@@ -36,6 +36,7 @@ enum nic_rss_hash_type {
#define NIC_RX_MODE_BC 0x04
#define NIC_RX_MODE_MC_ALL 0x08
#define NIC_RX_MODE_PROMISC 0x10
+#define NIC_RX_DB_COS_MAX 0x4
/* IEEE 802.1Qaz std */
#define NIC_DCB_COS_MAX 0x8
@@ -52,4 +53,7 @@ enum nic_rss_hash_type {
#define NIC_DCB_PRIO_STRICT 0x1
#define NIC_DCB_MAX_PFC_NUM 0x4
+
+#define NIC_ETS_PERCENT_WEIGHT 100
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/vram_common.h b/drivers/net/ethernet/huawei/hinic3/include/vram_common.h
index 801aeed..5476287 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/vram_common.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/vram_common.h
@@ -23,7 +23,11 @@
#define VRAM_CQM_BITMAP_BASE "B"
#define VRAM_NIC_DCB "DCB"
+#define VRAM_NIC_MHOST_MGMT "MHOST_MGMT"
#define VRAM_NIC_VRAM "NIC_VRAM"
+#define VRAM_NIC_IRQ_VRAM "NIC_IRQ"
+
+#define VRAM_NIC_MQM "NM"
#define VRAM_VBS_BASE_IOCB "BASE_IOCB"
#define VRAM_VBS_EX_IOCB "EX_IOCB"
@@ -32,6 +36,9 @@
#define VRAM_VBS_VOLQ_MTT "VOLQ_MTT"
#define VRAM_VBS_VOLQ_MTT_PAGE "MTT_PAGE"
+#define VRAM_OVS_PORT_CONF "OVS_PORT_CONF"
+#define VRAM_OVS_DFX_MGR "OVS_DFX_MGR"
+
#define VRAM_VROCE_ENTRY_POOL "VROCE_ENTRY"
#define VRAM_VROCE_GROUP_POOL "VROCE_GROUP"
#define VRAM_VROCE_UUID "VROCE_UUID"
@@ -42,6 +49,17 @@
#define VRAM_VROCE_DEV "VROCE_DEV"
#define VRAM_VROCE_RGROUP_HT_CNT "RGROUP_CNT"
#define VRAM_VROCE_RACL_HT_CNT "RACL_CNT"
+#define VRAM_VROCE_MQM_ENQC "VROCE_MQM_ENQC"
+
+#define VRAM_DTOE_NUMA_MEM "DTOE_NUMA"
+#define VRAM_DTOE_CARD_MEM "DTOE_CARD"
+#define VRAM_DTOE_CONN_MEM "DTOE_CONN"
+#define VRAM_DTOE_SUB_LEN 10
+
+#define VRAM_VROCE_MIG_ENTRY_POOL "VROCE_MIG_ENTRY"
+#define VRAM_VROCE_MIG_ENTRY_HT_CNT "MIG_ENTRY_CNT"
+
+#define VRAM_VBS_DEV_INDEX "VBS_INDEX"
#define VRAM_NAME_APPLY_LEN 64
@@ -55,11 +73,16 @@ enum KUP_HOOK_POINT {
PRE_FREEZE,
FREEZE_TO_KILL,
PRE_UPDATE_KERNEL,
- FLUSH_DURING_KUP,
POST_UPDATE_KERNEL,
UNFREEZE_TO_RUN,
POST_RUN,
KUP_HOOK_MAX,
};
+#define hi_vram_kalloc(name, size) 0
+#define hi_vram_kfree(vaddr, name, size)
+#define get_use_vram_flag(void) 0
+#define vram_get_kexec_flag(void) 0
+#define hi_vram_get_gfp_vram(void) 0
+
#endif /* VRAM_COMMON_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/mag_cmd.h b/drivers/net/ethernet/huawei/hinic3/mag_mpu_cmd_defs.h
similarity index 79%
rename from drivers/net/ethernet/huawei/hinic3/mag_cmd.h
rename to drivers/net/ethernet/huawei/hinic3/mag_mpu_cmd_defs.h
index 9649503..c8533e5 100644
--- a/drivers/net/ethernet/huawei/hinic3/mag_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/mag_mpu_cmd_defs.h
@@ -9,6 +9,7 @@
/* serdes cmd struct define */
#define CMD_ARRAY_BUF_SIZE 64
#define SERDES_CMD_DATA_BUF_SIZE 512
+#define RATE_MBPS_TO_GBPS 1000
struct serdes_in_info {
u32 chip_id : 16;
u32 macro_id : 16;
@@ -127,6 +128,7 @@ enum mag_cmd_cnt_type {
MAG_RX_PCS_E_BLK_CNT = 5,
MAG_RX_PCS_DEC_ERR_BLK_CNT = 6,
MAG_RX_PCS_LANE_BIP_ERR_CNT = 7,
+ MAG_RX_RSFEC_ERR_CW_CNT = 8,
MAG_CNT_NUM
};
@@ -208,7 +210,9 @@ struct mag_cmd_get_port_info {
u32 supported_mode;
u32 advertised_mode;
- u8 rsvd2[8];
+ u32 supported_fec_mode;
+ u16 bond_speed;
+ u8 rsvd2[2];
};
#define MAG_CMD_OPCODE_GET 0
@@ -330,8 +334,8 @@ struct mag_cmd_cfg_fec_mode {
u8 port_id;
u8 opcode; /* 0:get fec mode 1:set fec mode */
- u8 fec;
- u8 rsvd0;
+ u8 advertised_fec;
+ u8 supported_fec;
};
/* speed */
@@ -641,7 +645,7 @@ struct mag_cmd_event_port_info {
u32 cable_length; /* 1/3/5m */
u8 cable_temp; /* temp */
u8 max_speed; /* Maximum rate of an optical module */
- u8 sfp_type; /* sfp/qsfp */
+ u8 sfp_type; /* sfp/qsfp/dsfp */
u8 rsvd1;
u32 power[4]; /* Optical Power */
@@ -678,6 +682,10 @@ struct mag_cmd_event_port_info {
u8 rsvd3[360];
};
+struct mag_cmd_rsfec_stats {
+ u32 rx_err_lane_phy;
+};
+
struct mag_cmd_port_stats {
u64 mac_tx_fragment_pkt_num;
u64 mac_tx_undersize_pkt_num;
@@ -913,10 +921,222 @@ struct mag_cmd_sfp_temp_in_info {
};
struct mag_cmd_sfp_temp_out_info {
- struct mgmt_msg_head head; /* 8B */
- s16 sfp_temp_data[MAG_SFP_PORT_NUM]; /* Temperature read */
- s32 max_temp; /* Chip optical module threshold */
- s32 min_temp; /* Chip optical module threshold */
+ struct mgmt_msg_head head; /* 8B */
+ s16 sfp_temp_data[MAG_SFP_PORT_NUM]; /* Temperature read */
+ s32 max_temp; /* Chip optical module threshold */
+ s32 min_temp; /* Chip optical module threshold */
+};
+
+#define XSFP_CMIS_PARSE_PAGE_NUM 6
+#define XSFP_CMIS_INFO_MAX_SIZE 1536
+#define QSFP_CMIS_PAGE_SIZE 128
+#define QSFP_CMIS_MAX_CHANNEL_NUM 0x8
+
+/* Lower: Control and Essentials, Upper: Administrative Information */
+#define QSFP_CMIS_PAGE_00H 0x00
+/* Advertising */
+#define QSFP_CMIS_PAGE_01H 0x01
+/* Module and lane Thresholds */
+#define QSFP_CMIS_PAGE_02H 0x02
+/* User EEPROM */
+#define QSFP_CMIS_PAGE_03H 0x03
+/* Laser Capabilities Advertising (Page 04h, Optional) */
+#define QSFP_CMIS_PAGE_04H 0x04
+#define QSFP_CMIS_PAGE_05H 0x05
+/* Lane and Data Path Control */
+#define QSFP_CMIS_PAGE_10H 0x10
+/* Lane Status */
+#define QSFP_CMIS_PAGE_11H 0x11
+#define QSFP_CMIS_PAGE_12H 0x12
+
+#define MGMT_TLV_U8_SIZE 1
+#define MGMT_TLV_U16_SIZE 2
+#define MGMT_TLV_U32_SIZE 4
+
+#define MGMT_TLV_GET_U8(addr) (*((u8 *)(void *)(addr)))
+#define MGMT_TLV_SET_U8(addr, value) \
+ ((*((u8 *)(void *)(addr))) = ((u8)(value)))
+
+#define MGMT_TLV_GET_U16(addr) (*((u16 *)(void *)(addr)))
+#define MGMT_TLV_SET_U16(addr, value) \
+ ((*((u16 *)(void *)(addr))) = ((u16)(value)))
+
+#define MGMT_TLV_GET_U32(addr) (*((u32 *)(void *)(addr)))
+#define MGMT_TLV_SET_U32(addr, value) \
+ ((*((u32 *)(void *)(addr))) = ((u32)(value)))
+
+#define MGMT_TLV_TYPE_END 0xFFFF
+
+enum mag_xsfp_type {
+ MAG_XSFP_TYPE_PAGE = 0x01,
+ MAG_XSFP_TYPE_WIRE_TYPE = 0x02,
+ MAG_XSFP_TYPE_END = MGMT_TLV_TYPE_END
+};
+
+struct qsfp_cmis_lower_page_00_s {
+ u8 resv0[14];
+ u8 temperature_msb;
+ u8 temperature_lsb;
+ u8 volt_supply[2];
+ u8 resv1[67];
+ u8 media_type;
+ u8 electrical_interface_id;
+ u8 media_interface_id;
+ u8 lane_count;
+ u8 resv2[39];
+};
+
+struct qsfp_cmis_upper_page_00_s {
+ u8 identifier;
+ u8 vendor_name[16];
+ u8 vendor_oui[3];
+ u8 vendor_pn[16];
+ u8 vendor_rev[2];
+ u8 vendor_sn[16];
+ u8 date_code[8];
+ u8 clei_code[10];
+ u8 power_character[2];
+ u8 cable_len;
+ u8 connector;
+ u8 copper_cable_attenuation[6];
+ u8 near_end_implementation;
+ u8 far_end_config;
+ u8 media_technology;
+ u8 resv0[43];
+};
+
+struct qsfp_cmis_upper_page_01_s {
+ u8 firmware_rev[2];
+ u8 hardware_rev[2];
+ u8 smf_len_km;
+ u8 om5_len;
+ u8 om4_len;
+ u8 om3_len;
+ u8 om2_len;
+ u8 resv0;
+ u8 wavelength[2];
+ u8 wavelength_tolerance[2];
+ u8 pages_implement;
+ u8 resv1[16];
+ u8 monitor_implement[2];
+ u8 resv2[95];
+};
+
+struct qsfp_cmis_upper_page_02_s {
+ u8 temperature_high_alarm[2];
+ u8 temperature_low_alarm[2];
+ u8 temperature_high_warn[2];
+ u8 temperature_low_warn[2];
+ u8 volt_high_alarm[2];
+ u8 volt_low_alarm[2];
+ u8 volt_high_warn[2];
+ u8 volt_low_warn[2];
+ u8 resv0[32];
+ u8 tx_power_high_alarm[2];
+ u8 tx_power_low_alarm[2];
+ u8 tx_power_high_warn[2];
+ u8 tx_power_low_warn[2];
+ u8 tx_bias_high_alarm[2];
+ u8 tx_bias_low_alarm[2];
+ u8 tx_bias_high_warn[2];
+ u8 tx_bias_low_warn[2];
+ u8 rx_power_high_alarm[2];
+ u8 rx_power_low_alarm[2];
+ u8 rx_power_high_warn[2];
+ u8 rx_power_low_warn[2];
+ u8 resv1[56];
+};
+
+struct qsfp_cmis_upper_page_03_s {
+ u8 resv0[QSFP_CMIS_PAGE_SIZE]; /* Reg 128-255: Upper Memory: Page 03H */
+};
+
+struct qsfp_cmis_upper_page_10_s {
+ u8 resv0[2]; /* Reg 128-129: Upper Memory: Page 10H */
+ u8 tx_disable; /* Reg 130: Tx disable, 0b=enabled, 1b=disabled */
+ u8 resv1[125]; /* Reg 131-255 */
+};
+
+struct qsfp_cmis_upper_page_11_s {
+ u8 resv0[7];
+ u8 tx_fault;
+ u8 tx_los;
+ u8 resv1[10];
+ u8 rx_los;
+ u8 resv2[6];
+ u8 tx_power[16];
+ u8 tx_bias[16];
+ u8 rx_power[16];
+ u8 resv3[54];
+};
+
+struct qsfp_cmis_info_s {
+ struct qsfp_cmis_lower_page_00_s lower_page_00;
+ struct qsfp_cmis_upper_page_00_s upper_page_00;
+ struct qsfp_cmis_upper_page_01_s upper_page_01;
+ struct qsfp_cmis_upper_page_02_s upper_page_02;
+ struct qsfp_cmis_upper_page_10_s upper_page_10;
+ struct qsfp_cmis_upper_page_11_s upper_page_11;
+};
+
+struct qsfp_cmis_comm_power_s {
+ u32 chl_power[QSFP_CMIS_MAX_CHANNEL_NUM];
+};
+
+struct qsfp_cmis_wire_info_s {
+ struct qsfp_cmis_comm_power_s rx_power;
+ u8 rx_los;
+ u8 resv0[3];
+};
+
+struct mgmt_tlv_info {
+ u16 type;
+ u16 length;
+ u8 value[];
+};
+
+struct mag_cmd_set_xsfp_tlv_req {
+ struct mgmt_msg_head head;
+
+ u8 tlv_buf[];
+};
+
+struct mag_cmd_set_xsfp_tlv_rsp {
+ struct mgmt_msg_head head;
+};
+
+struct tag_mag_cmd_get_xsfp_tlv_req {
+ struct mgmt_msg_head head;
+
+ u8 port_id;
+ u8 rsvd;
+ u16 rsp_buf_len;
+};
+
+struct mag_cmd_get_xsfp_tlv_rsp {
+ struct mgmt_msg_head head;
+
+ u8 port_id;
+ u8 rsvd[3];
+
+ u8 tlv_buf[];
+};
+
+struct parse_tlv_info {
+ u8 tlv_page_info[XSFP_CMIS_INFO_MAX_SIZE + 1];
+ u32 tlv_page_info_len;
+ u32 tlv_page_num[XSFP_CMIS_PARSE_PAGE_NUM];
+ u32 wire_type;
+ u8 id;
+};
+
+struct drv_tag_mag_cmd_get_xsfp_tlv_rsp {
+ struct mgmt_msg_head head;
+
+ u8 port_id;
+ u8 rsvd[3];
+
+ u8 tlv_buf[XSFP_CMIS_INFO_MAX_SIZE];
};
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h b/drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h
deleted file mode 100644
index 257bf67..0000000
--- a/drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
- * File Name : mgmt_msg_base.h
- * Version : Initial Draft
- * Created : 2021/6/28
- * Last Modified :
- * Description : COMM Command interfaces between Driver and MPU
- * Function List :
- */
-
-#ifndef MGMT_MSG_BASE_H
-#define MGMT_MSG_BASE_H
-
-#define MGMT_MSG_CMD_OP_SET 1
-#define MGMT_MSG_CMD_OP_GET 0
-
-#define MGMT_MSG_CMD_OP_START 1
-#define MGMT_MSG_CMD_OP_STOP 0
-
-struct mgmt_msg_head {
- u8 status;
- u8 version;
- u8 rsvd0[6];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h b/drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h
deleted file mode 100644
index abcfa27..0000000
--- a/drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C), 2001-2021, Huawei Tech. Co., Ltd.
- * File Name : nic_cfg_comm.h
- * Version : Initial Draft
- * Description : nic config common header file
- * Function List :
- * History :
- * Modification: Created file
- */
-
-#ifndef NIC_CFG_COMM_H
-#define NIC_CFG_COMM_H
-
-#include <linux/types.h>
-
-/* rss */
-#define HINIC3_RSS_TYPE_VALID_SHIFT 23
-#define HINIC3_RSS_TYPE_TCP_IPV6_EXT_SHIFT 24
-#define HINIC3_RSS_TYPE_IPV6_EXT_SHIFT 25
-#define HINIC3_RSS_TYPE_TCP_IPV6_SHIFT 26
-#define HINIC3_RSS_TYPE_IPV6_SHIFT 27
-#define HINIC3_RSS_TYPE_TCP_IPV4_SHIFT 28
-#define HINIC3_RSS_TYPE_IPV4_SHIFT 29
-#define HINIC3_RSS_TYPE_UDP_IPV6_SHIFT 30
-#define HINIC3_RSS_TYPE_UDP_IPV4_SHIFT 31
-
-#define HINIC3_RSS_TYPE_SET(val, member) (((u32)(val) & 0x1) << HINIC3_RSS_TYPE_##member##_SHIFT)
-#define HINIC3_RSS_TYPE_GET(val, member) (((u32)(val) >> HINIC3_RSS_TYPE_##member##_SHIFT) & 0x1)
-
-enum nic_rss_hash_type {
- NIC_RSS_HASH_TYPE_XOR = 0,
- NIC_RSS_HASH_TYPE_TOEP,
-
- NIC_RSS_HASH_TYPE_MAX /* MUST BE THE LAST ONE */
-};
-
-#define NIC_RSS_INDIR_SIZE 256
-#define NIC_RSS_KEY_SIZE 40
-
-/* *
- * Definition of the NIC receiving mode
- */
-#define NIC_RX_MODE_UC 0x01
-#define NIC_RX_MODE_MC 0x02
-#define NIC_RX_MODE_BC 0x04
-#define NIC_RX_MODE_MC_ALL 0x08
-#define NIC_RX_MODE_PROMISC 0x10
-
-/* IEEE 802.1Qaz std */
-#define NIC_DCB_COS_MAX 0x8
-#define NIC_DCB_UP_MAX 0x8
-#define NIC_DCB_TC_MAX 0x8
-#define NIC_DCB_PG_MAX 0x8
-#define NIC_DCB_TSA_SP 0x0
-#define NIC_DCB_TSA_CBS 0x1
-#define NIC_DCB_TSA_ETS 0x2
-#define NIC_DCB_DSCP_NUM 0x8
-#define NIC_DCB_IP_PRI_MAX 0x40
-
-#define NIC_DCB_PRIO_DWRR 0x0
-#define NIC_DCB_PRIO_STRICT 0x1
-
-#define NIC_DCB_MAX_PFC_NUM 0x4
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cmd.h b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd.h
similarity index 77%
rename from drivers/net/ethernet/huawei/hinic3/hinic3_nic_cmd.h
rename to drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd.h
index c35bc82..b0114a0 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
- * File Name : hinic3_comm_cmd.h
+ * File Name : hinic3_nic_mpu_cmd.h
* Version : Initial Draft
* Created : 2019/4/25
* Last Modified :
@@ -33,10 +33,11 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_CFG_LOCAL_LRO_STATE,
HINIC3_NIC_CMD_CACHE_OUT_QP_RES,
+ HINIC3_NIC_CMD_SET_FUNC_ER_FWD_ID,
HINIC3_NIC_CMD_SET_RQ_CI_CTX,
- /* MAC & VLAN CFG */
+ /* MAC & VLAN CFG & VXLAN CFG */
HINIC3_NIC_CMD_GET_MAC = 20,
HINIC3_NIC_CMD_SET_MAC,
HINIC3_NIC_CMD_DEL_MAC,
@@ -47,6 +48,11 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_SET_VLAN_FILTER_EN,
HINIC3_NIC_CMD_SET_RX_VLAN_OFFLOAD,
HINIC3_NIC_CMD_SMAC_CHECK_STATE,
+ HINIC3_NIC_CMD_OUTBAND_SET_FUNC_VLAN,
+ HINIC3_NIC_CMD_CFG_VXLAN_PORT,
+
+ HINIC3_NIC_CMD_RX_RATE_CFG,
+ HINIC3_NIC_CMD_WR_ORDERING_CFG,
/* SR-IOV */
HINIC3_NIC_CMD_CFG_VF_VLAN = 40,
@@ -63,6 +69,7 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_SET_RSS_CTX_TBL_INTO_FUNC,
/* IP checksum error packets, enable rss quadruple hash */
HINIC3_NIC_CMD_IPCS_ERR_RSS_ENABLE_OP = 66,
+ HINIC3_NIC_CMD_GTP_INNER_PARSE_STATUS,
/* PPA/FDIR */
HINIC3_NIC_CMD_ADD_TC_FLOW = 80,
@@ -78,6 +85,10 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_CFG_PPA_FLUSH,
HINIC3_NIC_CMD_SET_FDIR_STATUS,
HINIC3_NIC_CMD_GET_PPA_COUNTER,
+ HINIC3_NIC_CMD_SET_FUNC_FLOW_BIFUR_ENABLE,
+ HINIC3_NIC_CMD_SET_BOND_MASK,
+ HINIC3_NIC_CMD_GET_BLOCK_TC_FLOWS,
+ HINIC3_NIC_CMD_GET_BOND_MASK,
/* PORT CFG */
HINIC3_NIC_CMD_SET_PORT_ENABLE = 100,
@@ -96,6 +107,8 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_QOS_PORT_CFG,
HINIC3_NIC_CMD_QOS_MAP_CFG,
HINIC3_NIC_CMD_FORCE_PKT_DROP,
+ HINIC3_NIC_CMD_CFG_TX_PROMISC_SKIP = 114,
+ HINIC3_NIC_CMD_SET_PORT_FLOW_BIFUR_ENABLE = 117,
HINIC3_NIC_CMD_TX_PAUSE_EXCP_NOTICE = 118,
HINIC3_NIC_CMD_INQUIRT_PAUSE_CFG = 119,
@@ -118,6 +131,10 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_SET_UCAPTURE_OPT = 160, /* TODO: move to roce */
HINIC3_NIC_CMD_SET_VHD_CFG,
+ /* OUT OF BAND */
+ HINIC3_NIC_CMD_GET_OUTBAND_CFG = 170, /* Get outband vlan cfg info */
+ HINIC3_NIC_CMD_OUTBAND_CFG_NOTICE, /* Outband vlan cfg info report */
+
/* TODO: move to HILINK */
HINIC3_NIC_CMD_GET_PORT_STAT = 200,
HINIC3_NIC_CMD_CLEAN_PORT_STAT,
@@ -138,24 +155,23 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_LINK_ERR_EVENT,
HINIC3_NIC_CMD_SET_LED_STATUS,
- HINIC3_NIC_CMD_MAX = 256,
-};
+ /* mig */
+ HINIC3_NIC_CMD_MIG_SET_CEQ_CTRL = 230,
+ HINIC3_NIC_CMD_MIG_CFG_MSIX_INFO,
+ HINIC3_NIC_CMD_MIG_CFG_FUNC_VAT_TBL,
+ HINIC3_NIC_CMD_MIG_GET_VF_INFO,
+ HINIC3_NIC_CMD_MIG_CHK_MBX_EMPTY,
+ HINIC3_NIC_CMD_MIG_SET_VPORT_ENABLE,
+ HINIC3_NIC_CMD_MIG_CFG_SQ_CI,
+ HINIC3_NIC_CMD_MIG_CFG_RSS_TBL,
+ HINIC3_NIC_CMD_MIG_CFG_MAC_TBL,
+ HINIC3_NIC_CMD_MIG_TMP_SET_CMDQ_CTX,
-/* NIC CMDQ MODE */
-enum hinic3_ucode_cmd {
- HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX = 0,
- HINIC3_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
- HINIC3_UCODE_CMD_ARM_SQ,
- HINIC3_UCODE_CMD_ARM_RQ,
- HINIC3_UCODE_CMD_SET_RSS_INDIR_TABLE,
- HINIC3_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
- HINIC3_UCODE_CMD_GET_RSS_INDIR_TABLE,
- HINIC3_UCODE_CMD_GET_RSS_CONTEXT_TABLE,
- HINIC3_UCODE_CMD_SET_IQ_ENABLE,
- HINIC3_UCODE_CMD_SET_RQ_FLUSH = 10,
- HINIC3_UCODE_CMD_MODIFY_VLAN_CTX,
- HINIC3_UCODE_CMD_PPA_HASH_TABLE,
- HINIC3_UCODE_CMD_RXQ_INFO_GET = 13,
+ HINIC3_OSHR_CMD_ACTIVE_FUNCTION = 240,
+
+ HINIC3_NIC_CMD_GET_RQ_INFO = 241,
+
+ HINIC3_NIC_CMD_MAX = 256,
};
#endif /* HINIC3_NIC_CMD_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h
new file mode 100644
index 0000000..5c28573
--- /dev/null
+++ b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h
@@ -0,0 +1,1440 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2024 Huawei Technologies Co., Ltd */
+
+#ifndef NIC_MPU_CMD_DEFS_H
+#define NIC_MPU_CMD_DEFS_H
+
+#include "nic_cfg_comm.h"
+#include "mpu_cmd_base_defs.h"
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#define HINIC3_CMD_OP_SET 1
+#define HINIC3_CMD_OP_GET 0
+
+#define HINIC3_CMD_OP_ADD 1
+#define HINIC3_CMD_OP_DEL 0
+
+#define NIC_TCAM_BLOCK_LARGE_NUM 256
+#define NIC_TCAM_BLOCK_LARGE_SIZE 16
+
+#define TRAFFIC_BIFUR_MODEL_TYPE 2
+
+#define NIC_TCAM_FLOW_BIFUR_FLAG (1 << 0)
+
+#ifndef BIT
+#define BIT(n) (1UL << (n))
+#endif
+
+enum nic_feature_cap {
+ NIC_F_CSUM = BIT(0),
+ NIC_F_SCTP_CRC = BIT(1),
+ NIC_F_TSO = BIT(2),
+ NIC_F_LRO = BIT(3),
+ NIC_F_UFO = BIT(4),
+ NIC_F_RSS = BIT(5),
+ NIC_F_RX_VLAN_FILTER = BIT(6),
+ NIC_F_RX_VLAN_STRIP = BIT(7),
+ NIC_F_TX_VLAN_INSERT = BIT(8),
+ NIC_F_VXLAN_OFFLOAD = BIT(9),
+ NIC_F_IPSEC_OFFLOAD = BIT(10),
+ NIC_F_FDIR = BIT(11),
+ NIC_F_PROMISC = BIT(12),
+ NIC_F_ALLMULTI = BIT(13),
+ NIC_F_XSFP_REPORT = BIT(14),
+ NIC_F_VF_MAC = BIT(15),
+ NIC_F_RATE_LIMIT = BIT(16),
+ NIC_F_RXQ_RECOVERY = BIT(17),
+ NIC_F_TX_COMPACT_WQE_OL = BIT(19),
+ NIC_F_RX_COMPACT_CQE = BIT(20),
+ NIC_F_HTN_CMDQ = BIT(21),
+};
+
+#define NIC_F_ALL_MASK 0x7FBFFFF /* 使能所有属性 */
+
+struct hinic3_mgmt_msg_head {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+};
+
+#define NIC_MAX_FEATURE_QWORD 4
+struct hinic3_cmd_feature_nego {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 1: set, 0: get */
+ u8 rsvd;
+ u64 s_feature[NIC_MAX_FEATURE_QWORD];
+};
+
+struct hinic3_port_mac_set {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 vlan_id;
+ u16 rsvd1;
+ u8 mac[ETH_ALEN];
+};
+
+struct hinic3_port_mac_update {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 vlan_id;
+ u16 rsvd1;
+ u8 old_mac[ETH_ALEN];
+ u16 rsvd2;
+ u8 new_mac[ETH_ALEN];
+};
+
+struct hinic3_vport_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 state; /* 0--disable, 1--enable */
+ u8 rsvd2[3];
+};
+
+struct hinic3_port_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 state; /* 0--disable, 1--enable */
+ u8 rsvd2[3];
+};
+
+#define HINIC3_SET_PORT_CAR_PROFILE 0
+#define HINIC3_SET_PORT_CAR_STATE 1
+#define HINIC3_GET_PORT_CAR_LIMIT_SPEED 2
+
+struct hinic3_port_car_info {
+ u32 cir; /* unit: kbps, range:[1,400*1000*1000], i.e. 1Kbps~400Gbps(400M*kbps) */
+ u32 xir; /* unit: kbps, range:[1,400*1000*1000], i.e. 1Kbps~400Gbps(400M*kbps) */
+ u32 cbs; /* unit: Byte, range:[1,320*1000*1000], i.e. 1byte~2560Mbit */
+ u32 xbs; /* unit: Byte, range:[1,320*1000*1000], i.e. 1byte~2560Mbit */
+};
+
+struct hinic3_cmd_set_port_car {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode; /* 0--set car profile, 1--set car state */
+ u8 state; /* 0--disable, 1--enable */
+ u8 level;
+
+ struct hinic3_port_car_info car;
+};
+
+struct hinic3_cmd_clear_qp_resource {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_cmd_cache_out_qp_resource {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_port_stats_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_vport_stats {
+ u64 tx_unicast_pkts_vport;
+ u64 tx_unicast_bytes_vport;
+ u64 tx_multicast_pkts_vport;
+ u64 tx_multicast_bytes_vport;
+ u64 tx_broadcast_pkts_vport;
+ u64 tx_broadcast_bytes_vport;
+
+ u64 rx_unicast_pkts_vport;
+ u64 rx_unicast_bytes_vport;
+ u64 rx_multicast_pkts_vport;
+ u64 rx_multicast_bytes_vport;
+ u64 rx_broadcast_pkts_vport;
+ u64 rx_broadcast_bytes_vport;
+
+ u64 tx_discard_vport;
+ u64 rx_discard_vport;
+ u64 tx_err_vport;
+ u64 rx_err_vport;
+};
+
+struct hinic3_phy_fpga_port_stats {
+ u64 mac_rx_total_octs_port;
+ u64 mac_tx_total_octs_port;
+ u64 mac_rx_under_frame_pkts_port;
+ u64 mac_rx_frag_pkts_port;
+ u64 mac_rx_64_oct_pkts_port;
+ u64 mac_rx_127_oct_pkts_port;
+ u64 mac_rx_255_oct_pkts_port;
+ u64 mac_rx_511_oct_pkts_port;
+ u64 mac_rx_1023_oct_pkts_port;
+ u64 mac_rx_max_oct_pkts_port;
+ u64 mac_rx_over_oct_pkts_port;
+ u64 mac_tx_64_oct_pkts_port;
+ u64 mac_tx_127_oct_pkts_port;
+ u64 mac_tx_255_oct_pkts_port;
+ u64 mac_tx_511_oct_pkts_port;
+ u64 mac_tx_1023_oct_pkts_port;
+ u64 mac_tx_max_oct_pkts_port;
+ u64 mac_tx_over_oct_pkts_port;
+ u64 mac_rx_good_pkts_port;
+ u64 mac_rx_crc_error_pkts_port;
+ u64 mac_rx_broadcast_ok_port;
+ u64 mac_rx_multicast_ok_port;
+ u64 mac_rx_mac_frame_ok_port;
+ u64 mac_rx_length_err_pkts_port;
+ u64 mac_rx_vlan_pkts_port;
+ u64 mac_rx_pause_pkts_port;
+ u64 mac_rx_unknown_mac_frame_port;
+ u64 mac_tx_good_pkts_port;
+ u64 mac_tx_broadcast_ok_port;
+ u64 mac_tx_multicast_ok_port;
+ u64 mac_tx_underrun_pkts_port;
+ u64 mac_tx_mac_frame_ok_port;
+ u64 mac_tx_vlan_pkts_port;
+ u64 mac_tx_pause_pkts_port;
+};
+
+struct hinic3_port_stats {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ struct hinic3_phy_fpga_port_stats stats;
+};
+
+struct hinic3_cmd_vport_stats {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u32 stats_size;
+ u32 rsvd1;
+ struct hinic3_vport_stats stats;
+ u64 rsvd2[6];
+};
+
+struct hinic3_cmd_qpn {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 base_qpn;
+};
+
+enum hinic3_func_tbl_cfg_bitmap {
+ FUNC_CFG_INIT,
+ FUNC_CFG_RX_BUF_SIZE,
+ FUNC_CFG_MTU,
+};
+
+struct hinic3_func_tbl_cfg {
+ u16 rx_wqe_buf_size;
+ u16 mtu;
+ u32 rsvd[9];
+};
+
+struct hinic3_cmd_set_func_tbl {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd;
+
+ u32 cfg_bitmap;
+ struct hinic3_func_tbl_cfg tbl_cfg;
+};
+
+struct hinic3_cmd_cons_idx_attr {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_idx;
+ u8 dma_attr_off;
+ u8 pending_limit;
+ u8 coalescing_time;
+ u8 intr_en;
+ u16 intr_idx;
+ u32 l2nic_sqn;
+ u32 rsvd;
+ u64 ci_addr;
+};
+
+union sm_tbl_args {
+ struct {
+ u32 tbl_index;
+ u32 cnt;
+ u32 total_cnt;
+ } mac_table_arg;
+ struct {
+ u32 er_id;
+ u32 vlan_id;
+ } vlan_elb_table_arg;
+ struct {
+ u32 func_id;
+ } vlan_filter_arg;
+ struct {
+ u32 mc_id;
+ } mc_elb_arg;
+ struct {
+ u32 func_id;
+ } func_tbl_arg;
+ struct {
+ u32 port_id;
+ } port_tbl_arg;
+ struct {
+ u32 tbl_index;
+ u32 cnt;
+ u32 total_cnt;
+ } fdir_io_table_arg;
+ struct {
+ u32 tbl_index;
+ u32 cnt;
+ u32 total_cnt;
+ } flexq_table_arg;
+ u32 args[4];
+};
+
+struct hinic3_rq_cqe_ctx {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 cqe_type;
+ u8 rq_id;
+ u8 threshold_cqe_num;
+ u8 rsvd1;
+
+ u16 msix_entry_idx;
+ u16 rsvd2;
+
+ u32 ci_addr_hi;
+ u32 ci_addr_lo;
+
+ u16 timer_loop;
+ u16 rsvd3;
+};
+
+#define DFX_SM_TBL_BUF_MAX (768)
+
+struct nic_cmd_dfx_sm_table {
+ struct hinic3_mgmt_msg_head msg_head;
+ u32 tbl_type;
+ union sm_tbl_args args;
+ u8 tbl_buf[DFX_SM_TBL_BUF_MAX];
+};
+
+struct hinic3_cmd_vlan_offload {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 vlan_offload;
+ u8 rsvd1[5];
+};
+
+/* ucode capture cfg info */
+struct nic_cmd_capture_info {
+ struct hinic3_mgmt_msg_head msg_head;
+ u32 op_type;
+ u32 func_port;
+ u32 is_en_trx;
+ u32 offset_cos;
+ u32 data_vlan;
+};
+
+struct hinic3_cmd_lro_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u8 lro_ipv4_en;
+ u8 lro_ipv6_en;
+ u8 lro_max_pkt_len; /* unit is 1K */
+ u8 resv2[13];
+};
+
+struct hinic3_cmd_lro_timer {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 opcode; /* 1: set timer value, 0: get timer value */
+ u8 rsvd1;
+ u16 rsvd2;
+ u32 timer;
+};
+
+struct hinic3_cmd_local_lro_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 0: get state, 1: set state */
+ u8 state; /* 0: disable, 1: enable */
+};
+
+struct hinic3_cmd_gtp_inner_parse_status {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 0: get state, 1: set state */
+ u8 status; /* 0: disable, 1: enable */
+};
+
+struct hinic3_cmd_vf_vlan_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u16 vlan_id;
+ u8 qos;
+ u8 rsvd2[5];
+};
+
+struct hinic3_cmd_spoofchk_set {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 state;
+ u8 rsvd1;
+};
+
+struct hinic3_cmd_tx_rate_cfg {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 rsvd1;
+ u8 direct;
+ u32 min_rate;
+ u32 max_rate;
+ u8 rsvd2[8];
+};
+
+struct hinic3_cmd_port_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+ u8 port_type;
+ u8 autoneg_cap;
+ u8 autoneg_state;
+ u8 duplex;
+ u8 speed;
+ u8 fec;
+ u16 rsvd2;
+ u32 rsvd3[4];
+};
+
+struct hinic3_cmd_register_vf {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 op_register; /* 0 - unregister, 1 - register */
+ u8 rsvd1[3];
+ u32 support_extra_feature;
+ u8 rsvd2[32];
+};
+
+struct hinic3_cmd_link_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 state;
+ u16 rsvd1;
+};
+
+struct hinic3_cmd_vlan_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 outband_defvid_flag;
+ u16 vlan_id;
+ u8 blacklist_flag;
+ u8 rsvd2;
+};
+
+#define VLAN_BLACKLIST_ENABLE 1
+#define VLAN_BLACKLIST_DISABLE 0
+
+struct hinic3_cmd_vxlan_port_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 cfg_mode;
+ u16 vxlan_port;
+ u16 rsvd2;
+};
+
+/* set vlan filter */
+struct hinic3_cmd_set_vlan_filter {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 resvd[2];
+ u32 vlan_filter_ctrl; /* bit0:vlan filter en; bit1:broadcast_filter_en */
+};
+
+struct hinic3_cmd_link_ksettings_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+
+ u32 valid_bitmap;
+ u8 speed; /* enum nic_speed_level */
+ u8 autoneg; /* 0 - off, 1 - on */
+ u8 fec; /* 0 - RSFEC, 1 - BASEFEC, 2 - NOFEC */
+ u8 rsvd2[21]; /* reserved for duplex, port, etc. */
+};
+
+struct mpu_lt_info {
+ u8 node;
+ u8 inst;
+ u8 entry_size;
+ u8 rsvd;
+ u32 lt_index;
+ u32 offset;
+ u32 len;
+};
+
+struct nic_mpu_lt_opera {
+ struct hinic3_mgmt_msg_head msg_head;
+ struct mpu_lt_info net_lt_cmd;
+ u8 data[100];
+};
+
+struct hinic3_force_pkt_drop {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port;
+ u8 rsvd1[3];
+};
+
+struct hinic3_rx_mode_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u32 rx_mode;
+};
+
+/* rss */
+struct hinic3_rss_context_table {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u32 context;
+};
+
+struct hinic3_cmd_rss_engine_type {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 hash_engine;
+ u8 rsvd1[4];
+};
+
+struct hinic3_cmd_rss_hash_key {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u8 key[NIC_RSS_KEY_SIZE];
+};
+
+struct hinic3_rss_indir_table {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 indir[NIC_RSS_INDIR_SIZE];
+};
+
+#define NIC_RSS_CMD_TEMP_ALLOC 0x01
+#define NIC_RSS_CMD_TEMP_FREE 0x02
+
+struct hinic3_rss_template_mgmt {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 cmd;
+ u8 template_id;
+ u8 rsvd1[4];
+};
+
+struct hinic3_cmd_rss_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 rss_en;
+ u8 rq_priority_number;
+ u8 prio_tc[NIC_DCB_COS_MAX];
+ u16 num_qps;
+ u16 rsvd1;
+};
+
+struct hinic3_dcb_state {
+ u8 dcb_on;
+ u8 default_cos;
+ u8 trust;
+ u8 rsvd1;
+ u8 pcp2cos[NIC_DCB_UP_MAX];
+ u8 dscp2cos[64];
+ u32 rsvd2[7];
+};
+
+struct hinic3_cmd_vf_dcb_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ struct hinic3_dcb_state state;
+};
+
+struct hinic3_up_ets_cfg { /* delet */
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+
+ u8 cos_tc[NIC_DCB_COS_MAX];
+ u8 tc_bw[NIC_DCB_TC_MAX];
+ u8 cos_prio[NIC_DCB_COS_MAX];
+ u8 cos_bw[NIC_DCB_COS_MAX];
+ u8 tc_prio[NIC_DCB_TC_MAX];
+};
+
+#define CMD_QOS_ETS_COS_TC BIT(0)
+#define CMD_QOS_ETS_TC_BW BIT(1)
+#define CMD_QOS_ETS_COS_PRIO BIT(2)
+#define CMD_QOS_ETS_COS_BW BIT(3)
+#define CMD_QOS_ETS_TC_PRIO BIT(4)
+#define CMD_QOS_ETS_TC_RATELIMIT BIT(5)
+struct hinic3_cmd_ets_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 port_id;
+ u8 op_code; /* 1 - set, 0 - get */
+ /* bit0 - cos_tc, bit1 - tc_bw, bit2 - cos_prio, bit3 - cos_bw, bit4 - tc_prio */
+ u8 cfg_bitmap;
+ u8 rsvd;
+
+ u8 cos_tc[NIC_DCB_COS_MAX];
+ u8 tc_bw[NIC_DCB_TC_MAX];
+ u8 cos_prio[NIC_DCB_COS_MAX]; /* 0 - DWRR, 1 - STRICT */
+ u8 cos_bw[NIC_DCB_COS_MAX];
+ u8 tc_prio[NIC_DCB_TC_MAX]; /* 0 - DWRR, 1 - STRICT */
+ u8 rate_limit[NIC_DCB_TC_MAX];
+};
+
+struct hinic3_cmd_set_dcb_state {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 op_code; /* 0 - get dcb state, 1 - set dcb state */
+ u8 state; /* 0 - disable, 1 - enable dcb */
+ u8 port_state; /* 0 - disable, 1 - enable dcb */
+ u8 rsvd[7];
+};
+
+#define PFC_BIT_MAP_NUM 8
+struct hinic3_cmd_set_pfc {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 port_id;
+ u8 op_code; /* 0:get 1: set pfc_en 2: set pfc_bitmap 3: set all */
+ u8 pfc_en; /* pfc_en 和 pfc_bitmap 必须同时设置 */
+ u8 pfc_bitmap;
+ u8 rsvd[4];
+};
+
+#define CMD_QOS_PORT_TRUST BIT(0)
+#define CMD_QOS_PORT_DFT_COS BIT(1)
+struct hinic3_cmd_qos_port_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 port_id;
+ u8 op_code; /* 0 - get, 1 - set */
+ u8 cfg_bitmap; /* bit0 - trust, bit1 - dft_cos */
+ u8 rsvd0;
+
+ u8 trust;
+ u8 dft_cos;
+ u8 rsvd1[18];
+};
+
+#define MAP_COS_MAX_NUM 8
+#define CMD_QOS_MAP_PCP2COS BIT(0)
+#define CMD_QOS_MAP_DSCP2COS BIT(1)
+struct hinic3_cmd_qos_map_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 op_code;
+ u8 cfg_bitmap; /* bit0 - pcp2cos, bit1 - dscp2cos */
+ u16 rsvd0;
+
+ u8 pcp2cos[8]; /* 8 must be configured together */
+ /* If the dscp2cos parameter is set to 0xFF, the MPU ignores the DSCP priority,
+ * Multiple mappings between DSCP values and CoS values can be configured at a time.
+ */
+ u8 dscp2cos[64];
+ u32 rsvd1[4];
+};
+
+struct hinic3_cos_up_map {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 cos_valid_mask; /* every bit indicate index of map is valid 1 or not 0 */
+ u16 rsvd1;
+
+ /* user priority in cos(index:cos, value: up pri) */
+ u8 map[NIC_DCB_UP_MAX];
+};
+
+struct hinic3_cmd_pause_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode;
+ u16 rsvd1;
+ u8 auto_neg;
+ u8 rx_pause;
+ u8 tx_pause;
+ u8 rsvd2[5];
+};
+
+struct nic_cmd_pause_inquiry_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 valid;
+
+ u32 type; /* 1: set, 2: get */
+
+ u32 cos_id;
+
+ u32 rx_inquiry_pause_drop_pkts_en;
+ u32 rx_inquiry_pause_period_ms;
+ u32 rx_inquiry_pause_times;
+ /* rx pause Detection Threshold, Default PAUSE_FRAME_THD_10G/25G/40G/100 */
+ u32 rx_inquiry_pause_frame_thd;
+ u32 rx_inquiry_tx_total_pkts;
+
+ u32 tx_inquiry_pause_en; /* tx pause detect enable */
+ u32 tx_inquiry_pause_period_ms; /* tx pause Default Detection Period 200ms */
+ u32 tx_inquiry_pause_times; /* tx pause Default Times Period 5 */
+ u32 tx_inquiry_pause_frame_thd; /* tx pause Detection Threshold */
+ u32 tx_inquiry_rx_total_pkts;
+ u32 rsvd[3];
+};
+
+/* pfc/pause Storm TX exception reporting */
+struct nic_cmd_tx_pause_notice {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 tx_pause_except; /* 1: abnormality,0: normal */
+ u32 except_level;
+ u32 rsvd;
+};
+
+#define HINIC3_CMD_OP_FREE 0
+#define HINIC3_CMD_OP_ALLOC 1
+
+struct hinic3_cmd_cfg_qps {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 1: alloc qp, 0: free qp */
+ u8 rsvd1;
+ u16 num_qps;
+ u16 rsvd2;
+};
+
+struct hinic3_cmd_led_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port;
+ u8 type;
+ u8 mode;
+ u8 rsvd1;
+};
+
+struct hinic3_cmd_port_loopback {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode;
+ u8 mode;
+ u8 en;
+ u32 rsvd1[2];
+};
+
+struct hinic3_cmd_get_light_module_abs {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 abs_status; /* 0:present, 1:absent */
+ u8 rsv[2];
+};
+
+#define STD_SFP_INFO_MAX_SIZE 640
+struct hinic3_cmd_get_std_sfp_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 wire_type;
+ u16 eeprom_len;
+ u32 rsvd;
+ u8 sfp_info[STD_SFP_INFO_MAX_SIZE];
+};
+
+struct hinic3_cable_plug_event {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 plugged; /* 0: unplugged, 1: plugged */
+ u8 port_id;
+};
+
+struct nic_cmd_mac_info {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 valid_bitmap;
+ u16 rsvd;
+
+ u8 host_id[32];
+ u8 port_id[32];
+ u8 mac_addr[192];
+};
+
+struct nic_cmd_set_tcam_enable {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 tcam_enable;
+ u8 rsvd1;
+ u32 rsvd2;
+};
+
+struct nic_cmd_set_fdir_status {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 pkt_type_en;
+ u8 pkt_type;
+ u8 qid;
+ u8 rsvd2;
+};
+
+#define HINIC3_TCAM_BLOCK_ENABLE 1
+#define HINIC3_TCAM_BLOCK_DISABLE 0
+#define HINIC3_MAX_TCAM_RULES_NUM 4096
+
+/* tcam block type, according to tcam block size */
+enum {
+ NIC_TCAM_BLOCK_TYPE_LARGE = 0, /* block_size: 16 */
+ NIC_TCAM_BLOCK_TYPE_SMALL, /* block_size: 0 */
+ NIC_TCAM_BLOCK_TYPE_MAX
+};
+
+/* alloc tcam block input struct */
+struct nic_cmd_ctrl_tcam_block_in {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id; /* func_id */
+ u8 alloc_en; /* 0: Releases the allocated TCAM block. 1: Applies for a new TCAM block */
+ /* 0: 16 size tcam block, 1: 0 size tcam block, other reserved. */
+ u8 tcam_type;
+ u16 tcam_block_index;
+ /* Size of the block that the driver wants to allocate
+ * Interface returned by the UP to the driver,
+ * indicating the size of the allocated TCAM block supported by the UP
+ */
+ u16 alloc_block_num;
+};
+
+/* alloc tcam block output struct */
+struct nic_cmd_ctrl_tcam_block_out {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id; /* func_id */
+ u8 alloc_en; /* 0: Releases the allocated TCAM block. 1: Applies for a new TCAM block */
+ /* 0: 16 size tcam block, 1: 0 size tcam block, other reserved. */
+ u8 tcam_type;
+ u16 tcam_block_index;
+ /* Size of the block that the driver wants to allocate
+ * Interface returned by the UP to the driver,
+ * indicating the size of the allocated TCAM block supported by the UP
+ */
+ u16 mpu_alloc_block_size;
+};
+
+struct nic_cmd_flush_tcam_rules {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id; /* func_id */
+ u16 rsvd;
+};
+
+struct nic_cmd_dfx_fdir_tcam_block_table {
+ struct hinic3_mgmt_msg_head head;
+ u8 tcam_type;
+ u8 valid;
+ u16 tcam_block_index;
+ u16 use_function_id;
+ u16 rsvd;
+};
+
+struct tcam_result {
+ u32 qid;
+ u32 rsvd;
+};
+
+#define TCAM_FLOW_KEY_SIZE (44)
+
+struct tcam_key_x_y {
+ u8 x[TCAM_FLOW_KEY_SIZE];
+ u8 y[TCAM_FLOW_KEY_SIZE];
+};
+
+struct nic_tcam_cfg_rule {
+ u32 index;
+ struct tcam_result data;
+ struct tcam_key_x_y key;
+};
+
+#define TCAM_RULE_FDIR_TYPE 0
+#define TCAM_RULE_PPA_TYPE 1
+
+struct nic_cmd_fdir_add_rule {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 type;
+ u8 fdir_ext; /* 0x1: flow bifur en bit */
+ struct nic_tcam_cfg_rule rule;
+};
+
+struct nic_cmd_fdir_del_rules {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 type;
+ u8 rsvd;
+ u32 index_start;
+ u32 index_num;
+};
+
+struct nic_cmd_fdir_get_rule {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 index;
+ u8 valid;
+ u8 type;
+ u16 rsvd;
+ struct tcam_key_x_y key;
+ struct tcam_result data;
+ u64 packet_count;
+ u64 byte_count;
+};
+
+struct nic_cmd_fdir_get_block_rules {
+ struct hinic3_mgmt_msg_head head;
+ u8 tcam_block_type; // only NIC_TCAM_BLOCK_TYPE_LARGE
+ u8 tcam_table_type; // TCAM_RULE_PPA_TYPE or TCAM_RULE_FDIR_TYPE
+ u16 tcam_block_index;
+ u8 valid[NIC_TCAM_BLOCK_LARGE_SIZE];
+ struct tcam_key_x_y key[NIC_TCAM_BLOCK_LARGE_SIZE];
+ struct tcam_result data[NIC_TCAM_BLOCK_LARGE_SIZE];
+};
+
+struct hinic3_tcam_key_ipv4_mem {
+ u32 rsvd1 : 1;
+ u32 bifur_flag : 2;
+ u32 model : 1;
+ u32 tunnel_type : 4;
+ u32 ip_proto : 8;
+ u32 rsvd0 : 16;
+ u32 sipv4_h : 16;
+ u32 ip_type : 1;
+ u32 function_id : 15;
+ u32 dipv4_h : 16;
+ u32 sipv4_l : 16;
+ u32 vlan_id : 15;
+ u32 vlan_flag : 1;
+ u32 dipv4_l : 16;
+ u32 rsvd3;
+ u32 dport : 16;
+ u32 rsvd4 : 16;
+ u32 rsvd5 : 16;
+ u32 sport : 16;
+ u32 outer_sipv4_h : 16;
+ u32 rsvd6 : 16;
+ u32 outer_dipv4_h : 16;
+ u32 outer_sipv4_l : 16;
+ u32 vni_h : 16;
+ u32 outer_dipv4_l : 16;
+ u32 rsvd7 : 16;
+ u32 vni_l : 16;
+};
+
+union hinic3_tag_tcam_ext_info {
+ struct {
+ u32 id : 16; /* id */
+ u32 type : 4; /* type: 0-func, 1-vmdq, 2-port, 3-rsvd, 4-trunk, 5-dp, 6-mc */
+ u32 host_id : 3;
+ u32 rss_q_num : 8; /* rss queue num */
+ u32 ext : 1;
+ } bs;
+ u32 value;
+};
+
+struct hinic3_tcam_key_ipv6_mem {
+ u32 bifur_flag : 2;
+ u32 vlan_flag : 1;
+ u32 outer_ip_type : 1;
+ u32 tunnel_type : 4;
+ u32 ip_proto : 8;
+ u32 rsvd0 : 16;
+ u32 sipv6_key0 : 16;
+ u32 ip_type : 1;
+ u32 function_id : 15;
+ u32 sipv6_key2 : 16;
+ u32 sipv6_key1 : 16;
+ u32 sipv6_key4 : 16;
+ u32 sipv6_key3 : 16;
+ u32 sipv6_key6 : 16;
+ u32 sipv6_key5 : 16;
+ u32 dport : 16;
+ u32 sipv6_key7 : 16;
+ u32 dipv6_key0 : 16;
+ u32 sport : 16;
+ u32 dipv6_key2 : 16;
+ u32 dipv6_key1 : 16;
+ u32 dipv6_key4 : 16;
+ u32 dipv6_key3 : 16;
+ u32 dipv6_key6 : 16;
+ u32 dipv6_key5 : 16;
+ u32 rsvd2 : 16;
+ u32 dipv6_key7 : 16;
+};
+
+struct hinic3_tcam_key_vxlan_ipv6_mem {
+ u32 rsvd1 : 4;
+ u32 tunnel_type : 4;
+ u32 ip_proto : 8;
+ u32 rsvd0 : 16;
+
+ u32 dipv6_key0 : 16;
+ u32 ip_type : 1;
+ u32 function_id : 15;
+
+ u32 dipv6_key2 : 16;
+ u32 dipv6_key1 : 16;
+
+ u32 dipv6_key4 : 16;
+ u32 dipv6_key3 : 16;
+
+ u32 dipv6_key6 : 16;
+ u32 dipv6_key5 : 16;
+
+ u32 dport : 16;
+ u32 dipv6_key7 : 16;
+
+ u32 rsvd2 : 16;
+ u32 sport : 16;
+
+ u32 outer_sipv4_h : 16;
+ u32 rsvd3 : 16;
+
+ u32 outer_dipv4_h : 16;
+ u32 outer_sipv4_l : 16;
+
+ u32 vni_h : 16;
+ u32 outer_dipv4_l : 16;
+
+ u32 rsvd4 : 16;
+ u32 vni_l : 16;
+};
+
+struct tag_tcam_key {
+ union {
+ struct hinic3_tcam_key_ipv4_mem key_info;
+ struct hinic3_tcam_key_ipv6_mem key_info_ipv6;
+ struct hinic3_tcam_key_vxlan_ipv6_mem key_info_vxlan_ipv6;
+ };
+
+ union {
+ struct hinic3_tcam_key_ipv4_mem key_mask;
+ struct hinic3_tcam_key_ipv6_mem key_mask_ipv6;
+ struct hinic3_tcam_key_vxlan_ipv6_mem key_mask_vxlan_ipv6;
+ };
+};
+
+enum {
+ PPA_TABLE_ID_CLEAN_CMD = 0,
+ PPA_TABLE_ID_ADD_CMD,
+ PPA_TABLE_ID_DEL_CMD,
+ FDIR_TABLE_ID_ADD_CMD,
+ FDIR_TABLE_ID_DEL_CMD,
+ PPA_TABEL_ID_MAX
+};
+
+struct hinic3_ppa_cfg_table_id_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 rsvd0;
+ u16 cmd;
+ u16 table_id;
+ u16 rsvd1;
+};
+
+struct hinic3_ppa_cfg_ppa_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 ppa_en;
+ u8 ppa_miss_drop_en;
+};
+
+struct hinic3_func_flow_bifur_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+ u16 func_id;
+ u8 flow_bifur_en;
+ u8 rsvd[5];
+};
+
+struct hinic3_port_flow_bifur_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+ u16 port_id;
+ u8 flow_bifur_en;
+ u8 flow_bifur_type; /* 0->vf bifur, 2->traffic bifur */
+ u8 rsvd[4];
+};
+
+struct hinic3_bond_mask_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+ u16 func_id;
+ u8 bond_mask;
+ u8 bond_en;
+ u8 func_valid;
+ 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;
+ u8 promisc_skip_en; /* 0: disable tx promisc replication, 1: enable */
+ u8 opcode; /* 0: set, 1: get */
+ u8 rsvd1;
+};
+
+struct hinic3_ppa_cfg_mode_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 rsvd0;
+ u8 ppa_mode;
+ u8 qpc_func_nums;
+ u16 base_qpc_func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_ppa_flush_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 rsvd0;
+ u8 flush_en; /* 0 flush done, 1 in flush operation */
+ u8 rsvd1;
+};
+
+struct hinic3_ppa_fdir_query_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u32 index;
+ u32 rsvd;
+ u64 pkt_nums;
+ u64 pkt_bytes;
+};
+
+/* BIOS CONF */
+enum {
+ NIC_NVM_DATA_SET = BIT(0), /* 1-save, 0-read */
+ NIC_NVM_DATA_PXE = BIT(1),
+ NIC_NVM_DATA_VLAN = BIT(2),
+ NIC_NVM_DATA_VLAN_PRI = BIT(3),
+ NIC_NVM_DATA_VLAN_ID = BIT(4),
+ NIC_NVM_DATA_WORK_MODE = BIT(5),
+ NIC_NVM_DATA_PF_TX_SPEED_LIMIT = BIT(6),
+ NIC_NVM_DATA_GE_MODE = BIT(7),
+ NIC_NVM_DATA_AUTO_NEG = BIT(8),
+ NIC_NVM_DATA_LINK_FEC = BIT(9),
+ NIC_NVM_DATA_PF_ADAPTIVE_LINK = BIT(10),
+ NIC_NVM_DATA_SRIOV_CONTROL = BIT(11),
+ NIC_NVM_DATA_EXTEND_MODE = BIT(12),
+ NIC_NVM_DATA_LEGACY_VLAN = BIT(13),
+ NIC_NVM_DATA_LEGACY_VLAN_PRI = BIT(14),
+ NIC_NVM_DATA_LEGACY_VLAN_ID = BIT(15),
+ NIC_NVM_DATA_RESET = BIT(31),
+};
+
+#define BIOS_CFG_SIGNATURE 0x1923E518
+#define BIOS_OP_CFG_ALL(op_code_val) \
+ ((((op_code_val) >> 1) & (0xFFFFFFFF)) != 0)
+#define BIOS_OP_CFG_WRITE(op_code_val) \
+ ((((op_code_val) & NIC_NVM_DATA_SET)) != 0)
+#define BIOS_OP_CFG_PXE_EN(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_PXE) != 0)
+#define BIOS_OP_CFG_VLAN_EN(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_VLAN) != 0)
+#define BIOS_OP_CFG_VLAN_PRI(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_VLAN_PRI) != 0)
+#define BIOS_OP_CFG_VLAN_ID(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_VLAN_ID) != 0)
+#define BIOS_OP_CFG_WORK_MODE(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_WORK_MODE) != 0)
+#define BIOS_OP_CFG_PF_BW(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_PF_TX_SPEED_LIMIT) != 0)
+#define BIOS_OP_CFG_GE_SPEED(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_GE_MODE) != 0)
+#define BIOS_OP_CFG_AUTO_NEG(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_AUTO_NEG) != 0)
+#define BIOS_OP_CFG_LINK_FEC(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LINK_FEC) != 0)
+#define BIOS_OP_CFG_AUTO_ADPAT(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_PF_ADAPTIVE_LINK) != 0)
+#define BIOS_OP_CFG_SRIOV_ENABLE(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_SRIOV_CONTROL) != 0)
+#define BIOS_OP_CFG_EXTEND_MODE(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_EXTEND_MODE) != 0)
+#define BIOS_OP_CFG_LEGACY_VLAN_EN(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LEGACY_VLAN) != 0)
+#define BIOS_OP_CFG_LEGACY_VLAN_PRI(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LEGACY_VLAN_PRI) != 0)
+#define BIOS_OP_CFG_LEGACY_VLAN_ID(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LEGACY_VLAN_ID) != 0)
+#define BIOS_OP_CFG_RST_DEF_SET(op_code_val) \
+ (((op_code_val) & (u32)NIC_NVM_DATA_RESET) != 0)
+
+
+#define NIC_BIOS_CFG_MAX_PF_BW 100
+
+struct nic_legacy_vlan_cfg {
+ /* Legacy mode PXE VLAN enable: 0 - disable 1 - enable */
+ u8 pxe_vlan_en : 1;
+ /* Legacy mode PXE VLAN priority: 0-7 */
+ u8 pxe_vlan_pri : 3;
+ /* Legacy mode PXE VLAN ID 1-4094 */
+ u16 pxe_vlan_id : 12;
+};
+
+/* Note: This structure must be 4-byte aligned. */
+struct nic_bios_cfg {
+ u32 signature;
+ u8 pxe_en;
+ u8 extend_mode;
+ struct nic_legacy_vlan_cfg nlvc;
+ u8 pxe_vlan_en;
+ u8 pxe_vlan_pri;
+ u16 pxe_vlan_id;
+ u32 service_mode;
+ u32 pf_tx_bw;
+ u8 speed;
+ u8 auto_neg;
+ u8 lanes;
+ u8 fec;
+ u8 auto_adapt;
+ u8 func_valid;
+ u8 func_id;
+ u8 sriov_en;
+};
+
+struct nic_cmd_bios_cfg {
+ struct hinic3_mgmt_msg_head head;
+ u32 op_code; /* Operation Code: Bit0[0: read 1:write, BIT1-6: cfg_mask */
+ struct nic_bios_cfg bios_cfg;
+};
+
+struct nic_rx_rate_bios_cfg {
+ struct mgmt_msg_head msg_head;
+
+ u32 op_code; /* Operation Code:[0:read 1:write] */
+ u8 rx_rate_limit;
+ u8 func_id;
+};
+
+struct nic_cmd_vhd_config {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 vhd_type;
+ u8 virtio_small_enable; /* 0: mergeable mode, 1: small mode */
+};
+
+/* BOND */
+struct hinic3_create_bond_info {
+ u32 bond_id;
+ u32 master_slave_port_id;
+ u32 slave_bitmap; /* bond port id bitmap */
+ u32 poll_timeout; /* Bond device link check time */
+ u32 up_delay; /* Temporarily reserved */
+ u32 down_delay; /* Temporarily reserved */
+ u32 bond_mode; /* Temporarily reserved */
+ u32 active_pf; /* bond use active pf id */
+ u32 active_port_max_num; /* Maximum number of active bond member interfaces */
+ u32 active_port_min_num; /* Minimum number of active bond member interfaces */
+ u32 xmit_hash_policy;
+ u32 default_param_flag;
+ u32 rsvd;
+};
+
+struct hinic3_cmd_create_bond {
+ struct hinic3_mgmt_msg_head head;
+ struct hinic3_create_bond_info create_bond_info;
+};
+
+struct hinic3_cmd_delete_bond {
+ struct hinic3_mgmt_msg_head head;
+ u32 bond_id;
+ u32 rsvd[2];
+};
+
+struct hinic3_open_close_bond_info {
+ u32 bond_id;
+ u32 open_close_flag; /* Bond flag. 1: open; 0: close. */
+ u32 rsvd[2];
+};
+
+struct hinic3_cmd_open_close_bond {
+ struct hinic3_mgmt_msg_head head;
+ struct hinic3_open_close_bond_info open_close_bond_info;
+};
+
+struct lacp_port_params {
+ u16 port_number;
+ u16 port_priority;
+ u16 key;
+ u16 system_priority;
+ u8 system[ETH_ALEN];
+ u8 port_state;
+ u8 rsvd;
+};
+
+struct lacp_port_info {
+ u32 selected;
+ u32 aggregator_port_id;
+
+ struct lacp_port_params actor;
+ struct lacp_port_params partner;
+
+ u64 tx_lacp_pkts;
+ u64 rx_lacp_pkts;
+ u64 rx_8023ad_drop;
+ u64 tx_8023ad_drop;
+ u64 unknown_pkt_drop;
+ u64 rx_marker_pkts;
+ u64 tx_marker_pkts;
+};
+
+struct hinic3_bond_status_info {
+ struct hinic3_mgmt_msg_head head;
+ u32 bond_id;
+ u32 bon_mmi_status;
+ u32 active_bitmap;
+ u32 port_count;
+
+ struct lacp_port_info port_info[4];
+
+ u64 success_report_cnt[4];
+ u64 fail_report_cnt[4];
+
+ u64 poll_timeout;
+ u64 fast_periodic_timeout;
+ u64 slow_periodic_timeout;
+ u64 short_timeout;
+ u64 long_timeout;
+ u64 aggregate_wait_timeout;
+ u64 tx_period_timeout;
+ u64 rx_marker_timer;
+};
+
+struct hinic3_bond_active_report_info {
+ struct hinic3_mgmt_msg_head head;
+ u32 bond_id;
+ u32 bon_mmi_status;
+ u32 active_bitmap;
+
+ u8 rsvd[16];
+};
+
+/* IP checksum error packets, enable rss quadruple hash. */
+struct hinic3_ipcs_err_rss_enable_operation_s {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 en_tag;
+ u8 type; /* 1: set 0: get */
+ u8 rsvd[2];
+};
+
+struct hinic3_smac_check_state {
+ struct hinic3_mgmt_msg_head head;
+ u8 smac_check_en; /* 1: enable 0: disable */
+ u8 op_code; /* 1: set 0: get */
+ u8 flash_en; /* 1: enable 0: disable */
+ u8 rsvd;
+};
+
+struct hinic3_clear_log_state {
+ struct hinic3_mgmt_msg_head head;
+ u32 type;
+};
+
+struct hinic3_outband_cfg_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 outband_default_vid;
+ u16 func_id;
+};
+
+struct hinic3_wr_ordering {
+ struct hinic3_mgmt_msg_head head;
+ u8 op_code; /* 1: set 0: get */
+ u8 wr_pkt_so_ro;
+ u8 rd_pkt_so_ro;
+ u8 rsvd;
+};
+
+struct hinic3_function_active_info {
+ struct hinic3_mgmt_msg_head head;
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_rq_info {
+ struct hinic3_mgmt_msg_head head;
+ u16 func_id;
+ u16 rq_depth;
+ u16 rq_num;
+ u16 pf_num;
+ u16 port_num;
+};
+
+#endif /* HINIC_MGMT_INTERFACE_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h b/drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h
new file mode 100644
index 0000000..3e625fc
--- /dev/null
+++ b/drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
+ * File Name : nic_npu_cmd.h
+ * Version : Initial Draft
+ * Created : 2019/4/25
+ * Last Modified :
+ * Description : NIC Commands between Driver and NPU
+ * Function List :
+ */
+
+#ifndef NIC_NPU_CMD_H
+#define NIC_NPU_CMD_H
+
+/* NIC CMDQ MODE */
+enum hinic3_ucode_cmd {
+ HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX = 0,
+ HINIC3_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
+ HINIC3_UCODE_CMD_ARM_SQ, /**< Unused */
+ HINIC3_UCODE_CMD_ARM_RQ, /**< Unused */
+ HINIC3_UCODE_CMD_SET_RSS_INDIR_TABLE,
+ 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,
+ HINIC3_UCODE_CMD_MODIFY_VLAN_CTX,
+ HINIC3_UCODE_CMD_PPA_HASH_TABLE,
+ HINIC3_UCODE_CMD_RXQ_INFO_GET = 13,
+ HINIC3_UCODE_MIG_CFG_Q_CTX = 14,
+ HINIC3_UCODE_MIG_CHK_SQ_STOP,
+ HINIC3_UCODE_CHK_RQ_STOP,
+ HINIC3_UCODE_MIG_CFG_BAT_INFO,
+};
+
+#endif /* NIC_NPU_CMD_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h b/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h
index 78a8d7f..66f4305 100644
--- a/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h
+++ b/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h
@@ -5,6 +5,7 @@
#define OSSL_KNL_LINUX_H_
#include <net/ipv6.h>
+#include <net/devlink.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/device.h>
@@ -18,6 +19,12 @@
#include <linux/list.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include <linux/aer.h>
+#include <linux/socket.h>
#ifndef NETIF_F_SCTP_CSUM
#define NETIF_F_SCTP_CSUM 0
@@ -173,12 +180,10 @@ static inline void *_hinic3_dma_zalloc_coherent(struct device *dev,
}
#endif
-#ifndef DT_KNL_EMU
struct timeval {
__kernel_old_time_t tv_sec; /* seconds */
__kernel_suseconds_t tv_usec; /* microseconds */
};
-#endif
#ifndef do_gettimeofday
#define do_gettimeofday(time) _kc_do_gettimeofday(time)
@@ -196,6 +201,10 @@ static inline void _kc_do_gettimeofday(struct timeval *tv)
#define ETH_GET_HEADLEN_NEED_DEV
#define HAVE_GENL_OPS_FIELD_VALIDATE
+#ifndef FIELD_SIZEOF
+#define FIELD_SIZEOF(t, f) (sizeof(((t *)0)->f))
+#endif
+
#define HAVE_DEVLINK_FLASH_UPDATE_PARAMS
#ifndef rtc_time_to_tm
@@ -253,12 +262,12 @@ static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
size, vaddr, dma_handle);
}
-#define HAVE_DEVLINK_FW_FILE_NAME_MEMBER
-
#define HAVE_ENCAPSULATION_TSO
#define HAVE_ENCAPSULATION_CSUM
+#define HAVE_UDP_TUNNEL_NIC_INFO
+
#ifndef eth_zero_addr
static inline void hinic3_eth_zero_addr(u8 *addr)
{
@@ -333,4 +342,15 @@ u64 ossl_get_real_time(void);
#define tasklet_state(tasklet) ((tasklet)->state)
+dma_addr_t pci_map_single(struct pci_dev *pdev,
+ void *ptr, size_t size, int direction);
+int pci_dma_mapping_error(struct pci_dev *pdev,
+ dma_addr_t dma_addr);
+void pci_unmap_single(struct pci_dev *pdev,
+ dma_addr_t dma_addr, size_t size, int direction);
+void *pci_alloc_consistent(struct pci_dev *pdev,
+ size_t size, dma_addr_t *dma_handle);
+void pci_free_consistent(struct pci_dev *pdev,
+ size_t size, void *vaddr, dma_addr_t dma_handle);
+
#endif
--
2.45.1.windows.1
2
1

09 May '25
From: fuguiming <fuguiming(a)huawei.com>
driver inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IC5K0L?from=project-issue
CVE: NA
--------------------------------
Add optical module type adaptation.
Add ethtool fec function.
Add NIC XDP PASS function.
Add QoS persistence.
Add NIC out-of-band VLAN configuration function.
Fix NIC bifur bugs.
Fix performance test bugs.
Fix NIC RX bugs.
Fix NIC VF bugs.
Fix the bug of exiting when probing NIC.
Fix bond bugs.
Fix the bug of MAC address configuration failure in OS 6.6.
Fix the bug of reading NIC status incorrectly.
Fix and add some statistics.
Signed-off-by: fuguiming <fuguiming(a)huawei.com>
---
drivers/net/ethernet/huawei/hinic3/Makefile | 1 +
drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c | 3 +-
drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c | 181 ++-
drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h | 1 +
drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h | 212 ---
drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h | 239 ---
drivers/net/ethernet/huawei/hinic3/comm_defs.h | 100 --
drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h | 103 --
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c | 38 +-
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h | 2 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c | 83 +-
drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h | 1 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c | 29 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c | 22 +-
drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h | 1 +
drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c | 4 +-
drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h | 185 ---
drivers/net/ethernet/huawei/hinic3/hinic3_common.h | 118 --
drivers/net/ethernet/huawei/hinic3/hinic3_crm.h | 16 +-
drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c | 298 ++--
drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c | 262 +--
drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h | 7 +-
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c | 247 ++-
drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c | 459 +++---
drivers/net/ethernet/huawei/hinic3/hinic3_filter.c | 4 +-
drivers/net/ethernet/huawei/hinic3/hinic3_hw.h | 19 +
drivers/net/ethernet/huawei/hinic3/hinic3_irq.c | 39 +-
drivers/net/ethernet/huawei/hinic3/hinic3_lld.h | 205 ---
drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c | 833 +++++++++-
drivers/net/ethernet/huawei/hinic3/hinic3_main.c | 490 +++++-
drivers/net/ethernet/huawei/hinic3/hinic3_mt.h | 191 ++-
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c | 397 +++--
drivers/net/ethernet/huawei/hinic3/hinic3_nic.h | 49 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c | 557 +++++--
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h | 54 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c | 186 ++-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c | 10 +
drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h | 112 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c | 105 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c | 50 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h | 2 +-
drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c | 2 +-
drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c | 15 +-
drivers/net/ethernet/huawei/hinic3/hinic3_profile.h | 4 +-
drivers/net/ethernet/huawei/hinic3/hinic3_rss.c | 137 +-
drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c | 41 +-
drivers/net/ethernet/huawei/hinic3/hinic3_rx.c | 311 +++-
drivers/net/ethernet/huawei/hinic3/hinic3_rx.h | 41 +-
drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h | 7 +-
drivers/net/ethernet/huawei/hinic3/hinic3_tx.c | 79 +-
drivers/net/ethernet/huawei/hinic3/hinic3_wq.h | 4 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c | 11 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c | 6 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h | 5 -
drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c | 1 -
drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c | 213 ++-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h | 18 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c | 3 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c | 14 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c | 42 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c | 79 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h | 7 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c | 155 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c | 115 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c | 85 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h | 31 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c | 40 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c | 1243 +++++++++++++-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c | 3 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c | 4 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c | 41 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c | 122 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h | 4 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h | 31 +
drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c | 64 +-
drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h | 14 +-
drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c | 1 +
drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h | 4 +
.../include/cfg_mgmt/cfg_mgmt_mpu_cmd_defs.h | 11 +-
drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h | 42 +-
drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h | 2 +
drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h | 4 +
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h | 70 +-
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h | 141 +-
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h | 5 +
drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h | 88 +-
.../include/mpu/mpu_outband_ncsi_cmd_defs.h | 8 +
drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h | 4 +
drivers/net/ethernet/huawei/hinic3/include/vram_common.h | 25 +-
drivers/net/ethernet/huawei/hinic3/{mag_cmd.h => mag_mpu_cmd_defs.h} | 236 ++-
drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h | 27 -
drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h | 65 -
drivers/net/ethernet/huawei/hinic3/{hinic3_nic_cmd.h => nic_mpu_cmd.h} | 54 +-
drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h | 1440 +++++++++++++++++
drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h | 36 +
drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h | 28 +-
96 files changed, 8407 insertions(+), 2791 deletions(-)
delete mode 100644 drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/comm_defs.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/hinic3_common.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/hinic3_lld.h
rename drivers/net/ethernet/huawei/hinic3/{mag_cmd.h => mag_mpu_cmd_defs.h} (79%)
delete mode 100644 drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h
delete mode 100644 drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h
rename drivers/net/ethernet/huawei/hinic3/{hinic3_nic_cmd.h => nic_mpu_cmd.h} (77%)
create mode 100644 drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h
create mode 100644 drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h
diff --git a/drivers/net/ethernet/huawei/hinic3/Makefile b/drivers/net/ethernet/huawei/hinic3/Makefile
index 6f9ed3f..457c920 100644
--- a/drivers/net/ethernet/huawei/hinic3/Makefile
+++ b/drivers/net/ethernet/huawei/hinic3/Makefile
@@ -11,6 +11,7 @@ ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/cfg_mgmt/
ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/mpu/
ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/bond/
ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/include/vmsec/
+ccflags-y += -I$(srctree)/drivers/net/ethernet/huawei/hinic3/bond/
obj-$(CONFIG_HINIC3) += hinic3.o
hinic3-objs := hw/hinic3_hwdev.o \
diff --git a/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c b/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c
index cc2e4b3..440fea6 100644
--- a/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/adapter/sw_cmdq/sw_cmdq_ops.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_nic_cmdq.h"
#include "sw_cmdq_ops.h"
diff --git a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c
index e8c703b..dd0699b 100644
--- a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c
+++ b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c
@@ -9,6 +9,7 @@
#include <linux/net.h>
#include <linux/mutex.h>
#include <linux/netdevice.h>
+#include <linux/version.h>
#include "hinic3_lld.h"
#include "hinic3_srv_nic.h"
@@ -109,7 +110,8 @@ static struct hinic3_nic_dev *get_nic_dev_safe(struct net_device *ndev)
return netdev_priv(ndev);
}
-static u8 bond_get_slaves_bitmap(struct hinic3_bond_dev *bdev, struct bonding *bond)
+static u8 bond_get_slaves_bitmap(struct hinic3_bond_dev *bdev,
+ struct bonding *bond)
{
struct slave *slave = NULL;
struct list_head *iter = NULL;
@@ -203,7 +205,8 @@ static u8 bond_dev_track_port(struct hinic3_bond_dev *bdev,
bdev->tracker.netdev_state[port_id].tx_enabled = 0;
if (!bdev->ppf_hwdev)
bdev->ppf_hwdev = ppf_hwdev;
- pr_info("TRACK cnt: %d, slave_name(%s)\n", bdev->tracker.cnt, ndev->name);
+ pr_info("TRACK cnt: %d, slave_name(%s)\n",
+ bdev->tracker.cnt, ndev->name);
spin_unlock(&bdev->lock);
return port_id;
@@ -268,11 +271,16 @@ static void bond_master_event(struct hinic3_bond_dev *bdev,
queue_delayed_work(bdev->wq, &bdev->bond_work, 0);
}
-static struct hinic3_bond_dev *bond_get_bdev(const struct bonding *bond)
+static struct hinic3_bond_dev *bond_get_bdev(struct bonding *bond)
{
struct hinic3_bond_dev *bdev = NULL;
int bid;
+ if (!bond) {
+ pr_err("hinic3_bond: bond is NULL\n");
+ return NULL;
+ }
+
mutex_lock(&g_bond_mutex);
for (bid = BOND_FIRST_ID; bid <= BOND_MAX_ID; bid++) {
bdev = bond_mngr.bond_dev[bid];
@@ -283,38 +291,73 @@ static struct hinic3_bond_dev *bond_get_bdev(const struct bonding *bond)
mutex_unlock(&g_bond_mutex);
return bdev;
}
+
+ if (strncmp(bond->dev->name,
+ bdev->name, BOND_NAME_MAX_LEN) == 0) {
+ bdev->bond = bond;
+ return bdev;
+ }
}
mutex_unlock(&g_bond_mutex);
return NULL;
}
-static void bond_handle_rtnl_event(struct net_device *ndev)
+static struct bonding *get_bonding_by_netdev(struct net_device *ndev)
{
- struct hinic3_bond_dev *bdev = NULL;
struct bonding *bond = NULL;
struct slave *slave = NULL;
if (netif_is_bond_master(ndev)) {
bond = netdev_priv(ndev);
- bdev = bond_get_bdev(bond);
} else if (netif_is_bond_slave(ndev)) {
- /*lint -e(160) */
slave = bond_slave_get_rtnl(ndev);
if (slave) {
bond = bond_get_bond_by_slave(slave);
- bdev = bond_get_bdev(bond);
}
}
- if (!bond || !bdev)
+ return bond;
+}
+
+bool hinic3_is_bond_dev_status_actived(struct net_device *ndev)
+{
+ struct hinic3_bond_dev *bdev = NULL;
+ struct bonding *bond = NULL;
+
+ if (!ndev) {
+ pr_err("hinic3_bond: netdev is NULL\n");
+ return false;
+ }
+
+ bond = get_bonding_by_netdev(ndev);
+ bdev = bond_get_bdev(bond);
+ if (!bdev)
+ return false;
+
+ return bdev->status == BOND_DEV_STATUS_ACTIVATED;
+}
+EXPORT_SYMBOL(hinic3_is_bond_dev_status_actived);
+/*lint +e580 +e546*/
+
+static void bond_handle_rtnl_event(struct net_device *ndev)
+{
+ struct hinic3_bond_dev *bdev = NULL;
+ struct bonding *bond = NULL;
+ struct slave *slave = NULL;
+
+ bond = get_bonding_by_netdev(ndev);
+ bdev = bond_get_bdev(bond);
+ if (!bdev)
return;
bond_update_attr(bdev, bond);
- if (slave)
+ if (netif_is_bond_slave(ndev)) {
+ slave = bond_slave_get_rtnl(ndev);
bond_slave_event(bdev, slave);
- else
+ } else {
bond_master_event(bdev, bond);
+ }
}
static void bond_rtnl_data_ready(struct sock *sk)
@@ -368,7 +411,8 @@ static int bond_enable_netdev_event(void)
(*rtnl_sock)->sk->sk_data_ready = bond_rtnl_data_ready;
(*rtnl_sock)->sk->sk_allocation = GFP_KERNEL;
- err = kernel_bind(*rtnl_sock, (struct sockaddr *)(u8 *)&addr, sizeof(addr));
+ err = kernel_bind(*rtnl_sock, (struct sockaddr *)(u8 *)&addr,
+ sizeof(addr));
if (err) {
pr_err("hinic3_bond: Couldn't bind rtnl socket.\n");
sock_release(*rtnl_sock);
@@ -387,7 +431,7 @@ static void bond_disable_netdev_event(void)
static int bond_send_upcmd(struct hinic3_bond_dev *bdev, struct bond_attr *attr,
u8 cmd_type)
{
- int err, len;
+ int err, ret, len;
struct hinic3_bond_cmd cmd = {0};
u16 out_size = sizeof(cmd);
@@ -403,7 +447,9 @@ static int bond_send_upcmd(struct hinic3_bond_dev *bdev, struct bond_attr *attr,
len = sizeof(cmd.bond_name);
if (cmd_type == MPU_CMD_BOND_CREATE) {
- strscpy(cmd.bond_name, bdev->name, len);
+ ret = strscpy(cmd.bond_name, bdev->name, len);
+ if (ret < 0)
+ pr_err("strscpy bond name failed\n");
cmd.bond_name[sizeof(cmd.bond_name) - 1] = '\0';
}
@@ -478,7 +524,11 @@ static void bond_update_slave_info(struct hinic3_bond_dev *bdev,
continue;
}
+ if (!bdev->tracker.ndev[i])
+ continue;
+
bond_pf_bitmap_set(bdev, i);
+
if (!bdev->tracker.netdev_state[i].tx_enabled)
continue;
@@ -516,6 +566,7 @@ static int bond_upcmd_config(struct hinic3_bond_dev *bdev,
attr->active_slaves,
attr->lacp_collect_slaves);
pr_info("bond_pf_bitmap: 0x%x\n", attr->bond_pf_bitmap);
+ pr_info("bond user_bitmap 0x%x\n", attr->user_bitmap);
err = bond_send_upcmd(bdev, attr, MPU_CMD_BOND_SET_ATTR);
if (!err)
@@ -544,8 +595,10 @@ static int bond_upcmd_activate(struct hinic3_bond_dev *bdev,
return err;
}
-static void bond_call_service_func(struct hinic3_bond_dev *bdev, struct bond_attr *attr,
- enum bond_service_proc_pos pos, int bond_status)
+static void bond_call_service_func(struct hinic3_bond_dev *bdev,
+ struct bond_attr *attr,
+ enum bond_service_proc_pos pos,
+ int bond_status)
{
int i;
@@ -560,6 +613,18 @@ static void bond_call_service_func(struct hinic3_bond_dev *bdev, struct bond_att
mutex_unlock(&g_bond_service_func_mutex);
}
+static u32 bond_get_user_bitmap(struct hinic3_bond_dev *bdev)
+{
+ u32 user_bitmap = 0;
+ u8 user;
+
+ for (user = HINIC3_BOND_USER_OVS; user < HINIC3_BOND_USER_NUM; user++) {
+ if (bdev->slot_used[user] == 1)
+ BITMAP_SET(user_bitmap, user);
+ }
+ return user_bitmap;
+}
+
static void bond_do_work(struct hinic3_bond_dev *bdev)
{
bool is_bonded = 0;
@@ -570,7 +635,7 @@ static void bond_do_work(struct hinic3_bond_dev *bdev)
is_bonded = bdev->tracker.is_bonded;
attr = bdev->new_attr;
spin_unlock(&bdev->lock);
- attr.user_bitmap = 0;
+ attr.user_bitmap = bond_get_user_bitmap(bdev);
/* is_bonded indicates whether bond should be activated. */
if (is_bonded && !bond_dev_is_activated(bdev)) {
@@ -597,15 +662,22 @@ static void bond_try_do_work(struct work_struct *work)
struct delayed_work *delayed_work = to_delayed_work(work);
struct hinic3_bond_dev *bdev =
container_of(delayed_work, struct hinic3_bond_dev, bond_work);
+ int status;
- if (g_bond_service_func[HINIC3_BOND_USER_ROCE] && bdev->tracker.cnt < MIN_BOND_SLAVE_CNT)
+ status = mutex_trylock(&g_bond_mutex);
+ if (status == 0) {
+ /* Delay 1 sec and retry */
queue_delayed_work(bdev->wq, &bdev->bond_work, HZ);
- else
+ } else {
bond_do_work(bdev);
+ mutex_unlock(&g_bond_mutex);
+ }
}
static int bond_dev_init(struct hinic3_bond_dev *bdev, const char *name)
{
+ int err = 0;
+
bdev->wq = create_singlethread_workqueue("hinic3_bond_wq");
if (!bdev->wq) {
pr_err("hinic3_bond: Failed to create workqueue\n");
@@ -614,7 +686,13 @@ static int bond_dev_init(struct hinic3_bond_dev *bdev, const char *name)
INIT_DELAYED_WORK(&bdev->bond_work, bond_try_do_work);
bdev->status = BOND_DEV_STATUS_IDLE;
- strscpy(bdev->name, name, sizeof(bdev->name));
+ err = strscpy(bdev->name, name, strlen(name));
+ if (err < 0) {
+ pr_err("hinic3_bond: Failed to init bond dev\n");
+ cancel_delayed_work_sync(&bdev->bond_work);
+ destroy_workqueue(bdev->wq);
+ return err;
+ }
spin_lock_init(&bdev->lock);
@@ -630,6 +708,7 @@ static int bond_dev_release(struct hinic3_bond_dev *bdev)
err = bond_upcmd_deactivate(bdev);
if (err) {
pr_err("hinic3_bond: Failed to deactivate dev\n");
+ mutex_unlock(&g_bond_mutex);
return err;
}
@@ -637,7 +716,8 @@ static int bond_dev_release(struct hinic3_bond_dev *bdev)
if (bond_mngr.bond_dev[i] == bdev) {
bond_mngr.bond_dev[i] = NULL;
bond_mngr.cnt--;
- pr_info("hinic3_bond: Free bond, id: %u mngr_cnt:%u\n", i, bond_mngr.cnt);
+ pr_info("hinic3_bond: Free bond, id: %u mngr_cnt:%u\n",
+ i, bond_mngr.cnt);
break;
}
}
@@ -694,7 +774,8 @@ static struct hinic3_bond_dev *bond_dev_alloc(const char *name)
bdev->bond_attr.bond_id = i;
bond_mngr.bond_dev[i] = bdev;
bond_mngr.cnt++;
- pr_info("hinic3_bond: Create bond dev, id:%u cnt:%u\n", i, bond_mngr.cnt);
+ pr_info("hinic3_bond: Create bond dev, id:%u cnt:%u\n",
+ i, bond_mngr.cnt);
break;
}
}
@@ -764,20 +845,28 @@ static struct hinic3_bond_dev *bond_dev_by_name(const char *name)
static void bond_dev_user_attach(struct hinic3_bond_dev *bdev,
enum hinic3_bond_user user)
{
+ u32 user_bitmap;
+
+ if (user < 0 || user >= HINIC3_BOND_USER_NUM)
+ return;
+
if (bdev->slot_used[user])
return;
bdev->slot_used[user] = 1;
- if (!kref_get_unless_zero(&bdev->ref))
+ if (!kref_get_unless_zero(&bdev->ref)) {
kref_init(&bdev->ref);
+ } else {
+ user_bitmap = bond_get_user_bitmap(bdev);
+ pr_info("hinic3_bond: user %u attach bond %s, user_bitmap %#x\n",
+ user, bdev->name, user_bitmap);
+ queue_delayed_work(bdev->wq, &bdev->bond_work, 0);
+ }
}
static void bond_dev_user_detach(struct hinic3_bond_dev *bdev,
enum hinic3_bond_user user, bool *freed)
{
- if (user < 0 || user >= HINIC3_BOND_USER_NUM)
- return;
-
if (bdev->slot_used[user]) {
bdev->slot_used[user] = 0;
if (kref_read(&bdev->ref) == 1)
@@ -790,16 +879,20 @@ static struct bonding *bond_get_knl_bonding(const char *name)
{
struct net_device *ndev_tmp = NULL;
+ rcu_read_lock();
for_each_netdev(&init_net, ndev_tmp) {
if (netif_is_bond_master(ndev_tmp) &&
- !strcmp(ndev_tmp->name, name))
+ !strcmp(ndev_tmp->name, name)) {
+ rcu_read_unlock();
return netdev_priv(ndev_tmp);
+ }
}
-
+ rcu_read_unlock();
return NULL;
}
-void hinic3_bond_set_user_bitmap(struct bond_attr *attr, enum hinic3_bond_user user)
+void hinic3_bond_set_user_bitmap(struct bond_attr *attr,
+ enum hinic3_bond_user user)
{
if (!BITMAP_JUDGE(attr->user_bitmap, user))
BITMAP_SET(attr->user_bitmap, user);
@@ -852,8 +945,9 @@ int hinic3_bond_detach(u16 bond_id, enum hinic3_bond_user user)
int err = 0;
bool lock_freed = false;
- if (bond_id < BOND_FIRST_ID || bond_id > BOND_MAX_ID) {
- pr_warn("hinic3_bond: Invalid bond id:%u to delete\n", bond_id);
+ if (!BOND_ID_IS_VALID(bond_id) || user >= HINIC3_BOND_USER_NUM) {
+ pr_warn("hinic3_bond: Invalid bond id or user, bond_id: %u, user: %d\n",
+ bond_id, user);
return -EINVAL;
}
@@ -861,7 +955,8 @@ int hinic3_bond_detach(u16 bond_id, enum hinic3_bond_user user)
if (!bond_mngr.bond_dev[bond_id])
err = -ENODEV;
else
- bond_dev_user_detach(bond_mngr.bond_dev[bond_id], user, &lock_freed);
+ bond_dev_user_detach(bond_mngr.bond_dev[bond_id],
+ user, &lock_freed);
if (!lock_freed)
mutex_unlock(&g_bond_mutex);
@@ -877,7 +972,8 @@ void hinic3_bond_clean_user(enum hinic3_bond_user user)
mutex_lock(&g_bond_mutex);
for (i = BOND_FIRST_ID; i <= BOND_MAX_ID; i++) {
if (bond_mngr.bond_dev[i]) {
- bond_dev_user_detach(bond_mngr.bond_dev[i], user, &lock_freed);
+ bond_dev_user_detach(bond_mngr.bond_dev[i],
+ user, &lock_freed);
if (lock_freed) {
mutex_lock(&g_bond_mutex);
lock_freed = false;
@@ -891,7 +987,7 @@ EXPORT_SYMBOL(hinic3_bond_clean_user);
int hinic3_bond_get_uplink_id(u16 bond_id, u32 *uplink_id)
{
- if (bond_id < BOND_FIRST_ID || bond_id > BOND_MAX_ID || !uplink_id) {
+ if (!BOND_ID_IS_VALID(bond_id) || !uplink_id) {
pr_warn("hinic3_bond: Invalid args, id: %u, uplink: %d\n",
bond_id, !!uplink_id);
return -EINVAL;
@@ -941,7 +1037,7 @@ int hinic3_bond_get_slaves(u16 bond_id, struct hinic3_bond_info_s *info)
int i;
int len;
- if (!info || bond_id < BOND_FIRST_ID || bond_id > BOND_MAX_ID) {
+ if (!info || !BOND_ID_IS_VALID(bond_id)) {
pr_warn("hinic3_bond: Invalid args, info: %d,id: %u\n",
!!info, bond_id);
return -EINVAL;
@@ -962,7 +1058,8 @@ int hinic3_bond_get_slaves(u16 bond_id, struct hinic3_bond_info_s *info)
for (i = 0; i < BOND_PORT_MAX_NUM; i++) {
if (BITMAP_JUDGE(info->slaves, i) && tracker->ndev[i]) {
len = sizeof(info->slaves_name[0]);
- strscpy(info->slaves_name[info->cnt], tracker->ndev[i]->name, len);
+ strscpy(info->slaves_name[info->cnt],
+ tracker->ndev[i]->name, len);
info->cnt++;
}
}
@@ -972,7 +1069,8 @@ int hinic3_bond_get_slaves(u16 bond_id, struct hinic3_bond_info_s *info)
}
EXPORT_SYMBOL(hinic3_bond_get_slaves);
-struct net_device *hinic3_bond_get_netdev_by_portid(const char *bond_name, u8 port_id)
+struct net_device *hinic3_bond_get_netdev_by_portid(const char *bond_name,
+ u8 port_id)
{
struct hinic3_bond_dev *bdev = NULL;
@@ -989,7 +1087,8 @@ struct net_device *hinic3_bond_get_netdev_by_portid(const char *bond_name, u8 po
}
EXPORT_SYMBOL(hinic3_bond_get_netdev_by_portid);
-int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos, u16 channel)
+int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos,
+ u16 channel)
{
struct comm_cmd_hw_bond_infos bond_infos;
u16 out_size = sizeof(bond_infos);
@@ -1002,7 +1101,8 @@ int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos, u1
bond_infos.infos.bond_id = infos->bond_id;
- err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_COMM, COMM_MGMT_CMD_GET_HW_BOND,
+ err = hinic3_msg_to_mgmt_sync(hwdev, HINIC3_MOD_COMM,
+ COMM_MGMT_CMD_GET_HW_BOND,
&bond_infos, sizeof(bond_infos),
&bond_infos, &out_size, 0, channel);
if (bond_infos.head.status || err || !out_size) {
@@ -1018,7 +1118,8 @@ int hinic3_get_hw_bond_infos(void *hwdev, struct hinic3_hw_bond_infos *infos, u1
}
EXPORT_SYMBOL(hinic3_get_hw_bond_infos);
-int hinic3_get_bond_tracker_by_name(const char *name, struct bond_tracker *tracker)
+int hinic3_get_bond_tracker_by_name(const char *name,
+ struct bond_tracker *tracker)
{
struct hinic3_bond_dev *bdev = NULL;
int i;
diff --git a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h
index 024de95..5ab36f7 100644
--- a/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h
+++ b/drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.h
@@ -82,6 +82,7 @@ struct hinic3_bond_cmd {
char bond_name[16];
};
+bool hinic3_is_bond_dev_status_actived(struct net_device *ndev);
void hinic3_bond_set_user_bitmap(struct bond_attr *attr, enum hinic3_bond_user user);
int hinic3_bond_attach(const char *name, enum hinic3_bond_user user, u16 *bond_id);
int hinic3_bond_detach(u16 bond_id, enum hinic3_bond_user user);
diff --git a/drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h b/drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h
deleted file mode 100644
index 557f326..0000000
--- a/drivers/net/ethernet/huawei/hinic3/cfg_mgt_comm_pub.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2016-2022. All rights reserved.
- * File name: Cfg_mgt_comm_pub.h
- * Version No.: Draft
- * Generation date: 2016 year 05 month 07 day
- * Latest modification:
- * Function description: Header file for communication between the: Host and FW
- * Function list:
- * Modification history:
- * 1. Date: 2016 May 07
- * Modify content: Create a file.
- */
-#ifndef CFG_MGT_COMM_PUB_H
-#define CFG_MGT_COMM_PUB_H
-
-#include "mgmt_msg_base.h"
-
-enum servic_bit_define {
- SERVICE_BIT_NIC = 0,
- SERVICE_BIT_ROCE = 1,
- SERVICE_BIT_VBS = 2,
- SERVICE_BIT_TOE = 3,
- SERVICE_BIT_IPSEC = 4,
- SERVICE_BIT_FC = 5,
- SERVICE_BIT_VIRTIO = 6,
- SERVICE_BIT_OVS = 7,
- SERVICE_BIT_NVME = 8,
- SERVICE_BIT_ROCEAA = 9,
- SERVICE_BIT_CURRENET = 10,
- SERVICE_BIT_PPA = 11,
- SERVICE_BIT_MIGRATE = 12,
- SERVICE_BIT_MAX
-};
-
-#define CFG_SERVICE_MASK_NIC (0x1 << SERVICE_BIT_NIC)
-#define CFG_SERVICE_MASK_ROCE (0x1 << SERVICE_BIT_ROCE)
-#define CFG_SERVICE_MASK_VBS (0x1 << SERVICE_BIT_VBS)
-#define CFG_SERVICE_MASK_TOE (0x1 << SERVICE_BIT_TOE)
-#define CFG_SERVICE_MASK_IPSEC (0x1 << SERVICE_BIT_IPSEC)
-#define CFG_SERVICE_MASK_FC (0x1 << SERVICE_BIT_FC)
-#define CFG_SERVICE_MASK_VIRTIO (0x1 << SERVICE_BIT_VIRTIO)
-#define CFG_SERVICE_MASK_OVS (0x1 << SERVICE_BIT_OVS)
-#define CFG_SERVICE_MASK_NVME (0x1 << SERVICE_BIT_NVME)
-#define CFG_SERVICE_MASK_ROCEAA (0x1 << SERVICE_BIT_ROCEAA)
-#define CFG_SERVICE_MASK_CURRENET (0x1 << SERVICE_BIT_CURRENET)
-#define CFG_SERVICE_MASK_PPA (0x1 << SERVICE_BIT_PPA)
-#define CFG_SERVICE_MASK_MIGRATE (0x1 << SERVICE_BIT_MIGRATE)
-
-/* Definition of the scenario ID in the cfg_data, which is used for SML memory allocation. */
-enum scenes_id_define {
- SCENES_ID_FPGA_ETH = 0,
- SCENES_ID_FPGA_TIOE = 1, /* Discarded */
- SCENES_ID_STORAGE_ROCEAA_2x100 = 2,
- SCENES_ID_STORAGE_ROCEAA_4x25 = 3,
- SCENES_ID_CLOUD = 4,
- SCENES_ID_FC = 5,
- SCENES_ID_STORAGE_ROCE = 6,
- SCENES_ID_COMPUTE_ROCE = 7,
- SCENES_ID_STORAGE_TOE = 8,
- SCENES_ID_MAX
-};
-
-/* struct cfg_cmd_dev_cap.sf_svc_attr */
-enum {
- SF_SVC_FT_BIT = (1 << 0),
- SF_SVC_RDMA_BIT = (1 << 1),
-};
-
-enum cfg_cmd {
- CFG_CMD_GET_DEV_CAP = 0,
- CFG_CMD_GET_HOST_TIMER = 1,
-};
-
-struct cfg_cmd_host_timer {
- struct mgmt_msg_head head;
-
- u8 host_id;
- u8 rsvd1;
-
- u8 timer_pf_num;
- u8 timer_pf_id_start;
- u16 timer_vf_num;
- u16 timer_vf_id_start;
- u32 rsvd2[8];
-};
-
-struct cfg_cmd_dev_cap {
- struct mgmt_msg_head head;
-
- u16 func_id;
- u16 rsvd1;
-
- /* Public resources */
- u8 host_id;
- u8 ep_id;
- u8 er_id;
- u8 port_id;
-
- u16 host_total_func;
- u8 host_pf_num;
- u8 pf_id_start;
- u16 host_vf_num;
- u16 vf_id_start;
- u8 host_oq_id_mask_val;
- u8 timer_en;
- u8 host_valid_bitmap;
- u8 rsvd_host;
-
- u16 svc_cap_en;
- u16 max_vf;
- u8 flexq_en;
- u8 valid_cos_bitmap;
- /* Reserved for func_valid_cos_bitmap */
- u8 port_cos_valid_bitmap;
- u8 rsvd_func1;
- u32 rsvd_func2;
-
- u8 sf_svc_attr;
- u8 func_sf_en;
- u8 lb_mode;
- u8 smf_pg;
-
- u32 max_conn_num;
- u16 max_stick2cache_num;
- u16 max_bfilter_start_addr;
- u16 bfilter_len;
- u16 hash_bucket_num;
-
- /* shared resource */
- u8 host_sf_en;
- u8 master_host_id;
- u8 srv_multi_host_mode;
- u8 virtio_vq_size;
-
- u32 rsvd_func3[5];
-
- /* l2nic */
- u16 nic_max_sq_id;
- u16 nic_max_rq_id;
- u16 nic_default_num_queues;
- u16 rsvd1_nic;
- u32 rsvd2_nic[2];
-
- /* RoCE */
- u32 roce_max_qp;
- u32 roce_max_cq;
- u32 roce_max_srq;
- u32 roce_max_mpt;
- u32 roce_max_drc_qp;
-
- u32 roce_cmtt_cl_start;
- u32 roce_cmtt_cl_end;
- u32 roce_cmtt_cl_size;
-
- u32 roce_dmtt_cl_start;
- u32 roce_dmtt_cl_end;
- u32 roce_dmtt_cl_size;
-
- u32 roce_wqe_cl_start;
- u32 roce_wqe_cl_end;
- u32 roce_wqe_cl_size;
- u8 roce_srq_container_mode;
- u8 rsvd_roce1[3];
- u32 rsvd_roce2[5];
-
- /* IPsec */
- u32 ipsec_max_sactx;
- u16 ipsec_max_cq;
- u16 rsvd_ipsec1;
- u32 rsvd_ipsec[2];
-
- /* OVS */
- u32 ovs_max_qpc;
- u32 rsvd_ovs1[3];
-
- /* ToE */
- u32 toe_max_pctx;
- u32 toe_max_cq;
- u16 toe_max_srq;
- u16 toe_srq_id_start;
- u16 toe_max_mpt;
- u16 toe_max_cctxt;
- u32 rsvd_toe[2];
-
- /* FC */
- u32 fc_max_pctx;
- u32 fc_max_scq;
- u32 fc_max_srq;
-
- u32 fc_max_cctx;
- u32 fc_cctx_id_start;
-
- u8 fc_vp_id_start;
- u8 fc_vp_id_end;
- u8 rsvd_fc1[2];
- u32 rsvd_fc2[5];
-
- /* VBS */
- u16 vbs_max_volq;
- u16 rsvd0_vbs;
- u32 rsvd1_vbs[3];
-
- u16 fake_vf_start_id;
- u16 fake_vf_num;
- u32 fake_vf_max_pctx;
- u16 fake_vf_bfilter_start_addr;
- u16 fake_vf_bfilter_len;
- u32 rsvd_glb[8];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h b/drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h
deleted file mode 100644
index 59e20a1..0000000
--- a/drivers/net/ethernet/huawei/hinic3/comm_cmdq_intf.h
+++ /dev/null
@@ -1,239 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
- ******************************************************************************
- File Name : comm_cmdq_intf.h
- Version : Initial Draft
- Description : common command queue interface
- Function List :
- History :
- Modification: Created file
-
-******************************************************************************/
-
-#ifndef COMM_CMDQ_INTF_H
-#define COMM_CMDQ_INTF_H
-
-/* Cmdq ack type */
-enum hinic3_ack_type {
- HINIC3_ACK_TYPE_CMDQ,
- HINIC3_ACK_TYPE_SHARE_CQN,
- HINIC3_ACK_TYPE_APP_CQN,
-
- HINIC3_MOD_ACK_MAX = 15,
-};
-
-/* Defines the queue type of the set arm bit. */
-enum {
- SET_ARM_BIT_FOR_CMDQ = 0,
- SET_ARM_BIT_FOR_L2NIC_SQ,
- SET_ARM_BIT_FOR_L2NIC_RQ,
- SET_ARM_BIT_TYPE_NUM
-};
-
-/* Defines the type. Each function supports a maximum of eight CMDQ types. */
-enum {
- CMDQ_0 = 0,
- CMDQ_1 = 1, /* dedicated and non-blocking queues */
- CMDQ_NUM
-};
-
-/* *******************cmd common command data structure ************************ */
-// Func->ucode, which is used to set arm bit data,
-// The microcode needs to perform big-endian conversion.
-struct comm_info_ucode_set_arm_bit {
- u32 q_type;
- u32 q_id;
-};
-
-/* *******************WQE data structure ************************ */
-union cmdq_wqe_cs_dw0 {
- struct {
- u32 err_status : 29;
- u32 error_code : 2;
- u32 rsvd : 1;
- } bs;
- u32 val;
-};
-
-union cmdq_wqe_cs_dw1 {
- // This structure is used when the driver writes the wqe.
- struct {
- u32 token : 16; // [15:0]
- u32 cmd : 8; // [23:16]
- u32 mod : 5; // [28:24]
- u32 ack_type : 2; // [30:29]
- u32 obit : 1; // [31]
- } drv_wr;
-
- /* The uCode writes back the structure of the CS_DW1. */
- /* The driver reads and uses the structure. */
- struct {
- u32 mod : 5; // [4:0]
- u32 ack_type : 3; // [7:5]
- u32 cmd : 8; // [15:8]
- u32 arm : 1; // [16]
- u32 rsvd : 14; // [30:17]
- u32 obit : 1; // [31]
- } wb;
- u32 val;
-};
-
-/* CmdQ BD information or write back buffer information */
-struct cmdq_sge {
- u32 pa_h; // Upper 32 bits of the physical address
- u32 pa_l; // Upper 32 bits of the physical address
- u32 len; // Invalid bit[31].
- u32 resv;
-};
-
-/* Ctrls section definition of WQE */
-struct cmdq_wqe_ctrls {
- union {
- struct {
- u32 bdsl : 8; // [7:0]
- u32 drvsl : 2; // [9:8]
- u32 rsv : 4; // [13:10]
- u32 wf : 1; // [14]
- u32 cf : 1; // [15]
- u32 tsl : 5; // [20:16]
- u32 va : 1; // [21]
- u32 df : 1; // [22]
- u32 cr : 1; // [23]
- u32 difsl : 3; // [26:24]
- u32 csl : 2; // [28:27]
- u32 ctrlsl : 2; // [30:29]
- u32 obit : 1; // [31]
- } bs;
- u32 val;
- } header;
- u32 qsf;
-};
-
-/* Complete section definition of WQE */
-struct cmdq_wqe_cs {
- union cmdq_wqe_cs_dw0 dw0;
- union cmdq_wqe_cs_dw1 dw1;
- union {
- struct cmdq_sge sge;
- u32 dw2_5[4];
- } ack;
-};
-
-/* Inline header in WQE inline, describing the length of inline data */
-union cmdq_wqe_inline_header {
- struct {
- u32 buf_len : 11; // [10:0] inline data len
- u32 rsv : 21; // [31:11]
- } bs;
- u32 val;
-};
-
-/* Definition of buffer descriptor section in WQE */
-union cmdq_wqe_bds {
- struct {
- struct cmdq_sge bds_sge;
- u32 rsvd[4]; /* Zwy is used to transfer the virtual address of the buffer. */
- } lcmd; /* Long command, non-inline, and SGE describe the buffer information. */
-};
-
-/* Definition of CMDQ WQE */
-/* (long cmd, 64B)
- * +----------------------------------------+
- * | ctrl section(8B) |
- * +----------------------------------------+
- * | |
- * | complete section(24B) |
- * | |
- * +----------------------------------------+
- * | |
- * | buffer descriptor section(16B) |
- * | |
- * +----------------------------------------+
- * | driver section(16B) |
- * +----------------------------------------+
- *
- *
- * (middle cmd, 128B)
- * +----------------------------------------+
- * | ctrl section(8B) |
- * +----------------------------------------+
- * | |
- * | complete section(24B) |
- * | |
- * +----------------------------------------+
- * | |
- * | buffer descriptor section(88B) |
- * | |
- * +----------------------------------------+
- * | driver section(8B) |
- * +----------------------------------------+
- *
- *
- * (short cmd, 64B)
- * +----------------------------------------+
- * | ctrl section(8B) |
- * +----------------------------------------+
- * | |
- * | complete section(24B) |
- * | |
- * +----------------------------------------+
- * | |
- * | buffer descriptor section(24B) |
- * | |
- * +----------------------------------------+
- * | driver section(8B) |
- * +----------------------------------------+
- */
-struct cmdq_wqe {
- struct cmdq_wqe_ctrls ctrls;
- struct cmdq_wqe_cs cs;
- union cmdq_wqe_bds bds;
-};
-
-/* Definition of ctrls section in inline WQE */
-struct cmdq_wqe_ctrls_inline {
- union {
- struct {
- u32 bdsl : 8; // [7:0]
- u32 drvsl : 2; // [9:8]
- u32 rsv : 4; // [13:10]
- u32 wf : 1; // [14]
- u32 cf : 1; // [15]
- u32 tsl : 5; // [20:16]
- u32 va : 1; // [21]
- u32 df : 1; // [22]
- u32 cr : 1; // [23]
- u32 difsl : 3; // [26:24]
- u32 csl : 2; // [28:27]
- u32 ctrlsl : 2; // [30:29]
- u32 obit : 1; // [31]
- } bs;
- u32 val;
- } header;
- u32 qsf;
- u64 db;
-};
-
-/* Buffer descriptor section definition of WQE */
-union cmdq_wqe_bds_inline {
- struct {
- union cmdq_wqe_inline_header header;
- u32 rsvd;
- u8 data_inline[80];
- } mcmd; /* Middle command, inline mode */
-
- struct {
- union cmdq_wqe_inline_header header;
- u32 rsvd;
- u8 data_inline[16];
- } scmd; /* Short command, inline mode */
-};
-
-struct cmdq_wqe_inline {
- struct cmdq_wqe_ctrls_inline ctrls;
- struct cmdq_wqe_cs cs;
- union cmdq_wqe_bds_inline bds;
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/comm_defs.h b/drivers/net/ethernet/huawei/hinic3/comm_defs.h
deleted file mode 100644
index c5b1913..0000000
--- a/drivers/net/ethernet/huawei/hinic3/comm_defs.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
- * File Name : comm_defs.h
- * Version : Initial Draft
- * Description : common definitions
- * Function List :
- * History :
- * Modification: Created file
- */
-
-#ifndef COMM_DEFS_H
-#define COMM_DEFS_H
-
-/* CMDQ MODULE_TYPE */
-enum hinic3_mod_type {
- HINIC3_MOD_COMM = 0, /* HW communication module */
- HINIC3_MOD_L2NIC = 1, /* L2NIC module */
- HINIC3_MOD_ROCE = 2,
- HINIC3_MOD_PLOG = 3,
- HINIC3_MOD_TOE = 4,
- HINIC3_MOD_FLR = 5,
- HINIC3_MOD_RSVD1 = 6,
- HINIC3_MOD_CFGM = 7, /* Configuration module */
- HINIC3_MOD_CQM = 8,
- HINIC3_MOD_VMSEC = 9,
- COMM_MOD_FC = 10,
- HINIC3_MOD_OVS = 11,
- HINIC3_MOD_DSW = 12,
- HINIC3_MOD_MIGRATE = 13,
- HINIC3_MOD_HILINK = 14,
- HINIC3_MOD_CRYPT = 15, /* secure crypto module */
- HINIC3_MOD_VIO = 16,
- HINIC3_MOD_IMU = 17,
- HINIC3_MOD_DFT = 18, /* DFT */
- HINIC3_MOD_HW_MAX = 19, /* hardware max module id */
- /* Software module id, for PF/VF and multi-host */
- HINIC3_MOD_SW_FUNC = 20,
- HINIC3_MOD_MAX,
-};
-
-/* func reset的flag ,用于指示清理哪种资源 */
-enum func_reset_flag {
- RES_TYPE_FLUSH_BIT = 0,
- RES_TYPE_MQM,
- RES_TYPE_SMF,
- RES_TYPE_PF_BW_CFG,
-
- RES_TYPE_COMM = 10,
- RES_TYPE_COMM_MGMT_CH, /* clear mbox and aeq, The RES_TYPE_COMM bit must be set */
- RES_TYPE_COMM_CMD_CH, /* clear cmdq and ceq, The RES_TYPE_COMM bit must be set */
- RES_TYPE_NIC,
- RES_TYPE_OVS,
- RES_TYPE_VBS,
- RES_TYPE_ROCE,
- RES_TYPE_FC,
- RES_TYPE_TOE,
- RES_TYPE_IPSEC,
- RES_TYPE_MAX,
-};
-
-#define HINIC3_COMM_RES \
- ((1 << RES_TYPE_COMM) | (1 << RES_TYPE_COMM_CMD_CH) | \
- (1 << RES_TYPE_FLUSH_BIT) | (1 << RES_TYPE_MQM) | \
- (1 << RES_TYPE_SMF) | (1 << RES_TYPE_PF_BW_CFG))
-
-#define HINIC3_NIC_RES BIT(RES_TYPE_NIC)
-#define HINIC3_OVS_RES BIT(RES_TYPE_OVS)
-#define HINIC3_VBS_RES BIT(RES_TYPE_VBS)
-#define HINIC3_ROCE_RES BIT(RES_TYPE_ROCE)
-#define HINIC3_FC_RES BIT(RES_TYPE_FC)
-#define HINIC3_TOE_RES BIT(RES_TYPE_TOE)
-#define HINIC3_IPSEC_RES BIT(RES_TYPE_IPSEC)
-
-/* MODE OVS、NIC、UNKNOWN */
-#define HINIC3_WORK_MODE_OVS 0
-#define HINIC3_WORK_MODE_UNKNOWN 1
-#define HINIC3_WORK_MODE_NIC 2
-
-#define DEVICE_TYPE_L2NIC 0
-#define DEVICE_TYPE_NVME 1
-#define DEVICE_TYPE_VIRTIO_NET 2
-#define DEVICE_TYPE_VIRTIO_BLK 3
-#define DEVICE_TYPE_VIRTIO_VSOCK 4
-#define DEVICE_TYPE_VIRTIO_NET_TRANSITION 5
-#define DEVICE_TYPE_VIRTIO_BLK_TRANSITION 6
-#define DEVICE_TYPE_VIRTIO_SCSI_TRANSITION 7
-#define DEVICE_TYPE_VIRTIO_HPC 8
-
-/* Common header control information of the COMM message
- * interaction command word between the driver and PF
- */
-struct comm_info_head {
- u8 status;
- u8 version;
- u8 rep_aeq_num;
- u8 rsvd[5];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h b/drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h
deleted file mode 100644
index ae998cf..0000000
--- a/drivers/net/ethernet/huawei/hinic3/comm_msg_intf.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
- * File Name : comm_msg_intf.h
- * Version : Initial Draft
- * Created : 2021/6/28
- * Last Modified :
- * Description : COMM Command interfaces between Driver and MPU
- * Function List :
- */
-
-#ifndef COMM_MSG_INTF_H
-#define COMM_MSG_INTF_H
-
-#include "comm_defs.h"
-#include "mgmt_msg_base.h"
-#include "mpu_cmd_base_defs.h"
-#include "mpu_inband_cmd_defs.h"
-
-struct spu_cmd_freq_operation {
- struct comm_info_head head;
-
- u8 op_code; /* 0: get 1: set 2: check */
- u8 rsvd[3];
- u32 freq;
-};
-
-struct spu_cmd_power_operation {
- struct comm_info_head head;
-
- u8 op_code; /* 0: get 1: set 2: init */
- u8 slave_addr;
- u8 cmd_id;
- u8 size;
- u32 value;
-};
-
-struct spu_cmd_tsensor_operation {
- struct comm_info_head head;
-
- u8 op_code;
- u8 rsvd[3];
- s16 fabric_tsensor_temp_avg;
- s16 fabric_tsensor_temp;
- s16 sys_tsensor_temp_avg;
- s16 sys_tsensor_temp;
-};
-
-enum cfg_msix_operation {
- CFG_MSIX_OPERATION_FREE = 0,
- CFG_MSIX_OPERATION_ALLOC = 1,
-};
-
-struct comm_cmd_ffm_info {
- struct mgmt_msg_head head;
-
- u8 node_id;
- /* error level of the interrupt source */
- u8 err_level;
- /* Classification by interrupt source properties */
- u16 err_type;
- u32 err_csr_addr;
- u32 err_csr_value;
- u32 rsvd1;
-};
-
-struct hinic3_cmd_update_firmware {
- struct mgmt_msg_head msg_head;
-
- struct {
- u32 sl : 1;
- u32 sf : 1;
- u32 flag : 1;
- u32 bit_signed : 1;
- u32 reserved : 12;
- u32 fragment_len : 16;
- } ctl_info;
-
- struct {
- u32 section_crc;
- u32 section_type;
- } section_info;
-
- u32 total_len;
- u32 section_len;
- u32 section_version;
- u32 section_offset;
- u32 data[384];
-};
-
-struct hinic3_cmd_activate_firmware {
- struct mgmt_msg_head msg_head;
- u8 index; /* 0 ~ 7 */
- u8 data[7];
-};
-
-struct hinic3_cmd_switch_config {
- struct mgmt_msg_head msg_head;
- u8 index; /* 0 ~ 7 */
- u8 data[7];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c
index 8c95032..aad3a97 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.c
@@ -28,6 +28,8 @@
#include "cqm_npu_cmd.h"
#include "cqm_npu_cmd_defs.h"
+#include "vram_common.h"
+
static void cqm_bat_fill_cla_common_gpa(struct tag_cqm_handle *cqm_handle,
struct tag_cqm_cla_table *cla_table,
struct tag_cqm_bat_entry_standerd *bat_entry_standerd)
@@ -366,6 +368,13 @@ static s32 cqm_bat_update_cmd(struct tag_cqm_handle *cqm_handle, struct tag_cqm_
struct hinic3_hwdev *handle = cqm_handle->ex_handle;
struct tag_cqm_cmdq_bat_update *bat_update_cmd = NULL;
s32 ret = CQM_FAIL;
+ int is_in_kexec;
+
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ cqm_info(handle->dev_hdl, "Skip updating the cqm_bat to chip during kexec!\n");
+ return CQM_SUCCESS;
+ }
bat_update_cmd = (struct tag_cqm_cmdq_bat_update *)(buf_in->buf);
bat_update_cmd->offset = 0;
@@ -768,8 +777,10 @@ static s32 cqm_cla_xyz_lvl1(struct tag_cqm_handle *cqm_handle,
/* Applying for CLA_Z_BUF Space */
cla_z_buf = &cla_table->cla_z_buf;
cla_z_buf->buf_size = trunk_size;
- cla_z_buf->buf_number = (ALIGN(cla_table->max_buffer_size, trunk_size)) / trunk_size;
- cla_z_buf->page_number = cla_z_buf->buf_number << cla_table->trunk_order;
+ cla_z_buf->buf_number =
+ (ALIGN(cla_table->max_buffer_size, trunk_size)) / trunk_size;
+ cla_z_buf->page_number = cla_z_buf->buf_number <<
+ cla_table->trunk_order;
/* All buffer space must be statically allocated. */
if (cla_table->alloc_static) {
@@ -840,6 +851,7 @@ static s32 cqm_cla_xyz_lvl2_xyz_apply(struct tag_cqm_handle *cqm_handle,
cla_x_buf->buf_size = trunk_size;
cla_x_buf->buf_number = 1;
cla_x_buf->page_number = cla_x_buf->buf_number << cla_table->trunk_order;
+ cla_x_buf->buf_info.use_vram = get_use_vram_flag();
ret = cqm_buf_alloc(cqm_handle, cla_x_buf, false);
if (ret != CQM_SUCCESS)
return CQM_FAIL;
@@ -869,14 +881,20 @@ static s32 cqm_cla_xyz_vram_name_init(struct tag_cqm_cla_table *cla_table,
cla_x_buf = &cla_table->cla_x_buf;
cla_z_buf = &cla_table->cla_z_buf;
cla_y_buf = &cla_table->cla_y_buf;
+ cla_x_buf->buf_info.use_vram = get_use_vram_flag();
snprintf(cla_x_buf->buf_info.buf_vram_name,
- VRAM_NAME_MAX_LEN - 1, "%s%s", cla_table->name, VRAM_CQM_CLA_COORD_X);
+ VRAM_NAME_MAX_LEN, "%s%s", cla_table->name,
+ VRAM_CQM_CLA_COORD_X);
+ cla_y_buf->buf_info.use_vram = get_use_vram_flag();
snprintf(cla_y_buf->buf_info.buf_vram_name,
- VRAM_NAME_MAX_LEN - 1, "%s%s", cla_table->name, VRAM_CQM_CLA_COORD_Y);
+ VRAM_NAME_MAX_LEN, "%s%s", cla_table->name,
+ VRAM_CQM_CLA_COORD_Y);
+ cla_z_buf->buf_info.use_vram = get_use_vram_flag();
snprintf(cla_z_buf->buf_info.buf_vram_name,
- VRAM_NAME_MAX_LEN - 1, "%s%s", cla_table->name, VRAM_CQM_CLA_COORD_Z);
+ VRAM_NAME_MAX_LEN, "%s%s", cla_table->name,
+ VRAM_CQM_CLA_COORD_Z);
return CQM_SUCCESS;
}
@@ -1188,7 +1206,7 @@ static void cqm_cla_init_entry_extern(struct tag_cqm_handle *cqm_handle,
* exceed 128 x 4 KB. Otherwise, clearing the timer buffer of
* the function is complex.
*/
- cla_table->trunk_order = CQM_4K_PAGE_ORDER;
+ cla_table->trunk_order = CQM_8K_PAGE_ORDER;
cla_table->max_buffer_size = capability->timer_number *
capability->timer_basic_size;
cla_table->obj_size = capability->timer_basic_size;
@@ -1237,7 +1255,7 @@ static s32 cqm_cla_init_entry_condition(struct tag_cqm_handle *cqm_handle, u32 e
memcpy(cla_table_timer, cla_table, sizeof(struct tag_cqm_cla_table));
snprintf(cla_table_timer->name,
- VRAM_NAME_MAX_LEN - 1, "%s%s%01u", cla_table->name,
+ VRAM_NAME_MAX_LEN, "%s%s%01u", cla_table->name,
VRAM_CQM_CLA_SMF_BASE, i);
if (cqm_cla_xyz(cqm_handle, cla_table_timer) ==
@@ -1268,7 +1286,7 @@ static s32 cqm_cla_init_entry(struct tag_cqm_handle *cqm_handle,
for (i = 0; i < CQM_BAT_ENTRY_MAX; i++) {
cla_table = &bat_table->entry[i];
cla_table->type = bat_table->bat_entry_type[i];
- snprintf(cla_table->name, VRAM_NAME_MAX_LEN - 1,
+ snprintf(cla_table->name, VRAM_NAME_MAX_LEN,
"%s%s%s%02u", cqm_handle->name, VRAM_CQM_CLA_BASE,
VRAM_CQM_CLA_TYPE_BASE, cla_table->type);
@@ -1485,11 +1503,11 @@ static s32 cqm_cla_update(struct tag_cqm_handle *cqm_handle,
spu_en = 0;
pa = ((buf_node_parent->pa + (child_index * sizeof(dma_addr_t))) |
- (u32)spu_en);
+ spu_en);
cmd.gpa_h = CQM_ADDR_HI(pa);
cmd.gpa_l = CQM_ADDR_LW(pa);
- pa = (buf_node_child->pa | (u32)spu_en);
+ pa = (buf_node_child->pa | spu_en);
cmd.value_h = CQM_ADDR_HI(pa);
cmd.value_l = CQM_ADDR_LW(pa);
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h
index dd0766e..a51c1dc 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bat_cla.h
@@ -9,6 +9,7 @@
#include "cqm_bitmap_table.h"
#include "cqm_object.h"
+#include "vram_common.h"
/* When the connection check is enabled, the maximum number of connections
* supported by the chip is 1M - 63, which cannot reach 1M
@@ -19,6 +20,7 @@
#define CLA_TABLE_PAGE_ORDER 0
#define CQM_4K_PAGE_ORDER 0
#define CQM_4K_PAGE_SIZE 4096
+#define CQM_8K_PAGE_ORDER 1
#define CQM_BAT_ENTRY_MAX 16
#define CQM_BAT_ENTRY_SIZE 16
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c
index d5fac94..61602e6 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.c
@@ -273,6 +273,11 @@ s32 cqm_buf_alloc_direct(struct tag_cqm_handle *cqm_handle, struct tag_cqm_buf *
return CQM_SUCCESS;
}
+static bool check_use_vram(struct hinic3_hwdev *handle, struct tag_cqm_buf *buf)
+{
+ return buf->buf_info.use_vram ? true : false;
+}
+
static bool check_use_non_vram(struct hinic3_hwdev *handle, struct tag_cqm_buf *buf)
{
return buf->buf_info.use_vram ? false : true;
@@ -294,11 +299,46 @@ static bool check_for_nouse_node_alloc(struct hinic3_hwdev *handle, struct tag_c
return false;
}
+static s32 cqm_buf_vram_kalloc(struct hinic3_hwdev *handle, struct tag_cqm_buf *buf)
+{
+ void *vaddr = NULL;
+ int i;
+
+ vaddr = hi_vram_kalloc(buf->buf_info.buf_vram_name, (u64)buf->buf_size * buf->buf_number);
+ if (!vaddr) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
+ return CQM_FAIL;
+ }
+
+ for (i = 0; i < (s32)buf->buf_number; i++)
+ buf->buf_list[i].va = (void *)((char *)vaddr + i * (u64)buf->buf_size);
+
+ return CQM_SUCCESS;
+}
+
+static void cqm_buf_vram_free(struct tag_cqm_buf *buf)
+{
+ s32 i;
+
+ if (!buf->buf_list)
+ return;
+
+ if (buf->buf_list[0].va)
+ hi_vram_kfree(buf->buf_list[0].va, buf->buf_info.buf_vram_name,
+ (u64)buf->buf_size * buf->buf_number);
+
+ for (i = 0; i < (s32)buf->buf_number; i++)
+ buf->buf_list[i].va = NULL;
+}
+
static void cqm_buf_free_page_common(struct tag_cqm_buf *buf)
{
u32 order;
s32 i;
+ if (!buf->buf_list)
+ return;
+
order = (u32)get_order(buf->buf_size);
for (i = 0; i < (s32)buf->buf_number; i++) {
@@ -320,8 +360,10 @@ static s32 cqm_buf_use_node_alloc_page(struct hinic3_hwdev *handle, struct tag_c
node = dev_to_node(handle->dev_hdl);
for (i = 0; i < (s32)buf->buf_number; i++) {
newpage = alloc_pages_node(node, GFP_KERNEL | __GFP_ZERO, order);
- if (!newpage)
+ if (!newpage) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
break;
+ }
va = (void *)page_address(newpage);
/* Initialize the page after the page is applied for.
* If hash entries are involved, the initialization
@@ -349,8 +391,10 @@ static s32 cqm_buf_unused_node_alloc_page(struct hinic3_hwdev *handle, struct ta
for (i = 0; i < (s32)buf->buf_number; i++) {
va = (void *)ossl_get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
- if (!va)
+ if (!va) {
+ cqm_err(handle->dev_hdl, CQM_ALLOC_FAIL(buf_page));
break;
+ }
/* Initialize the page after the page is applied for.
* If hash entries are involved, the initialization
* value must be 0.
@@ -367,21 +411,21 @@ static s32 cqm_buf_unused_node_alloc_page(struct hinic3_hwdev *handle, struct ta
return CQM_SUCCESS;
}
-#define MALLOC_FUNCS_COUNT 2
-#define FREE_FUNCS_COUNT 1
-static const struct malloc_memory g_malloc_funcs[MALLOC_FUNCS_COUNT] = {
+static const struct malloc_memory g_malloc_funcs[] = {
+ {check_use_vram, cqm_buf_vram_kalloc},
{check_for_use_node_alloc, cqm_buf_use_node_alloc_page},
{check_for_nouse_node_alloc, cqm_buf_unused_node_alloc_page}
};
-static const struct free_memory g_free_funcs[FREE_FUNCS_COUNT] = {
+static const struct free_memory g_free_funcs[] = {
+ {check_use_vram, cqm_buf_vram_free},
{check_use_non_vram, cqm_buf_free_page_common}
};
static s32 cqm_buf_alloc_page(struct tag_cqm_handle *cqm_handle, struct tag_cqm_buf *buf)
{
struct hinic3_hwdev *handle = cqm_handle->ex_handle;
- u32 malloc_funcs_num = MALLOC_FUNCS_COUNT;
+ u32 malloc_funcs_num = ARRAY_SIZE(g_malloc_funcs);
u32 i;
for (i = 0; i < malloc_funcs_num; i++) {
@@ -398,7 +442,7 @@ static s32 cqm_buf_alloc_page(struct tag_cqm_handle *cqm_handle, struct tag_cqm_
static void cqm_buf_free_page(struct tag_cqm_buf *buf)
{
- u32 free_funcs_num = FREE_FUNCS_COUNT;
+ u32 free_funcs_num = ARRAY_SIZE(g_free_funcs);
u32 i;
for (i = 0; i < free_funcs_num; i++) {
@@ -447,8 +491,11 @@ static s32 cqm_buf_get_secure_mem_pages(struct tag_cqm_handle *cqm_handle, struc
cqm_get_secure_mem_pages(handle,
(u32)get_order(buf->buf_size),
&buf->buf_list[i].pa);
- if (!buf->buf_list[i].va)
+ if (!buf->buf_list[i].va) {
+ cqm_err(handle->dev_hdl,
+ CQM_ALLOC_FAIL(cqm_get_secure_mem_pages));
break;
+ }
}
if (i != buf->buf_number) {
@@ -777,7 +824,11 @@ static s32 cqm_single_bitmap_init(struct tag_cqm_bitmap *bitmap)
*/
bit_number = (ALIGN(bitmap->max_num, CQM_NUM_BIT_BYTE) >>
CQM_BYTE_BIT_SHIFT);
- bitmap->table = vmalloc(bit_number);
+ if (bitmap->bitmap_info.use_vram != 0)
+ bitmap->table = hi_vram_kalloc(bitmap->bitmap_info.buf_vram_name,
+ bit_number);
+ else
+ bitmap->table = vmalloc(bit_number);
if (!bitmap->table)
return CQM_FAIL;
memset(bitmap->table, 0, bit_number);
@@ -856,7 +907,7 @@ s32 cqm_bitmap_init(struct tag_cqm_handle *cqm_handle)
}
bitmap = &cla_table->bitmap;
- snprintf(bitmap->bitmap_info.buf_vram_name, VRAM_NAME_MAX_LEN - 1,
+ snprintf(bitmap->bitmap_info.buf_vram_name, VRAM_NAME_MAX_LEN,
"%s%s%02d", cla_table->name,
VRAM_CQM_BITMAP_BASE, cla_table->type);
@@ -866,6 +917,7 @@ s32 cqm_bitmap_init(struct tag_cqm_handle *cqm_handle)
bitmap->reserved_top = capability->qpc_reserved;
bitmap->reserved_back = capability->qpc_reserved_back;
bitmap->last = capability->qpc_reserved;
+ bitmap->bitmap_info.use_vram = get_use_vram_flag();
cqm_info(handle->dev_hdl,
"Bitmap init: cla_table_type=%u, max_num=0x%x\n",
cla_table->type, bitmap->max_num);
@@ -945,7 +997,14 @@ void cqm_bitmap_uninit(struct tag_cqm_handle *cqm_handle)
if (cla_table->type != CQM_BAT_ENTRY_T_INVALID &&
bitmap->table) {
spin_lock_deinit(&bitmap->lock);
- vfree(bitmap->table);
+ if (bitmap->bitmap_info.use_vram != 0)
+ hi_vram_kfree(bitmap->table,
+ bitmap->bitmap_info.buf_vram_name,
+ ALIGN(bitmap->max_num,
+ CQM_NUM_BIT_BYTE) >>
+ CQM_BYTE_BIT_SHIFT);
+ else
+ vfree(bitmap->table);
bitmap->table = NULL;
}
}
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h
index 7febf76..06b8661 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_bitmap_table.h
@@ -9,6 +9,7 @@
#include <linux/spinlock.h>
#include "cqm_object.h"
+#include "vram_common.h"
struct tag_cqm_bitmap {
ulong *table;
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c
index 9a13ae0..2a24e4a 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_db.c
@@ -196,6 +196,13 @@ void *cqm_get_db_addr(void *ex_handle, u32 service_type)
pr_err("[CQM]%s: ex_handle is null\n", __func__);
return NULL;
}
+
+ if (service_type >= CQM_SERVICE_T_MAX) {
+ pr_err("%s service_type = %d state is error\n", __func__,
+ service_type);
+ return NULL;
+ }
+
handle = (struct hinic3_hwdev *)ex_handle;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
service = &cqm_handle->service[service_type];
@@ -218,6 +225,17 @@ s32 cqm_ring_hardware_db(void *ex_handle, u32 service_type, u8 db_count, u64 db)
struct tag_cqm_service *service = NULL;
struct hinic3_hwdev *handle = NULL;
+ if (unlikely(!ex_handle)) {
+ pr_err("[CQM]%s: ex_handle is null\n", __func__);
+ return CQM_FAIL;
+ }
+
+ if (service_type >= CQM_SERVICE_T_MAX) {
+ pr_err("%s service_type = %d state is error\n", __func__,
+ service_type);
+ return CQM_FAIL;
+ }
+
handle = (struct hinic3_hwdev *)ex_handle;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
service = &cqm_handle->service[service_type];
@@ -278,6 +296,17 @@ s32 cqm_ring_direct_wqe_db(void *ex_handle, u32 service_type, u8 db_count,
u64 *tmp = (u64 *)direct_wqe;
int i;
+ if (unlikely(!ex_handle)) {
+ pr_err("[CQM]%s: ex_handle is null\n", __func__);
+ return CQM_FAIL;
+ }
+
+ if (service_type >= CQM_SERVICE_T_MAX) {
+ pr_err("%s service_type = %d state is error\n", __func__,
+ service_type);
+ return CQM_FAIL;
+ }
+
handle = (struct hinic3_hwdev *)ex_handle;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
service = &cqm_handle->service[service_type];
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c
index 19a8b56..1f1235c 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.c
@@ -23,6 +23,8 @@
#include "cqm_memsec.h"
#include "cqm_main.h"
+#include "vram_common.h"
+
static unsigned char roce_qpc_rsv_mode = CQM_QPC_ROCE_NORMAL;
module_param(roce_qpc_rsv_mode, byte, 0644);
MODULE_PARM_DESC(roce_qpc_rsv_mode,
@@ -98,10 +100,17 @@ static s32 cqm_set_timer_enable(void *ex_handle)
{
struct hinic3_hwdev *handle = (struct hinic3_hwdev *)ex_handle;
struct tag_cqm_handle *cqm_handle = NULL;
+ int is_in_kexec;
if (!ex_handle)
return CQM_FAIL;
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ cqm_info(handle->dev_hdl, "Skip starting cqm timer during kexec\n");
+ return CQM_SUCCESS;
+ }
+
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
if (cqm_handle->func_capability.fake_func_type == CQM_FAKE_FUNC_PARENT &&
cqm_set_fake_vf_timer(cqm_handle) != CQM_SUCCESS)
@@ -473,7 +482,8 @@ static void cqm_service_capability_init_roce(struct tag_cqm_handle *cqm_handle,
func_cap->qpc_number += roce_own_cap->max_qps;
func_cap->qpc_basic_size = GET_MAX(roce_own_cap->qpc_entry_sz,
func_cap->qpc_basic_size);
- if (cqm_handle->func_attribute.func_type == CQM_PF && (IS_MASTER_HOST(handle))) {
+ if (cqm_handle->func_attribute.func_type == CQM_PF &&
+ (IS_MASTER_HOST(handle))) {
func_cap->hash_number = roce_own_cap->max_qps;
func_cap->hash_basic_size = CQM_HASH_BUCKET_SIZE_64;
}
@@ -1129,8 +1139,9 @@ static s32 cqm_fake_mem_init(struct tag_cqm_handle *cqm_handle)
for (i = 0; i < (u32)child_func_number; i++) {
fake_cqm_handle = cqm_handle->fake_cqm_handle[i];
- snprintf(fake_cqm_handle->name, VRAM_NAME_MAX_LEN - 1,
- "%s%s%02u", cqm_handle->name, VRAM_CQM_FAKE_MEM_BASE, i);
+ snprintf(fake_cqm_handle->name, VRAM_NAME_MAX_LEN,
+ "%s%s%02u", cqm_handle->name,
+ VRAM_CQM_FAKE_MEM_BASE, i);
if (cqm_bat_init(fake_cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl,
@@ -1174,8 +1185,9 @@ s32 cqm_mem_init(void *ex_handle)
struct tag_cqm_handle *cqm_handle = NULL;
cqm_handle = (struct tag_cqm_handle *)(handle->cqm_hdl);
- snprintf(cqm_handle->name, VRAM_NAME_MAX_LEN - 1,
- "%s%02u", VRAM_CQM_GLB_FUNC_BASE, hinic3_global_func_id(handle));
+ snprintf(cqm_handle->name, VRAM_NAME_MAX_LEN,
+ "%s%02u", VRAM_CQM_GLB_FUNC_BASE,
+ hinic3_global_func_id(handle));
if (cqm_fake_init(cqm_handle) != CQM_SUCCESS) {
cqm_err(handle->dev_hdl, CQM_FUNCTION_FAIL(cqm_fake_init));
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h
index 4f87bd1..8d1e481 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_main.h
@@ -362,6 +362,7 @@ s32 cqm_fake_vf_num_set(void *ex_handle, u16 fake_vf_num_cfg);
#define CQM_LOG_ID 0
#define CQM_PTR_NULL(x) "%s: " #x " is null\n", __func__
+#define CQM_ALLOC_FAIL(x) "%s: " #x " alloc fail\n", __func__
#define CQM_MAP_FAIL(x) "%s: " #x " map fail\n", __func__
#define CQM_FUNCTION_FAIL(x) "%s: " #x " return failure\n", __func__
#define CQM_WRONG_VALUE(x) "%s: " #x " %u is wrong\n", __func__, (u32)(x)
diff --git a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c
index 213803f..f5fce8f 100644
--- a/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c
+++ b/drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c
@@ -378,7 +378,7 @@ static int hinic3_secure_mem_proc_node_remove(void *hwdev)
atomic_dec(&g_memsec_proc_refcnt);
- snprintf(pci_name, PCI_PROC_NAME_LEN - 1,
+ snprintf(pci_name, PCI_PROC_NAME_LEN,
"%02x:%02x:%x", pdev->bus->number, pdev->slot->number,
PCI_FUNC(pdev->devfn));
@@ -401,7 +401,7 @@ static int hinic3_secure_mem_proc_node_add(void *hwdev)
atomic_inc(&g_memsec_proc_refcnt);
- snprintf(pci_name, PCI_PROC_NAME_LEN - 1,
+ snprintf(pci_name, PCI_PROC_NAME_LEN,
"%02x:%02x:%x", pdev->bus->number, pdev->slot->number,
PCI_FUNC(pdev->devfn));
/* 0400 Read by owner */
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h b/drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h
deleted file mode 100644
index ad732c3..0000000
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_comm_cmd.h
+++ /dev/null
@@ -1,185 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2019-2022. All rights reserved.
- * File Name : hinic3_comm_cmd.h
- * Version : Initial Draft
- * Created : 2019/4/25
- * Last Modified :
- * Description : COMM Commands between Driver and MPU
- * Function List :
- */
-
-#ifndef HINIC3_COMMON_CMD_H
-#define HINIC3_COMMON_CMD_H
-
-/* COMM Commands between Driver to MPU */
-enum hinic3_mgmt_cmd {
- /* flr及资源清理相关命令 */
- COMM_MGMT_CMD_FUNC_RESET = 0,
- COMM_MGMT_CMD_FEATURE_NEGO,
- COMM_MGMT_CMD_FLUSH_DOORBELL,
- COMM_MGMT_CMD_START_FLUSH,
- COMM_MGMT_CMD_SET_FUNC_FLR,
- COMM_MGMT_CMD_GET_GLOBAL_ATTR,
- COMM_MGMT_CMD_SET_PPF_FLR_TYPE,
- COMM_MGMT_CMD_SET_FUNC_SVC_USED_STATE,
-
- /* 分配msi-x中断资源 */
- COMM_MGMT_CMD_CFG_MSIX_NUM = 10,
-
- /* 驱动相关配置命令 */
- COMM_MGMT_CMD_SET_CMDQ_CTXT = 20,
- COMM_MGMT_CMD_SET_VAT,
- COMM_MGMT_CMD_CFG_PAGESIZE,
- COMM_MGMT_CMD_CFG_MSIX_CTRL_REG,
- COMM_MGMT_CMD_SET_CEQ_CTRL_REG,
- COMM_MGMT_CMD_SET_DMA_ATTR,
-
- /* INFRA配置相关命令字 */
- COMM_MGMT_CMD_GET_MQM_FIX_INFO = 40,
- COMM_MGMT_CMD_SET_MQM_CFG_INFO,
- COMM_MGMT_CMD_SET_MQM_SRCH_GPA,
- COMM_MGMT_CMD_SET_PPF_TMR,
- COMM_MGMT_CMD_SET_PPF_HT_GPA,
- COMM_MGMT_CMD_SET_FUNC_TMR_BITMAT,
- COMM_MGMT_CMD_SET_MBX_CRDT,
- COMM_MGMT_CMD_CFG_TEMPLATE,
- COMM_MGMT_CMD_SET_MQM_LIMIT,
-
- /* 信息获取相关命令字 */
- COMM_MGMT_CMD_GET_FW_VERSION = 60,
- COMM_MGMT_CMD_GET_BOARD_INFO,
- COMM_MGMT_CMD_SYNC_TIME,
- COMM_MGMT_CMD_GET_HW_PF_INFOS,
- COMM_MGMT_CMD_SEND_BDF_INFO,
- COMM_MGMT_CMD_GET_VIRTIO_BDF_INFO,
- COMM_MGMT_CMD_GET_SML_TABLE_INFO,
- COMM_MGMT_CMD_GET_SDI_INFO,
-
- /* 升级相关命令字 */
- COMM_MGMT_CMD_UPDATE_FW = 80,
- COMM_MGMT_CMD_ACTIVE_FW,
- COMM_MGMT_CMD_HOT_ACTIVE_FW,
- COMM_MGMT_CMD_HOT_ACTIVE_DONE_NOTICE,
- COMM_MGMT_CMD_SWITCH_CFG,
- COMM_MGMT_CMD_CHECK_FLASH,
- COMM_MGMT_CMD_CHECK_FLASH_RW,
- COMM_MGMT_CMD_RESOURCE_CFG,
- COMM_MGMT_CMD_UPDATE_BIOS, /* TODO: merge to COMM_MGMT_CMD_UPDATE_FW */
- COMM_MGMT_CMD_MPU_GIT_CODE,
-
- /* chip reset相关 */
- COMM_MGMT_CMD_FAULT_REPORT = 100,
- COMM_MGMT_CMD_WATCHDOG_INFO,
- COMM_MGMT_CMD_MGMT_RESET,
- COMM_MGMT_CMD_FFM_SET, /* TODO: check if needed */
-
- /* chip info/log 相关 */
- COMM_MGMT_CMD_GET_LOG = 120,
- COMM_MGMT_CMD_TEMP_OP,
- COMM_MGMT_CMD_EN_AUTO_RST_CHIP,
- COMM_MGMT_CMD_CFG_REG,
- COMM_MGMT_CMD_GET_CHIP_ID,
- COMM_MGMT_CMD_SYSINFO_DFX,
- COMM_MGMT_CMD_PCIE_DFX_NTC,
- COMM_MGMT_CMD_DICT_LOG_STATUS, /* LOG STATUS 127 */
- COMM_MGMT_CMD_MSIX_INFO,
- COMM_MGMT_CMD_CHANNEL_DETECT,
- COMM_MGMT_CMD_DICT_COUNTER_STATUS,
-
- /* switch workmode 相关 */
- COMM_MGMT_CMD_CHECK_IF_SWITCH_WORKMODE = 140,
- COMM_MGMT_CMD_SWITCH_WORKMODE,
-
- /* mpu 相关 */
- COMM_MGMT_CMD_MIGRATE_DFX_HPA = 150,
- COMM_MGMT_CMD_BDF_INFO,
- COMM_MGMT_CMD_NCSI_CFG_INFO_GET_PROC,
-
- /* rsvd0 section */
- COMM_MGMT_CMD_SECTION_RSVD_0 = 160,
-
- /* rsvd1 section */
- COMM_MGMT_CMD_SECTION_RSVD_1 = 170,
-
- /* rsvd2 section */
- COMM_MGMT_CMD_SECTION_RSVD_2 = 180,
-
- /* rsvd3 section */
- COMM_MGMT_CMD_SECTION_RSVD_3 = 190,
-
- /* TODO: move to DFT mode */
- COMM_MGMT_CMD_GET_DIE_ID = 200,
- COMM_MGMT_CMD_GET_EFUSE_TEST,
- COMM_MGMT_CMD_EFUSE_INFO_CFG,
- COMM_MGMT_CMD_GPIO_CTL,
- COMM_MGMT_CMD_HI30_SERLOOP_START, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_HI30_SERLOOP_STOP, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_HI30_MBIST_SET_FLAG, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_HI30_MBIST_GET_RESULT, /* TODO: DFT or hilink */
- COMM_MGMT_CMD_ECC_TEST,
- COMM_MGMT_CMD_FUNC_BIST_TEST, /* 209 */
-
- COMM_MGMT_CMD_VPD_SET = 210,
- COMM_MGMT_CMD_VPD_GET,
-
- COMM_MGMT_CMD_ERASE_FLASH,
- COMM_MGMT_CMD_QUERY_FW_INFO,
- COMM_MGMT_CMD_GET_CFG_INFO,
- COMM_MGMT_CMD_GET_UART_LOG,
- COMM_MGMT_CMD_SET_UART_CMD,
- COMM_MGMT_CMD_SPI_TEST,
-
- /* TODO: ALL reg read/write merge to COMM_MGMT_CMD_CFG_REG */
- COMM_MGMT_CMD_UP_REG_GET,
- COMM_MGMT_CMD_UP_REG_SET, /* 219 */
-
- COMM_MGMT_CMD_REG_READ = 220,
- COMM_MGMT_CMD_REG_WRITE,
- COMM_MGMT_CMD_MAG_REG_WRITE,
- COMM_MGMT_CMD_ANLT_REG_WRITE,
-
- COMM_MGMT_CMD_HEART_EVENT, /* TODO: delete */
- COMM_MGMT_CMD_NCSI_OEM_GET_DRV_INFO, /* TODO: delete */
- COMM_MGMT_CMD_LASTWORD_GET,
- COMM_MGMT_CMD_READ_BIN_DATA, /* TODO: delete */
- /* COMM_MGMT_CMD_WWPN_GET, TODO: move to FC? */
- /* COMM_MGMT_CMD_WWPN_SET, TODO: move to FC? */ /* 229 */
-
- /* TODO: check if needed */
- COMM_MGMT_CMD_SET_VIRTIO_DEV = 230,
- COMM_MGMT_CMD_SET_MAC,
- /* MPU patch cmd */
- COMM_MGMT_CMD_LOAD_PATCH,
- COMM_MGMT_CMD_REMOVE_PATCH,
- COMM_MGMT_CMD_PATCH_ACTIVE,
- COMM_MGMT_CMD_PATCH_DEACTIVE,
- COMM_MGMT_CMD_PATCH_SRAM_OPTIMIZE,
- /* container host process */
- COMM_MGMT_CMD_CONTAINER_HOST_PROC,
- /* nsci counter */
- COMM_MGMT_CMD_NCSI_COUNTER_PROC,
- COMM_MGMT_CMD_CHANNEL_STATUS_CHECK, /* 239 */
-
- /* hot patch rsvd cmd */
- COMM_MGMT_CMD_RSVD_0 = 240,
- COMM_MGMT_CMD_RSVD_1,
- COMM_MGMT_CMD_RSVD_2,
- COMM_MGMT_CMD_RSVD_3,
- COMM_MGMT_CMD_RSVD_4,
- /* 无效字段,版本收编删除,编译使用 */
- COMM_MGMT_CMD_SEND_API_ACK_BY_UP,
-
- /* 注:添加cmd,不能修改已有命令字的值,请在前方rsvd
- * section中添加;原则上所有分支cmd表完全一致
- */
- COMM_MGMT_CMD_MAX = 255,
-};
-
-/* CmdQ Common subtype */
-enum comm_cmdq_cmd {
- COMM_CMD_UCODE_ARM_BIT_SET = 2,
- COMM_CMD_SEND_NPU_DFT_CMD,
-};
-
-#endif /* HINIC3_COMMON_CMD_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h
deleted file mode 100644
index 9ce908e..0000000
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
-
-#ifndef HINIC3_COMMON_H
-#define HINIC3_COMMON_H
-
-#include <linux/types.h>
-
-struct hinic3_dma_addr_align {
- u32 real_size;
-
- void *ori_vaddr;
- dma_addr_t ori_paddr;
-
- void *align_vaddr;
- dma_addr_t align_paddr;
-};
-
-enum hinic3_wait_return {
- WAIT_PROCESS_CPL = 0,
- WAIT_PROCESS_WAITING = 1,
- WAIT_PROCESS_ERR = 2,
-};
-
-struct hinic3_sge {
- u32 hi_addr;
- u32 lo_addr;
- u32 len;
-};
-
-#ifdef static
-#undef static
-#define LLT_STATIC_DEF_SAVED
-#endif
-
-/* *
- * hinic_cpu_to_be32 - convert data to big endian 32 bit format
- * @data: the data to convert
- * @len: length of data to convert, must be Multiple of 4B
- */
-static inline void hinic3_cpu_to_be32(void *data, int len)
-{
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = cpu_to_be32(*mem);
- mem++;
- }
-}
-
-/* *
- * hinic3_cpu_to_be32 - convert data from big endian 32 bit format
- * @data: the data to convert
- * @len: length of data to convert
- */
-static inline void hinic3_be32_to_cpu(void *data, int len)
-{
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = be32_to_cpu(*mem);
- mem++;
- }
-}
-
-/* *
- * hinic3_set_sge - set dma area in scatter gather entry
- * @sge: scatter gather entry
- * @addr: dma address
- * @len: length of relevant data in the dma address
- */
-static inline void hinic3_set_sge(struct hinic3_sge *sge, dma_addr_t addr,
- int len)
-{
- sge->hi_addr = upper_32_bits(addr);
- sge->lo_addr = lower_32_bits(addr);
- sge->len = len;
-}
-
-#define hinic3_hw_be32(val) (val)
-#define hinic3_hw_cpu32(val) (val)
-#define hinic3_hw_cpu16(val) (val)
-
-static inline void hinic3_hw_be32_len(void *data, int len)
-{
-}
-
-static inline void hinic3_hw_cpu32_len(void *data, int len)
-{
-}
-
-int hinic3_dma_zalloc_coherent_align(void *dev_hdl, u64 size, u64 align,
- unsigned int flag,
- struct hinic3_dma_addr_align *mem_align);
-
-void hinic3_dma_free_coherent_align(void *dev_hdl,
- struct hinic3_dma_addr_align *mem_align);
-
-typedef enum hinic3_wait_return (*wait_cpl_handler)(void *priv_data);
-
-int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler,
- u32 wait_total_ms, u32 wait_once_us);
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h b/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h
index 64139c4..4f5792f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_crm.h
@@ -8,7 +8,7 @@
#include "mpu_cmd_base_defs.h"
-#define HINIC3_DRV_VERSION "15.17.1.2"
+#define HINIC3_DRV_VERSION "17.7.8.1"
#define HINIC3_DRV_DESC "Intelligent Network Interface Card Driver"
#define HIUDK_DRV_DESC "Intelligent Network Unified Driver"
@@ -45,6 +45,7 @@ enum hinic3_service_type {
SERVICE_T_CUSTOM,
SERVICE_T_VROCE,
SERVICE_T_CRYPT,
+ SERVICE_T_VSOCK,
SERVICE_T_BIFUR,
SERVICE_T_MAX,
@@ -64,6 +65,9 @@ struct nic_service_cap {
u16 max_sqs;
u16 max_rqs;
u16 default_num_queues;
+ u16 outband_vlan_cfg_en;
+ u8 lro_enable;
+ u8 rsvd1[3];
};
struct ppa_service_cap {
@@ -909,6 +913,13 @@ int hinic3_get_mgmt_version(void *hwdev, u8 *mgmt_ver, u8 version_size,
int hinic3_get_fw_version(void *hwdev, struct hinic3_fw_version *fw_ver,
u16 channel);
+/* *
+ * @brief hinic3_get_bond_create_mode - get bond create mode
+ * @param hwdev: device pointer to hwdev
+ * @retval global function id
+ */
+u8 hinic3_get_bond_create_mode(void *udkdev);
+
/* *
* @brief hinic3_global_func_id - get global function id
* @param hwdev: device pointer to hwdev
@@ -1263,4 +1274,7 @@ int hinic3_mbox_to_host_sync(void *hwdev, enum hinic3_mod_type mod,
int hinic3_get_func_vroce_enable(void *hwdev, u16 glb_func_idx, u8 *en);
+void hinic3_module_get(void *hwdev, enum hinic3_service_type type);
+void hinic3_module_put(void *hwdev, enum hinic3_service_type type);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c
index 40ff473..1191653 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_dbg.c
@@ -18,9 +18,10 @@
#include "hinic3_tx.h"
#include "hinic3_dcb.h"
#include "hinic3_nic.h"
-#include "hinic3_mgmt_interface.h"
+#include "hinic3_bond.h"
+#include "nic_mpu_cmd_defs.h"
#include "mag_mpu_cmd.h"
-#include "mag_cmd.h"
+#include "mag_mpu_cmd_defs.h"
typedef int (*nic_driv_module)(struct hinic3_nic_dev *nic_dev,
const void *buf_in, u32 in_size,
@@ -34,7 +35,6 @@ struct nic_drv_module_handle {
static int get_nic_drv_version(void *buf_out, const u32 *out_size)
{
struct drv_version_info *ver_info = buf_out;
- int err;
if (!buf_out) {
pr_err("Buf_out is NULL.\n");
@@ -47,10 +47,8 @@ static int get_nic_drv_version(void *buf_out, const u32 *out_size)
return -EINVAL;
}
- err = snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s",
- HINIC3_NIC_DRV_VERSION, "2023-05-17_19:56:38");
- if (err < 0)
- return -EINVAL;
+ snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s",
+ HINIC3_NIC_DRV_VERSION, "2025-05-08_00:00:08");
return 0;
}
@@ -126,7 +124,8 @@ static int get_tx_wqe_info(struct hinic3_nic_dev *nic_dev,
}
if (!buf_in || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Buf_in or buf_out is NULL.\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_in or buf_out is NULL.\n");
return -EINVAL;
}
@@ -178,7 +177,8 @@ static int get_rx_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
}
rq_info->delta = (u16)nic_dev->rxqs[q_id].delta;
- rq_info->ci = (u16)(nic_dev->rxqs[q_id].cons_idx & nic_dev->rxqs[q_id].q_mask);
+ rq_info->ci = (u16)(nic_dev->rxqs[q_id].cons_idx &
+ nic_dev->rxqs[q_id].q_mask);
rq_info->sw_pi = nic_dev->rxqs[q_id].next_to_update;
rq_info->msix_vector = nic_dev->rxqs[q_id].irq_id;
@@ -201,7 +201,8 @@ static int get_rx_wqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
}
if (!buf_in || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Buf_in or buf_out is NULL.\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_in or buf_out is NULL.\n");
return -EINVAL;
}
@@ -230,7 +231,7 @@ static int get_rx_cqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return -EFAULT;
}
- if (!buf_in || !buf_out) {
+ if (!buf_in || !buf_out || !out_size) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Buf_in or buf_out is NULL.\n");
return -EINVAL;
@@ -243,7 +244,7 @@ static int get_rx_cqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return -EINVAL;
}
- if (!out_size || *out_size != sizeof(struct hinic3_rq_cqe)) {
+ if (*out_size != sizeof(struct hinic3_rq_cqe)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%u, expect: %lu\n",
*out_size, sizeof(struct hinic3_rq_cqe));
@@ -252,10 +253,12 @@ static int get_rx_cqe_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
q_id = (u16)info->q_id;
idx = (u16)info->wqe_id;
- if (q_id >= nic_dev->q_params.num_qps || idx >= nic_dev->rxqs[q_id].q_depth) {
+ if (q_id >= nic_dev->q_params.num_qps ||
+ idx >= nic_dev->rxqs[q_id].q_depth) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid q_id[%u] >= %u, or wqe idx[%u] >= %u.\n",
- q_id, nic_dev->q_params.num_qps, idx, nic_dev->rxqs[q_id].q_depth);
+ q_id, nic_dev->q_params.num_qps, idx,
+ nic_dev->rxqs[q_id].q_depth);
return -EFAULT;
}
@@ -338,7 +341,8 @@ static int set_loopback_mode(struct hinic3_nic_dev *nic_dev, const void *buf_in,
err = hinic3_set_loopback_mode(nic_dev->hwdev, (u8)mode->loop_mode,
(u8)mode->loop_ctrl);
if (err == 0)
- nicif_info(nic_dev, drv, nic_dev->netdev, "Set loopback mode %u en %u succeed\n",
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "Set loopback mode %u en %u succeed\n",
mode->loop_mode, mode->loop_ctrl);
return err;
@@ -417,6 +421,59 @@ static int set_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
{
u32 pf_bw_limit;
int err;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct net_device *net_dev = nic_dev->netdev;
+
+ if (hinic3_support_roce(nic_dev->hwdev, NULL) &&
+ hinic3_is_bond_dev_status_actived(net_dev)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "The rate limit func is not supported when RoCE bonding is enabled\n");
+ return -EINVAL;
+ }
+
+ if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "To set VF bandwidth rate, please use ip link cmd\n");
+ return -EINVAL;
+ }
+
+ if (!buf_in || !buf_out || in_size != sizeof(u32) ||
+ !out_size || *out_size != sizeof(u8))
+ return -EINVAL;
+
+ nic_io = hinic3_get_service_adapter(nic_dev->hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+ nic_io->direct = HINIC3_NIC_TX;
+ pf_bw_limit = *((u32 *)buf_in);
+
+ err = hinic3_set_pf_bw_limit(nic_dev->hwdev, pf_bw_limit);
+ if (err) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to set pf bandwidth limit to %u%%\n",
+ pf_bw_limit);
+ if (err < 0)
+ return err;
+ }
+
+ *((u8 *)buf_out) = (u8)err;
+
+ return 0;
+}
+
+static int set_rx_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ u32 pf_bw_limit;
+ int err;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct net_device *net_dev = nic_dev->netdev;
+
+ if (hinic3_support_roce(nic_dev->hwdev, NULL) &&
+ hinic3_is_bond_dev_status_actived(net_dev)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "The rate limit func is not supported when RoCE bonding is enabled\n");
+ return -EINVAL;
+ }
if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
nicif_err(nic_dev, drv, nic_dev->netdev, "To set VF bandwidth rate, please use ip link cmd\n");
@@ -426,11 +483,16 @@ static int set_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (!buf_in || !buf_out || in_size != sizeof(u32) || !out_size || *out_size != sizeof(u8))
return -EINVAL;
+ nic_io = hinic3_get_service_adapter(nic_dev->hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+ nic_io->direct = HINIC3_NIC_RX;
pf_bw_limit = *((u32 *)buf_in);
err = hinic3_set_pf_bw_limit(nic_dev->hwdev, pf_bw_limit);
if (err) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to set pf bandwidth limit to %d%%\n",
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to set pf bandwidth limit to %d%%\n",
pf_bw_limit);
if (err < 0)
return err;
@@ -445,19 +507,21 @@ static int get_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
struct hinic3_nic_io *nic_io = NULL;
+ u32 *rate_limit = (u32 *)buf_out;
if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "To get VF bandwidth rate, please use ip link cmd\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "To get VF bandwidth rate, please use ip link cmd\n");
return -EINVAL;
}
if (!buf_out || !out_size)
return -EINVAL;
- if (*out_size != sizeof(u32)) {
+ if (*out_size != sizeof(u32) * 2) { // 2:Stored in an array, TX and RX, both length are u32
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user: %d, expect: %lu\n",
- *out_size, sizeof(u32));
+ *out_size, sizeof(u32) * 2);
return -EFAULT;
}
@@ -465,8 +529,12 @@ static int get_pf_bw_limit(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (!nic_io)
return -EINVAL;
- *((u32 *)buf_out) = nic_io->nic_cfg.pf_bw_limit;
+ rate_limit[HINIC3_NIC_RX] = nic_io->nic_cfg.pf_bw_rx_limit;
+ rate_limit[HINIC3_NIC_TX] = nic_io->nic_cfg.pf_bw_tx_limit;
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "read rate cfg success rx rate is: %u, tx rate is : %u\n",
+ rate_limit[HINIC3_NIC_RX], rate_limit[HINIC3_NIC_TX]);
return 0;
}
@@ -477,8 +545,8 @@ static int get_sset_count(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (!buf_in || in_size != sizeof(u32) || !out_size ||
*out_size != sizeof(u32) || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n",
- in_size);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Invalid parameters, in_size: %u\n", in_size);
return -EINVAL;
}
@@ -504,16 +572,16 @@ static int get_sset_stats(struct hinic3_nic_dev *nic_dev, const void *buf_in,
int err;
if (!buf_in || in_size != sizeof(u32) || !out_size || !buf_out) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Invalid parameters, in_size: %u\n",
- in_size);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Invalid parameters, in_size: %u\n", in_size);
return -EINVAL;
}
size = sizeof(u32);
err = get_sset_count(nic_dev, buf_in, in_size, &count, &size);
if (err) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Get sset count failed, ret=%d\n",
- err);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Get sset count failed, ret=%d\n", err);
return -EINVAL;
}
if (count * sizeof(*items) != *out_size) {
@@ -527,12 +595,14 @@ static int get_sset_stats(struct hinic3_nic_dev *nic_dev, const void *buf_in,
switch (sset) {
case HINIC3_SHOW_SSET_IO_STATS:
- hinic3_get_io_stats(nic_dev, items);
+ err = hinic3_get_io_stats(nic_dev, items);
+ if (err < 0)
+ return -EINVAL;
break;
default:
- nicif_err(nic_dev, drv, nic_dev->netdev, "Unknown %u to get stats\n",
- sset);
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Unknown %u to get stats\n", sset);
err = -EINVAL;
break;
}
@@ -544,15 +614,18 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
struct hinic3_dcb_config *wanted_dcb_cfg,
const struct hinic3_mt_qos_dev_cfg *qos_in)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int i;
u8 cos_num = 0, valid_cos_bitmap = 0;
if (qos_in->cfg_bitmap & CMD_QOS_DEV_PCP2COS) {
for (i = 0; i < NIC_DCB_UP_MAX; i++) {
- if (!(nic_dev->func_dft_cos_bitmap & BIT(qos_in->pcp2cos[i]))) {
+ if (!(dcb->func_dft_cos_bitmap &
+ BIT(qos_in->pcp2cos[i]))) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid cos=%u, func cos valid map is %u",
- qos_in->pcp2cos[i], nic_dev->func_dft_cos_bitmap);
+ qos_in->pcp2cos[i],
+ dcb->func_dft_cos_bitmap);
return -EINVAL;
}
@@ -562,7 +635,8 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
}
}
- memcpy(wanted_dcb_cfg->pcp2cos, qos_in->pcp2cos, sizeof(qos_in->pcp2cos));
+ memcpy(wanted_dcb_cfg->pcp2cos, qos_in->pcp2cos,
+ sizeof(qos_in->pcp2cos));
wanted_dcb_cfg->pcp_user_cos_num = cos_num;
wanted_dcb_cfg->pcp_valid_cos_map = valid_cos_bitmap;
}
@@ -572,12 +646,14 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
valid_cos_bitmap = 0;
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++) {
u8 cos = qos_in->dscp2cos[i] == DBG_DFLT_DSCP_VAL ?
- nic_dev->wanted_dcb_cfg.dscp2cos[i] : qos_in->dscp2cos[i];
+ dcb->wanted_dcb_cfg.dscp2cos[i] :
+ qos_in->dscp2cos[i];
- if (cos >= NIC_DCB_UP_MAX || !(nic_dev->func_dft_cos_bitmap & BIT(cos))) {
+ if (cos >= NIC_DCB_UP_MAX ||
+ !(dcb->func_dft_cos_bitmap & BIT(cos))) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid cos=%u, func cos valid map is %u",
- cos, nic_dev->func_dft_cos_bitmap);
+ cos, dcb->func_dft_cos_bitmap);
return -EINVAL;
}
@@ -588,8 +664,10 @@ static int update_pcp_dscp_cfg(struct hinic3_nic_dev *nic_dev,
}
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++)
- wanted_dcb_cfg->dscp2cos[i] = qos_in->dscp2cos[i] == DBG_DFLT_DSCP_VAL ?
- nic_dev->hw_dcb_cfg.dscp2cos[i] : qos_in->dscp2cos[i];
+ wanted_dcb_cfg->dscp2cos[i] =
+ qos_in->dscp2cos[i] == DBG_DFLT_DSCP_VAL ?
+ dcb->hw_dcb_cfg.dscp2cos[i] :
+ qos_in->dscp2cos[i];
wanted_dcb_cfg->dscp_user_cos_num = cos_num;
wanted_dcb_cfg->dscp_valid_cos_map = valid_cos_bitmap;
}
@@ -601,11 +679,12 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
struct hinic3_dcb_config *wanted_dcb_cfg,
const struct hinic3_mt_qos_dev_cfg *qos_in)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int ret;
u8 cos_num, valid_cos_bitmap;
if (qos_in->cfg_bitmap & CMD_QOS_DEV_TRUST) {
- if (qos_in->trust > DCB_DSCP) {
+ if (qos_in->trust > HINIC3_DCB_DSCP) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid trust=%u\n", qos_in->trust);
return -EINVAL;
@@ -615,7 +694,7 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
}
if (qos_in->cfg_bitmap & CMD_QOS_DEV_DFT_COS) {
- if (!(BIT(qos_in->dft_cos) & nic_dev->func_dft_cos_bitmap)) {
+ if (!(BIT(qos_in->dft_cos) & dcb->func_dft_cos_bitmap)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Invalid dft_cos=%u\n", qos_in->dft_cos);
return -EINVAL;
@@ -628,7 +707,7 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
if (ret)
return ret;
- if (wanted_dcb_cfg->trust == DCB_PCP) {
+ if (wanted_dcb_cfg->trust == HINIC3_DCB_PCP) {
cos_num = wanted_dcb_cfg->pcp_user_cos_num;
valid_cos_bitmap = wanted_dcb_cfg->pcp_valid_cos_map;
} else {
@@ -636,18 +715,11 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
valid_cos_bitmap = wanted_dcb_cfg->dscp_valid_cos_map;
}
- if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
- if (cos_num > nic_dev->q_params.num_qps) {
- nicif_err(nic_dev, drv, nic_dev->netdev,
- "DCB is on, cos num should not more than channel num:%u\n",
- nic_dev->q_params.num_qps);
- return -EOPNOTSUPP;
- }
- }
-
if (!(BIT(wanted_dcb_cfg->default_cos) & valid_cos_bitmap)) {
- nicif_info(nic_dev, drv, nic_dev->netdev, "Current default_cos=%u, change to %u\n",
- wanted_dcb_cfg->default_cos, (u8)fls(valid_cos_bitmap) - 1);
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "Current default_cos=%u, change to %u\n",
+ wanted_dcb_cfg->default_cos,
+ (u8)fls(valid_cos_bitmap) - 1);
wanted_dcb_cfg->default_cos = (u8)fls(valid_cos_bitmap) - 1;
}
@@ -657,6 +729,7 @@ static int update_wanted_qos_cfg(struct hinic3_nic_dev *nic_dev,
static int dcb_mt_qos_map(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
const struct hinic3_mt_qos_dev_cfg *qos_in = buf_in;
struct hinic3_mt_qos_dev_cfg *qos_out = buf_out;
u8 i;
@@ -675,9 +748,10 @@ static int dcb_mt_qos_map(struct hinic3_nic_dev *nic_dev, const void *buf_in,
memcpy(qos_out, qos_in, sizeof(*qos_in));
qos_out->head.status = 0;
if (qos_in->op_code & MT_DCB_OPCODE_WR) {
- memcpy(&nic_dev->wanted_dcb_cfg, &nic_dev->hw_dcb_cfg,
+ memcpy(&dcb->wanted_dcb_cfg, &dcb->hw_dcb_cfg,
sizeof(struct hinic3_dcb_config));
- err = update_wanted_qos_cfg(nic_dev, &nic_dev->wanted_dcb_cfg, qos_in);
+ err = update_wanted_qos_cfg(nic_dev, &dcb->wanted_dcb_cfg,
+ qos_in);
if (err) {
qos_out->head.status = MT_EINVAL;
return 0;
@@ -687,12 +761,12 @@ static int dcb_mt_qos_map(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (err)
qos_out->head.status = MT_EIO;
} else {
- qos_out->dft_cos = nic_dev->hw_dcb_cfg.default_cos;
- qos_out->trust = nic_dev->hw_dcb_cfg.trust;
+ qos_out->dft_cos = dcb->hw_dcb_cfg.default_cos;
+ qos_out->trust = dcb->hw_dcb_cfg.trust;
for (i = 0; i < NIC_DCB_UP_MAX; i++)
- qos_out->pcp2cos[i] = nic_dev->hw_dcb_cfg.pcp2cos[i];
+ qos_out->pcp2cos[i] = dcb->hw_dcb_cfg.pcp2cos[i];
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++)
- qos_out->dscp2cos[i] = nic_dev->hw_dcb_cfg.dscp2cos[i];
+ qos_out->dscp2cos[i] = dcb->hw_dcb_cfg.dscp2cos[i];
}
return 0;
@@ -721,27 +795,17 @@ static int dcb_mt_dcb_state(struct hinic3_nic_dev *nic_dev, const void *buf_in,
memcpy(dcb_out, dcb_in, sizeof(*dcb_in));
dcb_out->head.status = 0;
if (dcb_in->op_code & MT_DCB_OPCODE_WR) {
- if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) == dcb_in->state)
+ if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ==
+ dcb_in->state)
return 0;
- if (dcb_in->state) {
- if (user_cos_num > nic_dev->q_params.num_qps) {
- nicif_err(nic_dev, drv, nic_dev->netdev,
- "cos num %u should not more than channel num %u\n",
- user_cos_num,
- nic_dev->q_params.num_qps);
-
- return -EOPNOTSUPP;
- }
- }
-
- rtnl_lock();
if (netif_running(nic_dev->netdev)) {
netif_run = 1;
hinic3_vport_down(nic_dev);
}
- err = hinic3_setup_cos(nic_dev->netdev, dcb_in->state ? user_cos_num : 0,
+ err = hinic3_setup_cos(nic_dev->netdev,
+ dcb_in->state ? user_cos_num : 0,
netif_run);
if (err)
goto setup_cos_fail;
@@ -751,7 +815,6 @@ static int dcb_mt_dcb_state(struct hinic3_nic_dev *nic_dev, const void *buf_in,
if (err)
goto vport_up_fail;
}
- rtnl_unlock();
} else {
dcb_out->state = !!test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
}
@@ -759,12 +822,12 @@ static int dcb_mt_dcb_state(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return 0;
vport_up_fail:
- hinic3_setup_cos(nic_dev->netdev, dcb_in->state ? 0 : user_cos_num, netif_run);
+ hinic3_setup_cos(nic_dev->netdev, dcb_in->state ? 0 : user_cos_num,
+ netif_run);
setup_cos_fail:
if (netif_run)
hinic3_vport_up(nic_dev);
- rtnl_unlock();
return err;
}
@@ -772,13 +835,15 @@ setup_cos_fail:
static int dcb_mt_hw_qos_get(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
const struct hinic3_mt_qos_cos_cfg *cos_cfg_in = buf_in;
struct hinic3_mt_qos_cos_cfg *cos_cfg_out = buf_out;
if (!buf_in || !buf_out || !out_size)
return -EINVAL;
- if (*out_size != sizeof(*cos_cfg_out) || in_size != sizeof(*cos_cfg_in)) {
+ if (*out_size != sizeof(*cos_cfg_out) ||
+ in_size != sizeof(*cos_cfg_in)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n",
in_size, *out_size, sizeof(*cos_cfg_in));
@@ -789,9 +854,9 @@ static int dcb_mt_hw_qos_get(struct hinic3_nic_dev *nic_dev, const void *buf_in,
cos_cfg_out->head.status = 0;
cos_cfg_out->port_id = hinic3_physical_port_id(nic_dev->hwdev);
- cos_cfg_out->func_cos_bitmap = (u8)nic_dev->func_dft_cos_bitmap;
- cos_cfg_out->port_cos_bitmap = (u8)nic_dev->port_dft_cos_bitmap;
- cos_cfg_out->func_max_cos_num = nic_dev->cos_config_num_max;
+ cos_cfg_out->func_cos_bitmap = (u8)dcb->func_dft_cos_bitmap;
+ cos_cfg_out->port_cos_bitmap = (u8)dcb->port_dft_cos_bitmap;
+ cos_cfg_out->func_max_cos_num = dcb->cos_config_num_max;
return 0;
}
@@ -803,7 +868,13 @@ static int get_inter_num(struct hinic3_nic_dev *nic_dev, const void *buf_in,
intr_num = hinic3_intr_num(nic_dev->hwdev);
- if (!buf_out || !out_size || *out_size != sizeof(u16)) {
+ if (!buf_out || !out_size) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_out or out_size is NULL.\n");
+ return -EINVAL;
+ }
+
+ if (*out_size != sizeof(u16)) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%u, expect: %lu\n",
*out_size, sizeof(u16));
@@ -817,7 +888,13 @@ static int get_inter_num(struct hinic3_nic_dev *nic_dev, const void *buf_in,
static int get_netdev_name(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
- if (!buf_out || !out_size || *out_size != IFNAMSIZ) {
+ if (!buf_out || !out_size) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Buf_out or out_size is NULL.\n");
+ return -EINVAL;
+ }
+
+ if (*out_size != IFNAMSIZ) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Unexpect out buf size from user :%u, expect: %u\n",
*out_size, IFNAMSIZ);
@@ -829,8 +906,9 @@ static int get_netdev_name(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return 0;
}
-static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf_in,
- u32 in_size, void *buf_out, u32 *out_size)
+static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev,
+ const void *buf_in, u32 in_size,
+ void *buf_out, u32 *out_size)
{
struct net_device *net_dev = nic_dev->netdev;
int *tx_timeout = buf_out;
@@ -839,7 +917,8 @@ static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf
return -EINVAL;
if (*out_size != sizeof(int)) {
- nicif_err(nic_dev, drv, net_dev, "Unexpect buf size from user, out_size: %u, expect: %lu\n",
+ nicif_err(nic_dev, drv, net_dev,
+ "Unexpect buf size from user, out_size: %u, expect: %lu\n",
*out_size, sizeof(int));
return -EINVAL;
}
@@ -849,8 +928,9 @@ static int get_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf
return 0;
}
-static int set_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf_in,
- u32 in_size, void *buf_out, u32 *out_size)
+static int set_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev,
+ const void *buf_in, u32 in_size,
+ void *buf_out, u32 *out_size)
{
struct net_device *net_dev = nic_dev->netdev;
const int *tx_timeout = buf_in;
@@ -859,13 +939,15 @@ static int set_netdev_tx_timeout(struct hinic3_nic_dev *nic_dev, const void *buf
return -EINVAL;
if (in_size != sizeof(int)) {
- nicif_err(nic_dev, drv, net_dev, "Unexpect buf size from user, in_size: %u, expect: %lu\n",
+ nicif_err(nic_dev, drv, net_dev,
+ "Unexpect buf size from user, in_size: %u, expect: %lu\n",
in_size, sizeof(int));
return -EINVAL;
}
net_dev->watchdog_timeo = *tx_timeout * HZ;
- nicif_info(nic_dev, drv, net_dev, "Set tx timeout check period to %ds\n", *tx_timeout);
+ nicif_info(nic_dev, drv, net_dev,
+ "Set tx timeout check period to %ds\n", *tx_timeout);
return 0;
}
@@ -891,6 +973,34 @@ static int get_xsfp_present(struct hinic3_nic_dev *nic_dev, const void *buf_in,
return 0;
}
+static int get_xsfp_tlv_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp *sfp_tlv_info = buf_out;
+ const struct tag_mag_cmd_get_xsfp_tlv_req *sfp_tlv_info_req = buf_in;
+ int err;
+
+ if (!buf_in || !buf_out || !out_size)
+ return -EINVAL;
+
+ if (*out_size != sizeof(*sfp_tlv_info) ||
+ in_size != sizeof(*sfp_tlv_info_req)) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Unexpect buf size from user, in_size: %u, out_size: %u, expect: %lu\n",
+ in_size, *out_size, sizeof(*sfp_tlv_info));
+ return -EINVAL;
+ }
+
+ err = hinic3_get_sfp_tlv_info(nic_dev->hwdev,
+ sfp_tlv_info, sfp_tlv_info_req);
+ if (err != 0) {
+ sfp_tlv_info->head.status = MT_EIO;
+ return 0;
+ }
+
+ return 0;
+}
+
static int get_xsfp_info(struct hinic3_nic_dev *nic_dev, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
@@ -928,7 +1038,7 @@ static const struct nic_drv_module_handle nic_driv_module_cmd_handle[] = {
{GET_LOOPBACK_MODE, get_loopback_mode},
{SET_LOOPBACK_MODE, set_loopback_mode},
{SET_LINK_MODE, set_link_mode},
- {SET_PF_BW_LIMIT, set_pf_bw_limit},
+ {SET_TX_PF_BW_LIMIT, set_pf_bw_limit},
{GET_PF_BW_LIMIT, get_pf_bw_limit},
{GET_SSET_COUNT, get_sset_count},
{GET_SSET_ITEMS, get_sset_stats},
@@ -940,17 +1050,22 @@ static const struct nic_drv_module_handle nic_driv_module_cmd_handle[] = {
{SET_TX_TIMEOUT, set_netdev_tx_timeout},
{GET_XSFP_PRESENT, get_xsfp_present},
{GET_XSFP_INFO, get_xsfp_info},
+ {GET_XSFP_INFO_COMP_CMIS, get_xsfp_tlv_info},
+ {SET_RX_PF_BW_LIMIT, set_rx_pf_bw_limit}
};
static int send_to_nic_driver(struct hinic3_nic_dev *nic_dev,
u32 cmd, const void *buf_in,
u32 in_size, void *buf_out, u32 *out_size)
{
- int index, num_cmds = sizeof(nic_driv_module_cmd_handle) /
- sizeof(nic_driv_module_cmd_handle[0]);
+ int index, num_cmds = (int)(sizeof(nic_driv_module_cmd_handle) /
+ sizeof(nic_driv_module_cmd_handle[0]));
enum driver_cmd_type cmd_type = (enum driver_cmd_type)cmd;
int err = 0;
+ if (cmd_type == DCB_STATE || cmd_type == QOS_DEV)
+ rtnl_lock();
+
mutex_lock(&nic_dev->nic_mutex);
for (index = 0; index < num_cmds; index++) {
if (cmd_type ==
@@ -963,6 +1078,9 @@ static int send_to_nic_driver(struct hinic3_nic_dev *nic_dev,
}
mutex_unlock(&nic_dev->nic_mutex);
+ if (cmd_type == DCB_STATE || cmd_type == QOS_DEV)
+ rtnl_unlock();
+
if (index == num_cmds) {
pr_err("Can't find callback for %d\n", cmd_type);
return -EINVAL;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c
index a1fb4af..603a2ab 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.c
@@ -24,82 +24,80 @@
u8 hinic3_get_dev_user_cos_num(struct hinic3_nic_dev *nic_dev)
{
- if (nic_dev->hw_dcb_cfg.trust == 0)
- return nic_dev->hw_dcb_cfg.pcp_user_cos_num;
- if (nic_dev->hw_dcb_cfg.trust == 1)
- return nic_dev->hw_dcb_cfg.dscp_user_cos_num;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_PCP)
+ return dcb->hw_dcb_cfg.pcp_user_cos_num;
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_DSCP)
+ return dcb->hw_dcb_cfg.dscp_user_cos_num;
return 0;
}
u8 hinic3_get_dev_valid_cos_map(struct hinic3_nic_dev *nic_dev)
{
- if (nic_dev->hw_dcb_cfg.trust == 0)
- return nic_dev->hw_dcb_cfg.pcp_valid_cos_map;
- if (nic_dev->hw_dcb_cfg.trust == 1)
- return nic_dev->hw_dcb_cfg.dscp_valid_cos_map;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_PCP)
+ return dcb->hw_dcb_cfg.pcp_valid_cos_map;
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_DSCP)
+ return dcb->hw_dcb_cfg.dscp_valid_cos_map;
return 0;
}
void hinic3_update_qp_cos_cfg(struct hinic3_nic_dev *nic_dev, u8 num_cos)
{
- struct hinic3_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg;
- u8 i, remainder, num_sq_per_cos, cur_cos_num = 0;
+ struct hinic3_dcb_config *hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
+ struct hinic3_dcb_config *wanted_dcb_cfg =
+ &nic_dev->dcb->wanted_dcb_cfg;
u8 valid_cos_map = hinic3_get_dev_valid_cos_map(nic_dev);
+ u8 cos_qp_num, cos_qp_offset = 0;
+ u8 i, remainder, num_qp_per_cos;
- if (num_cos == 0)
- return;
-
- num_sq_per_cos = (u8)(nic_dev->q_params.num_qps / num_cos);
- if (num_sq_per_cos == 0)
+ if (num_cos == 0 || nic_dev->q_params.num_qps == 0)
return;
- remainder = nic_dev->q_params.num_qps % num_sq_per_cos;
+ num_qp_per_cos = (u8)(nic_dev->q_params.num_qps / num_cos);
+ remainder = nic_dev->q_params.num_qps % num_cos;
- memset(dcb_cfg->cos_qp_offset, 0, sizeof(dcb_cfg->cos_qp_offset));
- memset(dcb_cfg->cos_qp_num, 0, sizeof(dcb_cfg->cos_qp_num));
+ memset(hw_dcb_cfg->cos_qp_offset, 0, sizeof(hw_dcb_cfg->cos_qp_offset));
+ memset(hw_dcb_cfg->cos_qp_num, 0, sizeof(hw_dcb_cfg->cos_qp_num));
for (i = 0; i < PCP_MAX_UP; i++) {
if (BIT(i) & valid_cos_map) {
- u8 cos_qp_num = num_sq_per_cos;
- u8 cos_qp_offset = (u8)(cur_cos_num * num_sq_per_cos);
-
- if (cur_cos_num < remainder) {
- cos_qp_num++;
- cos_qp_offset += cur_cos_num;
- } else {
- cos_qp_offset += remainder;
- }
-
- cur_cos_num++;
- valid_cos_map -= (u8)BIT(i);
+ cos_qp_num = num_qp_per_cos + ((remainder > 0) ?
+ (remainder--, 1) : 0);
- dcb_cfg->cos_qp_offset[i] = cos_qp_offset;
- dcb_cfg->cos_qp_num[i] = cos_qp_num;
+ hw_dcb_cfg->cos_qp_offset[i] = cos_qp_offset;
+ hw_dcb_cfg->cos_qp_num[i] = cos_qp_num;
hinic3_info(nic_dev, drv, "cos %u, cos_qp_offset=%u cos_qp_num=%u\n",
i, cos_qp_offset, cos_qp_num);
+
+ cos_qp_offset += cos_qp_num;
+ valid_cos_map -= (u8)BIT(i);
}
}
- memcpy(nic_dev->wanted_dcb_cfg.cos_qp_offset, dcb_cfg->cos_qp_offset,
- sizeof(dcb_cfg->cos_qp_offset));
- memcpy(nic_dev->wanted_dcb_cfg.cos_qp_num, dcb_cfg->cos_qp_num,
- sizeof(dcb_cfg->cos_qp_num));
+ memcpy(wanted_dcb_cfg->cos_qp_offset, hw_dcb_cfg->cos_qp_offset,
+ sizeof(hw_dcb_cfg->cos_qp_offset));
+ memcpy(wanted_dcb_cfg->cos_qp_num, hw_dcb_cfg->cos_qp_num,
+ sizeof(hw_dcb_cfg->cos_qp_num));
}
void hinic3_update_tx_db_cos(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
{
+ struct hinic3_dcb_config *hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
u8 i;
u16 start_qid, q_num;
hinic3_set_txq_cos(nic_dev, 0, nic_dev->q_params.num_qps,
- nic_dev->hw_dcb_cfg.default_cos);
+ hw_dcb_cfg->default_cos);
if (!dcb_en)
return;
for (i = 0; i < NIC_DCB_COS_MAX; i++) {
- q_num = (u16)nic_dev->hw_dcb_cfg.cos_qp_num[i];
+ q_num = (u16)hw_dcb_cfg->cos_qp_num[i];
if (q_num) {
- start_qid = (u16)nic_dev->hw_dcb_cfg.cos_qp_offset[i];
+ start_qid = (u16)hw_dcb_cfg->cos_qp_offset[i];
hinic3_set_txq_cos(nic_dev, start_qid, q_num, i);
hinic3_info(nic_dev, drv, "update tx db cos, start_qid %u, q_num=%u cos=%u\n",
@@ -110,30 +108,28 @@ void hinic3_update_tx_db_cos(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
static int hinic3_set_tx_cos_state(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
{
- struct hinic3_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+ struct hinic3_dcb_config *hw_dcb_cfg = &dcb->hw_dcb_cfg;
struct hinic3_dcb_state dcb_state = {0};
u8 i;
int err;
-
- if (HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- /* VF does not support DCB, use the default cos */
- dcb_cfg->default_cos = (u8)fls(nic_dev->func_dft_cos_bitmap) - 1;
-
- return 0;
- }
+ u32 pcp2cos_size = sizeof(dcb_state.pcp2cos);
+ u32 dscp2cos_size = sizeof(dcb_state.dscp2cos);
dcb_state.dcb_on = dcb_en;
- dcb_state.default_cos = dcb_cfg->default_cos;
- dcb_state.trust = dcb_cfg->trust;
+ dcb_state.default_cos = hw_dcb_cfg->default_cos;
+ dcb_state.trust = hw_dcb_cfg->trust;
if (dcb_en) {
for (i = 0; i < NIC_DCB_COS_MAX; i++)
- dcb_state.pcp2cos[i] = dcb_cfg->pcp2cos[i];
+ dcb_state.pcp2cos[i] = hw_dcb_cfg->pcp2cos[i];
for (i = 0; i < NIC_DCB_IP_PRI_MAX; i++)
- dcb_state.dscp2cos[i] = dcb_cfg->dscp2cos[i];
+ dcb_state.dscp2cos[i] = hw_dcb_cfg->dscp2cos[i];
} else {
- memset(dcb_state.pcp2cos, dcb_cfg->default_cos, sizeof(dcb_state.pcp2cos));
- memset(dcb_state.dscp2cos, dcb_cfg->default_cos, sizeof(dcb_state.dscp2cos));
+ memset(dcb_state.pcp2cos, hw_dcb_cfg->default_cos,
+ pcp2cos_size);
+ memset(dcb_state.dscp2cos, hw_dcb_cfg->default_cos,
+ dscp2cos_size);
}
err = hinic3_set_dcb_state(nic_dev->hwdev, &dcb_state);
@@ -143,7 +139,7 @@ static int hinic3_set_tx_cos_state(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
return err;
}
-static int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
+int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
{
int err;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
@@ -169,11 +165,13 @@ static int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en)
goto rx_configure_fail;
}
- if (dcb_en)
+ if (dcb_en) {
set_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
- else
+ set_bit(HINIC3_DCB_ENABLE, &nic_dev->nic_vram->flags);
+ } else {
clear_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
-
+ clear_bit(HINIC3_DCB_ENABLE, &nic_dev->nic_vram->flags);
+ }
return 0;
rx_configure_fail:
hinic3_set_tx_cos_state(nic_dev, dcb_en ? 0 : 1);
@@ -188,6 +186,7 @@ set_tx_cos_fail:
int hinic3_setup_cos(struct net_device *netdev, u8 cos, u8 netif_run)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int err;
if (cos && test_bit(HINIC3_SAME_RXTX, &nic_dev->flags)) {
@@ -195,9 +194,10 @@ int hinic3_setup_cos(struct net_device *netdev, u8 cos, u8 netif_run)
return -EOPNOTSUPP;
}
- if (cos > nic_dev->cos_config_num_max) {
- nicif_err(nic_dev, drv, netdev, "Invalid num_tc: %u, max cos: %u\n",
- cos, nic_dev->cos_config_num_max);
+ if (cos > dcb->cos_config_num_max) {
+ nicif_err(nic_dev, drv, netdev,
+ "Invalid num_tc: %u, max cos: %u\n",
+ cos, dcb->cos_config_num_max);
return -EINVAL;
}
@@ -223,36 +223,48 @@ static u8 get_cos_num(u8 hw_valid_cos_bitmap)
static void hinic3_sync_dcb_cfg(struct hinic3_nic_dev *nic_dev,
const struct hinic3_dcb_config *dcb_cfg)
{
- struct hinic3_dcb_config *hw_cfg = &nic_dev->hw_dcb_cfg;
+ struct hinic3_dcb_config *hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
- memcpy(hw_cfg, dcb_cfg, sizeof(struct hinic3_dcb_config));
+ memcpy(hw_dcb_cfg, dcb_cfg, sizeof(struct hinic3_dcb_config));
}
static int init_default_dcb_cfg(struct hinic3_nic_dev *nic_dev,
struct hinic3_dcb_config *dcb_cfg)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u8 i, hw_dft_cos_map, port_cos_bitmap, dscp_ind;
int err;
+ int is_in_kexec;
- err = hinic3_cos_valid_bitmap(nic_dev->hwdev, &hw_dft_cos_map, &port_cos_bitmap);
+ err = hinic3_cos_valid_bitmap(nic_dev->hwdev,
+ &hw_dft_cos_map, &port_cos_bitmap);
if (err) {
hinic3_err(nic_dev, drv, "None cos supported\n");
return -EFAULT;
}
- nic_dev->func_dft_cos_bitmap = hw_dft_cos_map;
- nic_dev->port_dft_cos_bitmap = port_cos_bitmap;
- nic_dev->cos_config_num_max = get_cos_num(hw_dft_cos_map);
+ is_in_kexec = vram_get_kexec_flag();
- dcb_cfg->trust = DCB_PCP;
- dcb_cfg->pcp_user_cos_num = nic_dev->cos_config_num_max;
- dcb_cfg->dscp_user_cos_num = nic_dev->cos_config_num_max;
- dcb_cfg->default_cos = (u8)fls(nic_dev->func_dft_cos_bitmap) - 1;
+ dcb->func_dft_cos_bitmap = hw_dft_cos_map;
+ dcb->port_dft_cos_bitmap = port_cos_bitmap;
+
+ dcb->cos_config_num_max = get_cos_num(hw_dft_cos_map);
+
+ if (is_in_kexec == 0) {
+ dcb_cfg->trust = HINIC3_DCB_PCP;
+ dcb_cfg->default_cos = (u8)fls(dcb->func_dft_cos_bitmap) - 1;
+ } else {
+ dcb_cfg->trust = nic_dev->dcb->hw_dcb_cfg.trust;
+ dcb_cfg->default_cos = nic_dev->dcb->hw_dcb_cfg.default_cos;
+ }
+ dcb_cfg->pcp_user_cos_num = dcb->cos_config_num_max;
+ dcb_cfg->dscp_user_cos_num = dcb->cos_config_num_max;
dcb_cfg->pcp_valid_cos_map = hw_dft_cos_map;
dcb_cfg->dscp_valid_cos_map = hw_dft_cos_map;
for (i = 0; i < NIC_DCB_COS_MAX; i++) {
- dcb_cfg->pcp2cos[i] = hw_dft_cos_map & BIT(i) ? i : dcb_cfg->default_cos;
+ dcb_cfg->pcp2cos[i] = hw_dft_cos_map & BIT(i) ?
+ i : (u8)fls(dcb->func_dft_cos_bitmap) - 1;
for (dscp_ind = 0; dscp_ind < NIC_DCB_COS_MAX; dscp_ind++)
dcb_cfg->dscp2cos[i * NIC_DCB_DSCP_NUM + dscp_ind] = dcb_cfg->pcp2cos[i];
}
@@ -276,58 +288,115 @@ int hinic3_configure_dcb(struct net_device *netdev)
int err;
err = hinic3_sync_dcb_state(nic_dev->hwdev, 1,
- test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ? 1 : 0);
+ test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)
+ ? 1 : 0);
if (err) {
hinic3_err(nic_dev, drv, "Set dcb state failed\n");
return err;
}
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
- hinic3_sync_dcb_cfg(nic_dev, &nic_dev->wanted_dcb_cfg);
+ hinic3_sync_dcb_cfg(nic_dev, &nic_dev->dcb->wanted_dcb_cfg);
else
hinic3_dcb_reset_hw_config(nic_dev);
return 0;
}
+static int hinic3_dcb_alloc(struct hinic3_nic_dev *nic_dev)
+{
+ u16 func_id;
+ int is_use_vram;
+
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram) {
+ func_id = hinic3_global_func_id(nic_dev->hwdev);
+ snprintf(nic_dev->dcb_name, VRAM_NAME_MAX_LEN,
+ "%s%hu%s", VRAM_CQM_GLB_FUNC_BASE, func_id,
+ VRAM_NIC_DCB);
+
+ nic_dev->dcb = (struct hinic3_dcb *)hi_vram_kalloc(nic_dev->dcb_name,
+ sizeof(*nic_dev->dcb));
+ if (!nic_dev->dcb) {
+ hinic3_err(nic_dev, drv, "Failed to vram alloc dcb.\n");
+ return -EFAULT;
+ }
+ } else {
+ nic_dev->dcb = kzalloc(sizeof(*nic_dev->dcb), GFP_KERNEL);
+ if (!nic_dev->dcb)
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static void hinic3_dcb_free(struct hinic3_nic_dev *nic_dev)
+{
+ int is_use_vram;
+
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram)
+ hi_vram_kfree((void *)nic_dev->dcb, nic_dev->dcb_name,
+ sizeof(*nic_dev->dcb));
+ else
+ kfree(nic_dev->dcb);
+ nic_dev->dcb = NULL;
+}
+
+void hinic3_dcb_deinit(struct hinic3_nic_dev *nic_dev)
+{
+ if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
+ hinic3_sync_dcb_state(nic_dev->hwdev, 1, 0);
+
+ hinic3_dcb_free(nic_dev);
+}
+
int hinic3_dcb_init(struct hinic3_nic_dev *nic_dev)
{
- struct hinic3_dcb_config *dcb_cfg = &nic_dev->hw_dcb_cfg;
+ struct hinic3_dcb_config *hw_dcb_cfg = NULL;
int err;
u8 dcb_en = test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ? 1 : 0;
- if (HINIC3_FUNC_IS_VF(nic_dev->hwdev))
- return hinic3_set_tx_cos_state(nic_dev, dcb_en);
+ err = hinic3_dcb_alloc(nic_dev);
+ if (err != 0) {
+ hinic3_err(nic_dev, drv, "Dcb alloc failed.\n");
+ return err;
+ }
- err = init_default_dcb_cfg(nic_dev, dcb_cfg);
+ hw_dcb_cfg = &nic_dev->dcb->hw_dcb_cfg;
+ err = init_default_dcb_cfg(nic_dev, hw_dcb_cfg);
if (err) {
- hinic3_err(nic_dev, drv, "Initialize dcb configuration failed\n");
+ hinic3_err(nic_dev, drv,
+ "Initialize dcb configuration failed\n");
+ hinic3_dcb_free(nic_dev);
return err;
}
- memcpy(&nic_dev->wanted_dcb_cfg, &nic_dev->hw_dcb_cfg, sizeof(struct hinic3_dcb_config));
+ memcpy(&nic_dev->dcb->wanted_dcb_cfg, hw_dcb_cfg,
+ sizeof(struct hinic3_dcb_config));
hinic3_info(nic_dev, drv, "Support num cos %u, default cos %u\n",
- nic_dev->cos_config_num_max, dcb_cfg->default_cos);
+ nic_dev->dcb->cos_config_num_max, hw_dcb_cfg->default_cos);
err = hinic3_set_tx_cos_state(nic_dev, dcb_en);
if (err) {
hinic3_err(nic_dev, drv, "Set tx cos state failed\n");
+ hinic3_dcb_free(nic_dev);
return err;
}
- sema_init(&nic_dev->dcb_sem, 1);
-
return 0;
}
-static int change_qos_cfg(struct hinic3_nic_dev *nic_dev, const struct hinic3_dcb_config *dcb_cfg)
+static int change_qos_cfg(struct hinic3_nic_dev *nic_dev,
+ const struct hinic3_dcb_config *dcb_cfg)
{
struct net_device *netdev = nic_dev->netdev;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int err = 0;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
- if (test_and_set_bit(HINIC3_DCB_UP_COS_SETTING, &nic_dev->dcb_flags)) {
+ if (test_and_set_bit(HINIC3_DCB_UP_COS_SETTING, &dcb->dcb_flags)) {
nicif_warn(nic_dev, drv, netdev,
"Cos_up map setting in inprocess, please try again later\n");
return -EFAULT;
@@ -337,40 +406,44 @@ static int change_qos_cfg(struct hinic3_nic_dev *nic_dev, const struct hinic3_dc
hinic3_update_qp_cos_cfg(nic_dev, user_cos_num);
- clear_bit(HINIC3_DCB_UP_COS_SETTING, &nic_dev->dcb_flags);
+ clear_bit(HINIC3_DCB_UP_COS_SETTING, &dcb->dcb_flags);
return err;
}
int hinic3_dcbcfg_set_up_bitmap(struct hinic3_nic_dev *nic_dev)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int err, rollback_err;
u8 netif_run = 0;
struct hinic3_dcb_config old_dcb_cfg;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
- memcpy(&old_dcb_cfg, &nic_dev->hw_dcb_cfg, sizeof(struct hinic3_dcb_config));
+ memcpy(&old_dcb_cfg, &dcb->hw_dcb_cfg,
+ sizeof(struct hinic3_dcb_config));
- if (!memcmp(&nic_dev->wanted_dcb_cfg, &old_dcb_cfg, sizeof(struct hinic3_dcb_config))) {
+ if (!memcmp(&dcb->wanted_dcb_cfg, &old_dcb_cfg,
+ sizeof(struct hinic3_dcb_config))) {
nicif_info(nic_dev, drv, nic_dev->netdev,
"Same valid up bitmap, don't need to change anything\n");
return 0;
}
- rtnl_lock();
if (netif_running(nic_dev->netdev)) {
netif_run = 1;
hinic3_vport_down(nic_dev);
}
- err = change_qos_cfg(nic_dev, &nic_dev->wanted_dcb_cfg);
+ err = change_qos_cfg(nic_dev, &dcb->wanted_dcb_cfg);
if (err) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Set cos_up map to hw failed\n");
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Set cos_up map to hw failed\n");
goto change_qos_cfg_fail;
}
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
- err = hinic3_setup_cos(nic_dev->netdev, user_cos_num, netif_run);
+ err = hinic3_setup_cos(nic_dev->netdev,
+ user_cos_num, netif_run);
if (err)
goto set_err;
}
@@ -381,13 +454,12 @@ int hinic3_dcbcfg_set_up_bitmap(struct hinic3_nic_dev *nic_dev)
goto vport_up_fail;
}
- rtnl_unlock();
-
return 0;
vport_up_fail:
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
- hinic3_setup_cos(nic_dev->netdev, user_cos_num ? 0 : user_cos_num, netif_run);
+ hinic3_setup_cos(nic_dev->netdev, user_cos_num
+ ? 0 : user_cos_num, netif_run);
set_err:
rollback_err = change_qos_cfg(nic_dev, &old_dcb_cfg);
@@ -399,7 +471,5 @@ change_qos_cfg_fail:
if (netif_run)
hinic3_vport_up(nic_dev);
- rtnl_unlock();
-
return err;
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h
index 7987f56..e0b35cb 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_dcb.h
@@ -24,11 +24,6 @@ struct hinic3_tc_cfg {
u16 rsvd;
};
-enum HINIC3_DCB_TRUST {
- DCB_PCP,
- DCB_DSCP,
-};
-
#define PCP_MAX_UP 8
#define DSCP_MAC_UP 64
#define DBG_DFLT_DSCP_VAL 0xFF
@@ -50,6 +45,7 @@ struct hinic3_dcb_config {
u8 hinic3_get_dev_user_cos_num(struct hinic3_nic_dev *nic_dev);
u8 hinic3_get_dev_valid_cos_map(struct hinic3_nic_dev *nic_dev);
int hinic3_dcb_init(struct hinic3_nic_dev *nic_dev);
+void hinic3_dcb_deinit(struct hinic3_nic_dev *nic_dev);
void hinic3_dcb_reset_hw_config(struct hinic3_nic_dev *nic_dev);
int hinic3_configure_dcb(struct net_device *netdev);
int hinic3_setup_cos(struct net_device *netdev, u8 cos, u8 netif_run);
@@ -75,4 +71,5 @@ void hinic3_update_tx_db_cos(struct hinic3_nic_dev *nic_dev, u8 dcb_en);
void hinic3_update_qp_cos_cfg(struct hinic3_nic_dev *nic_dev, u8 num_cos);
void hinic3_vport_down(struct hinic3_nic_dev *nic_dev);
int hinic3_vport_up(struct hinic3_nic_dev *nic_dev);
+int hinic3_configure_dcb_hw(struct hinic3_nic_dev *nic_dev, u8 dcb_en);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
index 5a19959..e5e5578 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool.c
@@ -56,9 +56,8 @@ static void hinic3_get_drvinfo(struct net_device *netdev,
return;
}
- err = snprintf(info->fw_version, sizeof(info->fw_version), "%s", mgmt_ver);
- if (err < 0)
- nicif_err(nic_dev, drv, netdev, "Failed to snprintf fw version\n");
+ snprintf(info->fw_version, sizeof(info->fw_version),
+ "%s", mgmt_ver);
}
static u32 hinic3_get_msglevel(struct net_device *netdev)
@@ -86,7 +85,8 @@ static int hinic3_nway_reset(struct net_device *netdev)
while (test_and_set_bit(HINIC3_AUTONEG_RESET, &nic_dev->flags))
msleep(100); /* sleep 100 ms, waiting for another autoneg restart progress done */
- err = hinic3_get_port_info(nic_dev->hwdev, &port_info, HINIC3_CHANNEL_NIC);
+ err = hinic3_get_port_info(nic_dev->hwdev, &port_info,
+ HINIC3_CHANNEL_NIC);
if (err) {
nicif_err(nic_dev, drv, netdev, "Get port info failed\n");
err = -EFAULT;
@@ -273,7 +273,7 @@ static int get_coalesce(struct net_device *netdev,
static int set_queue_coalesce(struct hinic3_nic_dev *nic_dev, u16 q_id,
struct hinic3_intr_coal_info *coal)
{
- struct hinic3_intr_coal_info *intr_coal;
+ struct hinic3_intr_coal_info *intr_coal = NULL;
struct interrupt_info info = {0};
struct net_device *netdev = nic_dev->netdev;
int err;
@@ -367,24 +367,11 @@ static int is_coalesce_exceed_limit(struct net_device *netdev,
return 0;
}
-static int is_coalesce_legal(struct net_device *netdev,
- const struct ethtool_coalesce *coal)
+static int is_coalesce_allowed_change(struct net_device *netdev,
+ const struct ethtool_coalesce *coal)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
struct ethtool_coalesce tmp_coal = {0};
- int err;
-
- if (coal->rx_coalesce_usecs != coal->tx_coalesce_usecs) {
- nicif_err(nic_dev, drv, netdev,
- "tx-usecs must be equal to rx-usecs\n");
- return -EINVAL;
- }
-
- if (coal->rx_max_coalesced_frames != coal->tx_max_coalesced_frames) {
- nicif_err(nic_dev, drv, netdev,
- "tx-frames must be equal to rx-frames\n");
- return -EINVAL;
- }
tmp_coal.cmd = coal->cmd;
tmp_coal.rx_coalesce_usecs = coal->rx_coalesce_usecs;
@@ -409,6 +396,31 @@ static int is_coalesce_legal(struct net_device *netdev,
return -EOPNOTSUPP;
}
+ return 0;
+}
+
+static int is_coalesce_legal(struct net_device *netdev,
+ const struct ethtool_coalesce *coal)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ int err;
+
+ if (coal->rx_coalesce_usecs != coal->tx_coalesce_usecs) {
+ nicif_err(nic_dev, drv, netdev,
+ "tx-usecs must be equal to rx-usecs\n");
+ return -EINVAL;
+ }
+
+ if (coal->rx_max_coalesced_frames != coal->tx_max_coalesced_frames) {
+ nicif_err(nic_dev, drv, netdev,
+ "tx-frames must be equal to rx-frames\n");
+ return -EINVAL;
+ }
+
+ err = is_coalesce_allowed_change(netdev, coal);
+ if (err)
+ return err;
+
err = is_coalesce_exceed_limit(netdev, coal);
if (err)
return err;
@@ -444,8 +456,9 @@ static int is_coalesce_legal(struct net_device *netdev,
return 0;
}
-static inline void check_coalesce_align(struct hinic3_nic_dev *nic_dev, struct net_device *netdev,
- u32 item, u32 unit, char *str)
+static inline void check_coalesce_aligned(struct hinic3_nic_dev *nic_dev,
+ struct net_device *netdev,
+ u32 item, u32 unit, char *str)
{
if (item % unit)
nicif_warn(nic_dev, drv, netdev, "%s in %d units, change to %u\n",
@@ -453,10 +466,12 @@ static inline void check_coalesce_align(struct hinic3_nic_dev *nic_dev, struct n
}
#define CHECK_COALESCE_ALIGN(member, unit) \
- check_coalesce_align(nic_dev, netdev, member, unit, #member)
+ check_coalesce_aligned(nic_dev, netdev, member, unit, #member)
-static inline void check_coalesce_changed(struct hinic3_nic_dev *nic_dev, struct net_device *netdev,
- u32 item, u32 unit, u32 ori_val, char *obj_str, char *str)
+static inline void check_coalesce_changed(struct hinic3_nic_dev *nic_dev,
+ struct net_device *netdev,
+ u32 item, u32 unit, u32 ori_val,
+ char *obj_str, char *str)
{
if ((item / unit) != ori_val)
nicif_info(nic_dev, drv, netdev, "Change %s from %d to %u %s\n",
@@ -466,8 +481,10 @@ static inline void check_coalesce_changed(struct hinic3_nic_dev *nic_dev, struct
#define CHECK_COALESCE_CHANGED(member, unit, ori_val, obj_str) \
check_coalesce_changed(nic_dev, netdev, member, unit, ori_val, obj_str, #member)
-static inline void check_pkt_rate_changed(struct hinic3_nic_dev *nic_dev, struct net_device *netdev,
- u32 item, u32 ori_val, char *obj_str, char *str)
+static inline void check_pkt_rate_changed(struct hinic3_nic_dev *nic_dev,
+ struct net_device *netdev,
+ u32 item, u32 ori_val, char *obj_str,
+ char *str)
{
if (item != ori_val)
nicif_info(nic_dev, drv, netdev, "Change %s from %d to %u %s\n",
@@ -497,19 +514,10 @@ static int set_hw_coal_param(struct hinic3_nic_dev *nic_dev,
return 0;
}
-static int set_coalesce(struct net_device *netdev,
- struct ethtool_coalesce *coal, u16 queue)
+static void check_coalesce_align(struct net_device *netdev,
+ struct ethtool_coalesce *coal)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
- struct hinic3_intr_coal_info intr_coal = {0};
- struct hinic3_intr_coal_info *ori_intr_coal = NULL;
- u32 last_adaptive_rx;
- char obj_str[32] = {0};
- int err = 0;
-
- err = is_coalesce_legal(netdev, coal);
- if (err)
- return err;
CHECK_COALESCE_ALIGN(coal->rx_coalesce_usecs, COALESCE_TIMER_CFG_UNIT);
CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames,
@@ -522,6 +530,14 @@ static int set_coalesce(struct net_device *netdev,
COALESCE_TIMER_CFG_UNIT);
CHECK_COALESCE_ALIGN(coal->rx_max_coalesced_frames_low,
COALESCE_PENDING_LIMIT_UNIT);
+}
+
+static int check_coalesce_change(struct net_device *netdev,
+ u16 queue, struct ethtool_coalesce *coal)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_intr_coal_info *ori_intr_coal = NULL;
+ char obj_str[32] = {0};
if (queue == COALESCE_ALL_QUEUE) {
ori_intr_coal = &nic_dev->intr_coalesce[0];
@@ -552,27 +568,54 @@ static int set_coalesce(struct net_device *netdev,
COALESCE_PENDING_LIMIT_UNIT,
ori_intr_coal->rx_pending_limt_low, obj_str);
- intr_coal.coalesce_timer_cfg =
+ return 0;
+}
+
+static void init_intr_coal_params(struct hinic3_intr_coal_info *intr_coal,
+ struct ethtool_coalesce *coal)
+{
+ intr_coal->coalesce_timer_cfg =
(u8)(coal->rx_coalesce_usecs / COALESCE_TIMER_CFG_UNIT);
- intr_coal.pending_limt = (u8)(coal->rx_max_coalesced_frames /
+ intr_coal->pending_limt = (u8)(coal->rx_max_coalesced_frames /
COALESCE_PENDING_LIMIT_UNIT);
- last_adaptive_rx = nic_dev->adaptive_rx_coal;
- nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
-
- intr_coal.pkt_rate_high = coal->pkt_rate_high;
- intr_coal.rx_usecs_high =
+ intr_coal->pkt_rate_high = coal->pkt_rate_high;
+ intr_coal->rx_usecs_high =
(u8)(coal->rx_coalesce_usecs_high / COALESCE_TIMER_CFG_UNIT);
- intr_coal.rx_pending_limt_high =
+ intr_coal->rx_pending_limt_high =
(u8)(coal->rx_max_coalesced_frames_high /
COALESCE_PENDING_LIMIT_UNIT);
- intr_coal.pkt_rate_low = coal->pkt_rate_low;
- intr_coal.rx_usecs_low =
+ intr_coal->pkt_rate_low = coal->pkt_rate_low;
+ intr_coal->rx_usecs_low =
(u8)(coal->rx_coalesce_usecs_low / COALESCE_TIMER_CFG_UNIT);
- intr_coal.rx_pending_limt_low =
+ intr_coal->rx_pending_limt_low =
(u8)(coal->rx_max_coalesced_frames_low /
COALESCE_PENDING_LIMIT_UNIT);
+}
+
+static int set_coalesce(struct net_device *netdev,
+ struct ethtool_coalesce *coal, u16 queue)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_intr_coal_info intr_coal = {0};
+ u32 last_adaptive_rx;
+ int err = 0;
+
+ err = is_coalesce_legal(netdev, coal);
+ if (err)
+ return err;
+
+ check_coalesce_align(netdev, coal);
+
+ err = check_coalesce_change(netdev, queue, coal);
+ if (err)
+ return err;
+
+ init_intr_coal_params(&intr_coal, coal);
+
+ last_adaptive_rx = nic_dev->adaptive_rx_coal;
+ nic_dev->adaptive_rx_coal = coal->use_adaptive_rx_coalesce;
/* coalesce timer or pending set to zero will disable coalesce */
if (!nic_dev->adaptive_rx_coal &&
@@ -709,14 +752,16 @@ static int hinic3_set_pauseparam(struct net_device *netdev,
return -EFAULT;
}
- auto_neg = port_info.autoneg_state == PORT_CFG_AN_ON ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+ auto_neg = port_info.autoneg_state == PORT_CFG_AN_ON ?
+ AUTONEG_ENABLE : AUTONEG_DISABLE;
if (pause->autoneg != auto_neg) {
nicif_err(nic_dev, drv, netdev,
"To change autoneg please use: ethtool -s <dev> autoneg <on|off>\n");
return -EOPNOTSUPP;
}
- nic_pause.auto_neg = pause->autoneg == AUTONEG_ENABLE ? PORT_CFG_AN_ON : PORT_CFG_AN_OFF;
+ nic_pause.auto_neg = pause->autoneg == AUTONEG_ENABLE ?
+ PORT_CFG_AN_ON : PORT_CFG_AN_OFF;
nic_pause.rx_pause = (u8)pause->rx_pause;
nic_pause.tx_pause = (u8)pause->tx_pause;
@@ -768,6 +813,14 @@ static int hinic3_get_module_info(struct net_device *netdev,
modinfo->type = ETH_MODULE_SFF_8636;
modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
break;
+ case MODULE_TYPE_DSFP:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
+ break;
+ case MODULE_TYPE_QSFP_CMIS:
+ modinfo->type = ETH_MODULE_SFF_8636;
+ modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
+ break;
default:
nicif_warn(nic_dev, drv, netdev,
"Optical module unknown: 0x%x\n", sfp_type);
@@ -790,6 +843,11 @@ static int hinic3_get_module_eeprom(struct net_device *netdev,
memset(data, 0, ee->len);
err = hinic3_get_sfp_eeprom(nic_dev->hwdev, (u8 *)sfp_data, ee->len);
+ if (err == HINIC3_MGMT_CMD_UNSUPPORTED)
+ err = hinic3_get_tlv_xsfp_eeprom(nic_dev->hwdev,
+ (u8 *)sfp_data,
+ sizeof(sfp_data));
+
if (err)
return err;
@@ -832,7 +890,8 @@ int hinic3_set_rxq_recovery_flag(struct net_device *netdev, u32 priv_flags)
if (test_and_set_bit(HINIC3_RXQ_RECOVERY, &nic_dev->flags))
return 0;
- queue_delayed_work(nic_dev->workq, &nic_dev->rxq_check_work, HZ);
+ queue_delayed_work(nic_dev->workq,
+ &nic_dev->rxq_check_work, HZ);
nicif_info(nic_dev, drv, netdev, "open rxq recovery\n");
} else {
if (!test_and_clear_bit(HINIC3_RXQ_RECOVERY, &nic_dev->flags))
@@ -888,7 +947,8 @@ static int hinic3_set_force_link_flag(struct net_device *netdev, u32 priv_flags)
nicif_info(nic_dev, link, netdev, "Set link up\n");
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
- hinic3_notify_all_vfs_link_changed(nic_dev->hwdev, nic_dev->link_status);
+ hinic3_notify_all_vfs_link_changed(nic_dev->hwdev,
+ nic_dev->link_status);
} else {
if (!test_and_clear_bit(HINIC3_FORCE_LINK_UP, &nic_dev->flags))
return 0;
@@ -919,7 +979,8 @@ static int hinic3_set_force_link_flag(struct net_device *netdev, u32 priv_flags)
}
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
- hinic3_notify_all_vfs_link_changed(nic_dev->hwdev, nic_dev->link_status);
+ hinic3_notify_all_vfs_link_changed(nic_dev->hwdev,
+ nic_dev->link_status);
}
return 0;
@@ -942,7 +1003,6 @@ static int hinic3_set_priv_flags(struct net_device *netdev, u32 priv_flags)
#define PORT_DOWN_ERR_IDX 0
#define LP_DEFAULT_TIME 5 /* seconds */
-#define LP_PKT_LEN 60
#define TEST_TIME_MULTIPLE 5
static int hinic3_run_lp_test(struct hinic3_nic_dev *nic_dev, u32 test_time)
@@ -1086,7 +1146,8 @@ static int do_lp_test(struct hinic3_nic_dev *nic_dev, u32 *flags, u32 test_time,
return err;
}
-static void hinic3_lp_test(struct net_device *netdev, struct ethtool_test *eth_test,
+static void hinic3_lp_test(struct net_device *netdev,
+ struct ethtool_test *eth_test,
u64 *data, u32 test_time)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
@@ -1109,7 +1170,8 @@ static void hinic3_lp_test(struct net_device *netdev, struct ethtool_test *eth_t
netif_carrier_off(netdev);
netif_tx_disable(netdev);
- err = do_lp_test(nic_dev, ð_test->flags, test_time_real, &test_index);
+ err = do_lp_test(nic_dev, ð_test->flags,
+ test_time_real, &test_index);
if (err) {
eth_test->flags |= ETH_TEST_FL_FAILED;
data[test_index] = 1;
@@ -1130,10 +1192,65 @@ static void hinic3_diag_test(struct net_device *netdev,
hinic3_lp_test(netdev, eth_test, data, 0);
}
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+static int hinic3_get_fecparam(struct net_device *netdev,
+ struct ethtool_fecparam *fecparam)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ u8 advertised_fec = 0;
+ u8 supported_fec = 0;
+ int err;
+
+ if (fecparam->cmd != ETHTOOL_GFECPARAM) {
+ nicif_err(nic_dev, drv, netdev,
+ "get fecparam cmd err.exp:0x%x,real:0x%x\n",
+ ETHTOOL_GFECPARAM, fecparam->cmd);
+ return -EINVAL;
+ }
+
+ err = get_fecparam(nic_dev->hwdev, &advertised_fec, &supported_fec);
+ if (err) {
+ nicif_err(nic_dev, drv, netdev, "Get fec param failed\n");
+ return err;
+ }
+ fecparam->active_fec = (u32)advertised_fec;
+ fecparam->fec = (u32)supported_fec;
+
+ nicif_info(nic_dev, drv, netdev, "Get fec param success\n");
+ return 0;
+}
+
+static int hinic3_set_fecparam(struct net_device *netdev,
+ struct ethtool_fecparam *fecparam)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ int err;
+
+ if (fecparam->cmd != ETHTOOL_SFECPARAM) {
+ nicif_err(nic_dev, drv, netdev,
+ "Set fecparam cmd err.exp:0x%x,real:0x%x\n",
+ ETHTOOL_SFECPARAM, fecparam->cmd);
+ return -EINVAL;
+ }
+
+ err = set_fecparam(nic_dev->hwdev, (u8)fecparam->fec);
+ if (err) {
+ nicif_err(nic_dev, drv, netdev, "Set fec param failed\n");
+ return err;
+ }
+
+ nicif_info(nic_dev, drv, netdev, "Set fec param success\n");
+ return 0;
+}
+#endif
+
static const struct ethtool_ops hinic3_ethtool_ops = {
#ifdef SUPPORTED_COALESCE_PARAMS
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
- ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
+ ETHTOOL_COALESCE_PKT_RATE_RX_USECS |
+ ETHTOOL_COALESCE_MAX_FRAMES |
+ ETHTOOL_COALESCE_USECS_LOW_HIGH |
+ ETHTOOL_COALESCE_MAX_FRAMES_LOW_HIGH,
#endif
#ifdef ETHTOOL_GLINKSETTINGS
#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
@@ -1180,6 +1297,10 @@ static const struct ethtool_ops hinic3_ethtool_ops = {
.set_per_queue_coalesce = hinic3_set_per_queue_coalesce,
#endif
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+ .get_fecparam = hinic3_get_fecparam,
+ .set_fecparam = hinic3_set_fecparam,
+#endif
.get_rxnfc = hinic3_get_rxnfc,
.set_rxnfc = hinic3_set_rxnfc,
.get_priv_flags = hinic3_get_priv_flags,
@@ -1240,7 +1361,10 @@ static const struct ethtool_ops_ext hinic3_ethtool_ops_ext = {
static const struct ethtool_ops hinic3vf_ethtool_ops = {
#ifdef SUPPORTED_COALESCE_PARAMS
.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
- ETHTOOL_COALESCE_PKT_RATE_RX_USECS,
+ ETHTOOL_COALESCE_PKT_RATE_RX_USECS |
+ ETHTOOL_COALESCE_MAX_FRAMES |
+ ETHTOOL_COALESCE_USECS_LOW_HIGH |
+ ETHTOOL_COALESCE_MAX_FRAMES_LOW_HIGH,
#endif
#ifdef ETHTOOL_GLINKSETTINGS
#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
@@ -1267,6 +1391,11 @@ static const struct ethtool_ops hinic3vf_ethtool_ops = {
.set_per_queue_coalesce = hinic3_set_per_queue_coalesce,
#endif
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+ .get_fecparam = hinic3_get_fecparam,
+ .set_fecparam = hinic3_set_fecparam,
+#endif
+
.get_rxnfc = hinic3_get_rxnfc,
.set_rxnfc = hinic3_set_rxnfc,
.get_priv_flags = hinic3_get_priv_flags,
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c
index b0e6aad..7f2537a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ethtool_stats.c
@@ -24,11 +24,29 @@
#include "hinic3_tx.h"
#include "hinic3_rx.h"
-#define FPGA_PORT_COUNTER 0
-#define EVB_PORT_COUNTER 1
-u16 mag_support_mode = EVB_PORT_COUNTER;
-module_param(mag_support_mode, ushort, 0444);
-MODULE_PARM_DESC(mag_support_mode, "Set mag port counter support mode, 0:FPGA 1:EVB, default is 1");
+#define HINIC_SET_LINK_STR_LEN 128
+#define HINIC_ETHTOOL_FEC_INFO_LEN 6
+#define HINIC_SUPPORTED_FEC_CMD 0
+#define HINIC_ADVERTISED_FEC_CMD 1
+
+struct hinic3_ethtool_fec {
+ u8 hinic_fec_offset;
+ u8 ethtool_bit_offset;
+};
+
+static struct hinic3_ethtool_fec
+ hinic3_ethtool_fec_info[HINIC_ETHTOOL_FEC_INFO_LEN] = {
+ /* The ethtool does not have the corresponding enumeration variable */
+ {PORT_FEC_NOT_SET, 0xFF},
+ {PORT_FEC_RSFEC, 0x32}, /* ETHTOOL_LINK_MODE_FEC_RS_BIT */
+ /* ETHTOOL_LINK_MODE_FEC_BASER_BIT */
+ {PORT_FEC_BASEFEC, 0x33},
+ {PORT_FEC_NOFEC, 0x31}, /* ETHTOOL_LINK_MODE_FEC_NONE_BIT */
+ /* ETHTOOL_LINK_MODE_FEC_LLRS_BIT: Available only in later versions */
+ {PORT_FEC_LLRSFEC, 0x4A},
+ /* The ethtool does not have the corresponding enumeration variable */
+ {PORT_FEC_AUTO, 0XFF}
+};
struct hinic3_stats {
char name[ETH_GSTRING_LEN];
@@ -36,9 +54,23 @@ struct hinic3_stats {
int offset;
};
+struct hinic3_netdev_link_count_str {
+ u64 link_down_events_phy;
+};
+
+#define HINIC3_NETDEV_LINK_COUNT(_stat_item) { \
+ .name = #_stat_item, \
+ .size = FIELD_SIZEOF(struct hinic3_netdev_link_count_str, _stat_item), \
+ .offset = offsetof(struct hinic3_netdev_link_count_str, _stat_item) \
+}
+
+static struct hinic3_stats hinic3_netdev_link_count[] = {
+ HINIC3_NETDEV_LINK_COUNT(link_down_events_phy),
+};
+
#define HINIC3_NETDEV_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct rtnl_link_stats64, _stat_item), \
+ .size = FIELD_SIZEOF(struct rtnl_link_stats64, _stat_item), \
.offset = offsetof(struct rtnl_link_stats64, _stat_item) \
}
@@ -67,7 +99,7 @@ static struct hinic3_stats hinic3_netdev_stats[] = {
#define HINIC3_NIC_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct hinic3_nic_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_nic_stats, _stat_item), \
.offset = offsetof(struct hinic3_nic_stats, _stat_item) \
}
@@ -84,17 +116,16 @@ static struct hinic3_stats hinic3_nic_dev_stats_extern[] = {
#define HINIC3_RXQ_STAT(_stat_item) { \
.name = "rxq%d_"#_stat_item, \
- .size = sizeof_field(struct hinic3_rxq_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_rxq_stats, _stat_item), \
.offset = offsetof(struct hinic3_rxq_stats, _stat_item) \
}
#define HINIC3_TXQ_STAT(_stat_item) { \
.name = "txq%d_"#_stat_item, \
- .size = sizeof_field(struct hinic3_txq_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_txq_stats, _stat_item), \
.offset = offsetof(struct hinic3_txq_stats, _stat_item) \
}
-/*lint -save -e786*/
static struct hinic3_stats hinic3_rx_queue_stats[] = {
HINIC3_RXQ_STAT(packets),
HINIC3_RXQ_STAT(bytes),
@@ -135,11 +166,9 @@ static struct hinic3_stats hinic3_tx_queue_stats_extern[] = {
HINIC3_TXQ_STAT(rsvd2),
};
-/*lint -restore*/
-
#define HINIC3_FUNC_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct hinic3_vport_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct hinic3_vport_stats, _stat_item), \
.offset = offsetof(struct hinic3_vport_stats, _stat_item) \
}
@@ -166,7 +195,7 @@ static struct hinic3_stats hinic3_function_stats[] = {
#define HINIC3_PORT_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct mag_cmd_port_stats, _stat_item), \
+ .size = FIELD_SIZEOF(struct mag_cmd_port_stats, _stat_item), \
.offset = offsetof(struct mag_cmd_port_stats, _stat_item) \
}
@@ -260,49 +289,22 @@ static struct hinic3_stats hinic3_port_stats[] = {
HINIC3_PORT_STAT(mac_rx_unfilter_pkt_num),
};
-#define HINIC3_FGPA_PORT_STAT(_stat_item) { \
+#define HINIC3_RSFEC_STAT(_stat_item) { \
.name = #_stat_item, \
- .size = sizeof_field(struct hinic3_phy_fpga_port_stats, _stat_item), \
- .offset = offsetof(struct hinic3_phy_fpga_port_stats, _stat_item) \
+ .size = FIELD_SIZEOF(struct mag_cmd_rsfec_stats, _stat_item), \
+ .offset = offsetof(struct mag_cmd_rsfec_stats, _stat_item) \
}
-static struct hinic3_stats g_hinic3_fpga_port_stats[] = {
- HINIC3_FGPA_PORT_STAT(mac_rx_total_octs_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_total_octs_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_under_frame_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_frag_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_64_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_127_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_255_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_511_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_1023_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_max_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_over_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_64_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_127_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_255_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_511_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_1023_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_max_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_over_oct_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_good_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_crc_error_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_broadcast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_multicast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_mac_frame_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_length_err_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_vlan_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_pause_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_rx_unknown_mac_frame_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_good_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_broadcast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_multicast_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_underrun_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_mac_frame_ok_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_vlan_pkts_port),
- HINIC3_FGPA_PORT_STAT(mac_tx_pause_pkts_port),
+static struct hinic3_stats g_hinic3_rsfec_stats[] = {
+ HINIC3_RSFEC_STAT(rx_err_lane_phy),
};
+#define HINIC3_FGPA_PORT_STAT(_stat_item) { \
+ .name = #_stat_item, \
+ .size = FIELD_SIZEOF(struct hinic3_phy_fpga_port_stats, _stat_item), \
+ .offset = offsetof(struct hinic3_phy_fpga_port_stats, _stat_item) \
+}
+
static char g_hinic_priv_flags_strings[][ETH_GSTRING_LEN] = {
"Symmetric-RSS",
"Force-Link-up",
@@ -318,8 +320,7 @@ u32 hinic3_get_io_stats_size(const struct hinic3_nic_dev *nic_dev)
(ARRAY_LEN(hinic3_tx_queue_stats) +
ARRAY_LEN(hinic3_tx_queue_stats_extern) +
ARRAY_LEN(hinic3_rx_queue_stats) +
- ARRAY_LEN(hinic3_rx_queue_stats_extern)) *
- nic_dev->max_qps;
+ ARRAY_LEN(hinic3_rx_queue_stats_extern)) * nic_dev->max_qps;
return count;
}
@@ -343,72 +344,89 @@ static int dev_stats_pack(struct hinic3_show_item *items, int len,
memcpy(items[item_idx].name, array[j].name,
HINIC3_SHOW_ITEM_LEN);
items[item_idx].hexadecimal = 0;
- items[item_idx].value = get_value_of_ptr(array[j].size,
- stats_ptr + array[j].offset);
+ items[item_idx].value =
+ get_value_of_ptr(array[j].size,
+ stats_ptr + array[j].offset);
item_idx++;
}
return item_idx;
}
-static int queue_stats_pack(struct hinic3_show_item *items, int len,
- struct hinic3_stats *array, void *stats_ptr,
- u16 qid)
+int hinic3_rx_queue_stat_pack(struct hinic3_show_item *item,
+ struct hinic3_stats *stat,
+ struct hinic3_rxq_stats *rxq_stats, u16 qid)
{
- int j;
- int item_idx = 0;
+ snprintf(item->name, HINIC3_SHOW_ITEM_LEN, stat->name, qid);
- for (j = 0; j < len; j++) {
- memcpy(items[item_idx].name, array[j].name,
- HINIC3_SHOW_ITEM_LEN);
- snprintf(items[item_idx].name, HINIC3_SHOW_ITEM_LEN,
- array[j].name, qid);
- items[item_idx].hexadecimal = 0;
- items[item_idx].value = get_value_of_ptr(array[j].size,
- stats_ptr + array[j].offset);
- item_idx++;
- }
+ item->hexadecimal = 0;
+ item->value = get_value_of_ptr(stat->size, (char *)(rxq_stats) +
+ stat->offset);
- return item_idx;
+ return 0;
}
-void hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats)
+int hinic3_tx_queue_stat_pack(struct hinic3_show_item *item,
+ struct hinic3_stats *stat,
+ struct hinic3_txq_stats *txq_stats, u16 qid)
+{
+ snprintf(item->name, HINIC3_SHOW_ITEM_LEN, stat->name, qid);
+
+ item->hexadecimal = 0;
+ item->value = get_value_of_ptr(stat->size, (char *)(txq_stats) +
+ stat->offset);
+
+ return 0;
+}
+
+int hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats)
{
struct hinic3_show_item *items = stats;
int item_idx = 0;
u16 qid;
+ int idx;
+ int ret;
- item_idx += dev_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_nic_dev_stats),
- hinic3_nic_dev_stats, &nic_dev->stats);
- item_idx += dev_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_nic_dev_stats_extern),
- hinic3_nic_dev_stats_extern,
- &nic_dev->stats);
+ dev_stats_pack(items, item_idx, hinic3_nic_dev_stats, &nic_dev->stats);
+ dev_stats_pack(items, item_idx, hinic3_nic_dev_stats_extern, &nic_dev->stats);
for (qid = 0; qid < nic_dev->max_qps; qid++) {
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_tx_queue_stats),
- hinic3_tx_queue_stats,
- &nic_dev->txqs[qid].txq_stats,
- qid);
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_tx_queue_stats_extern),
- hinic3_tx_queue_stats_extern,
- &nic_dev->txqs[qid].txq_stats, qid);
+ for (idx = 0; idx < ARRAY_LEN(hinic3_tx_queue_stats); idx++) {
+ ret = hinic3_tx_queue_stat_pack(&items[item_idx++],
+ &hinic3_tx_queue_stats[idx],
+ &nic_dev->txqs[qid].txq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
+ }
+ }
+
+ for (idx = 0; idx < ARRAY_LEN(hinic3_tx_queue_stats_extern); idx++) {
+ ret = hinic3_tx_queue_stat_pack(&items[item_idx++],
+ &hinic3_tx_queue_stats_extern[idx],
+ &nic_dev->txqs[qid].txq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
}
for (qid = 0; qid < nic_dev->max_qps; qid++) {
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_rx_queue_stats),
- hinic3_rx_queue_stats,
- &nic_dev->rxqs[qid].rxq_stats,
- qid);
- item_idx += queue_stats_pack(&items[item_idx],
- ARRAY_LEN(hinic3_rx_queue_stats_extern),
- hinic3_rx_queue_stats_extern,
- &nic_dev->rxqs[qid].rxq_stats, qid);
+ for (idx = 0; idx < ARRAY_LEN(hinic3_rx_queue_stats); idx++) {
+ ret = hinic3_rx_queue_stat_pack(&items[item_idx++],
+ &hinic3_rx_queue_stats[idx],
+ &nic_dev->rxqs[qid].rxq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
+ }
+
+ for (idx = 0; idx < ARRAY_LEN(hinic3_rx_queue_stats_extern); idx++) {
+ ret = hinic3_rx_queue_stat_pack(&items[item_idx++],
+ &hinic3_rx_queue_stats_extern[idx],
+ &nic_dev->rxqs[qid].rxq_stats, qid);
+ if (ret != 0)
+ return -EINVAL;
+ }
}
+
+ return 0;
}
static char g_hinic3_test_strings[][ETH_GSTRING_LEN] = {
@@ -428,16 +446,14 @@ int hinic3_get_sset_count(struct net_device *netdev, int sset)
q_num = nic_dev->q_params.num_qps;
count = ARRAY_LEN(hinic3_netdev_stats) +
ARRAY_LEN(hinic3_nic_dev_stats) +
+ ARRAY_LEN(hinic3_netdev_link_count) +
ARRAY_LEN(hinic3_function_stats) +
(ARRAY_LEN(hinic3_tx_queue_stats) +
- ARRAY_LEN(hinic3_rx_queue_stats)) *
- q_num;
+ ARRAY_LEN(hinic3_rx_queue_stats)) * q_num;
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- if (mag_support_mode == FPGA_PORT_COUNTER)
- count += ARRAY_LEN(g_hinic3_fpga_port_stats);
- else
- count += ARRAY_LEN(hinic3_port_stats);
+ count += ARRAY_LEN(hinic3_port_stats);
+ count += ARRAY_LEN(g_hinic3_rsfec_stats);
}
return count;
@@ -486,9 +502,9 @@ static void get_drv_queue_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
}
}
-static u16 get_fpga_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
+static u16 get_ethtool_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
{
- struct hinic3_phy_fpga_port_stats *port_stats = NULL;
+ struct mag_cmd_port_stats *port_stats = NULL;
char *p = NULL;
u16 i = 0, j = 0;
int err;
@@ -496,19 +512,19 @@ static u16 get_fpga_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
if (!port_stats) {
memset(&data[i], 0,
- ARRAY_LEN(g_hinic3_fpga_port_stats) * sizeof(*data));
- i += ARRAY_LEN(g_hinic3_fpga_port_stats);
+ ARRAY_LEN(hinic3_port_stats) * sizeof(*data));
+ i += ARRAY_LEN(hinic3_port_stats);
return i;
}
- err = hinic3_get_fpga_phy_port_stats(nic_dev->hwdev, port_stats);
+ err = hinic3_get_phy_port_stats(nic_dev->hwdev, port_stats);
if (err)
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to get port stats from fw\n");
- for (j = 0; j < ARRAY_LEN(g_hinic3_fpga_port_stats); j++, i++) {
- p = (char *)(port_stats) + g_hinic3_fpga_port_stats[j].offset;
- data[i] = (g_hinic3_fpga_port_stats[j].size == sizeof(u64)) ?
+ for (j = 0; j < ARRAY_LEN(hinic3_port_stats); j++, i++) {
+ p = (char *)(port_stats) + hinic3_port_stats[j].offset;
+ data[i] = (hinic3_port_stats[j].size == sizeof(u64)) ?
*(u64 *)p :
*(u32 *)p;
}
@@ -518,34 +534,32 @@ static u16 get_fpga_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
return i;
}
-static u16 get_ethtool_port_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
+static u16 get_ethtool_rsfec_stats(struct hinic3_nic_dev *nic_dev, u64 *data)
{
- struct mag_cmd_port_stats *port_stats = NULL;
+ struct mag_cmd_rsfec_stats *port_stats = NULL;
char *p = NULL;
u16 i = 0, j = 0;
int err;
- if (mag_support_mode == FPGA_PORT_COUNTER)
- return get_fpga_port_stats(nic_dev, data);
-
port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
if (!port_stats) {
- memset(&data[i], 0,
- ARRAY_LEN(hinic3_port_stats) * sizeof(*data));
- i += ARRAY_LEN(hinic3_port_stats);
- return i;
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to malloc port stats\n");
+ memset(&data[i], 0,
+ ARRAY_LEN(g_hinic3_rsfec_stats) * sizeof(*data));
+ i += ARRAY_LEN(g_hinic3_rsfec_stats);
+ return i;
}
- err = hinic3_get_phy_port_stats(nic_dev->hwdev, port_stats);
+ err = hinic3_get_phy_rsfec_stats(nic_dev->hwdev, port_stats);
if (err)
nicif_err(nic_dev, drv, nic_dev->netdev,
- "Failed to get port stats from fw\n");
+ "Failed to get rsfec stats from fw\n");
- for (j = 0; j < ARRAY_LEN(hinic3_port_stats); j++, i++) {
- p = (char *)(port_stats) + hinic3_port_stats[j].offset;
- data[i] = (hinic3_port_stats[j].size == sizeof(u64)) ?
- *(u64 *)p :
- *(u32 *)p;
+ for (j = 0; j < ARRAY_LEN(g_hinic3_rsfec_stats); j++, i++) {
+ p = (char *)(port_stats) + g_hinic3_rsfec_stats[j].offset;
+ data[i] = (g_hinic3_rsfec_stats[j].size ==
+ sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
kfree(port_stats);
@@ -569,6 +583,8 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
u16 i = 0, j = 0;
char *p = NULL;
int err;
+ int link_down_events_phy_tmp = 0;
+ struct hinic3_netdev_link_count_str link_count = {0};
#ifdef HAVE_NDO_GET_STATS64
net_stats = dev_get_stats(netdev, &temp);
@@ -586,6 +602,15 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
data[i] = get_value_of_ptr(hinic3_nic_dev_stats[j].size, p);
}
+ err = hinic3_get_link_event_stats(nic_dev->hwdev,
+ &link_down_events_phy_tmp);
+
+ link_count.link_down_events_phy = (u64)link_down_events_phy_tmp;
+ for (j = 0; j < ARRAY_LEN(hinic3_netdev_link_count); j++, i++) {
+ p = (char *)(&link_count) + hinic3_netdev_link_count[j].offset;
+ data[i] = get_value_of_ptr(hinic3_netdev_link_count[j].size, p);
+ }
+
err = hinic3_get_vport_stats(nic_dev->hwdev,
hinic3_global_func_id(nic_dev->hwdev),
&vport_stats);
@@ -598,8 +623,10 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
data[i] = get_value_of_ptr(hinic3_function_stats[j].size, p);
}
- if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
i += get_ethtool_port_stats(nic_dev, data + i);
+ i += get_ethtool_rsfec_stats(nic_dev, data + i);
+ }
get_drv_queue_stats(nic_dev, data + i);
}
@@ -620,6 +647,12 @@ static u16 get_drv_dev_strings(struct hinic3_nic_dev *nic_dev, char *p)
cnt++;
}
+ for (i = 0; i < ARRAY_LEN(hinic3_netdev_link_count); i++) {
+ memcpy(p, hinic3_netdev_link_count[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ cnt++;
+ }
+
return cnt;
}
@@ -634,21 +667,16 @@ static u16 get_hw_stats_strings(struct hinic3_nic_dev *nic_dev, char *p)
}
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
- if (mag_support_mode == FPGA_PORT_COUNTER) {
- for (i = 0; i < ARRAY_LEN(g_hinic3_fpga_port_stats);
- i++) {
- memcpy(p, g_hinic3_fpga_port_stats[i].name,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- cnt++;
- }
- } else {
- for (i = 0; i < ARRAY_LEN(hinic3_port_stats); i++) {
- memcpy(p, hinic3_port_stats[i].name,
- ETH_GSTRING_LEN);
- p += ETH_GSTRING_LEN;
- cnt++;
- }
+ for (i = 0; i < ARRAY_LEN(hinic3_port_stats); i++) {
+ memcpy(p, hinic3_port_stats[i].name, ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ cnt++;
+ }
+ for (i = 0; i < ARRAY_LEN(g_hinic3_rsfec_stats); i++) {
+ memcpy(p, g_hinic3_rsfec_stats[i].name,
+ ETH_GSTRING_LEN);
+ p += ETH_GSTRING_LEN;
+ cnt++;
}
}
@@ -664,7 +692,8 @@ static u16 get_qp_stats_strings(const struct hinic3_nic_dev *nic_dev, char *p)
for (j = 0; j < ARRAY_LEN(hinic3_tx_queue_stats); j++) {
err = sprintf(p, hinic3_tx_queue_stats[j].name, i);
if (err < 0)
- nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to sprintf tx queue stats name, idx_qps: %u, idx_stats: %u\n",
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to sprintf tx queue stats name, idx_qps: %u, idx_stats: %u\n",
i, j);
p += ETH_GSTRING_LEN;
cnt++;
@@ -675,7 +704,8 @@ static u16 get_qp_stats_strings(const struct hinic3_nic_dev *nic_dev, char *p)
for (j = 0; j < ARRAY_LEN(hinic3_rx_queue_stats); j++) {
err = sprintf(p, hinic3_rx_queue_stats[j].name, i);
if (err < 0)
- nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to sprintf rx queue stats name, idx_qps: %u, idx_stats: %u\n",
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to sprintf rx queue stats name, idx_qps: %u, idx_stats: %u\n",
i, j);
p += ETH_GSTRING_LEN;
cnt++;
@@ -791,7 +821,6 @@ struct hw2ethtool_link_mode {
u32 speed;
};
-/*lint -save -e26 */
static const struct hw2ethtool_link_mode
hw2ethtool_link_mode_table[LINK_MODE_MAX_NUMBERS] = {
[LINK_MODE_GE] = {
@@ -851,8 +880,6 @@ static const struct hw2ethtool_link_mode
},
};
-/*lint -restore */
-
#define GET_SUPPORTED_MODE 0
#define GET_ADVERTISED_MODE 1
@@ -867,21 +894,35 @@ struct cmd_link_settings {
};
#define ETHTOOL_ADD_SUPPORTED_LINK_MODE(ecmd, mode) \
- set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->supported)
+ set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->supported)
#define ETHTOOL_ADD_ADVERTISED_LINK_MODE(ecmd, mode) \
- set_bit(ETHTOOL_LINK_##mode##_BIT, (ecmd)->advertising)
+ set_bit(ETHTOOL_LINK_MODE_##mode##_BIT, (ecmd)->advertising)
-static void ethtool_add_speed_link_mode(__ETHTOOL_DECLARE_LINK_MODE_MASK(bitmap), u32 mode)
+static void ethtool_add_supported_speed_link_mode(struct cmd_link_settings *link_settings,
+ u32 mode)
{
u32 i;
for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) {
if (hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i] >=
- __ETHTOOL_LINK_MODE_MASK_NBITS)
+ __ETHTOOL_LINK_MODE_MASK_NBITS)
continue;
+ set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i],
+ link_settings->supported);
+ }
+}
+static void ethtool_add_advertised_speed_link_mode(struct cmd_link_settings *link_settings,
+ u32 mode)
+{
+ u32 i;
+
+ for (i = 0; i < hw2ethtool_link_mode_table[mode].arr_size; i++) {
+ if (hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i] >=
+ __ETHTOOL_LINK_MODE_MASK_NBITS)
+ continue;
set_bit(hw2ethtool_link_mode_table[mode].link_mode_bit_arr[i],
- bitmap);
+ link_settings->advertising);
}
}
@@ -912,9 +953,11 @@ hinic3_add_ethtool_link_mode(struct cmd_link_settings *link_settings,
for (link_mode = 0; link_mode < LINK_MODE_MAX_NUMBERS; link_mode++) {
if (hw_link_mode & BIT(link_mode)) {
if (name == GET_SUPPORTED_MODE)
- ethtool_add_speed_link_mode(link_settings->supported, link_mode);
+ ethtool_add_supported_speed_link_mode(link_settings,
+ link_mode);
else
- ethtool_add_speed_link_mode(link_settings->advertising, link_mode);
+ ethtool_add_advertised_speed_link_mode(
+ link_settings, link_mode);
}
}
}
@@ -937,10 +980,15 @@ static int hinic3_link_speed_set(struct hinic3_nic_dev *nic_dev,
err = hinic3_get_link_state(nic_dev->hwdev, &link_state);
if (!err && link_state) {
- link_settings->speed =
- port_info->speed < ARRAY_LEN(hw_to_ethtool_speed) ?
+ if (hinic3_get_bond_create_mode(nic_dev->hwdev)) {
+ link_settings->speed = port_info->bond_speed;
+ } else {
+ link_settings->speed =
+ port_info->speed <
+ ARRAY_LEN(hw_to_ethtool_speed) ?
hw_to_ethtool_speed[port_info->speed] :
(u32)SPEED_UNKNOWN;
+ }
link_settings->duplex = port_info->duplex;
} else {
@@ -956,28 +1004,28 @@ static void hinic3_link_port_type(struct cmd_link_settings *link_settings,
{
switch (port_type) {
case MAG_CMD_WIRE_TYPE_ELECTRIC:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_TP);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_TP);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, TP);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, TP);
link_settings->port = PORT_TP;
break;
case MAG_CMD_WIRE_TYPE_AOC:
case MAG_CMD_WIRE_TYPE_MM:
case MAG_CMD_WIRE_TYPE_SM:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
link_settings->port = PORT_FIBRE;
break;
case MAG_CMD_WIRE_TYPE_COPPER:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_FIBRE);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_FIBRE);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, FIBRE);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, FIBRE);
link_settings->port = PORT_DA;
break;
case MAG_CMD_WIRE_TYPE_BACKPLANE:
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Backplane);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Backplane);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Backplane);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Backplane);
link_settings->port = PORT_NONE;
break;
@@ -1000,19 +1048,56 @@ static int get_link_pause_settings(struct hinic3_nic_dev *nic_dev,
return err;
}
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Pause);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Pause);
if (nic_pause.rx_pause && nic_pause.tx_pause) {
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause);
} else if (nic_pause.tx_pause) {
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Asym_Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause);
} else if (nic_pause.rx_pause) {
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Pause);
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Asym_Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Pause);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Asym_Pause);
}
return 0;
}
+static bool is_bit_offset_defined(u8 bit_offset)
+{
+ if (bit_offset < __ETHTOOL_LINK_MODE_MASK_NBITS)
+ return true;
+ return false;
+}
+
+static void ethtool_add_supported_advertised_fec(struct cmd_link_settings *link_settings,
+ u32 fec, u8 cmd)
+{
+ u8 i;
+
+ for (i = 0; i < HINIC_ETHTOOL_FEC_INFO_LEN; i++) {
+ if ((fec & BIT(hinic3_ethtool_fec_info[i].hinic_fec_offset)) == 0)
+ continue;
+ if (is_bit_offset_defined(hinic3_ethtool_fec_info[i].ethtool_bit_offset) == true &&
+ cmd == HINIC_ADVERTISED_FEC_CMD) {
+ set_bit(hinic3_ethtool_fec_info[i].ethtool_bit_offset,
+ link_settings->advertising);
+ return; /* There can be only one advertised fec mode. */
+ }
+ if (is_bit_offset_defined(hinic3_ethtool_fec_info[i].ethtool_bit_offset) == true &&
+ cmd == HINIC_SUPPORTED_FEC_CMD)
+ set_bit(hinic3_ethtool_fec_info[i].ethtool_bit_offset,
+ link_settings->supported);
+ }
+}
+
+static void hinic3_link_fec_type(struct cmd_link_settings *link_settings,
+ u32 fec, u32 supported_fec)
+{
+ ethtool_add_supported_advertised_fec(link_settings, supported_fec,
+ HINIC_SUPPORTED_FEC_CMD);
+ ethtool_add_supported_advertised_fec(link_settings, fec,
+ HINIC_ADVERTISED_FEC_CMD);
+}
+
static int get_link_settings(struct net_device *netdev,
struct cmd_link_settings *link_settings)
{
@@ -1033,13 +1118,19 @@ static int get_link_settings(struct net_device *netdev,
hinic3_link_port_type(link_settings, port_info.port_type);
+ /* port_info.fec is bit offset, value is BIT(port_info.fec);
+ * but port_info.supported_fec_mode is bit value
+ */
+ hinic3_link_fec_type(link_settings, BIT(port_info.fec),
+ port_info.supported_fec_mode);
+
link_settings->autoneg = port_info.autoneg_state == PORT_CFG_AN_ON ?
AUTONEG_ENABLE :
AUTONEG_DISABLE;
if (port_info.autoneg_cap)
- ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, MODE_Autoneg);
+ ETHTOOL_ADD_SUPPORTED_LINK_MODE(link_settings, Autoneg);
if (port_info.autoneg_state == PORT_CFG_AN_ON)
- ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, MODE_Autoneg);
+ ETHTOOL_ADD_ADVERTISED_LINK_MODE(link_settings, Autoneg);
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
err = get_link_pause_settings(nic_dev, link_settings);
@@ -1163,23 +1254,18 @@ static int hinic3_set_settings_to_hw(struct hinic3_nic_dev *nic_dev,
struct net_device *netdev = nic_dev->netdev;
struct hinic3_link_ksettings settings = { 0 };
int speed_level = 0;
- char set_link_str[128] = { 0 };
+ char set_link_str[HINIC_SET_LINK_STR_LEN] = {0};
+ char link_info[HINIC_SET_LINK_STR_LEN] = {0};
int err = 0;
- err = snprintf(set_link_str, sizeof(set_link_str) - 1, "%s",
- (bool)(set_settings & HILINK_LINK_SET_AUTONEG) ?
- ((bool)autoneg ? "autong enable " :
- "autong disable ") :
- "");
- if (err < 0)
- return -EINVAL;
+ snprintf(link_info, sizeof(link_info), "%s",
+ (bool)(set_settings & HILINK_LINK_SET_AUTONEG) ?
+ ((bool)autoneg ? "autong enable " : "autong disable ") : "");
if (set_settings & HILINK_LINK_SET_SPEED) {
speed_level = hinic3_ethtool_to_hw_speed_level(speed);
- err = snprintf(set_link_str, sizeof(set_link_str) - 1,
- "%sspeed %u ", set_link_str, speed);
- if (err < 0)
- return -EINVAL;
+ snprintf(set_link_str, sizeof(set_link_str),
+ "%sspeed %u ", link_info, speed);
}
settings.valid_bitmap = set_settings;
@@ -1218,7 +1304,8 @@ static int set_link_settings(struct net_device *netdev, u8 autoneg, u32 speed)
#ifdef ETHTOOL_GLINKSETTINGS
#ifndef XENSERVER_HAVE_NEW_ETHTOOL_OPS
int hinic3_set_link_ksettings(struct net_device *netdev,
- const struct ethtool_link_ksettings *link_settings)
+ const
+ struct ethtool_link_ksettings *link_settings)
{
/* Only support to set autoneg and speed */
return set_link_settings(netdev, link_settings->base.autoneg,
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c b/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
index 70346d6..2daa7f9 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_filter.c
@@ -82,7 +82,7 @@ static struct hinic3_mac_filter *hinic3_add_filter(struct hinic3_nic_dev *nic_de
struct list_head *mac_filter_list,
u8 *addr)
{
- struct hinic3_mac_filter *f;
+ struct hinic3_mac_filter *f = NULL;
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f)
@@ -117,7 +117,7 @@ static void hinic3_del_filter(struct hinic3_nic_dev *nic_dev,
static struct hinic3_mac_filter *hinic3_mac_filter_entry_clone(const struct hinic3_mac_filter *src)
{
- struct hinic3_mac_filter *f;
+ struct hinic3_mac_filter *f = NULL;
f = kzalloc(sizeof(*f), GFP_ATOMIC);
if (!f)
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h b/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h
index ef8c62b..a3136ce 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw.h
@@ -40,6 +40,7 @@ enum hinic3_channel_id {
HINIC3_CHANNEL_DSW,
HINIC3_CHANNEL_MIG,
HINIC3_CHANNEL_CRYPT,
+ HINIC3_CHANNEL_VROCE,
HINIC3_CHANNEL_MAX = 32,
};
@@ -397,6 +398,16 @@ void hinic3_free_cmd_buf(void *hwdev, struct hinic3_cmd_buf *cmd_buf);
**/
int hinic3_sm_ctr_rd16(void *hwdev, u8 node, u8 instance, u32 ctr_id, u16 *value);
+/**
+ * hinic3_sm_ctr_rd16_clear - small single 16 counter read clear
+ * @hwdev: the hardware device
+ * @node: the node id
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ **/
+int hinic3_sm_ctr_rd16_clear(void *hwdev, u8 node, u8 instance, u32 ctr_id, u16 *value);
+
/**
* @brief hinic3_sm_ctr_rd32 - small single 32 counter read
* @param hwdev: device pointer to hwdev
@@ -810,6 +821,13 @@ int hinic3_dbg_lt_wr_16byte_mask(void *hwdev, u8 dest, u8 instance,
*/
void hinic3_link_event_stats(void *dev, u8 link);
+/**
+ * @brief hinic3_get_link_event_stats - link event stats
+ * @param hwdev: device pointer to hwdev
+ * @param link: link status
+ */
+int hinic3_get_link_event_stats(void *dev, int *link_state);
+
/**
* @brief hinic3_get_hw_pf_infos - get pf infos
* @param hwdev: device pointer to hwdev
@@ -856,4 +874,5 @@ void hinic3_set_api_stop(void *hwdev);
int hinic3_activate_firmware(void *hwdev, u8 cfg_index);
int hinic3_switch_config(void *hwdev, u8 cfg_index);
+bool hinic3_is_optical_module_mode(void *hwdev);
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c b/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
index 7e59c81..6525b76 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_irq.c
@@ -47,12 +47,16 @@ static void qp_add_napi(struct hinic3_irq *irq_cfg)
netif_napi_add_weight(nic_dev->netdev, &irq_cfg->napi,
hinic3_poll, nic_dev->poll_weight);
napi_enable(&irq_cfg->napi);
+ irq_cfg->napi_reign = NAPI_IS_REGIN;
}
-static void qp_del_napi(struct hinic3_irq *irq_cfg)
+void qp_del_napi(struct hinic3_irq *irq_cfg)
{
- napi_disable(&irq_cfg->napi);
- netif_napi_del(&irq_cfg->napi);
+ if (irq_cfg->napi_reign == NAPI_IS_REGIN) {
+ napi_disable(&irq_cfg->napi);
+ netif_napi_del(&irq_cfg->napi);
+ irq_cfg->napi_reign = NAPI_NOT_REGIN;
+ }
}
static irqreturn_t qp_irq(int irq, void *data)
@@ -60,7 +64,8 @@ static irqreturn_t qp_irq(int irq, void *data)
struct hinic3_irq *irq_cfg = (struct hinic3_irq *)data;
struct hinic3_nic_dev *nic_dev = netdev_priv(irq_cfg->netdev);
- hinic3_misx_intr_clear_resend_bit(nic_dev->hwdev, irq_cfg->msix_entry_idx, 1);
+ hinic3_misx_intr_clear_resend_bit(nic_dev->hwdev,
+ irq_cfg->msix_entry_idx, 1);
napi_schedule(&irq_cfg->napi);
@@ -95,7 +100,8 @@ static int hinic3_request_irq(struct hinic3_irq *irq_cfg, u16 q_id)
return err;
}
- err = request_irq(irq_cfg->irq_id, &qp_irq, 0, irq_cfg->irq_name, irq_cfg);
+ err = request_irq(irq_cfg->irq_id, &qp_irq, 0,
+ irq_cfg->irq_name, irq_cfg);
if (err) {
nicif_err(nic_dev, drv, irq_cfg->netdev, "Failed to request Rx irq\n");
qp_del_napi(irq_cfg);
@@ -138,12 +144,8 @@ int hinic3_qps_irq_init(struct hinic3_nic_dev *nic_dev)
local_cpu = cpumask_local_spread(q_id, dev_to_node(&pdev->dev));
cpumask_set_cpu(local_cpu, &irq_cfg->affinity_mask);
- err = snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name),
- "%s_qp%u", nic_dev->netdev->name, q_id);
- if (err < 0) {
- err = -EINVAL;
- goto req_tx_irq_err;
- }
+ snprintf(irq_cfg->irq_name, sizeof(irq_cfg->irq_name),
+ "%s_qp%u", nic_dev->netdev->name, q_id);
err = hinic3_request_irq(irq_cfg, q_id);
if (err) {
@@ -151,20 +153,25 @@ int hinic3_qps_irq_init(struct hinic3_nic_dev *nic_dev)
goto req_tx_irq_err;
}
- hinic3_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
+ irq_cfg->msix_entry_idx,
HINIC3_SET_MSIX_AUTO_MASK);
- hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, HINIC3_MSIX_ENABLE);
+ hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ HINIC3_MSIX_ENABLE);
}
- INIT_DELAYED_WORK(&nic_dev->moderation_task, hinic3_auto_moderation_work);
+ INIT_DELAYED_WORK(&nic_dev->moderation_task,
+ hinic3_auto_moderation_work);
return 0;
req_tx_irq_err:
for (i = 0; i < q_id; i++) {
irq_cfg = &nic_dev->q_params.irq_cfg[i];
- hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx, HINIC3_MSIX_DISABLE);
- hinic3_set_msix_auto_mask_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ hinic3_set_msix_state(nic_dev->hwdev, irq_cfg->msix_entry_idx,
+ HINIC3_MSIX_DISABLE);
+ hinic3_set_msix_auto_mask_state(nic_dev->hwdev,
+ irq_cfg->msix_entry_idx,
HINIC3_CLR_MSIX_AUTO_MASK);
hinic3_release_irq(irq_cfg);
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.h b/drivers/net/ethernet/huawei/hinic3/hinic3_lld.h
deleted file mode 100644
index 2482c5f..0000000
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_lld.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 2021 Huawei Technologies Co., Ltd */
-
-#ifndef HINIC3_LLD_H
-#define HINIC3_LLD_H
-
-#include "hinic3_crm.h"
-
-struct hinic3_lld_dev {
- struct pci_dev *pdev;
- void *hwdev;
-};
-
-struct hinic3_uld_info {
- /* When the function does not need to initialize the corresponding uld,
- * @probe needs to return 0 and uld_dev is set to NULL;
- * if uld_dev is NULL, @remove will not be called when uninstalling
- */
- int (*probe)(struct hinic3_lld_dev *lld_dev, void **uld_dev, char *uld_dev_name);
- void (*remove)(struct hinic3_lld_dev *lld_dev, void *uld_dev);
- int (*suspend)(struct hinic3_lld_dev *lld_dev, void *uld_dev, pm_message_t state);
- int (*resume)(struct hinic3_lld_dev *lld_dev, void *uld_dev);
- void (*event)(struct hinic3_lld_dev *lld_dev, void *uld_dev,
- struct hinic3_event_info *event);
- int (*ioctl)(void *uld_dev, u32 cmd, const void *buf_in, u32 in_size,
- void *buf_out, u32 *out_size);
-};
-
-/* hinic3_register_uld - register an upper-layer driver
- * @type: uld service type
- * @uld_info: uld callback
- *
- * Registers an upper-layer driver.
- * Traverse existing devices and call @probe to initialize the uld device.
- */
-int hinic3_register_uld(enum hinic3_service_type type, struct hinic3_uld_info *uld_info);
-
-/**
- * hinic3_unregister_uld - unregister an upper-layer driver
- * @type: uld service type
- *
- * Traverse existing devices and call @remove to uninstall the uld device.
- * Unregisters an existing upper-layer driver.
- */
-void hinic3_unregister_uld(enum hinic3_service_type type);
-
-void lld_hold(void);
-void lld_put(void);
-
-/**
- * @brief hinic3_get_lld_dev_by_chip_name - get lld device by chip name
- * @param chip_name: chip name
- *
- * The value of lld_dev reference increases when lld_dev is obtained. The caller needs
- * to release the reference by calling lld_dev_put.
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_chip_name(const char *chip_name);
-
-/**
- * @brief lld_dev_hold - get reference to lld_dev
- * @param dev: lld device
- *
- * Hold reference to device to keep it from being freed
- **/
-void lld_dev_hold(struct hinic3_lld_dev *dev);
-
-/**
- * @brief lld_dev_put - release reference to lld_dev
- * @param dev: lld device
- *
- * Release reference to device to allow it to be freed
- **/
-void lld_dev_put(struct hinic3_lld_dev *dev);
-
-/**
- * @brief hinic3_get_lld_dev_by_dev_name - get lld device by uld device name
- * @param dev_name: uld device name
- * @param type: uld service type, When the type is SERVICE_T_MAX, try to match
- * all ULD names to get uld_dev
- *
- * The value of lld_dev reference increases when lld_dev is obtained. The caller needs
- * to release the reference by calling lld_dev_put.
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_dev_name(const char *dev_name,
- enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_lld_dev_by_dev_name_unsafe - get lld device by uld device name
- * @param dev_name: uld device name
- * @param type: uld service type, When the type is SERVICE_T_MAX, try to match
- * all ULD names to get uld_dev
- *
- * hinic3_get_lld_dev_by_dev_name_unsafe() is completely analogous to
- * hinic3_get_lld_dev_by_dev_name(), The only difference is that the reference
- * of lld_dev is not increased when lld_dev is obtained.
- *
- * The caller must ensure that lld_dev will not be freed during the remove process
- * when using lld_dev.
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_dev_name_unsafe(const char *dev_name,
- enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_lld_dev_by_chip_and_port - get lld device by chip name and port id
- * @param chip_name: chip name
- * @param port_id: port id
- **/
-struct hinic3_lld_dev *hinic3_get_lld_dev_by_chip_and_port(const char *chip_name, u8 port_id);
-
-/**
- * @brief hinic3_get_ppf_lld_dev - get ppf lld device by current function's lld device
- * @param lld_dev: current function's lld device
- *
- * The value of lld_dev reference increases when lld_dev is obtained. The caller needs
- * to release the reference by calling lld_dev_put.
- **/
-struct hinic3_lld_dev *hinic3_get_ppf_lld_dev(struct hinic3_lld_dev *lld_dev);
-
-/**
- * @brief hinic3_get_ppf_lld_dev_unsafe - get ppf lld device by current function's lld device
- * @param lld_dev: current function's lld device
- *
- * hinic3_get_ppf_lld_dev_unsafe() is completely analogous to hinic3_get_ppf_lld_dev(),
- * The only difference is that the reference of lld_dev is not increased when lld_dev is obtained.
- *
- * The caller must ensure that ppf's lld_dev will not be freed during the remove process
- * when using ppf lld_dev.
- **/
-struct hinic3_lld_dev *hinic3_get_ppf_lld_dev_unsafe(struct hinic3_lld_dev *lld_dev);
-
-/**
- * @brief uld_dev_hold - get reference to uld_dev
- * @param lld_dev: lld device
- * @param type: uld service type
- *
- * Hold reference to uld device to keep it from being freed
- **/
-void uld_dev_hold(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief uld_dev_put - release reference to lld_dev
- * @param dev: lld device
- * @param type: uld service type
- *
- * Release reference to uld device to allow it to be freed
- **/
-void uld_dev_put(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_uld_dev - get uld device by lld device
- * @param lld_dev: lld device
- * @param type: uld service type
- *
- * The value of uld_dev reference increases when uld_dev is obtained. The caller needs
- * to release the reference by calling uld_dev_put.
- **/
-void *hinic3_get_uld_dev(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_uld_dev_unsafe - get uld device by lld device
- * @param lld_dev: lld device
- * @param type: uld service type
- *
- * hinic3_get_uld_dev_unsafe() is completely analogous to hinic3_get_uld_dev(),
- * The only difference is that the reference of uld_dev is not increased when uld_dev is obtained.
- *
- * The caller must ensure that uld_dev will not be freed during the remove process
- * when using uld_dev.
- **/
-void *hinic3_get_uld_dev_unsafe(struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-
-/**
- * @brief hinic3_get_chip_name - get chip name by lld device
- * @param lld_dev: lld device
- * @param chip_name: String for storing the chip name
- * @param max_len: Maximum number of characters to be copied for chip_name
- **/
-int hinic3_get_chip_name(struct hinic3_lld_dev *lld_dev, char *chip_name, u16 max_len);
-
-struct card_node *hinic3_get_chip_node_by_lld(struct hinic3_lld_dev *lld_dev);
-
-struct hinic3_hwdev *hinic3_get_sdk_hwdev_by_lld(struct hinic3_lld_dev *lld_dev);
-
-bool hinic3_get_vf_service_load(struct pci_dev *pdev, u16 service);
-
-int hinic3_set_vf_service_load(struct pci_dev *pdev, u16 service,
- bool vf_srv_load);
-
-int hinic3_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id,
- u16 service, bool en);
-
-bool hinic3_get_vf_load_state(struct pci_dev *pdev);
-
-int hinic3_set_vf_load_state(struct pci_dev *pdev, bool vf_load_state);
-
-int hinic3_attach_nic(struct hinic3_lld_dev *lld_dev);
-
-void hinic3_detach_nic(const struct hinic3_lld_dev *lld_dev);
-
-int hinic3_attach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-void hinic3_detach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
-const char **hinic3_get_uld_names(void);
-int hinic3_lld_init(void);
-void hinic3_lld_exit(void);
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c
index 2fe808b..688bb7d 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mag_cfg.c
@@ -17,11 +17,22 @@
#include "ossl_knl.h"
#include "hinic3_crm.h"
#include "hinic3_hw.h"
+#include "mag_mpu_cmd.h"
+#include "mag_mpu_cmd_defs.h"
#include "hinic3_nic_io.h"
#include "hinic3_nic_cfg.h"
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
#include "hinic3_common.h"
+#include "mag_mpu_cmd_defs.h"
+
+#define BIFUR_RESOURCE_PF_SSID 0x5a1
+#define CAP_INFO_MAX_LEN 512
+#define DEVICE_VENDOR_MAX_LEN 17
+#define READ_RSFEC_REGISTER_DELAY_TIME_MS 500
+
+struct parse_tlv_info g_page_info = {0};
+struct drv_tag_mag_cmd_get_xsfp_tlv_rsp g_xsfp_tlv_info = {0};
static int mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size);
@@ -78,8 +89,10 @@ int hinic3_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats)
return -ENOMEM;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (!nic_io)
- return -EINVAL;
+ if (!nic_io) {
+ err = -EINVAL;
+ goto out;
+ }
memset(&stats_info, 0, sizeof(stats_info));
stats_info.port_id = hinic3_physical_port_id(hwdev);
@@ -104,6 +117,64 @@ out:
}
EXPORT_SYMBOL(hinic3_get_phy_port_stats);
+int hinic3_get_phy_rsfec_stats(void *hwdev, struct mag_cmd_rsfec_stats *stats)
+{
+ struct mag_cmd_get_mag_cnt *port_stats = NULL;
+ struct mag_cmd_get_mag_cnt stats_info;
+ u16 out_size = sizeof(*port_stats);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err;
+
+ if (!hwdev || !stats)
+ return -EINVAL;
+
+ port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
+ if (!port_stats)
+ return -ENOMEM;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ err = -EINVAL;
+ goto out;
+ }
+
+ memset(&stats_info, 0, sizeof(stats_info));
+ stats_info.port_id = hinic3_physical_port_id(hwdev);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_MAG_CNT,
+ &stats_info, sizeof(stats_info),
+ port_stats, &out_size);
+ if (err || !out_size || port_stats->head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get rsfec statistics, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, port_stats->head.status, out_size);
+ err = -EIO;
+ goto out;
+ }
+ /* 读2遍, 清除误码残留 */
+ msleep(READ_RSFEC_REGISTER_DELAY_TIME_MS);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_MAG_CNT, &stats_info,
+ sizeof(stats_info),
+ port_stats, &out_size);
+ if (err || !out_size || port_stats->head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get rsfec statistics, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, port_stats->head.status, out_size);
+ err = -EIO;
+ goto out;
+ }
+
+ memcpy(stats, &port_stats->mag_csr[MAG_RX_RSFEC_ERR_CW_CNT],
+ sizeof(u32));
+
+out:
+ kfree(port_stats);
+
+ return err;
+}
+EXPORT_SYMBOL(hinic3_get_phy_rsfec_stats);
+
int hinic3_set_port_funcs_state(void *hwdev, bool enable)
{
return 0;
@@ -180,6 +251,8 @@ int hinic3_get_loopback_mode(void *hwdev, u8 *mode, u8 *enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
return hinic3_cfg_loopback_mode(nic_io, MGMT_MSG_CMD_OP_GET, mode,
enable);
@@ -195,6 +268,8 @@ int hinic3_set_loopback_mode(void *hwdev, u8 mode, u8 enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (mode < LOOP_MODE_MIN || mode > LOOP_MODE_MAX) {
nic_err(nic_io->dev_hdl, "Invalid loopback mode %u to set\n",
@@ -218,6 +293,9 @@ int hinic3_set_led_status(void *hwdev, enum mag_led_type type,
return -EFAULT;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memset(&led_info, 0, sizeof(led_info));
led_info.function_id = hinic3_global_func_id(hwdev);
@@ -249,6 +327,8 @@ int hinic3_get_port_info(void *hwdev, struct nic_port_info *port_info,
memset(&port_msg, 0, sizeof(port_msg));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
port_msg.port_id = hinic3_physical_port_id(hwdev);
@@ -268,9 +348,12 @@ int hinic3_get_port_info(void *hwdev, struct nic_port_info *port_info,
port_info->port_type = port_msg.wire_type;
port_info->speed = port_msg.speed;
port_info->fec = port_msg.fec;
+ port_info->lanes = port_msg.lanes;
port_info->supported_mode = port_msg.supported_mode;
port_info->advertised_mode = port_msg.advertised_mode;
-
+ port_info->supported_fec_mode = port_msg.supported_fec_mode;
+ /* switch Gbps to Mbps */
+ port_info->bond_speed = (u32)port_msg.bond_speed * RATE_MBPS_TO_GBPS;
return 0;
}
@@ -306,6 +389,8 @@ int hinic3_set_link_settings(void *hwdev,
memset(&info, 0, sizeof(info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
info.port_id = hinic3_physical_port_id(hwdev);
info.config_bitmap = settings->valid_bitmap;
@@ -335,6 +420,8 @@ int hinic3_get_link_state(void *hwdev, u8 *link_state)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&get_link, 0, sizeof(get_link));
get_link.port_id = hinic3_physical_port_id(hwdev);
@@ -364,10 +451,11 @@ void hinic3_notify_vf_link_status(struct hinic3_nic_io *nic_io,
if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) {
link.status = link_status;
link.port_id = hinic3_physical_port_id(nic_io->hwdev);
- err = hinic3_mbox_to_vf(nic_io->hwdev, vf_id, HINIC3_MOD_HILINK,
- MAG_CMD_GET_LINK_STATUS, &link,
- sizeof(link), &link, &out_size, 0,
- HINIC3_CHANNEL_NIC);
+ err = hinic3_mbox_to_vf_no_ack(nic_io->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) {
nic_warn(nic_io->dev_hdl, "VF%d not initialized, disconnect it\n",
HW_VF_ID_TO_OS(vf_id));
@@ -387,6 +475,8 @@ void hinic3_notify_all_vfs_link_changed(void *hwdev, u8 link_status)
u16 i;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
nic_io->link_status = link_status;
for (i = 1; i <= nic_io->max_vfs; i++) {
if (!nic_io->vf_infos[HW_VF_ID_TO_OS(i)].link_forced)
@@ -394,6 +484,165 @@ void hinic3_notify_all_vfs_link_changed(void *hwdev, u8 link_status)
}
}
+static char *g_hw_to_char_fec[HILINK_FEC_MAX_TYPE] = {
+ "not set", "rsfec", "basefec",
+ "nofec", "llrsfec"};
+static char *g_hw_to_speed_info[PORT_SPEED_UNKNOWN] = {
+ "not set", "10MB", "100MB", "1GB", "10GB",
+ "25GB", "40GB", "50GB", "100GB", "200GB"};
+static char *g_hw_to_an_state_info[PORT_CFG_AN_OFF + 1] = {
+ "not set", "on", "off"};
+
+struct port_type_table {
+ u32 port_type;
+ char *port_type_name;
+};
+
+static const struct port_type_table port_optical_type_table_s[] = {
+ {LINK_PORT_UNKNOWN, "UNKNOWN"},
+ {LINK_PORT_OPTICAL_MM, "optical_sr"},
+ {LINK_PORT_OPTICAL_SM, "optical_lr"},
+ {LINK_PORT_PAS_COPPER, "copper"},
+ {LINK_PORT_ACC, "ACC"},
+ {LINK_PORT_BASET, "baset"},
+ {LINK_PORT_AOC, "AOC"},
+ {LINK_PORT_ELECTRIC, "electric"},
+ {LINK_PORT_BACKBOARD_INTERFACE, "interface"},
+};
+
+static char *get_port_type_name(u32 type)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(port_optical_type_table_s); i++) {
+ if (type == port_optical_type_table_s[i].port_type)
+ return port_optical_type_table_s[i].port_type_name;
+ }
+ return "UNKNOWN TYPE";
+}
+
+static void get_port_type(struct hinic3_nic_io *nic_io,
+ struct mag_cmd_event_port_info *info,
+ char **port_type)
+{
+ if (info->port_type <= LINK_PORT_BACKBOARD_INTERFACE)
+ *port_type = get_port_type_name(info->port_type);
+ else
+ sdk_info(nic_io->dev_hdl, "Unknown port type: %u\n", info->port_type);
+}
+
+static int get_port_temperature_power(struct mag_cmd_event_port_info *info,
+ char *str)
+{
+ char cap_info[CAP_INFO_MAX_LEN];
+
+ memset(cap_info, 0, sizeof(cap_info));
+ snprintf(cap_info, CAP_INFO_MAX_LEN, "%s, %s, Temperature: %u", str,
+ info->sfp_type ? "QSFP" : "SFP", info->cable_temp);
+
+ if (info->sfp_type)
+ snprintf(str, CAP_INFO_MAX_LEN, "%s, rx power: %uuw %uuW %uuW %uuW",
+ cap_info, info->power[0x0], info->power[0x1],
+ info->power[0x2], info->power[0x3]);
+ else
+ snprintf(str, CAP_INFO_MAX_LEN, "%s, rx power: %uuW, tx power: %uuW",
+ cap_info, info->power[0x0], info->power[0x1]);
+
+ return 0;
+}
+
+static void print_cable_info(struct hinic3_nic_io *nic_io, struct mag_cmd_event_port_info *info)
+{
+ char tmp_str[CAP_INFO_MAX_LEN] = {0};
+ char tmp_vendor[DEVICE_VENDOR_MAX_LEN] = {0};
+ char *port_type = "Unknown port type";
+ int i;
+ int err = 0;
+
+ if (info->gpio_insert) {
+ sdk_info(nic_io->dev_hdl, "Cable unpresent\n");
+ return;
+ }
+
+ get_port_type(nic_io, info, &port_type);
+
+ for (i = sizeof(info->vendor_name) - 1; i >= 0; i--) {
+ if (info->vendor_name[i] == ' ')
+ info->vendor_name[i] = '\0';
+ else
+ break;
+ }
+
+ memcpy(tmp_vendor, info->vendor_name, sizeof(info->vendor_name));
+ snprintf(tmp_str, CAP_INFO_MAX_LEN, "Vendor: %s, %s, length: %um, max_speed: %uGbps",
+ tmp_vendor, port_type, info->cable_length, info->max_speed);
+
+ if (info->port_type == LINK_PORT_OPTICAL_MM ||
+ info->port_type == LINK_PORT_AOC) {
+ err = get_port_temperature_power(info, tmp_str);
+ if (err)
+ return;
+ }
+
+ sdk_info(nic_io->dev_hdl, "Cable information: %s\n", tmp_str);
+}
+
+static void print_link_info(struct hinic3_nic_io *nic_io,
+ struct mag_cmd_event_port_info *info,
+ enum hinic3_nic_event_type type)
+{
+ char *fec = "None";
+ char *speed = "None";
+ char *an_state = "None";
+
+ if (info->fec < HILINK_FEC_MAX_TYPE)
+ fec = g_hw_to_char_fec[info->fec];
+ else
+ sdk_info(nic_io->dev_hdl, "Unknown fec type: %u\n", info->fec);
+
+ if (info->an_state > PORT_CFG_AN_OFF) {
+ sdk_info(nic_io->dev_hdl, "an_state %d is invalid",
+ info->an_state);
+ return;
+ }
+
+ an_state = g_hw_to_an_state_info[info->an_state];
+
+ if (info->speed >= PORT_SPEED_UNKNOWN) {
+ sdk_info(nic_io->dev_hdl, "speed %u is invalid", info->speed);
+ return;
+ }
+
+ speed = g_hw_to_speed_info[info->speed];
+ sdk_info(nic_io->dev_hdl, "Link information: speed %s, %s, autoneg %s",
+ speed, fec, an_state);
+}
+
+void print_port_info(struct hinic3_nic_io *nic_io,
+ struct mag_cmd_event_port_info *port_info,
+ enum hinic3_nic_event_type type)
+{
+ print_cable_info(nic_io, port_info);
+
+ print_link_info(nic_io, port_info, type);
+
+ if (type == EVENT_NIC_LINK_UP)
+ return;
+
+ sdk_info(nic_io->dev_hdl, "PMA ctrl: %s, tx %s, rx %s, PMA fifo reg: 0x%x, PMA signal ok reg: 0x%x, RF/LF status reg: 0x%x\n",
+ port_info->pma_ctrl == 1 ? "off" : "on",
+ port_info->tx_enable ? "enable" : "disable",
+ port_info->rx_enable ? "enable" : "disable", port_info->pma_fifo_reg,
+ port_info->pma_signal_ok_reg, port_info->rf_lf);
+ sdk_info(nic_io->dev_hdl, "alos: %u, rx_los: %u, PCS 64 66b reg: 0x%x, PCS link: 0x%x, MAC link: 0x%x PCS_err_cnt: 0x%x\n",
+ port_info->alos, port_info->rx_los, port_info->pcs_64_66b_reg,
+ port_info->pcs_link, port_info->pcs_mac_link,
+ port_info->pcs_err_cnt);
+ sdk_info(nic_io->dev_hdl, "his_link_machine_state = 0x%08x, cur_link_machine_state = 0x%08x\n",
+ port_info->his_link_machine_state,
+ port_info->cur_link_machine_state);
+}
+
static int hinic3_get_vf_link_status_msg_handler(struct hinic3_nic_io *nic_io,
u16 vf_id, void *buf_in,
u16 in_size, void *buf_out,
@@ -433,6 +682,10 @@ static void get_port_info(void *hwdev,
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
if (hinic3_func_type(hwdev) != TYPE_VF && link_status->status) {
err = hinic3_get_port_info(hwdev, &port_info, HINIC3_CHANNEL_NIC);
if (err) {
@@ -457,8 +710,18 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
struct hinic3_event_info event_info = {0};
struct hinic3_event_link_info *link_info = (void *)event_info.event_data;
struct hinic3_nic_io *nic_io = NULL;
+#ifndef __UEFI__
+ struct pci_dev *pdev = NULL;
+#endif
+ /* Ignore link change event */
+ if (hinic3_is_bm_slave_host(hwdev))
+ return;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
link_status = buf_in;
sdk_info(nic_io->dev_hdl, "Link status report received, func_id: %u, status: %u\n",
@@ -475,6 +738,15 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
hinic3_event_callback(hwdev, &event_info);
+#ifndef __UEFI__
+ if (nic_io->pcidev_hdl) {
+ pdev = nic_io->pcidev_hdl;
+ if (pdev->subsystem_device == BIFUR_RESOURCE_PF_SSID) {
+ return;
+ }
+ }
+#endif
+
if (hinic3_func_type(hwdev) != TYPE_VF) {
hinic3_notify_all_vfs_link_changed(hwdev, link_status->status);
ret_link_status = buf_out;
@@ -483,20 +755,142 @@ static void link_status_event_handler(void *hwdev, void *buf_in,
}
}
+static void port_info_event_printf(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct mag_cmd_event_port_info *port_info = buf_in;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct hinic3_event_info event_info;
+ enum hinic3_nic_event_type type;
+
+ if (!hwdev) {
+ pr_err("hwdev is NULL\n");
+ return;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
+
+ if (in_size != sizeof(*port_info)) {
+ sdk_info(nic_io->dev_hdl, "Invalid port info message size %d, should be %ld\n",
+ in_size, sizeof(*port_info));
+ return;
+ }
+
+ ((struct mag_cmd_event_port_info *)buf_out)->head.status = 0;
+
+ type = port_info->event_type;
+ if (type < EVENT_NIC_LINK_DOWN || type > EVENT_NIC_LINK_UP) {
+ sdk_info(nic_io->dev_hdl, "Invalid hilink info report, type: %d\n",
+ type);
+ return;
+ }
+
+ print_port_info(nic_io, port_info, type);
+
+ memset(&event_info, 0, sizeof(event_info));
+ event_info.service = EVENT_SRV_NIC;
+ event_info.type = type;
+
+ *out_size = sizeof(*port_info);
+
+ hinic3_event_callback(hwdev, &event_info);
+}
+
+void hinic3_notify_vf_bond_status(struct hinic3_nic_io *nic_io,
+ u16 vf_id, u8 bond_status)
+{
+ struct mag_cmd_get_bond_status bond;
+ struct vf_data_storage *vf_infos = nic_io->vf_infos;
+ u16 out_size = sizeof(bond);
+ int err;
+
+ memset(&bond, 0, sizeof(bond));
+ if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) {
+ bond.status = bond_status;
+ err = hinic3_mbox_to_vf_no_ack(nic_io->hwdev, vf_id,
+ HINIC3_MOD_HILINK,
+ MAG_CMD_GET_BOND_STATUS, &bond,
+ sizeof(bond), &bond, &out_size,
+ HINIC3_CHANNEL_NIC);
+ if (err == MBOX_ERRCODE_UNKNOWN_DES_FUNC) {
+ nic_warn(nic_io->dev_hdl, "VF %u not initialized, disconnect it\n",
+ HW_VF_ID_TO_OS(vf_id));
+ hinic3_unregister_vf(nic_io, vf_id);
+ return;
+ }
+ if (err || !out_size || bond.head.status)
+ nic_err(nic_io->dev_hdl,
+ "Send bond change event to VF %hu failed, err: %d, status: 0x%x, out_size: 0x%x\n",
+ HW_VF_ID_TO_OS(vf_id), err, bond.head.status,
+ out_size);
+ }
+}
+
+void hinic3_notify_all_vfs_bond_changed(void *hwdev, u8 bond_status)
+{
+ struct hinic3_nic_io *nic_io = NULL;
+ u16 i;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ nic_io->link_status = bond_status;
+ for (i = 1; i <= nic_io->max_vfs; i++)
+ hinic3_notify_vf_bond_status(nic_io, i, bond_status);
+}
+
+static void bond_status_event_handler(void *hwdev, void *buf_in,
+ u16 in_size, void *buf_out, u16 *out_size)
+{
+ struct mag_cmd_get_bond_status *bond_status = NULL;
+ struct hinic3_event_info event_info = {};
+ struct hinic3_nic_io *nic_io = NULL;
+ struct mag_cmd_get_bond_status *ret_bond_status = NULL;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+
+ bond_status = (struct mag_cmd_get_bond_status *)buf_in;
+ sdk_info(nic_io->dev_hdl, "bond status report received, func_id: %u, status: %u\n",
+ hinic3_global_func_id(hwdev), bond_status->status);
+
+ event_info.service = EVENT_SRV_NIC;
+ event_info.type = bond_status->status ?
+ EVENT_NIC_BOND_UP : EVENT_NIC_BOND_DOWN;
+
+ hinic3_event_callback(hwdev, &event_info);
+
+ if (hinic3_func_type(hwdev) != TYPE_VF) {
+ hinic3_notify_all_vfs_bond_changed(hwdev, bond_status->status);
+ ret_bond_status = buf_out;
+ ret_bond_status->head.status = 0;
+ *out_size = sizeof(*ret_bond_status);
+ }
+}
+
static void cable_plug_event(void *hwdev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
struct mag_cmd_wire_event *plug_event = buf_in;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
struct hinic3_nic_io *nic_io = NULL;
struct hinic3_event_info event_info;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
+
rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
rt_cmd->mpu_send_sfp_abs = false;
rt_cmd->mpu_send_sfp_info = false;
+ rt_cmd_ext->mpu_send_xsfp_tlv_info = false;
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
memset(&event_info, 0, sizeof(event_info));
@@ -518,9 +912,12 @@ static void port_sfp_info_event(void *hwdev, void *buf_in, u16 in_size,
{
struct mag_cmd_get_xsfp_info *sfp_info = buf_in;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
if (in_size != sizeof(*sfp_info)) {
sdk_err(nic_io->dev_hdl, "Invalid sfp info cmd, length: %u, should be %ld\n",
in_size, sizeof(*sfp_info));
@@ -528,10 +925,41 @@ static void port_sfp_info_event(void *hwdev, void *buf_in, u16 in_size,
}
rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
memcpy(&rt_cmd->std_sfp_info, sfp_info,
sizeof(struct mag_cmd_get_xsfp_info));
rt_cmd->mpu_send_sfp_info = true;
+ rt_cmd_ext->mpu_send_xsfp_tlv_info = false;
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+}
+
+static void port_xsfp_tlv_info_event(void *hwdev, void *buf_in, u16 in_size,
+ void *buf_out, u16 *out_size)
+{
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp *xsfp_tlv_info = buf_in;
+ struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
+ size_t cpy_len = in_size - sizeof(struct mgmt_msg_head) -
+ XSFP_TLV_PRE_INFO_LEN;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
+
+ if (cpy_len > XSFP_CMIS_INFO_MAX_SIZE) {
+ sdk_err(nic_io->dev_hdl, "invalid cpy_len(%lu)\n", cpy_len);
+ return;
+ }
+ rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
+ mutex_lock(&nic_io->nic_cfg.sfp_mutex);
+ rt_cmd_ext->std_xsfp_tlv_info.port_id = xsfp_tlv_info->port_id;
+ memcpy(&rt_cmd_ext->std_xsfp_tlv_info.tlv_buf[0],
+ &xsfp_tlv_info->tlv_buf[0], cpy_len);
+ rt_cmd->mpu_send_sfp_info = false;
+ rt_cmd_ext->mpu_send_xsfp_tlv_info = true;
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
}
@@ -543,6 +971,8 @@ static void port_sfp_abs_event(void *hwdev, void *buf_in, u16 in_size,
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
if (in_size != sizeof(*sfp_abs)) {
sdk_err(nic_io->dev_hdl, "Invalid sfp absent cmd, length: %u, should be %ld\n",
in_size, sizeof(*sfp_abs));
@@ -564,9 +994,11 @@ bool hinic3_if_sfp_absent(void *hwdev)
u8 port_id = hinic3_physical_port_id(hwdev);
u16 out_size = sizeof(sfp_abs);
int err;
- bool sfp_abs_status;
+ bool sfp_abs_status = 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return true;
memset(&sfp_abs, 0, sizeof(sfp_abs));
rt_cmd = &nic_io->nic_cfg.rt_cmd;
@@ -597,10 +1029,184 @@ bool hinic3_if_sfp_absent(void *hwdev)
return (sfp_abs.abs_status == 0 ? false : true);
}
+int hinic3_get_sfp_tlv_info(void *hwdev, struct drv_tag_mag_cmd_get_xsfp_tlv_rsp
+ *sfp_tlv_info,
+ const struct tag_mag_cmd_get_xsfp_tlv_req
+ *sfp_tlv_info_req)
+{
+ struct hinic3_nic_io *nic_io = NULL;
+ struct hinic3_port_routine_cmd_extern *rt_cmd_ext = NULL;
+ u16 out_size = sizeof(*sfp_tlv_info);
+ int err;
+
+ if (!hwdev || !sfp_tlv_info)
+ return -EINVAL;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ rt_cmd_ext = &nic_io->nic_cfg.rt_cmd_ext;
+ mutex_lock(&nic_io->nic_cfg.sfp_mutex);
+ if (rt_cmd_ext->mpu_send_xsfp_tlv_info) {
+ if (rt_cmd_ext->std_xsfp_tlv_info.head.status != 0) {
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+ return -EIO;
+ }
+
+ memcpy(sfp_tlv_info, &rt_cmd_ext->std_xsfp_tlv_info,
+ sizeof(*sfp_tlv_info));
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+ return 0;
+ }
+
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+
+ err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_TLV_INFO,
+ (void *)sfp_tlv_info_req,
+ sizeof(*sfp_tlv_info_req),
+ sfp_tlv_info, &out_size);
+ if (sfp_tlv_info->head.status != 0 || err != 0 || out_size == 0) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get port%u tlv sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
+ hinic3_physical_port_id(hwdev), err,
+ sfp_tlv_info->head.status, out_size);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int hinic3_trans_cmis_get_page_pos(u32 page_id, u32 content_len, u32 *pos)
+{
+ if (page_id <= QSFP_CMIS_PAGE_03H) {
+ *pos = (page_id * content_len);
+ return 0;
+ }
+
+ if (page_id == QSFP_CMIS_PAGE_11H) {
+ *pos = (QSFP_CMIS_PAGE_04H * content_len);
+ return 0;
+ }
+
+ if (page_id == QSFP_CMIS_PAGE_12H) {
+ *pos = (QSFP_CMIS_PAGE_05H * content_len);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int hinic3_get_page_key_info(struct mgmt_tlv_info *tlv_info,
+ struct parse_tlv_info *page_info, u8 idx,
+ u32 *total_len)
+{
+ u8 *src_addr = NULL;
+ u8 *dst_addr = NULL;
+ u8 *tmp_addr = NULL;
+ u32 page_id = 0;
+ u32 content_len = 0;
+ u32 src_pos = 0;
+ int ret;
+
+ page_id = MGMT_TLV_GET_U32(tlv_info->value);
+ content_len = tlv_info->length - MGMT_TLV_U32_SIZE;
+ if (page_id == QSFP_CMIS_PAGE_00H) {
+ tmp_addr = (u8 *)(tlv_info + 1);
+ page_info->id = *(tmp_addr + MGMT_TLV_U32_SIZE);
+ }
+
+ ret = hinic3_trans_cmis_get_page_pos(page_id, content_len, &src_pos);
+ if (ret != 0)
+ return ret;
+
+ src_addr = page_info->tlv_page_info + src_pos;
+ tmp_addr = (u8 *)(tlv_info + 1);
+ dst_addr = tmp_addr + MGMT_TLV_U32_SIZE;
+ memcpy(src_addr, dst_addr, content_len);
+
+ if (idx < XSFP_CMIS_PARSE_PAGE_NUM)
+ page_info->tlv_page_num[idx] = page_id;
+
+ *total_len += content_len;
+
+ return 0;
+}
+
+static int hinic3_trans_cmis_tlv_info_to_buf(u8 *sfp_tlv_info,
+ struct parse_tlv_info *page_info)
+{
+ struct mgmt_tlv_info *tlv_info = NULL;
+ u8 *tlv_buf = sfp_tlv_info;
+ u8 idx = 0;
+ u32 total_len = 0;
+ int ret = 0;
+ bool need_continue = true;
+
+ if (!sfp_tlv_info || !page_info)
+ return -EIO;
+
+ while (need_continue) {
+ tlv_info = (struct mgmt_tlv_info *)tlv_buf;
+ switch (tlv_info->type) {
+ case MAG_XSFP_TYPE_PAGE:
+ ret = hinic3_get_page_key_info(tlv_info, page_info,
+ idx, &total_len);
+ if (ret != 0) {
+ pr_err("lib_get_page_key_info fail,ret:0x%x.\n",
+ ret);
+ break;
+ }
+ idx++;
+ break;
+
+ case MAG_XSFP_TYPE_WIRE_TYPE:
+ page_info->wire_type = MGMT_TLV_GET_U32(&tlv_info->value);
+ break;
+
+ case MAG_XSFP_TYPE_END:
+ need_continue = false;
+ break;
+
+ default:
+ break;
+ }
+
+ tlv_buf += (sizeof(struct mgmt_tlv_info) + tlv_info->length);
+ }
+
+ page_info->tlv_page_info_len = total_len;
+
+ return 0;
+}
+
+int hinic3_get_tlv_xsfp_eeprom(void *hwdev, u8 *data, u32 len)
+{
+ int err = 0;
+ struct tag_mag_cmd_get_xsfp_tlv_req xsfp_tlv_info_req = {0};
+
+ xsfp_tlv_info_req.rsp_buf_len = XSFP_CMIS_INFO_MAX_SIZE;
+ xsfp_tlv_info_req.port_id = hinic3_physical_port_id(hwdev);
+ err = hinic3_get_sfp_tlv_info(hwdev, &g_xsfp_tlv_info,
+ &xsfp_tlv_info_req);
+ if (err != 0)
+ return err;
+
+ err = hinic3_trans_cmis_tlv_info_to_buf(g_xsfp_tlv_info.tlv_buf,
+ &g_page_info);
+ if (err)
+ return -ENOMEM;
+
+ memcpy(data, g_page_info.tlv_page_info, len);
+
+ return (err == 0) ? 0 : -ENOMEM;
+}
+
int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info)
{
struct hinic3_nic_io *nic_io = NULL;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
+ u8 sfp_info_status = 0;
u16 out_size = sizeof(*sfp_info);
int err;
@@ -608,13 +1214,17 @@ int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
rt_cmd = &nic_io->nic_cfg.rt_cmd;
+ sfp_info_status = rt_cmd->std_sfp_info.head.status;
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
if (rt_cmd->mpu_send_sfp_info) {
- if (rt_cmd->std_sfp_info.head.status) {
+ if (sfp_info_status != 0) {
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
- return -EIO;
+ return (sfp_info_status == HINIC3_MGMT_CMD_UNSUPPORTED)
+ ? HINIC3_MGMT_CMD_UNSUPPORTED : -EIO;
}
memcpy(sfp_info, &rt_cmd->std_sfp_info, sizeof(*sfp_info));
@@ -626,7 +1236,12 @@ int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info)
sfp_info->port_id = hinic3_physical_port_id(hwdev);
err = mag_msg_to_mgmt_sync(hwdev, MAG_CMD_GET_XSFP_INFO, sfp_info,
sizeof(*sfp_info), sfp_info, &out_size);
- if (sfp_info->head.status || err || !out_size) {
+ if (sfp_info->head.status == HINIC3_MGMT_CMD_UNSUPPORTED)
+ return HINIC3_MGMT_CMD_UNSUPPORTED;
+
+ if (sfp_info->head.status == HINIC3_MGMT_CMD_UNSUPPORTED)
+ return -EOPNOTSUPP;
+ if (sfp_info->head.status != 0 || err != 0 || out_size == 0) {
nic_err(nic_io->dev_hdl,
"Failed to get port%u sfp eeprom information, err: %d, status: 0x%x, out size: 0x%x\n",
hinic3_physical_port_id(hwdev), err,
@@ -642,7 +1257,7 @@ int hinic3_get_sfp_eeprom(void *hwdev, u8 *data, u32 len)
struct mag_cmd_get_xsfp_info sfp_info;
int err;
- if (!hwdev || !data)
+ if (!hwdev || !data || len > PAGE_SIZE)
return -EINVAL;
if (hinic3_if_sfp_absent(hwdev))
@@ -654,7 +1269,7 @@ int hinic3_get_sfp_eeprom(void *hwdev, u8 *data, u32 len)
if (err)
return err;
- memcpy(data, sfp_info.sfp_info, len);
+ memcpy(data, sfp_info.sfp_info, sizeof(sfp_info.sfp_info));
return 0;
}
@@ -664,7 +1279,7 @@ int hinic3_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext)
struct hinic3_nic_io *nic_io = NULL;
struct hinic3_port_routine_cmd *rt_cmd = NULL;
u8 sfp_data[STD_SFP_INFO_MAX_SIZE];
- int err;
+ int err = 0;
if (!hwdev || !sfp_type || !sfp_type_ext)
return -EINVAL;
@@ -677,20 +1292,35 @@ int hinic3_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext)
mutex_lock(&nic_io->nic_cfg.sfp_mutex);
if (rt_cmd->mpu_send_sfp_info) {
- if (rt_cmd->std_sfp_info.head.status) {
+ if (rt_cmd->std_sfp_info.head.status == 0) {
+ *sfp_type = rt_cmd->std_sfp_info.sfp_info[0];
+ *sfp_type_ext = rt_cmd->std_sfp_info.sfp_info[1];
+ mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
+ return 0;
+ }
+
+ if (rt_cmd->std_sfp_info.head.status != HINIC3_MGMT_CMD_UNSUPPORTED) {
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
return -EIO;
}
- *sfp_type = rt_cmd->std_sfp_info.sfp_info[0];
- *sfp_type_ext = rt_cmd->std_sfp_info.sfp_info[1];
- mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
- return 0;
+ err = HINIC3_MGMT_CMD_UNSUPPORTED; /* cmis */
}
mutex_unlock(&nic_io->nic_cfg.sfp_mutex);
- err = hinic3_get_sfp_eeprom(hwdev, (u8 *)sfp_data,
- STD_SFP_INFO_MAX_SIZE);
+ if (err == 0) {
+ err = hinic3_get_sfp_eeprom(hwdev, (u8 *)sfp_data,
+ STD_SFP_INFO_MAX_SIZE);
+ } else {
+ /* mpu_send_sfp_info is false */
+ err = hinic3_get_tlv_xsfp_eeprom(hwdev, (u8 *)sfp_data,
+ STD_SFP_INFO_MAX_SIZE);
+ }
+
+ if (err == HINIC3_MGMT_CMD_UNSUPPORTED)
+ err = hinic3_get_tlv_xsfp_eeprom(hwdev, (u8 *)sfp_data,
+ STD_SFP_INFO_MAX_SIZE);
+
if (err)
return err;
@@ -796,16 +1426,23 @@ int hinic3_set_pf_bw_limit(void *hwdev, u32 bw_limit)
return -EINVAL;
}
- old_bw_limit = nic_io->nic_cfg.pf_bw_limit;
- nic_io->nic_cfg.pf_bw_limit = bw_limit;
+ if (nic_io->direct == HINIC3_NIC_TX) {
+ old_bw_limit = nic_io->nic_cfg.pf_bw_tx_limit;
+ nic_io->nic_cfg.pf_bw_tx_limit = bw_limit;
+ } else {
+ old_bw_limit = nic_io->nic_cfg.pf_bw_rx_limit;
+ nic_io->nic_cfg.pf_bw_rx_limit = bw_limit;
+ }
err = hinic3_update_pf_bw(hwdev);
if (err) {
- nic_io->nic_cfg.pf_bw_limit = old_bw_limit;
- return err;
+ if (nic_io->direct == HINIC3_NIC_TX)
+ nic_io->nic_cfg.pf_bw_tx_limit = old_bw_limit;
+ else
+ nic_io->nic_cfg.pf_bw_rx_limit = old_bw_limit;
}
- return 0;
+ return err;
}
static const struct vf_msg_handler vf_mag_cmd_handler[] = {
@@ -828,6 +1465,9 @@ int hinic3_pf_mag_mbox_handler(void *hwdev, u16 vf_id,
return -EFAULT;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
for (index = 0; index < cmd_size; index++) {
handler = &vf_mag_cmd_handler[index];
@@ -848,6 +1488,11 @@ static struct nic_event_handler mag_cmd_handler[] = {
.handler = link_status_event_handler,
},
+ {
+ .cmd = MAG_CMD_EVENT_PORT_INFO,
+ .handler = port_info_event_printf,
+ },
+
{
.cmd = MAG_CMD_WIRE_EVENT,
.handler = cable_plug_event,
@@ -862,6 +1507,16 @@ static struct nic_event_handler mag_cmd_handler[] = {
.cmd = MAG_CMD_GET_XSFP_PRESENT,
.handler = port_sfp_abs_event,
},
+
+ {
+ .cmd = MAG_CMD_GET_BOND_STATUS,
+ .handler = bond_status_event_handler,
+ },
+
+ {
+ .cmd = MAG_CMD_GET_XSFP_TLV_INFO,
+ .handler = port_xsfp_tlv_info_event,
+ },
};
static int hinic3_mag_event_handler(void *hwdev, u16 cmd,
@@ -877,6 +1532,9 @@ static int hinic3_mag_event_handler(void *hwdev, u16 cmd,
*out_size = 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
for (i = 0; i < size; i++) {
if (cmd == mag_cmd_handler[i].cmd) {
mag_cmd_handler[i].handler(hwdev, buf_in, in_size,
@@ -917,7 +1575,8 @@ static int _mag_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in,
u32 i, cmd_cnt = ARRAY_LEN(vf_mag_cmd_handler);
bool cmd_to_pf = false;
- if (hinic3_func_type(hwdev) == TYPE_VF) {
+ if (hinic3_func_type(hwdev) == TYPE_VF &&
+ !hinic3_is_slave_host(hwdev)) {
for (i = 0; i < cmd_cnt; i++) {
if (cmd == vf_mag_cmd_handler[i].cmd) {
cmd_to_pf = true;
@@ -949,3 +1608,123 @@ static int mag_msg_to_mgmt_sync_ch(void *hwdev, u16 cmd, void *buf_in,
return _mag_msg_to_mgmt_sync(hwdev, cmd, buf_in, in_size, buf_out,
out_size, channel);
}
+
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+struct fecparam_value_map {
+ u8 hinic3_fec_offset;
+ u8 hinic3_fec_value;
+ u8 ethtool_fec_value;
+};
+
+static void fecparam_convert(u32 opcode, u8 in_fec_param, u8 *out_fec_param)
+{
+ u8 i;
+ u8 fec_value_table_lenth;
+ struct fecparam_value_map fec_value_table[] = {
+ {PORT_FEC_NOT_SET, BIT(PORT_FEC_NOT_SET), ETHTOOL_FEC_NONE},
+ {PORT_FEC_RSFEC, BIT(PORT_FEC_RSFEC), ETHTOOL_FEC_RS},
+ {PORT_FEC_BASEFEC, BIT(PORT_FEC_BASEFEC), ETHTOOL_FEC_BASER},
+ {PORT_FEC_NOFEC, BIT(PORT_FEC_NOFEC), ETHTOOL_FEC_OFF},
+#ifdef ETHTOOL_FEC_LLRS
+ {PORT_FEC_LLRSFEC, BIT(PORT_FEC_LLRSFEC), ETHTOOL_FEC_LLRS},
+#endif
+ {PORT_FEC_AUTO, BIT(PORT_FEC_AUTO), ETHTOOL_FEC_AUTO}
+ };
+
+ *out_fec_param = 0;
+ fec_value_table_lenth = (u8)(sizeof(fec_value_table) / sizeof(struct fecparam_value_map));
+
+ if (opcode == MAG_CMD_OPCODE_SET) {
+ for (i = 0; i < fec_value_table_lenth; i++) {
+ if ((in_fec_param &
+ fec_value_table[i].ethtool_fec_value) != 0)
+ /* The MPU uses the offset to determine the FEC mode. */
+ *out_fec_param =
+ fec_value_table[i].hinic3_fec_offset;
+ }
+ }
+
+ if (opcode == MAG_CMD_OPCODE_GET) {
+ for (i = 0; i < fec_value_table_lenth; i++) {
+ if ((in_fec_param &
+ fec_value_table[i].hinic3_fec_value) != 0)
+ *out_fec_param |=
+ fec_value_table[i].ethtool_fec_value;
+ }
+ }
+}
+
+/* When the ethtool is used to set the FEC mode */
+static bool check_fecparam_is_valid(u8 fec_param)
+{
+ if (fec_param == ETHTOOL_FEC_RS ||
+#ifdef ETHTOOL_FEC_LLRS
+ fec_param == ETHTOOL_FEC_LLRS ||
+#endif
+ fec_param == ETHTOOL_FEC_BASER ||
+ fec_param == ETHTOOL_FEC_OFF) {
+ return true;
+ }
+ return false;
+}
+
+int set_fecparam(void *hwdev, u8 fecparam)
+{
+ struct mag_cmd_cfg_fec_mode fec_msg = {0};
+ struct hinic3_nic_io *nic_io = NULL;
+ u16 out_size = sizeof(fec_msg);
+ u8 advertised_fec = 0;
+ int err;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ if (check_fecparam_is_valid(fecparam) == false) {
+ nic_err(nic_io->dev_hdl, "fec param is invalid, failed to set fec param\n");
+ return -EINVAL;
+ }
+ fecparam_convert(MAG_CMD_OPCODE_SET, fecparam, &advertised_fec);
+ fec_msg.opcode = MAG_CMD_OPCODE_SET;
+ fec_msg.port_id = hinic3_physical_port_id(hwdev);
+ fec_msg.advertised_fec = advertised_fec;
+ err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_CFG_FEC_MODE,
+ &fec_msg, sizeof(fec_msg),
+ &fec_msg, &out_size, HINIC3_CHANNEL_NIC);
+ if (err != 0 || fec_msg.head.status != 0)
+ return -EINVAL;
+ return 0;
+}
+
+int get_fecparam(void *hwdev, u8 *advertised_fec, u8 *supported_fec)
+{
+ struct mag_cmd_cfg_fec_mode fec_msg = {0};
+ struct hinic3_nic_io *nic_io = NULL;
+ u16 out_size = sizeof(fec_msg);
+ int err;
+
+ if (!hwdev)
+ return -EINVAL;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ fec_msg.opcode = MAG_CMD_OPCODE_GET;
+ fec_msg.port_id = hinic3_physical_port_id(hwdev);
+ err = mag_msg_to_mgmt_sync_ch(hwdev, MAG_CMD_CFG_FEC_MODE,
+ &fec_msg, sizeof(fec_msg),
+ &fec_msg, &out_size, HINIC3_CHANNEL_NIC);
+ if (err != 0 || fec_msg.head.status != 0)
+ return -EINVAL;
+
+ /* fec_msg.advertised_fec: bit offset,
+ *value is BIT(fec_msg.advertised_fec); fec_msg.supported_fec: value
+ */
+ fecparam_convert(MAG_CMD_OPCODE_GET, BIT(fec_msg.advertised_fec),
+ advertised_fec);
+ fecparam_convert(MAG_CMD_OPCODE_GET, fec_msg.supported_fec,
+ supported_fec);
+ return 0;
+}
+#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
index 6f90c86..d240a53 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_main.c
@@ -20,6 +20,9 @@
#include <linux/debugfs.h>
#include "ossl_knl.h"
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+#include <net/udp_tunnel.h>
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
#include "hinic3_hw.h"
#include "hinic3_crm.h"
#include "hinic3_mt.h"
@@ -35,8 +38,8 @@
#include "hinic3_dcb.h"
#include "hinic3_nic_prof.h"
#include "hinic3_profile.h"
+#include "hinic3_bond.h"
-/*lint -e806*/
#define DEFAULT_POLL_WEIGHT 64
static unsigned int poll_weight = DEFAULT_POLL_WEIGHT;
module_param(poll_weight, uint, 0444);
@@ -68,7 +71,9 @@ static unsigned char set_link_status_follow = HINIC3_LINK_FOLLOW_STATUS_MAX;
module_param(set_link_status_follow, byte, 0444);
MODULE_PARM_DESC(set_link_status_follow, "Set link status follow port status (0=default,1=follow,2=separate,3=unset");
-/*lint +e806*/
+static bool page_pool_enabled = true;
+module_param(page_pool_enabled, bool, 0444);
+MODULE_PARM_DESC(page_pool_enabled, "enable/disable page_pool feature for rxq page management (default enable)");
#define HINIC3_NIC_DEV_WQ_NAME "hinic3_nic_dev_wq"
@@ -80,6 +85,8 @@ MODULE_PARM_DESC(set_link_status_follow, "Set link status follow port status (0=
#define HINIC3_SQ_DEPTH 1024
#define HINIC3_RQ_DEPTH 1024
+#define LRO_ENABLE 1
+
enum hinic3_rx_buff_len {
RX_BUFF_VALID_2KB = 2,
RX_BUFF_VALID_4KB = 4,
@@ -87,12 +94,15 @@ enum hinic3_rx_buff_len {
RX_BUFF_VALID_16KB = 16,
};
+#define NIC_MAX_PF_NUM 32
+
#define CONVERT_UNIT 1024
-#define BIFUR_RESOURCE_PF_SSID 0x5a1
+#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);
+static int hinic3_netdev_event(struct notifier_block *notifier,
+ unsigned long event, void *ptr);
/* used for netdev notifier register/unregister */
static DEFINE_MUTEX(hinic3_netdev_notifiers_mutex);
@@ -101,6 +111,17 @@ static struct notifier_block hinic3_netdev_notifier = {
.notifier_call = hinic3_netdev_event,
};
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+static const struct udp_tunnel_nic_info hinic3_udp_tunnels = {
+ .set_port = hinic3_udp_tunnel_set_port,
+ .unset_port = hinic3_udp_tunnel_unset_port,
+ .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP,
+ .tables = {
+ { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, },
+ },
+};
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
static void hinic3_register_notifier(struct hinic3_nic_dev *nic_dev)
{
int err;
@@ -134,7 +155,8 @@ static void hinic3_unregister_notifier(struct hinic3_nic_dev *nic_dev)
NETIF_F_SCTP_CRC | NETIF_F_RXCSUM | \
NETIF_F_ALL_TSO)
-static int hinic3_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr)
+static int hinic3_netdev_event(struct notifier_block *notifier,
+ unsigned long event, void *ptr)
{
struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
struct net_device *real_dev = NULL;
@@ -266,6 +288,11 @@ static void netdev_feature_init(struct net_device *netdev)
netdev->features |= dft_fts | cso_fts | tso_fts | vlan_fts;
netdev->vlan_features |= dft_fts | cso_fts | tso_fts;
+ if (nic_dev->nic_cap.lro_enable == LRO_ENABLE) {
+ netdev->features |= NETIF_F_LRO;
+ netdev->vlan_features |= NETIF_F_LRO;
+ }
+
#ifdef HAVE_RHEL6_NET_DEVICE_OPS_EXT
hw_features |= get_netdev_hw_features(netdev);
#else
@@ -306,7 +333,8 @@ static void init_intr_coal_param(struct hinic3_nic_dev *nic_dev)
info->pending_limt = qp_pending_limit;
info->coalesce_timer_cfg = qp_coalesc_timer_cfg;
- info->resend_timer_cfg = HINIC3_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
+ info->resend_timer_cfg =
+ HINIC3_DEAULT_TXRX_MSIX_RESEND_TIMER_CFG;
info->pkt_rate_high = HINIC3_RX_RATE_HIGH;
info->rx_usecs_high = HINIC3_RX_COAL_TIME_HIGH;
@@ -350,6 +378,7 @@ static int hinic3_init_intr_coalesce(struct hinic3_nic_dev *nic_dev)
static void hinic3_free_intr_coalesce(struct hinic3_nic_dev *nic_dev)
{
kfree(nic_dev->intr_coalesce);
+ nic_dev->intr_coalesce = NULL;
}
static int hinic3_alloc_txrxqs(struct hinic3_nic_dev *nic_dev)
@@ -396,15 +425,18 @@ static void hinic3_free_txrxqs(struct hinic3_nic_dev *nic_dev)
static void hinic3_tx_rx_ops_init(struct hinic3_nic_dev *nic_dev)
{
if (HINIC3_SUPPORT_TX_COMPACT_WQE_OL(nic_dev->hwdev)) {
- nic_dev->tx_rx_ops.tx_set_wqebb_cnt = hinic3_tx_set_compact_offload_wqebb_cnt;
- nic_dev->tx_rx_ops.tx_set_wqe_task = hinic3_tx_set_compact_offload_wqe_task;
+ nic_dev->tx_rx_ops.tx_set_wqebb_cnt =
+ hinic3_tx_set_compact_offload_wqebb_cnt;
+ nic_dev->tx_rx_ops.tx_set_wqe_task =
+ hinic3_tx_set_compact_offload_wqe_task;
} else {
nic_dev->tx_rx_ops.tx_set_wqebb_cnt = hinic3_tx_set_wqebb_cnt;
nic_dev->tx_rx_ops.tx_set_wqe_task = hinic3_tx_set_wqe_task;
}
if (HINIC3_SUPPORT_RX_COMPACT_CQE(nic_dev->hwdev))
- nic_dev->tx_rx_ops.rx_get_cqe_info = hinic3_rx_get_compact_cqe_info;
+ nic_dev->tx_rx_ops.rx_get_cqe_info =
+ hinic3_rx_get_compact_cqe_info;
else
nic_dev->tx_rx_ops.rx_get_cqe_info = hinic3_rx_get_cqe_info;
}
@@ -420,53 +452,47 @@ static void hinic3_sw_deinit(struct hinic3_nic_dev *nic_dev)
HINIC3_CHANNEL_NIC);
hinic3_clear_rss_config(nic_dev);
- if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags))
- hinic3_sync_dcb_state(nic_dev->hwdev, 1, 0);
+
+ hinic3_dcb_deinit(nic_dev);
}
-static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
+static void hinic3_netdev_mtu_init(struct net_device *netdev)
+{
+ /* MTU range: 384 - 9600 */
+#ifdef HAVE_NETDEVICE_MIN_MAX_MTU
+ netdev->min_mtu = HINIC3_MIN_MTU_SIZE;
+ netdev->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
+#endif
+
+#ifdef HAVE_NETDEVICE_EXTENDED_MIN_MAX_MTU
+ netdev->extended->min_mtu = HINIC3_MIN_MTU_SIZE;
+ netdev->extended->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
+#endif
+}
+
+static int hinic3_set_default_mac(struct hinic3_nic_dev *nic_dev)
{
struct net_device *netdev = nic_dev->netdev;
u8 mac_addr[ETH_ALEN];
- u64 nic_features;
int err = 0;
- nic_features = hinic3_get_feature_cap(nic_dev->hwdev);
- /* You can update the features supported by the driver according to the
- * scenario here
- */
- nic_features &= NIC_DRV_DEFAULT_FEATURE;
- hinic3_update_nic_feature(nic_dev->hwdev, nic_features);
-
- sema_init(&nic_dev->port_state_sem, 1);
-
- err = hinic3_dcb_init(nic_dev);
- if (err) {
- nic_err(&nic_dev->pdev->dev, "Failed to init dcb\n");
- return -EFAULT;
- }
-
- nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH;
- nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH;
-
- hinic3_try_to_enable_rss(nic_dev);
-
err = hinic3_get_default_mac(nic_dev->hwdev, mac_addr);
if (err) {
nic_err(&nic_dev->pdev->dev, "Failed to get MAC address\n");
- goto get_mac_err;
+ return err;
}
+
eth_hw_addr_set(netdev, mac_addr);
if (!is_valid_ether_addr(netdev->dev_addr)) {
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev)) {
nic_err(&nic_dev->pdev->dev, "Invalid MAC address %pM\n",
- netdev->dev_addr);
- err = -EIO;
- goto err_mac;
- }
+ netdev->dev_addr);
+ return -EIO;
+ }
- nic_info(&nic_dev->pdev->dev, "Invalid MAC address %pM, using random\n",
+ nic_info(&nic_dev->pdev->dev,
+ "Invalid MAC address %pM, using random\n",
netdev->dev_addr);
eth_hw_addr_random(netdev);
}
@@ -478,21 +504,62 @@ static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
* MAC, and we can't consider this condition is error status during
* driver probe procedure.
*/
- if (err && err != HINIC3_PF_SET_VF_ALREADY) {
+ if (err && err != HINIC3_PF_SET_VF_ALREADY)
nic_err(&nic_dev->pdev->dev, "Failed to set default MAC\n");
- goto set_mac_err;
+
+ if (err == HINIC3_PF_SET_VF_ALREADY)
+ return 0;
+
+ return err;
+}
+
+static void hinic3_outband_cfg_init(struct hinic3_nic_dev *nic_dev)
+{
+ u16 outband_default_vid = 0;
+ int err = 0;
+
+ if (!nic_dev->nic_cap.outband_vlan_cfg_en)
+ return;
+
+ err = hinic3_get_outband_vlan_cfg(nic_dev->hwdev, &outband_default_vid);
+ if (err) {
+ nic_err(&nic_dev->pdev->dev,
+ "Failed to get_outband_cfg, err: %d\n", err);
+ return;
}
- /* MTU range: 384 - 9600 */
-#ifdef HAVE_NETDEVICE_MIN_MAX_MTU
- netdev->min_mtu = HINIC3_MIN_MTU_SIZE;
- netdev->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
-#endif
+ nic_dev->outband_cfg.outband_default_vid = outband_default_vid;
+}
-#ifdef HAVE_NETDEVICE_EXTENDED_MIN_MAX_MTU
- netdev->extended->min_mtu = HINIC3_MIN_MTU_SIZE;
- netdev->extended->max_mtu = HINIC3_MAX_JUMBO_FRAME_SIZE;
-#endif
+static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
+{
+ struct net_device *netdev = nic_dev->netdev;
+ u64 nic_features;
+ int err = 0;
+
+ nic_features = hinic3_get_feature_cap(nic_dev->hwdev);
+ /* You can update the features supported by the driver according to the
+ * scenario here
+ */
+ nic_features &= NIC_DRV_DEFAULT_FEATURE;
+ hinic3_update_nic_feature(nic_dev->hwdev, nic_features);
+
+ err = hinic3_dcb_init(nic_dev);
+ if (err) {
+ nic_err(&nic_dev->pdev->dev, "Failed to init dcb\n");
+ return -EFAULT;
+ }
+
+ nic_dev->q_params.sq_depth = HINIC3_SQ_DEPTH;
+ nic_dev->q_params.rq_depth = HINIC3_RQ_DEPTH;
+
+ hinic3_try_to_enable_rss(nic_dev);
+
+ err = hinic3_set_default_mac(nic_dev);
+ if (err)
+ goto set_mac_err;
+
+ hinic3_netdev_mtu_init(netdev);
err = hinic3_alloc_txrxqs(nic_dev);
if (err) {
@@ -500,6 +567,8 @@ static int hinic3_sw_init(struct hinic3_nic_dev *nic_dev)
goto alloc_qps_err;
}
+ hinic3_outband_cfg_init(nic_dev);
+
hinic3_tx_rx_ops_init(nic_dev);
return 0;
@@ -510,8 +579,6 @@ alloc_qps_err:
HINIC3_CHANNEL_NIC);
set_mac_err:
-err_mac:
-get_mac_err:
hinic3_clear_rss_config(nic_dev);
return err;
@@ -623,7 +690,8 @@ static void calc_coal_para(struct hinic3_nic_dev *nic_dev,
*pending_limt =
(u8)((rx_rate - q_coal->pkt_rate_low) *
- (q_coal->rx_pending_limt_high - q_coal->rx_pending_limt_low) /
+ (q_coal->rx_pending_limt_high -
+ q_coal->rx_pending_limt_low) /
(q_coal->pkt_rate_high - q_coal->pkt_rate_low) +
q_coal->rx_pending_limt_low);
}
@@ -637,8 +705,10 @@ static void update_queue_coal(struct hinic3_nic_dev *nic_dev, u16 qid,
q_coal = &nic_dev->intr_coalesce[qid];
- if (rx_rate > HINIC3_RX_RATE_THRESH && avg_pkt_size > HINIC3_AVG_PKT_SMALL) {
- calc_coal_para(nic_dev, q_coal, rx_rate, &coalesc_timer_cfg, &pending_limt);
+ if (rx_rate > HINIC3_RX_RATE_THRESH &&
+ avg_pkt_size > HINIC3_AVG_PKT_SMALL) {
+ calc_coal_para(nic_dev, q_coal, rx_rate,
+ &coalesc_timer_cfg, &pending_limt);
} else {
coalesc_timer_cfg = HINIC3_LOWEST_LATENCY;
pending_limt = q_coal->rx_pending_limt_low;
@@ -701,20 +771,55 @@ void hinic3_auto_moderation_work(struct work_struct *work)
static void hinic3_periodic_work_handler(struct work_struct *work)
{
struct delayed_work *delay = to_delayed_work(work);
- struct hinic3_nic_dev *nic_dev = container_of(delay, struct hinic3_nic_dev, periodic_work);
+ struct hinic3_nic_dev *nic_dev =
+ container_of(delay, struct hinic3_nic_dev, periodic_work);
if (test_and_clear_bit(EVENT_WORK_TX_TIMEOUT, &nic_dev->event_flag))
- hinic3_fault_event_report(nic_dev->hwdev, HINIC3_FAULT_SRC_TX_TIMEOUT,
+ hinic3_fault_event_report(nic_dev->hwdev,
+ HINIC3_FAULT_SRC_TX_TIMEOUT,
FAULT_LEVEL_SERIOUS_FLR);
queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ);
}
+static void hinic3_vport_stats_work_handler(struct work_struct *work)
+{
+ int err;
+ struct hinic3_vport_stats vport_stats = {0};
+ struct delayed_work *delay = to_delayed_work(work);
+ struct hinic3_nic_dev *nic_dev = container_of(delay,
+ struct hinic3_nic_dev,
+ vport_stats_work);
+ err = hinic3_get_vport_stats(nic_dev->hwdev,
+ hinic3_global_func_id(nic_dev->hwdev),
+ &vport_stats);
+ if (err)
+ nic_err(&nic_dev->pdev->dev, "Failed to get dropped stats from fw\n");
+ else
+ nic_dev->vport_stats.rx_discard_vport =
+ vport_stats.rx_discard_vport;
+ queue_delayed_work(nic_dev->workq, &nic_dev->vport_stats_work, HZ);
+}
+
+static void free_nic_dev_vram(struct hinic3_nic_dev *nic_dev)
+{
+ int is_use_vram = get_use_vram_flag();
+
+ if (is_use_vram != 0)
+ hi_vram_kfree((void *)nic_dev->nic_vram, nic_dev->nic_vram_name,
+ sizeof(struct hinic3_vram));
+ else
+ kfree(nic_dev->nic_vram);
+ nic_dev->nic_vram = NULL;
+}
+
static void free_nic_dev(struct hinic3_nic_dev *nic_dev)
{
hinic3_deinit_nic_prof_adapter(nic_dev);
destroy_workqueue(nic_dev->workq);
kfree(nic_dev->vlan_bitmap);
+ nic_dev->vlan_bitmap = NULL;
+ free_nic_dev_vram(nic_dev);
}
static int setup_nic_dev(struct net_device *netdev,
@@ -724,6 +829,10 @@ static int setup_nic_dev(struct net_device *netdev,
struct hinic3_nic_dev *nic_dev;
char *netdev_name_fmt;
u32 page_num;
+ u16 func_id;
+ int ret;
+ int is_in_kexec = vram_get_kexec_flag();
+ int is_use_vram = get_use_vram_flag();
nic_dev = (struct hinic3_nic_dev *)netdev_priv(netdev);
nic_dev->netdev = netdev;
@@ -738,22 +847,58 @@ static int setup_nic_dev(struct net_device *netdev,
nic_dev->dma_rx_buff_size = RX_BUFF_NUM_PER_PAGE * nic_dev->rx_buff_len;
page_num = nic_dev->dma_rx_buff_size / PAGE_SIZE;
nic_dev->page_order = page_num > 0 ? ilog2(page_num) : 0;
+ nic_dev->page_pool_enabled = page_pool_enabled;
+ nic_dev->outband_cfg.outband_default_vid = 0;
+
+ // value other than 0 indicates hot replace
+ if (is_use_vram != 0) {
+ func_id = hinic3_global_func_id(nic_dev->hwdev);
+ snprintf(nic_dev->nic_vram_name, VRAM_NAME_MAX_LEN,
+ "%s%hu", VRAM_NIC_VRAM, func_id);
+
+ nic_dev->nic_vram = (struct hinic3_vram *)hi_vram_kalloc(nic_dev->nic_vram_name,
+ sizeof(struct hinic3_vram));
+ if (!nic_dev->nic_vram) {
+ nic_err(&pdev->dev, "Failed to allocate nic vram\n");
+ return -ENOMEM;
+ }
+
+ if (is_in_kexec == 0)
+ nic_dev->nic_vram->vram_mtu = netdev->mtu;
+ else
+ netdev->mtu = nic_dev->nic_vram->vram_mtu;
+ } else {
+ nic_dev->nic_vram = kzalloc(sizeof(*nic_dev->nic_vram),
+ GFP_KERNEL);
+ if (!nic_dev->nic_vram)
+ return -ENOMEM;
+
+ nic_dev->nic_vram->vram_mtu = netdev->mtu;
+ }
mutex_init(&nic_dev->nic_mutex);
nic_dev->vlan_bitmap = kzalloc(VLAN_BITMAP_SIZE(nic_dev), GFP_KERNEL);
- if (!nic_dev->vlan_bitmap)
- return -ENOMEM;
+ if (!nic_dev->vlan_bitmap) {
+ nic_err(&pdev->dev, "Failed to allocate vlan bitmap\n");
+ ret = -ENOMEM;
+ goto vlan_bitmap_error;
+ }
nic_dev->workq = create_singlethread_workqueue(HINIC3_NIC_DEV_WQ_NAME);
if (!nic_dev->workq) {
nic_err(&pdev->dev, "Failed to initialize nic workqueue\n");
- kfree(nic_dev->vlan_bitmap);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto create_workq_error;
}
- INIT_DELAYED_WORK(&nic_dev->periodic_work, hinic3_periodic_work_handler);
- INIT_DELAYED_WORK(&nic_dev->rxq_check_work, hinic3_rxq_check_work_handler);
+ INIT_DELAYED_WORK(&nic_dev->periodic_work,
+ hinic3_periodic_work_handler);
+ INIT_DELAYED_WORK(&nic_dev->rxq_check_work,
+ hinic3_rxq_check_work_handler);
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ INIT_DELAYED_WORK(&nic_dev->vport_stats_work,
+ hinic3_vport_stats_work_handler);
INIT_LIST_HEAD(&nic_dev->uc_filter_list);
INIT_LIST_HEAD(&nic_dev->mc_filter_list);
@@ -766,10 +911,23 @@ static int setup_nic_dev(struct net_device *netdev,
hinic3_init_nic_prof_adapter(nic_dev);
netdev_name_fmt = hinic3_get_dft_netdev_name_fmt(nic_dev);
- if (netdev_name_fmt)
- strscpy(netdev->name, netdev_name_fmt, IFNAMSIZ);
+ if (netdev_name_fmt) {
+ ret = strscpy(netdev->name, netdev_name_fmt, IFNAMSIZ);
+ if (ret < 0)
+ goto get_netdev_name_error;
+ }
return 0;
+
+get_netdev_name_error:
+ hinic3_deinit_nic_prof_adapter(nic_dev);
+ destroy_workqueue(nic_dev->workq);
+create_workq_error:
+ kfree(nic_dev->vlan_bitmap);
+ nic_dev->vlan_bitmap = NULL;
+vlan_bitmap_error:
+ free_nic_dev_vram(nic_dev);
+ return ret;
}
static int hinic3_set_default_hw_feature(struct hinic3_nic_dev *nic_dev)
@@ -808,6 +966,31 @@ static int hinic3_set_default_hw_feature(struct hinic3_nic_dev *nic_dev)
return 0;
}
+static void hinic3_bond_init(struct hinic3_nic_dev *nic_dev)
+{
+ u32 bond_id = HINIC3_INVALID_BOND_ID;
+ int err = hinic3_create_bond(nic_dev->hwdev, &bond_id);
+
+ if (err != 0)
+ goto bond_init_failed;
+
+ /* bond id does not change, means this pf is not bond active pf, no log is generated */
+ if (bond_id == HINIC3_INVALID_BOND_ID)
+ return;
+
+ err = hinic3_open_close_bond(nic_dev->hwdev, true);
+ if (err != 0) {
+ hinic3_delete_bond(nic_dev->hwdev);
+ goto bond_init_failed;
+ }
+
+ nic_info(&nic_dev->pdev->dev, "Bond %d init success\n", bond_id);
+ return;
+
+bond_init_failed:
+ nic_err(&nic_dev->pdev->dev, "Bond init failed\n");
+}
+
static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
char *uld_dev_name)
{
@@ -838,6 +1021,12 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
goto err_out;
}
+ err = hinic3_get_dev_cap(lld_dev->hwdev);
+ if (err != 0) {
+ nic_err(&pdev->dev, "Failed to get dev cap\n");
+ goto err_out;
+ }
+
max_qps = hinic3_func_max_nic_qnum(lld_dev->hwdev);
netdev = alloc_etherdev_mq(sizeof(*nic_dev), max_qps);
if (!netdev) {
@@ -870,10 +1059,17 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
hinic3_assign_netdev_ops(nic_dev);
netdev_feature_init(netdev);
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+ netdev->udp_tunnel_nic_info = &hinic3_udp_tunnels;
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
err = hinic3_set_default_hw_feature(nic_dev);
if (err)
goto set_features_err;
+ if (hinic3_get_bond_create_mode(lld_dev->hwdev) != 0)
+ hinic3_bond_init(nic_dev);
+
#ifdef HAVE_MULTI_VLAN_OFFLOAD_EN
hinic3_register_notifier(nic_dev);
#endif
@@ -888,6 +1084,9 @@ static int nic_probe(struct hinic3_lld_dev *lld_dev, void **uld_dev,
}
queue_delayed_work(nic_dev->workq, &nic_dev->periodic_work, HZ);
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ queue_delayed_work(nic_dev->workq,
+ &nic_dev->vport_stats_work, HZ);
netif_carrier_off(netdev);
*uld_dev = nic_dev;
@@ -920,6 +1119,25 @@ err_out:
return err;
}
+static void hinic3_bond_deinit(struct hinic3_nic_dev *nic_dev)
+{
+ int ret = 0;
+
+ ret = hinic3_open_close_bond(nic_dev->hwdev, false);
+ if (ret != 0)
+ goto bond_deinit_failed;
+
+ ret = hinic3_delete_bond(nic_dev->hwdev);
+ if (ret != 0)
+ goto bond_deinit_failed;
+
+ nic_info(&nic_dev->pdev->dev, "Bond deinit success\n");
+ return;
+
+bond_deinit_failed:
+ nic_err(&nic_dev->pdev->dev, "Bond deinit failed\n");
+}
+
static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
{
struct hinic3_nic_dev *nic_dev = adapter;
@@ -939,6 +1157,8 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
hinic3_unregister_notifier(nic_dev);
#endif
+ if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
+ cancel_delayed_work_sync(&nic_dev->vport_stats_work);
cancel_delayed_work_sync(&nic_dev->periodic_work);
cancel_delayed_work_sync(&nic_dev->rxq_check_work);
cancel_work_sync(&nic_dev->rx_mode_work);
@@ -946,6 +1166,9 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
hinic3_flush_rx_flow_rule(nic_dev);
+ if (hinic3_get_bond_create_mode(lld_dev->hwdev) != 0)
+ hinic3_bond_deinit(nic_dev);
+
hinic3_update_nic_feature(nic_dev->hwdev, 0);
hinic3_set_nic_feature_to_hw(nic_dev->hwdev);
@@ -955,6 +1178,7 @@ static void nic_remove(struct hinic3_lld_dev *lld_dev, void *adapter)
hinic3_deinit_nic_prof_adapter(nic_dev);
kfree(nic_dev->vlan_bitmap);
+ nic_dev->vlan_bitmap = NULL;
free_netdev(netdev);
@@ -971,8 +1195,10 @@ static void sriov_state_change(struct hinic3_nic_dev *nic_dev,
static void hinic3_port_module_event_handler(struct hinic3_nic_dev *nic_dev,
struct hinic3_event_info *event)
{
- const char *g_hinic3_module_link_err[LINK_ERR_NUM] = { "Unrecognized module" };
- struct hinic3_port_module_event *module_event = (void *)event->event_data;
+ const char *g_hinic3_module_link_err[LINK_ERR_NUM] = {
+ "Unrecognized module" };
+ struct hinic3_port_module_event *module_event =
+ (void *)event->event_data;
enum port_module_event_type type = module_event->type;
enum link_err_type err_type = module_event->err_type;
@@ -1003,6 +1229,116 @@ static void hinic3_port_module_event_handler(struct hinic3_nic_dev *nic_dev,
}
}
+bool hinic3_need_proc_link_event(struct hinic3_lld_dev *lld_dev)
+{
+ int ret = 0;
+ u16 func_id;
+ u8 roce_enable = false;
+ bool is_slave_func = false;
+ struct hinic3_hw_bond_infos hw_bond_infos = {0};
+
+ if (!lld_dev)
+ return false;
+
+ /* 非slave设备需要处理link down事件 */
+ ret = hinic3_is_slave_func(lld_dev->hwdev, &is_slave_func);
+ if (ret != 0) {
+ nic_err(&lld_dev->pdev->dev, "NIC get info, lld_dev is null\n");
+ return true;
+ }
+
+ if (!is_slave_func)
+ return true;
+
+ /* 未使能了vroce功能,需处理link down事件 */
+ func_id = hinic3_global_func_id(lld_dev->hwdev);
+ ret = hinic3_get_func_vroce_enable(lld_dev->hwdev, func_id, &roce_enable);
+ if (ret != 0)
+ return true;
+
+ if (!roce_enable)
+ return true;
+
+ /* 未创建bond,需要处理link down事件 */
+ hw_bond_infos.bond_id = HINIC_OVS_BOND_DEFAULT_ID;
+
+ ret = hinic3_get_hw_bond_infos(lld_dev->hwdev, &hw_bond_infos, HINIC3_CHANNEL_COMM);
+ if (ret != 0) {
+ pr_err("[ROCE, ERR] Get chipf bond info failed (%d)\n", ret);
+ return true;
+ }
+
+ if (!hw_bond_infos.valid)
+ return true;
+
+ return false;
+}
+
+bool hinic3_need_proc_bond_event(struct hinic3_lld_dev *lld_dev)
+{
+ return !hinic3_need_proc_link_event(lld_dev);
+}
+
+static void hinic_porc_bond_state_change(struct hinic3_lld_dev *lld_dev, void *adapter,
+ struct hinic3_event_info *event)
+{
+ struct hinic3_nic_dev *nic_dev = adapter;
+
+ if (!nic_dev || !event || !hinic3_support_nic(lld_dev->hwdev, NULL))
+ return;
+
+ switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_DOWN):
+ if (!hinic3_need_proc_bond_event(lld_dev)) {
+ nic_info(&lld_dev->pdev->dev, "NIC don't need proc bond event\n");
+ return;
+ }
+ nic_info(&lld_dev->pdev->dev, "NIC proc bond down\n");
+ hinic3_link_status_change(nic_dev, false);
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_UP):
+ if (!hinic3_need_proc_bond_event(lld_dev)) {
+ nic_info(&lld_dev->pdev->dev, "NIC don't need proc bond event\n");
+ return;
+ }
+ nic_info(&lld_dev->pdev->dev, "NIC proc bond up\n");
+ hinic3_link_status_change(nic_dev, true);
+ break;
+ default:
+ break;
+ }
+}
+
+static void hinic3_outband_cfg_event_handler(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_outband_cfg_info *info)
+{
+ int err = 0;
+
+ if (!nic_dev || !info || !hinic3_support_nic(nic_dev->hwdev, NULL)) {
+ pr_err("Outband cfg event invalid param\n");
+ return;
+ }
+
+ if (hinic3_func_type(nic_dev->hwdev) != TYPE_VF &&
+ info->func_id >= NIC_MAX_PF_NUM) {
+ err = hinic3_notify_vf_outband_cfg(nic_dev->hwdev,
+ info->func_id,
+ info->outband_default_vid);
+ if (err) {
+ nic_err(&nic_dev->pdev->dev,
+ "Outband cfg event notify vf err: %d, func_id: 0x%x, vid: 0x%x\n",
+ err, info->func_id, info->outband_default_vid);
+ return;
+ }
+ }
+
+ nic_info(&nic_dev->pdev->dev, "Change outband default vid from %u to %u\n",
+ nic_dev->outband_cfg.outband_default_vid,
+ info->outband_default_vid);
+
+ nic_dev->outband_cfg.outband_default_vid = info->outband_default_vid;
+}
+
static void nic_event(struct hinic3_lld_dev *lld_dev, void *adapter,
struct hinic3_event_info *event)
{
@@ -1014,21 +1350,35 @@ static void nic_event(struct hinic3_lld_dev *lld_dev, void *adapter,
switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_LINK_DOWN):
+ if (!hinic3_need_proc_link_event(lld_dev)) {
+ nic_info(&lld_dev->pdev->dev, "NIC don't need proc link event\n");
+ return;
+ }
hinic3_link_status_change(nic_dev, false);
break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_LINK_UP):
hinic3_link_status_change(nic_dev, true);
break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_DOWN):
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_BOND_UP):
+ hinic_porc_bond_state_change(lld_dev, adapter, event);
+ break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_PORT_MODULE_EVENT):
hinic3_port_module_event_handler(nic_dev, event);
break;
- case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_SRIOV_STATE_CHANGE):
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_NIC, EVENT_NIC_OUTBAND_CFG):
+ hinic3_outband_cfg_event_handler(nic_dev,
+ (void *)event->event_data);
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM,
+ EVENT_COMM_SRIOV_STATE_CHANGE):
sriov_state_change(nic_dev, (void *)event->event_data);
break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_FAULT):
fault = (void *)event->event_data;
if (fault->fault_level == FAULT_LEVEL_SERIOUS_FLR &&
- fault->event.chip.func_id == hinic3_global_func_id(lld_dev->hwdev))
+ fault->event.chip.func_id ==
+ hinic3_global_func_id(lld_dev->hwdev))
hinic3_link_status_change(nic_dev, false);
break;
case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_PCIE_LINK_DOWN):
@@ -1081,7 +1431,7 @@ struct hinic3_uld_info g_nic_uld_info = {
.resume = NULL,
.event = nic_event,
.ioctl = nic_ioctl,
-}; /*lint -e766*/
+};
struct hinic3_uld_info *get_nic_uld_info(void)
{
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h b/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h
index 94e606e..5bd4c3d 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mt.h
@@ -9,6 +9,7 @@
/* Interrupt at most records, interrupt will be recorded in the FFM */
#define NICTOOL_CMD_TYPE (0x18)
+#define HINIC3_CARD_NAME_MAX_LEN (128)
struct api_cmd_rd {
u32 pf_id;
@@ -110,7 +111,8 @@ enum dbgtool_cmd {
DBGTOOL_CMD_NUM
};
-#define PF_MAX_SIZE (16)
+#define HINIC_PF_MAX_SIZE (16)
+#define HINIC_VF_MAX_SIZE (4096)
#define BUSINFO_LEN (32)
enum module_name {
@@ -132,7 +134,8 @@ enum module_name {
SEND_TO_MIGRATE_DRIVER,
SEND_TO_PPA_DRIVER,
SEND_TO_CUSTOM_DRIVER = SEND_TO_SRV_DRV_BASE + 11,
- SEND_TO_BIFUR_DRIVER = SEND_TO_SRV_DRV_BASE + 15,
+ SEND_TO_VSOCK_DRIVER = SEND_TO_SRV_DRV_BASE + 14,
+ SEND_TO_BIFUR_DRIVER,
SEND_TO_DRIVER_MAX = SEND_TO_SRV_DRV_BASE + 16, /* reserved */
};
@@ -160,7 +163,7 @@ enum driver_cmd_type {
GET_CHIP_FAULT_STATS,
NIC_RSVD1,
NIC_RSVD2,
- NIC_RSVD3,
+ GET_OS_HOT_REPLACE_INFO,
GET_CHIP_ID,
GET_SINGLE_CARD_INFO,
GET_FIRMWARE_ACTIVE_STATUS,
@@ -171,7 +174,7 @@ enum driver_cmd_type {
GET_LOOPBACK_MODE = 32,
SET_LOOPBACK_MODE,
SET_LINK_MODE,
- SET_PF_BW_LIMIT,
+ SET_TX_PF_BW_LIMIT,
GET_PF_BW_LIMIT,
ROCE_CMD,
GET_POLL_WEIGHT,
@@ -189,6 +192,7 @@ enum driver_cmd_type {
GET_NIC_STATS_STRING,
GET_NIC_STATS_INFO,
GET_PF_ID,
+ GET_MBOX_CNT,
NIC_RSVD4,
NIC_RSVD5,
DCB_QOS_INFO,
@@ -205,6 +209,8 @@ enum driver_cmd_type {
RSS_INDIR,
PORT_ID,
+ SET_RX_PF_BW_LIMIT = 0x43,
+
GET_FUNC_CAP = 0x50,
GET_XSFP_PRESENT = 0x51,
GET_XSFP_INFO = 0x52,
@@ -216,6 +222,10 @@ enum driver_cmd_type {
WIN_CSR_WRITE = 0x62,
WIN_API_CMD_RD = 0x63,
+ GET_FUSION_Q = 0x64,
+
+ ROCE_CMD_BOND_HASH_TYPE_SET = 0xb2,
+
BIFUR_SET_ENABLE = 0xc0,
BIFUR_GET_ENABLE = 0xc1,
@@ -234,7 +244,8 @@ enum sm_cmd_type {
SM_CTR_RD64,
SM_CTR_RD32_CLEAR,
SM_CTR_RD64_PAIR_CLEAR,
- SM_CTR_RD64_CLEAR
+ SM_CTR_RD64_CLEAR,
+ SM_CTR_RD16_CLEAR,
};
struct cqm_stats {
@@ -321,10 +332,22 @@ struct pf_info {
};
struct card_info {
- struct pf_info pf[PF_MAX_SIZE];
+ struct pf_info pf[HINIC_PF_MAX_SIZE];
u32 pf_num;
};
+struct func_mbox_cnt_info {
+ char bus_info[BUSINFO_LEN];
+ u64 send_cnt;
+ u64 ack_cnt;
+};
+
+struct card_mbox_cnt_info {
+ struct func_mbox_cnt_info func_info[HINIC_PF_MAX_SIZE +
+ HINIC_VF_MAX_SIZE];
+ u32 func_num;
+};
+
struct hinic3_nic_loop_mode {
u32 loop_mode;
u32 loop_ctrl;
@@ -665,6 +688,162 @@ struct get_card_bond_msg_s {
struct bond_all_msg_s all_msg[MAX_BONDING_CNT_PER_CARD];
};
+#define MAX_FUSION_Q_STATS_STR_LEN 16
+#define MAX_FUSION_Q_NUM 256
+struct queue_status_s {
+ pid_t tgid;
+ char status[MAX_FUSION_Q_STATS_STR_LEN];
+};
+
+struct fusion_q_status_s {
+ u16 queue_num;
+ struct queue_status_s queue[MAX_FUSION_Q_NUM];
+};
+
+struct fusion_q_tx_hw_page {
+ u64 phy_addr;
+ u64 *map_addr;
+};
+
+struct fusion_sq_info {
+ u16 q_id;
+ u16 pi;
+ u16 ci; /* sw_ci */
+ u16 fi; /* hw_ci */
+ u32 q_depth;
+ u16 pi_reverse;
+ u16 wqebb_size;
+ u8 priority;
+ u16 *ci_addr;
+ u64 cla_addr;
+ void *slq_handle;
+ struct fusion_q_tx_hw_page direct_wqe;
+ struct fusion_q_tx_hw_page doorbell;
+ u32 page_idx;
+ u32 glb_sq_id;
+};
+
+struct fusion_q_tx_wqe {
+ u32 data[4];
+};
+
+struct fusion_rq_info {
+ u16 q_id;
+ u16 delta;
+ u16 hw_pi;
+ u16 ci; /* sw_ci */
+ u16 sw_pi;
+ u16 wqebb_size;
+ u16 q_depth;
+ u16 buf_len;
+
+ void *slq_handle;
+ u64 ci_wqe_page_addr;
+ u64 ci_cla_tbl_addr;
+
+ u8 coalesc_timer_cfg;
+ u8 pending_limt;
+ u16 msix_idx;
+ u32 msix_vector;
+};
+
+struct fusion_q_rx_wqe {
+ u32 data[8];
+};
+
+struct fusion_q_rx_cqe {
+ union {
+ struct {
+ unsigned int checksum_err : 16;
+ unsigned int lro_num : 8;
+ unsigned int rsvd1 : 7;
+ unsigned int rx_done : 1;
+ } bs;
+ unsigned int value;
+ } dw0;
+
+ union {
+ struct {
+ unsigned int vlan : 16;
+ unsigned int length : 16;
+ } bs;
+ unsigned int value;
+ } dw1;
+
+ union {
+ struct {
+ unsigned int pkt_types : 12;
+ unsigned int rsvd : 4;
+ unsigned int udp_0 : 1;
+ unsigned int ipv6_ex_add : 1;
+ unsigned int loopback : 1;
+ unsigned int umbcast : 2;
+ unsigned int vlan_offload_en : 1;
+ unsigned int tag_num : 2;
+ unsigned int rss_type : 8;
+ } bs;
+ unsigned int value;
+ } dw2;
+
+ union {
+ struct {
+ unsigned int rss_hash_value;
+ } bs;
+ unsigned int value;
+ } dw3;
+
+ union {
+ struct {
+ unsigned int tx_ts_seq : 16;
+ unsigned int message_1588_offset : 8;
+ unsigned int message_1588_type : 4;
+ unsigned int rsvd : 1;
+ unsigned int if_rx_ts : 1;
+ unsigned int if_tx_ts : 1;
+ unsigned int if_1588 : 1;
+ } bs;
+ unsigned int value;
+ } dw4;
+
+ union {
+ struct {
+ unsigned int ts;
+ } bs;
+ unsigned int value;
+ } dw5;
+
+ union {
+ struct {
+ unsigned int lro_ts;
+ } bs;
+ unsigned int value;
+ } dw6;
+
+ union {
+ struct {
+ unsigned int rsvd0;
+ } bs;
+ unsigned int value;
+ } dw7; /* 16Bytes Align */
+};
+
+struct os_hot_repalce_func_info {
+ char card_name[HINIC3_CARD_NAME_MAX_LEN];
+ u32 bus_num;
+ u32 valid;
+ u32 bdf;
+ int partition;
+ u16 backup_pf;
+ u16 pf_idx;
+ int port_id;
+};
+
+#define ALL_CARD_PF_NUM 2048 /* 64 card * 32 pf */
+struct os_hot_replace_info {
+ struct os_hot_repalce_func_info func_infos[ALL_CARD_PF_NUM];
+ u32 func_cnt;
+};
+
int alloc_buff_in(void *hwdev, struct msg_module *nt_msg, u32 in_size, void **buf_in);
int alloc_buff_out(void *hwdev, struct msg_module *nt_msg, u32 out_size, void **buf_out);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
index ea1d506..c4b3d5b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
@@ -15,6 +15,9 @@
#include <linux/ip.h>
#include "ossl_knl.h"
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+#include <net/udp_tunnel.h>
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
#ifdef HAVE_XDP_SUPPORT
#include <linux/bpf.h>
#endif
@@ -28,6 +31,10 @@
#include "hinic3_dcb.h"
#include "hinic3_nic_prof.h"
+#include "nic_npu_cmd.h"
+
+#include "vram_common.h"
+
#define HINIC3_DEFAULT_RX_CSUM_OFFLOAD 0xFFF
#define HINIC3_LRO_DEFAULT_COAL_PKT_SIZE 32
@@ -47,8 +54,62 @@ static void hinic3_nic_set_rx_mode(struct net_device *netdev)
queue_work(nic_dev->workq, &nic_dev->rx_mode_work);
}
+static void hinic3_free_irq_vram(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_dyna_txrxq_params *in_q_params)
+{
+ u32 size;
+ int is_use_vram = get_use_vram_flag();
+ struct hinic3_dyna_txrxq_params q_params = nic_dev->q_params;
+
+ if (!q_params.irq_cfg)
+ return;
+
+ size = sizeof(struct hinic3_irq) * (q_params.num_qps);
+
+ if (is_use_vram != 0) {
+ hi_vram_kfree((void *)q_params.irq_cfg, q_params.irq_cfg_vram_name, size);
+ q_params.irq_cfg = NULL;
+ } else {
+ kfree(in_q_params->irq_cfg);
+ in_q_params->irq_cfg = NULL;
+ }
+}
+
+static int hinic3_alloc_irq_vram(struct hinic3_nic_dev *nic_dev,
+ struct hinic3_dyna_txrxq_params *q_params,
+ bool is_up_eth)
+{
+ u32 size;
+ int is_use_vram = get_use_vram_flag();
+ u16 func_id;
+
+ size = sizeof(struct hinic3_irq) * q_params->num_qps;
+
+ if (is_use_vram != 0) {
+ func_id = hinic3_global_func_id(nic_dev->hwdev);
+ snprintf(q_params->irq_cfg_vram_name, VRAM_NAME_MAX_LEN,
+ "%s%hu", VRAM_NIC_IRQ_VRAM, func_id);
+ q_params->irq_cfg = (struct hinic3_irq *)hi_vram_kalloc(q_params->irq_cfg_vram_name,
+ size);
+ if (!q_params->irq_cfg) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "NIC irq vram alloc failed.\n");
+ return -ENOMEM;
+ }
+ /* in order to clear napi stored in vram, irq need to init when eth up */
+ if (is_up_eth)
+ memset(q_params->irq_cfg, 0, size);
+ } else {
+ q_params->irq_cfg = kzalloc(size, GFP_KERNEL);
+ if (!q_params->irq_cfg)
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
static int hinic3_alloc_txrxq_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_txrxq_params *q_params)
+ struct hinic3_dyna_txrxq_params *q_params,
+ bool is_up_eth)
{
u32 size;
int err;
@@ -70,12 +131,9 @@ static int hinic3_alloc_txrxq_resources(struct hinic3_nic_dev *nic_dev,
goto alloc_rxqs_res_arr_err;
}
- size = sizeof(*q_params->irq_cfg) * q_params->num_qps;
- q_params->irq_cfg = kzalloc(size, GFP_KERNEL);
- if (!q_params->irq_cfg) {
- nicif_err(nic_dev, drv, nic_dev->netdev,
- "Failed to alloc irq resource array\n");
- err = -ENOMEM;
+ err = hinic3_alloc_irq_vram(nic_dev, q_params, is_up_eth);
+ if (err != 0) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc irq resource array\n");
goto alloc_irq_cfg_err;
}
@@ -102,8 +160,7 @@ alloc_rxqs_res_err:
q_params->txqs_res);
alloc_txqs_res_err:
- kfree(q_params->irq_cfg);
- q_params->irq_cfg = NULL;
+ hinic3_free_irq_vram(nic_dev, q_params);
alloc_irq_cfg_err:
kfree(q_params->rxqs_res);
@@ -117,15 +174,17 @@ alloc_rxqs_res_arr_err:
}
static void hinic3_free_txrxq_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_txrxq_params *q_params)
+ struct hinic3_dyna_txrxq_params *q_params)
{
+ int is_in_kexec = vram_get_kexec_flag();
+
hinic3_free_rxqs_res(nic_dev, q_params->num_qps, q_params->rq_depth,
q_params->rxqs_res);
hinic3_free_txqs_res(nic_dev, q_params->num_qps, q_params->sq_depth,
q_params->txqs_res);
- kfree(q_params->irq_cfg);
- q_params->irq_cfg = NULL;
+ if (is_in_kexec == 0)
+ hinic3_free_irq_vram(nic_dev, q_params);
kfree(q_params->rxqs_res);
q_params->rxqs_res = NULL;
@@ -161,6 +220,7 @@ static int hinic3_configure_txrxqs(struct hinic3_nic_dev *nic_dev,
static void config_dcb_qps_map(struct hinic3_nic_dev *nic_dev)
{
struct net_device *netdev = nic_dev->netdev;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u8 num_cos;
if (!test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
@@ -171,12 +231,13 @@ static void config_dcb_qps_map(struct hinic3_nic_dev *nic_dev)
num_cos = hinic3_get_dev_user_cos_num(nic_dev);
hinic3_update_qp_cos_cfg(nic_dev, num_cos);
/* For now, we don't support to change num_cos */
- if (num_cos > nic_dev->cos_config_num_max ||
+ if (num_cos > dcb->cos_config_num_max ||
nic_dev->q_params.num_qps < num_cos) {
nicif_err(nic_dev, drv, netdev, "Invalid num_cos: %u or num_qps: %u, disable DCB\n",
num_cos, nic_dev->q_params.num_qps);
nic_dev->q_params.num_cos = 0;
clear_bit(HINIC3_DCB_ENABLE, &nic_dev->flags);
+ clear_bit(HINIC3_DCB_ENABLE, &nic_dev->nic_vram->flags);
/* if we can't enable rss or get enough num_qps,
* need to sync default configure to hw
*/
@@ -190,17 +251,22 @@ static int hinic3_configure(struct hinic3_nic_dev *nic_dev)
{
struct net_device *netdev = nic_dev->netdev;
int err;
+ int is_in_kexec = vram_get_kexec_flag();
- err = hinic3_set_port_mtu(nic_dev->hwdev, (u16)netdev->mtu);
- if (err) {
- nicif_err(nic_dev, drv, netdev, "Failed to set mtu\n");
- return err;
+ if (is_in_kexec == 0) {
+ err = hinic3_set_port_mtu(nic_dev->hwdev, (u16)netdev->mtu);
+ if (err != 0) {
+ nicif_err(nic_dev, drv, netdev, "Failed to set mtu\n");
+ return err;
+ }
}
config_dcb_qps_map(nic_dev);
/* rx rss init */
- err = hinic3_rx_configure(netdev, test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags) ? 1 : 0);
+ err = hinic3_rx_configure(netdev,
+ test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)
+ ? 1 : 0);
if (err) {
nicif_err(nic_dev, drv, netdev, "Failed to configure rx\n");
return err;
@@ -256,10 +322,11 @@ static void config_dcb_num_qps(struct hinic3_nic_dev *nic_dev,
const struct hinic3_dyna_txrxq_params *q_params,
u16 max_qps)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u8 num_cos = q_params->num_cos;
u8 user_cos_num = hinic3_get_dev_user_cos_num(nic_dev);
- if (!num_cos || num_cos > nic_dev->cos_config_num_max || num_cos > max_qps)
+ if (!num_cos || num_cos > dcb->cos_config_num_max || num_cos > max_qps)
return; /* will disable DCB in config_dcb_qps_map() */
hinic3_update_qp_cos_cfg(nic_dev, user_cos_num);
@@ -332,57 +399,10 @@ static void hinic3_destroy_num_qps(struct hinic3_nic_dev *nic_dev)
kfree(nic_dev->qps_irq_info);
}
-int hinic3_force_port_disable(struct hinic3_nic_dev *nic_dev)
-{
- int err;
-
- down(&nic_dev->port_state_sem);
-
- err = hinic3_set_port_enable(nic_dev->hwdev, false, HINIC3_CHANNEL_NIC);
- if (!err)
- nic_dev->force_port_disable = true;
-
- up(&nic_dev->port_state_sem);
-
- return err;
-}
-
-int hinic3_force_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable)
-{
- int err = 0;
-
- down(&nic_dev->port_state_sem);
-
- nic_dev->force_port_disable = false;
- err = hinic3_set_port_enable(nic_dev->hwdev, enable,
- HINIC3_CHANNEL_NIC);
-
- up(&nic_dev->port_state_sem);
-
- return err;
-}
-
int hinic3_maybe_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable)
{
- int err;
-
- down(&nic_dev->port_state_sem);
-
- /* Do nothing when force disable
- * Port will disable when call force port disable
- * and should not enable port when in force mode
- */
- if (nic_dev->force_port_disable) {
- up(&nic_dev->port_state_sem);
- return 0;
- }
-
- err = hinic3_set_port_enable(nic_dev->hwdev, enable,
- HINIC3_CHANNEL_NIC);
-
- up(&nic_dev->port_state_sem);
-
- return err;
+ return hinic3_set_port_enable(nic_dev->hwdev, enable,
+ HINIC3_CHANNEL_NIC);
}
static void hinic3_print_link_message(struct hinic3_nic_dev *nic_dev,
@@ -398,8 +418,8 @@ static void hinic3_print_link_message(struct hinic3_nic_dev *nic_dev,
}
static int hinic3_alloc_channel_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_qp_params *qp_params,
- struct hinic3_dyna_txrxq_params *trxq_params)
+ struct hinic3_dyna_qp_params *qp_params,
+ struct hinic3_dyna_txrxq_params *trxq_params, bool is_up_eth)
{
int err;
@@ -414,7 +434,7 @@ static int hinic3_alloc_channel_resources(struct hinic3_nic_dev *nic_dev,
return err;
}
- err = hinic3_alloc_txrxq_resources(nic_dev, trxq_params);
+ err = hinic3_alloc_txrxq_resources(nic_dev, trxq_params, is_up_eth);
if (err) {
nicif_err(nic_dev, drv, nic_dev->netdev, "Failed to alloc txrxq resources\n");
hinic3_free_qps(nic_dev->hwdev, qp_params);
@@ -425,8 +445,8 @@ static int hinic3_alloc_channel_resources(struct hinic3_nic_dev *nic_dev,
}
static void hinic3_free_channel_resources(struct hinic3_nic_dev *nic_dev,
- struct hinic3_dyna_qp_params *qp_params,
- struct hinic3_dyna_txrxq_params *trxq_params)
+ struct hinic3_dyna_qp_params *qp_params,
+ struct hinic3_dyna_txrxq_params *trxq_params)
{
mutex_lock(&nic_dev->nic_mutex);
hinic3_free_txrxq_resources(nic_dev, trxq_params);
@@ -521,7 +541,8 @@ int hinic3_vport_up(struct hinic3_nic_dev *nic_dev)
queue_delayed_work(nic_dev->workq, &nic_dev->moderation_task,
HINIC3_MODERATONE_DELAY);
if (test_bit(HINIC3_RXQ_RECOVERY, &nic_dev->flags))
- queue_delayed_work(nic_dev->workq, &nic_dev->rxq_check_work, HZ);
+ queue_delayed_work(nic_dev->workq,
+ &nic_dev->rxq_check_work, HZ);
hinic3_print_link_message(nic_dev, link_status);
@@ -542,9 +563,52 @@ vport_enable_err:
return err;
}
+static int hinic3_flush_rq_and_check(struct hinic3_nic_dev *nic_dev, u16 glb_func_id)
+{
+ struct hinic3_flush_rq *rq_flush_msg = NULL;
+ struct hinic3_cmd_buf *cmd_buf = NULL;
+ int out_buf_len = sizeof(struct hinic3_flush_rq);
+ u16 rq_id;
+ u64 out_param = 0;
+ int ret;
+
+ cmd_buf = hinic3_alloc_cmd_buf(nic_dev->hwdev);
+ if (!cmd_buf) {
+ nic_err(&nic_dev->pdev->dev, "Failed to allocate cmd buf\n");
+ return -ENOMEM;
+ }
+
+ cmd_buf->size = sizeof(struct hinic3_flush_rq);
+ rq_flush_msg = (struct hinic3_flush_rq *)cmd_buf->buf;
+ rq_flush_msg->dw.bs.func_id = glb_func_id;
+ for (rq_id = 0; rq_id < nic_dev->q_params.num_qps; rq_id++) {
+ rq_flush_msg->dw.bs.rq_id = rq_id;
+ hinic3_cpu_to_be32(rq_flush_msg, out_buf_len);
+ ret = hinic3_cmdq_direct_resp(nic_dev->hwdev, HINIC3_MOD_L2NIC,
+ HINIC3_UCODE_CHK_RQ_STOP,
+ cmd_buf, &out_param, 0,
+ HINIC3_CHANNEL_NIC);
+ if (ret != 0 || out_param != 0) {
+ nic_err(&nic_dev->pdev->dev, "Failed to flush rq, ret:%d, func:%u, rq:%u\n",
+ ret, glb_func_id, rq_id);
+ goto err;
+ }
+ hinic3_be32_to_cpu(rq_flush_msg, out_buf_len);
+ }
+
+ nic_info(&nic_dev->pdev->dev, "Func:%u rq_num:%u flush rq success\n",
+ glb_func_id, nic_dev->q_params.num_qps);
+ hinic3_free_cmd_buf(nic_dev->hwdev, cmd_buf);
+ return 0;
+err:
+ hinic3_free_cmd_buf(nic_dev->hwdev, cmd_buf);
+ return -1;
+}
+
void hinic3_vport_down(struct hinic3_nic_dev *nic_dev)
{
u16 glb_func_id;
+ int is_in_kexec = vram_get_kexec_flag();
netif_carrier_off(nic_dev->netdev);
netif_tx_disable(nic_dev->netdev);
@@ -557,18 +621,21 @@ void hinic3_vport_down(struct hinic3_nic_dev *nic_dev)
if (!HINIC3_FUNC_IS_VF(nic_dev->hwdev))
hinic3_notify_all_vfs_link_changed(nic_dev->hwdev, 0);
- hinic3_maybe_set_port_state(nic_dev, false);
+ if (is_in_kexec != 0)
+ nicif_info(nic_dev, drv, nic_dev->netdev, "Skip changing mag status!\n");
+ else
+ hinic3_maybe_set_port_state(nic_dev, false);
glb_func_id = hinic3_global_func_id(nic_dev->hwdev);
hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false,
HINIC3_CHANNEL_NIC);
hinic3_flush_txqs(nic_dev->netdev);
- /* After set vport disable 100ms,
- * no packets will be send to host
- * FPGA set 2000ms
- */
- msleep(HINIC3_WAIT_FLUSH_QP_RESOURCE_TIMEOUT);
+
+ if (is_in_kexec == 0)
+ msleep(HINIC3_WAIT_FLUSH_QP_RESOURCE_TIMEOUT);
+ else
+ (void)hinic3_flush_rq_and_check(nic_dev, glb_func_id);
hinic3_flush_qps_res(nic_dev->hwdev);
}
}
@@ -581,11 +648,12 @@ int hinic3_change_channel_settings(struct hinic3_nic_dev *nic_dev,
struct hinic3_dyna_qp_params new_qp_params = {0};
struct hinic3_dyna_qp_params cur_qp_params = {0};
int err;
+ bool is_free_resources = false;
hinic3_config_num_qps(nic_dev, trxq_params);
err = hinic3_alloc_channel_resources(nic_dev, &new_qp_params,
- trxq_params);
+ trxq_params, false);
if (err) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc channel resources\n");
@@ -597,10 +665,19 @@ int hinic3_change_channel_settings(struct hinic3_nic_dev *nic_dev,
hinic3_close_channel(nic_dev, &cur_qp_params);
hinic3_free_channel_resources(nic_dev, &cur_qp_params,
&nic_dev->q_params);
+ is_free_resources = true;
}
if (nic_dev->num_qp_irq > trxq_params->num_qps)
hinic3_qp_irq_change(nic_dev, trxq_params->num_qps);
+
+ if (is_free_resources) {
+ err = hinic3_alloc_irq_vram(nic_dev, trxq_params, false);
+ if (err != 0) {
+ nicif_err(nic_dev, drv, nic_dev->netdev, "Change chl alloc irq failed\n");
+ goto alloc_irq_err;
+ }
+ }
nic_dev->q_params = *trxq_params;
if (reopen_handler)
@@ -621,7 +698,7 @@ int hinic3_change_channel_settings(struct hinic3_nic_dev *nic_dev,
vport_up_err:
hinic3_close_channel(nic_dev, &new_qp_params);
-
+alloc_irq_err:
open_channel_err:
hinic3_free_channel_resources(nic_dev, &new_qp_params, trxq_params);
@@ -652,7 +729,7 @@ int hinic3_open(struct net_device *netdev)
}
err = hinic3_alloc_channel_resources(nic_dev, &qp_params,
- &nic_dev->q_params);
+ &nic_dev->q_params, true);
if (err)
goto alloc_channel_res_err;
@@ -691,12 +768,31 @@ setup_qps_err:
return err;
}
+static void hinic3_delete_napi(struct hinic3_nic_dev *nic_dev)
+{
+ u16 q_id;
+ int is_in_kexec = vram_get_kexec_flag();
+ struct hinic3_irq *irq_cfg = NULL;
+
+ if (is_in_kexec == 0 || !nic_dev->q_params.irq_cfg)
+ return;
+
+ for (q_id = 0; q_id < nic_dev->q_params.num_qps; q_id++) {
+ irq_cfg = &nic_dev->q_params.irq_cfg[q_id];
+ qp_del_napi(irq_cfg);
+ }
+
+ hinic3_free_irq_vram(nic_dev, &nic_dev->q_params);
+}
+
int hinic3_close(struct net_device *netdev)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
struct hinic3_dyna_qp_params qp_params = {0};
if (!test_and_clear_bit(HINIC3_INTF_UP, &nic_dev->flags)) {
+ /* delete napi in os hotreplace rollback */
+ hinic3_delete_napi(nic_dev);
nicif_info(nic_dev, drv, netdev, "Netdev already close, do nothing\n");
return 0;
}
@@ -776,7 +872,8 @@ static u8 parse_ipv6_info(struct sk_buff *skb, u32 *rss_tunple,
return 0;
}
-static u16 select_queue_by_hash_func(struct net_device *dev, struct sk_buff *skb,
+static u16 select_queue_by_hash_func(struct net_device *dev,
+ struct sk_buff *skb,
unsigned int num_tx_queues)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(dev);
@@ -831,17 +928,20 @@ static u16 select_queue_by_hash_func(struct net_device *dev, struct sk_buff *skb
}
#define GET_DSCP_PRI_OFFSET 2
-static u8 hinic3_get_dscp_up(struct hinic3_nic_dev *nic_dev, struct sk_buff *skb)
+static u8 hinic3_get_dscp_up(struct hinic3_nic_dev *nic_dev,
+ struct sk_buff *skb)
{
+ struct hinic3_dcb *dcb = nic_dev->dcb;
int dscp_cp;
if (skb->protocol == htons(ETH_P_IP))
dscp_cp = ipv4_get_dsfield(ip_hdr(skb)) >> GET_DSCP_PRI_OFFSET;
else if (skb->protocol == htons(ETH_P_IPV6))
- dscp_cp = ipv6_get_dsfield(ipv6_hdr(skb)) >> GET_DSCP_PRI_OFFSET;
+ dscp_cp = ipv6_get_dsfield(ipv6_hdr(skb)) >>
+ GET_DSCP_PRI_OFFSET;
else
- return nic_dev->hw_dcb_cfg.default_cos;
- return nic_dev->hw_dcb_cfg.dscp2cos[dscp_cp];
+ return dcb->hw_dcb_cfg.default_cos;
+ return dcb->hw_dcb_cfg.dscp2cos[dscp_cp];
}
#if defined(HAVE_NDO_SELECT_QUEUE_SB_DEV_ONLY)
@@ -867,11 +967,13 @@ static u16 hinic3_select_queue(struct net_device *netdev, struct sk_buff *skb)
#endif /* end of HAVE_NDO_SELECT_QUEUE_ACCEL_FALLBACK */
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ struct hinic3_dcb *dcb = nic_dev->dcb;
u16 txq;
u8 cos, qp_num;
if (test_bit(HINIC3_SAME_RXTX, &nic_dev->flags))
- return select_queue_by_hash_func(netdev, skb, netdev->real_num_tx_queues);
+ return select_queue_by_hash_func(netdev, skb,
+ netdev->real_num_tx_queues);
txq =
#if defined(HAVE_NDO_SELECT_QUEUE_SB_DEV_ONLY)
@@ -887,18 +989,19 @@ static u16 hinic3_select_queue(struct net_device *netdev, struct sk_buff *skb)
#endif
if (test_bit(HINIC3_DCB_ENABLE, &nic_dev->flags)) {
- if (nic_dev->hw_dcb_cfg.trust == DCB_PCP) {
+ if (dcb->hw_dcb_cfg.trust == HINIC3_DCB_PCP) {
if (skb->vlan_tci)
- cos = nic_dev->hw_dcb_cfg.pcp2cos[skb->vlan_tci >> VLAN_PRIO_SHIFT];
+ cos = dcb->hw_dcb_cfg.pcp2cos[skb->vlan_tci >>
+ VLAN_PRIO_SHIFT];
else
- cos = nic_dev->hw_dcb_cfg.default_cos;
+ cos = dcb->hw_dcb_cfg.default_cos;
} else {
cos = hinic3_get_dscp_up(nic_dev, skb);
}
- qp_num = nic_dev->hw_dcb_cfg.cos_qp_num[cos] ?
- txq % nic_dev->hw_dcb_cfg.cos_qp_num[cos] : 0;
- txq = nic_dev->hw_dcb_cfg.cos_qp_offset[cos] + qp_num;
+ qp_num = dcb->hw_dcb_cfg.cos_qp_num[cos] ?
+ txq % dcb->hw_dcb_cfg.cos_qp_num[cos] : 0;
+ txq = dcb->hw_dcb_cfg.cos_qp_offset[cos] + qp_num;
}
return txq;
@@ -976,7 +1079,7 @@ static struct net_device_stats *hinic3_get_stats(struct net_device *netdev)
stats->rx_packets = packets;
stats->rx_bytes = bytes;
stats->rx_errors = errors;
- stats->rx_dropped = dropped;
+ stats->rx_dropped = dropped + nic_dev->vport_stats.rx_discard_vport;
#ifndef HAVE_VOID_NDO_GET_STATS64
return stats;
@@ -1023,10 +1126,18 @@ static int hinic3_change_mtu(struct net_device *netdev, int new_mtu)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
u32 mtu = (u32)new_mtu;
int err = 0;
+ int is_in_kexec = vram_get_kexec_flag();
#ifdef HAVE_XDP_SUPPORT
u32 xdp_max_mtu;
+#endif
+
+ if (is_in_kexec != 0) {
+ nicif_info(nic_dev, drv, netdev, "Hotreplace skip change mtu\n");
+ return err;
+ }
+#ifdef HAVE_XDP_SUPPORT
if (hinic3_is_xdp_enable(nic_dev)) {
xdp_max_mtu = hinic3_xdp_max_mtu(nic_dev);
if (mtu > xdp_max_mtu) {
@@ -1045,6 +1156,7 @@ static int hinic3_change_mtu(struct net_device *netdev, int new_mtu)
nicif_info(nic_dev, drv, nic_dev->netdev, "Change mtu from %u to %d\n",
netdev->mtu, new_mtu);
netdev->mtu = mtu;
+ nic_dev->nic_vram->vram_mtu = mtu;
}
return err;
@@ -1078,6 +1190,76 @@ static int hinic3_set_mac_addr(struct net_device *netdev, void *addr)
return 0;
}
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+static int hinic3_udp_tunnel_port_config(struct net_device *netdev,
+ struct udp_tunnel_info *ti,
+ u8 action)
+{
+ struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
+ u16 func_id = hinic3_global_func_id(nic_dev->hwdev);
+ u16 dst_port;
+ int ret = 0;
+
+ switch (ti->type) {
+ case UDP_TUNNEL_TYPE_VXLAN:
+ dst_port = ntohs(ti->port);
+ ret = hinic3_vlxan_port_config(nic_dev->hwdev,
+ func_id, dst_port, action);
+ if (ret != 0) {
+ nicif_warn(nic_dev, drv, netdev,
+ "Failed to set vxlan port %u to device\n",
+ dst_port);
+ break;
+ }
+ nicif_info(nic_dev, link, netdev, "Vxlan dst port set to %u\n",
+ action == HINIC3_CMD_OP_ADD ?
+ dst_port : ntohs(VXLAN_OFFLOAD_PORT_LE));
+ break;
+ default:
+ nicif_err(nic_dev, drv, netdev, "Failed to add port, only vxlan dst port is supported\n");
+ ret = -EINVAL;
+ }
+ return ret;
+}
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
+#ifdef HAVE_NDO_UDP_TUNNEL_ADD
+static void hinic3_udp_tunnel_add(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
+{
+ if (ti->sa_family != AF_INET && ti->sa_family != AF_INET6)
+ return;
+
+ hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_ADD);
+}
+
+static void hinic3_udp_tunnel_del(struct net_device *netdev,
+ struct udp_tunnel_info *ti)
+{
+ if (ti->sa_family != AF_INET && ti->sa_family != AF_INET6)
+ return;
+
+ hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_DEL);
+}
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD */
+
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+int hinic3_udp_tunnel_set_port(struct net_device *netdev,
+ __always_unused unsigned int table,
+ __always_unused unsigned int entry,
+ struct udp_tunnel_info *ti)
+{
+ return hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_ADD);
+}
+
+int hinic3_udp_tunnel_unset_port(struct net_device *netdev,
+ __always_unused unsigned int table,
+ __always_unused unsigned int entry,
+ struct udp_tunnel_info *ti)
+{
+ return hinic3_udp_tunnel_port_config(netdev, ti, HINIC3_CMD_OP_DEL);
+}
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
static int
hinic3_vlan_rx_add_vid(struct net_device *netdev,
__always_unused __be16 proto,
@@ -1124,7 +1306,7 @@ hinic3_vlan_rx_kill_vid(struct net_device *netdev,
int err = 0;
col = VID_COL(nic_dev, vid);
- line = VID_LINE(nic_dev, vid);
+ line = (int)VID_LINE(nic_dev, vid);
/* In the broadcast scenario, ucode finds the corresponding function
* based on VLAN 0 of vlan table. If we delete VLAN 0, the VLAN function
@@ -1163,14 +1345,12 @@ static int hinic3_vlan_restore(struct net_device *netdev)
return -EFAULT;
rcu_read_lock();
for (i = 0; i < VLAN_N_VID; i++) {
-/* lint -e778 */
#ifdef HAVE_VLAN_FIND_DEV_DEEP_RCU
vlandev =
__vlan_find_dev_deep_rcu(netdev, htons(ETH_P_8021Q), i);
#else
vlandev = __vlan_find_dev_deep(netdev, htons(ETH_P_8021Q), i);
#endif
-/* lint +e778 */
col = VID_COL(nic_dev, i);
line = VID_LINE(nic_dev, i);
if (!vlandev && (vlan_bitmap[line] & (1UL << col)) != 0) {
@@ -1328,12 +1508,17 @@ static int set_feature_vlan_filter(struct hinic3_nic_dev *nic_dev,
return 0;
#ifdef NEED_VLAN_RESTORE
- if (en)
+ if (en) {
err = hinic3_vlan_restore(nic_dev->netdev);
+ if (err) {
+ hinic3_err(nic_dev, drv, "vlan restore failed\n");
+ *failed_features |= vlan_filter_feature;
+ return err;
+ }
+ }
#endif
- if (err == 0)
- err = hinic3_set_vlan_fliter(nic_dev->hwdev, en);
+ err = hinic3_set_vlan_fliter(nic_dev->hwdev, en);
if (err) {
hinic3_err(nic_dev, drv, "%s rx vlan filter failed\n",
SET_FEATURES_OP_STR(en));
@@ -1427,8 +1612,8 @@ static int hinic3_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
struct hinic3_nic_dev *adapter = netdev_priv(netdev);
int err;
- if (is_multicast_ether_addr(mac) || /*lint !e574*/
- vf >= pci_num_vf(adapter->pdev)) /*lint !e574*/
+ if (is_multicast_ether_addr(mac) ||
+ vf >= pci_num_vf(adapter->pdev))
return -EINVAL;
err = hinic3_set_vf_mac(adapter->hwdev, OS_VF_ID_TO_HW(vf), mac);
@@ -1446,7 +1631,6 @@ static int hinic3_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
return 0;
}
-/*lint -save -e574 -e734*/
#ifdef IFLA_VF_MAX
static int set_hw_vf_vlan(void *hwdev, u16 cur_vlanprio, int vf,
u16 vlan, u8 qos)
@@ -1529,7 +1713,8 @@ static int hinic3_ndo_set_vf_spoofchk(struct net_device *netdev, int vf,
#endif
#ifdef HAVE_NDO_SET_VF_TRUST
-static int hinic3_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
+static int hinic3_ndo_set_vf_trust(struct net_device *netdev, int vf,
+ bool setting)
{
struct hinic3_nic_dev *adapter = netdev_priv(netdev);
int err;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h
index 11c1731..d8c5419 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic.h
@@ -10,6 +10,8 @@
#include "hinic3_common.h"
#include "hinic3_nic_io.h"
#include "hinic3_nic_cfg.h"
+#include "mag_mpu_cmd.h"
+#include "mag_mpu_cmd_defs.h"
/* ************************ array index define ********************* */
#define ARRAY_INDEX_0 0
@@ -21,6 +23,35 @@
#define ARRAY_INDEX_6 6
#define ARRAY_INDEX_7 7
+#define XSFP_TLV_PRE_INFO_LEN 4
+
+enum hinic3_link_port_type {
+ LINK_PORT_UNKNOWN,
+ LINK_PORT_OPTICAL_MM,
+ LINK_PORT_OPTICAL_SM,
+ LINK_PORT_PAS_COPPER,
+ LINK_PORT_ACC,
+ LINK_PORT_BASET,
+ LINK_PORT_AOC = 0x40,
+ LINK_PORT_ELECTRIC,
+ LINK_PORT_BACKBOARD_INTERFACE,
+};
+
+enum hilink_fibre_subtype {
+ FIBRE_SUBTYPE_SR = 1,
+ FIBRE_SUBTYPE_LR,
+ FIBRE_SUBTYPE_MAX,
+};
+
+enum hilink_fec_type {
+ HILINK_FEC_NOT_SET,
+ HILINK_FEC_RSFEC,
+ HILINK_FEC_BASEFEC,
+ HILINK_FEC_NOFEC,
+ HILINK_FEC_LLRSFE,
+ HILINK_FEC_MAX_TYPE,
+};
+
#define SQ_CI_ADDR_SHIFT 2
#define RQ_CI_ADDR_SHIFT 4
@@ -71,6 +102,12 @@ struct hinic3_port_routine_cmd {
struct mag_cmd_get_xsfp_present abs;
};
+struct hinic3_port_routine_cmd_extern {
+ bool mpu_send_xsfp_tlv_info;
+
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp std_xsfp_tlv_info;
+};
+
struct hinic3_nic_cfg {
struct semaphore cfg_lock;
@@ -84,11 +121,13 @@ struct hinic3_nic_cfg {
struct nic_port_info port_info;
/* percentage of pf link bandwidth */
- u32 pf_bw_limit;
- u32 rsvd2;
+ u32 pf_bw_tx_limit;
+ u32 pf_bw_rx_limit;
- struct hinic3_port_routine_cmd rt_cmd;
- struct mutex sfp_mutex; /* mutex used for copy sfp info */
+ struct hinic3_port_routine_cmd rt_cmd;
+ struct hinic3_port_routine_cmd_extern rt_cmd_ext;
+ /* mutex used for copy sfp info */
+ struct mutex sfp_mutex;
};
struct hinic3_nic_cmdq_ops;
@@ -98,7 +137,7 @@ struct hinic3_nic_io {
void *dev_hdl;
u8 link_status;
- u8 rsvd1;
+ u8 direct;
u32 rsvd2;
struct hinic3_io_queue *sq;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
index 747ac03..fc3c90a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.c
@@ -21,11 +21,133 @@
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
#include "hinic3_nic_cmdq.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_common.h"
#include "hinic3_nic_cfg.h"
-int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_sq_attr *attr)
+#include "vram_common.h"
+
+int hinic3_delete_bond(void *hwdev)
+{
+ struct hinic3_cmd_delete_bond cmd_delete_bond;
+ u16 out_size = sizeof(cmd_delete_bond);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err = 0;
+
+ if (!hwdev) {
+ pr_err("hwdev is null.\n");
+ return -EINVAL;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is null.\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd_delete_bond, 0, sizeof(cmd_delete_bond));
+ cmd_delete_bond.bond_id = HINIC3_INVALID_BOND_ID;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BOND_DEV_DELETE,
+ &cmd_delete_bond, sizeof(cmd_delete_bond),
+ &cmd_delete_bond, &out_size);
+ if (err || !out_size || cmd_delete_bond.head.status) {
+ nic_err(nic_io->dev_hdl, "Failed to delete bond, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, cmd_delete_bond.head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (cmd_delete_bond.bond_id != HINIC3_INVALID_BOND_ID)
+ nic_info(nic_io->dev_hdl, "Delete bond success\n");
+
+ return 0;
+}
+
+int hinic3_open_close_bond(void *hwdev, u32 bond_en)
+{
+ struct hinic3_cmd_open_close_bond cmd_open_close_bond;
+ u16 out_size = sizeof(cmd_open_close_bond);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err = 0;
+
+ if (!hwdev) {
+ pr_err("hwdev is null.\n");
+ return -EINVAL;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is null.\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd_open_close_bond, 0, sizeof(cmd_open_close_bond));
+ cmd_open_close_bond.open_close_bond_info.bond_id =
+ HINIC3_INVALID_BOND_ID;
+ cmd_open_close_bond.open_close_bond_info.open_close_flag = bond_en;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BOND_DEV_OPEN_CLOSE,
+ &cmd_open_close_bond,
+ sizeof(cmd_open_close_bond),
+ &cmd_open_close_bond, &out_size);
+ if (err || !out_size || cmd_open_close_bond.head.status) {
+ nic_err(nic_io->dev_hdl, "Failed to %s bond, err: %d, status: 0x%x, out_size: 0x%x\n",
+ bond_en ? "open" : "close", err,
+ cmd_open_close_bond.head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (cmd_open_close_bond.open_close_bond_info.bond_id !=
+ HINIC3_INVALID_BOND_ID) {
+ nic_info(nic_io->dev_hdl, "%s bond success\n",
+ bond_en ? "Open" : "Close");
+ }
+
+ return 0;
+}
+
+int hinic3_create_bond(void *hwdev, u32 *bond_id)
+{
+ struct hinic3_cmd_create_bond cmd_create_bond;
+ u16 out_size = sizeof(cmd_create_bond);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err = 0;
+
+ if (!hwdev) {
+ pr_err("hwdev is null.\n");
+ return -EINVAL;
+ }
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is null.\n");
+ return -EINVAL;
+ }
+
+ memset(&cmd_create_bond, 0, sizeof(cmd_create_bond));
+ cmd_create_bond.create_bond_info.default_param_flag = true;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BOND_DEV_CREATE,
+ &cmd_create_bond, sizeof(cmd_create_bond),
+ &cmd_create_bond, &out_size);
+ if (err || !out_size || cmd_create_bond.head.status) {
+ nic_err(nic_io->dev_hdl, "Failed to create default bond, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, cmd_create_bond.head.status, out_size);
+ return -EFAULT;
+ }
+
+ if (cmd_create_bond.create_bond_info.bond_id !=
+ HINIC3_INVALID_BOND_ID) {
+ *bond_id = cmd_create_bond.create_bond_info.bond_id;
+ nic_info(nic_io->dev_hdl, "Create bond success\n");
+ }
+
+ return 0;
+}
+
+int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io,
+ struct hinic3_sq_attr *attr)
{
struct hinic3_cmd_cons_idx_attr cons_idx_attr;
u16 out_size = sizeof(cons_idx_attr);
@@ -48,7 +170,8 @@ int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_sq_attr *at
cons_idx_attr.l2nic_sqn = attr->l2nic_sqn;
cons_idx_attr.ci_addr = attr->ci_dma_base >> SQ_CI_ADDR_SHIFT;
- err = l2nic_msg_to_mgmt_sync(nic_io->hwdev, HINIC3_NIC_CMD_SQ_CI_ATTR_SET,
+ err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
+ HINIC3_NIC_CMD_SQ_CI_ATTR_SET,
&cons_idx_attr, sizeof(cons_idx_attr),
&cons_idx_attr, &out_size);
if (err || !out_size || cons_idx_attr.msg_head.status) {
@@ -61,7 +184,8 @@ int hinic3_set_sq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_sq_attr *at
return 0;
}
-int hinic3_set_rq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_rq_attr *attr)
+int hinic3_set_rq_ci_ctx(struct hinic3_nic_io *nic_io,
+ struct hinic3_rq_attr *attr)
{
struct hinic3_rq_cqe_ctx cons_idx_ctx;
u16 out_size = sizeof(cons_idx_ctx);
@@ -76,15 +200,19 @@ int hinic3_set_rq_ci_ctx(struct hinic3_nic_io *nic_io, struct hinic3_rq_attr *at
cons_idx_ctx.timer_loop = attr->coalescing_time;
cons_idx_ctx.threshold_cqe_num = attr->pending_limit;
cons_idx_ctx.msix_entry_idx = attr->intr_idx;
- cons_idx_ctx.ci_addr_hi = upper_32_bits(attr->ci_dma_base >> RQ_CI_ADDR_SHIFT);
- cons_idx_ctx.ci_addr_lo = lower_32_bits(attr->ci_dma_base >> RQ_CI_ADDR_SHIFT);
+ cons_idx_ctx.ci_addr_hi = upper_32_bits(attr->ci_dma_base >>
+ RQ_CI_ADDR_SHIFT);
+ cons_idx_ctx.ci_addr_lo = lower_32_bits(attr->ci_dma_base >>
+ RQ_CI_ADDR_SHIFT);
- err = l2nic_msg_to_mgmt_sync(nic_io->hwdev, HINIC3_NIC_CMD_SET_RQ_CI_CTX,
+ err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
+ HINIC3_NIC_CMD_SET_RQ_CI_CTX,
&cons_idx_ctx, sizeof(cons_idx_ctx),
&cons_idx_ctx, &out_size);
if (err || !out_size || cons_idx_ctx.msg_head.status) {
nic_err(nic_io->dev_hdl, "Set rq cqe ctx fail, qid: %d, err: %d, status: 0x%x, out_size: 0x%x",
- attr->l2nic_rqn, err, cons_idx_ctx.msg_head.status, out_size);
+ attr->l2nic_rqn, err,
+ cons_idx_ctx.msg_head.status, out_size);
return -EFAULT;
}
@@ -142,8 +270,8 @@ int hinic3_set_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id,
&mac_info, sizeof(mac_info),
&mac_info, &out_size, channel);
if (err || !out_size ||
- hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
- mac_info.vlan_id)) {
+ (hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
+ mac_info.vlan_id) != 0)) {
nic_err(nic_io->dev_hdl,
"Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n",
err, mac_info.msg_head.status, out_size, channel);
@@ -178,6 +306,8 @@ int hinic3_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id,
memset(&mac_info, 0, sizeof(mac_info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) {
nic_err(nic_io->dev_hdl, "Invalid VLAN number: %d\n",
@@ -193,7 +323,8 @@ int hinic3_del_mac(void *hwdev, const u8 *mac_addr, u16 vlan_id, u16 func_id,
&mac_info, sizeof(mac_info), &mac_info,
&out_size, channel);
if (err || !out_size ||
- (mac_info.msg_head.status && !PF_SET_VF_MAC(hwdev, mac_info.msg_head.status))) {
+ (mac_info.msg_head.status &&
+ !PF_SET_VF_MAC(hwdev, mac_info.msg_head.status))) {
nic_err(nic_io->dev_hdl,
"Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x, channel: 0x%x\n",
err, mac_info.msg_head.status, out_size, channel);
@@ -223,6 +354,8 @@ int hinic3_update_mac(void *hwdev, const u8 *old_mac, u8 *new_mac, u16 vlan_id,
memset(&mac_info, 0, sizeof(mac_info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) {
nic_err(nic_io->dev_hdl, "Invalid VLAN number: %d\n",
@@ -239,8 +372,8 @@ int hinic3_update_mac(void *hwdev, const u8 *old_mac, u8 *new_mac, u16 vlan_id,
&mac_info, sizeof(mac_info),
&mac_info, &out_size);
if (err || !out_size ||
- hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
- mac_info.vlan_id)) {
+ (hinic3_check_mac_info(hwdev, mac_info.msg_head.status,
+ mac_info.vlan_id) != 0)) {
nic_err(nic_io->dev_hdl,
"Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n",
err, mac_info.msg_head.status, out_size);
@@ -273,6 +406,8 @@ int hinic3_get_default_mac(void *hwdev, u8 *mac_addr)
memset(&mac_info, 0, sizeof(mac_info));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
mac_info.func_id = hinic3_global_func_id(hwdev);
@@ -318,6 +453,45 @@ static int hinic3_config_vlan(struct hinic3_nic_io *nic_io, u8 opcode,
return 0;
}
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+int hinic3_vlxan_port_config(void *hwdev, u16 func_id, u16 port, u8 action)
+{
+ struct hinic3_cmd_vxlan_port_info vxlan_port_info;
+ u16 out_size = sizeof(vxlan_port_info);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ memset(&vxlan_port_info, 0, sizeof(vxlan_port_info));
+ vxlan_port_info.opcode = action;
+ vxlan_port_info.cfg_mode = 0; // other tool set
+ vxlan_port_info.func_id = func_id;
+ vxlan_port_info.vxlan_port = port;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_CFG_VXLAN_PORT,
+ &vxlan_port_info, sizeof(vxlan_port_info),
+ &vxlan_port_info, &out_size);
+ if (err || !out_size || vxlan_port_info.msg_head.status) {
+ if (vxlan_port_info.msg_head.status == 0x2) // other tool set failed
+ nic_warn(nic_io->dev_hdl,
+ "Failed to %s vxlan dst port because it has already been set by hinicadm\n",
+ action == HINIC3_CMD_OP_ADD
+ ? "add" : "delete");
+ else
+ nic_err(nic_io->dev_hdl,
+ "Failed to %s vxlan dst port, err: %d, status: 0x%x, out size: 0x%x\n",
+ action == HINIC3_CMD_OP_ADD ? "add" : "delete",
+ err, vxlan_port_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
+
int hinic3_add_vlan(void *hwdev, u16 vlan_id, u16 func_id)
{
struct hinic3_nic_io *nic_io = NULL;
@@ -326,6 +500,8 @@ int hinic3_add_vlan(void *hwdev, u16 vlan_id, u16 func_id)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
return hinic3_config_vlan(nic_io, HINIC3_CMD_OP_ADD, vlan_id, func_id);
}
@@ -337,6 +513,8 @@ int hinic3_del_vlan(void *hwdev, u16 vlan_id, u16 func_id)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
return hinic3_config_vlan(nic_io, HINIC3_CMD_OP_DEL, vlan_id, func_id);
}
@@ -380,6 +558,8 @@ int hinic3_set_dcb_state(void *hwdev, struct hinic3_dcb_state *dcb_state)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (!memcmp(&nic_io->dcb_state, dcb_state, sizeof(nic_io->dcb_state)))
return 0;
@@ -423,7 +603,8 @@ int hinic3_get_cos_by_pri(void *hwdev, u8 pri, u8 *cos)
if (pri >= NIC_DCB_UP_MAX && nic_io->dcb_state.trust == HINIC3_DCB_PCP)
return -EINVAL;
- if (pri >= NIC_DCB_IP_PRI_MAX && nic_io->dcb_state.trust == HINIC3_DCB_DSCP)
+ if (pri >= NIC_DCB_IP_PRI_MAX &&
+ nic_io->dcb_state.trust == HINIC3_DCB_DSCP)
return -EINVAL;
/*lint -e662*/
@@ -541,13 +722,15 @@ int hinic3_set_pause_info(void *hwdev, struct nic_pause_config nic_pause)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
nic_cfg = &nic_io->nic_cfg;
down(&nic_cfg->cfg_lock);
err = hinic3_cfg_hw_pause(nic_io, HINIC3_CMD_OP_SET, &nic_pause);
- if (err) {
+ if (err != 0) {
up(&nic_cfg->cfg_lock);
return err;
}
@@ -566,7 +749,6 @@ int hinic3_set_pause_info(void *hwdev, struct nic_pause_config nic_pause)
int hinic3_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
{
- struct hinic3_nic_cfg *nic_cfg = NULL;
struct hinic3_nic_io *nic_io = NULL;
int err = 0;
@@ -574,17 +756,13 @@ int hinic3_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- nic_cfg = &nic_io->nic_cfg;
+ if (!nic_io)
+ return -EINVAL;
err = hinic3_cfg_hw_pause(nic_io, HINIC3_CMD_OP_GET, nic_pause);
- if (err)
+ if (err != 0)
return err;
- if (nic_cfg->pause_set || !nic_pause->auto_neg) {
- nic_pause->rx_pause = nic_cfg->nic_pause.rx_pause;
- nic_pause->tx_pause = nic_cfg->nic_pause.tx_pause;
- }
-
return 0;
}
@@ -599,6 +777,8 @@ int hinic3_sync_dcb_state(void *hwdev, u8 op_code, u8 state)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&dcb_state, 0, sizeof(dcb_state));
@@ -607,7 +787,8 @@ int hinic3_sync_dcb_state(void *hwdev, u8 op_code, u8 state)
dcb_state.func_id = hinic3_global_func_id(hwdev);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_QOS_DCB_STATE,
- &dcb_state, sizeof(dcb_state), &dcb_state, &out_size);
+ &dcb_state, sizeof(dcb_state),
+ &dcb_state, &out_size);
if (err || dcb_state.head.status || !out_size) {
nic_err(nic_io->dev_hdl,
"Failed to set dcb state, err: %d, status: 0x%x, out size: 0x%x\n",
@@ -675,7 +856,8 @@ int hinic3_cache_out_qps_res(void *hwdev)
qp_res.func_id = hinic3_global_func_id(hwdev);
err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_CACHE_OUT_QP_RES,
- &qp_res, sizeof(qp_res), &qp_res, &out_size);
+ &qp_res, sizeof(qp_res),
+ &qp_res, &out_size);
if (err || !out_size || qp_res.msg_head.status) {
nic_err(nic_io->dev_hdl, "Failed to cache out qp resources, err: %d, status: 0x%x, out size: 0x%x\n",
err, qp_res.msg_head.status, out_size);
@@ -685,45 +867,8 @@ int hinic3_cache_out_qps_res(void *hwdev)
return 0;
}
-int hinic3_get_fpga_phy_port_stats(void *hwdev, struct hinic3_phy_fpga_port_stats *stats)
-{
- struct hinic3_port_stats *port_stats = NULL;
- struct hinic3_port_stats_info stats_info;
- u16 out_size = sizeof(*port_stats);
- struct hinic3_nic_io *nic_io = NULL;
- int err;
-
- port_stats = kzalloc(sizeof(*port_stats), GFP_KERNEL);
- if (!port_stats)
- return -ENOMEM;
-
- nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (!nic_io)
- return -EINVAL;
-
- memset(&stats_info, 0, sizeof(stats_info));
-
- err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_GET_PORT_STAT,
- &stats_info, sizeof(stats_info),
- port_stats, &out_size);
- if (err || !out_size || port_stats->msg_head.status) {
- nic_err(nic_io->dev_hdl,
- "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x\n",
- err, port_stats->msg_head.status, out_size);
- err = -EIO;
- goto out;
- }
-
- memcpy(stats, &port_stats->stats, sizeof(*stats));
-
-out:
- kfree(port_stats);
-
- return err;
-}
-EXPORT_SYMBOL(hinic3_get_fpga_phy_port_stats);
-
-int hinic3_get_vport_stats(void *hwdev, u16 func_id, struct hinic3_vport_stats *stats)
+int hinic3_get_vport_stats(void *hwdev, u16 func_id,
+ struct hinic3_vport_stats *stats)
{
struct hinic3_port_stats_info stats_info;
struct hinic3_cmd_vport_stats vport_stats;
@@ -738,6 +883,8 @@ int hinic3_get_vport_stats(void *hwdev, u16 func_id, struct hinic3_vport_stats *
memset(&vport_stats, 0, sizeof(vport_stats));
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
stats_info.func_id = func_id;
@@ -756,7 +903,8 @@ int hinic3_get_vport_stats(void *hwdev, u16 func_id, struct hinic3_vport_stats *
return 0;
}
-static int hinic3_set_function_table(struct hinic3_nic_io *nic_io, u32 cfg_bitmap,
+static int hinic3_set_function_table(struct hinic3_nic_io *nic_io,
+ u32 cfg_bitmap,
const struct hinic3_func_tbl_cfg *cfg)
{
struct hinic3_cmd_set_func_tbl cmd_func_tbl;
@@ -804,6 +952,8 @@ int hinic3_set_port_mtu(void *hwdev, u16 new_mtu)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (new_mtu < HINIC3_MIN_MTU_SIZE) {
nic_err(nic_io->dev_hdl,
@@ -834,6 +984,8 @@ static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&feature_nego, 0, sizeof(feature_nego));
feature_nego.func_id = hinic3_global_func_id(hwdev);
feature_nego.opcode = opcode;
@@ -855,29 +1007,24 @@ static int nic_feature_nego(void *hwdev, u8 opcode, u64 *s_feature, u16 size)
return 0;
}
-static int hinic3_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit)
+static int hinic3_get_bios_pf_bw_tx_limit(void *hwdev,
+ struct hinic3_nic_io *nic_io,
+ u16 func_id, u32 *pf_rate)
{
- struct hinic3_nic_io *nic_io = NULL;
+ int err = 0; // default success
struct nic_cmd_bios_cfg cfg = {{0}};
u16 out_size = sizeof(cfg);
- int err;
-
- if (!hwdev || !pf_bw_limit)
- return -EINVAL;
-
- if (hinic3_func_type(hwdev) == TYPE_VF || !HINIC3_SUPPORT_RATE_LIMIT(hwdev))
- return 0;
- nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- cfg.bios_cfg.func_id = (u8)hinic3_global_func_id(hwdev);
+ cfg.bios_cfg.func_id = (u8)func_id;
cfg.bios_cfg.func_valid = 1;
- cfg.op_code = 0 | NIC_NVM_DATA_PF_SPEED_LIMIT;
+ cfg.op_code = 0 | NIC_NVM_DATA_PF_TX_SPEED_LIMIT;
- err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BIOS_CFG, &cfg, sizeof(cfg),
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_BIOS_CFG,
+ &cfg, sizeof(cfg),
&cfg, &out_size);
if (err || !out_size || cfg.head.status) {
nic_err(nic_io->dev_hdl,
- "Failed to get bios pf bandwidth limit, err: %d, status: 0x%x, out size: 0x%x\n",
+ "Failed to get bios pf bandwidth tx limit, err: %d, status: 0x%x, out size: 0x%x\n",
err, cfg.head.status, out_size);
return -EIO;
}
@@ -887,13 +1034,86 @@ static int hinic3_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit)
nic_warn(nic_io->dev_hdl, "Invalid bios configuration data, signature: 0x%x\n",
cfg.bios_cfg.signature);
- if (cfg.bios_cfg.pf_bw > MAX_LIMIT_BW) {
+ if (cfg.bios_cfg.pf_tx_bw > MAX_LIMIT_BW) {
+ nic_err(nic_io->dev_hdl, "Invalid bios cfg pf bandwidth limit: %u\n",
+ cfg.bios_cfg.pf_tx_bw);
+ return -EINVAL;
+ }
+
+ (*pf_rate) = cfg.bios_cfg.pf_tx_bw;
+ return err;
+}
+
+static int hinic3_get_bios_pf_bw_rx_limit(void *hwdev,
+ struct hinic3_nic_io *nic_io,
+ u16 func_id, u32 *pf_rate)
+{
+ int err = 0; // default success
+ struct nic_rx_rate_bios_cfg rx_bios_conf = {{0}};
+ u16 out_size = sizeof(rx_bios_conf);
+
+ rx_bios_conf.func_id = (u8)func_id;
+ rx_bios_conf.op_code = 0; /* 1-save, 0-read */
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_RX_RATE_CFG,
+ &rx_bios_conf, sizeof(rx_bios_conf),
+ &rx_bios_conf, &out_size);
+ if (rx_bios_conf.msg_head.status == HINIC3_MGMT_CMD_UNSUPPORTED &&
+ err == 0) { // Compatible older firmware
+ nic_warn(nic_io->dev_hdl, "Not support get bios pf bandwidth rx limit\n");
+ return 0;
+ } else if (err || !out_size || rx_bios_conf.msg_head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get bios pf bandwidth rx limit, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, rx_bios_conf.msg_head.status, out_size);
+ return -EIO;
+ }
+ if (rx_bios_conf.rx_rate_limit > MAX_LIMIT_BW) {
nic_err(nic_io->dev_hdl, "Invalid bios cfg pf bandwidth limit: %u\n",
- cfg.bios_cfg.pf_bw);
+ rx_bios_conf.rx_rate_limit);
return -EINVAL;
}
- *pf_bw_limit = cfg.bios_cfg.pf_bw;
+ (*pf_rate) = rx_bios_conf.rx_rate_limit;
+ return err;
+}
+
+static int hinic3_get_bios_pf_bw_limit(void *hwdev, u32 *pf_bw_limit, u8 direct)
+{
+ struct hinic3_nic_io *nic_io = NULL;
+ u32 pf_rate = 0;
+ int err = 0;
+ u16 func_id;
+
+ func_id = hinic3_global_func_id(hwdev);
+
+ if (!hwdev || !pf_bw_limit)
+ return -EINVAL;
+
+ if (hinic3_func_type(hwdev) == TYPE_VF ||
+ !HINIC3_SUPPORT_RATE_LIMIT(hwdev))
+ return 0;
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ if (direct == HINIC3_NIC_TX)
+ err = hinic3_get_bios_pf_bw_tx_limit(hwdev, nic_io,
+ func_id, &pf_rate);
+ else if (direct == HINIC3_NIC_RX)
+ err = hinic3_get_bios_pf_bw_rx_limit(hwdev, nic_io,
+ func_id, &pf_rate);
+
+ if (err != 0)
+ return err;
+
+ if (pf_rate > MAX_LIMIT_BW) {
+ nic_err(nic_io->dev_hdl,
+ "Invalid bios cfg pf bandwidth limit: %u\n", pf_rate);
+ return -EINVAL;
+ }
+
+ *pf_bw_limit = pf_rate;
return 0;
}
@@ -902,8 +1122,9 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level)
{
struct hinic3_cmd_tx_rate_cfg rate_cfg = {{0}};
struct hinic3_nic_io *nic_io = NULL;
+ u32 rate_limit;
u16 out_size = sizeof(rate_cfg);
- u32 pf_rate;
+ u32 pf_rate = 0;
int err;
u32 speed_convert[PORT_SPEED_UNKNOWN] = {
0, 10, 100, 1000, 10000, 25000, 40000, 50000, 100000, 200000
@@ -914,15 +1135,16 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level)
return -EINVAL;
if (speed_level >= PORT_SPEED_UNKNOWN) {
- nic_err(nic_io->dev_hdl, "Invalid speed level: %u\n", speed_level);
+ nic_err(nic_io->dev_hdl,
+ "Invalid speed level: %u\n", speed_level);
return -EINVAL;
}
- if (nic_io->nic_cfg.pf_bw_limit == MAX_LIMIT_BW) {
- pf_rate = 0;
- } else {
+ rate_limit = (nic_io->direct == HINIC3_NIC_TX) ?
+ nic_io->nic_cfg.pf_bw_tx_limit : nic_io->nic_cfg.pf_bw_rx_limit;
+ if (rate_limit != MAX_LIMIT_BW) {
/* divided by 100 to convert to percentage */
- pf_rate = (speed_convert[speed_level] / 100) * nic_io->nic_cfg.pf_bw_limit;
+ pf_rate = (speed_convert[speed_level] / 100) * rate_limit;
/* bandwidth limit is very small but not unlimit in this case */
if (pf_rate == 0 && speed_level != PORT_SPEED_NOT_SET)
pf_rate = 1;
@@ -931,13 +1153,16 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level)
rate_cfg.func_id = hinic3_global_func_id(hwdev);
rate_cfg.min_rate = 0;
rate_cfg.max_rate = pf_rate;
+ rate_cfg.direct = nic_io->direct;
- err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_SET_MAX_MIN_RATE, &rate_cfg,
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_SET_MAX_MIN_RATE,
+ &rate_cfg,
sizeof(rate_cfg), &rate_cfg, &out_size);
if (err || !out_size || rate_cfg.msg_head.status) {
nic_err(nic_io->dev_hdl, "Failed to set rate(%u), err: %d, status: 0x%x, out size: 0x%x\n",
pf_rate, err, rate_cfg.msg_head.status, out_size);
- return rate_cfg.msg_head.status ? rate_cfg.msg_head.status : -EIO;
+ return rate_cfg.msg_head.status
+ ? rate_cfg.msg_head.status : -EIO;
}
return 0;
@@ -954,7 +1179,8 @@ int hinic3_set_nic_feature_to_hw(void *hwdev)
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- return nic_feature_nego(hwdev, HINIC3_CMD_OP_SET, &nic_io->feature_cap, 1);
+ return nic_feature_nego(hwdev, HINIC3_CMD_OP_SET,
+ &nic_io->feature_cap, 1);
}
u64 hinic3_get_feature_cap(void *hwdev)
@@ -962,6 +1188,8 @@ u64 hinic3_get_feature_cap(void *hwdev)
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return 0;
return nic_io->feature_cap;
}
@@ -971,12 +1199,17 @@ void hinic3_update_nic_feature(void *hwdev, u64 s_feature)
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
nic_io->feature_cap = s_feature;
- nic_info(nic_io->dev_hdl, "Update nic feature to 0x%llx\n", nic_io->feature_cap);
+ nic_info(nic_io->dev_hdl,
+ "Update nic feature to 0x%llx\n",
+ nic_io->feature_cap);
}
-static inline int init_nic_hwdev_param_valid(const void *hwdev, const void *pcidev_hdl,
+static inline int init_nic_hwdev_param_valid(const void *hwdev,
+ const void *pcidev_hdl,
const void *dev_hdl)
{
if (!hwdev || !pcidev_hdl || !dev_hdl)
@@ -1004,6 +1237,7 @@ static int hinic3_init_nic_io(void *hwdev, void *pcidev_hdl, void *dev_hdl,
(*nic_io)->nic_cfg.rt_cmd.mpu_send_sfp_abs = false;
(*nic_io)->nic_cfg.rt_cmd.mpu_send_sfp_info = false;
+ (*nic_io)->nic_cfg.rt_cmd_ext.mpu_send_xsfp_tlv_info = false;
return 0;
}
@@ -1020,27 +1254,34 @@ int hinic3_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl,
{
struct hinic3_nic_io *nic_io = NULL;
int err;
+ int is_in_kexec = vram_get_kexec_flag();
err = hinic3_init_nic_io(hwdev, pcidev_hdl, dev_hdl, &nic_io);
- if (err)
+ if (err != 0)
return err;
+ nic_io->rx_buff_len = rx_buff_len;
+
err = hinic3_register_service_adapter(hwdev, nic_io, SERVICE_T_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to register service adapter\n");
goto register_sa_err;
}
- err = hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC, 1, HINIC3_CHANNEL_NIC);
- if (err) {
+ err = hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC,
+ 1, HINIC3_CHANNEL_NIC);
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set function svc used state\n");
goto set_used_state_err;
}
- err = hinic3_init_function_table(nic_io);
- if (err) {
- nic_err(nic_io->dev_hdl, "Failed to init function table\n");
- goto err_out;
+ if (is_in_kexec == 0) {
+ err = hinic3_init_function_table(nic_io);
+ if (err != 0) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to init function table\n");
+ goto err_out;
+ }
}
err = hinic3_get_nic_feature_from_hw(hwdev, &nic_io->feature_cap, 1);
@@ -1052,24 +1293,35 @@ int hinic3_init_nic_hwdev(void *hwdev, void *pcidev_hdl, void *dev_hdl,
sdk_info(dev_hdl, "nic features: 0x%llx\n", nic_io->feature_cap);
hinic3_nic_cmdq_adapt_init(nic_io);
- err = hinic3_get_bios_pf_bw_limit(hwdev, &nic_io->nic_cfg.pf_bw_limit);
- if (err) {
- nic_err(nic_io->dev_hdl, "Failed to get pf bandwidth limit\n");
+ err = hinic3_get_bios_pf_bw_limit(hwdev,
+ &nic_io->nic_cfg.pf_bw_tx_limit,
+ HINIC3_NIC_TX);
+ if (err != 0) {
+ nic_err(nic_io->dev_hdl, "Failed to get pf tx bandwidth limit\n");
+ goto err_out;
+ }
+
+ err = hinic3_get_bios_pf_bw_limit(hwdev,
+ &nic_io->nic_cfg.pf_bw_rx_limit,
+ HINIC3_NIC_RX);
+ if (err != 0) {
+ nic_err(nic_io->dev_hdl, "Failed to get pf rx bandwidth limit\n");
goto err_out;
}
err = hinic3_vf_func_init(nic_io);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to init vf info\n");
goto err_out;
}
- nic_io->rx_buff_len = rx_buff_len;
-
return 0;
err_out:
- hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC, 0, HINIC3_CHANNEL_NIC);
+ if (hinic3_set_func_svc_used_state(hwdev, SVC_T_NIC,
+ 0, HINIC3_CHANNEL_NIC) != 0) {
+ nic_err(nic_io->dev_hdl, "Failed to set function svc used state\n");
+ }
set_used_state_err:
hinic3_unregister_service_adapter(hwdev, SERVICE_T_NIC);
@@ -1119,6 +1371,8 @@ int hinic3_force_drop_tx_pkt(void *hwdev)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&pkt_drop, 0, sizeof(pkt_drop));
pkt_drop.port = hinic3_physical_port_id(hwdev);
@@ -1147,6 +1401,8 @@ int hinic3_set_rx_mode(void *hwdev, u32 enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
rx_mode_cfg.func_id = hinic3_global_func_id(hwdev);
@@ -1175,6 +1431,8 @@ int hinic3_set_rx_vlan_offload(void *hwdev, u8 en)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&vlan_cfg, 0, sizeof(vlan_cfg));
vlan_cfg.func_id = hinic3_global_func_id(hwdev);
@@ -1192,7 +1450,8 @@ int hinic3_set_rx_vlan_offload(void *hwdev, u8 en)
return 0;
}
-int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
+int hinic3_update_mac_vlan(void *hwdev, const u16 old_vlan,
+ u16 new_vlan, int vf_id)
{
struct vf_data_storage *vf_info = NULL;
struct hinic3_nic_io *nic_io = NULL;
@@ -1203,6 +1462,8 @@ int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
if (!nic_io->vf_infos || is_zero_ether_addr(vf_info->drv_mac_addr))
return 0;
@@ -1211,7 +1472,7 @@ int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
err = hinic3_del_mac(nic_io->hwdev, vf_info->drv_mac_addr,
old_vlan, func_id, HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to delete VF %d MAC %pM vlan %u\n",
HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, old_vlan);
return err;
@@ -1219,7 +1480,7 @@ int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id)
err = hinic3_set_mac(nic_io->hwdev, vf_info->drv_mac_addr,
new_vlan, func_id, HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to add VF %d MAC %pM vlan %u\n",
HW_VF_ID_TO_OS(vf_id), vf_info->drv_mac_addr, new_vlan);
hinic3_set_mac(nic_io->hwdev, vf_info->drv_mac_addr,
@@ -1242,6 +1503,8 @@ static int hinic3_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en,
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&lro_cfg, 0, sizeof(lro_cfg));
lro_cfg.func_id = hinic3_global_func_id(hwdev);
@@ -1273,6 +1536,8 @@ static int hinic3_set_rx_lro_timer(void *hwdev, u32 timer_value)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&lro_timer, 0, sizeof(lro_timer));
lro_timer.opcode = HINIC3_CMD_OP_SET;
@@ -1305,12 +1570,14 @@ int hinic3_set_rx_lro_state(void *hwdev, u8 lro_en, u32 lro_timer,
ipv6_en = lro_en ? 1 : 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
nic_info(nic_io->dev_hdl, "Set LRO max coalesce packet size to %uK\n",
lro_max_pkt_len);
err = hinic3_set_rx_lro(hwdev, ipv4_en, ipv6_en, (u8)lro_max_pkt_len);
- if (err)
+ if (err != 0)
return err;
/* we don't set LRO timer for VF */
@@ -1333,6 +1600,8 @@ int hinic3_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&vlan_filter, 0, sizeof(vlan_filter));
vlan_filter.func_id = hinic3_global_func_id(hwdev);
@@ -1352,7 +1621,6 @@ int hinic3_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl)
int hinic3_set_func_capture_en(void *hwdev, u16 func_id, bool cap_en)
{
- // struct hinic_hwdev *dev = hwdev;
struct nic_cmd_capture_info cap_info = {{0}};
u16 out_size = sizeof(cap_info);
int err;
@@ -1361,7 +1629,6 @@ int hinic3_set_func_capture_en(void *hwdev, u16 func_id, bool cap_en)
return -EINVAL;
/* 2 function capture types */
- // cap_info.op_type = UP_UCAPTURE_OP_TYPE_FUNC;
cap_info.is_en_trx = cap_en;
cap_info.func_port = func_id;
@@ -1386,6 +1653,8 @@ int hinic3_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (tcam_rule->index >= HINIC3_MAX_TCAM_RULES_NUM) {
nic_err(nic_io->dev_hdl, "Tcam rules num to add is invalid\n");
return -EINVAL;
@@ -1421,6 +1690,8 @@ int hinic3_del_tcam_rule(void *hwdev, u32 index)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (index >= HINIC3_MAX_TCAM_RULES_NUM) {
nic_err(nic_io->dev_hdl, "Tcam rules num to del is invalid\n");
return -EINVAL;
@@ -1470,6 +1741,8 @@ static int hinic3_mgmt_tcam_block(void *hwdev, u8 alloc_en, u16 *index)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&tcam_block_info, 0,
sizeof(struct nic_cmd_ctrl_tcam_block_out));
@@ -1515,6 +1788,8 @@ int hinic3_set_fdir_tcam_rule_filter(void *hwdev, bool enable)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
port_tcam_cmd.func_id = hinic3_global_func_id(hwdev);
port_tcam_cmd.tcam_enable = (u8)enable;
@@ -1543,6 +1818,8 @@ int hinic3_flush_tcam_rule(void *hwdev)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&tcam_flush, 0, sizeof(struct nic_cmd_flush_tcam_rules));
tcam_flush.func_id = hinic3_global_func_id(hwdev);
@@ -1560,7 +1837,8 @@ int hinic3_flush_tcam_rule(void *hwdev)
return 0;
}
-int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num_qps, u16 wqe_type)
+int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info,
+ u16 num_qps, u16 wqe_type)
{
struct hinic3_cmd_buf *cmd_buf = NULL;
struct hinic3_nic_io *nic_io = NULL;
@@ -1573,6 +1851,8 @@ int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
cmd_buf = hinic3_alloc_cmd_buf(hwdev);
if (!cmd_buf) {
nic_err(nic_io->dev_hdl, "Failed to allocate cmd_buf.\n");
@@ -1587,9 +1867,11 @@ int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num
cmd_buf->size = sizeof(struct hinic3_rxq_hw);
- err = hinic3_cmdq_detail_resp(hwdev, HINIC3_MOD_L2NIC, HINIC3_UCODE_CMD_RXQ_INFO_GET,
- cmd_buf, cmd_buf, NULL, 0, HINIC3_CHANNEL_NIC);
- if (err)
+ err = hinic3_cmdq_detail_resp(hwdev, HINIC3_MOD_L2NIC,
+ HINIC3_UCODE_CMD_RXQ_INFO_GET,
+ cmd_buf, cmd_buf, NULL, 0,
+ HINIC3_CHANNEL_NIC);
+ if (err != 0)
goto get_rxq_info_failed;
rxq_info_out = cmd_buf->buf;
@@ -1604,7 +1886,8 @@ get_rxq_info_failed:
return err;
}
-int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced, bool link_state)
+int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced,
+ bool link_state)
{
struct hinic3_nic_io *nic_io = NULL;
struct vf_data_storage *vf_infos = NULL;
@@ -1615,8 +1898,10 @@ int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced, bool link_stat
return -EINVAL;
}
- if (hinic3_func_type(hwdev) == TYPE_VF)
+ if (hinic3_func_type(hwdev) == TYPE_VF) {
+ pr_err("VF are not supported to set link state.\n");
return -EINVAL;
+ }
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
if (!nic_io) {
@@ -1633,3 +1918,35 @@ int hinic3_pf_set_vf_link_state(void *hwdev, bool vf_link_forced, bool link_stat
return 0;
}
EXPORT_SYMBOL(hinic3_pf_set_vf_link_state);
+
+int hinic3_get_outband_vlan_cfg(void *hwdev, u16 *outband_default_vid)
+{
+ struct hinic3_outband_cfg_info outband_cfg_info;
+ u16 out_size = sizeof(outband_cfg_info);
+ struct hinic3_nic_io *nic_io = NULL;
+ int err;
+
+ if (!hwdev || !outband_default_vid)
+ return -EINVAL;
+
+ memset(&outband_cfg_info, 0, sizeof(outband_cfg_info));
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
+ err = l2nic_msg_to_mgmt_sync(hwdev, HINIC3_NIC_CMD_GET_OUTBAND_CFG,
+ &outband_cfg_info,
+ sizeof(outband_cfg_info),
+ &outband_cfg_info, &out_size);
+ if (err || !out_size || outband_cfg_info.msg_head.status) {
+ nic_err(nic_io->dev_hdl,
+ "Failed to get outband cfg, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, outband_cfg_info.msg_head.status, out_size);
+ return -EINVAL;
+ }
+
+ *outband_default_vid = outband_cfg_info.outband_default_vid;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
index dd2c2fd..60caf68 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg.h
@@ -7,9 +7,10 @@
#include <linux/types.h>
#include <linux/netdevice.h>
-#include "hinic3_mgmt_interface.h"
#include "mag_mpu_cmd.h"
-#include "mag_cmd.h"
+#include "mag_mpu_cmd_defs.h"
+#include "nic_cfg_comm.h"
+#include "nic_mpu_cmd_defs.h"
#define OS_VF_ID_TO_HW(os_vf_id) ((os_vf_id) + 1)
#define HW_VF_ID_TO_OS(hw_vf_id) ((hw_vf_id) - 1)
@@ -54,6 +55,8 @@
#define MAX_LIMIT_BW 100
+#define HINIC3_INVALID_BOND_ID 0xffffffff
+
enum hinic3_valid_link_settings {
HILINK_LINK_SET_SPEED = 0x1,
HILINK_LINK_SET_AUTONEG = 0x2,
@@ -67,6 +70,11 @@ enum hinic3_link_follow_status {
HINIC3_LINK_FOLLOW_STATUS_MAX,
};
+enum hinic3_nic_pf_direct {
+ HINIC3_NIC_RX = 0,
+ HINIC3_NIC_TX,
+};
+
struct hinic3_link_ksettings {
u32 valid_bitmap;
u8 speed; /* enum nic_speed_level */
@@ -152,8 +160,12 @@ struct nic_port_info {
u8 duplex;
u8 speed;
u8 fec;
+ u8 lanes;
+ u8 rsvd;
u32 supported_mode;
u32 advertised_mode;
+ u32 supported_fec_mode;
+ u32 bond_speed;
};
struct nic_pause_config {
@@ -178,11 +190,17 @@ struct hinic3_rxq_hw {
#define MODULE_TYPE_QSFP28 0x11
#define MODULE_TYPE_QSFP 0x0C
#define MODULE_TYPE_QSFP_PLUS 0x0D
+#define MODULE_TYPE_DSFP 0x1B
+#define MODULE_TYPE_QSFP_CMIS 0x1E
#define TCAM_IP_TYPE_MASK 0x1
#define TCAM_TUNNEL_TYPE_MASK 0xF
#define TCAM_FUNC_ID_MASK 0x7FFF
+int hinic3_delete_bond(void *hwdev);
+int hinic3_open_close_bond(void *hwdev, u32 bond_en);
+int hinic3_create_bond(void *hwdev, u32 *bond_id);
+
int hinic3_add_tcam_rule(void *hwdev, struct nic_tcam_cfg_rule *tcam_rule);
int hinic3_del_tcam_rule(void *hwdev, u32 index);
@@ -335,7 +353,7 @@ int hinic3_kill_vf_vlan(void *hwdev, int vf_id);
* @retval zero: success
* @retval non-zero: failure
*/
-int hinic3_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr);
+int hinic3_set_vf_mac(void *hwdev, int vf_id, const unsigned char *mac_addr);
/* *
* @brief hinic3_vf_info_vlanprio - get vf vlan priority
@@ -510,7 +528,14 @@ int hinic3_rss_get_indir_tbl(void *hwdev, u32 *indir_table);
*/
int hinic3_get_phy_port_stats(void *hwdev, struct mag_cmd_port_stats *stats);
-int hinic3_get_fpga_phy_port_stats(void *hwdev, struct hinic3_phy_fpga_port_stats *stats);
+/* *
+ * @brief hinic3_get_phy_rsfec_stats - get rsfec stats
+ * @param hwdev: device pointer to hwdev
+ * @param stats: rsfec(Reed-Solomon Forward Error Correction) stats
+ * @retval zero: success
+ * @retval non-zero: failure
+ */
+int hinic3_get_phy_rsfec_stats(void *hwdev, struct mag_cmd_rsfec_stats *stats);
int hinic3_set_port_funcs_state(void *hwdev, bool enable);
@@ -546,6 +571,8 @@ int hinic3_set_vlan_fliter(void *hwdev, u32 vlan_filter_ctrl);
void hinic3_clear_vfs_info(void *hwdev);
+int hinic3_notify_vf_outband_cfg(void *hwdev, u16 func_id, u16 vlan_id);
+
int hinic3_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id);
int hinic3_set_led_status(void *hwdev, enum mag_led_type type,
@@ -565,9 +592,13 @@ int hinic3_set_autoneg(void *hwdev, bool enable);
int hinic3_get_sfp_type(void *hwdev, u8 *sfp_type, u8 *sfp_type_ext);
int hinic3_get_sfp_eeprom(void *hwdev, u8 *data, u32 len);
+int hinic3_get_tlv_xsfp_eeprom(void *hwdev, u8 *data, u32 len);
bool hinic3_if_sfp_absent(void *hwdev);
int hinic3_get_sfp_info(void *hwdev, struct mag_cmd_get_xsfp_info *sfp_info);
+int hinic3_get_sfp_tlv_info(void *hwdev,
+ struct drv_tag_mag_cmd_get_xsfp_tlv_rsp *sfp_tlv_info,
+ const struct tag_mag_cmd_get_xsfp_tlv_req *sfp_tlv_info_req);
/* *
* @brief hinic3_set_nic_feature_to_hw - sync nic feature to hardware
@@ -620,4 +651,19 @@ int hinic3_set_pf_rate(void *hwdev, u8 speed_level);
int hinic3_get_rxq_hw_info(void *hwdev, struct rxq_check_info *rxq_info, u16 num_qps, u16 wqe_type);
+#if defined(HAVE_NDO_UDP_TUNNEL_ADD) || defined(HAVE_UDP_TUNNEL_NIC_INFO)
+/* *
+ * @brief hinic3_vlxan_port_config - add/del vxlan dst port
+ * @param hwdev: device pointer to hwdev
+ * @param func_id: function id
+ * @param port: vxlan dst port
+ * @param action: add or del, del will set to default value (0x12B5)
+ * @retval zero: success
+ * @retval non-zero: failure
+ */
+int hinic3_vlxan_port_config(void *hwdev, u16 func_id, u16 port, u8 action);
+#endif /* HAVE_NDO_UDP_TUNNEL_ADD || HAVE_UDP_TUNNEL_NIC_INFO */
+
+int hinic3_get_outband_vlan_cfg(void *hwdev, u16 *outband_default_vid);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c
index 15d081b..c0e0a61 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cfg_vf.c
@@ -22,7 +22,8 @@
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
#include "hinic3_nic_cmdq.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
/*lint -e806*/
static unsigned char set_vf_link_state;
@@ -59,7 +60,8 @@ static int hinic3_set_vlan_ctx(struct hinic3_nic_io *nic_io, u16 func_id,
vlan_tag, q_id, vlan_mode);
err = hinic3_cmdq_direct_resp(nic_io->hwdev, HINIC3_MOD_L2NIC,
- cmd, cmd_buf, &out_param, 0, HINIC3_CHANNEL_NIC);
+ cmd, cmd_buf, &out_param,
+ 0, HINIC3_CHANNEL_NIC);
hinic3_free_cmd_buf(nic_io->hwdev, cmd_buf);
@@ -108,7 +110,7 @@ int hinic3_cfg_vf_vlan(struct hinic3_nic_io *nic_io, u8 opcode, u16 vid,
err = hinic3_set_vlan_ctx(nic_io, glb_func_id, vlan_tag,
NIC_CONFIG_ALL_QUEUE_VLAN_CTX,
opcode == HINIC3_CMD_OP_ADD);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set VF %d vlan ctx, err: %d\n",
HW_VF_ID_TO_OS(vf_id), err);
@@ -129,12 +131,15 @@ int hinic3_cfg_vf_vlan(struct hinic3_nic_io *nic_io, u8 opcode, u16 vid,
/* this function just be called by hinic3_ndo_set_vf_mac,
* others are not permitted.
*/
-int hinic3_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr)
+int hinic3_set_vf_mac(void *hwdev, int vf_id, const unsigned char *mac_addr)
{
- struct vf_data_storage *vf_info;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vf_info = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
#ifndef __VMWARE__
/* duplicate request, so just return success */
@@ -152,13 +157,15 @@ int hinic3_set_vf_mac(void *hwdev, int vf_id, unsigned char *mac_addr)
int hinic3_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos)
{
- struct hinic3_nic_io *nic_io;
+ struct hinic3_nic_io *nic_io = NULL;
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
err = hinic3_cfg_vf_vlan(nic_io, HINIC3_CMD_OP_ADD, vlan, qos, vf_id);
- if (err)
+ if (err != 0)
return err;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan;
@@ -172,17 +179,19 @@ int hinic3_add_vf_vlan(void *hwdev, int vf_id, u16 vlan, u8 qos)
int hinic3_kill_vf_vlan(void *hwdev, int vf_id)
{
- struct vf_data_storage *vf_infos;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vf_infos = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
vf_infos = nic_io->vf_infos;
err = hinic3_cfg_vf_vlan(nic_io, HINIC3_CMD_OP_DEL,
vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,
vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos, vf_id);
- if (err)
+ if (err != 0)
return err;
nic_info(nic_io->dev_hdl, "Remove VLAN %u on VF %d\n",
@@ -197,11 +206,13 @@ int hinic3_kill_vf_vlan(void *hwdev, int vf_id)
u16 hinic3_vf_info_vlanprio(void *hwdev, int vf_id)
{
- struct hinic3_nic_io *nic_io;
+ struct hinic3_nic_io *nic_io = NULL;
u16 pf_vlan, vlanprio;
u8 pf_qos;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return 0;
pf_vlan = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan;
pf_qos = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos;
@@ -214,9 +225,14 @@ int hinic3_set_vf_link_state(void *hwdev, u16 vf_id, int link)
{
struct hinic3_nic_io *nic_io =
hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- struct vf_data_storage *vf_infos = nic_io->vf_infos;
+ struct vf_data_storage *vf_infos = NULL;
u8 link_status = 0;
+ if (!nic_io)
+ return -EINVAL;
+
+ vf_infos = nic_io->vf_infos;
+
switch (link) {
case HINIC3_IFLA_VF_LINK_STATE_AUTO:
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false;
@@ -256,6 +272,8 @@ int hinic3_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
vf_infos = nic_io->vf_infos;
memset(&spoofchk_cfg, 0, sizeof(spoofchk_cfg));
@@ -280,9 +298,11 @@ int hinic3_set_vf_spoofchk(void *hwdev, u16 vf_id, bool spoofchk)
bool hinic3_vf_info_spoofchk(void *hwdev, int vf_id)
{
- struct hinic3_nic_io *nic_io;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return false;
return nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk;
}
@@ -296,7 +316,7 @@ int hinic3_set_vf_trust(void *hwdev, u16 vf_id, bool trust)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (vf_id > nic_io->max_vfs)
+ if (!nic_io || vf_id > nic_io->max_vfs)
return -EINVAL;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust = trust;
@@ -309,11 +329,11 @@ bool hinic3_get_vf_trust(void *hwdev, int vf_id)
struct hinic3_nic_io *nic_io = NULL;
if (!hwdev)
- return -EINVAL;
+ return false;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- if (vf_id > nic_io->max_vfs)
- return -EINVAL;
+ if (!nic_io || vf_id > nic_io->max_vfs)
+ return false;
return nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].trust;
}
@@ -331,6 +351,7 @@ static int hinic3_set_vf_tx_rate_max_min(struct hinic3_nic_io *nic_io,
rate_cfg.func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf_id;
rate_cfg.max_rate = max_rate;
rate_cfg.min_rate = min_rate;
+ rate_cfg.direct = HINIC3_NIC_TX;
err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
HINIC3_NIC_CMD_SET_MAX_MIN_RATE,
&rate_cfg, sizeof(rate_cfg), &rate_cfg,
@@ -351,13 +372,15 @@ int hinic3_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate)
int err;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (!HINIC3_SUPPORT_RATE_LIMIT(hwdev)) {
nic_err(nic_io->dev_hdl, "Current function doesn't support to set vf rate limit\n");
return -EOPNOTSUPP;
}
err = hinic3_set_vf_tx_rate_max_min(nic_io, vf_id, max_rate, min_rate);
- if (err)
+ if (err != 0)
return err;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate;
@@ -368,12 +391,16 @@ int hinic3_set_vf_tx_rate(void *hwdev, u16 vf_id, u32 max_rate, u32 min_rate)
void hinic3_get_vf_config(void *hwdev, u16 vf_id, struct ifla_vf_info *ivi)
{
- struct vf_data_storage *vfinfo;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vfinfo = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return;
vfinfo = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+ if (!vfinfo)
+ return;
ivi->vf = HW_VF_ID_TO_OS(vf_id);
ether_addr_copy(ivi->mac, vfinfo->user_mac_addr);
@@ -446,13 +473,15 @@ static int vf_func_register(struct hinic3_nic_io *nic_io)
int err;
err = hinic3_register_vf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC,
- nic_io->hwdev, hinic3_vf_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_vf_event_handler);
+ if (err != 0)
return err;
err = hinic3_register_vf_mbox_cb(nic_io->hwdev, HINIC3_MOD_HILINK,
- nic_io->hwdev, hinic3_vf_mag_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_vf_mag_event_handler);
+ if (err != 0)
goto reg_hilink_err;
memset(®ister_info, 0, sizeof(register_info));
@@ -464,6 +493,11 @@ static int vf_func_register(struct hinic3_nic_io *nic_io)
®ister_info, &out_size, 0,
HINIC3_CHANNEL_NIC);
if (err || !out_size || register_info.msg_head.status) {
+ if (hinic3_is_slave_host(nic_io->hwdev)) {
+ nic_warn(nic_io->dev_hdl, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, register_info.msg_head.status, out_size);
+ return 0;
+ }
nic_err(nic_io->dev_hdl, "Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",
err, register_info.msg_head.status, out_size);
err = -EIO;
@@ -498,18 +532,20 @@ static int pf_init_vf_infos(struct hinic3_nic_io *nic_io)
for (i = 0; i < nic_io->max_vfs; i++) {
err = hinic3_init_vf_infos(nic_io, i);
- if (err)
+ if (err != 0)
goto init_vf_infos_err;
}
err = hinic3_register_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC,
- nic_io->hwdev, hinic3_pf_mbox_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_mbox_handler);
+ if (err != 0)
goto register_pf_mbox_cb_err;
err = hinic3_register_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_HILINK,
- nic_io->hwdev, hinic3_pf_mag_mbox_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_mag_mbox_handler);
+ if (err != 0)
goto register_pf_mag_mbox_cb_err;
return 0;
@@ -531,17 +567,19 @@ int hinic3_vf_func_init(struct hinic3_nic_io *nic_io)
return vf_func_register(nic_io);
err = hinic3_register_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_L2NIC,
- nic_io->hwdev, hinic3_pf_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_event_handler);
+ if (err != 0)
return err;
err = hinic3_register_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_HILINK,
- nic_io->hwdev, hinic3_pf_mag_event_handler);
- if (err)
+ nic_io->hwdev,
+ hinic3_pf_mag_event_handler);
+ if (err != 0)
goto register_mgmt_msg_cb_err;
err = pf_init_vf_infos(nic_io);
- if (err)
+ if (err != 0)
goto pf_init_vf_infos_err;
return 0;
@@ -568,17 +606,24 @@ void hinic3_vf_func_free(struct hinic3_nic_io *nic_io)
&unregister, sizeof(unregister),
&unregister, &out_size, 0,
HINIC3_CHANNEL_NIC);
- if (err || !out_size || unregister.msg_head.status)
- nic_err(nic_io->dev_hdl, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n",
- err, unregister.msg_head.status, out_size);
-
+ if (err || !out_size || unregister.msg_head.status) {
+ if (hinic3_is_slave_host(nic_io->hwdev)) {
+ nic_info(nic_io->dev_hdl, "vRoCE VF notify PF unsuccessful is allowed");
+ } else {
+ nic_err(nic_io->dev_hdl, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n",
+ err, unregister.msg_head.status, out_size);
+ }
+ }
hinic3_unregister_vf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC);
} else {
if (nic_io->vf_infos) {
- hinic3_unregister_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_HILINK);
- hinic3_unregister_pf_mbox_cb(nic_io->hwdev, HINIC3_MOD_L2NIC);
+ hinic3_unregister_pf_mbox_cb(nic_io->hwdev,
+ HINIC3_MOD_HILINK);
+ hinic3_unregister_pf_mbox_cb(nic_io->hwdev,
+ HINIC3_MOD_L2NIC);
hinic3_clear_vfs_info(nic_io->hwdev);
kfree(nic_io->vf_infos);
+ nic_io->vf_infos = NULL;
}
hinic3_unregister_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_HILINK);
hinic3_unregister_mgmt_msg_cb(nic_io->hwdev, HINIC3_MOD_L2NIC);
@@ -587,11 +632,15 @@ void hinic3_vf_func_free(struct hinic3_nic_io *nic_io)
static void clear_vf_infos(void *hwdev, u16 vf_id)
{
- struct vf_data_storage *vf_infos;
- struct hinic3_nic_io *nic_io;
+ struct vf_data_storage *vf_infos = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
u16 func_id;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
func_id = hinic3_glb_pf_vf_offset(hwdev) + vf_id;
vf_infos = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
@@ -620,10 +669,59 @@ static void clear_vf_infos(void *hwdev, u16 vf_id)
void hinic3_clear_vfs_info(void *hwdev)
{
+ u16 i;
struct hinic3_nic_io *nic_io =
hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- u16 i;
+
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
for (i = 0; i < nic_io->max_vfs; i++)
clear_vf_infos(hwdev, OS_VF_ID_TO_HW(i));
}
+
+int hinic3_notify_vf_outband_cfg(void *hwdev, u16 func_id, u16 vlan_id)
+{
+ int err = 0;
+ struct hinic3_outband_cfg_info outband_cfg_info;
+ struct vf_data_storage *vf_infos = NULL;
+ u16 out_size = sizeof(outband_cfg_info);
+ u16 vf_id;
+ struct hinic3_nic_io *nic_io =
+ hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return 0;
+ }
+
+ vf_id = func_id - hinic3_glb_pf_vf_offset(nic_io->hwdev);
+ vf_infos = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+
+ memset(&outband_cfg_info, 0, sizeof(outband_cfg_info));
+ if (vf_infos->registered) {
+ outband_cfg_info.func_id = func_id;
+ outband_cfg_info.outband_default_vid = vlan_id;
+ err = hinic3_mbox_to_vf_no_ack(nic_io->hwdev, vf_id,
+ HINIC3_MOD_L2NIC,
+ HINIC3_NIC_CMD_OUTBAND_CFG_NOTICE,
+ &outband_cfg_info,
+ sizeof(outband_cfg_info),
+ &outband_cfg_info, &out_size,
+ HINIC3_CHANNEL_NIC);
+ if (err == MBOX_ERRCODE_UNKNOWN_DES_FUNC) {
+ nic_warn(nic_io->dev_hdl, "VF%d not initialized, disconnect it\n",
+ HW_VF_ID_TO_OS(vf_id));
+ hinic3_unregister_vf(nic_io, vf_id);
+ return 0;
+ }
+ if (err || !out_size || outband_cfg_info.msg_head.status)
+ nic_err(nic_io->dev_hdl,
+ "outband cfg event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n",
+ HW_VF_ID_TO_OS(vf_id), err,
+ outband_cfg_info.msg_head.status, out_size);
+ }
+
+ return err;
+}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c
index 0ec4b32..b45c875 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dbg.c
@@ -30,6 +30,8 @@ int hinic3_dbg_get_wqe_info(void *hwdev, u16 q_id, u16 idx, u16 wqebb_cnt,
}
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (q_id >= nic_io->num_qps) {
pr_err("q_id[%u] > num_qps_cfg[%u].\n", q_id, nic_io->num_qps);
return -EINVAL;
@@ -69,6 +71,8 @@ int hinic3_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info,
}
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (q_id >= nic_io->num_qps) {
nic_err(nic_io->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n",
q_id);
@@ -82,6 +86,8 @@ int hinic3_dbg_get_sq_info(void *hwdev, u16 q_id, struct nic_sq_info *sq_info,
}
sq = &nic_io->sq[q_id];
+ if (!sq)
+ return -EINVAL;
sq_info->q_id = q_id;
sq_info->pi = hinic3_get_sq_local_pi(sq);
@@ -112,6 +118,8 @@ int hinic3_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info,
}
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
if (q_id >= nic_io->num_qps) {
nic_err(nic_io->dev_hdl, "Input queue id(%u) is larger than the actual queue number\n",
q_id);
@@ -125,6 +133,8 @@ int hinic3_dbg_get_rq_info(void *hwdev, u16 q_id, struct nic_rq_info *rq_info,
}
rq = &nic_io->rq[q_id];
+ if (!rq)
+ return -EINVAL;
rq_info->q_id = q_id;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
index e76a66b..c219452 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_dev.h
@@ -15,9 +15,10 @@
#include "hinic3_tx.h"
#include "hinic3_rx.h"
#include "hinic3_dcb.h"
+#include "vram_common.h"
#define HINIC3_NIC_DRV_NAME "hinic3"
-#define HINIC3_NIC_DRV_VERSION HINIC3_DRV_VERSION
+#define HINIC3_NIC_DRV_VERSION "17.7.8.1"
#define HINIC3_FUNC_IS_VF(hwdev) (hinic3_func_type(hwdev) == TYPE_VF)
@@ -25,6 +26,10 @@
#define HINIC3_MODERATONE_DELAY HZ
#define LP_PKT_CNT 64
+#define LP_PKT_LEN 60
+
+#define NAPI_IS_REGIN 1
+#define NAPI_NOT_REGIN 0
enum hinic3_flags {
HINIC3_INTF_UP,
@@ -91,6 +96,8 @@ struct hinic3_irq {
u16 rsvd1;
u32 irq_id; /* The IRQ number from OS */
+ u32 napi_reign;
+
char irq_name[IFNAMSIZ + 16];
struct napi_struct napi;
cpumask_t affinity_mask;
@@ -123,6 +130,41 @@ struct hinic3_dyna_txrxq_params {
struct hinic3_dyna_txq_res *txqs_res;
struct hinic3_dyna_rxq_res *rxqs_res;
struct hinic3_irq *irq_cfg;
+ char irq_cfg_vram_name[VRAM_NAME_MAX_LEN];
+};
+
+struct hinic3_flush_rq {
+ union {
+ struct {
+#if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
+ u32 lb_proc : 1;
+ u32 rsvd : 10;
+ u32 rq_id : 8;
+ u32 func_id : 13;
+#else
+ u32 func_id : 13;
+ u32 rq_id : 8;
+ u32 rsvd : 10;
+ u32 lb_proc : 1;
+#endif
+ } bs;
+ u32 value;
+ } dw;
+
+ union {
+ struct {
+#if defined(BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN)
+ u32 rsvd2 : 2;
+ u32 src_chnl : 12;
+ u32 pkt_len : 18;
+#else
+ u32 pkt_len : 18;
+ u32 src_chnl : 12;
+ u32 rsvd2 : 2;
+#endif
+ } bs;
+ u32 value;
+ } lb_info0; /* loop back information, used by uCode */
};
#define HINIC3_NIC_STATS_INC(nic_dev, field) \
@@ -147,6 +189,10 @@ struct hinic3_nic_stats {
#endif
};
+struct hinic3_nic_vport_stats {
+ u64 rx_discard_vport;
+};
+
#define HINIC3_TCAM_DYNAMIC_BLOCK_SIZE 16
#define HINIC3_MAX_TCAM_FILTERS 512
@@ -185,6 +231,28 @@ struct hinic3_tcam_info {
struct hinic3_tcam_dynamic_block_info tcam_dynamic_info;
};
+struct hinic3_dcb {
+ u8 cos_config_num_max;
+ u8 func_dft_cos_bitmap;
+ /* used to tool validity check */
+ u16 port_dft_cos_bitmap;
+
+ struct hinic3_dcb_config hw_dcb_cfg;
+ struct hinic3_dcb_config wanted_dcb_cfg;
+ unsigned long dcb_flags;
+};
+
+struct hinic3_vram {
+ u32 vram_mtu;
+ u16 vram_num_qps;
+ unsigned long flags;
+};
+
+struct hinic3_outband_cfg {
+ u16 outband_default_vid;
+ u16 rsvd;
+};
+
struct hinic3_nic_dev {
struct pci_dev *pdev;
struct net_device *netdev;
@@ -204,6 +272,7 @@ struct hinic3_nic_dev {
u32 dma_rx_buff_size;
u16 rx_buff_len;
u32 page_order;
+ bool page_pool_enabled;
/* Rss related varibles */
u8 rss_hash_engine;
@@ -213,17 +282,13 @@ struct hinic3_nic_dev {
u32 *rss_hkey_be;
u32 *rss_indir;
- u8 cos_config_num_max;
- u8 func_dft_cos_bitmap;
- u16 port_dft_cos_bitmap; /* used to tool validity check */
+ struct hinic3_dcb *dcb;
+ char dcb_name[VRAM_NAME_MAX_LEN];
+
+ struct hinic3_vram *nic_vram;
+ char nic_vram_name[VRAM_NAME_MAX_LEN];
- struct hinic3_dcb_config hw_dcb_cfg;
- struct hinic3_dcb_config wanted_dcb_cfg;
- struct hinic3_dcb_config dcb_cfg;
- unsigned long dcb_flags;
int disable_port_cnt;
- /* lock for disable or enable traffic flow */
- struct semaphore dcb_sem;
struct hinic3_intr_coal_info *intr_coalesce;
unsigned long last_moder_jiffies;
@@ -235,11 +300,10 @@ struct hinic3_nic_dev {
#endif
struct hinic3_nic_stats stats;
+ struct hinic3_nic_vport_stats vport_stats;
/* lock for nic resource */
struct mutex nic_mutex;
- bool force_port_disable;
- struct semaphore port_state_sem;
u8 link_status;
struct nic_service_cap nic_cap;
@@ -281,9 +345,10 @@ struct hinic3_nic_dev {
struct hinic3_nic_prof_attr *prof_attr;
struct hinic3_prof_adapter *prof_adap;
u64 rsvd8[7];
- u32 rsvd9;
+ struct hinic3_outband_cfg outband_cfg;
u32 rxq_get_err_times;
struct delayed_work rxq_check_work;
+ struct delayed_work vport_stats_work;
struct hinic3_tx_rx_ops tx_rx_ops;
};
@@ -312,7 +377,7 @@ struct hinic3_uld_info *get_nic_uld_info(void);
u32 hinic3_get_io_stats_size(const struct hinic3_nic_dev *nic_dev);
-void hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats);
+int hinic3_get_io_stats(const struct hinic3_nic_dev *nic_dev, void *stats);
int hinic3_open(struct net_device *netdev);
@@ -331,6 +396,8 @@ int hinic3_qps_irq_init(struct hinic3_nic_dev *nic_dev);
void hinic3_qps_irq_deinit(struct hinic3_nic_dev *nic_dev);
+void qp_del_napi(struct hinic3_irq *irq_cfg);
+
void hinic3_set_netdev_ops(struct hinic3_nic_dev *nic_dev);
bool hinic3_is_netdev_ops_match(const struct net_device *netdev);
@@ -348,10 +415,6 @@ void hinic3_get_ethtool_stats(struct net_device *netdev,
int hinic3_get_sset_count(struct net_device *netdev, int sset);
-int hinic3_force_port_disable(struct hinic3_nic_dev *nic_dev);
-
-int hinic3_force_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable);
-
int hinic3_maybe_set_port_state(struct hinic3_nic_dev *nic_dev, bool enable);
#ifdef ETHTOOL_GLINKSETTINGS
@@ -386,5 +449,18 @@ bool hinic3_is_xdp_enable(struct hinic3_nic_dev *nic_dev);
int hinic3_xdp_max_mtu(struct hinic3_nic_dev *nic_dev);
#endif
+#ifdef HAVE_UDP_TUNNEL_NIC_INFO
+int hinic3_udp_tunnel_set_port(struct net_device *netdev, unsigned int table,
+ unsigned int entry, struct udp_tunnel_info *ti);
+int hinic3_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table,
+ unsigned int entry,
+ struct udp_tunnel_info *ti);
+#endif /* HAVE_UDP_TUNNEL_NIC_INFO */
+
+#if defined(ETHTOOL_GFECPARAM) && defined(ETHTOOL_SFECPARAM)
+int set_fecparam(void *hwdev, u8 fecparam);
+int get_fecparam(void *hwdev, u8 *advertised_fec, u8 *supported_fec);
+#endif
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c
index 57cf07c..87b5aa6 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_event.c
@@ -21,11 +21,12 @@
#include "hinic3_nic_cfg.h"
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
{
- struct vf_data_storage *vf_info;
+ struct vf_data_storage *vf_info = NULL;
u16 func_id;
int err = 0;
@@ -38,7 +39,7 @@ static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
err = hinic3_set_mac(nic_io->hwdev, vf_info->drv_mac_addr,
vf_info->pf_vlan, func_id,
HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set VF %d MAC\n",
HW_VF_ID_TO_OS(vf_id));
return err;
@@ -51,7 +52,7 @@ static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
err = hinic3_cfg_vf_vlan(nic_io, HINIC3_CMD_OP_ADD,
vf_info->pf_vlan, vf_info->pf_qos,
vf_id);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to add VF %d VLAN_QOS\n",
HW_VF_ID_TO_OS(vf_id));
return err;
@@ -62,7 +63,7 @@ static int hinic3_init_vf_config(struct hinic3_nic_io *nic_io, u16 vf_id)
err = hinic3_set_vf_tx_rate(nic_io->hwdev, vf_id,
vf_info->max_rate,
vf_info->min_rate);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set VF %d max rate %u, min rate %u\n",
HW_VF_ID_TO_OS(vf_id), vf_info->max_rate,
vf_info->min_rate);
@@ -84,7 +85,7 @@ static int register_vf_msg_handler(struct hinic3_nic_io *nic_io, u16 vf_id)
}
err = hinic3_init_vf_config(nic_io, vf_id);
- if (err)
+ if (err != 0)
return err;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true;
@@ -137,6 +138,9 @@ static int hinic3_register_vf_msg_handler(struct hinic3_nic_io *nic_io,
struct vf_data_storage *vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
int err;
+ if (!vf_info)
+ return -EINVAL;
+
if (register_vf->op_register) {
vf_info->support_extra_feature = register_vf->support_extra_feature;
err = register_vf_msg_handler(nic_io, vf_id);
@@ -145,7 +149,7 @@ static int hinic3_register_vf_msg_handler(struct hinic3_nic_io *nic_io,
vf_info->support_extra_feature = 0;
}
- if (err)
+ if (err != 0)
register_info->msg_head.status = EFAULT;
*out_size = sizeof(*register_info);
@@ -157,6 +161,8 @@ void hinic3_unregister_vf(struct hinic3_nic_io *nic_io, u16 vf_id)
{
struct vf_data_storage *vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
+ if (!vf_info)
+ return;
unregister_vf_msg_handler(nic_io, vf_id);
vf_info->support_extra_feature = 0;
}
@@ -181,14 +187,21 @@ static int hinic3_get_vf_mac_msg_handler(struct hinic3_nic_io *nic_io, u16 vf,
void *buf_out, u16 *out_size)
{
struct vf_data_storage *vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf);
+ struct hinic3_port_mac_set *mac_in =
+ (struct hinic3_port_mac_set *)buf_in;
struct hinic3_port_mac_set *mac_info = buf_out;
int err;
+ if (!mac_info || !vf_info)
+ return -EINVAL;
+
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
+
if (HINIC3_SUPPORT_VF_MAC(nic_io->hwdev)) {
err = l2nic_msg_to_mgmt_sync(nic_io->hwdev, HINIC3_NIC_CMD_GET_MAC, buf_in,
in_size, buf_out, out_size);
- if (!err) {
+ if (err == 0) {
if (is_zero_ether_addr(mac_info->mac))
ether_addr_copy(mac_info->mac, vf_info->drv_mac_addr);
}
@@ -211,6 +224,11 @@ static int hinic3_set_vf_mac_msg_handler(struct hinic3_nic_io *nic_io, u16 vf,
struct hinic3_port_mac_set *mac_out = buf_out;
int err;
+ if (!vf_info)
+ return -EINVAL;
+
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
+
if (vf_info->use_specified_mac && !vf_info->trust &&
is_valid_ether_addr(mac_in->mac)) {
nic_warn(nic_io->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n",
@@ -247,6 +265,10 @@ static int hinic3_del_vf_mac_msg_handler(struct hinic3_nic_io *nic_io, u16 vf,
struct hinic3_port_mac_set *mac_out = buf_out;
int err;
+ if (!vf_info)
+ return -EINVAL;
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
+
if (vf_info->use_specified_mac && !vf_info->trust &&
is_valid_ether_addr(mac_in->mac)) {
nic_warn(nic_io->dev_hdl, "PF has already set VF %d MAC address, and vf trust is off.\n",
@@ -283,10 +305,13 @@ static int hinic3_update_vf_mac_msg_handler(struct hinic3_nic_io *nic_io,
struct hinic3_port_mac_update *mac_out = buf_out;
int err;
+ if (!vf_info)
+ return -EINVAL;
if (!is_valid_ether_addr(mac_in->new_mac)) {
nic_err(nic_io->dev_hdl, "Update VF MAC is invalid.\n");
return -EINVAL;
}
+ mac_in->func_id = hinic3_glb_pf_vf_offset(nic_io->hwdev) + vf;
#ifndef __VMWARE__
if (vf_info->use_specified_mac && !vf_info->trust) {
@@ -301,7 +326,7 @@ static int hinic3_update_vf_mac_msg_handler(struct hinic3_nic_io *nic_io,
HW_VF_ID_TO_OS(vf),
HINIC_CFG_VF_MAC_CHANGED,
(void *)mac_in->new_mac);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to config VF %d MAC request, err: %d\n",
HW_VF_ID_TO_OS(vf), err);
return err;
@@ -359,10 +384,11 @@ static int _l2nic_msg_to_mgmt_sync(void *hwdev, u16 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size,
u16 channel)
{
- u32 i, cmd_cnt = ARRAY_LEN(vf_cmd_handler);
+ int i, cmd_cnt = ARRAY_LEN(vf_cmd_handler);
bool cmd_to_pf = false;
- if (hinic3_func_type(hwdev) == TYPE_VF) {
+ if (hinic3_func_type(hwdev) == TYPE_VF &&
+ !hinic3_is_slave_host(hwdev)) {
for (i = 0; i < cmd_cnt; i++) {
if (cmd == vf_cmd_handler[i].cmd)
cmd_to_pf = true;
@@ -397,13 +423,15 @@ int hinic3_pf_mbox_handler(void *hwdev,
u16 vf_id, u16 cmd, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
- u32 index, cmd_size = ARRAY_LEN(vf_cmd_handler);
+ int index, cmd_size = ARRAY_LEN(vf_cmd_handler);
struct hinic3_nic_io *nic_io = NULL;
if (!hwdev)
return -EFAULT;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
for (index = 0; index < cmd_size; index++) {
if (cmd == vf_cmd_handler[index].cmd)
@@ -460,10 +488,14 @@ void hinic3_notify_dcb_state_event(struct hinic3_nic_io *nic_io,
static void dcb_state_event(void *hwdev, void *buf_in, u16 in_size,
void *buf_out, u16 *out_size)
{
- struct hinic3_cmd_vf_dcb_state *vf_dcb;
- struct hinic3_nic_io *nic_io;
+ struct hinic3_cmd_vf_dcb_state *vf_dcb = NULL;
+ struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
vf_dcb = buf_in;
if (!vf_dcb)
@@ -479,6 +511,10 @@ static void tx_pause_excp_event_handler(void *hwdev, void *buf_in, u16 in_size,
struct hinic3_nic_io *nic_io = NULL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
if (in_size != sizeof(*excp_info)) {
nic_err(nic_io->dev_hdl, "Invalid in_size: %u, should be %ld\n",
@@ -501,6 +537,10 @@ static void bond_active_event_handler(void *hwdev, void *buf_in, u16 in_size,
struct hinic3_event_info event_info = {0};
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
if (in_size != sizeof(*active_info)) {
nic_err(nic_io->dev_hdl, "Invalid in_size: %u, should be %ld\n",
@@ -515,6 +555,36 @@ static void bond_active_event_handler(void *hwdev, void *buf_in, u16 in_size,
hinic3_event_callback(nic_io->hwdev, &event_info);
}
+static void outband_vlan_cfg_event_handler(void *hwdev, void *buf_in,
+ u16 in_size, void *buf_out,
+ u16 *out_size)
+{
+ struct hinic3_outband_cfg_info *outband_cfg_info = buf_in;
+ struct hinic3_nic_io *nic_io = NULL;
+ struct hinic3_event_info event_info = {0};
+
+ nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io) {
+ pr_err("nic_io is NULL\n");
+ return;
+ }
+
+ nic_info(nic_io->dev_hdl, "outband vlan cfg event received\n");
+
+ if (in_size != sizeof(*outband_cfg_info)) {
+ nic_err(nic_io->dev_hdl, "outband cfg info invalid in_size: %u, should be %lu\n",
+ in_size, sizeof(*outband_cfg_info));
+ return;
+ }
+
+ event_info.service = EVENT_SRV_NIC;
+ event_info.type = EVENT_NIC_OUTBAND_CFG;
+ memcpy((void *)event_info.event_data,
+ outband_cfg_info, sizeof(*outband_cfg_info));
+
+ hinic3_event_callback(nic_io->hwdev, &event_info);
+}
+
static const struct nic_event_handler nic_cmd_handler[] = {
{
.cmd = HINIC3_NIC_CMD_VF_COS,
@@ -529,6 +599,11 @@ static const struct nic_event_handler nic_cmd_handler[] = {
.cmd = HINIC3_NIC_CMD_BOND_ACTIVE_NOTICE,
.handler = bond_active_event_handler,
},
+
+ {
+ .cmd = HINIC3_NIC_CMD_OUTBAND_CFG_NOTICE,
+ .handler = outband_vlan_cfg_event_handler,
+ },
};
static int _event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
@@ -543,6 +618,8 @@ static int _event_handler(void *hwdev, u16 cmd, void *buf_in, u16 in_size,
*out_size = 0;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
for (i = 0; i < size; i++) {
if (cmd == nic_cmd_handler[i].cmd) {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c
index a827f44..f3bb4c5 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.c
@@ -16,9 +16,10 @@
#include "hinic3_nic_cfg.h"
#include "hinic3_srv_nic.h"
#include "hinic3_nic.h"
-#include "hinic3_nic_cmd.h"
-#include "hinic3_nic_io.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_nic_cmdq.h"
+#include "hinic3_nic_io.h"
#define HINIC3_DEAULT_TX_CI_PENDING_LIMIT 1
#define HINIC3_DEAULT_TX_CI_COALESCING_TIME 1
@@ -35,7 +36,7 @@ MODULE_PARM_DESC(tx_coalescing_time, "TX CI coalescing parameter coalescing_time
static unsigned char rq_wqe_type = HINIC3_NORMAL_RQ_WQE;
module_param(rq_wqe_type, byte, 0444);
-MODULE_PARM_DESC(rq_wqe_type, "RQ WQE type 0-8Bytes, 1-16Bytes, 2-32Bytes (default=1)");
+MODULE_PARM_DESC(rq_wqe_type, "RQ WQE type 1-16Bytes, 2-32Bytes (default=2)");
/*lint +e806*/
static u32 tx_drop_thd_on = HINIC3_DEAULT_DROP_THD_ON;
@@ -46,7 +47,7 @@ static u32 tx_drop_thd_off = HINIC3_DEAULT_DROP_THD_OFF;
module_param(tx_drop_thd_off, uint, 0644);
MODULE_PARM_DESC(tx_drop_thd_off, "TX parameter drop_thd_off (default=0)");
/* performance: ci addr RTE_CACHE_SIZE(64B) alignment */
-#define HINIC3_CI_Q_ADDR_SIZE (64)
+#define HINIC3_CI_Q_ADDR_SIZE (64U)
#define CI_TABLE_SIZE(num_qps, pg_sz) \
(ALIGN((num_qps) * HINIC3_CI_Q_ADDR_SIZE, pg_sz))
@@ -255,7 +256,7 @@ static int hinic3_create_sq(struct hinic3_nic_io *nic_io, struct hinic3_io_queue
err = hinic3_wq_create(nic_io->hwdev, &sq->wq, sq_depth,
(u16)BIT(HINIC3_SQ_WQEBB_SHIFT));
- if (err) {
+ if (err != 0) {
sdk_err(nic_io->dev_hdl, "Failed to create tx queue(%u) wq\n",
q_id);
return err;
@@ -291,13 +292,22 @@ static int hinic3_create_rq(struct hinic3_nic_io *nic_io, struct hinic3_io_queue
{
int err;
- rq->wqe_type = (u8)(hinic3_get_rq_wqe_type(nic_io->hwdev));
+ /* rq_wqe_type Only support type 1-16Bytes, 2-32Bytes */
+ if (rq_wqe_type != HINIC3_NORMAL_RQ_WQE &&
+ rq_wqe_type != HINIC3_EXTEND_RQ_WQE) {
+ sdk_warn(nic_io->dev_hdl, "Module Parameter rq_wqe_type value %d is out of range: [%d, %d].",
+ rq_wqe_type, HINIC3_NORMAL_RQ_WQE,
+ HINIC3_EXTEND_RQ_WQE);
+ rq_wqe_type = HINIC3_NORMAL_RQ_WQE;
+ }
+
+ rq->wqe_type = rq_wqe_type;
rq->q_id = q_id;
rq->msix_entry_idx = rq_msix_idx;
err = hinic3_wq_create(nic_io->hwdev, &rq->wq, rq_depth,
(u16)BIT(HINIC3_RQ_WQEBB_SHIFT + rq->wqe_type));
- if (err) {
+ if (err != 0) {
sdk_err(nic_io->dev_hdl, "Failed to create rx queue(%u) wq\n",
q_id);
return err;
@@ -318,14 +328,14 @@ static int create_qp(struct hinic3_nic_io *nic_io, struct hinic3_io_queue *sq,
int err;
err = hinic3_create_sq(nic_io, sq, q_id, sq_depth, qp_msix_idx);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to create sq, qid: %u\n",
q_id);
return err;
}
err = hinic3_create_rq(nic_io, rq, q_id, rq_depth, qp_msix_idx);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to create rq, qid: %u\n",
q_id);
goto create_rq_err;
@@ -364,14 +374,14 @@ int hinic3_init_nicio_res(void *hwdev)
nic_io->max_qps = hinic3_func_max_qnum(hwdev);
err = hinic3_alloc_db_addr(hwdev, &db_base, NULL);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to allocate doorbell for sqs\n");
goto alloc_sq_db_fail;
}
nic_io->sqs_db_addr = (u8 *)db_base;
err = hinic3_alloc_db_addr(hwdev, &db_base, NULL);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to allocate doorbell for rqs\n");
goto alloc_rq_db_fail;
}
@@ -474,7 +484,7 @@ int hinic3_alloc_qps(void *hwdev, struct irq_info *qps_msix_arry,
for (q_id = 0; q_id < num_qps; q_id++) {
err = create_qp(nic_io, &sqs[q_id], &rqs[q_id], q_id, qp_params->sq_depth,
qp_params->rq_depth, qps_msix_arry[q_id].msix_entry_idx);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to allocate qp %u, err: %d\n", q_id, err);
goto create_qp_err;
}
@@ -599,14 +609,14 @@ int hinic3_create_qps(void *hwdev, u16 num_qp, u32 sq_depth, u32 rq_depth,
}
err = hinic3_init_nicio_res(hwdev);
- if (err)
+ if (err != 0)
return err;
qp_params.num_qps = num_qp;
qp_params.sq_depth = sq_depth;
qp_params.rq_depth = rq_depth;
err = hinic3_alloc_qps(hwdev, qps_msix_arry, &qp_params);
- if (err) {
+ if (err != 0) {
hinic3_deinit_nicio_res(hwdev);
nic_err(nic_io->dev_hdl,
"Failed to allocate qps, err: %d\n", err);
@@ -906,11 +916,11 @@ static int init_qp_ctxts(struct hinic3_nic_io *nic_io)
int err;
err = init_sq_ctxts(nic_io);
- if (err)
+ if (err != 0)
return err;
err = init_rq_ctxts(nic_io);
- if (err)
+ if (err != 0)
return err;
return 0;
@@ -1026,14 +1036,14 @@ int hinic3_init_qp_ctxts(void *hwdev)
return -EFAULT;
err = init_qp_ctxts(nic_io);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to init QP ctxts\n");
return err;
}
/* clean LRO/TSO context space */
err = clean_qp_offload_ctxt(nic_io);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to clean qp offload ctxts\n");
return err;
}
@@ -1042,13 +1052,13 @@ int hinic3_init_qp_ctxts(void *hwdev)
err = hinic3_set_root_ctxt(hwdev, rq_depth, nic_io->sq[0].wq.q_depth,
nic_io->rx_buff_len, HINIC3_CHANNEL_NIC);
- if (err) {
+ if (err != 0) {
nic_err(nic_io->dev_hdl, "Failed to set root context\n");
return err;
}
err = init_sq_ci_ctxts(nic_io);
- if (err)
+ if (err != 0)
goto clean_root_ctxt;
if (HINIC3_SUPPORT_RX_COMPACT_CQE(hwdev)) {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
index 37f923d..c5e02ad 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_io.h
@@ -317,7 +317,7 @@ static inline void hinic3_write_db(struct hinic3_io_queue *queue, int cos,
wmb(); /* Write all before the doorbell */
- writeq(*((u64 *)&db), DB_ADDR(queue, pi));
+ writeq(*((u64 *)(u8 *)&db), DB_ADDR(queue, pi));
}
struct hinic3_dyna_qp_params {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c
index 78d943d..9ea93a0 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_nic_prof.c
@@ -32,7 +32,7 @@ struct hinic3_prof_adapter nic_prof_adap_objs[] = {
void hinic3_init_nic_prof_adapter(struct hinic3_nic_dev *nic_dev)
{
- u16 num_adap = ARRAY_SIZE(nic_prof_adap_objs);
+ int num_adap = ARRAY_LEN(nic_prof_adap_objs);
nic_dev->prof_adap = hinic3_prof_init(nic_dev, nic_prof_adap_objs, num_adap,
(void *)&nic_dev->prof_attr);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c b/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c
index 6302fb8..dc4bb9e 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_ntuple.c
@@ -430,7 +430,8 @@ hinic3_dynamic_lookup_tcam_filter(struct hinic3_nic_dev *nic_dev,
list_for_each_entry(tmp,
&tcam_info->tcam_dynamic_info.tcam_dynamic_list,
block_list)
- if (tmp->dynamic_index_cnt < HINIC3_TCAM_DYNAMIC_BLOCK_SIZE)
+ if (tmp->dynamic_index_cnt < HINIC3_TCAM_DYNAMIC_BLOCK_SIZE ||
+ !tmp)
break;
if (!tmp || tmp->dynamic_index_cnt >= HINIC3_TCAM_DYNAMIC_BLOCK_SIZE) {
@@ -512,7 +513,7 @@ static int hinic3_add_tcam_filter(struct hinic3_nic_dev *nic_dev,
}
nicif_info(nic_dev, drv, nic_dev->netdev,
- "Add fdir tcam rule, function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, queue: %d, tcam_rule_nums: %d succeed\n",
+ "Add fdir tcam rule, function_id: 0x%x, tcam_block_id: %u, local_index: %u, global_index: %u, queue: %u, tcam_rule_nums: %u succeed\n",
hinic3_global_func_id(nic_dev->hwdev),
tcam_filter->dynamic_block_id, index, fdir_tcam_rule->index,
fdir_tcam_rule->data.qid, tcam_info->tcam_rule_nums + 1);
@@ -579,7 +580,7 @@ static int hinic3_del_tcam_filter(struct hinic3_nic_dev *nic_dev,
}
nicif_info(nic_dev, drv, nic_dev->netdev,
- "Del fdir_tcam_dynamic_rule function_id: 0x%x, tcam_block_id: %d, local_index: %d, global_index: %d, local_rules_nums: %d, global_rule_nums: %d succeed\n",
+ "Del fdir_tcam_dynamic_rule function_id: 0x%x, tcam_block_id: %u, local_index: %u, global_index: %u, local_rules_nums: %u, global_rule_nums: %u succeed\n",
hinic3_global_func_id(nic_dev->hwdev), dynamic_block_id,
tcam_filter->index, index, tmp->dynamic_index_cnt - 1,
tcam_info->tcam_rule_nums - 1);
@@ -605,7 +606,7 @@ static inline struct hinic3_tcam_filter *
hinic3_tcam_filter_lookup(const struct list_head *filter_list,
struct tag_tcam_key *key)
{
- struct hinic3_tcam_filter *iter;
+ struct hinic3_tcam_filter *iter = NULL;
list_for_each_entry(iter, filter_list, tcam_filter_list) {
if (memcmp(key, &iter->tcam_key,
@@ -630,7 +631,7 @@ static int hinic3_remove_one_rule(struct hinic3_nic_dev *nic_dev,
struct hinic3_ethtool_rx_flow_rule *eth_rule)
{
struct hinic3_tcam_info *tcam_info = &nic_dev->tcam;
- struct hinic3_tcam_filter *tcam_filter;
+ struct hinic3_tcam_filter *tcam_filter = NULL;
struct nic_tcam_cfg_rule fdir_tcam_rule;
struct tag_tcam_key tcam_key;
int err;
@@ -751,7 +752,7 @@ static int validate_flow(struct hinic3_nic_dev *nic_dev,
{
if (fs->location >= MAX_NUM_OF_ETHTOOL_NTUPLE_RULES) {
nicif_err(nic_dev, drv, nic_dev->netdev, "loc exceed limit[0,%lu]\n",
- MAX_NUM_OF_ETHTOOL_NTUPLE_RULES);
+ MAX_NUM_OF_ETHTOOL_NTUPLE_RULES - 1);
return -EINVAL;
}
@@ -872,7 +873,7 @@ int hinic3_ethtool_get_flow(const struct hinic3_nic_dev *nic_dev,
int hinic3_ethtool_get_all_flows(const struct hinic3_nic_dev *nic_dev,
struct ethtool_rxnfc *info, u32 *rule_locs)
{
- int idx = 0;
+ u32 idx = 0;
struct hinic3_ethtool_rx_flow_rule *eth_rule = NULL;
if (!HINIC3_SUPPORT_FDIR(nic_dev->hwdev)) {
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h b/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h
index a93f3b6..9202218 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_profile.h
@@ -38,13 +38,12 @@ struct hinic3_prof_adapter {
#define LLT_STATIC_DEF_SAVED
#endif
-/*lint -save -e661 */
static inline struct hinic3_prof_adapter *
hinic3_prof_init(void *device, struct hinic3_prof_adapter *adap_objs, int num_adap,
void **prof_attr)
{
struct hinic3_prof_adapter *prof_obj = NULL;
- u16 i;
+ int i;
for (i = 0; i < num_adap; i++) {
prof_obj = &adap_objs[i];
@@ -68,7 +67,6 @@ static inline void hinic3_prof_deinit(struct hinic3_prof_adapter *prof_obj, void
prof_obj->deinit(prof_attr);
}
-/*lint -restore*/
/* module-level interface */
#ifdef CONFIG_MODULE_PROF
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
index e4705c2..dcd79ee 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/dcbnl.h>
+#include <linux/init.h>
#include "ossl_knl.h"
#include "hinic3_crm.h"
@@ -23,7 +24,6 @@
#include "hinic3_hw.h"
#include "hinic3_rss.h"
-/*lint -e806*/
static u16 num_qps;
module_param(num_qps, ushort, 0444);
MODULE_PARM_DESC(num_qps, "Number of Queue Pairs (default=0)");
@@ -104,88 +104,83 @@ static int hinic3_get_rq2iq_map(struct hinic3_nic_dev *nic_dev,
return 0;
}
-static void hinic3_fillout_indir_tbl(struct hinic3_nic_dev *nic_dev, u8 num_cos, u32 *indir)
+static void hinic3_fillout_indir_tbl(struct hinic3_nic_dev *nic_dev,
+ u8 group_num, u32 *indir)
{
- u16 k, group_size, start_qid = 0, qp_num = 0;
- int i = 0;
- u8 j, cur_cos = 0, default_cos;
+ struct hinic3_dcb *dcb = nic_dev->dcb;
+ u16 k, group_size, start_qid = 0, cur_cos_qnum = 0;
+ u32 i = 0;
+ u8 j, cur_cos = 0, group = 0;
u8 valid_cos_map = hinic3_get_dev_valid_cos_map(nic_dev);
- if (num_cos == 0) {
+ if (group_num == 0) {
for (i = 0; i < NIC_RSS_INDIR_SIZE; i++)
indir[i] = i % nic_dev->q_params.num_qps;
} else {
- group_size = NIC_RSS_INDIR_SIZE / num_cos;
-
- for (j = 0; j < num_cos; j++) {
- while (cur_cos < NIC_DCB_COS_MAX &&
- nic_dev->hw_dcb_cfg.cos_qp_num[cur_cos] == 0)
- cur_cos++;
-
- if (cur_cos >= NIC_DCB_COS_MAX) {
- if (BIT(nic_dev->hw_dcb_cfg.default_cos) & valid_cos_map)
- default_cos = nic_dev->hw_dcb_cfg.default_cos;
- else
- default_cos = (u8)fls(valid_cos_map) - 1;
+ group_size = NIC_RSS_INDIR_SIZE / group_num;
+
+ for (group = 0; group < group_num; group++) {
+ cur_cos = dcb->hw_dcb_cfg.default_cos;
+ for (j = 0; j < NIC_DCB_COS_MAX; j++) {
+ if ((BIT(j) & valid_cos_map) != 0) {
+ cur_cos = j;
+ valid_cos_map -= (u8)BIT(j);
+ break;
+ }
+ }
- start_qid = nic_dev->hw_dcb_cfg.cos_qp_offset[default_cos];
- qp_num = nic_dev->hw_dcb_cfg.cos_qp_num[default_cos];
+ cur_cos_qnum = dcb->hw_dcb_cfg.cos_qp_num[cur_cos];
+ if (cur_cos_qnum > 0) {
+ start_qid =
+ dcb->hw_dcb_cfg.cos_qp_offset[cur_cos];
} else {
- start_qid = nic_dev->hw_dcb_cfg.cos_qp_offset[cur_cos];
- qp_num = nic_dev->hw_dcb_cfg.cos_qp_num[cur_cos];
+ start_qid = cur_cos % nic_dev->q_params.num_qps;
+ /* Ensure that the offset of start_id is 0. */
+ cur_cos_qnum = 1;
}
for (k = 0; k < group_size; k++)
- indir[i++] = start_qid + k % qp_num;
-
- cur_cos++;
+ indir[i++] = start_qid + k % cur_cos_qnum;
}
}
}
-/*lint -e528*/
int hinic3_rss_init(struct hinic3_nic_dev *nic_dev, u8 *rq2iq_map, u32 map_size, u8 dcb_en)
{
struct net_device *netdev = nic_dev->netdev;
- u8 i, cos_num;
- u8 cos_map[NIC_DCB_UP_MAX] = {0};
- u8 cfg_map[NIC_DCB_UP_MAX] = {0};
+ u8 i, group_num, cos_bitmap, group = 0;
+ u8 cos_group[NIC_DCB_UP_MAX] = {0};
int err;
- if (dcb_en) {
- cos_num = hinic3_get_dev_user_cos_num(nic_dev);
-
- if (nic_dev->hw_dcb_cfg.trust == 0) {
- memcpy(cfg_map, nic_dev->hw_dcb_cfg.pcp2cos, sizeof(cfg_map));
- } else if (nic_dev->hw_dcb_cfg.trust == 1) {
- for (i = 0; i < NIC_DCB_UP_MAX; i++)
- cfg_map[i] = nic_dev->hw_dcb_cfg.dscp2cos[i * NIC_DCB_DSCP_NUM];
- }
-#define COS_CHANGE_OFFSET 4
- for (i = 0; i < COS_CHANGE_OFFSET; i++)
- cos_map[COS_CHANGE_OFFSET + i] = cfg_map[i];
+ if (dcb_en != 0) {
+ group_num = (u8)roundup_pow_of_two(hinic3_get_dev_user_cos_num(nic_dev));
- for (i = 0; i < COS_CHANGE_OFFSET; i++)
- cos_map[i] = cfg_map[NIC_DCB_UP_MAX - (i + 1)];
+ cos_bitmap = hinic3_get_dev_valid_cos_map(nic_dev);
- while (cos_num & (cos_num - 1))
- cos_num++;
+ for (i = 0; i < NIC_DCB_UP_MAX; i++) {
+ if ((BIT(i) & cos_bitmap) != 0)
+ cos_group[NIC_DCB_UP_MAX - i - 1] = group++;
+ else
+ cos_group[NIC_DCB_UP_MAX - i - 1] =
+ group_num - 1;
+ }
} else {
- cos_num = 0;
+ group_num = 0;
}
- err = hinic3_set_hw_rss_parameters(netdev, 1, cos_num, cos_map, dcb_en);
+ err = hinic3_set_hw_rss_parameters(netdev, 1, group_num,
+ cos_group, dcb_en);
if (err)
return err;
- err = hinic3_get_rq2iq_map(nic_dev, nic_dev->q_params.num_qps, cos_num, cos_map,
- NIC_DCB_UP_MAX, nic_dev->rss_indir, rq2iq_map, map_size);
+ err = hinic3_get_rq2iq_map(nic_dev, nic_dev->q_params.num_qps,
+ group_num, cos_group, NIC_DCB_UP_MAX,
+ nic_dev->rss_indir, rq2iq_map, map_size);
if (err)
nicif_err(nic_dev, drv, netdev, "Failed to get rq map\n");
return err;
}
-/*lint -e528*/
void hinic3_rss_deinit(struct hinic3_nic_dev *nic_dev)
{
u8 cos_map[NIC_DCB_UP_MAX] = {0};
@@ -246,11 +241,29 @@ discard_user_rss_indir:
hinic3_set_default_rss_indir(netdev);
}
+#ifdef HAVE_HOT_REPLACE_FUNC
+bool partition_slave_doing_hotupgrade(void)
+{
+ return get_partition_role() && partition_doing_hotupgrade();
+}
+#endif
+
static void decide_num_qps(struct hinic3_nic_dev *nic_dev)
{
u16 tmp_num_qps = nic_dev->max_qps;
u16 num_cpus = 0;
+ u16 max_num_cpus;
int i, node;
+ int is_in_kexec = vram_get_kexec_flag();
+
+ if (is_in_kexec != 0) {
+ nic_dev->q_params.num_qps = nic_dev->nic_vram->vram_num_qps;
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "Os hotreplace use vram to init num qps 1:%u 2:%u\n",
+ nic_dev->q_params.num_qps,
+ nic_dev->nic_vram->vram_num_qps);
+ return;
+ }
if (nic_dev->nic_cap.default_num_queues != 0 &&
nic_dev->nic_cap.default_num_queues < nic_dev->max_qps)
@@ -258,16 +271,29 @@ static void decide_num_qps(struct hinic3_nic_dev *nic_dev)
MOD_PARA_VALIDATE_NUM_QPS(nic_dev, num_qps, tmp_num_qps);
- for (i = 0; i < (int)num_online_cpus(); i++) {
+#ifdef HAVE_HOT_REPLACE_FUNC
+ if (partition_slave_doing_hotupgrade())
+ max_num_cpus = (u16)num_present_cpus();
+ else
+ max_num_cpus = (u16)num_online_cpus();
+#else
+ max_num_cpus = (u16)num_online_cpus();
+#endif
+
+ for (i = 0; i < max_num_cpus; i++) {
node = (int)cpu_to_node(i);
if (node == dev_to_node(&nic_dev->pdev->dev))
num_cpus++;
}
if (!num_cpus)
- num_cpus = (u16)num_online_cpus();
+ num_cpus = max_num_cpus;
nic_dev->q_params.num_qps = (u16)min_t(u16, tmp_num_qps, num_cpus);
+ nic_dev->nic_vram->vram_num_qps = nic_dev->q_params.num_qps;
+ nicif_info(nic_dev, drv, nic_dev->netdev,
+ "init num qps 1:%u 2:%u\n",
+ nic_dev->q_params.num_qps, nic_dev->nic_vram->vram_num_qps);
}
static void copy_value_to_rss_hkey(struct hinic3_nic_dev *nic_dev,
@@ -322,7 +348,6 @@ static int alloc_rss_resource(struct hinic3_nic_dev *nic_dev)
return 0;
}
-/*lint -e528*/
void hinic3_try_to_enable_rss(struct hinic3_nic_dev *nic_dev)
{
u8 cos_map[NIC_DCB_UP_MAX] = {0};
@@ -361,6 +386,7 @@ void hinic3_try_to_enable_rss(struct hinic3_nic_dev *nic_dev)
set_q_params:
clear_bit(HINIC3_RSS_ENABLE, &nic_dev->flags);
nic_dev->q_params.num_qps = nic_dev->max_qps;
+ nic_dev->nic_vram->vram_num_qps = nic_dev->max_qps;
}
static int hinic3_config_rss_hw_resource(struct hinic3_nic_dev *nic_dev,
@@ -754,6 +780,7 @@ int hinic3_set_channels(struct net_device *netdev,
nic_dev->q_params.num_qps = (u16)count;
}
+ nic_dev->nic_vram->vram_num_qps = nic_dev->q_params.num_qps;
return 0;
}
@@ -814,7 +841,7 @@ int hinic3_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
int err = 0;
if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Rss is disable\n");
+ netdev_warn_once(nic_dev->netdev, "Rss is disable\n");
return -EOPNOTSUPP;
}
@@ -921,7 +948,7 @@ int hinic3_get_rxfh_indir(struct net_device *netdev, u32 *indir)
indir = indir1->ring_index;
#endif
if (!test_bit(HINIC3_RSS_ENABLE, &nic_dev->flags)) {
- nicif_err(nic_dev, drv, nic_dev->netdev, "Rss is disable\n");
+ netdev_warn_once(nic_dev->netdev, "Rss is disable\n");
return -EOPNOTSUPP;
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c
index 071418d..4f4b18c 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rss_cfg.c
@@ -15,14 +15,15 @@
#include "ossl_knl.h"
#include "hinic3_crm.h"
#include "hinic3_nic_cfg.h"
-#include "hinic3_nic_cmd.h"
+#include "nic_mpu_cmd.h"
+#include "nic_npu_cmd.h"
#include "hinic3_hw.h"
#include "hinic3_nic.h"
#include "hinic3_nic_cmdq.h"
#include "hinic3_common.h"
static int hinic3_rss_cfg_hash_key(struct hinic3_nic_io *nic_io, u8 opcode,
- u8 *key)
+ u8 *key, u16 key_size)
{
struct hinic3_cmd_rss_hash_key hash_key;
u16 out_size = sizeof(hash_key);
@@ -33,7 +34,7 @@ static int hinic3_rss_cfg_hash_key(struct hinic3_nic_io *nic_io, u8 opcode,
hash_key.opcode = opcode;
if (opcode == HINIC3_CMD_OP_SET)
- memcpy(hash_key.key, key, NIC_RSS_KEY_SIZE);
+ memcpy(hash_key.key, key, key_size);
err = l2nic_msg_to_mgmt_sync(nic_io->hwdev,
HINIC3_NIC_CMD_CFG_RSS_HASH_KEY,
@@ -47,7 +48,7 @@ static int hinic3_rss_cfg_hash_key(struct hinic3_nic_io *nic_io, u8 opcode,
}
if (opcode == HINIC3_CMD_OP_GET)
- memcpy(key, hash_key.key, NIC_RSS_KEY_SIZE);
+ memcpy(key, hash_key.key, key_size);
return 0;
}
@@ -61,8 +62,12 @@ int hinic3_rss_set_hash_key(void *hwdev, const u8 *key)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memcpy(hash_key, key, NIC_RSS_KEY_SIZE);
- return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_SET, hash_key);
+ return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_SET,
+ hash_key, NIC_RSS_KEY_SIZE);
}
int hinic3_rss_get_hash_key(void *hwdev, u8 *key)
@@ -73,7 +78,11 @@ int hinic3_rss_get_hash_key(void *hwdev, u8 *key)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
- return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_GET, key);
+ if (!nic_io)
+ return -EINVAL;
+
+ return hinic3_rss_cfg_hash_key(nic_io, HINIC3_CMD_OP_GET,
+ key, NIC_RSS_KEY_SIZE);
}
int hinic3_rss_get_indir_tbl(void *hwdev, u32 *indir_table)
@@ -89,6 +98,7 @@ int hinic3_rss_get_indir_tbl(void *hwdev, u32 *indir_table)
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
if (nic_io == NULL)
return -EINVAL;
+
cmd_buf = hinic3_alloc_cmd_buf(hwdev);
if (cmd_buf == NULL) {
nic_err(nic_io->dev_hdl, "Failed to allocate cmd_buf.\n");
@@ -159,6 +169,8 @@ static int hinic3_cmdq_set_rss_type(void *hwdev, struct nic_rss_type rss_type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
cmd_buf = hinic3_alloc_cmd_buf(hwdev);
if (!cmd_buf) {
@@ -210,6 +222,9 @@ static int hinic3_mgmt_set_rss_type(void *hwdev, struct nic_rss_type rss_type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memset(&ctx_tbl, 0, sizeof(ctx_tbl));
ctx_tbl.func_id = hinic3_global_func_id(hwdev);
ctx |= HINIC3_RSS_TYPE_SET(1, VALID) |
@@ -259,6 +274,8 @@ int hinic3_get_rss_type(void *hwdev, struct nic_rss_type *rss_type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
memset(&ctx_tbl, 0, sizeof(struct hinic3_rss_context_table));
ctx_tbl.func_id = hinic3_global_func_id(hwdev);
@@ -292,6 +309,9 @@ static int hinic3_rss_cfg_hash_engine(struct hinic3_nic_io *nic_io, u8 opcode,
u16 out_size = sizeof(hash_type);
int err;
+ if (!nic_io)
+ return -EINVAL;
+
memset(&hash_type, 0, sizeof(struct hinic3_cmd_rss_engine_type));
hash_type.func_id = hinic3_global_func_id(nic_io->hwdev);
@@ -325,6 +345,9 @@ int hinic3_rss_set_hash_engine(void *hwdev, u8 type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
return hinic3_rss_cfg_hash_engine(nic_io, HINIC3_CMD_OP_SET, &type);
}
@@ -336,6 +359,9 @@ int hinic3_rss_get_hash_engine(void *hwdev, u8 *type)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
return hinic3_rss_cfg_hash_engine(nic_io, HINIC3_CMD_OP_GET, type);
}
@@ -351,6 +377,9 @@ int hinic3_rss_cfg(void *hwdev, u8 rss_en, u8 cos_num, u8 *prio_tc, u16 num_qps)
return -EINVAL;
nic_io = hinic3_get_service_adapter(hwdev, SERVICE_T_NIC);
+ if (!nic_io)
+ return -EINVAL;
+
memset(&rss_cfg, 0, sizeof(struct hinic3_cmd_rss_config));
rss_cfg.func_id = hinic3_global_func_id(hwdev);
rss_cfg.rss_en = rss_en;
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
index f8a866d..936258c 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.c
@@ -21,6 +21,7 @@
#include <linux/ipv6.h>
#include <linux/module.h>
#include <linux/compiler.h>
+#include <linux/filter.h>
#include "ossl_knl.h"
#include "hinic3_crm.h"
@@ -63,19 +64,31 @@ static bool rx_alloc_mapped_page(struct hinic3_nic_dev *nic_dev,
struct pci_dev *pdev = nic_dev->pdev;
struct page *page = rx_info->page;
dma_addr_t dma = rx_info->buf_dma_addr;
+ u32 page_offset = 0;
if (likely(dma))
return true;
/* alloc new page for storage */
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ page = page_pool_alloc_frag(rx_info->page_pool, &page_offset,
+ nic_dev->rx_buff_len,
+ GFP_ATOMIC | __GFP_COLD | __GFP_COMP);
+ if (unlikely(!page))
+ return false;
+ dma = page_pool_get_dma_addr(page);
+ goto set_rx_info;
+ }
+#endif
page = alloc_pages_node(NUMA_NO_NODE, GFP_ATOMIC | __GFP_COLD |
__GFP_COMP, nic_dev->page_order);
if (unlikely(!page))
return false;
/* map page for use */
- dma = dma_map_page(&pdev->dev, page, 0, nic_dev->dma_rx_buff_size,
- DMA_FROM_DEVICE);
+ dma = dma_map_page(&pdev->dev, page, page_offset,
+ nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE);
/* if mapping failed free memory back to system since
* there isn't much point in holding memory we can't use
*/
@@ -83,10 +96,12 @@ static bool rx_alloc_mapped_page(struct hinic3_nic_dev *nic_dev,
__free_pages(page, nic_dev->page_order);
return false;
}
+ goto set_rx_info;
+set_rx_info:
rx_info->page = page;
rx_info->buf_dma_addr = dma;
- rx_info->page_offset = 0;
+ rx_info->page_offset = page_offset;
return true;
}
@@ -108,7 +123,7 @@ static u32 hinic3_rx_fill_wqe(struct hinic3_rxq *rxq)
/* unit of cqe length is 16B */
hinic3_set_sge(&rq_wqe->extend_wqe.cqe_sect.sge,
rx_info->cqe_dma,
- (sizeof(struct hinic3_rq_cqe) >>
+ (HINIC3_CQE_LEN >>
HINIC3_CQE_SIZE_SHIFT));
/* use fixed len */
rq_wqe->extend_wqe.buf_desc.sge.len =
@@ -169,7 +184,7 @@ static u32 hinic3_rx_fill_buffers(struct hinic3_rxq *rxq)
if (likely(i)) {
hinic3_write_db(rxq->rq,
- rxq->q_id & 3,
+ rxq->q_id & (NIC_RX_DB_COS_MAX - 1),
RQ_CFLAG_DP,
(u16)((u32)rxq->next_to_update <<
rxq->rq->wqe_type));
@@ -206,6 +221,18 @@ static void hinic3_rx_free_buffers(struct hinic3_nic_dev *nic_dev, u32 q_depth,
for (i = 0; i < q_depth; i++) {
rx_info = &rx_info_arr[i];
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ if (rx_info->page) {
+ page_pool_put_full_page(rx_info->page_pool,
+ rx_info->page, false);
+ rx_info->buf_dma_addr = 0;
+ rx_info->page = NULL;
+ }
+ continue;
+ }
+#endif
+
if (rx_info->buf_dma_addr) {
dma_unmap_page(&nic_dev->pdev->dev,
rx_info->buf_dma_addr,
@@ -265,8 +292,15 @@ static bool hinic3_add_rx_frag(struct hinic3_rxq *rxq,
DMA_FROM_DEVICE);
if (size <= HINIC3_RX_HDR_SIZE && !skb_is_nonlinear(skb)) {
- memcpy(__skb_put(skb, size), va + offset,
- ALIGN(size, sizeof(long))); /*lint !e666*/
+ __skb_put_data(skb, va + offset, size);
+
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ page_pool_put_full_page(rx_info->page_pool,
+ page, false);
+ return false;
+ }
+#endif
/* page is not reserved, we can reuse buffer as-is */
if (likely(page_to_nid(page) == numa_node_id()))
@@ -274,25 +308,38 @@ static bool hinic3_add_rx_frag(struct hinic3_rxq *rxq,
/* this page cannot be reused so discard it */
put_page(page);
- return false;
+ goto discard_page;
}
skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
- (int)(rx_info->page_offset + offset), (int)size, rxq->buf_len);
+ (int)(rx_info->page_offset + offset), (int)size,
+ rxq->buf_len);
+
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ skb_mark_for_recycle(skb);
+ return false;
+ }
+#endif
/* avoid re-using remote pages */
if (unlikely(page_to_nid(page) != numa_node_id()))
- return false;
+ goto discard_page;
/* if we are only owner of page we can reuse it */
if (unlikely(page_count(page) != 1))
- return false;
+ goto discard_page;
/* flip page offset to other buffer */
rx_info->page_offset ^= rxq->buf_len;
get_page(page);
return true;
+
+discard_page:
+ dma_unmap_page(rxq->dev, rx_info->buf_dma_addr,
+ rxq->dma_rx_buff_size, DMA_FROM_DEVICE);
+ return false;
}
static void packaging_skb(struct hinic3_rxq *rxq, struct sk_buff *head_skb,
@@ -338,10 +385,6 @@ static void packaging_skb(struct hinic3_rxq *rxq, struct sk_buff *head_skb,
if (likely(hinic3_add_rx_frag(rxq, rx_info, skb, frag_size, tmp_pkt_offset))) {
hinic3_reuse_rx_page(rxq, rx_info);
- } else {
- /* we are not reusing the buffer so unmap it */
- dma_unmap_page(rxq->dev, rx_info->buf_dma_addr,
- rxq->dma_rx_buff_size, DMA_FROM_DEVICE);
}
/* clear contents of buffer_info */
rx_info->buf_dma_addr = 0;
@@ -486,9 +529,8 @@ static unsigned int hinic3_eth_get_headlen(unsigned char *data, unsigned int max
protocol = hdr.eth->h_proto;
/* L2 header */
- /*lint -save -e778*/
if (protocol == htons(ETH_P_8021_AD) ||
- protocol == htons(ETH_P_8021_Q)) { /*lint -restore*/
+ protocol == htons(ETH_P_8021_Q)) {
if (unlikely(max_len < ETH_HLEN + VLAN_HLEN))
return max_len;
@@ -500,9 +542,8 @@ static unsigned int hinic3_eth_get_headlen(unsigned char *data, unsigned int max
}
/* L3 header */
- /*lint -save -e778*/
switch (protocol) {
- case htons(ETH_P_IP): /*lint -restore*/
+ case htons(ETH_P_IP):
if ((int)(hdr.data - data) >
(int)(max_len - sizeof(struct iphdr)))
return max_len;
@@ -713,7 +754,10 @@ static inline void hinic3_lro_set_gso_params(struct sk_buff *skb, u16 num_lro)
}
#ifdef HAVE_XDP_SUPPORT
-enum hinic3_xdp_pkt {
+enum hinic3_xdp_status {
+ // bpf_prog status
+ HINIC3_XDP_PROG_EMPTY,
+ // pkt action
HINIC3_XDP_PKT_PASS,
HINIC3_XDP_PKT_DROP,
};
@@ -724,9 +768,15 @@ static void update_drop_rx_info(struct hinic3_rxq *rxq, u16 weqbb_num)
while (weqbb_num) {
rx_info = &rxq->rx_info[rxq->cons_idx & rxq->q_mask];
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool)
+ goto discard_direct;
+#endif
if (likely(page_to_nid(rx_info->page) == numa_node_id()))
hinic3_reuse_rx_page(rxq, rx_info);
+ goto discard_direct;
+discard_direct:
rx_info->buf_dma_addr = 0;
rx_info->page = NULL;
rxq->cons_idx++;
@@ -736,11 +786,11 @@ static void update_drop_rx_info(struct hinic3_rxq *rxq, u16 weqbb_num)
}
}
-int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len)
+int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len, struct xdp_buff *xdp)
{
struct bpf_prog *xdp_prog = NULL;
struct hinic3_rx_info *rx_info = NULL;
- struct xdp_buff xdp;
+ struct net_device *netdev = rxq->netdev;
int result = HINIC3_XDP_PKT_PASS;
u16 weqbb_num = 1; /* xdp can only use one rx_buff */
u8 *va = NULL;
@@ -748,13 +798,14 @@ int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len)
rcu_read_lock();
xdp_prog = READ_ONCE(rxq->xdp_prog);
- if (!xdp_prog)
+ if (!xdp_prog) {
+ result = HINIC3_XDP_PROG_EMPTY;
goto unlock_rcu;
+ }
if (unlikely(pkt_len > rxq->buf_len)) {
RXQ_STATS_INC(rxq, xdp_large_pkt);
- weqbb_num = (u16)(pkt_len >> rxq->rx_buff_shift) +
- ((pkt_len & (rxq->buf_len - 1)) ? 1 : 0);
+ weqbb_num = HINIC3_GET_SGE_NUM(pkt_len, rxq);
result = HINIC3_XDP_PKT_DROP;
goto xdp_out;
}
@@ -765,26 +816,27 @@ int hinic3_run_xdp(struct hinic3_rxq *rxq, u32 pkt_len)
dma_sync_single_range_for_cpu(rxq->dev, rx_info->buf_dma_addr,
rx_info->page_offset,
rxq->buf_len, DMA_FROM_DEVICE);
- xdp.data = va;
- xdp.data_hard_start = xdp.data;
- xdp.data_end = xdp.data + pkt_len;
+ xdp->data = va;
+ xdp->data_hard_start = xdp->data;
+ xdp->data_end = xdp->data + pkt_len;
#ifdef HAVE_XDP_FRAME_SZ
- xdp.frame_sz = rxq->buf_len;
+ xdp->frame_sz = rxq->buf_len;
#endif
#ifdef HAVE_XDP_DATA_META
- xdp_set_data_meta_invalid(&xdp);
+ xdp_set_data_meta_invalid(xdp);
#endif
- prefetchw(xdp.data_hard_start);
- act = bpf_prog_run_xdp(xdp_prog, &xdp);
+ prefetchw(xdp->data_hard_start);
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
switch (act) {
case XDP_PASS:
+ result = HINIC3_XDP_PKT_PASS;
break;
case XDP_DROP:
result = HINIC3_XDP_PKT_DROP;
break;
default:
result = HINIC3_XDP_PKT_DROP;
- bpf_warn_invalid_xdp_action(rxq->netdev, xdp_prog, act);
+ bpf_warn_invalid_xdp_action(netdev, xdp_prog, act);
}
xdp_out:
@@ -798,9 +850,86 @@ unlock_rcu:
return result;
}
+
+static bool hinic3_add_rx_frag_with_xdp(struct hinic3_rxq *rxq, u32 pkt_len,
+ struct hinic3_rx_info *rx_info,
+ struct sk_buff *skb, struct xdp_buff *xdp)
+{
+ struct page *page = rx_info->page;
+
+ if (pkt_len <= HINIC3_RX_HDR_SIZE) {
+ __skb_put_data(skb, xdp->data, pkt_len);
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ page_pool_put_full_page(rx_info->page_pool, page, false);
+ return false;
+ }
+#endif
+ if (likely(page_to_nid(page) == numa_node_id()))
+ return true;
+
+ put_page(page);
+ goto umap_page;
+ }
+
+ skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
+ (int)(rx_info->page_offset +
+ (xdp->data - xdp->data_hard_start)),
+ (int)pkt_len, rxq->buf_len);
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool) {
+ skb_mark_for_recycle(skb);
+ return false;
+ }
+#endif
+ if (unlikely(page_to_nid(page) != numa_node_id()))
+ goto umap_page;
+ if (unlikely(page_count(page) != 1))
+ goto umap_page;
+
+ rx_info->page_offset ^= rxq->buf_len;
+ get_page(page);
+
+ return true;
+umap_page:
+ dma_unmap_page(rxq->dev, rx_info->buf_dma_addr,
+ rxq->dma_rx_buff_size, DMA_FROM_DEVICE);
+ return false;
+}
+
+static struct sk_buff *hinic3_fetch_rx_buffer_xdp(struct hinic3_rxq *rxq,
+ u32 pkt_len,
+ struct xdp_buff *xdp)
+{
+ struct sk_buff *skb;
+ struct hinic3_rx_info *rx_info;
+ u32 sw_ci;
+ bool reuse;
+
+ sw_ci = rxq->cons_idx & rxq->q_mask;
+ rx_info = &rxq->rx_info[sw_ci];
+
+ skb = netdev_alloc_skb_ip_align(rxq->netdev, HINIC3_RX_HDR_SIZE);
+ if (unlikely(!skb))
+ return NULL;
+
+ reuse = hinic3_add_rx_frag_with_xdp(rxq, pkt_len, rx_info, skb, xdp);
+ if (likely(reuse))
+ hinic3_reuse_rx_page(rxq, rx_info);
+
+ rx_info->buf_dma_addr = 0;
+ rx_info->page = NULL;
+
+ rxq->cons_idx += 1;
+ rxq->delta += 1;
+
+ return skb;
+}
+
#endif
-static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_cqe_info *cqe_info)
+static int recv_one_pkt(struct hinic3_rxq *rxq,
+ struct hinic3_cqe_info *cqe_info)
{
struct sk_buff *skb = NULL;
struct net_device *netdev = rxq->netdev;
@@ -808,13 +937,25 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_cqe_info *cqe_info
#ifdef HAVE_XDP_SUPPORT
u32 xdp_status;
+ struct xdp_buff xdp = { 0 };
- xdp_status = (u32)(hinic3_run_xdp(rxq, cqe_info->pkt_len));
+ xdp_status = (u32)(hinic3_run_xdp(rxq, cqe_info->pkt_len, &xdp));
if (xdp_status == HINIC3_XDP_PKT_DROP)
return 0;
-#endif
+ // build skb
+ if (xdp_status != HINIC3_XDP_PROG_EMPTY) {
+ // xdp_prog configured, build skb with xdp
+ skb = hinic3_fetch_rx_buffer_xdp(rxq, cqe_info->pkt_len, &xdp);
+ } else {
+ // xdp_prog not configured, build skb
+ skb = hinic3_fetch_rx_buffer(rxq, cqe_info);
+ }
+#else
+
+ // xdp is not supported
skb = hinic3_fetch_rx_buffer(rxq, cqe_info);
+#endif
if (unlikely(!skb)) {
RXQ_STATS_INC(rxq, alloc_skb_err);
return -ENOMEM;
@@ -842,7 +983,7 @@ static int recv_one_pkt(struct hinic3_rxq *rxq, struct hinic3_cqe_info *cqe_info
if (unlikely(test_bit(HINIC3_LP_TEST, &nic_dev->flags)))
hinic3_copy_lp_data(nic_dev, skb);
- if (cqe_info->lro_num)
+ if (cqe_info->lro_num > 1)
hinic3_lro_set_gso_params(skb, cqe_info->lro_num);
skb_record_rx_queue(skb, rxq->q_id);
@@ -1021,12 +1162,39 @@ int hinic3_rx_poll(struct hinic3_rxq *rxq, int budget)
return pkts;
}
+#ifdef HAVE_PAGE_POOL_SUPPORT
+static struct page_pool *hinic3_create_page_pool(struct hinic3_nic_dev *nic_dev,
+ u32 rq_depth,
+ struct hinic3_rx_info *rx_info_arr)
+{
+ struct page_pool_params pp_params = {
+ .flags = PP_FLAG_DMA_MAP | PP_FLAG_PAGE_FRAG | PP_FLAG_DMA_SYNC_DEV,
+ .order = nic_dev->page_order,
+ .pool_size = rq_depth * nic_dev->rx_buff_len /
+ (PAGE_SIZE << nic_dev->page_order),
+ .nid = dev_to_node(&nic_dev->pdev->dev),
+ .dev = &nic_dev->pdev->dev,
+ .dma_dir = DMA_FROM_DEVICE,
+ .offset = 0,
+ .max_len = PAGE_SIZE << nic_dev->page_order,
+ };
+ struct page_pool *page_pool;
+ int i;
+
+ page_pool = nic_dev->page_pool_enabled ?
+ page_pool_create(&pp_params) : NULL;
+ for (i = 0; i < rq_depth; i++)
+ rx_info_arr[i].page_pool = page_pool;
+ return page_pool;
+}
+#endif
+
int hinic3_alloc_rxqs_res(struct hinic3_nic_dev *nic_dev, u16 num_rq,
u32 rq_depth, struct hinic3_dyna_rxq_res *rxqs_res)
{
struct hinic3_dyna_rxq_res *rqres = NULL;
u64 cqe_mem_size = sizeof(struct hinic3_rq_cqe) * rq_depth;
- int idx, i;
+ int idx;
u32 pkts;
u64 size;
@@ -1045,51 +1213,53 @@ int hinic3_alloc_rxqs_res(struct hinic3_nic_dev *nic_dev, u16 num_rq,
if (!rqres->rx_info) {
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc rxq%d rx info\n", idx);
- goto err_out;
+ goto err_alloc_rx_info;
}
-
if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
rqres->cqe_start_vaddr =
- dma_zalloc_coherent(&nic_dev->pdev->dev, cqe_mem_size,
+ dma_zalloc_coherent(&nic_dev->pdev->dev,
+ cqe_mem_size,
&rqres->cqe_start_paddr,
GFP_KERNEL);
if (!rqres->cqe_start_vaddr) {
- kfree(rqres->rx_info);
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc rxq%d cqe\n", idx);
- goto err_out;
+ goto err_alloc_cqe;
}
}
+
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ rqres->page_pool = hinic3_create_page_pool(nic_dev, rq_depth,
+ rqres->rx_info);
+ if (nic_dev->page_pool_enabled && !rqres->page_pool) {
+ nicif_err(nic_dev, drv, nic_dev->netdev,
+ "Failed to create rxq%d page pool\n", idx);
+ goto err_create_page_pool;
+ }
+#endif
pkts = hinic3_rx_alloc_buffers(nic_dev, rq_depth,
rqres->rx_info);
if (!pkts) {
- if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
- dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
- rqres->cqe_start_vaddr,
- rqres->cqe_start_paddr);
- }
- kfree(rqres->rx_info);
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc rxq%d rx buffers\n", idx);
- goto err_out;
+ goto err_alloc_buffers;
}
rqres->next_to_alloc = (u16)pkts;
}
return 0;
-err_out:
- for (i = 0; i < idx; i++) {
- rqres = &rxqs_res[i];
-
- hinic3_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info);
- if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
- dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
- rqres->cqe_start_vaddr,
- rqres->cqe_start_paddr);
- }
- kfree(rqres->rx_info);
- }
-
+err_alloc_buffers:
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ page_pool_destroy(rqres->page_pool);
+err_create_page_pool:
+#endif
+ dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
+ rqres->cqe_start_vaddr,
+ rqres->cqe_start_paddr);
+err_alloc_cqe:
+ kfree(rqres->rx_info);
+err_alloc_rx_info:
+ hinic3_free_rxqs_res(nic_dev, idx, rq_depth, rxqs_res);
return -ENOMEM;
}
@@ -1104,6 +1274,10 @@ void hinic3_free_rxqs_res(struct hinic3_nic_dev *nic_dev, u16 num_rq,
rqres = &rxqs_res[idx];
hinic3_rx_free_buffers(nic_dev, rq_depth, rqres->rx_info);
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rqres->page_pool)
+ page_pool_destroy(rqres->page_pool);
+#endif
if (nic_dev->cqe_mode == HINIC3_RQ_CQE_SEPARATE) {
dma_free_coherent(&nic_dev->pdev->dev, cqe_mem_size,
rqres->cqe_start_vaddr,
@@ -1191,6 +1365,7 @@ void hinic3_free_rxqs(struct net_device *netdev)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
kfree(nic_dev->rxqs);
+ nic_dev->rxqs = NULL;
}
int hinic3_alloc_rxqs(struct net_device *netdev)
@@ -1312,6 +1487,14 @@ int rxq_restore(struct hinic3_nic_dev *nic_dev, u16 q_id, u16 hw_ci)
nic_info(&nic_dev->pdev->dev, "rxq %u restore_buf_num:%u\n", q_id, rxq->restore_buf_num);
rx_info = &rxq->rx_info[(hw_ci + rxq->q_depth - 1) & rxq->q_mask];
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ if (rx_info->page_pool && rx_info->page) {
+ page_pool_put_full_page(rx_info->page_pool, rx_info->page, false);
+ rx_info->buf_dma_addr = 0;
+ rx_info->page = NULL;
+ goto reset_rxq;
+ }
+#endif
if (rx_info->buf_dma_addr) {
dma_unmap_page(&nic_dev->pdev->dev, rx_info->buf_dma_addr,
nic_dev->dma_rx_buff_size, DMA_FROM_DEVICE);
@@ -1322,7 +1505,9 @@ int rxq_restore(struct hinic3_nic_dev *nic_dev, u16 q_id, u16 hw_ci)
__free_pages(rx_info->page, nic_dev->page_order);
rx_info->page = NULL;
}
+ goto reset_rxq;
+reset_rxq:
rxq->delta = 1;
rxq->next_to_update = (u16)((hw_ci + rxq->q_depth - 1) & rxq->q_mask);
rxq->cons_idx = (u16)((rxq->next_to_update + 1) & rxq->q_mask);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
index 586a221..480f787 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_rx.h
@@ -4,6 +4,10 @@
#ifndef HINIC3_RX_H
#define HINIC3_RX_H
+#ifdef HAVE_PAGE_POOL_SUPPORT
+#include <net/page_pool/helpers.h>
+#endif
+
#include <linux/types.h>
#include <linux/device.h>
#include <linux/mm_types.h>
@@ -27,6 +31,7 @@
#define HINIC3_RX_CSUM_IPSU_OTHER_ERR BIT(8)
#define HINIC3_HEADER_DATA_UNIT 2
+#define HINIC3_CQE_LEN 32
#define HINIC3_COMPACT_CQE_8B 8
#define HINIC3_COMPACT_CQE_16B 16
@@ -35,20 +40,20 @@
#define HINIC3_RQ_CQE_INTEGRATE 1
struct hinic3_rxq_stats {
- u64 packets;
- u64 bytes;
- u64 errors;
- u64 csum_errors;
- u64 other_errors;
- u64 dropped;
- u64 xdp_dropped;
- u64 rx_buf_empty;
-
- u64 alloc_skb_err;
- u64 alloc_rx_buf_err;
- u64 xdp_large_pkt;
- u64 restore_drop_sge;
- u64 rsvd2;
+ u64 packets;
+ u64 bytes;
+ u64 errors;
+ u64 csum_errors;
+ u64 other_errors;
+ u64 dropped;
+ u64 xdp_dropped;
+ u64 rx_buf_empty;
+
+ u64 alloc_skb_err;
+ u64 alloc_rx_buf_err;
+ u64 xdp_large_pkt;
+ u64 restore_drop_sge;
+ u64 rsvd2;
#ifdef HAVE_NDO_GET_STATS64
struct u64_stats_sync syncp;
#else
@@ -62,6 +67,9 @@ struct hinic3_rx_info {
struct hinic3_rq_cqe *cqe;
dma_addr_t cqe_dma;
struct page *page;
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ struct page_pool *page_pool;
+#endif
u32 page_offset;
u32 rsvd1;
struct hinic3_rq_wqe *rq_wqe;
@@ -102,7 +110,7 @@ struct hinic3_rxq {
u16 next_to_update;
struct device *dev; /* device for DMA mapping */
- unsigned long status;
+ u64 status;
dma_addr_t cqe_start_paddr;
void *cqe_start_vaddr;
@@ -130,6 +138,9 @@ struct hinic3_dyna_rxq_res {
struct hinic3_rx_info *rx_info;
dma_addr_t cqe_start_paddr;
void *cqe_start_vaddr;
+#ifdef HAVE_PAGE_POOL_SUPPORT
+ struct page_pool *page_pool;
+#endif
};
int hinic3_alloc_rxqs(struct net_device *netdev);
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h b/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h
index bdd5a8e..d816609 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_srv_nic.h
@@ -11,10 +11,12 @@
#ifndef HINIC3_SRV_NIC_H
#define HINIC3_SRV_NIC_H
-#include "hinic3_mgmt_interface.h"
+#include <linux/netdevice.h>
#include "mag_mpu_cmd.h"
-#include "mag_cmd.h"
+#include "mag_mpu_cmd_defs.h"
#include "hinic3_lld.h"
+#include "nic_cfg_comm.h"
+#include "nic_mpu_cmd_defs.h"
enum hinic3_queue_type {
HINIC3_SQ,
@@ -64,6 +66,7 @@ enum hinic3_nic_event_type {
EVENT_NIC_DCB_STATE_CHANGE,
EVENT_NIC_BOND_DOWN,
EVENT_NIC_BOND_UP,
+ EVENT_NIC_OUTBAND_CFG,
};
/* *
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
index bc1a8ef..99264c7 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_tx.c
@@ -223,24 +223,72 @@ static void get_inner_l3_l4_type(struct sk_buff *skb, union hinic3_ip *ip,
enum sq_l3_type *l3_type, u8 *l4_proto)
{
unsigned char *exthdr = NULL;
- __be16 frag_off = 0;
if (ip->v4->version == IP4_VERSION) {
*l3_type = IPV4_PKT_WITH_CHKSUM_OFFLOAD;
*l4_proto = ip->v4->protocol;
+
+#ifdef HAVE_OUTER_IPV6_TUNNEL_OFFLOAD
+ /* inner_transport_header is wrong in centos7.0 and suse12.1 */
+ l4->hdr = ip->hdr + ((u8)ip->v4->ihl << IP_HDR_IHL_UNIT_SHIFT);
+#endif
} else if (ip->v4->version == IP6_VERSION) {
*l3_type = IPV6_PKT;
exthdr = ip->hdr + sizeof(*ip->v6);
*l4_proto = ip->v6->nexthdr;
- if (exthdr != l4->hdr)
+ if (exthdr != l4->hdr) {
+ __be16 frag_off = 0;
+#ifndef HAVE_OUTER_IPV6_TUNNEL_OFFLOAD
ipv6_skip_exthdr(skb, (int)(exthdr - skb->data),
- l4_proto, &frag_off);
+ l4_proto, &frag_off);
+#else
+ int pld_off = 0;
+
+ pld_off = ipv6_skip_exthdr(skb,
+ (int)(exthdr - skb->data),
+ l4_proto, &frag_off);
+ l4->hdr = skb->data + pld_off;
+#endif
+ }
} else {
*l3_type = UNKNOWN_L3TYPE;
*l4_proto = 0;
}
}
+static u8 hinic3_get_inner_l4_type(struct sk_buff *skb)
+{
+ enum sq_l3_type l3_type;
+ u8 l4_proto;
+ union hinic3_ip ip;
+ union hinic3_l4 l4;
+
+ ip.hdr = skb_inner_network_header(skb);
+ l4.hdr = skb_inner_transport_header(skb);
+
+ get_inner_l3_l4_type(skb, &ip, &l4, &l3_type, &l4_proto);
+
+ return l4_proto;
+}
+
+static void hinic3_set_unknown_tunnel_csum(struct sk_buff *skb)
+{
+ int csum_offset;
+ __sum16 skb_csum;
+ u8 l4_proto;
+
+ l4_proto = hinic3_get_inner_l4_type(skb);
+ /* Unsupport tunnel packet, disable csum offload */
+ skb_checksum_help(skb);
+ /* The value of csum is changed from 0xffff to 0 according to RFC1624. */
+ if (skb->ip_summed == CHECKSUM_NONE && l4_proto != IPPROTO_UDP) {
+ csum_offset = skb_checksum_start_offset(skb) + skb->csum_offset;
+ skb_csum = *(__sum16 *)(skb->data + csum_offset);
+ if (skb_csum == 0xffff)
+ *(__sum16 *)(skb->data + csum_offset) = 0;
+ }
+}
+
static int hinic3_tx_csum(struct hinic3_txq *txq, struct sk_buff *skb,
struct hinic3_offload_info *offload_info,
struct hinic3_queue_info *queue_info)
@@ -276,10 +324,9 @@ static int hinic3_tx_csum(struct hinic3_txq *txq, struct sk_buff *skb,
if (l4_proto == IPPROTO_UDP)
queue_info->udp_dp_en = 1;
- if (l4_proto != IPPROTO_UDP ||
- ((struct udphdr *)skb_transport_header(skb))->dest != VXLAN_OFFLOAD_PORT_LE) {
+ if (l4_proto != IPPROTO_UDP) {
TXQ_STATS_INC(txq, unknown_tunnel_pkt);
- skb_checksum_help(skb);
+ hinic3_set_unknown_tunnel_csum(skb);
return 0;
}
}
@@ -682,6 +729,14 @@ static netdev_tx_t hinic3_send_one_skb(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
+ /* l2nic outband vlan cfg enable */
+ if (!skb_vlan_tag_present(skb) &&
+ nic_dev->nic_cap.outband_vlan_cfg_en == 1 &&
+ nic_dev->outband_cfg.outband_default_vid != 0) {
+ __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q),
+ (u16)nic_dev->outband_cfg.outband_default_vid);
+ }
+
offload = hinic3_tx_offload(skb, &offload_info, &queue_info, txq);
if (unlikely(offload == TX_OFFLOAD_INVALID)) {
TXQ_STATS_INC(txq, offload_cow_skb_err);
@@ -880,6 +935,7 @@ int hinic3_alloc_txqs_res(struct hinic3_nic_dev *nic_dev, u16 num_sq,
tqres->bds = kzalloc(size, GFP_KERNEL);
if (!tqres->bds) {
kfree(tqres->tx_info);
+ tqres->tx_info = NULL;
nicif_err(nic_dev, drv, nic_dev->netdev,
"Failed to alloc txq%d bds info\n", idx);
goto err_out;
@@ -893,7 +949,9 @@ err_out:
tqres = &txqs_res[i];
kfree(tqres->bds);
+ tqres->bds = NULL;
kfree(tqres->tx_info);
+ tqres->tx_info = NULL;
}
return -ENOMEM;
@@ -910,7 +968,9 @@ void hinic3_free_txqs_res(struct hinic3_nic_dev *nic_dev, u16 num_sq,
free_all_tx_skbs(nic_dev, sq_depth, tqres->tx_info);
kfree(tqres->bds);
+ tqres->bds = NULL;
kfree(tqres->tx_info);
+ tqres->tx_info = NULL;
}
}
@@ -982,6 +1042,7 @@ void hinic3_free_txqs(struct net_device *netdev)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
kfree(nic_dev->txqs);
+ nic_dev->txqs = NULL;
}
static bool is_hw_complete_sq_process(struct hinic3_io_queue *sq)
@@ -998,7 +1059,7 @@ static bool is_hw_complete_sq_process(struct hinic3_io_queue *sq)
static int hinic3_stop_sq(struct hinic3_txq *txq)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(txq->netdev);
- unsigned long timeout;
+ u64 timeout;
int err;
timeout = msecs_to_jiffies(HINIC3_FLUSH_QUEUE_TIMEOUT) + jiffies;
@@ -1007,7 +1068,7 @@ static int hinic3_stop_sq(struct hinic3_txq *txq)
return 0;
usleep_range(900, 1000); /* sleep 900 us ~ 1000 us */
- } while (time_before(jiffies, timeout));
+ } while (time_before(jiffies, (unsigned long)timeout));
/* force hardware to drop packets */
timeout = msecs_to_jiffies(HINIC3_FLUSH_QUEUE_TIMEOUT) + jiffies;
@@ -1020,7 +1081,7 @@ static int hinic3_stop_sq(struct hinic3_txq *txq)
break;
usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
- } while (time_before(jiffies, timeout));
+ } while (time_before(jiffies, (unsigned long)timeout));
/* Avoid msleep takes too long and get a fake result */
if (is_hw_complete_sq_process(txq->sq))
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h b/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h
index 1b9e509..7ae029b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_wq.h
@@ -29,7 +29,7 @@ struct hinic3_wq {
#define WQ_MASK_IDX(wq, idx) ((idx) & (wq)->idx_mask)
#define WQ_MASK_PAGE(wq, pg_idx) \
- ((pg_idx) < (wq)->num_wq_pages ? (pg_idx) : 0)
+ (((pg_idx) < ((wq)->num_wq_pages)) ? (pg_idx) : 0)
#define WQ_PAGE_IDX(wq, idx) ((idx) >> (wq)->wqebbs_per_page_shift)
#define WQ_OFFSET_IN_PAGE(wq, idx) ((idx) & (wq)->wqebbs_per_page_mask)
#define WQ_GET_WQEBB_ADDR(wq, pg_idx, idx_in_pg) \
@@ -75,7 +75,7 @@ static inline void *hinic3_wq_get_multi_wqebbs(struct hinic3_wq *wq,
pg_idx = WQ_PAGE_IDX(wq, *prod_idx);
off_in_page = WQ_OFFSET_IN_PAGE(wq, *prod_idx);
- if (off_in_page + num_wqebbs > wq->wqebbs_per_page) {
+ if ((off_in_page + num_wqebbs) > wq->wqebbs_per_page) {
/* wqe across wq page boundary */
*second_part_wqebbs_addr =
WQ_GET_WQEBB_ADDR(wq, WQ_MASK_PAGE(wq, pg_idx + 1), 0);
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c
index 597d3fe..468351f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_api_cmd.c
@@ -400,12 +400,15 @@ static int wait_for_status_poll(struct hinic3_api_cmd_chain *chain)
API_CMD_STATUS_TIMEOUT, 100); /* wait 100 us once */
}
-static void copy_resp_data(struct hinic3_api_cmd_cell_ctxt *ctxt, void *ack,
+static void copy_resp_data(struct hinic3_api_cmd_chain *chain,
+ struct hinic3_api_cmd_cell_ctxt *ctxt, void *ack,
u16 ack_size)
{
struct hinic3_api_cmd_resp_fmt *resp = ctxt->resp;
+ int rsp_size_align = chain->rsp_size_align - 0x8;
+ int rsp_size = (ack_size > rsp_size_align) ? rsp_size_align : ack_size;
- memcpy(ack, &resp->resp_data, ack_size);
+ memcpy(ack, &resp->resp_data, rsp_size);
ctxt->status = 0;
}
@@ -464,7 +467,7 @@ static int wait_for_api_cmd_completion(struct hinic3_api_cmd_chain *chain,
case HINIC3_API_CMD_POLL_READ:
err = wait_for_resp_polling(ctxt);
if (err == 0)
- copy_resp_data(ctxt, ack, ack_size);
+ copy_resp_data(chain, ctxt, ack, ack_size);
else
sdk_err(dev, "API CMD poll response timeout\n");
break;
@@ -1054,13 +1057,11 @@ alloc_cells_buf_err:
alloc_wb_status_err:
kfree(chain->cell_ctxt);
-/*lint -save -e548*/
alloc_cell_ctxt_err:
if (chain->chain_type == HINIC3_API_CMD_WRITE_ASYNC_TO_MGMT_CPU)
spin_lock_deinit(&chain->async_lock);
else
sema_deinit(&chain->sem);
-/*lint -restore*/
return err;
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c
index 38474ba..9f10131 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.c
@@ -801,7 +801,7 @@ static int cmdq_sync_cmd(struct hinic3_cmdq *cmdq, u8 mod, u8 cmd,
hinic3_cmdq_fill_completion_info(cmd_info, &cmpt_code, &done, &errcode, out_param);
cmdq_set_cmd_buf(cmd_info, cmdq->hwdev, buf_in, buf_out);
- memcpy(&saved_cmd_info, cmd_info, sizeof(*cmd_info));
+ memcpy(&saved_cmd_info, cmd_info, sizeof(struct hinic3_cmdq_cmd_info));
cmdq_sync_wqe_prepare(cmdq, mod, cmd, buf_in, buf_out, curr_wqe, curr_pi, nic_cmd_type);
@@ -1075,6 +1075,7 @@ int hinic3_cmdq_async(void *hwdev, u8 mod, u8 cmd, struct hinic3_cmd_buf *buf_in
return cmdq_async_cmd(&cmdqs->cmdq[HINIC3_CMDQ_SYNC], mod,
cmd, buf_in, channel);
}
+EXPORT_SYMBOL(hinic3_cmdq_async);
int hinic3_cmdq_async_cos(void *hwdev, u8 mod, u8 cmd,
u8 cos_id, struct hinic3_cmd_buf *buf_in, u16 channel)
@@ -1320,6 +1321,7 @@ cmd_infos_err:
static void free_cmdq(struct hinic3_cmdq *cmdq)
{
kfree(cmdq->cmd_infos);
+ cmdq->cmd_infos = NULL;
spin_lock_deinit(&cmdq->cmdq_lock);
}
@@ -1530,7 +1532,7 @@ static int create_cmdq_wq(struct hinic3_cmdqs *cmdqs)
type = HINIC3_CMDQ_SYNC;
for (; type < cmdqs->cmdq_num; type++)
memcpy((u8 *)cmdqs->wq_block_vaddr +
- CMDQ_WQ_CLA_SIZE * type,
+ ((u64)type * CMDQ_WQ_CLA_SIZE),
cmdqs->cmdq[type].wq.wq_block_vaddr,
cmdqs->cmdq[type].wq.num_wq_pages * sizeof(u64));
}
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h
index b9b884f..4f4639d 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq.h
@@ -15,11 +15,6 @@
#include "hinic3_common.h"
#include "hinic3_hwdev.h"
-struct dma_pool {
- unsigned int size;
- void *dev_hdl;
-};
-
#define HINIC3_SCMD_DATA_LEN 16
#define HINIC3_CMDQ_DEPTH 4096
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c
index c212bcc..d7e4985 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_cmdq_enhance.c
@@ -16,7 +16,6 @@
#include "ossl_knl.h"
#include "npu_cmdq_base_defs.h"
-#include "comm_defs.h"
#include "hinic3_crm.h"
#include "hinic3_hw.h"
#include "hinic3_hwdev.h"
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 5e0139a..0981d94 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.c
@@ -22,11 +22,15 @@
#include "hinic3_sriov.h"
#include "hinic3_nictool.h"
#include "hinic3_pci_id_tbl.h"
+#include "hinic3_hwdev.h"
+#include "cfg_mgmt_mpu_cmd_defs.h"
+#include "mpu_cmd_base_defs.h"
#include "hinic3_dev_mgmt.h"
#define HINIC3_WAIT_TOOL_CNT_TIMEOUT 10000
#define HINIC3_WAIT_TOOL_MIN_USLEEP_TIME 9900
#define HINIC3_WAIT_TOOL_MAX_USLEEP_TIME 10000
+#define HIGHT_BDF 8
static unsigned long card_bit_map;
@@ -60,14 +64,24 @@ void lld_dev_cnt_init(struct hinic3_pcidev *pci_adapter)
void lld_dev_hold(struct hinic3_lld_dev *dev)
{
- struct hinic3_pcidev *pci_adapter = pci_get_drvdata(dev->pdev);
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!dev)
+ return;
+
+ pci_adapter = pci_get_drvdata(dev->pdev);
atomic_inc(&pci_adapter->ref_cnt);
}
void lld_dev_put(struct hinic3_lld_dev *dev)
{
- struct hinic3_pcidev *pci_adapter = pci_get_drvdata(dev->pdev);
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!dev)
+ return;
+
+ pci_adapter = pci_get_drvdata(dev->pdev);
atomic_dec(&pci_adapter->ref_cnt);
}
@@ -236,6 +250,40 @@ void hinic3_get_all_chip_id(void *id_info)
card_id->num = (u32)i;
}
+int hinic3_bar_mmap_param_valid(phys_addr_t phy_addr, unsigned long vmsize)
+{
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *dev = NULL;
+ u64 bar1_phy_addr = 0;
+ u64 bar3_phy_addr = 0;
+ u64 bar1_size = 0;
+ u64 bar3_size = 0;
+
+ lld_hold();
+
+ /* get PF bar1 or bar3 physical address to verify */
+ list_for_each_entry(chip_node, &g_hinic3_chip_list, node) {
+ list_for_each_entry(dev, &chip_node->func_list, node) {
+ if (hinic3_func_type(dev->hwdev) == TYPE_VF)
+ continue;
+
+ bar1_phy_addr = pci_resource_start(dev->pcidev, HINIC3_PF_PCI_CFG_REG_BAR);
+ bar1_size = pci_resource_len(dev->pcidev, HINIC3_PF_PCI_CFG_REG_BAR);
+
+ bar3_phy_addr = pci_resource_start(dev->pcidev, HINIC3_PCI_MGMT_REG_BAR);
+ bar3_size = pci_resource_len(dev->pcidev, HINIC3_PCI_MGMT_REG_BAR);
+ if ((phy_addr == bar1_phy_addr && vmsize <= bar1_size) ||
+ (phy_addr == bar3_phy_addr && vmsize <= bar3_size)) {
+ lld_put();
+ return 0;
+ }
+ }
+ }
+
+ lld_put();
+ return -EINVAL;
+}
+
void hinic3_get_card_func_info_by_card_name(const char *chip_name,
struct hinic3_card_func_info *card_func)
{
@@ -422,6 +470,29 @@ struct hinic3_lld_dev *hinic3_get_lld_dev_by_chip_and_port(const char *chip_name
return NULL;
}
+void *hinic3_get_ppf_dev(void)
+{
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct list_head *chip_list = NULL;
+
+ lld_hold();
+ chip_list = get_hinic3_chip_list();
+
+ list_for_each_entry(chip_node, chip_list, node)
+ list_for_each_entry(pci_adapter, &chip_node->func_list, node)
+ if (hinic3_func_type(pci_adapter->hwdev) == TYPE_PPF) {
+ pr_info("Get ppf_func_id:%u",
+ hinic3_global_func_id(pci_adapter->hwdev));
+ lld_put();
+ return pci_adapter->lld_dev.hwdev;
+ }
+
+ lld_put();
+ return NULL;
+}
+EXPORT_SYMBOL(hinic3_get_ppf_dev);
+
struct hinic3_lld_dev *hinic3_get_lld_dev_by_dev_name(const char *dev_name,
enum hinic3_service_type type)
{
@@ -518,6 +589,7 @@ EXPORT_SYMBOL(hinic3_get_ppf_lld_dev_unsafe);
int hinic3_get_chip_name(struct hinic3_lld_dev *lld_dev, char *chip_name, u16 max_len)
{
struct hinic3_pcidev *pci_adapter = NULL;
+ int ret = 0;
if (!lld_dev || !chip_name || !max_len)
return -EINVAL;
@@ -527,12 +599,18 @@ int hinic3_get_chip_name(struct hinic3_lld_dev *lld_dev, char *chip_name, u16 ma
return -EFAULT;
lld_hold();
- strscpy(chip_name, pci_adapter->chip_node->chip_name, max_len);
+ if (strscpy(chip_name, pci_adapter->chip_node->chip_name, max_len) < 0)
+ goto RELEASE;
chip_name[max_len - 1] = '\0';
lld_put();
return 0;
+
+RELEASE:
+ lld_put();
+
+ return ret;
}
EXPORT_SYMBOL(hinic3_get_chip_name);
@@ -541,6 +619,87 @@ struct hinic3_hwdev *hinic3_get_sdk_hwdev_by_lld(struct hinic3_lld_dev *lld_dev)
return lld_dev->hwdev;
}
+void hinic3_write_oshr_info(struct os_hot_replace_info *out_oshr_info,
+ struct hw_pf_info *info,
+ struct hinic3_board_info *board_info,
+ struct card_node *chip_node, u32 serivce_enable,
+ u32 func_info_idx)
+{
+ out_oshr_info->func_infos[func_info_idx].pf_idx = info->glb_func_idx;
+ out_oshr_info->func_infos[func_info_idx].backup_pf =
+ (((info->glb_func_idx) / (board_info->port_num)) %
+ HOT_REPLACE_PARTITION_NUM == 0) ?
+ ((info->glb_func_idx) + (board_info->port_num)) :
+ ((info->glb_func_idx) - (board_info->port_num));
+ out_oshr_info->func_infos[func_info_idx].partition =
+ ((info->glb_func_idx) / (board_info->port_num)) %
+ HOT_REPLACE_PARTITION_NUM;
+ out_oshr_info->func_infos[func_info_idx].port_id = info->port_id;
+ out_oshr_info->func_infos[func_info_idx].bdf =
+ (info->bus_num << HIGHT_BDF) + info->glb_func_idx;
+ out_oshr_info->func_infos[func_info_idx].bus_num = chip_node->bus_num;
+ out_oshr_info->func_infos[func_info_idx].valid = serivce_enable;
+ memcpy(out_oshr_info->func_infos[func_info_idx].card_name,
+ chip_node->chip_name, IFNAMSIZ);
+}
+
+void hinic3_get_os_hot_replace_info(void *oshr_info)
+{
+ struct os_hot_replace_info *out_oshr_info =
+ (struct os_hot_replace_info *)oshr_info;
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *dst_dev = NULL;
+ struct hinic3_board_info *board_info = NULL;
+ struct hw_pf_info *infos = NULL;
+ struct hinic3_hw_pf_infos *pf_infos = NULL;
+ struct hinic3_hwdev *hwdev = NULL;
+ u32 func_info_idx = 0, func_id = 0, func_num, serivce_enable = 0;
+ struct list_head *hinic3_chip_list = get_hinic3_chip_list();
+ int err;
+
+ lld_hold();
+ pf_infos = kzalloc(sizeof(*pf_infos), GFP_KERNEL);
+ if (!pf_infos) {
+ pr_err("kzalloc pf_infos fail\n");
+ lld_put();
+ return;
+ }
+ list_for_each_entry(chip_node, hinic3_chip_list, node) {
+ list_for_each_entry(dst_dev, &chip_node->func_list, node) {
+ err = hinic3_get_hw_pf_infos(dst_dev->hwdev,
+ pf_infos,
+ HINIC3_CHANNEL_COMM);
+ if (err != 0) {
+ pr_err("get pf info failed\n");
+ break;
+ }
+ hwdev = (struct hinic3_hwdev *)dst_dev->hwdev;
+ serivce_enable = 0;
+ infos = pf_infos->infos;
+ board_info = &hwdev->board_info;
+ if (hwdev->hot_replace_mode == HOT_REPLACE_ENABLE)
+ serivce_enable = 1;
+ break;
+ }
+
+ func_num = pf_infos->num_pfs;
+ if (func_num <= 0) {
+ pr_err("get pf num failed\n");
+ break;
+ }
+
+ for (func_id = 0; func_id < func_num; func_id++) {
+ hinic3_write_oshr_info(out_oshr_info, &infos[func_id],
+ board_info, chip_node,
+ serivce_enable, func_info_idx);
+ func_info_idx++;
+ }
+ }
+ out_oshr_info->func_cnt = func_info_idx;
+ kfree(pf_infos);
+ lld_put();
+}
+
struct card_node *hinic3_get_chip_node_by_lld(struct hinic3_lld_dev *lld_dev)
{
struct hinic3_pcidev *pci_adapter = pci_get_drvdata(lld_dev->pdev);
@@ -608,21 +767,24 @@ void hinic3_get_card_info(const void *hwdev, void *bufin)
if (hinic3_support_nic(fun_hwdev, NULL)) {
if (dev->uld_dev[SERVICE_T_NIC]) {
info->pf[i].pf_type |= (u32)BIT(SERVICE_T_NIC);
- get_dynamic_uld_dev_name(dev, SERVICE_T_NIC, info->pf[i].name);
+ get_dynamic_uld_dev_name(dev, SERVICE_T_NIC,
+ info->pf[i].name);
}
}
if (hinic3_support_ppa(fun_hwdev, NULL)) {
if (dev->uld_dev[SERVICE_T_PPA]) {
info->pf[i].pf_type |= (u32)BIT(SERVICE_T_PPA);
- get_dynamic_uld_dev_name(dev, SERVICE_T_PPA, info->pf[i].name);
+ get_dynamic_uld_dev_name(dev, SERVICE_T_PPA,
+ info->pf[i].name);
}
}
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)
+ 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),
@@ -721,6 +883,7 @@ int alloc_chip_node(struct hinic3_pcidev *pci_adapter)
struct card_node *chip_node = NULL;
unsigned char i;
unsigned char bus_number = 0;
+ int err;
if (chip_node_is_exist(pci_adapter, &bus_number))
return 0;
@@ -746,7 +909,10 @@ int alloc_chip_node(struct hinic3_pcidev *pci_adapter)
/* bus number */
chip_node->bus_num = bus_number;
- if (snprintf(chip_node->chip_name, IFNAMSIZ, "%s%u", HINIC3_CHIP_NAME, i) < 0) {
+ snprintf(chip_node->chip_name, IFNAMSIZ, "%s%u", HINIC3_CHIP_NAME, i);
+
+ err = sscanf(chip_node->chip_name, HINIC3_CHIP_NAME "%d", &chip_node->chip_id);
+ if (err <= 0) {
clear_bit(i, &card_bit_map);
kfree(chip_node);
return -EINVAL;
@@ -803,3 +969,36 @@ int hinic3_get_pf_id(struct card_node *chip_node, u32 port_id, u32 *pf_id, u32 *
return 0;
}
+
+void hinic3_get_mbox_cnt(const void *hwdev, void *bufin)
+{
+ struct card_node *chip_node = NULL;
+ struct card_mbox_cnt_info *info = (struct card_mbox_cnt_info *)bufin;
+ struct hinic3_pcidev *dev = NULL;
+ struct hinic3_hwdev *func_hwdev = NULL;
+ u32 i = 0;
+
+ info->func_num = 0;
+ chip_node = hinic3_get_chip_node_by_hwdev(hwdev);
+ if (!chip_node)
+ return;
+
+ lld_hold();
+
+ list_for_each_entry(dev, &chip_node->func_list, node) {
+ func_hwdev = (struct hinic3_hwdev *)dev->hwdev;
+ strscpy(info->func_info[i].bus_info, pci_name(dev->pcidev),
+ sizeof(info->func_info[i].bus_info));
+
+ info->func_info[i].send_cnt = func_hwdev->mbox_send_cnt;
+ info->func_info[i].ack_cnt = func_hwdev->mbox_ack_cnt;
+ info->func_num++;
+ i = info->func_num;
+ if (i >= ARRAY_SIZE(info->func_info)) {
+ sdk_err(&dev->pcidev->dev, "chip_node->func_list bigger than pf_max + vf_max\n");
+ break;
+ }
+ }
+
+ lld_put();
+}
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 5c7c7cd..9815082 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_dev_mgmt.h
@@ -22,8 +22,13 @@
#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)
+#define HINIC3_IS_VF_DEV(pdev) \
+ ((pdev)->device == HINIC3_DEV_ID_VF || \
+ (pdev)->device == HINIC3_DEV_SDI_5_1_ID_VF)
+#define HINIC3_IS_SPU_DEV(pdev) \
+ (((pdev)->device == HINIC3_DEV_ID_SPU) || \
+ ((pdev)->device == HINIC3_DEV_ID_SDI_5_0_PF) || \
+ (((pdev)->device == HINIC3_DEV_ID_DPU_PF)))
enum {
HINIC3_NOT_PROBE = 1,
@@ -79,6 +84,13 @@ struct hinic3_pcidev {
u16 probe_fault_level;
u16 rsvd2;
u64 rsvd4;
+
+ struct workqueue_struct *multi_host_mgmt_workq;
+ struct work_struct slave_nic_work;
+ struct work_struct slave_vroce_work;
+
+ struct workqueue_struct *migration_probe_workq;
+ struct delayed_work migration_probe_dwork;
};
struct hinic_chip_info {
@@ -104,4 +116,6 @@ void wait_lld_dev_unused(struct hinic3_pcidev *pci_adapter);
void *hinic3_get_hwdev_by_pcidev(struct pci_dev *pdev);
+int hinic3_bar_mmap_param_valid(phys_addr_t phy_addr, unsigned long vmsize);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c
index 11561a0..59ff722 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_devlink.c
@@ -101,7 +101,8 @@ static bool check_image_device_type(struct hinic3_hwdev *hwdev, u32 device_type)
static void encapsulate_update_cmd(struct hinic3_cmd_update_firmware *msg,
struct firmware_section *section_info,
- int *remain_len, u32 *send_len, u32 *send_pos)
+ const int *remain_len, u32 *send_len,
+ u32 *send_pos)
{
memset(msg->data, 0, sizeof(msg->data));
msg->ctl_info.sf = (*remain_len == section_info->section_len) ? true : false;
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c
index 937d699..be7c82b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_eqs.c
@@ -26,6 +26,8 @@
#include "hinic3_prof_adap.h"
#include "hinic3_eqs.h"
+#include "vram_common.h"
+
#define HINIC3_EQS_WQ_NAME "hinic3_eqs"
#define AEQ_CTRL_0_INTR_IDX_SHIFT 0
@@ -66,7 +68,6 @@
#define HINIC3_TASK_PROCESS_EQE_LIMIT 1024
#define HINIC3_EQ_UPDATE_CI_STEP 64
-/*lint -e806*/
static uint g_aeq_len = HINIC3_DEFAULT_AEQ_LEN;
module_param(g_aeq_len, uint, 0444);
MODULE_PARM_DESC(g_aeq_len,
@@ -83,7 +84,6 @@ static uint g_num_ceqe_in_tasklet = HINIC3_TASK_PROCESS_EQE_LIMIT;
module_param(g_num_ceqe_in_tasklet, uint, 0444);
MODULE_PARM_DESC(g_num_ceqe_in_tasklet,
"The max number of ceqe can be processed in tasklet, default = 1024");
-/*lint +e806*/
#define CEQ_CTRL_0_INTR_IDX_SHIFT 0
#define CEQ_CTRL_0_DMA_ATTR_SHIFT 12
@@ -819,18 +819,22 @@ static int alloc_eq_pages(struct hinic3_eq *eq)
u32 reg, init_val;
u16 pg_idx, i;
int err;
+ gfp_t gfp_vram;
eq->eq_pages = kcalloc(eq->num_pages, sizeof(*eq->eq_pages),
GFP_KERNEL);
if (!eq->eq_pages)
return -ENOMEM;
+ gfp_vram = hi_vram_get_gfp_vram();
+
for (pg_idx = 0; pg_idx < eq->num_pages; pg_idx++) {
eq_page = &eq->eq_pages[pg_idx];
err = hinic3_dma_zalloc_coherent_align(eq->hwdev->dev_hdl,
eq->page_size,
HINIC3_MIN_EQ_PAGE_SIZE,
- GFP_KERNEL, eq_page);
+ GFP_KERNEL | gfp_vram,
+ eq_page);
if (err) {
sdk_err(eq->hwdev->dev_hdl, "Failed to alloc eq page, page index: %u\n",
pg_idx);
@@ -881,6 +885,7 @@ static void free_eq_pages(struct hinic3_eq *eq)
&eq->eq_pages[pg_idx]);
kfree(eq->eq_pages);
+ eq->eq_pages = NULL;
}
static inline u32 get_page_size(const struct hinic3_eq *eq)
@@ -1120,7 +1125,8 @@ int hinic3_aeqs_init(struct hinic3_hwdev *hwdev, u16 num_aeqs,
hwdev->aeqs = aeqs;
aeqs->hwdev = hwdev;
aeqs->num_aeqs = num_aeqs;
- aeqs->workq = alloc_workqueue(HINIC3_EQS_WQ_NAME, WQ_MEM_RECLAIM,
+ aeqs->workq = alloc_workqueue(HINIC3_EQS_WQ_NAME,
+ WQ_MEM_RECLAIM | WQ_HIGHPRI,
HINIC3_MAX_AEQS);
if (!aeqs->workq) {
sdk_err(hwdev->dev_hdl, "Failed to initialize aeq workqueue\n");
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c
index a4cbac8..6b96b87 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_api.c
@@ -82,6 +82,48 @@ int hinic3_sm_ctr_rd16(void *hwdev, u8 node, u8 instance, u32 ctr_id,
return 0;
}
+/**
+ * hinic3_sm_ctr_rd16_clear - small single 16 counter read and clear to zero
+ * @hwdev: the hardware device
+ * @node: the node id
+ * @ctr_id: counter id
+ * @value: read counter value ptr
+ * Return: 0 - success, negative - failure
+ **/
+int hinic3_sm_ctr_rd16_clear(void *hwdev, u8 node, u8 instance, u32 ctr_id,
+ u16 *value)
+{
+ struct chipif_sml_ctr_rd_req req;
+ union ctr_rd_rsp rsp;
+ int ret;
+
+ if (!hwdev || !value)
+ return -EFAULT;
+
+ if (!COMM_SUPPORT_API_CHAIN((struct hinic3_hwdev *)hwdev))
+ return -EPERM;
+
+ memset(&req, 0, sizeof(req));
+
+ hinic3_sml_ctr_read_build_req(&req, instance,
+ CHIPIF_SM_CTR_OP_READ_CLEAR,
+ CHIPIF_ACK, ctr_id, 0);
+
+ ret = hinic3_api_cmd_read_ack(hwdev, node, (u8 *)&req,
+ (unsigned short)sizeof(req),
+ (void *)&rsp,
+ (unsigned short)sizeof(rsp));
+ if (ret) {
+ sdk_err(((struct hinic3_hwdev *)hwdev)->dev_hdl,
+ "Sm 16bit counter clear fail, err(%d)\n", ret);
+ return ret;
+ }
+ sml_ctr_htonl_n((u32 *)&rsp, sizeof(rsp) / sizeof(u32));
+ *value = rsp.bs_ss16_rsp.value1;
+
+ return 0;
+}
+
/**
* hinic3_sm_ctr_rd32 - small single 32 counter read
* @hwdev: the hardware device
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 030ef6d..41c439a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.c
@@ -34,13 +34,18 @@ static void parse_pub_res_cap_dfx(struct hinic3_hwdev *hwdev,
cap->max_vf);
sdk_info(hwdev->dev_hdl, "Host_pf_num: 0x%x, pf_id_start: 0x%x, host_vf_num: 0x%x, vf_id_start: 0x%x\n",
cap->pf_num, cap->pf_id_start, cap->vf_num, cap->vf_id_start);
- sdk_info(hwdev->dev_hdl, "host_valid_bitmap: 0x%x, master_host_id: 0x%x, srv_multi_host_mode: 0x%x\n",
- cap->host_valid_bitmap, cap->master_host_id, cap->srv_multi_host_mode);
sdk_info(hwdev->dev_hdl,
- "fake_vf_start_id: 0x%x, fake_vf_num: 0x%x, fake_vf_max_pctx: 0x%x\n",
- cap->fake_vf_start_id, cap->fake_vf_num, cap->fake_vf_max_pctx);
- sdk_info(hwdev->dev_hdl, "fake_vf_bfilter_start_addr: 0x%x, fake_vf_bfilter_len: 0x%x\n",
- cap->fake_vf_bfilter_start_addr, cap->fake_vf_bfilter_len);
+ "host_valid_bitmap: 0x%x, master_host_id: 0x%x, srv_multi_host_mode: 0x%x, hot_plug_disable: 0x%x\n",
+ cap->host_valid_bitmap, cap->master_host_id,
+ cap->srv_multi_host_mode, cap->hot_plug_disable);
+ sdk_info(hwdev->dev_hdl,
+ "os_hot_replace: 0x%x, fake_vf_start_id: 0x%x, fake_vf_num: 0x%x, fake_vf_max_pctx: 0x%x\n",
+ cap->os_hot_replace, cap->fake_vf_start_id,
+ cap->fake_vf_num, cap->fake_vf_max_pctx);
+ sdk_info(hwdev->dev_hdl,
+ "fake_vf_bfilter_start_addr: 0x%x, fake_vf_bfilter_len: 0x%x, bond_create_mode: 0x%x\n",
+ cap->fake_vf_bfilter_start_addr, cap->fake_vf_bfilter_len,
+ cap->bond_create_mode);
}
static void parse_cqm_res_cap(struct hinic3_hwdev *hwdev, struct service_cap *cap,
@@ -109,6 +114,9 @@ static void parse_pub_res_cap(struct hinic3_hwdev *hwdev,
cap->host_valid_bitmap = dev_cap->host_valid_bitmap;
cap->master_host_id = dev_cap->master_host_id;
cap->srv_multi_host_mode = dev_cap->srv_multi_host_mode;
+ cap->hot_plug_disable = dev_cap->hot_plug_disable;
+ cap->bond_create_mode = dev_cap->bond_create_mode;
+ cap->os_hot_replace = dev_cap->os_hot_replace;
cap->fake_vf_en = dev_cap->fake_vf_en;
cap->fake_vf_start_bit = dev_cap->fake_vf_start_bit;
cap->fake_vf_end_bit = dev_cap->fake_vf_end_bit;
@@ -148,18 +156,27 @@ static void parse_l2nic_res_cap(struct hinic3_hwdev *hwdev,
nic_cap->max_sqs = dev_cap->nic_max_sq_id + 1;
nic_cap->max_rqs = dev_cap->nic_max_rq_id + 1;
nic_cap->default_num_queues = dev_cap->nic_default_num_queues;
+ nic_cap->outband_vlan_cfg_en = dev_cap->outband_vlan_cfg_en;
+ nic_cap->lro_enable = dev_cap->lro_enable;
sdk_info(hwdev->dev_hdl, "L2nic resource capbility, max_sqs: 0x%x, max_rqs: 0x%x\n",
nic_cap->max_sqs, nic_cap->max_rqs);
/* Check parameters from firmware */
- if (nic_cap->max_sqs > HINIC3_CFG_MAX_QP ||
- nic_cap->max_rqs > HINIC3_CFG_MAX_QP) {
- sdk_info(hwdev->dev_hdl, "Number of qp exceed limit[1-%d]: sq: %u, rq: %u\n",
- HINIC3_CFG_MAX_QP, nic_cap->max_sqs, nic_cap->max_rqs);
+ if (nic_cap->max_sqs > HINIC3_CFG_MAX_QP) {
+ sdk_info(hwdev->dev_hdl, "Number of sq exceed limit[1-%d]: sq: %u\n",
+ HINIC3_CFG_MAX_QP, nic_cap->max_sqs);
nic_cap->max_sqs = HINIC3_CFG_MAX_QP;
+ }
+
+ if (nic_cap->max_rqs > HINIC3_CFG_MAX_QP) {
+ sdk_info(hwdev->dev_hdl, "Number of rq exceed limit[1-%d]: rq: %u\n",
+ HINIC3_CFG_MAX_QP, nic_cap->max_rqs);
nic_cap->max_rqs = HINIC3_CFG_MAX_QP;
}
+
+ if (nic_cap->outband_vlan_cfg_en)
+ sdk_info(hwdev->dev_hdl, "L2nic outband vlan cfg enabled\n");
}
static void parse_fc_res_cap(struct hinic3_hwdev *hwdev,
@@ -333,6 +350,28 @@ static void parse_ipsec_res_cap(struct hinic3_hwdev *hwdev,
dev_cap->ipsec_max_sactx, dev_cap->ipsec_max_cq);
}
+static void parse_vbs_res_cap(struct hinic3_hwdev *hwdev,
+ struct service_cap *cap,
+ struct cfg_cmd_dev_cap *dev_cap,
+ enum func_type type)
+{
+ struct vbs_service_cap *vbs_cap = &cap->vbs_cap;
+
+ vbs_cap->vbs_max_volq = dev_cap->vbs_max_volq;
+ vbs_cap->vbs_main_pf_enable = dev_cap->vbs_main_pf_enable;
+ vbs_cap->vbs_vsock_pf_enable = dev_cap->vbs_vsock_pf_enable;
+ vbs_cap->vbs_fushion_queue_pf_enable = dev_cap->vbs_fushion_queue_pf_enable;
+
+ sdk_info(hwdev->dev_hdl,
+ "Get VBS resource capbility, vbs_max_volq: 0x%x\n",
+ dev_cap->vbs_max_volq);
+ sdk_info(hwdev->dev_hdl,
+ "Get VBS pf info, vbs_main_pf_enable: 0x%x, vbs_vsock_pf_enable: 0x%x, vbs_fushion_queue_pf_enable: 0x%x\n",
+ dev_cap->vbs_main_pf_enable,
+ dev_cap->vbs_vsock_pf_enable,
+ dev_cap->vbs_fushion_queue_pf_enable);
+}
+
static void parse_dev_cap(struct hinic3_hwdev *dev,
struct cfg_cmd_dev_cap *dev_cap, enum func_type type)
{
@@ -375,6 +414,9 @@ static void parse_dev_cap(struct hinic3_hwdev *dev,
if (IS_PPA_TYPE(dev))
parse_ppa_res_cap(dev, cap, dev_cap, type);
+
+ if (IS_VBS_TYPE(dev))
+ parse_vbs_res_cap(dev, cap, dev_cap, type);
}
static int get_cap_from_fw(struct hinic3_hwdev *dev, enum func_type type)
@@ -404,6 +446,23 @@ static int get_cap_from_fw(struct hinic3_hwdev *dev, enum func_type type)
return 0;
}
+u8 hinic3_get_bond_create_mode(void *dev)
+{
+ struct hinic3_hwdev *hwdev = NULL;
+ struct service_cap *cap = NULL;
+
+ if (!dev) {
+ pr_err("pointer dev is NULL\n");
+ return -EINVAL;
+ }
+
+ hwdev = (struct hinic3_hwdev *)dev;
+ cap = &hwdev->cfg_mgmt->svc_cap;
+
+ return cap->bond_create_mode;
+}
+EXPORT_SYMBOL(hinic3_get_bond_create_mode);
+
int hinic3_get_dev_cap(void *dev)
{
enum func_type type;
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 671eed6..2f2310a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_cfg.h
@@ -166,6 +166,11 @@ struct service_cap {
u8 srv_multi_host_mode;
u16 virtio_vq_size;
+ u8 hot_plug_disable;
+ u8 bond_create_mode;
+ u8 os_hot_replace;
+ u8 rsvd1;
+
u8 timer_pf_num;
u8 timer_pf_id_start;
u16 timer_vf_num;
@@ -335,5 +340,7 @@ void free_capability(struct hinic3_hwdev *dev);
int hinic3_init_vf_dev_cap(void *hwdev);
+u8 hinic3_get_bond_create_mode(void *dev);
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c
index 8a87d25..8659e0b 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_comm.c
@@ -21,6 +21,7 @@
#include "hinic3_hw_cfg.h"
#include "hinic3_cmdq.h"
#include "mpu_inband_cmd_defs.h"
+#include "vram_common.h"
#include "hinic3_hw_comm.h"
#define HINIC3_MSIX_CNT_LLI_TIMER_SHIFT 0
@@ -242,12 +243,19 @@ int hinic3_func_reset(void *dev, u16 func_id, u64 reset_flag, u16 channel)
struct hinic3_hwdev *hwdev = dev;
u16 out_size = sizeof(func_reset);
int err = 0;
+ int is_in_kexec;
if (!dev) {
pr_err("Invalid para: dev is null.\n");
return -EINVAL;
}
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ sdk_info(hwdev->dev_hdl, "Skip function reset!\n");
+ return 0;
+ }
+
sdk_info(hwdev->dev_hdl, "Function is reset, flag: 0x%llx, channel:0x%x\n",
reset_flag, channel);
@@ -554,7 +562,7 @@ EXPORT_SYMBOL(hinic3_set_ppf_flr_type);
int hinic3_set_ppf_tbl_hotreplace_flag(void *hwdev, u8 flag)
{
- struct comm_cmd_ppf_tbl_htrp_config htr_info = {0};
+ struct comm_cmd_ppf_tbl_htrp_config htr_info = {};
u16 out_size = sizeof(struct comm_cmd_ppf_tbl_htrp_config);
struct hinic3_hwdev *dev = hwdev;
int ret;
@@ -899,11 +907,19 @@ static int set_ppf_tmr_status(struct hinic3_hwdev *hwdev,
int hinic3_ppf_tmr_start(void *hwdev)
{
+ int is_in_kexec;
+
if (!hwdev) {
pr_err("Hwdev pointer is NULL for starting ppf timer\n");
return -EINVAL;
}
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec != 0) {
+ pr_info("Skip starting ppt timer during kexec");
+ return 0;
+ }
+
return set_ppf_tmr_status(hwdev, HINIC_PPF_TMR_FLAG_START);
}
EXPORT_SYMBOL(hinic3_ppf_tmr_start);
@@ -919,18 +935,114 @@ int hinic3_ppf_tmr_stop(void *hwdev)
}
EXPORT_SYMBOL(hinic3_ppf_tmr_stop);
+static int hi_vram_kalloc_align(struct hinic3_hwdev *hwdev, char *name,
+ u32 page_size, u32 page_num,
+ struct hinic3_dma_addr_align *mem_align)
+{
+ void *vaddr = NULL, *align_vaddr = NULL;
+ dma_addr_t paddr, align_paddr;
+ u64 real_size = page_size;
+ u64 align = page_size;
+
+ vaddr = (void *)hi_vram_kalloc(name, real_size);
+ if (!vaddr) {
+ sdk_err(hwdev->dev_hdl, "vram kalloc failed, name:%s.\n", name);
+ return -ENOMEM;
+ }
+
+ paddr = (dma_addr_t)virt_to_phys(vaddr);
+ align_paddr = ALIGN(paddr, align);
+ /* align */
+ if (align_paddr == paddr) {
+ align_vaddr = vaddr;
+ goto out;
+ }
+
+ hi_vram_kfree((void *)vaddr, name, real_size);
+
+ /* realloc memory for align */
+ real_size = page_size + align;
+ vaddr = (void *)hi_vram_kalloc(name, real_size);
+ if (!vaddr) {
+ sdk_err(hwdev->dev_hdl, "vram kalloc align failed, name:%s.\n", name);
+ return -ENOMEM;
+ }
+
+ paddr = (dma_addr_t)virt_to_phys(vaddr);
+ align_paddr = ALIGN(paddr, align);
+ align_vaddr = (void *)((u64)vaddr + (align_paddr - paddr));
+
+out:
+ mem_align->real_size = (u32)real_size;
+ mem_align->ori_vaddr = vaddr;
+ mem_align->ori_paddr = paddr;
+ mem_align->align_vaddr = align_vaddr;
+ mem_align->align_paddr = align_paddr;
+
+ return 0;
+}
+
+static void mqm_eqm_free_page_mem(struct hinic3_hwdev *hwdev)
+{
+ u32 i;
+ struct hinic3_dma_addr_align *page_addr;
+ int is_use_vram = get_use_vram_flag();
+ struct mqm_eqm_vram_name_s *mqm_eqm_vram_name = hwdev->mqm_eqm_vram_name;
+
+ page_addr = hwdev->mqm_att.brm_srch_page_addr;
+
+ for (i = 0; i < hwdev->mqm_att.page_num; i++) {
+ if (is_use_vram != 0) {
+ hi_vram_kfree(page_addr->ori_vaddr,
+ mqm_eqm_vram_name[i].vram_name,
+ page_addr->real_size);
+ } else {
+ hinic3_dma_free_coherent_align(hwdev->dev_hdl, page_addr);
+ }
+ page_addr->ori_vaddr = NULL;
+ page_addr++;
+ }
+
+ kfree(mqm_eqm_vram_name);
+ hwdev->mqm_eqm_vram_name = NULL;
+}
+
static int mqm_eqm_try_alloc_mem(struct hinic3_hwdev *hwdev, u32 page_size,
u32 page_num)
{
struct hinic3_dma_addr_align *page_addr = hwdev->mqm_att.brm_srch_page_addr;
+ int is_use_vram = get_use_vram_flag();
+ struct mqm_eqm_vram_name_s *mqm_eqm_vram_name = NULL;
u32 valid_num = 0;
u32 flag = 1;
u32 i = 0;
int err;
+ u16 func_id;
+
+ mqm_eqm_vram_name = kcalloc(page_num, sizeof(struct mqm_eqm_vram_name_s), GFP_KERNEL);
+ if (!mqm_eqm_vram_name)
+ return -ENOMEM;
+
+ hwdev->mqm_eqm_vram_name = mqm_eqm_vram_name;
+ func_id = hinic3_global_func_id(hwdev);
for (i = 0; i < page_num; i++) {
- err = hinic3_dma_zalloc_coherent_align(hwdev->dev_hdl, page_size,
- page_size, GFP_KERNEL, page_addr);
+ if (is_use_vram != 0) {
+ snprintf(mqm_eqm_vram_name[i].vram_name,
+ VRAM_NAME_MAX_LEN, "%s%hu%s%u",
+ VRAM_CQM_GLB_FUNC_BASE, func_id,
+ VRAM_NIC_MQM, i);
+ err = hi_vram_kalloc_align(hwdev,
+ mqm_eqm_vram_name[i].vram_name,
+ page_size, page_num,
+ page_addr);
+ } else {
+ err = hinic3_dma_zalloc_coherent_align(hwdev->dev_hdl,
+ page_size,
+ page_size,
+ GFP_KERNEL,
+ page_addr);
+ }
if (err) {
flag = 0;
break;
@@ -939,15 +1051,12 @@ static int mqm_eqm_try_alloc_mem(struct hinic3_hwdev *hwdev, u32 page_size,
page_addr++;
}
+ hwdev->mqm_att.page_num = valid_num;
+
if (flag == 1) {
hwdev->mqm_att.page_size = page_size;
- hwdev->mqm_att.page_num = page_num;
} else {
- page_addr = hwdev->mqm_att.brm_srch_page_addr;
- for (i = 0; i < valid_num; i++) {
- hinic3_dma_free_coherent_align(hwdev->dev_hdl, page_addr);
- page_addr++;
- }
+ mqm_eqm_free_page_mem(hwdev);
return -EFAULT;
}
@@ -986,19 +1095,6 @@ static int mqm_eqm_alloc_page_mem(struct hinic3_hwdev *hwdev)
return ret;
}
-static void mqm_eqm_free_page_mem(struct hinic3_hwdev *hwdev)
-{
- u32 i;
- struct hinic3_dma_addr_align *page_addr;
-
- page_addr = hwdev->mqm_att.brm_srch_page_addr;
-
- for (i = 0; i < hwdev->mqm_att.page_num; i++) {
- hinic3_dma_free_coherent_align(hwdev->dev_hdl, page_addr);
- page_addr++;
- }
-}
-
static int mqm_eqm_set_cfg_2_hw(struct hinic3_hwdev *hwdev, u8 valid)
{
struct comm_cmd_eqm_cfg info_eqm_cfg;
@@ -1129,6 +1225,7 @@ static int mqm_eqm_init(struct hinic3_hwdev *hwdev)
{
struct comm_cmd_get_eqm_num info_eqm_fix;
int ret;
+ int is_in_kexec;
if (hwdev->hwif->attr.func_type != TYPE_PPF)
return 0;
@@ -1158,10 +1255,16 @@ static int mqm_eqm_init(struct hinic3_hwdev *hwdev)
goto err_page;
}
- ret = mqm_eqm_set_page_2_hw(hwdev);
- if (ret) {
- sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n");
- goto err_ecmd;
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec == 0) {
+ ret = mqm_eqm_set_page_2_hw(hwdev);
+ if (ret) {
+ sdk_err(hwdev->dev_hdl, "Set page to hw failed\r\n");
+ goto err_ecmd;
+ }
+ } else {
+ sdk_info(hwdev->dev_hdl,
+ "Mqm db don't set to chip when os hot replace.\r\n");
}
ret = mqm_eqm_set_cfg_2_hw(hwdev, 1);
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c
index e8aa7ef..722fecd 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hw_mt.c
@@ -252,97 +252,6 @@ static u32 get_up_timeout_val(enum hinic3_mod_type mod, u16 cmd)
return 0; /* use default mbox/apichain timeout time */
}
-static int api_csr_read(void *hwdev, struct msg_module *nt_msg,
- void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
-{
- struct up_log_msg_st *up_log_msg = (struct up_log_msg_st *)buf_in;
- u8 *buf_out_tmp = (u8 *)buf_out;
- int ret = 0;
- u32 rd_len;
- u32 rd_addr;
- u32 rd_cnt = 0;
- u32 offset = 0;
- u8 node_id;
- u32 i;
-
- if (!buf_in || !buf_out || in_size != sizeof(*up_log_msg) ||
- *out_size != up_log_msg->rd_len || up_log_msg->rd_len % DW_WIDTH != 0)
- return -EINVAL;
-
- rd_len = up_log_msg->rd_len;
- rd_addr = up_log_msg->addr;
- node_id = (u8)nt_msg->mpu_cmd.mod;
-
- rd_cnt = rd_len / DW_WIDTH;
-
- for (i = 0; i < rd_cnt; i++) {
- ret = hinic3_api_csr_rd32(hwdev, node_id,
- rd_addr + offset,
- (u32 *)(buf_out_tmp + offset));
- if (ret) {
- pr_err("Csr rd fail, err: %d, node_id: %u, csr addr: 0x%08x\n",
- ret, node_id, rd_addr + offset);
- return ret;
- }
- offset += DW_WIDTH;
- }
- *out_size = rd_len;
-
- return ret;
-}
-
-static int api_csr_write(void *hwdev, struct msg_module *nt_msg,
- void *buf_in, u32 in_size, void *buf_out,
- u32 *out_size)
-{
- struct csr_write_st *csr_write_msg = (struct csr_write_st *)buf_in;
- int ret = 0;
- u32 rd_len;
- u32 rd_addr;
- u32 rd_cnt = 0;
- u32 offset = 0;
- u8 node_id;
- u32 i;
- u8 *data = NULL;
-
- if (!buf_in || in_size != sizeof(*csr_write_msg) || csr_write_msg->rd_len == 0 ||
- csr_write_msg->rd_len > API_CSR_MAX_RD_LEN || csr_write_msg->rd_len % DW_WIDTH != 0)
- return -EINVAL;
-
- rd_len = csr_write_msg->rd_len;
- rd_addr = csr_write_msg->addr;
- node_id = (u8)nt_msg->mpu_cmd.mod;
-
- rd_cnt = rd_len / DW_WIDTH;
-
- data = kzalloc(rd_len, GFP_KERNEL);
- if (!data)
- return -EFAULT;
-
- if (copy_from_user(data, (void *)csr_write_msg->data, rd_len)) {
- pr_err("Copy information from user failed\n");
- kfree(data);
- return -EFAULT;
- }
-
- for (i = 0; i < rd_cnt; i++) {
- ret = hinic3_api_csr_wr32(hwdev, node_id,
- rd_addr + offset,
- *((u32 *)(data + offset)));
- if (ret) {
- pr_err("Csr wr fail, ret: %d, node_id: %u, csr addr: 0x%08x\n",
- ret, rd_addr + offset, node_id);
- kfree(data);
- return ret;
- }
- offset += DW_WIDTH;
- }
-
- *out_size = 0;
- kfree(data);
- return ret;
-}
-
int send_to_mpu(void *hwdev, struct msg_module *nt_msg,
void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
{
@@ -369,10 +278,8 @@ int send_to_mpu(void *hwdev, struct msg_module *nt_msg,
return ret;
}
} else if (nt_msg->mpu_cmd.api_type == API_TYPE_API_CHAIN_BYPASS) {
- if (nt_msg->mpu_cmd.cmd == API_CSR_WRITE)
- return api_csr_write(hwdev, nt_msg, buf_in, in_size, buf_out, out_size);
-
- ret = api_csr_read(hwdev, nt_msg, buf_in, in_size, buf_out, out_size);
+ pr_err("Unsupported api_type %u\n", nt_msg->mpu_cmd.api_type);
+ return -EINVAL;
} else if (nt_msg->mpu_cmd.api_type == API_TYPE_API_CHAIN_TO_MPU) {
timeout = get_up_timeout_val(mod, cmd);
if (hinic3_pcie_itf_id(hwdev) != SPU_HOST_ID)
@@ -439,6 +346,23 @@ static int sm_rd16(void *hwdev, u32 id, u8 instance,
return ret;
}
+static int sm_rd16_clear(void *hwdev, u32 id, u8 instance,
+ u8 node, struct sm_out_st *buf_out)
+{
+ u16 val1;
+ int ret;
+
+ ret = hinic3_sm_ctr_rd16_clear(hwdev, node, instance, id, &val1);
+ if (ret != 0) {
+ pr_err("Get sm ctr clear information (16 bits)failed!\n");
+ val1 = 0xffff;
+ }
+
+ buf_out->val1 = val1;
+
+ return ret;
+}
+
static int sm_rd32(void *hwdev, u32 id, u8 instance,
u8 node, struct sm_out_st *buf_out)
{
@@ -558,6 +482,7 @@ const struct sm_module_handle sm_module_cmd_handle[] = {
{SM_CTR_RD32, sm_rd32},
{SM_CTR_RD64_PAIR, sm_rd64_pair},
{SM_CTR_RD64, sm_rd64},
+ {SM_CTR_RD16_CLEAR, sm_rd16_clear},
{SM_CTR_RD32_CLEAR, sm_rd32_clear},
{SM_CTR_RD64_PAIR_CLEAR, sm_rd64_pair_clear},
{SM_CTR_RD64_CLEAR, sm_rd64_clear}
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c
index 83e7b63..c317f4a 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.c
@@ -101,6 +101,12 @@ enum hinic3_pcie_tph {
#define SLAVE_HOST_STATUS_SET(host_id, enable) (((u8)(enable) & 1U) << (host_id))
#define SLAVE_HOST_STATUS_GET(host_id, val) (!!((val) & (1U << (host_id))))
+#ifdef HAVE_HOT_REPLACE_FUNC
+ extern int get_partition_id(void);
+#else
+ static int get_partition_id(void) {return 0; }
+#endif
+
void set_slave_host_enable(void *hwdev, u8 host_id, bool enable)
{
u32 reg_val;
@@ -207,6 +213,27 @@ static void hinic3_init_host_mode_pre(struct hinic3_hwdev *hwdev)
}
}
+static void hinic3_init_hot_plug_status(struct hinic3_hwdev *hwdev)
+{
+ struct service_cap *cap = &hwdev->cfg_mgmt->svc_cap;
+
+ if (cap->hot_plug_disable)
+ hwdev->hot_plug_mode = HOT_PLUG_DISABLE;
+ else
+ hwdev->hot_plug_mode = HOT_PLUG_ENABLE;
+}
+
+static void hinic3_init_os_hot_replace(struct hinic3_hwdev *hwdev)
+{
+ struct service_cap *cap = &hwdev->cfg_mgmt->svc_cap;
+
+ if (cap->os_hot_replace) {
+ hwdev->hot_replace_mode = HOT_REPLACE_ENABLE;
+ } else {
+ hwdev->hot_replace_mode = HOT_REPLACE_DISABLE;
+ }
+}
+
static u8 hinic3_nic_sw_aeqe_handler(void *hwdev, u8 event, u8 *data)
{
struct hinic3_hwdev *dev = hwdev;
@@ -270,14 +297,20 @@ static void chip_fault_show(struct hinic3_hwdev *hwdev,
"fatal", "reset", "host", "flr", "general", "suggestion"};
char level_str[FAULT_SHOW_STR_LEN + 1];
u8 level;
+ int ret;
memset(level_str, 0, FAULT_SHOW_STR_LEN + 1);
level = event->event.chip.err_level;
- if (level < FAULT_LEVEL_MAX)
- strscpy(level_str, fault_level[level],
- FAULT_SHOW_STR_LEN);
- else
- strscpy(level_str, "Unknown", FAULT_SHOW_STR_LEN);
+ if (level < FAULT_LEVEL_MAX) {
+ ret = strscpy(level_str, fault_level[level],
+ FAULT_SHOW_STR_LEN);
+ if (ret < 0)
+ return;
+ } else {
+ ret = strscpy(level_str, "Unknown", FAULT_SHOW_STR_LEN);
+ if (ret < 0)
+ return;
+ }
if (level == FAULT_LEVEL_SERIOUS_FLR)
dev_err(hwdev->dev_hdl, "err_level: %u [%s], flr func_id: %u\n",
@@ -299,6 +332,7 @@ static void fault_report_show(struct hinic3_hwdev *hwdev,
"reg rd timeout", "reg wr timeout", "phy fault", "tsensor fault"};
char type_str[FAULT_SHOW_STR_LEN + 1] = {0};
struct fault_event_stats *fault = NULL;
+ int ret;
sdk_err(hwdev->dev_hdl, "Fault event report received, func_id: %u\n",
hinic3_global_func_id(hwdev));
@@ -306,10 +340,14 @@ static void fault_report_show(struct hinic3_hwdev *hwdev,
fault = &hwdev->hw_stats.fault_event_stats;
if (event->type < FAULT_TYPE_MAX) {
- strscpy(type_str, fault_type[event->type], sizeof(type_str));
+ ret = strscpy(type_str, fault_type[event->type], sizeof(type_str));
+ if (ret < 0)
+ return;
atomic_inc(&fault->fault_type_stat[event->type]);
} else {
- strscpy(type_str, "Unknown", sizeof(type_str));
+ ret = strscpy(type_str, "Unknown", sizeof(type_str));
+ if (ret < 0)
+ return;
}
sdk_err(hwdev->dev_hdl, "Fault type: %u [%s]\n", event->type, type_str);
@@ -1536,15 +1574,29 @@ int hinic3_init_hwdev(struct hinic3_init_para *para)
hinic3_init_host_mode_pre(hwdev);
+ hinic3_init_hot_plug_status(hwdev);
+
+ hinic3_init_os_hot_replace(hwdev);
+
err = hinic3_multi_host_mgmt_init(hwdev);
if (err != 0) {
sdk_err(hwdev->dev_hdl, "Failed to init function mode\n");
goto init_multi_host_fail;
}
- err = hinic3_init_ppf_work(hwdev);
- if (err != 0)
- goto init_ppf_work_fail;
+ // hot_replace_mode is enable, run ppf function only when partition_id is 0
+ // or run ppf function directly
+ if (hwdev->hot_replace_mode == HOT_REPLACE_ENABLE) {
+ if (get_partition_id() == 0) {
+ err = hinic3_init_ppf_work(hwdev);
+ if (err != 0)
+ goto init_ppf_work_fail;
+ }
+ } else {
+ err = hinic3_init_ppf_work(hwdev);
+ if (err != 0)
+ goto init_ppf_work_fail;
+ }
err = hinic3_set_comm_features(hwdev, hwdev->features, COMM_MAX_FEATURE_QWORD);
if (err != 0) {
@@ -1948,6 +2000,19 @@ void hinic3_link_event_stats(void *dev, u8 link)
}
EXPORT_SYMBOL(hinic3_link_event_stats);
+int hinic3_get_link_event_stats(void *dev, int *link_state)
+{
+ struct hinic3_hwdev *hwdev = dev;
+
+ if (!hwdev || !link_state)
+ return -EINVAL;
+
+ *link_state = hwdev->hw_stats.link_event_stats.link_down_stats.counter;
+
+ return 0;
+}
+EXPORT_SYMBOL(hinic3_get_link_event_stats);
+
u8 hinic3_max_pf_num(void *hwdev)
{
if (!hwdev)
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h
index b8a3356..0ca639f 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwdev.h
@@ -10,6 +10,7 @@
#include "hinic3_hw.h"
#include "mpu_inband_cmd_defs.h"
#include "hinic3_profile.h"
+#include "vram_common.h"
struct cfg_mgmt_info;
@@ -82,6 +83,22 @@ enum hinic3_host_mode_e {
HINIC3_SDI_MODE_MAX,
};
+enum hinic3_hot_plug_mode {
+ HOT_PLUG_ENABLE,
+ HOT_PLUG_DISABLE,
+};
+
+enum hinic3_os_hot_replace_mode {
+ HOT_REPLACE_DISABLE,
+ HOT_REPLACE_ENABLE,
+};
+
+#define UNSUPPORT_HOT_PLUG(hwdev) \
+ ((hwdev)->hot_plug_mode == HOT_PLUG_DISABLE)
+
+#define SUPPORT_HOT_PLUG(hwdev) \
+ ((hwdev)->hot_plug_mode == HOT_PLUG_ENABLE)
+
#define MULTI_HOST_CHIP_MODE_SHIFT 0
#define MULTI_HOST_MASTER_MBX_STS_SHIFT 17
#define MULTI_HOST_PRIV_DATA_SHIFT 0x8
@@ -100,6 +117,10 @@ enum hinic3_host_mode_e {
((val) & (~(MULTI_HOST_##member##_MASK \
<< MULTI_HOST_##member##_SHIFT)))
+struct mqm_eqm_vram_name_s {
+ char vram_name[VRAM_NAME_MAX_LEN];
+};
+
struct hinic3_hwdev {
void *adapter_hdl; /* pointer to hinic3_pcidev or NDIS_Adapter */
void *pcidev_hdl; /* pointer to pcidev or Handler */
@@ -138,6 +159,9 @@ struct hinic3_hwdev {
u32 rsvd2;
struct hinic3_multi_host_mgmt *mhost_mgmt;
+ char mhost_mgmt_name[VRAM_NAME_MAX_LEN];
+
+ struct mqm_eqm_vram_name_s *mqm_eqm_vram_name;
struct mutex stateful_mutex; /* protect cqm init and deinit */
@@ -170,6 +194,8 @@ struct hinic3_hwdev {
struct hinic3_devlink *devlink_dev;
enum hinic3_func_mode func_mode;
+ enum hinic3_hot_plug_mode hot_plug_mode;
+ enum hinic3_os_hot_replace_mode hot_replace_mode;
u32 rsvd3;
DECLARE_BITMAP(func_probe_in_host, MAX_FUNCTION_NUM);
@@ -179,7 +205,10 @@ struct hinic3_hwdev {
u64 last_recv_aeq_cnt;
u16 aeq_busy_cnt;
- u64 rsvd4[8];
+ u64 mbox_send_cnt;
+ u64 mbox_ack_cnt;
+
+ u64 rsvd4[5];
u8 cmdq_mode;
};
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c
index 33f1210..8590f70 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_hwif.c
@@ -544,6 +544,7 @@ static void free_db_area(struct hinic3_free_db_area *free_db_area)
{
spin_lock_deinit(&free_db_area->idx_lock);
kfree(free_db_area->db_bitmap_array);
+ free_db_area->db_bitmap_array = NULL;
}
static int get_db_idx(struct hinic3_hwif *hwif, u32 *idx)
@@ -841,6 +842,7 @@ void hinic3_free_hwif(struct hinic3_hwdev *hwdev)
free_db_area(&hwdev->hwif->free_db_area);
enable_all_msix(hwdev);
kfree(hwdev->hwif);
+ hwdev->hwif = NULL;
}
u16 hinic3_global_func_id(void *hwdev)
@@ -856,6 +858,44 @@ u16 hinic3_global_func_id(void *hwdev)
}
EXPORT_SYMBOL(hinic3_global_func_id);
+/**
+ * get function id from register,used by sriov hot migration process
+ * @hwdev: the pointer to hw device
+ */
+u16 hinic3_global_func_id_hw(void *hwdev)
+{
+ u32 addr, attr0;
+ struct hinic3_hwdev *dev;
+
+ dev = (struct hinic3_hwdev *)hwdev;
+ addr = HINIC3_CSR_FUNC_ATTR0_ADDR;
+ attr0 = hinic3_hwif_read_reg(dev->hwif, addr);
+
+ return HINIC3_AF0_GET(attr0, FUNC_GLOBAL_IDX);
+}
+
+/**
+ * get function id, used by sriov hot migratition process.
+ * @hwdev: the pointer to hw device
+ * @func_id: function id
+ */
+int hinic3_global_func_id_get(void *hwdev, u16 *func_id)
+{
+ struct hinic3_hwdev *dev = (struct hinic3_hwdev *)hwdev;
+
+ if (!hwdev || !func_id)
+ return -EINVAL;
+
+ /* only vf get func_id from chip reg for sriov migrate */
+ if (!HINIC3_IS_VF(dev)) {
+ *func_id = hinic3_global_func_id(hwdev);
+ return 0;
+ }
+
+ *func_id = hinic3_global_func_id_hw(dev);
+ return 0;
+}
+
u16 hinic3_intr_num(void *hwdev)
{
struct hinic3_hwif *hwif = NULL;
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c
index 6ab1b92..0b02176 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_lld.c
@@ -16,6 +16,7 @@
#include <linux/rtc.h>
#include <linux/aer.h>
#include <linux/debugfs.h>
+#include <linux/notifier.h>
#include "ossl_knl.h"
#include "hinic3_mt.h"
@@ -26,13 +27,38 @@
#include "hinic3_dev_mgmt.h"
#include "hinic3_nictool.h"
#include "hinic3_hw.h"
+#include "hinic3_multi_host_mgmt.h"
+#include "hinic3_hw_cfg.h"
#include "hinic3_lld.h"
#include "hinic3_profile.h"
#include "hinic3_hwdev.h"
#include "hinic3_prof_adap.h"
-#include "comm_msg_intf.h"
+#include "hinic3_devlink.h"
+#include "vram_common.h"
+
+enum partition_dev_type {
+ PARTITION_DEV_NONE = 0,
+ PARTITION_DEV_SHARED,
+ PARTITION_DEV_EXCLUSIVE,
+ PARTITION_DEV_BACKUP,
+};
+
+#ifdef HAVE_HOT_REPLACE_FUNC
+static int vpci_set_partition_attrs(struct pci_dev *dev, unsigned int dev_type,
+ unsigned int partition_id);
+static int get_partition_id(void);
+#else
+static int vpci_set_partition_attrs(struct pci_dev *dev, unsigned int dev_type,
+ unsigned int partition_id)
+{
+ return 0;
+}
+static int get_partition_id(void) { return 0; }
+#endif
+
+static bool g_is_pf_migrated;
static bool disable_vf_load;
module_param(disable_vf_load, bool, 0444);
MODULE_PARM_DESC(disable_vf_load,
@@ -44,10 +70,12 @@ MODULE_PARM_DESC(disable_attach, "disable_attach or not - default is false");
#define HINIC3_WAIT_SRIOV_CFG_TIMEOUT 15000
-MODULE_AUTHOR("Huawei Technologies CO., Ltd");
-MODULE_DESCRIPTION(HINIC3_DRV_DESC);
-MODULE_VERSION(HINIC3_DRV_VERSION);
-MODULE_LICENSE("GPL");
+#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
+static DEVICE_ATTR_RW(sriov_numvfs, 0644,
+ sriov_numvfs_show, sriov_numvfs_store);
+static DEVICE_ATTR_RO(sriov_totalvfs, 0444,
+ sriov_totalvfs_show, NULL);
+#endif /* !(HAVE_SRIOV_CONFIGURE || HAVE_RHEL6_SRIOV_CONFIGURE) */
static struct attribute *hinic3_attributes[] = {
#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
@@ -64,7 +92,18 @@ static const struct attribute_group hinic3_attr_group = {
struct hinic3_uld_info g_uld_info[SERVICE_T_MAX] = { {0} };
#define HINIC3_EVENT_PROCESS_TIMEOUT 10000
+#define HINIC3_WAIT_EVENT_PROCESS_TIMEOUT 100
struct mutex g_uld_mutex; /* g_uld_info lock */
+#define BUS_MAX_DEV_NUM 256
+#define HINIC3_SLAVE_WORK_MAX_NUM 20
+
+struct vf_offset_info {
+ u8 valid;
+ u16 vf_offset_from_pf[CMD_MAX_MAX_PF_NUM];
+};
+
+static struct vf_offset_info g_vf_offset;
+DEFINE_MUTEX(g_vf_offset_lock);
void hinic3_uld_lock_init(void)
{
@@ -73,13 +112,23 @@ 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", "bifur", "custom"};
+ "fc", "vbs", "ipsec", "virtio", "migrate",
+ "ppa", "custom", "vroce", "crypt", "vsock", "bifur"};
const char **hinic3_get_uld_names(void)
{
return s_uld_name;
}
+#ifdef CONFIG_PCI_IOV
+static int hinic3_get_pf_device_id(struct pci_dev *pdev)
+{
+ struct pci_dev *pf_dev = pci_physfn(pdev);
+
+ return pf_dev->device;
+}
+#endif
+
static int attach_uld(struct hinic3_pcidev *dev, enum hinic3_service_type type,
const struct hinic3_uld_info *uld_info)
{
@@ -98,6 +147,10 @@ static int attach_uld(struct hinic3_pcidev *dev, enum hinic3_service_type type,
atomic_set(&dev->uld_ref_cnt[type], 0);
+ if (!uld_info->probe) {
+ err = 0;
+ goto out_unlock;
+ }
err = uld_info->probe(&dev->lld_dev, &uld_dev, dev->uld_dev_name[type]);
if (err) {
sdk_err(&dev->pcidev->dev,
@@ -166,6 +219,10 @@ static void detach_uld(struct hinic3_pcidev *dev,
wait_uld_unused(dev, type);
+ if (!uld_info->remove) {
+ mutex_unlock(&dev->pdev_mutex);
+ return;
+ }
uld_info->remove(&dev->lld_dev, dev->uld_dev[type]);
dev->uld_dev[type] = NULL;
@@ -182,11 +239,14 @@ static void attach_ulds(struct hinic3_pcidev *dev)
{
enum hinic3_service_type type;
struct pci_dev *pdev = dev->pcidev;
+ int is_in_kexec = vram_get_kexec_flag();
+
+ if (is_in_kexec == 0)
+ lld_hold();
- lld_hold();
mutex_lock(&g_uld_mutex);
- for (type = SERVICE_T_NIC; type < SERVICE_T_MAX; type++) {
+ for (type = SERVICE_T_OVS; type < SERVICE_T_MAX; type++) {
if (g_uld_info[type].probe) {
if (pdev->is_virtfn &&
(!hinic3_get_vf_service_load(pdev, (u16)type))) {
@@ -198,7 +258,9 @@ static void attach_ulds(struct hinic3_pcidev *dev)
}
}
mutex_unlock(&g_uld_mutex);
- lld_put();
+
+ if (is_in_kexec == 0)
+ lld_put();
}
static void detach_ulds(struct hinic3_pcidev *dev)
@@ -305,7 +367,7 @@ void hinic3_unregister_uld(enum hinic3_service_type type)
}
uld_info = &g_uld_info[type];
- memset(uld_info, 0, sizeof(*uld_info));
+ memset(uld_info, 0, sizeof(struct hinic3_uld_info));
mutex_unlock(&g_uld_mutex);
lld_put();
}
@@ -359,6 +421,26 @@ void hinic3_detach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_ser
}
EXPORT_SYMBOL(hinic3_detach_service);
+void hinic3_module_get(void *hwdev, enum hinic3_service_type type)
+{
+ struct hinic3_hwdev *dev = hwdev;
+
+ if (!dev || type >= SERVICE_T_MAX)
+ return;
+ __module_get(THIS_MODULE);
+}
+EXPORT_SYMBOL(hinic3_module_get);
+
+void hinic3_module_put(void *hwdev, enum hinic3_service_type type)
+{
+ struct hinic3_hwdev *dev = hwdev;
+
+ if (!dev || type >= SERVICE_T_MAX)
+ return;
+ module_put(THIS_MODULE);
+}
+EXPORT_SYMBOL(hinic3_module_put);
+
static void hinic3_sync_time_to_fmw(struct hinic3_pcidev *pdev_pri)
{
struct timeval tv = {0};
@@ -441,23 +523,445 @@ static void send_event_to_all_pf(struct hinic3_pcidev *dev,
lld_put();
}
+u32 hinic3_pdev_is_virtfn(struct pci_dev *pdev)
+{
+#ifdef CONFIG_PCI_IOV
+ return pdev->is_virtfn;
+#else
+ return 0;
+#endif
+}
+
+static int hinic3_get_function_enable(struct pci_dev *pdev, bool *en)
+{
+ struct pci_dev *pf_pdev = pdev->physfn;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ void *pf_hwdev = NULL;
+ u16 global_func_id;
+ int err;
+
+ /* PF in host os or function in guest os, probe sdk in default */
+ if (!hinic3_pdev_is_virtfn(pdev) || !pf_pdev) {
+ *en = true;
+ return 0;
+ }
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter || !pci_adapter->hwdev) {
+ /* vf in host and pf sdk not probed */
+ return -EFAULT;
+ }
+ pf_hwdev = pci_adapter->hwdev;
+
+ err = hinic3_get_vfid_by_vfpci(NULL, pdev, &global_func_id);
+ if (err) {
+ sdk_err(&pci_adapter->pcidev->dev,
+ "Func hinic3_get_vfid_by_vfpci fail %d\n", err);
+ return err;
+ }
+
+ err = hinic3_get_func_nic_enable(pf_hwdev, global_func_id, en);
+ if (!!err) {
+ sdk_info(&pdev->dev, "Failed to get function nic status, err %d.\n", err);
+ return err;
+ }
+
+ return 0;
+}
+
+int hinic3_set_func_probe_in_host(void *hwdev, u16 func_id, bool probe)
+{
+ struct hinic3_hwdev *dev = hwdev;
+
+ if (hinic3_func_type(hwdev) != TYPE_PPF)
+ return -EINVAL;
+
+ if (probe)
+ set_bit(func_id, dev->func_probe_in_host);
+ else
+ clear_bit(func_id, dev->func_probe_in_host);
+
+ return 0;
+}
+
+bool hinic3_get_func_probe_in_host(void *hwdev, u16 func_id)
+{
+ struct hinic3_hwdev *dev = hwdev;
+ struct hinic3_hwdev *ppf_dev = NULL;
+ bool probed = false;
+
+ if (!hwdev)
+ return false;
+
+ down(&dev->ppf_sem);
+ ppf_dev = hinic3_get_ppf_hwdev_by_pdev(dev->pcidev_hdl);
+ if (!ppf_dev || hinic3_func_type(ppf_dev) != TYPE_PPF) {
+ up(&dev->ppf_sem);
+ return false;
+ }
+
+ probed = !!test_bit(func_id, ppf_dev->func_probe_in_host);
+ up(&dev->ppf_sem);
+
+ return probed;
+}
+
+void *hinic3_get_ppf_hwdev_by_pdev(struct pci_dev *pdev)
+{
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct card_node *chip_node = NULL;
+ struct hinic3_pcidev *dev = NULL;
+
+ if (!pdev)
+ return NULL;
+
+ pci_adapter = pci_get_drvdata(pdev);
+ if (!pci_adapter)
+ return NULL;
+
+ chip_node = pci_adapter->chip_node;
+ lld_dev_hold(&pci_adapter->lld_dev);
+ list_for_each_entry(dev, &chip_node->func_list, node) {
+ if (dev->lld_state == HINIC3_IN_REMOVE)
+ continue;
+
+ if (dev->hwdev && hinic3_func_type(dev->hwdev) == TYPE_PPF) {
+ lld_dev_put(&pci_adapter->lld_dev);
+ return dev->hwdev;
+ }
+ }
+ lld_dev_put(&pci_adapter->lld_dev);
+
+ return NULL;
+}
+
+static int hinic3_set_vf_nic_used_state(void *hwdev, u16 func_id, bool opened)
+{
+ struct hinic3_hwdev *dev = hwdev;
+ struct hinic3_hwdev *ppf_dev = NULL;
+
+ if (!dev || func_id >= MAX_FUNCTION_NUM)
+ return -EINVAL;
+
+ down(&dev->ppf_sem);
+ ppf_dev = hinic3_get_ppf_hwdev_by_pdev(dev->pcidev_hdl);
+ if (!ppf_dev || hinic3_func_type(ppf_dev) != TYPE_PPF) {
+ up(&dev->ppf_sem);
+ return -EINVAL;
+ }
+
+ if (opened)
+ set_bit(func_id, ppf_dev->netdev_setup_state);
+ else
+ clear_bit(func_id, ppf_dev->netdev_setup_state);
+
+ up(&dev->ppf_sem);
+
+ return 0;
+}
+
+static void set_vf_func_in_use(struct pci_dev *pdev, bool in_use)
+{
+ struct pci_dev *pf_pdev = pdev->physfn;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ void *pf_hwdev = NULL;
+ u16 global_func_id;
+
+ /* only need to be set when VF is on the host */
+ if (!hinic3_pdev_is_virtfn(pdev) || !pf_pdev)
+ return;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter || !pci_adapter->hwdev)
+ return;
+
+ pf_hwdev = pci_adapter->hwdev;
+
+ global_func_id = (u16)pdev->devfn + hinic3_glb_pf_vf_offset(pf_hwdev);
+ (void)hinic3_set_vf_nic_used_state(pf_hwdev, global_func_id, in_use);
+}
+
+static int hinic3_pf_get_vf_offset_info(struct hinic3_pcidev *des_dev, u16 *vf_offset)
+{
+ int err, i;
+ struct hinic3_hw_pf_infos *pf_infos = NULL;
+ u16 pf_func_id;
+ struct hinic3_pcidev *pf_pci_adapter = NULL;
+
+ pf_pci_adapter = (hinic3_pdev_is_virtfn(des_dev->pcidev)) ?
+ pci_get_drvdata(des_dev->pcidev->physfn) : des_dev;
+ pf_func_id = hinic3_global_func_id(pf_pci_adapter->hwdev);
+ if (pf_func_id >= CMD_MAX_MAX_PF_NUM || !vf_offset)
+ return -EINVAL;
+
+ mutex_lock(&g_vf_offset_lock);
+ if (g_vf_offset.valid == 0) {
+ pf_infos = kzalloc(sizeof(*pf_infos), GFP_KERNEL);
+ if (!pf_infos) {
+ err = -ENOMEM;
+ goto err_malloc;
+ }
+
+ err = hinic3_get_hw_pf_infos(pf_pci_adapter->hwdev,
+ pf_infos, HINIC3_CHANNEL_COMM);
+ if (err) {
+ sdk_warn(&pf_pci_adapter->pcidev->dev,
+ "Hinic3_get_hw_pf_infos fail err %d\n", err);
+ err = -EFAULT;
+ goto err_out;
+ }
+
+ g_vf_offset.valid = 1;
+ for (i = 0; i < CMD_MAX_MAX_PF_NUM; i++)
+ g_vf_offset.vf_offset_from_pf[i] = pf_infos->infos[i].vf_offset;
+
+ kfree(pf_infos);
+ }
+
+ *vf_offset = g_vf_offset.vf_offset_from_pf[pf_func_id];
+
+ mutex_unlock(&g_vf_offset_lock);
+
+ return 0;
+
+err_out:
+ kfree(pf_infos);
+err_malloc:
+ mutex_unlock(&g_vf_offset_lock);
+ return err;
+}
+
+static struct pci_dev *get_vf_pdev_by_pf(struct hinic3_pcidev *des_dev,
+ u16 func_id)
+{
+ int err;
+ u16 bus_num;
+ u16 vf_start, vf_end;
+ u16 des_fn, pf_func_id, vf_offset;
+
+ vf_start = hinic3_glb_pf_vf_offset(des_dev->hwdev);
+ vf_end = vf_start + hinic3_func_max_vf(des_dev->hwdev);
+ pf_func_id = hinic3_global_func_id(des_dev->hwdev);
+ if (func_id <= vf_start || func_id > vf_end || pf_func_id >= CMD_MAX_MAX_PF_NUM)
+ return NULL;
+
+ err = hinic3_pf_get_vf_offset_info(des_dev, &vf_offset);
+ if (err) {
+ sdk_warn(&des_dev->pcidev->dev, "Hinic3_pf_get_vf_offset_info fail\n");
+ return NULL;
+ }
+
+ des_fn = ((func_id - vf_start) - 1) + pf_func_id + vf_offset;
+ bus_num = des_dev->pcidev->bus->number + des_fn / BUS_MAX_DEV_NUM;
+
+ return pci_get_domain_bus_and_slot(0, bus_num, (des_fn % BUS_MAX_DEV_NUM));
+}
+
+static struct hinic3_pcidev *get_des_pci_adapter(struct hinic3_pcidev *des_dev,
+ u16 func_id)
+{
+ struct pci_dev *des_pdev = NULL;
+ u16 vf_start, vf_end;
+ bool probe_in_host = false;
+
+ if (hinic3_global_func_id(des_dev->hwdev) == func_id)
+ return des_dev;
+
+ vf_start = hinic3_glb_pf_vf_offset(des_dev->hwdev);
+ vf_end = vf_start + hinic3_func_max_vf(des_dev->hwdev);
+ if (func_id <= vf_start || func_id > vf_end)
+ return NULL;
+
+ des_pdev = get_vf_pdev_by_pf(des_dev, func_id);
+ if (!des_pdev)
+ return NULL;
+
+ pci_dev_put(des_pdev);
+
+ probe_in_host = hinic3_get_func_probe_in_host(des_dev->hwdev, func_id);
+ if (!probe_in_host)
+ return NULL;
+
+ return pci_get_drvdata(des_pdev);
+}
+
+int __set_vroce_func_state(struct hinic3_pcidev *pci_adapter)
+{
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ u16 func_id;
+ int err;
+ u8 enable_vroce = false;
+
+ func_id = hinic3_global_func_id(pci_adapter->hwdev);
+
+ err = hinic3_get_func_vroce_enable(pci_adapter->hwdev,
+ func_id, &enable_vroce);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Failed to get vroce state.\n");
+ return err;
+ }
+
+ mutex_lock(&g_uld_mutex);
+
+ if (!!enable_vroce) {
+ if (!g_uld_info[SERVICE_T_ROCE].probe) {
+ sdk_info(&pdev->dev, "Uld(roce_info) has not been registered!\n");
+ mutex_unlock(&g_uld_mutex);
+ return 0;
+ }
+
+ err = attach_uld(pci_adapter, SERVICE_T_ROCE,
+ &g_uld_info[SERVICE_T_ROCE]);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Failed to initialize VROCE.\n");
+ mutex_unlock(&g_uld_mutex);
+ return err;
+ }
+ } else {
+ sdk_info(&pdev->dev, "Func %u vroce state: disable.\n", func_id);
+ if (g_uld_info[SERVICE_T_ROCE].remove)
+ detach_uld(pci_adapter, SERVICE_T_ROCE);
+ }
+
+ mutex_unlock(&g_uld_mutex);
+
+ return 0;
+}
+
+void slave_host_mgmt_vroce_work(struct work_struct *work)
+{
+#ifndef __HIFC__
+ struct hinic3_pcidev *pci_adapter =
+ container_of(work, struct hinic3_pcidev, slave_vroce_work);
+
+ __set_vroce_func_state(pci_adapter);
+#endif
+}
+
+void *hinic3_get_roce_uld_by_pdev(struct pci_dev *pdev)
+{
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!pdev)
+ return NULL;
+
+ pci_adapter = pci_get_drvdata(pdev);
+ if (!pci_adapter)
+ return NULL;
+
+ return pci_adapter->uld_dev[SERVICE_T_ROCE];
+}
+
+static int func_service_state_process(struct hinic3_pcidev *event_dev,
+ struct hinic3_pcidev *des_dev,
+ struct hinic3_mhost_nic_func_state *state,
+ u16 cmd)
+{
+ int err = 0;
+ struct hinic3_hwdev *dev = (struct hinic3_hwdev *)event_dev->hwdev;
+
+ switch (cmd) {
+ case HINIC3_MHOST_GET_VROCE_STATE:
+ state->enable = hinic3_get_roce_uld_by_pdev(des_dev->pcidev) ? 1 : 0;
+ break;
+ case HINIC3_MHOST_NIC_STATE_CHANGE:
+ sdk_info(&des_dev->pcidev->dev, "Receive nic[%u] state changed event, state: %u\n",
+ state->func_idx, state->enable);
+ if (event_dev->multi_host_mgmt_workq) {
+ queue_work(event_dev->multi_host_mgmt_workq,
+ &des_dev->slave_nic_work);
+ } else {
+ sdk_err(&des_dev->pcidev->dev, "Can not schedule slave nic work\n");
+ err = -EFAULT;
+ }
+ break;
+ case HINIC3_MHOST_VROCE_STATE_CHANGE:
+ sdk_info(&des_dev->pcidev->dev, "Receive vroce[%u] state changed event, state: %u\n",
+ state->func_idx, state->enable);
+ queue_work_on(hisdk3_get_work_cpu_affinity(dev, WORK_TYPE_MBOX),
+ event_dev->multi_host_mgmt_workq,
+ &des_dev->slave_vroce_work);
+ break;
+ default:
+ sdk_warn(&des_dev->pcidev->dev,
+ "Service state process with unknown cmd: %u\n", cmd);
+ err = -EFAULT;
+ break;
+ }
+
+ return err;
+}
+
+static void multi_host_mgmt(struct hinic3_pcidev *dev,
+ struct hinic3_multi_host_mgmt_event *mhost_mgmt)
+{
+ struct hinic3_pcidev *cur_dev = NULL;
+ struct hinic3_pcidev *des_dev = NULL;
+ struct hinic3_mhost_nic_func_state *nic_state = NULL;
+ u16 sub_cmd = mhost_mgmt->sub_cmd;
+
+ switch (sub_cmd) {
+ case HINIC3_MHOST_GET_VROCE_STATE:
+ case HINIC3_MHOST_VROCE_STATE_CHANGE:
+ case HINIC3_MHOST_NIC_STATE_CHANGE:
+ nic_state = mhost_mgmt->data;
+ nic_state->status = 0;
+ if (!dev->hwdev)
+ return;
+
+ if (!IS_BMGW_SLAVE_HOST((struct hinic3_hwdev *)dev->hwdev))
+ return;
+
+ /* find func_idx pci_adapter and disable or enable nic */
+ lld_dev_hold(&dev->lld_dev);
+ list_for_each_entry(cur_dev, &dev->chip_node->func_list, node) {
+ if (cur_dev->lld_state == HINIC3_IN_REMOVE ||
+ hinic3_pdev_is_virtfn(cur_dev->pcidev))
+ continue;
+
+ des_dev = get_des_pci_adapter(cur_dev, nic_state->func_idx);
+ if (!des_dev)
+ continue;
+
+ if (func_service_state_process(dev, des_dev, nic_state, sub_cmd))
+ nic_state->status = 1;
+ break;
+ }
+ lld_dev_put(&dev->lld_dev);
+ break;
+ default:
+ sdk_warn(&dev->pcidev->dev, "Received unknown multi-host mgmt event: %u\n",
+ mhost_mgmt->sub_cmd);
+ break;
+ }
+}
+
static void hinic3_event_process(void *adapter, struct hinic3_event_info *event)
{
struct hinic3_pcidev *dev = adapter;
struct hinic3_fault_event *fault = (void *)event->event_data;
+ struct hinic3_multi_host_mgmt_event *mhost_event =
+ (void *)event->event_data;
u16 func_id;
- if ((event->service == EVENT_SRV_COMM && event->type == EVENT_COMM_FAULT) &&
- fault->fault_level == FAULT_LEVEL_SERIOUS_FLR &&
- fault->event.chip.func_id < hinic3_max_pf_num(dev->hwdev)) {
- func_id = fault->event.chip.func_id;
- return send_event_to_dst_pf(adapter, func_id, event);
- }
-
- if (event->type == EVENT_COMM_MGMT_WATCHDOG)
+ switch (HINIC3_SRV_EVENT_TYPE(event->service, event->type)) {
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_MULTI_HOST_MGMT):
+ multi_host_mgmt(dev, mhost_event);
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_FAULT):
+ if (fault->fault_level == FAULT_LEVEL_SERIOUS_FLR &&
+ fault->event.chip.func_id < hinic3_max_pf_num(dev->hwdev)) {
+ func_id = fault->event.chip.func_id;
+ return send_event_to_dst_pf(adapter, func_id, event);
+ }
+ break;
+ case HINIC3_SRV_EVENT_TYPE(EVENT_SRV_COMM, EVENT_COMM_MGMT_WATCHDOG):
send_event_to_all_pf(adapter, event);
- else
+ break;
+ default:
send_uld_dev_event(adapter, event);
+ break;
+ }
}
static void uld_def_init(struct hinic3_pcidev *pci_adapter)
@@ -605,31 +1109,70 @@ static void hinic3_pci_deinit(struct pci_dev *pdev)
kfree(pci_adapter);
}
-#ifdef CONFIG_X86
-/**
- * cfg_order_reg - when cpu model is haswell or broadwell, should configure dma
- * order register to zero
- * @pci_adapter: pci_adapter
- **/
-/*lint -save -e40 */
-static void cfg_order_reg(struct hinic3_pcidev *pci_adapter)
+static void set_vf_load_state(struct pci_dev *pdev, struct hinic3_pcidev *pci_adapter)
{
- u8 cpu_model[] = {0x3c, 0x3f, 0x45, 0x46, 0x3d, 0x47, 0x4f, 0x56};
- struct cpuinfo_x86 *cpuinfo = NULL;
- u32 i;
+ /* In bm mode, slave host will load vfs in default */
+ if (IS_BMGW_SLAVE_HOST(((struct hinic3_hwdev *)pci_adapter->hwdev)) &&
+ hinic3_func_type(pci_adapter->hwdev) != TYPE_VF)
+ hinic3_set_vf_load_state(pdev, false);
- if (hinic3_func_type(pci_adapter->hwdev) == TYPE_VF)
- return;
+ if (!disable_attach) {
+ if ((hinic3_func_type(pci_adapter->hwdev) != TYPE_VF) &&
+ hinic3_is_bm_slave_host(pci_adapter->hwdev)) {
+ if (hinic3_func_max_vf(pci_adapter->hwdev) == 0) {
+ sdk_warn(&pdev->dev, "The sriov enabling process is skipped, vfs_num: 0.\n");
+ return;
+ }
+ hinic3_pci_sriov_enable(pdev,
+ hinic3_func_max_vf(pci_adapter->hwdev));
+ }
+ }
+}
- cpuinfo = &cpu_data(0);
- for (i = 0; i < sizeof(cpu_model); i++) {
- if (cpu_model[i] == cpuinfo->x86_model)
- hinic3_set_pcie_order_cfg(pci_adapter->hwdev);
+static void hinic3_init_ppf_hwdev(struct hinic3_hwdev *hwdev)
+{
+ if (!hwdev) {
+ pr_err("[%s:%d] null hwdev pointer\n", __FILE__, __LINE__);
+ return;
}
+
+ hwdev->ppf_hwdev = hinic3_get_ppf_hwdev_by_pdev(hwdev->pcidev_hdl);
}
-/*lint -restore*/
-#endif
+static int set_nic_func_state(struct hinic3_pcidev *pci_adapter)
+{
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ u16 func_id;
+ int err;
+ bool enable_nic = false;
+
+ func_id = hinic3_global_func_id(pci_adapter->hwdev);
+
+ err = hinic3_get_func_nic_enable(pci_adapter->hwdev, func_id, &enable_nic);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Failed to get nic state.\n");
+ return err;
+ }
+
+ if (!enable_nic) {
+ sdk_info(&pdev->dev, "Func %u nic state: disable.\n", func_id);
+ detach_uld(pci_adapter, SERVICE_T_NIC);
+ return 0;
+ }
+
+ if (IS_BMGW_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev))
+ (void)hinic3_init_vf_dev_cap(pci_adapter->hwdev);
+
+ if (g_uld_info[SERVICE_T_NIC].probe) {
+ err = attach_uld(pci_adapter, SERVICE_T_NIC, &g_uld_info[SERVICE_T_NIC]);
+ if (err != 0) {
+ sdk_err(&pdev->dev, "Initialize NIC failed\n");
+ return err;
+ }
+ }
+
+ return 0;
+}
static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adapter)
{
@@ -689,7 +1232,16 @@ static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adap
list_add_tail(&pci_adapter->node, &pci_adapter->chip_node->func_list);
lld_unlock_chip_node();
+ hinic3_init_ppf_hwdev((struct hinic3_hwdev *)pci_adapter->hwdev);
+
+ set_vf_load_state(pdev, pci_adapter);
+
if (!disable_attach) {
+ /* NIC is base driver, probe firstly */
+ err = set_nic_func_state(pci_adapter);
+ if (err)
+ goto set_nic_func_state_err;
+
attach_ulds(pci_adapter);
if (hinic3_func_type(pci_adapter->hwdev) != TYPE_VF) {
@@ -700,10 +1252,6 @@ static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adap
goto create_sysfs_err;
}
}
-
-#ifdef CONFIG_X86
- cfg_order_reg(pci_adapter);
-#endif
}
return 0;
@@ -711,6 +1259,7 @@ static int hinic3_func_init(struct pci_dev *pdev, struct hinic3_pcidev *pci_adap
create_sysfs_err:
detach_ulds(pci_adapter);
+set_nic_func_state_err:
lld_lock_chip_node();
list_del(&pci_adapter->node);
lld_unlock_chip_node();
@@ -759,6 +1308,7 @@ static void hinic3_func_deinit(struct pci_dev *pdev)
hinic3_free_stateful(pci_adapter->hwdev);
hinic3_free_hwdev(pci_adapter->hwdev);
+ pci_adapter->hwdev = NULL;
}
static void wait_sriov_cfg_complete(struct hinic3_pcidev *pci_adapter)
@@ -766,18 +1316,61 @@ static void wait_sriov_cfg_complete(struct hinic3_pcidev *pci_adapter)
struct hinic3_sriov_info *sriov_info;
unsigned long end;
- sriov_info = &pci_adapter->sriov_info;
- clear_bit(HINIC3_FUNC_PERSENT, &sriov_info->state);
- usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
+ sriov_info = &pci_adapter->sriov_info;
+ clear_bit(HINIC3_FUNC_PERSENT, &sriov_info->state);
+ usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
+
+ end = jiffies + msecs_to_jiffies(HINIC3_WAIT_SRIOV_CFG_TIMEOUT);
+ do {
+ if (!test_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state) &&
+ !test_bit(HINIC3_SRIOV_DISABLE, &sriov_info->state))
+ return;
+
+ usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
+ } while (time_before(jiffies, end));
+}
+
+static bool hinic3_get_vf_nic_en_status(struct pci_dev *pdev)
+{
+ bool nic_en = false;
+ u16 global_func_id;
+ struct pci_dev *pf_pdev = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!pdev) {
+ pr_err("pdev is null.\n");
+ return false;
+ }
+
+ if (pdev->is_virtfn)
+ pf_pdev = pdev->physfn;
+ else
+ return false;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_err(&pdev->dev, "pci_adapter is null.\n");
+ return false;
+ }
+
+ if (!IS_BMGW_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev))
+ return false;
+
+ if (hinic3_get_vfid_by_vfpci(NULL, pdev, &global_func_id)) {
+ sdk_err(&pdev->dev, "Get vf id by vfpci failed\n");
+ return false;
+ }
+
+ if (hinic3_get_mhost_func_nic_enable(pci_adapter->hwdev,
+ global_func_id, &nic_en)) {
+ sdk_err(&pdev->dev, "Get function nic status failed\n");
+ return false;
+ }
- end = jiffies + msecs_to_jiffies(HINIC3_WAIT_SRIOV_CFG_TIMEOUT);
- do {
- if (!test_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state) &&
- !test_bit(HINIC3_SRIOV_DISABLE, &sriov_info->state))
- return;
+ sdk_info(&pdev->dev, "Func %hu %s default probe in host\n",
+ global_func_id, (nic_en) ? "enable" : "disable");
- usleep_range(9900, 10000); /* sleep 9900 us ~ 10000 us */
- } while (time_before(jiffies, end));
+ return nic_en;
}
bool hinic3_get_vf_load_state(struct pci_dev *pdev)
@@ -897,6 +1490,32 @@ int hinic3_set_vf_service_load(struct pci_dev *pdev, u16 service,
}
EXPORT_SYMBOL(hinic3_set_vf_service_load);
+static bool hinic3_is_host_vmsec_enable(struct pci_dev *pdev)
+{
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct pci_dev *pf_pdev = NULL;
+
+ if (pdev->is_virtfn)
+ pf_pdev = pdev->physfn;
+ else
+ pf_pdev = pdev;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ pr_err("Pci_adapter is null.\n");
+ return false;
+ }
+
+ /* pf/vf used in host */
+ if (IS_VM_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev) &&
+ (hinic3_func_type(pci_adapter->hwdev) == TYPE_PF) &&
+ IS_RDMA_TYPE((struct hinic3_hwdev *)pci_adapter->hwdev)) {
+ return true;
+ }
+
+ return false;
+}
+
static int hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
{
struct pci_dev *pdev = pci_adapter->pcidev;
@@ -910,6 +1529,13 @@ static int hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
pci_adapter->lld_state = HINIC3_IN_REMOVE;
mutex_unlock(&pci_adapter->pdev_mutex);
+ if (!(pdev->is_virtfn) && (hinic3_is_host_vmsec_enable(pdev) == true) &&
+ (hinic3_func_type((struct hinic3_hwdev *)pci_adapter->hwdev) == TYPE_PF)) {
+ cancel_delayed_work_sync(&pci_adapter->migration_probe_dwork);
+ flush_workqueue(pci_adapter->migration_probe_workq);
+ destroy_workqueue(pci_adapter->migration_probe_workq);
+ }
+
hinic3_detect_hw_present(pci_adapter->hwdev);
hisdk3_remove_pre_process(pci_adapter->hwdev);
@@ -934,23 +1560,127 @@ static int hinic3_remove_func(struct hinic3_pcidev *pci_adapter)
sdk_info(&pdev->dev, "Pcie device removed function\n");
+ set_vf_func_in_use(pdev, false);
+
+ return 0;
+}
+
+int hinic3_get_vfid_by_vfpci(void *hwdev, struct pci_dev *pdev, u16 *global_func_id)
+{
+ struct pci_dev *pf_pdev = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ u16 pf_bus, vf_bus, vf_offset;
+ int err;
+
+ if (!pdev || !global_func_id || !hinic3_pdev_is_virtfn(pdev))
+ return -EINVAL;
+ (void)hwdev;
+ pf_pdev = pdev->physfn;
+
+ vf_bus = pdev->bus->number;
+ pf_bus = pf_pdev->bus->number;
+
+ if (pdev->vendor == HINIC3_VIRTIO_VNEDER_ID)
+ return -EPERM;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_err(&pdev->dev, "pci_adapter is null.\n");
+ return -EINVAL;
+ }
+
+ err = hinic3_pf_get_vf_offset_info(pci_adapter, &vf_offset);
+ if (err) {
+ sdk_err(&pdev->dev, "Func hinic3_pf_get_vf_offset_info fail\n");
+ return -EFAULT;
+ }
+
+ *global_func_id = (u16)((vf_bus - pf_bus) * BUS_MAX_DEV_NUM) + (u16)pdev->devfn +
+ (u16)(CMD_MAX_MAX_PF_NUM - g_vf_offset.vf_offset_from_pf[0]);
+
return 0;
}
+EXPORT_SYMBOL(hinic3_get_vfid_by_vfpci);
+
+static void hinic3_set_vf_status_in_host(struct pci_dev *pdev, bool status)
+{
+ struct pci_dev *pf_pdev = pdev->physfn;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ void *pf_hwdev = NULL;
+ void *ppf_hwdev = NULL;
+ u16 global_func_id;
+ int ret;
+
+ if (!pf_pdev)
+ return;
+
+ if (!hinic3_pdev_is_virtfn(pdev))
+ return;
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ pf_hwdev = pci_adapter->hwdev;
+ ppf_hwdev = hinic3_get_ppf_hwdev_by_pdev(pf_pdev);
+ if (!pf_hwdev || !ppf_hwdev)
+ return;
+
+ ret = hinic3_get_vfid_by_vfpci(NULL, pdev, &global_func_id);
+ if (ret) {
+ sdk_err(&pci_adapter->pcidev->dev,
+ "Func hinic3_get_vfid_by_vfpci fail %d\n", ret);
+ return;
+ }
+
+ ret = hinic3_set_func_probe_in_host(ppf_hwdev, global_func_id, status);
+ if (ret)
+ sdk_err(&pci_adapter->pcidev->dev,
+ "Set the function probe status in host failed\n");
+}
+
+#ifdef CONFIG_PCI_IOV
+/* Check whether pdev is a VF and whether it belongs to the PF of the SDI card */
+static bool check_pdev_type_and_state(struct pci_dev *pdev)
+{
+ if (!(pdev->is_virtfn))
+ return false;
+
+ if ((hinic3_get_pf_device_id(pdev) != HINIC3_DEV_ID_SDI_5_1_PF) &&
+ (hinic3_get_pf_device_id(pdev) != HINIC3_DEV_ID_SDI_5_0_PF)) {
+ return false;
+ }
+
+ if (!hinic3_get_vf_load_state(pdev))
+ return false;
+
+ return true;
+}
+#endif
static void hinic3_remove(struct pci_dev *pdev)
{
struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
+ sdk_info(&pdev->dev, "Pcie device remove begin\n");
+
if (!pci_adapter)
- return;
+ goto out;
- sdk_info(&pdev->dev, "Pcie device remove begin\n");
+#ifdef CONFIG_PCI_IOV
+ if (check_pdev_type_and_state(pdev))
+ goto out;
+#endif
+ cancel_work_sync(&pci_adapter->slave_nic_work);
+ cancel_work_sync(&pci_adapter->slave_vroce_work);
hinic3_remove_func(pci_adapter);
+ if (!pci_adapter->pcidev->is_virtfn &&
+ pci_adapter->multi_host_mgmt_workq)
+ destroy_workqueue(pci_adapter->multi_host_mgmt_workq);
hinic3_pci_deinit(pdev);
hinic3_probe_pre_unprocess(pdev);
+out:
+ hinic3_set_vf_status_in_host(pdev, false);
sdk_info(&pdev->dev, "Pcie device removed\n");
}
@@ -969,7 +1699,7 @@ static int probe_func_param_init(struct hinic3_pcidev *pci_adapter)
if (pci_adapter->lld_state >= HINIC3_PROBE_START) {
sdk_warn(&pdev->dev, "Don not probe repeat\n");
mutex_unlock(&pci_adapter->pdev_mutex);
- return 0;
+ return -EEXIST;
}
pci_adapter->lld_state = HINIC3_PROBE_START;
mutex_unlock(&pci_adapter->pdev_mutex);
@@ -977,15 +1707,28 @@ static int probe_func_param_init(struct hinic3_pcidev *pci_adapter)
return 0;
}
+static void hinic3_probe_success_process(struct hinic3_pcidev *pci_adapter)
+{
+ hinic3_probe_success(pci_adapter->hwdev);
+
+ mutex_lock(&pci_adapter->pdev_mutex);
+ pci_adapter->lld_state = HINIC3_PROBE_OK;
+ mutex_unlock(&pci_adapter->pdev_mutex);
+}
+
static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)
{
struct pci_dev *pdev = pci_adapter->pcidev;
int err;
err = probe_func_param_init(pci_adapter);
- if (err)
+ if (err == -EEXIST)
+ return 0;
+ else if (err)
return err;
+ set_vf_func_in_use(pdev, true);
+
err = mapping_bar(pdev, pci_adapter);
if (err) {
sdk_err(&pdev->dev, "Failed to map bar\n");
@@ -1017,11 +1760,7 @@ static int hinic3_probe_func(struct hinic3_pcidev *pci_adapter)
}
}
- hinic3_probe_success(pci_adapter->hwdev);
-
- mutex_lock(&pci_adapter->pdev_mutex);
- pci_adapter->lld_state = HINIC3_PROBE_OK;
- mutex_unlock(&pci_adapter->pdev_mutex);
+ hinic3_probe_success_process(pci_adapter);
return 0;
@@ -1037,18 +1776,300 @@ alloc_chip_node_fail:
unmapping_bar(pci_adapter);
map_bar_failed:
+ set_vf_func_in_use(pdev, false);
sdk_err(&pdev->dev, "Pcie device probe function failed\n");
return err;
}
+void hinic3_set_func_state(struct hinic3_pcidev *pci_adapter)
+{
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ int err;
+ bool enable_func = false;
+
+ err = hinic3_get_function_enable(pdev, &enable_func);
+ if (err) {
+ sdk_info(&pdev->dev, "Get function enable failed\n");
+ return;
+ }
+
+ sdk_info(&pdev->dev, "%s function resource start\n",
+ enable_func ? "Initialize" : "Free");
+ if (enable_func) {
+ err = hinic3_probe_func(pci_adapter);
+ if (err)
+ sdk_info(&pdev->dev, "Function probe failed\n");
+ } else {
+ hinic3_remove_func(pci_adapter);
+ }
+ if (err == 0)
+ sdk_info(&pdev->dev, "%s function resource end\n",
+ enable_func ? "Initialize" : "Free");
+}
+
+void slave_host_mgmt_work(struct work_struct *work)
+{
+ struct hinic3_pcidev *pci_adapter =
+ container_of(work, struct hinic3_pcidev, slave_nic_work);
+
+ if (hinic3_pdev_is_virtfn(pci_adapter->pcidev))
+ hinic3_set_func_state(pci_adapter);
+ else
+ set_nic_func_state(pci_adapter);
+}
+
+static int pci_adapter_assign_val(struct hinic3_pcidev **ppci_adapter,
+ struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ *ppci_adapter = pci_get_drvdata(pdev);
+ (*ppci_adapter)->disable_vf_load = disable_vf_load;
+ (*ppci_adapter)->id = *id;
+ (*ppci_adapter)->lld_state = HINIC3_NOT_PROBE;
+ (*ppci_adapter)->probe_fault_level = FAULT_LEVEL_SERIOUS_FLR;
+ lld_dev_cnt_init(*ppci_adapter);
+
+ (*ppci_adapter)->multi_host_mgmt_workq = alloc_workqueue("hinic_mhost_mgmt",
+ WQ_UNBOUND,
+ HINIC3_SLAVE_WORK_MAX_NUM);
+ if (!(*ppci_adapter)->multi_host_mgmt_workq) {
+ hinic3_pci_deinit(pdev);
+ sdk_err(&pdev->dev, "Alloc multi host mgmt workqueue failed\n");
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&(*ppci_adapter)->slave_nic_work, slave_host_mgmt_work);
+ INIT_WORK(&(*ppci_adapter)->slave_vroce_work,
+ slave_host_mgmt_vroce_work);
+
+ return 0;
+}
+
+static void slave_host_vfio_probe_delay_work(struct work_struct *work)
+{
+ struct delayed_work *delay = to_delayed_work(work);
+ struct hinic3_pcidev *pci_adapter = container_of(delay, struct hinic3_pcidev,
+ migration_probe_dwork);
+ struct pci_dev *pdev = pci_adapter->pcidev;
+ int (*dev_migration_probe)(struct pci_dev *pdev);
+ int rc;
+
+ if (hinic3_func_type((struct hinic3_hwdev *)pci_adapter->hwdev) != TYPE_PF)
+ return;
+
+ dev_migration_probe = __symbol_get("migration_dev_migration_probe");
+ if (!(dev_migration_probe)) {
+ sdk_err(&pdev->dev,
+ "Failed to find: migration_dev_migration_probe");
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &pci_adapter->migration_probe_dwork,
+ WAIT_TIME * HZ);
+ } else {
+ rc = dev_migration_probe(pdev);
+ __symbol_put("migration_dev_migration_probe");
+ if (rc) {
+ sdk_err(&pdev->dev,
+ "Failed to __dev_migration_probe, rc:0x%x, pf migrated(%d).\n",
+ rc, g_is_pf_migrated);
+ } else {
+ g_is_pf_migrated = true;
+ sdk_info(&pdev->dev,
+ "Succeeded in __dev_migration_probe, pf migrated(%d).\n",
+ g_is_pf_migrated);
+ }
+ }
+}
+
+struct vf_add_delaywork {
+ struct pci_dev *vf_pdev;
+ struct delayed_work migration_vf_add_dwork;
+};
+
+static void slave_host_migration_vf_add_delay_work(struct work_struct *work)
+{
+ struct delayed_work *delay = to_delayed_work(work);
+ struct vf_add_delaywork *vf_add = container_of(delay, struct vf_add_delaywork,
+ migration_vf_add_dwork);
+ struct pci_dev *vf_pdev = vf_add->vf_pdev;
+ struct pci_dev *pf_pdev = NULL;
+ int (*migration_dev_add_vf)(struct pci_dev *vf_pdev);
+ int ret;
+ struct hinic3_pcidev *pci_adapter = NULL;
+
+ if (!vf_pdev) {
+ pr_err("vf pdev is null.\n");
+ goto err1;
+ }
+ if (!vf_pdev->is_virtfn) {
+ sdk_err(&vf_pdev->dev, "Pdev is not virtfn.\n");
+ goto err1;
+ }
+
+ pf_pdev = vf_pdev->physfn;
+ if (!pf_pdev) {
+ sdk_err(&vf_pdev->dev, "pf_pdev is null.\n");
+ goto err1;
+ }
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_err(&vf_pdev->dev, "Pci_adapter is null.\n");
+ goto err1;
+ }
+
+ if (!g_is_pf_migrated) {
+ sdk_info(&vf_pdev->dev, "pf is not migrated yet, so vf continues to try again.\n");
+ goto delay_work;
+ }
+
+ migration_dev_add_vf = __symbol_get("migration_dev_add_vf");
+ if (migration_dev_add_vf) {
+ ret = migration_dev_add_vf(vf_pdev);
+ __symbol_put("migration_dev_add_vf");
+ if (ret)
+ sdk_err(&vf_pdev->dev, "vf get migration symbol succeeded, but dev add vf failed, ret:%d.\n",
+ ret);
+ else
+ sdk_info(&vf_pdev->dev, "vf get migration symbol succeeded, and dev add vf success.\n");
+ goto err1;
+ }
+ sdk_info(&vf_pdev->dev, "pf is migrated, but vf get migration symbol failed.\n");
+
+delay_work:
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &vf_add->migration_vf_add_dwork, WAIT_TIME * HZ);
+ return;
+
+err1:
+ kfree(vf_add);
+}
+
+static void hinic3_probe_vf_add_dwork(struct pci_dev *pdev)
+{
+ struct pci_dev *pf_pdev = NULL;
+ struct hinic3_pcidev *pci_adapter = NULL;
+ struct vf_add_delaywork *vf_add = NULL;
+
+ if (!hinic3_is_host_vmsec_enable(pdev))
+ return;
+
+#if defined(CONFIG_SP_VID_DID)
+ if (pdev->vendor == PCI_VENDOR_ID_SPNIC && pdev->device == HINIC3_DEV_SDI_5_1_ID_VF) {
+#elif defined(CONFIG_NF_VID_DID)
+ if (pdev->vendor == PCI_VENDOR_ID_NF && pdev->device == NFNIC_DEV_ID_VF) {
+#else
+ if (pdev->vendor == PCI_VENDOR_ID_HUAWEI && pdev->device == HINIC3_DEV_SDI_5_0_ID_VF) {
+#endif
+ vf_add = kmalloc(sizeof(*vf_add), GFP_ATOMIC);
+
+ if (!vf_add) {
+ sdk_info(&pdev->dev, "vf_add is null.\n");
+ return;
+ }
+ vf_add->vf_pdev = pdev;
+
+ pf_pdev = pdev->physfn;
+
+ if (!pf_pdev) {
+ sdk_info(&pdev->dev, "Vf-pf_pdev is null.\n");
+ kfree(vf_add);
+ return;
+ }
+
+ pci_adapter = pci_get_drvdata(pf_pdev);
+ if (!pci_adapter) {
+ sdk_info(&pdev->dev, "Pci_adapter is null.\n");
+ kfree(vf_add);
+ return;
+ }
+
+ INIT_DELAYED_WORK(&vf_add->migration_vf_add_dwork,
+ slave_host_migration_vf_add_delay_work);
+
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &vf_add->migration_vf_add_dwork,
+ WAIT_TIME * HZ);
+ }
+}
+
+static int hinic3_probe_migration_dwork(struct pci_dev *pdev, struct hinic3_pcidev *pci_adapter)
+{
+ if (!hinic3_is_host_vmsec_enable(pdev)) {
+ sdk_info(&pdev->dev, "Probe_migration : hinic3_is_host_vmsec_enable is (0).\n");
+ return 0;
+ }
+
+ if (IS_VM_SLAVE_HOST((struct hinic3_hwdev *)pci_adapter->hwdev) &&
+ hinic3_func_type((struct hinic3_hwdev *)pci_adapter->hwdev) == TYPE_PF) {
+ pci_adapter->migration_probe_workq =
+ create_singlethread_workqueue("hinic3_migration_probe_delay");
+ if (!pci_adapter->migration_probe_workq) {
+ sdk_err(&pdev->dev, "Failed to create work queue:%s\n",
+ "hinic3_migration_probe_delay");
+ return -EINVAL;
+ }
+
+ INIT_DELAYED_WORK(&pci_adapter->migration_probe_dwork,
+ slave_host_vfio_probe_delay_work);
+
+ queue_delayed_work(pci_adapter->migration_probe_workq,
+ &pci_adapter->migration_probe_dwork,
+ WAIT_TIME * HZ);
+ }
+
+ return 0;
+}
+
+static bool hinic3_os_hot_replace_allow(struct hinic3_pcidev *pci_adapter)
+{
+ struct hinic3_hwdev *hwdev = (struct hinic3_hwdev *)pci_adapter->hwdev;
+ // check service enable and dev is not VF
+ if (hinic3_func_type(hwdev) == TYPE_VF || hwdev->hot_replace_mode == HOT_REPLACE_DISABLE)
+ return false;
+
+ return true;
+}
+
+static bool hinic3_os_hot_replace_process(struct hinic3_pcidev *pci_adapter)
+{
+ struct hinic3_board_info *board_info;
+ u16 cur_pf_id = hinic3_global_func_id(pci_adapter->hwdev);
+ u8 cur_partion_id;
+
+ board_info = &((struct hinic3_hwdev *)(pci_adapter->hwdev))->board_info;
+ // probe to os
+ vpci_set_partition_attrs(pci_adapter->pcidev, PARTITION_DEV_EXCLUSIVE,
+ get_function_partition(cur_pf_id,
+ board_info->port_num));
+
+ // check pf_id is in the right partition_id
+ cur_partion_id = get_partition_id();
+ if (get_function_partition(cur_pf_id, board_info->port_num) ==
+ cur_partion_id)
+ return true;
+
+ pci_adapter->probe_fault_level = FAULT_LEVEL_SUGGESTION;
+ return false;
+}
+
static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct hinic3_pcidev *pci_adapter = NULL;
u16 probe_fault_level = FAULT_LEVEL_SERIOUS_FLR;
+ u32 device_id, function_id;
int err;
sdk_info(&pdev->dev, "Pcie device probe begin\n");
+#ifdef CONFIG_PCI_IOV
+ hinic3_set_vf_status_in_host(pdev, true);
+ if (check_pdev_type_and_state(pdev)) {
+ sdk_info(&pdev->dev, "VFs are not binded to hinic\n");
+ hinic3_probe_vf_add_dwork(pdev);
+ return -EINVAL;
+ }
+#endif
+
err = hinic3_probe_pre_process(pdev);
if (err != 0 && err != HINIC3_NOT_PROBE)
goto out;
@@ -1060,26 +2081,48 @@ static int hinic3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto pci_init_err;
- pci_adapter = pci_get_drvdata(pdev);
- pci_adapter->disable_vf_load = disable_vf_load;
- pci_adapter->id = *id;
- pci_adapter->lld_state = HINIC3_NOT_PROBE;
- pci_adapter->probe_fault_level = probe_fault_level;
- lld_dev_cnt_init(pci_adapter);
+ err = pci_adapter_assign_val(&pci_adapter, pdev, id);
+ if (err)
+ goto allco_queue_err;
- if (pdev->is_virtfn && (!hinic3_get_vf_load_state(pdev))) {
+ if (pdev->is_virtfn && (!hinic3_get_vf_load_state(pdev)) &&
+ (!hinic3_get_vf_nic_en_status(pdev))) {
sdk_info(&pdev->dev, "VF device disable load in host\n");
return 0;
}
- err = hinic3_probe_func(pci_adapter);
- if (err)
+ if (hinic3_probe_func(pci_adapter))
+ goto hinic3_probe_func_fail;
+
+ if (hinic3_os_hot_replace_allow(pci_adapter)) {
+ if (!hinic3_os_hot_replace_process(pci_adapter)) {
+ device_id = PCI_SLOT(pdev->devfn);
+ function_id = PCI_FUNC(pdev->devfn);
+ sdk_info(&pdev->dev,
+ "os hot replace: skip function %d:%d for partition %d",
+ device_id, function_id, get_partition_id());
+ goto os_hot_repalce_not_allow;
+ }
+ }
+
+ if (hinic3_probe_migration_dwork(pdev, pci_adapter))
goto hinic3_probe_func_fail;
sdk_info(&pdev->dev, "Pcie device probed\n");
return 0;
+os_hot_repalce_not_allow:
+ hinic3_func_deinit(pdev);
+ lld_lock_chip_node();
+ free_chip_node(pci_adapter);
+ lld_unlock_chip_node();
+ unmapping_bar(pci_adapter);
+ set_vf_func_in_use(pdev, false);
hinic3_probe_func_fail:
+ destroy_workqueue(pci_adapter->multi_host_mgmt_workq);
+ cancel_work_sync(&pci_adapter->slave_nic_work);
+ cancel_work_sync(&pci_adapter->slave_vroce_work);
+allco_queue_err:
probe_fault_level = pci_adapter->probe_fault_level;
hinic3_pci_deinit(pdev);
@@ -1105,6 +2148,11 @@ static int hinic3_get_pf_info(struct pci_dev *pdev, u16 service,
}
*pf_infos = kzalloc(sizeof(*pf_infos), GFP_KERNEL);
+ if (*pf_infos == NULL) {
+ sdk_err(&pdev->dev, "pf_infos kzalloc failed\n");
+ return -EFAULT;
+ }
+
err = hinic3_get_hw_pf_infos(dev->hwdev, *pf_infos, HINIC3_CHANNEL_COMM);
if (err) {
kfree(*pf_infos);
@@ -1120,6 +2168,7 @@ static int hinic3_set_func_en(struct pci_dev *des_pdev, struct hinic3_pcidev *ds
{
int err;
+ mutex_lock(&dst_dev->pdev_mutex);
/* unload invalid vf func id */
if (!en && vf_func_id != hinic3_global_func_id(dst_dev->hwdev) &&
!strcmp(des_pdev->driver->name, HINIC3_DRV_NAME)) {
@@ -1137,6 +2186,8 @@ static int hinic3_set_func_en(struct pci_dev *des_pdev, struct hinic3_pcidev *ds
err = hinic3_probe_func(dst_dev);
if (err)
return -EFAULT;
+ } else {
+ mutex_unlock(&dst_dev->pdev_mutex);
}
return 0;
@@ -1161,7 +2212,6 @@ static int get_vf_service_state_param(struct pci_dev *pdev, struct hinic3_pcidev
return 0;
}
-#define BUS_MAX_DEV_NUM 256
static int hinic3_dst_pdev_valid(struct hinic3_pcidev *dst_dev, struct pci_dev **des_pdev_ptr,
u16 vf_devfn, bool en)
{
@@ -1243,7 +2293,6 @@ int hinic3_set_vf_service_state(struct pci_dev *pdev, u16 vf_func_id, u16 servic
if (en)
pci_dev_put(des_pdev);
- mutex_lock(&dst_dev->pdev_mutex);
find_dst_dev = true;
break;
}
@@ -1263,19 +2312,30 @@ free_pf_info:
}
EXPORT_SYMBOL(hinic3_set_vf_service_state);
-/*lint -save -e133 -e10*/
static const struct pci_device_id hinic3_pci_table[] = {
+#if defined(CONFIG_SP_VID_DID)
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_STANDARD), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_SDI_5_1_PF), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_SDI_5_0_PF), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_SPN120), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_ID_VF), 0},
+ {PCI_VDEVICE(SPNIC, HINIC3_DEV_SDI_5_1_ID_VF), 0},
+#elif defined(CONFIG_NF_VID_DID)
+ {PCI_VDEVICE(NF, NFNIC_DEV_ID_STANDARD), 0},
+ {PCI_VDEVICE(NF, NFNIC_DEV_ID_VF), 0},
+#else
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SPU), 0},
{PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_STANDARD), 0},
- {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_DPU_PF), 0},
- {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SDI_5_0_PF), 0},
{PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SDI_5_1_PF), 0},
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_SDI_5_0_PF), 0},
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_DPU_PF), 0},
+ {PCI_VDEVICE(HUAWEI, HINIC3_DEV_SDI_5_1_ID_VF), 0},
{PCI_VDEVICE(HUAWEI, HINIC3_DEV_ID_VF), 0},
+#endif
{0, 0}
};
-/*lint -restore*/
-
MODULE_DEVICE_TABLE(pci, hinic3_pci_table);
/**
@@ -1307,14 +2367,27 @@ static pci_ers_result_t hinic3_io_error_detected(struct pci_dev *pdev,
return PCI_ERS_RESULT_CAN_RECOVER;
}
+static void hinic3_timer_disable(void *hwdev)
+{
+ if (!hwdev)
+ return;
+
+ if (hinic3_get_stateful_enable(hwdev) && hinic3_get_timer_enable(hwdev))
+ (void)hinic3_func_tmr_bitmap_set(hwdev,
+ hinic3_global_func_id(hwdev),
+ false);
+}
+
static void hinic3_shutdown(struct pci_dev *pdev)
{
struct hinic3_pcidev *pci_adapter = pci_get_drvdata(pdev);
sdk_info(&pdev->dev, "Shutdown device\n");
- if (pci_adapter)
+ if (pci_adapter) {
+ hinic3_timer_disable(pci_adapter->hwdev);
hinic3_shutdown_hwdev(pci_adapter->hwdev);
+ }
pci_disable_device(pdev);
@@ -1341,6 +2414,9 @@ static struct pci_driver hinic3_driver = {
.probe = hinic3_probe,
.remove = hinic3_remove,
.shutdown = hinic3_shutdown,
+#ifdef CONFIG_PARTITION_DEVICE
+ .driver.probe_concurrency = true,
+#endif
#if defined(HAVE_SRIOV_CONFIGURE)
.sriov_configure = hinic3_pci_sriov_configure,
#elif defined(HAVE_RHEL6_SRIOV_CONFIGURE)
@@ -1362,16 +2438,21 @@ int hinic3_lld_init(void)
err = hinic3_module_pre_init();
if (err) {
pr_err("Init custom failed\n");
- return err;
+ goto module_pre_init_err;
}
err = pci_register_driver(&hinic3_driver);
if (err) {
- hinic3_module_post_exit();
- return err;
+ pr_err("sdk3 pci register driver failed\n");
+ goto register_pci_driver_err;
}
return 0;
+
+register_pci_driver_err:
+ hinic3_module_post_exit();
+module_pre_init_err:
+ return err;
}
void hinic3_lld_exit(void)
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c
index b2851c6..3626262 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mbox.c
@@ -584,6 +584,7 @@ static void free_recv_mbox(struct hinic3_recv_mbox *recv_msg)
kfree(recv_msg->resp_buff);
kfree(recv_msg->msg);
kfree(recv_msg);
+ recv_msg = NULL;
}
static void recv_func_mbox_work_handler(struct work_struct *work)
@@ -1232,6 +1233,7 @@ int hinic3_mbox_to_func(struct hinic3_mbox *func_to_func, u8 mod, u16 cmd,
set_mbox_to_func_event(func_to_func, EVENT_FAIL);
goto send_err;
}
+ func_to_func->hwdev->mbox_send_cnt++;
if (wait_mbox_msg_completion(func_to_func, timeout) != 0) {
sdk_err(func_to_func->hwdev->dev_hdl,
@@ -1240,6 +1242,7 @@ int hinic3_mbox_to_func(struct hinic3_mbox *func_to_func, u8 mod, u16 cmd,
err = -ETIMEDOUT;
goto send_err;
}
+ func_to_func->hwdev->mbox_ack_cnt++;
if (mod != msg_desc->mod || cmd != msg_desc->cmd) {
sdk_err(func_to_func->hwdev->dev_hdl,
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c
index 2bd63f1..4718458 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_mgmt.c
@@ -861,6 +861,7 @@ static int alloc_recv_msg(struct hinic3_recv_msg *recv_msg)
static void free_recv_msg(struct hinic3_recv_msg *recv_msg)
{
kfree(recv_msg->msg);
+ recv_msg->msg = NULL;
}
/**
@@ -932,6 +933,9 @@ static void free_msg_buf(struct hinic3_msg_pf_to_mgmt *pf_to_mgmt)
free_recv_msg(&pf_to_mgmt->recv_resp_msg_from_mgmt);
free_recv_msg(&pf_to_mgmt->recv_msg_from_mgmt);
+ pf_to_mgmt->mgmt_ack_buf = NULL;
+ pf_to_mgmt->sync_msg_buf = NULL;
+ pf_to_mgmt->async_msg_buf = NULL;
}
/**
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c
index 3548410..a0f5e73 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_multi_host_mgmt.c
@@ -676,6 +676,9 @@ static int hinic3_register_slave_ppf(struct hinic3_hwdev *hwdev, bool registered
if (!IS_SLAVE_HOST(hwdev))
return -EINVAL;
+ if (UNSUPPORT_HOT_PLUG((struct hinic3_hwdev *)hwdev))
+ return 0;
+
host_info = kcalloc(1, sizeof(struct register_slave_host), GFP_KERNEL);
if (!host_info)
return -ENOMEM;
@@ -1075,7 +1078,8 @@ int hinic3_get_func_nic_enable(void *hwdev, u16 glb_func_idx, bool *en)
return -EINVAL;
/* if single host, return true. */
- if (!IS_MULTI_HOST((struct hinic3_hwdev *)hwdev)) {
+ if (!IS_MULTI_HOST((struct hinic3_hwdev *)hwdev) ||
+ UNSUPPORT_HOT_PLUG((struct hinic3_hwdev *)hwdev)) {
*en = true;
return 0;
}
@@ -1145,11 +1149,21 @@ int hinic3_multi_host_mgmt_init(struct hinic3_hwdev *hwdev)
{
int err;
struct service_cap *cap = &hwdev->cfg_mgmt->svc_cap;
+ int is_use_vram, is_in_kexec;
if (!IS_MULTI_HOST(hwdev) || !HINIC3_IS_PPF(hwdev))
return 0;
- hwdev->mhost_mgmt = kcalloc(1, sizeof(*hwdev->mhost_mgmt), GFP_KERNEL);
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram != 0) {
+ snprintf(hwdev->mhost_mgmt_name, VRAM_NAME_MAX_LEN, "%s",
+ VRAM_NIC_MHOST_MGMT);
+ hwdev->mhost_mgmt = hi_vram_kalloc(hwdev->mhost_mgmt_name,
+ sizeof(*hwdev->mhost_mgmt));
+ } else {
+ hwdev->mhost_mgmt = kcalloc(1, sizeof(*hwdev->mhost_mgmt), GFP_KERNEL);
+ }
+
if (!hwdev->mhost_mgmt)
return -ENOMEM;
@@ -1165,8 +1179,11 @@ int hinic3_multi_host_mgmt_init(struct hinic3_hwdev *hwdev)
hinic3_register_ppf_mbox_cb(hwdev, HINIC3_MOD_HILINK, hwdev, hilink_ppf_mbox_handler);
hinic3_register_ppf_mbox_cb(hwdev, HINIC3_MOD_SW_FUNC, hwdev, sw_func_ppf_mbox_handler);
- bitmap_zero(hwdev->mhost_mgmt->func_nic_en, HINIC3_MAX_MGMT_FUNCTIONS);
- bitmap_zero(hwdev->mhost_mgmt->func_vroce_en, HINIC3_MAX_MGMT_FUNCTIONS);
+ is_in_kexec = vram_get_kexec_flag();
+ if (is_in_kexec == 0) {
+ bitmap_zero(hwdev->mhost_mgmt->func_nic_en, HINIC3_MAX_MGMT_FUNCTIONS);
+ bitmap_zero(hwdev->mhost_mgmt->func_vroce_en, HINIC3_MAX_MGMT_FUNCTIONS);
+ }
/* Slave host:
* register slave host ppf functions
@@ -1179,7 +1196,11 @@ int hinic3_multi_host_mgmt_init(struct hinic3_hwdev *hwdev)
return 0;
out_free_mhost_mgmt:
- kfree(hwdev->mhost_mgmt);
+ if (is_use_vram != 0)
+ hi_vram_kfree((void *)hwdev->mhost_mgmt, hwdev->mhost_mgmt_name,
+ sizeof(*hwdev->mhost_mgmt));
+ else
+ kfree(hwdev->mhost_mgmt);
hwdev->mhost_mgmt = NULL;
return err;
@@ -1187,6 +1208,8 @@ out_free_mhost_mgmt:
int hinic3_multi_host_mgmt_free(struct hinic3_hwdev *hwdev)
{
+ int is_use_vram;
+
if (!IS_MULTI_HOST(hwdev) || !HINIC3_IS_PPF(hwdev))
return 0;
@@ -1203,7 +1226,13 @@ int hinic3_multi_host_mgmt_free(struct hinic3_hwdev *hwdev)
hinic3_unregister_ppf_mbox_cb(hwdev, HINIC3_MOD_HILINK);
hinic3_unregister_ppf_mbox_cb(hwdev, HINIC3_MOD_SW_FUNC);
- kfree(hwdev->mhost_mgmt);
+ is_use_vram = get_use_vram_flag();
+ if (is_use_vram != 0)
+ hi_vram_kfree((void *)hwdev->mhost_mgmt, hwdev->mhost_mgmt_name,
+ sizeof(*hwdev->mhost_mgmt));
+ else
+ kfree(hwdev->mhost_mgmt);
+
hwdev->mhost_mgmt = NULL;
return 0;
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c
index 5e4804a..5a5ea53 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.c
@@ -17,14 +17,13 @@
#include "hinic3_hwdev.h"
#include "hinic3_lld.h"
#include "hinic3_hw_mt.h"
+#include "hinic3_dev_mgmt.h"
#include "hinic3_nictool.h"
static int g_nictool_ref_cnt;
static dev_t g_dev_id = {0};
-/*lint -save -e104 -e808*/
static struct class *g_nictool_class;
-/*lint -restore*/
static struct cdev g_nictool_cdev;
#define HINIC3_MAX_BUF_SIZE (2048 * 1024)
@@ -92,6 +91,23 @@ static int get_all_chip_id_cmd(struct hinic3_lld_dev *lld_dev, const void *buf_i
return 0;
}
+#ifndef __HIFC__
+static int get_os_hot_replace_info(struct hinic3_lld_dev *lld_dev,
+ const void *buf_in, u32 in_size,
+ void *buf_out, u32 *out_size)
+{
+ if (*out_size != sizeof(struct os_hot_replace_info) || !buf_out) {
+ pr_err("Invalid parameter: out_buf_size %u, expect %lu\n",
+ *out_size, sizeof(struct os_hot_replace_info));
+ return -EFAULT;
+ }
+
+ hinic3_get_os_hot_replace_info(buf_out);
+
+ return 0;
+}
+#endif
+
static int get_card_usr_api_chain_mem(int card_idx)
{
unsigned char *tmp = NULL;
@@ -166,7 +182,7 @@ static int get_pf_dev_info(struct hinic3_lld_dev *lld_dev, const void *buf_in, u
if (!buf_out || *out_size != sizeof(struct pf_dev_info) * PF_DEV_INFO_NUM) {
pr_err("Invalid parameter: out_buf_size %u, expect %lu\n",
- *out_size, sizeof(dev_info) * PF_DEV_INFO_NUM);
+ *out_size, sizeof(*dev_info) * PF_DEV_INFO_NUM);
return -EFAULT;
}
@@ -193,13 +209,18 @@ static int get_pf_dev_info(struct hinic3_lld_dev *lld_dev, const void *buf_in, u
return 0;
}
-static long dbgtool_knl_free_mem(int id)
+static void dbgtool_knl_free_mem(int id)
{
unsigned char *tmp = NULL;
int i;
+ if (id < 0 || id >= MAX_CARD_NUM) {
+ pr_err("Invalid card id\n");
+ return;
+ }
+
if (!g_card_vir_addr[id])
- return 0;
+ return;
tmp = g_card_vir_addr[id];
for (i = 0; i < (1 << DBGTOOL_PAGE_ORDER); i++) {
@@ -211,7 +232,6 @@ static long dbgtool_knl_free_mem(int id)
g_card_vir_addr[id] = NULL;
g_card_phy_addr[id] = 0;
- return 0;
}
static int free_knl_mem(struct hinic3_lld_dev *lld_dev, const void *buf_in, u32 in_size,
@@ -337,7 +357,6 @@ static int get_hw_drv_version(struct hinic3_lld_dev *lld_dev, const void *buf_in
void *buf_out, u32 *out_size)
{
struct drv_version_info *ver_info = buf_out;
- int err;
if (!buf_out) {
pr_err("Buf_out is NULL.\n");
@@ -350,10 +369,8 @@ static int get_hw_drv_version(struct hinic3_lld_dev *lld_dev, const void *buf_in
return -EINVAL;
}
- err = snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s", HINIC3_DRV_VERSION,
- "2023-05-17_19:56:38");
- if (err < 0)
- return -EINVAL;
+ snprintf(ver_info->ver, sizeof(ver_info->ver), "%s %s", HINIC3_DRV_VERSION,
+ "2025-05-08_00:00:08");
return 0;
}
@@ -386,6 +403,22 @@ static int get_pf_id(struct hinic3_lld_dev *lld_dev, const void *buf_in, u32 in_
return 0;
}
+#ifndef __HIFC__
+/* not support fc yet */
+static int get_mbox_cnt(struct hinic3_lld_dev *lld_dev, const void *buf_in,
+ u32 in_size, void *buf_out, u32 *out_size)
+{
+ if (!buf_out || *out_size != sizeof(struct card_mbox_cnt_info)) {
+ pr_err("buf_out is NULL, or out_size != %lu\n", sizeof(struct card_info));
+ return -EINVAL;
+ }
+
+ hinic3_get_mbox_cnt(hinic3_get_sdk_hwdev_by_lld(lld_dev), buf_out);
+
+ return 0;
+}
+#endif
+
struct hw_drv_module_handle hw_driv_module_cmd_handle[] = {
{FUNC_TYPE, get_func_type},
{GET_FUNC_IDX, get_func_id},
@@ -402,6 +435,10 @@ struct hw_drv_module_handle hw_driv_module_cmd_handle[] = {
{GET_FUNC_CAP, get_pf_cap_info},
{GET_DRV_VERSION, get_hw_drv_version},
{GET_PF_ID, get_pf_id},
+#ifndef __HIFC__
+ {GET_OS_HOT_REPLACE_INFO, get_os_hot_replace_info},
+ {GET_MBOX_CNT, (hw_driv_module)get_mbox_cnt},
+#endif
};
static int alloc_tmp_buf(void *hwdev, struct msg_module *nt_msg, u32 in_size,
@@ -439,8 +476,8 @@ static void free_tmp_buf(void *hwdev, struct msg_module *nt_msg,
static int send_to_hw_driver(struct hinic3_lld_dev *lld_dev, struct msg_module *nt_msg,
const void *buf_in, u32 in_size, void *buf_out, u32 *out_size)
{
- int index, num_cmds = sizeof(hw_driv_module_cmd_handle) /
- sizeof(hw_driv_module_cmd_handle[0]);
+ int index, num_cmds = (int)(sizeof(hw_driv_module_cmd_handle) /
+ sizeof(hw_driv_module_cmd_handle[0]));
enum driver_cmd_type cmd_type =
(enum driver_cmd_type)(nt_msg->msg_formate);
int err = 0;
@@ -482,8 +519,8 @@ static int send_to_service_driver(struct hinic3_lld_dev *lld_dev, struct msg_mod
if (nt_msg->msg_formate == GET_DRV_VERSION)
return 0;
- pr_err("Can not get the uld dev correctly: %s, %s driver may be not register\n",
- nt_msg->device_name, service_name[type]);
+ pr_err("Can not get the uld dev correctly: %s driver may be not register\n",
+ service_name[type]);
return -EINVAL;
}
@@ -597,8 +634,10 @@ static long hinicadm_k_unlocked_ioctl(struct file *pfile, unsigned long arg)
return -ENODEV;
}
- if (nt_msg.msg_formate == DEV_NAME_TEST)
+ if (nt_msg.msg_formate == DEV_NAME_TEST) {
+ lld_dev_put(lld_dev);
return 0;
+ }
ret = alloc_tmp_buf(hinic3_get_sdk_hwdev_by_lld(lld_dev), &nt_msg,
in_size, &buf_in, out_size_expect, &buf_out);
@@ -642,6 +681,9 @@ out_free_lock:
static long dbgtool_knl_ffm_info_rd(struct dbgtool_param *para,
struct dbgtool_k_glb_info *dbgtool_info)
{
+ if (!para->param.ffm_rd || !dbgtool_info->ffm)
+ return -EINVAL;
+
/* Copy the ffm_info to user mode */
if (copy_to_user(para->param.ffm_rd, dbgtool_info->ffm,
(unsigned int)sizeof(struct ffm_record_info))) {
@@ -674,13 +716,14 @@ static long dbgtool_k_unlocked_ioctl(struct file *pfile,
card_info = (struct card_node *)g_card_node_array[i];
if (!card_info)
continue;
- if (!strncmp(param.chip_name, card_info->chip_name, IFNAMSIZ))
+ if (memcmp(param.chip_name, card_info->chip_name,
+ strlen(card_info->chip_name) + 1) == 0)
break;
}
if (i == MAX_CARD_NUM || !card_info) {
lld_put();
- pr_err("Can't find this card %s\n", param.chip_name);
+ pr_err("Can't find this card.\n");
return -EFAULT;
}
@@ -697,10 +740,10 @@ static long dbgtool_k_unlocked_ioctl(struct file *pfile,
pr_err("Not suppose to use this cmd(0x%x).\n", real_cmd);
ret = 0;
break;
-
default:
pr_err("Dbgtool cmd(0x%x) not support now\n", real_cmd);
ret = -EFAULT;
+ break;
}
up(&dbgtool_info->dbgtool_sem);
@@ -746,9 +789,11 @@ static long nictool_k_unlocked_ioctl(struct file *pfile,
static int hinic3_mem_mmap(struct file *filp, struct vm_area_struct *vma)
{
+ pgprot_t vm_page_prot;
unsigned long vmsize = vma->vm_end - vma->vm_start;
phys_addr_t offset = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
phys_addr_t phy_addr;
+ int err = 0;
if (vmsize > (PAGE_SIZE * (1 << DBGTOOL_PAGE_ORDER))) {
pr_err("Map size = %lu is bigger than alloc\n", vmsize);
@@ -758,13 +803,18 @@ static int hinic3_mem_mmap(struct file *filp, struct vm_area_struct *vma)
/* old version of tool set vma->vm_pgoff to 0 */
phy_addr = offset ? offset : g_card_phy_addr[card_id];
- if (!phy_addr) {
- pr_err("Card_id = %d physical address is 0\n", card_id);
- return -EAGAIN;
+ /* check phy_addr valid */
+ if (phy_addr != g_card_phy_addr[card_id]) {
+ err = hinic3_bar_mmap_param_valid(phy_addr, vmsize);
+ if (err != 0) {
+ pr_err("mmap param invalid, err: %d\n", err);
+ return err;
+ }
}
/* Disable cache and write buffer in the mapping area */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ vma->vm_page_prot = vm_page_prot;
if (remap_pfn_range(vma, vma->vm_start, (phy_addr >> PAGE_SHIFT),
vmsize, vma->vm_page_prot)) {
pr_err("Remap pfn range failed.\n");
@@ -787,7 +837,6 @@ static const struct file_operations fifo_operations = {
static void free_dbgtool_info(void *hwdev, struct card_node *chip_info)
{
struct dbgtool_k_glb_info *dbgtool_info = NULL;
- int err, id;
if (hinic3_func_type(hwdev) != TYPE_VF)
chip_info->func_handle_array[hinic3_global_func_id(hwdev)] = NULL;
@@ -795,23 +844,22 @@ static void free_dbgtool_info(void *hwdev, struct card_node *chip_info)
if (--chip_info->func_num)
return;
- err = sscanf(chip_info->chip_name, HINIC3_CHIP_NAME "%d", &id);
- if (err < 0)
- pr_err("Failed to get card id\n");
-
- if (id < MAX_CARD_NUM)
- g_card_node_array[id] = NULL;
+ if (chip_info->chip_id >= 0 && chip_info->chip_id < MAX_CARD_NUM)
+ g_card_node_array[chip_info->chip_id] = NULL;
dbgtool_info = chip_info->dbgtool_info;
/* FFM deinit */
- kfree(dbgtool_info->ffm);
- dbgtool_info->ffm = NULL;
+ if (dbgtool_info && dbgtool_info->ffm) {
+ kfree(dbgtool_info->ffm);
+ dbgtool_info->ffm = NULL;
+ }
kfree(dbgtool_info);
+
chip_info->dbgtool_info = NULL;
- if (id < MAX_CARD_NUM)
- (void)dbgtool_knl_free_mem(id);
+ if (chip_info->chip_id >= 0 && chip_info->chip_id < MAX_CARD_NUM)
+ dbgtool_knl_free_mem(chip_info->chip_id);
}
static int alloc_dbgtool_info(void *hwdev, struct card_node *chip_info)
@@ -872,7 +920,7 @@ dbgtool_info_fail:
* nictool_k_init - initialize the hw interface
**/
/* temp for dbgtool_info */
-/*lint -e438*/
+
int nictool_k_init(void *hwdev, void *chip_node)
{
struct card_node *chip_info = (struct card_node *)chip_node;
@@ -895,9 +943,7 @@ int nictool_k_init(void *hwdev, void *chip_node)
}
/* Create equipment */
- /*lint -save -e160*/
g_nictool_class = class_create(HIADM3_DEV_CLASS);
- /*lint -restore*/
if (IS_ERR(g_nictool_class)) {
pr_err("Create nictool_class fail\n");
err = -EFAULT;
@@ -944,7 +990,7 @@ alloc_chdev_fail:
free_dbgtool_info(hwdev, chip_info);
return err;
-} /*lint +e438*/
+}
void nictool_k_uninit(void *hwdev, void *chip_node)
{
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h
index f368133..c943dfc 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_nictool.h
@@ -18,6 +18,8 @@
int nictool_k_init(void *hwdev, void *chip_node);
void nictool_k_uninit(void *hwdev, void *chip_node);
+void hinic3_get_os_hot_replace_info(void *oshr_info);
+
void hinic3_get_all_chip_id(void *id_info);
void hinic3_get_card_func_info_by_card_name
@@ -29,6 +31,8 @@ bool hinic3_is_in_host(void);
int hinic3_get_pf_id(struct card_node *chip_node, u32 port_id, u32 *pf_id, u32 *isvalid);
+void hinic3_get_mbox_cnt(const void *hwdev, void *bufin);
+
extern struct hinic3_uld_info g_uld_info[SERVICE_T_MAX];
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h
index 2d5423e..e961ef7 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_pci_id_tbl.h
@@ -19,6 +19,20 @@
#define HINIC3_DEV_ID_SPU 0xAC00
#define HINIC3_DEV_SDI_5_1_SSDID_VF 0x1000
#define HINIC3_DEV_SDI_V100_SSDID_MASK (3 << 12)
+#elif defined(CONFIG_NF_VID_DID)
+#define PCI_VENDOR_ID_NF 0x2036
+#define NFNIC_DEV_ID_STANDARD 0x1618
+#define NFNIC_DEV_ID_SDI_5_1_PF 0x0226
+#define NFNIC_DEV_ID_SDI_5_0_PF 0x0225
+#define NFNIC_DEV_ID_DPU_PF 0x0224
+#define NFNIC_DEV_ID_VF 0x1619
+#define NFNIC_DEV_ID_VF_HV 0x379F
+#define NFNIC_DEV_SDI_5_1_ID_VF 0x375F
+#define NFNIC_DEV_SDI_5_0_ID_VF 0x375F
+#define NFNIC_DEV_SDI_5_1_ID_VF_HV 0x379F
+#define NFNIC_DEV_ID_SPU 0xAC00
+#define NFNIC_DEV_SDI_5_1_SSDID_VF 0x1000
+#define NFNIC_DEV_SDI_V100_SSDID_MASK (3 << 12)
#else
#define PCI_VENDOR_ID_HUAWEI 0x19e5
#define HINIC3_DEV_ID_STANDARD 0x0222
@@ -28,16 +42,33 @@
#define HINIC3_DEV_ID_VF 0x375F
#define HINIC3_DEV_ID_VF_HV 0x379F
#define HINIC3_DEV_SDI_5_1_ID_VF 0x375F
+#define HINIC3_DEV_SDI_5_0_ID_VF 0x375F
#define HINIC3_DEV_SDI_5_1_ID_VF_HV 0x379F
#define HINIC3_DEV_ID_SPU 0xAC00
#define HINIC3_DEV_SDI_5_1_SSDID_VF 0x1000
#define HINIC3_DEV_SDI_V100_SSDID_MASK (3 << 12)
#endif
+#define NFNIC_DEV_SSID_2X25G_NF 0x0860
+#define NFNIC_DEV_SSID_4X25G_NF 0x0861
+#define NFNIC_DEV_SSID_2x100G_NF 0x0862
+#define NFNIC_DEV_SSID_2x200G_NF 0x0863
+
+#define HINIC3_DEV_SSID_2X10G 0x0035
#define HINIC3_DEV_SSID_2X25G 0x0051
#define HINIC3_DEV_SSID_4X25G 0x0052
+#define HINIC3_DEV_SSID_4X25G_BD 0x0252
+#define HINIC3_DEV_SSID_4X25G_SMARTNIC 0x0152
+#define HINIC3_DEV_SSID_6X25G_VL 0x0356
#define HINIC3_DEV_SSID_2X100G 0x00A1
+#define HINIC3_DEV_SSID_2X100G_SMARTNIC 0x01A1
+#define HINIC3_DEV_SSID_2X200G 0x04B1
#define HINIC3_DEV_SSID_2X100G_VF 0x1000
+#define HINIC3_DEV_SSID_HPC_4_HOST_NIC 0x005A
+#define HINIC3_DEV_SSID_2X200G_VL 0x00B1
+#define HINIC3_DEV_SSID_1X100G 0x02A4
+
+#define BIFUR_RESOURCE_PF_SSID 0x05a1
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c
index b23b69f..461272e 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.c
@@ -52,26 +52,25 @@ static int hinic3_deinit_vf_hw(void *hwdev, u16 start_vf_id, u16 end_vf_id)
}
#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
-ssize_t hinic3_sriov_totalvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ssize_t sriov_totalvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%d\n", pci_sriov_get_totalvfs(pdev));
}
-ssize_t hinic3_sriov_numvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+ssize_t sriov_numvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct pci_dev *pdev = to_pci_dev(dev);
return sprintf(buf, "%d\n", pci_num_vf(pdev));
}
-/*lint -save -e713*/
-ssize_t hinic3_sriov_numvfs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
+ssize_t sriov_numvfs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct pci_dev *pdev = to_pci_dev(dev);
int ret;
@@ -116,7 +115,6 @@ ssize_t hinic3_sriov_numvfs_store(struct device *dev,
return count;
}
-/*lint -restore*/
#endif /* !(HAVE_SRIOV_CONFIGURE || HAVE_RHEL6_SRIOV_CONFIGURE) */
int hinic3_pci_sriov_disable(struct pci_dev *dev)
@@ -174,24 +172,15 @@ int hinic3_pci_sriov_disable(struct pci_dev *dev)
return 0;
}
-int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
-{
#ifdef CONFIG_PCI_IOV
- struct hinic3_sriov_info *sriov_info = NULL;
- struct hinic3_event_info event = {0};
- void *hwdev = NULL;
- int pre_existing_vfs = 0;
- int err = 0;
-
- sriov_info = hinic3_get_sriov_info_by_pcidev(dev);
- hwdev = hinic3_get_hwdev_by_pcidev(dev);
- if (!hwdev) {
- sdk_err(&dev->dev, "SR-IOV enable is not permitted, please wait...\n");
- return -EPERM;
- }
+int hinic3_pci_sriov_check(struct hinic3_sriov_info *sriov_info, struct pci_dev *dev, int num_vfs)
+{
+ int pre_existing_vfs;
+ int err;
if (test_and_set_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state)) {
- sdk_err(&dev->dev, "SR-IOV enable in process, please wait, num_vfs %d\n",
+ sdk_err(&dev->dev,
+ "SR-IOV enable in process, please wait, num_vfs %d\n",
num_vfs);
return -EPERM;
}
@@ -202,6 +191,7 @@ int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
clear_bit(HINIC3_SRIOV_ENABLE, &sriov_info->state);
return -ERANGE;
}
+
if (pre_existing_vfs && pre_existing_vfs != num_vfs) {
err = hinic3_pci_sriov_disable(dev);
if (err) {
@@ -213,6 +203,29 @@ int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
return num_vfs;
}
+ return 0;
+}
+#endif
+
+int hinic3_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
+{
+#ifdef CONFIG_PCI_IOV
+ struct hinic3_sriov_info *sriov_info = NULL;
+ struct hinic3_event_info event = {0};
+ void *hwdev = NULL;
+ int err = 0;
+
+ sriov_info = hinic3_get_sriov_info_by_pcidev(dev);
+ hwdev = hinic3_get_hwdev_by_pcidev(dev);
+ if (!hwdev) {
+ sdk_err(&dev->dev, "SR-IOV enable is not permitted, please wait...\n");
+ return -EPERM;
+ }
+
+ err = hinic3_pci_sriov_check(sriov_info, dev, num_vfs);
+ if (err != 0)
+ return err;
+
err = hinic3_init_vf_hw(hwdev, 1, (u16)num_vfs);
if (err) {
sdk_err(&dev->dev, "Failed to init vf in hardware before enable sriov, error %d\n",
@@ -262,6 +275,3 @@ int hinic3_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
else
return hinic3_pci_sriov_enable(dev, num_vfs);
}
-
-/*lint -restore*/
-
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h
index 4a640ad..becb5c7 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h
+++ b/drivers/net/ethernet/huawei/hinic3/hw/hinic3_sriov.h
@@ -7,13 +7,13 @@
#include <linux/pci.h>
#if !(defined(HAVE_SRIOV_CONFIGURE) || defined(HAVE_RHEL6_SRIOV_CONFIGURE))
-ssize_t hinic3_sriov_totalvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-ssize_t hinic3_sriov_numvfs_show(struct device *dev,
- struct device_attribute *attr, char *buf);
-ssize_t hinic3_sriov_numvfs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count);
+ssize_t sriov_totalvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ssize_t sriov_numvfs_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+ssize_t sriov_numvfs_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count);
#endif /* !(HAVE_SRIOV_CONFIGURE || HAVE_RHEL6_SRIOV_CONFIGURE) */
enum hinic3_sriov_state {
diff --git a/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c b/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c
index f8aea696..be83022 100644
--- a/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c
+++ b/drivers/net/ethernet/huawei/hinic3/hw/ossl_knl_linux.c
@@ -117,3 +117,4 @@ u64 ossl_get_real_time(void)
tv_msec = (u64)tv.tv_sec * MSEC_PER_SEC + (u64)tv.tv_usec / USEC_PER_MSEC;
return tv_msec;
}
+
diff --git a/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h b/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h
index 9e8fc75..01ab739 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/bond/bond_common_defs.h
@@ -10,6 +10,10 @@
#define OVS_PORT_NUM_MAX BOND_PORT_MAX_NUM
#define DEFAULT_ROCE_BOND_FUNC 0xFFFFFFFF
+#define BOND_ID_IS_VALID(_id) \
+ (((_id) >= BOND_FIRST_ID) && ((_id) <= BOND_MAX_ID))
+#define BOND_ID_IS_INVALID(_id) (!(BOND_ID_IS_VALID(_id)))
+
enum bond_group_id {
BOND_FIRST_ID = 1,
BOND_MAX_ID = 4,
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 e7e16fc..f9737ea 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
@@ -52,6 +52,8 @@ enum scenes_id_define {
SCENES_ID_STORAGE_ROCE = 6,
SCENES_ID_COMPUTE_ROCE = 7,
SCENES_ID_STORAGE_TOE = 8,
+ SCENES_ID_COMPUTE_DPU = 100,
+ SCENES_ID_COMPUTE_SMART_NIC = 101,
SCENES_ID_MAX
};
@@ -122,13 +124,18 @@ struct cfg_cmd_dev_cap {
u8 srv_multi_host_mode;
u8 virtio_vq_size;
- u32 rsvd_func3[5];
+ u8 hot_plug_disable;
+ u8 bond_create_mode;
+ u8 lro_enable;
+ u8 os_hot_replace;
+
+ u32 rsvd_func3[4];
/* l2nic */
u16 nic_max_sq_id;
u16 nic_max_rq_id;
u16 nic_default_num_queues;
- u16 rsvd1_nic;
+ u16 outband_vlan_cfg_en;
u32 rsvd2_nic[2];
/* RoCE */
diff --git a/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h b/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h
index d9f67e2..6c5b995 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/hinic3_common.h
@@ -37,7 +37,7 @@ static inline void hinic3_cpu_to_be32(void *data, int len)
{
int i, chunk_sz = sizeof(u32);
int data_len = len;
- u32 *mem = data;
+ u32 *mem = (u32 *)data;
if (!data)
return;
@@ -59,7 +59,7 @@ static inline void hinic3_be32_to_cpu(void *data, int len)
{
int i, chunk_sz = sizeof(u32);
int data_len = len;
- u32 *mem = data;
+ u32 *mem = (u32 *)data;
if (!data)
return;
@@ -86,52 +86,16 @@ static inline void hinic3_set_sge(struct hinic3_sge *sge, dma_addr_t addr,
sge->len = (u32)len;
}
-#ifdef HW_CONVERT_ENDIAN
#define hinic3_hw_be32(val) (val)
#define hinic3_hw_cpu32(val) (val)
#define hinic3_hw_cpu16(val) (val)
-#else
-#define hinic3_hw_be32(val) cpu_to_be32(val)
-#define hinic3_hw_cpu32(val) be32_to_cpu(val)
-#define hinic3_hw_cpu16(val) be16_to_cpu(val)
-#endif
static inline void hinic3_hw_be32_len(void *data, int len)
{
-#ifndef HW_CONVERT_ENDIAN
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = hinic3_hw_be32(*mem);
- mem++;
- }
-#endif
}
static inline void hinic3_hw_cpu32_len(void *data, int len)
{
-#ifndef HW_CONVERT_ENDIAN
- int i, chunk_sz = sizeof(u32);
- int data_len = len;
- u32 *mem = data;
-
- if (!data)
- return;
-
- data_len = data_len / chunk_sz;
-
- for (i = 0; i < data_len; i++) {
- *mem = hinic3_hw_cpu32(*mem);
- mem++;
- }
-#endif
}
int hinic3_dma_zalloc_coherent_align(void *dev_hdl, u64 size, u64 align,
@@ -149,6 +113,8 @@ int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler,
/* func_attr.glb_func_idx, global function index */
u16 hinic3_global_func_id(void *hwdev);
+int hinic3_global_func_id_get(void *hwdev, u16 *func_id);
+
/* func_attr.p2p_idx, belongs to which pf */
u8 hinic3_pf_id_of_vf(void *hwdev);
diff --git a/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h b/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h
index 9a9bfe2..e36ba1d 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/hinic3_lld.h
@@ -219,5 +219,7 @@ void hinic3_detach_nic(const struct hinic3_lld_dev *lld_dev);
int hinic3_attach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
void hinic3_detach_service(const struct hinic3_lld_dev *lld_dev, enum hinic3_service_type type);
const char **hinic3_get_uld_names(void);
+int hinic3_lld_init(void);
+void hinic3_lld_exit(void);
#endif
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h
index 97d34f0..4cd6f94 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mag_mpu_cmd.h
@@ -43,6 +43,10 @@ enum mag_cmd {
MAG_CMD_GET_XSFP_PRESENT = 62, /* get xsfp present status @see mag_cmd_get_xsfp_present */
MAG_CMD_SET_XSFP_RW = 63, /* sfp/qsfp single byte read/write, @see mag_cmd_set_xsfp_rw */
MAG_CMD_CFG_XSFP_TEMPERATURE = 64, /* get xsfp temp @see mag_cmd_sfp_temp_out_info */
+ /**< set xsfp tlv info @see struct mag_cmd_set_xsfp_tlv_req */
+ MAG_CMD_SET_XSFP_TLV_INFO = 65,
+ /**< get xsfp tlv info @see struct drv_tag_mag_cmd_get_xsfp_tlv_rsp */
+ MAG_CMD_GET_XSFP_TLV_INFO = 66,
/* Event reported 100-149 */
MAG_CMD_WIRE_EVENT = 100,
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h
index caaba5d..d33b9f4 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_board_defs.h
@@ -31,17 +31,28 @@ enum board_type_define_e {
BOARD_TYPE_STRG_2X100G_ROCE_AA = 42, /* 2X100G SmartIO ROCE_AA Card */
BOARD_TYPE_CAL_2X25G_NIC_75MPPS = 100, /* 2X25G ETH Standard card 75MPPS */
BOARD_TYPE_CAL_2X25G_NIC_40MPPS = 101, /* 2X25G ETH Standard card 40MPPS */
- BOARD_TYPE_CAL_2X100G_DPU = 102, /* 2x100G DPU Card */
+ BOARD_TYPE_CAL_2X100G_DPU_VL = 102, /* 2x100G DPU Card */
BOARD_TYPE_CAL_4X25G_NIC_120MPPS = 105, /* 4X25G ETH Standard card 120MPPS */
BOARD_TYPE_CAL_4X25G_COMSTORAGE = 106, /* 4X25GE compute storage Onboard Card */
BOARD_TYPE_CAL_2X32G_FC_HBA = 110, /* 2X32G FC HBA card */
BOARD_TYPE_CAL_2X16G_FC_HBA = 111, /* 2X16G FC HBA card */
BOARD_TYPE_CAL_2X100G_NIC_120MPPS = 115, /* 2X100G ETH Standard card 120MPPS */
- BOARD_TYPE_CAL_2X25G_DPU = 116, /* 2x25G DPU Card */
- BOARD_TYPE_CAL_4X25G_DPU = 118, /* 4x25G DPU Card */
+ BOARD_TYPE_CAL_2X25G_DPU_BD = 116, /* 2x25G DPU Card */
+ BOARD_TYPE_CAL_2X100G_TCE_BACKPLANE = 117,
+ BOARD_TYPE_CAL_4X25G_DPU_VL = 118, /* 4x25G DPU Card */
+ BOARD_TYPE_CAL_4X25G_SMARTNIC_120MPPS = 119,
+ BOARD_TYPE_CAL_2X100G_SMARTNIC_120MPPS = 120,
+ BOARD_TYPE_CAL_6X25G_DPU_VL = 121, /* 6x25G DPU Card */
+ BOARD_TYPE_CAL_4X25G_DPU_BD = 122,
+ BOARD_TYPE_CAL_2X25G_NIC_4HOST = 123,
+ BOARD_TYPE_CAL_2X10G_LOW_POWER = 125,
+ BOARD_TYPE_CAL_2X200G_NIC_INTERNET = 127,
+ BOARD_TYPE_CAL_1X100GR2_OCP = 129, /* 1X100G ETH Standard card */
+ BOARD_TYPE_CAL_2X200G_DPU_VL = 130,
BOARD_TYPE_CLD_2X100G_SDI5_1 = 170, /* 2X100G SDI 5.1 Card */
BOARD_TYPE_CLD_2X25G_SDI5_0_LITE = 171, /* 2x25G SDI5.0 Lite Card */
BOARD_TYPE_CLD_2X100G_SDI5_0 = 172, /* 2x100G SDI5.0 Card */
+ BOARD_TYPE_CLD_4X25G_SDI5_0_C = 175,
BOARD_TYPE_MAX_INDEX = 0xFF
};
@@ -49,23 +60,62 @@ static inline u32 spu_board_type_valid(u32 board_type)
{
return ((board_type) == BOARD_TYPE_CLD_2X25G_SDI5_0_LITE) ||
((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_0) ||
- ((board_type) == BOARD_TYPE_CAL_2X25G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_2X100G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_4X25G_DPU);
+ ((board_type) == BOARD_TYPE_CLD_4X25G_SDI5_0_C) ||
+ ((board_type) == BOARD_TYPE_CAL_2X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_DPU_VL);
}
static inline int board_type_is_sdi(u32 board_type)
{
return ((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_1) ||
((board_type) == BOARD_TYPE_CLD_2X25G_SDI5_0_LITE) ||
- ((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_0);
+ ((board_type) == BOARD_TYPE_CLD_2X100G_SDI5_0) ||
+ ((board_type) == BOARD_TYPE_CLD_4X25G_SDI5_0_C);
+}
+
+static inline int board_type_is_dpu_spu(u32 board_type)
+{
+ return ((board_type) == BOARD_TYPE_CAL_2X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_DPU_VL);
}
static inline int board_type_is_dpu(u32 board_type)
{
- return ((board_type) == BOARD_TYPE_CAL_2X25G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_2X100G_DPU) ||
- ((board_type) == BOARD_TYPE_CAL_4X25G_DPU);
+ return ((board_type) == BOARD_TYPE_CAL_2X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_DPU_BD) ||
+ ((board_type) == BOARD_TYPE_CAL_6X25G_DPU_VL) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_DPU_VL);
+}
+
+/* 此接口判断是否是分布式存储的标卡以及计算的标卡(含ROCE特性),
+ * 仅用于LLDP TX功能冲突命令字处理的判断
+ */
+static inline int board_type_is_compute(u32 board_type)
+{
+ return ((board_type) == BOARD_TYPE_CAL_2X25G_NIC_75MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_2X25G_NIC_40MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_NIC_120MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_COMSTORAGE) ||
+ ((board_type) == BOARD_TYPE_CAL_2X10G_LOW_POWER) ||
+ ((board_type) == BOARD_TYPE_CAL_2X200G_NIC_INTERNET) ||
+ ((board_type) == BOARD_TYPE_CAL_1X100GR2_OCP) ||
+ ((board_type) == BOARD_TYPE_CAL_2X25G_NIC_4HOST) ||
+ ((board_type) == BOARD_TYPE_CAL_4X25G_SMARTNIC_120MPPS) ||
+ ((board_type) == BOARD_TYPE_CAL_2X100G_NIC_120MPPS);
+}
+
+/* 此接口判断服务器输入reboot网卡是否需要复位 */
+static inline int board_type_is_multi_socket(u32 board_type)
+{
+ return ((board_type) == BOARD_TYPE_CAL_1X100GR2_OCP);
}
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h
index 291e475..4d4d543 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_cmd_base_defs.h
@@ -4,8 +4,95 @@
#ifndef MPU_CMD_BASE_DEFS_H
#define MPU_CMD_BASE_DEFS_H
-#include "mgmt_msg_base.h"
-#include "comm_defs.h"
+/** MPU CMD MODULE TYPE */
+enum hinic3_mod_type {
+ HINIC3_MOD_COMM = 0, /* HW communication module */
+ HINIC3_MOD_L2NIC = 1, /* L2NIC module */
+ HINIC3_MOD_ROCE = 2,
+ HINIC3_MOD_PLOG = 3,
+ HINIC3_MOD_TOE = 4,
+ HINIC3_MOD_FLR = 5,
+ HINIC3_MOD_VROCE = 6,
+ HINIC3_MOD_CFGM = 7, /* Configuration management */
+ HINIC3_MOD_CQM = 8,
+ HINIC3_MOD_VMSEC = 9,
+ COMM_MOD_FC = 10,
+ HINIC3_MOD_OVS = 11,
+ HINIC3_MOD_DSW = 12,
+ HINIC3_MOD_MIGRATE = 13,
+ HINIC3_MOD_HILINK = 14,
+ HINIC3_MOD_CRYPT = 15, /* secure crypto module */
+ HINIC3_MOD_VIO = 16,
+ HINIC3_MOD_IMU = 17,
+ HINIC3_MOD_DFX = 18, /* DFX */
+ HINIC3_MOD_HW_MAX = 19, /* hardware max module id */
+ /* Software module id, for PF/VF and multi-host */
+ HINIC3_MOD_SW_FUNC = 20,
+ HINIC3_MOD_MAX,
+};
+
+/* func reset的flag ,用于指示清理哪种资源 */
+enum func_reset_flag_e {
+ RES_TYPE_FLUSH_BIT = 0,
+ RES_TYPE_MQM,
+ RES_TYPE_SMF,
+ RES_TYPE_PF_BW_CFG,
+
+ RES_TYPE_COMM = 10,
+ RES_TYPE_COMM_MGMT_CH, /* clear mbox and aeq, The RES_TYPE_COMM bit must be set */
+ RES_TYPE_COMM_CMD_CH, /* clear cmdq and ceq, The RES_TYPE_COMM bit must be set */
+ RES_TYPE_NIC,
+ RES_TYPE_OVS,
+ RES_TYPE_VBS,
+ RES_TYPE_ROCE,
+ RES_TYPE_FC,
+ RES_TYPE_TOE,
+ RES_TYPE_IPSEC,
+ RES_TYPE_MAX,
+};
+
+#define HINIC3_COMM_RES \
+ ((1 << RES_TYPE_COMM) | (1 << RES_TYPE_COMM_CMD_CH) | \
+ (1 << RES_TYPE_FLUSH_BIT) | (1 << RES_TYPE_MQM) | \
+ (1 << RES_TYPE_SMF) | (1 << RES_TYPE_PF_BW_CFG))
+
+#define HINIC3_NIC_RES (1 << RES_TYPE_NIC)
+#define HINIC3_OVS_RES (1 << RES_TYPE_OVS)
+#define HINIC3_VBS_RES (1 << RES_TYPE_VBS)
+#define HINIC3_ROCE_RES (1 << RES_TYPE_ROCE)
+#define HINIC3_FC_RES (1 << RES_TYPE_FC)
+#define HINIC3_TOE_RES (1 << RES_TYPE_TOE)
+#define HINIC3_IPSEC_RES (1 << RES_TYPE_IPSEC)
+
+/* MODE OVS、NIC、UNKNOWN */
+#define HINIC3_WORK_MODE_OVS 0
+#define HINIC3_WORK_MODE_UNKNOWN 1
+#define HINIC3_WORK_MODE_NIC 2
+
+#define DEVICE_TYPE_L2NIC 0
+#define DEVICE_TYPE_NVME 1
+#define DEVICE_TYPE_VIRTIO_NET 2
+#define DEVICE_TYPE_VIRTIO_BLK 3
+#define DEVICE_TYPE_VIRTIO_VSOCK 4
+#define DEVICE_TYPE_VIRTIO_NET_TRANSITION 5
+#define DEVICE_TYPE_VIRTIO_BLK_TRANSITION 6
+#define DEVICE_TYPE_VIRTIO_SCSI_TRANSITION 7
+#define DEVICE_TYPE_VIRTIO_HPC 8
+#define DEVICE_TYPE_VIRTIO_FS 9
+
+#define IS_STORAGE_DEVICE_TYPE(dev_type) \
+ ((dev_type) == DEVICE_TYPE_VIRTIO_BLK || \
+ (dev_type) == DEVICE_TYPE_VIRTIO_BLK_TRANSITION || \
+ (dev_type) == DEVICE_TYPE_VIRTIO_SCSI_TRANSITION || \
+ (dev_type) == DEVICE_TYPE_VIRTIO_FS)
+
+#define MGMT_MSG_CMD_OP_SET 1
+#define MGMT_MSG_CMD_OP_GET 0
+
+#define MGMT_MSG_CMD_OP_START 1
+#define MGMT_MSG_CMD_OP_STOP 0
+
+#define HOT_REPLACE_PARTITION_NUM 2
enum hinic3_svc_type {
SVC_T_COMM = 0,
@@ -23,4 +110,54 @@ enum hinic3_svc_type {
SVC_T_MAX,
};
+/**
+ * Common header control information of the COMM message interaction
+ * command word between the driver and PF
+ * struct mgmt_msg_head and struct comm_info_head are the same structure
+ */
+struct mgmt_msg_head {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+};
+
+/**
+ * Common header control information of the COMM message interaction
+ * command word between the driver and PF
+ */
+struct comm_info_head {
+ /** response status code, 0: success, others: error code */
+ u8 status;
+
+ /** firmware version for command */
+ u8 version;
+
+ /** response aeq number, unused for now */
+ u8 rep_aeq_num;
+ u8 rsvd[5];
+};
+
+static inline u32 get_function_partition(u32 function_id, u32 port_num)
+{
+ return (function_id / port_num) % HOT_REPLACE_PARTITION_NUM;
+}
+
+static inline u32 is_primary_function(u32 function_id, u32 port_num)
+{
+ return (function_id / port_num) % HOT_REPLACE_PARTITION_NUM == 0;
+}
+
+static inline u32 mpu_nic_get_primary_function(u32 function_id, u32 port_num)
+{
+ return ((function_id / port_num) % HOT_REPLACE_PARTITION_NUM == 0) ?
+ function_id : (function_id - port_num);
+}
+
+// when func_id is in partition 0/1, it will get its another func_id in partition 1/0
+static inline u32 mpu_nic_get_backup_function(u32 function_id, u32 port_num)
+{
+ return ((function_id / port_num) % HOT_REPLACE_PARTITION_NUM == 0) ?
+ (function_id + port_num) : (function_id - port_num);
+}
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h
index a8e2d63..3841bb5 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd.h
@@ -91,6 +91,10 @@ enum hinic3_mgmt_cmd {
* @see comm_read_ucode_sm_resp
*/
COMM_MGMT_CMD_CLEAR_LOG, /**< clear log @see comm_cmd_clear_log_s */
+ COMM_MGMT_CMD_UCODE_SM_COUNTER_PER,
+ /**< get ucode sm counter @see struct comm_read_ucode_sm_per_req
+ * @see struct comm_read_ucode_sm_per_resp
+ */
COMM_MGMT_CMD_CHECK_IF_SWITCH_WORKMODE = 140, /* check if switch workmode reserved
* @see comm_cmd_check_if_switch_workmode
@@ -103,6 +107,7 @@ enum hinic3_mgmt_cmd {
COMM_MGMT_CMD_CPI_TCAM_DBG, /* enable or disable the scheduled cpi tcam task,
* set task interval time @see comm_cmd_cpi_tcam_dbg_s
*/
+ COMM_MGMT_CMD_LLDP_TX_FUNC_SET,
COMM_MGMT_CMD_SECTION_RSVD_0 = 160, /**< rsvd0 section */
COMM_MGMT_CMD_SECTION_RSVD_1 = 170, /**< rsvd1 section */
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h
index 674603d..698730f 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_inband_cmd_defs.h
@@ -338,7 +338,8 @@ struct comm_cmd_get_fw_version {
struct mgmt_msg_head head;
u16 fw_type; /**< firmware type @see enum hinic3_fw_ver_type */
- u16 rsvd1;
+ u16 fw_dfx_vld : 1; /**< 0: release, 1: debug */
+ u16 rsvd1 : 15;
u8 ver[HINIC3_FW_VERSION_LEN]; /**< firmware version */
u8 time[HINIC3_FW_COMPILE_TIME_LEN]; /**< firmware compile time */
};
@@ -430,6 +431,22 @@ struct comm_cmd_bdf_info {
u8 rsvd2[5];
};
+struct mpu_pcie_pf_info {
+ u32 device_id; /**< device id */
+ u32 vendor_id; /**< vendor id */
+};
+
+struct mpu_pcie_device_info {
+ u8 status;
+ u8 version;
+ u8 rep_aeq_num;
+ u8 rsvd[5];
+
+ struct mpu_pcie_pf_info pf_info[32];
+ u32 bus_id; /**< bus id */
+ u32 pf_num; /**< pf index */
+};
+
#define TABLE_INDEX_MAX 129
struct sml_table_id_info {
u8 node_id;
@@ -446,6 +463,13 @@ struct comm_cmd_sdi_info {
u32 cfg_sdi_mode; /**< host mode, 0:normal 1:virtual machine 2:bare metal */
};
+struct comm_cmd_root_ctx_load_req {
+ struct comm_info_head head;
+ u32 func_id; /**< function id */
+ u32 smf_id; /**< smf id */
+ u32 queue_id; /**< queue id */
+};
+
#define HINIC_OVS_BOND_DEFAULT_ID 1
struct hinic3_hw_bond_infos {
u8 bond_id;
@@ -685,6 +709,28 @@ struct comm_read_ucode_sm_resp {
u64 val2;
};
+#define PER_REQ_MAX_DATA_LEN 0x600
+
+struct comm_read_ucode_sm_per_req {
+ struct mgmt_msg_head msg_head;
+
+ u32 tbl_type;
+ u32 count_id;
+};
+
+struct comm_read_ucode_sm_per_resp {
+ struct mgmt_msg_head msg_head;
+
+ u8 data[PER_REQ_MAX_DATA_LEN];
+};
+
+struct ucode_sm_counter_get_info {
+ u32 width_type;
+ u32 tbl_type;
+ unsigned int base_count;
+ unsigned int count_num;
+};
+
enum log_type {
MPU_LOG_CLEAR = 0,
SMU_LOG_CLEAR = 1,
@@ -693,6 +739,11 @@ enum log_type {
ALL_LOG_CLEAR = 4,
};
+struct comm_cmd_clear_log {
+ struct comm_info_head head;
+ u32 type; /**< log type @see enum log_type */
+};
+
#define ABLESWITCH 1
#define IMABLESWITCH 2
enum switch_workmode_op {
@@ -717,6 +768,14 @@ struct comm_cmd_check_if_switch_workmode {
u32 rsvd3[3];
};
+struct comm_cmd_switch_workmode {
+ struct mgmt_msg_head head;
+ u8 operation;
+ u8 work_mode;
+ u16 rsvd1[3];
+ u32 rsvd2[3];
+};
+
#define MIG_NOR_VM_ONE_MAX_SGE_MEM (64 * 8)
#define MIG_NOR_VM_ONE_MAX_MEM (MIG_NOR_VM_ONE_MAX_SGE_MEM + 16)
#define MIG_VM_MAX_SML_ENTRY_NUM 24
@@ -755,6 +814,15 @@ struct cmd_get_bdf_info_s {
#define CPI_TCAM_DBG_CMD_TYPE_SET 0
#define CPI_TCAM_DBG_CMD_TYPE_GET 1
+struct comm_cmd_cpi_tcam_dbg {
+ struct comm_info_head head;
+ u8 type;
+ u8 set_bitmap;
+ u8 enable;
+ u8 rsvd;
+ u32 time_interval;
+};
+
#define UDIE_ID_DATA_LEN 8
#define TDIE_ID_DATA_LEN 18
struct comm_cmd_get_die_id {
@@ -808,6 +876,12 @@ struct cmd_query_fw {
u32 len; /**< length */
};
+struct comm_cmd_get_cfg_info_t {
+ struct comm_info_head head;
+ u8 rsvd[8];
+ u8 info[64]; /**< flash config info */
+};
+
struct nic_cmd_get_uart_log_info {
struct comm_info_head head;
struct {
@@ -969,6 +1043,7 @@ enum comm_virtio_dev_type {
COMM_VIRTIO_NET_TYPE = 0,
COMM_VIRTIO_BLK_TYPE = 1,
COMM_VIRTIO_SCSI_TYPE = 4,
+ COMM_VIRTIO_FS_TYPE = 5,
};
struct comm_virtio_dev_cmd {
@@ -1030,6 +1105,13 @@ struct cmd_patch_sram_optimize {
u32 data[4]; /**< reserved */
};
+struct comm_cmd_con_sel_sta {
+ struct comm_info_head head;
+ u8 valid;
+ u8 host_id; /**< host id, range[0,3] */
+ u8 rsvd[2];
+};
+
/* ncsi counter */
struct nsci_counter_in_info_s {
struct comm_info_head head;
@@ -1082,7 +1164,9 @@ struct comm_cmd_ncsi_settings {
u8 lldp_over_ncsi_enable;
u8 lldp_over_mctp_enable;
u32 magicwd;
- u8 rsvd[8];
+ u8 lldp_tx_enable;
+ u8 rsvd[3];
+ u32 crc;
struct tag_ncsi_chan_info ncsi_chan_info;
};
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h
index fde8617..1ee44a8 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/mpu_outband_ncsi_cmd_defs.h
@@ -114,6 +114,14 @@ struct tag_ncsi_client_info {
#define AEN_CTRL_CONFIG_REQ_SHIFT 1
#define AEN_CTRL_DRV_CHANGE_SHIFT 2
+/* AEN Type */
+enum aen_type_e {
+ AEN_LINK_STATUS_CHANGE_TYPE = 0x0,
+ AEN_CONFIG_REQUIRED_TYPE = 0x1,
+ OEM_AEN_CONFIG_REQUEST_TYPE = 0x80,
+ AEN_TYPE_MAX = 0x100
+};
+
/* get link status 0x0A */
#define GET_LINK_STATUS_REQ_LEN 0
#define GET_LINK_STATUS_RSP_LEN 16
diff --git a/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h b/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h
index 0bd168c..5b2bdc8 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/mpu/nic_cfg_comm.h
@@ -36,6 +36,7 @@ enum nic_rss_hash_type {
#define NIC_RX_MODE_BC 0x04
#define NIC_RX_MODE_MC_ALL 0x08
#define NIC_RX_MODE_PROMISC 0x10
+#define NIC_RX_DB_COS_MAX 0x4
/* IEEE 802.1Qaz std */
#define NIC_DCB_COS_MAX 0x8
@@ -52,4 +53,7 @@ enum nic_rss_hash_type {
#define NIC_DCB_PRIO_STRICT 0x1
#define NIC_DCB_MAX_PFC_NUM 0x4
+
+#define NIC_ETS_PERCENT_WEIGHT 100
+
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/include/vram_common.h b/drivers/net/ethernet/huawei/hinic3/include/vram_common.h
index 801aeed..5476287 100644
--- a/drivers/net/ethernet/huawei/hinic3/include/vram_common.h
+++ b/drivers/net/ethernet/huawei/hinic3/include/vram_common.h
@@ -23,7 +23,11 @@
#define VRAM_CQM_BITMAP_BASE "B"
#define VRAM_NIC_DCB "DCB"
+#define VRAM_NIC_MHOST_MGMT "MHOST_MGMT"
#define VRAM_NIC_VRAM "NIC_VRAM"
+#define VRAM_NIC_IRQ_VRAM "NIC_IRQ"
+
+#define VRAM_NIC_MQM "NM"
#define VRAM_VBS_BASE_IOCB "BASE_IOCB"
#define VRAM_VBS_EX_IOCB "EX_IOCB"
@@ -32,6 +36,9 @@
#define VRAM_VBS_VOLQ_MTT "VOLQ_MTT"
#define VRAM_VBS_VOLQ_MTT_PAGE "MTT_PAGE"
+#define VRAM_OVS_PORT_CONF "OVS_PORT_CONF"
+#define VRAM_OVS_DFX_MGR "OVS_DFX_MGR"
+
#define VRAM_VROCE_ENTRY_POOL "VROCE_ENTRY"
#define VRAM_VROCE_GROUP_POOL "VROCE_GROUP"
#define VRAM_VROCE_UUID "VROCE_UUID"
@@ -42,6 +49,17 @@
#define VRAM_VROCE_DEV "VROCE_DEV"
#define VRAM_VROCE_RGROUP_HT_CNT "RGROUP_CNT"
#define VRAM_VROCE_RACL_HT_CNT "RACL_CNT"
+#define VRAM_VROCE_MQM_ENQC "VROCE_MQM_ENQC"
+
+#define VRAM_DTOE_NUMA_MEM "DTOE_NUMA"
+#define VRAM_DTOE_CARD_MEM "DTOE_CARD"
+#define VRAM_DTOE_CONN_MEM "DTOE_CONN"
+#define VRAM_DTOE_SUB_LEN 10
+
+#define VRAM_VROCE_MIG_ENTRY_POOL "VROCE_MIG_ENTRY"
+#define VRAM_VROCE_MIG_ENTRY_HT_CNT "MIG_ENTRY_CNT"
+
+#define VRAM_VBS_DEV_INDEX "VBS_INDEX"
#define VRAM_NAME_APPLY_LEN 64
@@ -55,11 +73,16 @@ enum KUP_HOOK_POINT {
PRE_FREEZE,
FREEZE_TO_KILL,
PRE_UPDATE_KERNEL,
- FLUSH_DURING_KUP,
POST_UPDATE_KERNEL,
UNFREEZE_TO_RUN,
POST_RUN,
KUP_HOOK_MAX,
};
+#define hi_vram_kalloc(name, size) 0
+#define hi_vram_kfree(vaddr, name, size)
+#define get_use_vram_flag(void) 0
+#define vram_get_kexec_flag(void) 0
+#define hi_vram_get_gfp_vram(void) 0
+
#endif /* VRAM_COMMON_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/mag_cmd.h b/drivers/net/ethernet/huawei/hinic3/mag_mpu_cmd_defs.h
similarity index 79%
rename from drivers/net/ethernet/huawei/hinic3/mag_cmd.h
rename to drivers/net/ethernet/huawei/hinic3/mag_mpu_cmd_defs.h
index 9649503..c8533e5 100644
--- a/drivers/net/ethernet/huawei/hinic3/mag_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/mag_mpu_cmd_defs.h
@@ -9,6 +9,7 @@
/* serdes cmd struct define */
#define CMD_ARRAY_BUF_SIZE 64
#define SERDES_CMD_DATA_BUF_SIZE 512
+#define RATE_MBPS_TO_GBPS 1000
struct serdes_in_info {
u32 chip_id : 16;
u32 macro_id : 16;
@@ -127,6 +128,7 @@ enum mag_cmd_cnt_type {
MAG_RX_PCS_E_BLK_CNT = 5,
MAG_RX_PCS_DEC_ERR_BLK_CNT = 6,
MAG_RX_PCS_LANE_BIP_ERR_CNT = 7,
+ MAG_RX_RSFEC_ERR_CW_CNT = 8,
MAG_CNT_NUM
};
@@ -208,7 +210,9 @@ struct mag_cmd_get_port_info {
u32 supported_mode;
u32 advertised_mode;
- u8 rsvd2[8];
+ u32 supported_fec_mode;
+ u16 bond_speed;
+ u8 rsvd2[2];
};
#define MAG_CMD_OPCODE_GET 0
@@ -330,8 +334,8 @@ struct mag_cmd_cfg_fec_mode {
u8 port_id;
u8 opcode; /* 0:get fec mode 1:set fec mode */
- u8 fec;
- u8 rsvd0;
+ u8 advertised_fec;
+ u8 supported_fec;
};
/* speed */
@@ -641,7 +645,7 @@ struct mag_cmd_event_port_info {
u32 cable_length; /* 1/3/5m */
u8 cable_temp; /* temp */
u8 max_speed; /* Maximum rate of an optical module */
- u8 sfp_type; /* sfp/qsfp */
+ u8 sfp_type; /* sfp/qsfp/dsfp */
u8 rsvd1;
u32 power[4]; /* Optical Power */
@@ -678,6 +682,10 @@ struct mag_cmd_event_port_info {
u8 rsvd3[360];
};
+struct mag_cmd_rsfec_stats {
+ u32 rx_err_lane_phy;
+};
+
struct mag_cmd_port_stats {
u64 mac_tx_fragment_pkt_num;
u64 mac_tx_undersize_pkt_num;
@@ -913,10 +921,222 @@ struct mag_cmd_sfp_temp_in_info {
};
struct mag_cmd_sfp_temp_out_info {
- struct mgmt_msg_head head; /* 8B */
- s16 sfp_temp_data[MAG_SFP_PORT_NUM]; /* Temperature read */
- s32 max_temp; /* Chip optical module threshold */
- s32 min_temp; /* Chip optical module threshold */
+ struct mgmt_msg_head head; /* 8B */
+ s16 sfp_temp_data[MAG_SFP_PORT_NUM]; /* Temperature read */
+ s32 max_temp; /* Chip optical module threshold */
+ s32 min_temp; /* Chip optical module threshold */
+};
+
+#define XSFP_CMIS_PARSE_PAGE_NUM 6
+#define XSFP_CMIS_INFO_MAX_SIZE 1536
+#define QSFP_CMIS_PAGE_SIZE 128
+#define QSFP_CMIS_MAX_CHANNEL_NUM 0x8
+
+/* Lower: Control and Essentials, Upper: Administrative Information */
+#define QSFP_CMIS_PAGE_00H 0x00
+/* Advertising */
+#define QSFP_CMIS_PAGE_01H 0x01
+/* Module and lane Thresholds */
+#define QSFP_CMIS_PAGE_02H 0x02
+/* User EEPROM */
+#define QSFP_CMIS_PAGE_03H 0x03
+/* Laser Capabilities Advertising (Page 04h, Optional) */
+#define QSFP_CMIS_PAGE_04H 0x04
+#define QSFP_CMIS_PAGE_05H 0x05
+/* Lane and Data Path Control */
+#define QSFP_CMIS_PAGE_10H 0x10
+/* Lane Status */
+#define QSFP_CMIS_PAGE_11H 0x11
+#define QSFP_CMIS_PAGE_12H 0x12
+
+#define MGMT_TLV_U8_SIZE 1
+#define MGMT_TLV_U16_SIZE 2
+#define MGMT_TLV_U32_SIZE 4
+
+#define MGMT_TLV_GET_U8(addr) (*((u8 *)(void *)(addr)))
+#define MGMT_TLV_SET_U8(addr, value) \
+ ((*((u8 *)(void *)(addr))) = ((u8)(value)))
+
+#define MGMT_TLV_GET_U16(addr) (*((u16 *)(void *)(addr)))
+#define MGMT_TLV_SET_U16(addr, value) \
+ ((*((u16 *)(void *)(addr))) = ((u16)(value)))
+
+#define MGMT_TLV_GET_U32(addr) (*((u32 *)(void *)(addr)))
+#define MGMT_TLV_SET_U32(addr, value) \
+ ((*((u32 *)(void *)(addr))) = ((u32)(value)))
+
+#define MGMT_TLV_TYPE_END 0xFFFF
+
+enum mag_xsfp_type {
+ MAG_XSFP_TYPE_PAGE = 0x01,
+ MAG_XSFP_TYPE_WIRE_TYPE = 0x02,
+ MAG_XSFP_TYPE_END = MGMT_TLV_TYPE_END
+};
+
+struct qsfp_cmis_lower_page_00_s {
+ u8 resv0[14];
+ u8 temperature_msb;
+ u8 temperature_lsb;
+ u8 volt_supply[2];
+ u8 resv1[67];
+ u8 media_type;
+ u8 electrical_interface_id;
+ u8 media_interface_id;
+ u8 lane_count;
+ u8 resv2[39];
+};
+
+struct qsfp_cmis_upper_page_00_s {
+ u8 identifier;
+ u8 vendor_name[16];
+ u8 vendor_oui[3];
+ u8 vendor_pn[16];
+ u8 vendor_rev[2];
+ u8 vendor_sn[16];
+ u8 date_code[8];
+ u8 clei_code[10];
+ u8 power_character[2];
+ u8 cable_len;
+ u8 connector;
+ u8 copper_cable_attenuation[6];
+ u8 near_end_implementation;
+ u8 far_end_config;
+ u8 media_technology;
+ u8 resv0[43];
+};
+
+struct qsfp_cmis_upper_page_01_s {
+ u8 firmware_rev[2];
+ u8 hardware_rev[2];
+ u8 smf_len_km;
+ u8 om5_len;
+ u8 om4_len;
+ u8 om3_len;
+ u8 om2_len;
+ u8 resv0;
+ u8 wavelength[2];
+ u8 wavelength_tolerance[2];
+ u8 pages_implement;
+ u8 resv1[16];
+ u8 monitor_implement[2];
+ u8 resv2[95];
+};
+
+struct qsfp_cmis_upper_page_02_s {
+ u8 temperature_high_alarm[2];
+ u8 temperature_low_alarm[2];
+ u8 temperature_high_warn[2];
+ u8 temperature_low_warn[2];
+ u8 volt_high_alarm[2];
+ u8 volt_low_alarm[2];
+ u8 volt_high_warn[2];
+ u8 volt_low_warn[2];
+ u8 resv0[32];
+ u8 tx_power_high_alarm[2];
+ u8 tx_power_low_alarm[2];
+ u8 tx_power_high_warn[2];
+ u8 tx_power_low_warn[2];
+ u8 tx_bias_high_alarm[2];
+ u8 tx_bias_low_alarm[2];
+ u8 tx_bias_high_warn[2];
+ u8 tx_bias_low_warn[2];
+ u8 rx_power_high_alarm[2];
+ u8 rx_power_low_alarm[2];
+ u8 rx_power_high_warn[2];
+ u8 rx_power_low_warn[2];
+ u8 resv1[56];
+};
+
+struct qsfp_cmis_upper_page_03_s {
+ u8 resv0[QSFP_CMIS_PAGE_SIZE]; /* Reg 128-255: Upper Memory: Page 03H */
+};
+
+struct qsfp_cmis_upper_page_10_s {
+ u8 resv0[2]; /* Reg 128-129: Upper Memory: Page 10H */
+ u8 tx_disable; /* Reg 130: Tx disable, 0b=enabled, 1b=disabled */
+ u8 resv1[125]; /* Reg 131-255 */
+};
+
+struct qsfp_cmis_upper_page_11_s {
+ u8 resv0[7];
+ u8 tx_fault;
+ u8 tx_los;
+ u8 resv1[10];
+ u8 rx_los;
+ u8 resv2[6];
+ u8 tx_power[16];
+ u8 tx_bias[16];
+ u8 rx_power[16];
+ u8 resv3[54];
+};
+
+struct qsfp_cmis_info_s {
+ struct qsfp_cmis_lower_page_00_s lower_page_00;
+ struct qsfp_cmis_upper_page_00_s upper_page_00;
+ struct qsfp_cmis_upper_page_01_s upper_page_01;
+ struct qsfp_cmis_upper_page_02_s upper_page_02;
+ struct qsfp_cmis_upper_page_10_s upper_page_10;
+ struct qsfp_cmis_upper_page_11_s upper_page_11;
+};
+
+struct qsfp_cmis_comm_power_s {
+ u32 chl_power[QSFP_CMIS_MAX_CHANNEL_NUM];
+};
+
+struct qsfp_cmis_wire_info_s {
+ struct qsfp_cmis_comm_power_s rx_power;
+ u8 rx_los;
+ u8 resv0[3];
+};
+
+struct mgmt_tlv_info {
+ u16 type;
+ u16 length;
+ u8 value[];
+};
+
+struct mag_cmd_set_xsfp_tlv_req {
+ struct mgmt_msg_head head;
+
+ u8 tlv_buf[];
+};
+
+struct mag_cmd_set_xsfp_tlv_rsp {
+ struct mgmt_msg_head head;
+};
+
+struct tag_mag_cmd_get_xsfp_tlv_req {
+ struct mgmt_msg_head head;
+
+ u8 port_id;
+ u8 rsvd;
+ u16 rsp_buf_len;
+};
+
+struct mag_cmd_get_xsfp_tlv_rsp {
+ struct mgmt_msg_head head;
+
+ u8 port_id;
+ u8 rsvd[3];
+
+ u8 tlv_buf[];
+};
+
+struct parse_tlv_info {
+ u8 tlv_page_info[XSFP_CMIS_INFO_MAX_SIZE + 1];
+ u32 tlv_page_info_len;
+ u32 tlv_page_num[XSFP_CMIS_PARSE_PAGE_NUM];
+ u32 wire_type;
+ u8 id;
+};
+
+struct drv_tag_mag_cmd_get_xsfp_tlv_rsp {
+ struct mgmt_msg_head head;
+
+ u8 port_id;
+ u8 rsvd[3];
+
+ u8 tlv_buf[XSFP_CMIS_INFO_MAX_SIZE];
};
#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h b/drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h
deleted file mode 100644
index 257bf67..0000000
--- a/drivers/net/ethernet/huawei/hinic3/mgmt_msg_base.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
- * File Name : mgmt_msg_base.h
- * Version : Initial Draft
- * Created : 2021/6/28
- * Last Modified :
- * Description : COMM Command interfaces between Driver and MPU
- * Function List :
- */
-
-#ifndef MGMT_MSG_BASE_H
-#define MGMT_MSG_BASE_H
-
-#define MGMT_MSG_CMD_OP_SET 1
-#define MGMT_MSG_CMD_OP_GET 0
-
-#define MGMT_MSG_CMD_OP_START 1
-#define MGMT_MSG_CMD_OP_STOP 0
-
-struct mgmt_msg_head {
- u8 status;
- u8 version;
- u8 rsvd0[6];
-};
-
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h b/drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h
deleted file mode 100644
index abcfa27..0000000
--- a/drivers/net/ethernet/huawei/hinic3/nic_cfg_comm.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C), 2001-2021, Huawei Tech. Co., Ltd.
- * File Name : nic_cfg_comm.h
- * Version : Initial Draft
- * Description : nic config common header file
- * Function List :
- * History :
- * Modification: Created file
- */
-
-#ifndef NIC_CFG_COMM_H
-#define NIC_CFG_COMM_H
-
-#include <linux/types.h>
-
-/* rss */
-#define HINIC3_RSS_TYPE_VALID_SHIFT 23
-#define HINIC3_RSS_TYPE_TCP_IPV6_EXT_SHIFT 24
-#define HINIC3_RSS_TYPE_IPV6_EXT_SHIFT 25
-#define HINIC3_RSS_TYPE_TCP_IPV6_SHIFT 26
-#define HINIC3_RSS_TYPE_IPV6_SHIFT 27
-#define HINIC3_RSS_TYPE_TCP_IPV4_SHIFT 28
-#define HINIC3_RSS_TYPE_IPV4_SHIFT 29
-#define HINIC3_RSS_TYPE_UDP_IPV6_SHIFT 30
-#define HINIC3_RSS_TYPE_UDP_IPV4_SHIFT 31
-
-#define HINIC3_RSS_TYPE_SET(val, member) (((u32)(val) & 0x1) << HINIC3_RSS_TYPE_##member##_SHIFT)
-#define HINIC3_RSS_TYPE_GET(val, member) (((u32)(val) >> HINIC3_RSS_TYPE_##member##_SHIFT) & 0x1)
-
-enum nic_rss_hash_type {
- NIC_RSS_HASH_TYPE_XOR = 0,
- NIC_RSS_HASH_TYPE_TOEP,
-
- NIC_RSS_HASH_TYPE_MAX /* MUST BE THE LAST ONE */
-};
-
-#define NIC_RSS_INDIR_SIZE 256
-#define NIC_RSS_KEY_SIZE 40
-
-/* *
- * Definition of the NIC receiving mode
- */
-#define NIC_RX_MODE_UC 0x01
-#define NIC_RX_MODE_MC 0x02
-#define NIC_RX_MODE_BC 0x04
-#define NIC_RX_MODE_MC_ALL 0x08
-#define NIC_RX_MODE_PROMISC 0x10
-
-/* IEEE 802.1Qaz std */
-#define NIC_DCB_COS_MAX 0x8
-#define NIC_DCB_UP_MAX 0x8
-#define NIC_DCB_TC_MAX 0x8
-#define NIC_DCB_PG_MAX 0x8
-#define NIC_DCB_TSA_SP 0x0
-#define NIC_DCB_TSA_CBS 0x1
-#define NIC_DCB_TSA_ETS 0x2
-#define NIC_DCB_DSCP_NUM 0x8
-#define NIC_DCB_IP_PRI_MAX 0x40
-
-#define NIC_DCB_PRIO_DWRR 0x0
-#define NIC_DCB_PRIO_STRICT 0x1
-
-#define NIC_DCB_MAX_PFC_NUM 0x4
-#endif
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cmd.h b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd.h
similarity index 77%
rename from drivers/net/ethernet/huawei/hinic3/hinic3_nic_cmd.h
rename to drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd.h
index c35bc82..b0114a0 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_nic_cmd.h
+++ b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
- * File Name : hinic3_comm_cmd.h
+ * File Name : hinic3_nic_mpu_cmd.h
* Version : Initial Draft
* Created : 2019/4/25
* Last Modified :
@@ -33,10 +33,11 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_CFG_LOCAL_LRO_STATE,
HINIC3_NIC_CMD_CACHE_OUT_QP_RES,
+ HINIC3_NIC_CMD_SET_FUNC_ER_FWD_ID,
HINIC3_NIC_CMD_SET_RQ_CI_CTX,
- /* MAC & VLAN CFG */
+ /* MAC & VLAN CFG & VXLAN CFG */
HINIC3_NIC_CMD_GET_MAC = 20,
HINIC3_NIC_CMD_SET_MAC,
HINIC3_NIC_CMD_DEL_MAC,
@@ -47,6 +48,11 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_SET_VLAN_FILTER_EN,
HINIC3_NIC_CMD_SET_RX_VLAN_OFFLOAD,
HINIC3_NIC_CMD_SMAC_CHECK_STATE,
+ HINIC3_NIC_CMD_OUTBAND_SET_FUNC_VLAN,
+ HINIC3_NIC_CMD_CFG_VXLAN_PORT,
+
+ HINIC3_NIC_CMD_RX_RATE_CFG,
+ HINIC3_NIC_CMD_WR_ORDERING_CFG,
/* SR-IOV */
HINIC3_NIC_CMD_CFG_VF_VLAN = 40,
@@ -63,6 +69,7 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_SET_RSS_CTX_TBL_INTO_FUNC,
/* IP checksum error packets, enable rss quadruple hash */
HINIC3_NIC_CMD_IPCS_ERR_RSS_ENABLE_OP = 66,
+ HINIC3_NIC_CMD_GTP_INNER_PARSE_STATUS,
/* PPA/FDIR */
HINIC3_NIC_CMD_ADD_TC_FLOW = 80,
@@ -78,6 +85,10 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_CFG_PPA_FLUSH,
HINIC3_NIC_CMD_SET_FDIR_STATUS,
HINIC3_NIC_CMD_GET_PPA_COUNTER,
+ HINIC3_NIC_CMD_SET_FUNC_FLOW_BIFUR_ENABLE,
+ HINIC3_NIC_CMD_SET_BOND_MASK,
+ HINIC3_NIC_CMD_GET_BLOCK_TC_FLOWS,
+ HINIC3_NIC_CMD_GET_BOND_MASK,
/* PORT CFG */
HINIC3_NIC_CMD_SET_PORT_ENABLE = 100,
@@ -96,6 +107,8 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_QOS_PORT_CFG,
HINIC3_NIC_CMD_QOS_MAP_CFG,
HINIC3_NIC_CMD_FORCE_PKT_DROP,
+ HINIC3_NIC_CMD_CFG_TX_PROMISC_SKIP = 114,
+ HINIC3_NIC_CMD_SET_PORT_FLOW_BIFUR_ENABLE = 117,
HINIC3_NIC_CMD_TX_PAUSE_EXCP_NOTICE = 118,
HINIC3_NIC_CMD_INQUIRT_PAUSE_CFG = 119,
@@ -118,6 +131,10 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_SET_UCAPTURE_OPT = 160, /* TODO: move to roce */
HINIC3_NIC_CMD_SET_VHD_CFG,
+ /* OUT OF BAND */
+ HINIC3_NIC_CMD_GET_OUTBAND_CFG = 170, /* Get outband vlan cfg info */
+ HINIC3_NIC_CMD_OUTBAND_CFG_NOTICE, /* Outband vlan cfg info report */
+
/* TODO: move to HILINK */
HINIC3_NIC_CMD_GET_PORT_STAT = 200,
HINIC3_NIC_CMD_CLEAN_PORT_STAT,
@@ -138,24 +155,23 @@ enum hinic3_nic_cmd {
HINIC3_NIC_CMD_LINK_ERR_EVENT,
HINIC3_NIC_CMD_SET_LED_STATUS,
- HINIC3_NIC_CMD_MAX = 256,
-};
+ /* mig */
+ HINIC3_NIC_CMD_MIG_SET_CEQ_CTRL = 230,
+ HINIC3_NIC_CMD_MIG_CFG_MSIX_INFO,
+ HINIC3_NIC_CMD_MIG_CFG_FUNC_VAT_TBL,
+ HINIC3_NIC_CMD_MIG_GET_VF_INFO,
+ HINIC3_NIC_CMD_MIG_CHK_MBX_EMPTY,
+ HINIC3_NIC_CMD_MIG_SET_VPORT_ENABLE,
+ HINIC3_NIC_CMD_MIG_CFG_SQ_CI,
+ HINIC3_NIC_CMD_MIG_CFG_RSS_TBL,
+ HINIC3_NIC_CMD_MIG_CFG_MAC_TBL,
+ HINIC3_NIC_CMD_MIG_TMP_SET_CMDQ_CTX,
-/* NIC CMDQ MODE */
-enum hinic3_ucode_cmd {
- HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX = 0,
- HINIC3_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
- HINIC3_UCODE_CMD_ARM_SQ,
- HINIC3_UCODE_CMD_ARM_RQ,
- HINIC3_UCODE_CMD_SET_RSS_INDIR_TABLE,
- HINIC3_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
- HINIC3_UCODE_CMD_GET_RSS_INDIR_TABLE,
- HINIC3_UCODE_CMD_GET_RSS_CONTEXT_TABLE,
- HINIC3_UCODE_CMD_SET_IQ_ENABLE,
- HINIC3_UCODE_CMD_SET_RQ_FLUSH = 10,
- HINIC3_UCODE_CMD_MODIFY_VLAN_CTX,
- HINIC3_UCODE_CMD_PPA_HASH_TABLE,
- HINIC3_UCODE_CMD_RXQ_INFO_GET = 13,
+ HINIC3_OSHR_CMD_ACTIVE_FUNCTION = 240,
+
+ HINIC3_NIC_CMD_GET_RQ_INFO = 241,
+
+ HINIC3_NIC_CMD_MAX = 256,
};
#endif /* HINIC3_NIC_CMD_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h
new file mode 100644
index 0000000..5c28573
--- /dev/null
+++ b/drivers/net/ethernet/huawei/hinic3/nic_mpu_cmd_defs.h
@@ -0,0 +1,1440 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2024 Huawei Technologies Co., Ltd */
+
+#ifndef NIC_MPU_CMD_DEFS_H
+#define NIC_MPU_CMD_DEFS_H
+
+#include "nic_cfg_comm.h"
+#include "mpu_cmd_base_defs.h"
+
+#ifndef ETH_ALEN
+#define ETH_ALEN 6
+#endif
+
+#define HINIC3_CMD_OP_SET 1
+#define HINIC3_CMD_OP_GET 0
+
+#define HINIC3_CMD_OP_ADD 1
+#define HINIC3_CMD_OP_DEL 0
+
+#define NIC_TCAM_BLOCK_LARGE_NUM 256
+#define NIC_TCAM_BLOCK_LARGE_SIZE 16
+
+#define TRAFFIC_BIFUR_MODEL_TYPE 2
+
+#define NIC_TCAM_FLOW_BIFUR_FLAG (1 << 0)
+
+#ifndef BIT
+#define BIT(n) (1UL << (n))
+#endif
+
+enum nic_feature_cap {
+ NIC_F_CSUM = BIT(0),
+ NIC_F_SCTP_CRC = BIT(1),
+ NIC_F_TSO = BIT(2),
+ NIC_F_LRO = BIT(3),
+ NIC_F_UFO = BIT(4),
+ NIC_F_RSS = BIT(5),
+ NIC_F_RX_VLAN_FILTER = BIT(6),
+ NIC_F_RX_VLAN_STRIP = BIT(7),
+ NIC_F_TX_VLAN_INSERT = BIT(8),
+ NIC_F_VXLAN_OFFLOAD = BIT(9),
+ NIC_F_IPSEC_OFFLOAD = BIT(10),
+ NIC_F_FDIR = BIT(11),
+ NIC_F_PROMISC = BIT(12),
+ NIC_F_ALLMULTI = BIT(13),
+ NIC_F_XSFP_REPORT = BIT(14),
+ NIC_F_VF_MAC = BIT(15),
+ NIC_F_RATE_LIMIT = BIT(16),
+ NIC_F_RXQ_RECOVERY = BIT(17),
+ NIC_F_TX_COMPACT_WQE_OL = BIT(19),
+ NIC_F_RX_COMPACT_CQE = BIT(20),
+ NIC_F_HTN_CMDQ = BIT(21),
+};
+
+#define NIC_F_ALL_MASK 0x7FBFFFF /* 使能所有属性 */
+
+struct hinic3_mgmt_msg_head {
+ u8 status;
+ u8 version;
+ u8 rsvd0[6];
+};
+
+#define NIC_MAX_FEATURE_QWORD 4
+struct hinic3_cmd_feature_nego {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 1: set, 0: get */
+ u8 rsvd;
+ u64 s_feature[NIC_MAX_FEATURE_QWORD];
+};
+
+struct hinic3_port_mac_set {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 vlan_id;
+ u16 rsvd1;
+ u8 mac[ETH_ALEN];
+};
+
+struct hinic3_port_mac_update {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 vlan_id;
+ u16 rsvd1;
+ u8 old_mac[ETH_ALEN];
+ u16 rsvd2;
+ u8 new_mac[ETH_ALEN];
+};
+
+struct hinic3_vport_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 state; /* 0--disable, 1--enable */
+ u8 rsvd2[3];
+};
+
+struct hinic3_port_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 state; /* 0--disable, 1--enable */
+ u8 rsvd2[3];
+};
+
+#define HINIC3_SET_PORT_CAR_PROFILE 0
+#define HINIC3_SET_PORT_CAR_STATE 1
+#define HINIC3_GET_PORT_CAR_LIMIT_SPEED 2
+
+struct hinic3_port_car_info {
+ u32 cir; /* unit: kbps, range:[1,400*1000*1000], i.e. 1Kbps~400Gbps(400M*kbps) */
+ u32 xir; /* unit: kbps, range:[1,400*1000*1000], i.e. 1Kbps~400Gbps(400M*kbps) */
+ u32 cbs; /* unit: Byte, range:[1,320*1000*1000], i.e. 1byte~2560Mbit */
+ u32 xbs; /* unit: Byte, range:[1,320*1000*1000], i.e. 1byte~2560Mbit */
+};
+
+struct hinic3_cmd_set_port_car {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode; /* 0--set car profile, 1--set car state */
+ u8 state; /* 0--disable, 1--enable */
+ u8 level;
+
+ struct hinic3_port_car_info car;
+};
+
+struct hinic3_cmd_clear_qp_resource {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_cmd_cache_out_qp_resource {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_port_stats_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_vport_stats {
+ u64 tx_unicast_pkts_vport;
+ u64 tx_unicast_bytes_vport;
+ u64 tx_multicast_pkts_vport;
+ u64 tx_multicast_bytes_vport;
+ u64 tx_broadcast_pkts_vport;
+ u64 tx_broadcast_bytes_vport;
+
+ u64 rx_unicast_pkts_vport;
+ u64 rx_unicast_bytes_vport;
+ u64 rx_multicast_pkts_vport;
+ u64 rx_multicast_bytes_vport;
+ u64 rx_broadcast_pkts_vport;
+ u64 rx_broadcast_bytes_vport;
+
+ u64 tx_discard_vport;
+ u64 rx_discard_vport;
+ u64 tx_err_vport;
+ u64 rx_err_vport;
+};
+
+struct hinic3_phy_fpga_port_stats {
+ u64 mac_rx_total_octs_port;
+ u64 mac_tx_total_octs_port;
+ u64 mac_rx_under_frame_pkts_port;
+ u64 mac_rx_frag_pkts_port;
+ u64 mac_rx_64_oct_pkts_port;
+ u64 mac_rx_127_oct_pkts_port;
+ u64 mac_rx_255_oct_pkts_port;
+ u64 mac_rx_511_oct_pkts_port;
+ u64 mac_rx_1023_oct_pkts_port;
+ u64 mac_rx_max_oct_pkts_port;
+ u64 mac_rx_over_oct_pkts_port;
+ u64 mac_tx_64_oct_pkts_port;
+ u64 mac_tx_127_oct_pkts_port;
+ u64 mac_tx_255_oct_pkts_port;
+ u64 mac_tx_511_oct_pkts_port;
+ u64 mac_tx_1023_oct_pkts_port;
+ u64 mac_tx_max_oct_pkts_port;
+ u64 mac_tx_over_oct_pkts_port;
+ u64 mac_rx_good_pkts_port;
+ u64 mac_rx_crc_error_pkts_port;
+ u64 mac_rx_broadcast_ok_port;
+ u64 mac_rx_multicast_ok_port;
+ u64 mac_rx_mac_frame_ok_port;
+ u64 mac_rx_length_err_pkts_port;
+ u64 mac_rx_vlan_pkts_port;
+ u64 mac_rx_pause_pkts_port;
+ u64 mac_rx_unknown_mac_frame_port;
+ u64 mac_tx_good_pkts_port;
+ u64 mac_tx_broadcast_ok_port;
+ u64 mac_tx_multicast_ok_port;
+ u64 mac_tx_underrun_pkts_port;
+ u64 mac_tx_mac_frame_ok_port;
+ u64 mac_tx_vlan_pkts_port;
+ u64 mac_tx_pause_pkts_port;
+};
+
+struct hinic3_port_stats {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ struct hinic3_phy_fpga_port_stats stats;
+};
+
+struct hinic3_cmd_vport_stats {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u32 stats_size;
+ u32 rsvd1;
+ struct hinic3_vport_stats stats;
+ u64 rsvd2[6];
+};
+
+struct hinic3_cmd_qpn {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 base_qpn;
+};
+
+enum hinic3_func_tbl_cfg_bitmap {
+ FUNC_CFG_INIT,
+ FUNC_CFG_RX_BUF_SIZE,
+ FUNC_CFG_MTU,
+};
+
+struct hinic3_func_tbl_cfg {
+ u16 rx_wqe_buf_size;
+ u16 mtu;
+ u32 rsvd[9];
+};
+
+struct hinic3_cmd_set_func_tbl {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd;
+
+ u32 cfg_bitmap;
+ struct hinic3_func_tbl_cfg tbl_cfg;
+};
+
+struct hinic3_cmd_cons_idx_attr {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_idx;
+ u8 dma_attr_off;
+ u8 pending_limit;
+ u8 coalescing_time;
+ u8 intr_en;
+ u16 intr_idx;
+ u32 l2nic_sqn;
+ u32 rsvd;
+ u64 ci_addr;
+};
+
+union sm_tbl_args {
+ struct {
+ u32 tbl_index;
+ u32 cnt;
+ u32 total_cnt;
+ } mac_table_arg;
+ struct {
+ u32 er_id;
+ u32 vlan_id;
+ } vlan_elb_table_arg;
+ struct {
+ u32 func_id;
+ } vlan_filter_arg;
+ struct {
+ u32 mc_id;
+ } mc_elb_arg;
+ struct {
+ u32 func_id;
+ } func_tbl_arg;
+ struct {
+ u32 port_id;
+ } port_tbl_arg;
+ struct {
+ u32 tbl_index;
+ u32 cnt;
+ u32 total_cnt;
+ } fdir_io_table_arg;
+ struct {
+ u32 tbl_index;
+ u32 cnt;
+ u32 total_cnt;
+ } flexq_table_arg;
+ u32 args[4];
+};
+
+struct hinic3_rq_cqe_ctx {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 cqe_type;
+ u8 rq_id;
+ u8 threshold_cqe_num;
+ u8 rsvd1;
+
+ u16 msix_entry_idx;
+ u16 rsvd2;
+
+ u32 ci_addr_hi;
+ u32 ci_addr_lo;
+
+ u16 timer_loop;
+ u16 rsvd3;
+};
+
+#define DFX_SM_TBL_BUF_MAX (768)
+
+struct nic_cmd_dfx_sm_table {
+ struct hinic3_mgmt_msg_head msg_head;
+ u32 tbl_type;
+ union sm_tbl_args args;
+ u8 tbl_buf[DFX_SM_TBL_BUF_MAX];
+};
+
+struct hinic3_cmd_vlan_offload {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 vlan_offload;
+ u8 rsvd1[5];
+};
+
+/* ucode capture cfg info */
+struct nic_cmd_capture_info {
+ struct hinic3_mgmt_msg_head msg_head;
+ u32 op_type;
+ u32 func_port;
+ u32 is_en_trx;
+ u32 offset_cos;
+ u32 data_vlan;
+};
+
+struct hinic3_cmd_lro_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u8 lro_ipv4_en;
+ u8 lro_ipv6_en;
+ u8 lro_max_pkt_len; /* unit is 1K */
+ u8 resv2[13];
+};
+
+struct hinic3_cmd_lro_timer {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 opcode; /* 1: set timer value, 0: get timer value */
+ u8 rsvd1;
+ u16 rsvd2;
+ u32 timer;
+};
+
+struct hinic3_cmd_local_lro_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 0: get state, 1: set state */
+ u8 state; /* 0: disable, 1: enable */
+};
+
+struct hinic3_cmd_gtp_inner_parse_status {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 0: get state, 1: set state */
+ u8 status; /* 0: disable, 1: enable */
+};
+
+struct hinic3_cmd_vf_vlan_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u16 vlan_id;
+ u8 qos;
+ u8 rsvd2[5];
+};
+
+struct hinic3_cmd_spoofchk_set {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 state;
+ u8 rsvd1;
+};
+
+struct hinic3_cmd_tx_rate_cfg {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 rsvd1;
+ u8 direct;
+ u32 min_rate;
+ u32 max_rate;
+ u8 rsvd2[8];
+};
+
+struct hinic3_cmd_port_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+ u8 port_type;
+ u8 autoneg_cap;
+ u8 autoneg_state;
+ u8 duplex;
+ u8 speed;
+ u8 fec;
+ u16 rsvd2;
+ u32 rsvd3[4];
+};
+
+struct hinic3_cmd_register_vf {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 op_register; /* 0 - unregister, 1 - register */
+ u8 rsvd1[3];
+ u32 support_extra_feature;
+ u8 rsvd2[32];
+};
+
+struct hinic3_cmd_link_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 state;
+ u16 rsvd1;
+};
+
+struct hinic3_cmd_vlan_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 outband_defvid_flag;
+ u16 vlan_id;
+ u8 blacklist_flag;
+ u8 rsvd2;
+};
+
+#define VLAN_BLACKLIST_ENABLE 1
+#define VLAN_BLACKLIST_DISABLE 0
+
+struct hinic3_cmd_vxlan_port_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 cfg_mode;
+ u16 vxlan_port;
+ u16 rsvd2;
+};
+
+/* set vlan filter */
+struct hinic3_cmd_set_vlan_filter {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 resvd[2];
+ u32 vlan_filter_ctrl; /* bit0:vlan filter en; bit1:broadcast_filter_en */
+};
+
+struct hinic3_cmd_link_ksettings_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+
+ u32 valid_bitmap;
+ u8 speed; /* enum nic_speed_level */
+ u8 autoneg; /* 0 - off, 1 - on */
+ u8 fec; /* 0 - RSFEC, 1 - BASEFEC, 2 - NOFEC */
+ u8 rsvd2[21]; /* reserved for duplex, port, etc. */
+};
+
+struct mpu_lt_info {
+ u8 node;
+ u8 inst;
+ u8 entry_size;
+ u8 rsvd;
+ u32 lt_index;
+ u32 offset;
+ u32 len;
+};
+
+struct nic_mpu_lt_opera {
+ struct hinic3_mgmt_msg_head msg_head;
+ struct mpu_lt_info net_lt_cmd;
+ u8 data[100];
+};
+
+struct hinic3_force_pkt_drop {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port;
+ u8 rsvd1[3];
+};
+
+struct hinic3_rx_mode_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u32 rx_mode;
+};
+
+/* rss */
+struct hinic3_rss_context_table {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u32 context;
+};
+
+struct hinic3_cmd_rss_engine_type {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 hash_engine;
+ u8 rsvd1[4];
+};
+
+struct hinic3_cmd_rss_hash_key {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode;
+ u8 rsvd1;
+ u8 key[NIC_RSS_KEY_SIZE];
+};
+
+struct hinic3_rss_indir_table {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 indir[NIC_RSS_INDIR_SIZE];
+};
+
+#define NIC_RSS_CMD_TEMP_ALLOC 0x01
+#define NIC_RSS_CMD_TEMP_FREE 0x02
+
+struct hinic3_rss_template_mgmt {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 cmd;
+ u8 template_id;
+ u8 rsvd1[4];
+};
+
+struct hinic3_cmd_rss_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 rss_en;
+ u8 rq_priority_number;
+ u8 prio_tc[NIC_DCB_COS_MAX];
+ u16 num_qps;
+ u16 rsvd1;
+};
+
+struct hinic3_dcb_state {
+ u8 dcb_on;
+ u8 default_cos;
+ u8 trust;
+ u8 rsvd1;
+ u8 pcp2cos[NIC_DCB_UP_MAX];
+ u8 dscp2cos[64];
+ u32 rsvd2[7];
+};
+
+struct hinic3_cmd_vf_dcb_state {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ struct hinic3_dcb_state state;
+};
+
+struct hinic3_up_ets_cfg { /* delet */
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 rsvd1[3];
+
+ u8 cos_tc[NIC_DCB_COS_MAX];
+ u8 tc_bw[NIC_DCB_TC_MAX];
+ u8 cos_prio[NIC_DCB_COS_MAX];
+ u8 cos_bw[NIC_DCB_COS_MAX];
+ u8 tc_prio[NIC_DCB_TC_MAX];
+};
+
+#define CMD_QOS_ETS_COS_TC BIT(0)
+#define CMD_QOS_ETS_TC_BW BIT(1)
+#define CMD_QOS_ETS_COS_PRIO BIT(2)
+#define CMD_QOS_ETS_COS_BW BIT(3)
+#define CMD_QOS_ETS_TC_PRIO BIT(4)
+#define CMD_QOS_ETS_TC_RATELIMIT BIT(5)
+struct hinic3_cmd_ets_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 port_id;
+ u8 op_code; /* 1 - set, 0 - get */
+ /* bit0 - cos_tc, bit1 - tc_bw, bit2 - cos_prio, bit3 - cos_bw, bit4 - tc_prio */
+ u8 cfg_bitmap;
+ u8 rsvd;
+
+ u8 cos_tc[NIC_DCB_COS_MAX];
+ u8 tc_bw[NIC_DCB_TC_MAX];
+ u8 cos_prio[NIC_DCB_COS_MAX]; /* 0 - DWRR, 1 - STRICT */
+ u8 cos_bw[NIC_DCB_COS_MAX];
+ u8 tc_prio[NIC_DCB_TC_MAX]; /* 0 - DWRR, 1 - STRICT */
+ u8 rate_limit[NIC_DCB_TC_MAX];
+};
+
+struct hinic3_cmd_set_dcb_state {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 op_code; /* 0 - get dcb state, 1 - set dcb state */
+ u8 state; /* 0 - disable, 1 - enable dcb */
+ u8 port_state; /* 0 - disable, 1 - enable dcb */
+ u8 rsvd[7];
+};
+
+#define PFC_BIT_MAP_NUM 8
+struct hinic3_cmd_set_pfc {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 port_id;
+ u8 op_code; /* 0:get 1: set pfc_en 2: set pfc_bitmap 3: set all */
+ u8 pfc_en; /* pfc_en 和 pfc_bitmap 必须同时设置 */
+ u8 pfc_bitmap;
+ u8 rsvd[4];
+};
+
+#define CMD_QOS_PORT_TRUST BIT(0)
+#define CMD_QOS_PORT_DFT_COS BIT(1)
+struct hinic3_cmd_qos_port_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 port_id;
+ u8 op_code; /* 0 - get, 1 - set */
+ u8 cfg_bitmap; /* bit0 - trust, bit1 - dft_cos */
+ u8 rsvd0;
+
+ u8 trust;
+ u8 dft_cos;
+ u8 rsvd1[18];
+};
+
+#define MAP_COS_MAX_NUM 8
+#define CMD_QOS_MAP_PCP2COS BIT(0)
+#define CMD_QOS_MAP_DSCP2COS BIT(1)
+struct hinic3_cmd_qos_map_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 op_code;
+ u8 cfg_bitmap; /* bit0 - pcp2cos, bit1 - dscp2cos */
+ u16 rsvd0;
+
+ u8 pcp2cos[8]; /* 8 must be configured together */
+ /* If the dscp2cos parameter is set to 0xFF, the MPU ignores the DSCP priority,
+ * Multiple mappings between DSCP values and CoS values can be configured at a time.
+ */
+ u8 dscp2cos[64];
+ u32 rsvd1[4];
+};
+
+struct hinic3_cos_up_map {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 cos_valid_mask; /* every bit indicate index of map is valid 1 or not 0 */
+ u16 rsvd1;
+
+ /* user priority in cos(index:cos, value: up pri) */
+ u8 map[NIC_DCB_UP_MAX];
+};
+
+struct hinic3_cmd_pause_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode;
+ u16 rsvd1;
+ u8 auto_neg;
+ u8 rx_pause;
+ u8 tx_pause;
+ u8 rsvd2[5];
+};
+
+struct nic_cmd_pause_inquiry_cfg {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 valid;
+
+ u32 type; /* 1: set, 2: get */
+
+ u32 cos_id;
+
+ u32 rx_inquiry_pause_drop_pkts_en;
+ u32 rx_inquiry_pause_period_ms;
+ u32 rx_inquiry_pause_times;
+ /* rx pause Detection Threshold, Default PAUSE_FRAME_THD_10G/25G/40G/100 */
+ u32 rx_inquiry_pause_frame_thd;
+ u32 rx_inquiry_tx_total_pkts;
+
+ u32 tx_inquiry_pause_en; /* tx pause detect enable */
+ u32 tx_inquiry_pause_period_ms; /* tx pause Default Detection Period 200ms */
+ u32 tx_inquiry_pause_times; /* tx pause Default Times Period 5 */
+ u32 tx_inquiry_pause_frame_thd; /* tx pause Detection Threshold */
+ u32 tx_inquiry_rx_total_pkts;
+ u32 rsvd[3];
+};
+
+/* pfc/pause Storm TX exception reporting */
+struct nic_cmd_tx_pause_notice {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 tx_pause_except; /* 1: abnormality,0: normal */
+ u32 except_level;
+ u32 rsvd;
+};
+
+#define HINIC3_CMD_OP_FREE 0
+#define HINIC3_CMD_OP_ALLOC 1
+
+struct hinic3_cmd_cfg_qps {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 opcode; /* 1: alloc qp, 0: free qp */
+ u8 rsvd1;
+ u16 num_qps;
+ u16 rsvd2;
+};
+
+struct hinic3_cmd_led_config {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port;
+ u8 type;
+ u8 mode;
+ u8 rsvd1;
+};
+
+struct hinic3_cmd_port_loopback {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 opcode;
+ u8 mode;
+ u8 en;
+ u32 rsvd1[2];
+};
+
+struct hinic3_cmd_get_light_module_abs {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 abs_status; /* 0:present, 1:absent */
+ u8 rsv[2];
+};
+
+#define STD_SFP_INFO_MAX_SIZE 640
+struct hinic3_cmd_get_std_sfp_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u8 port_id;
+ u8 wire_type;
+ u16 eeprom_len;
+ u32 rsvd;
+ u8 sfp_info[STD_SFP_INFO_MAX_SIZE];
+};
+
+struct hinic3_cable_plug_event {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 plugged; /* 0: unplugged, 1: plugged */
+ u8 port_id;
+};
+
+struct nic_cmd_mac_info {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 valid_bitmap;
+ u16 rsvd;
+
+ u8 host_id[32];
+ u8 port_id[32];
+ u8 mac_addr[192];
+};
+
+struct nic_cmd_set_tcam_enable {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 tcam_enable;
+ u8 rsvd1;
+ u32 rsvd2;
+};
+
+struct nic_cmd_set_fdir_status {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u16 rsvd1;
+ u8 pkt_type_en;
+ u8 pkt_type;
+ u8 qid;
+ u8 rsvd2;
+};
+
+#define HINIC3_TCAM_BLOCK_ENABLE 1
+#define HINIC3_TCAM_BLOCK_DISABLE 0
+#define HINIC3_MAX_TCAM_RULES_NUM 4096
+
+/* tcam block type, according to tcam block size */
+enum {
+ NIC_TCAM_BLOCK_TYPE_LARGE = 0, /* block_size: 16 */
+ NIC_TCAM_BLOCK_TYPE_SMALL, /* block_size: 0 */
+ NIC_TCAM_BLOCK_TYPE_MAX
+};
+
+/* alloc tcam block input struct */
+struct nic_cmd_ctrl_tcam_block_in {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id; /* func_id */
+ u8 alloc_en; /* 0: Releases the allocated TCAM block. 1: Applies for a new TCAM block */
+ /* 0: 16 size tcam block, 1: 0 size tcam block, other reserved. */
+ u8 tcam_type;
+ u16 tcam_block_index;
+ /* Size of the block that the driver wants to allocate
+ * Interface returned by the UP to the driver,
+ * indicating the size of the allocated TCAM block supported by the UP
+ */
+ u16 alloc_block_num;
+};
+
+/* alloc tcam block output struct */
+struct nic_cmd_ctrl_tcam_block_out {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id; /* func_id */
+ u8 alloc_en; /* 0: Releases the allocated TCAM block. 1: Applies for a new TCAM block */
+ /* 0: 16 size tcam block, 1: 0 size tcam block, other reserved. */
+ u8 tcam_type;
+ u16 tcam_block_index;
+ /* Size of the block that the driver wants to allocate
+ * Interface returned by the UP to the driver,
+ * indicating the size of the allocated TCAM block supported by the UP
+ */
+ u16 mpu_alloc_block_size;
+};
+
+struct nic_cmd_flush_tcam_rules {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id; /* func_id */
+ u16 rsvd;
+};
+
+struct nic_cmd_dfx_fdir_tcam_block_table {
+ struct hinic3_mgmt_msg_head head;
+ u8 tcam_type;
+ u8 valid;
+ u16 tcam_block_index;
+ u16 use_function_id;
+ u16 rsvd;
+};
+
+struct tcam_result {
+ u32 qid;
+ u32 rsvd;
+};
+
+#define TCAM_FLOW_KEY_SIZE (44)
+
+struct tcam_key_x_y {
+ u8 x[TCAM_FLOW_KEY_SIZE];
+ u8 y[TCAM_FLOW_KEY_SIZE];
+};
+
+struct nic_tcam_cfg_rule {
+ u32 index;
+ struct tcam_result data;
+ struct tcam_key_x_y key;
+};
+
+#define TCAM_RULE_FDIR_TYPE 0
+#define TCAM_RULE_PPA_TYPE 1
+
+struct nic_cmd_fdir_add_rule {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 type;
+ u8 fdir_ext; /* 0x1: flow bifur en bit */
+ struct nic_tcam_cfg_rule rule;
+};
+
+struct nic_cmd_fdir_del_rules {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 type;
+ u8 rsvd;
+ u32 index_start;
+ u32 index_num;
+};
+
+struct nic_cmd_fdir_get_rule {
+ struct hinic3_mgmt_msg_head head;
+
+ u32 index;
+ u8 valid;
+ u8 type;
+ u16 rsvd;
+ struct tcam_key_x_y key;
+ struct tcam_result data;
+ u64 packet_count;
+ u64 byte_count;
+};
+
+struct nic_cmd_fdir_get_block_rules {
+ struct hinic3_mgmt_msg_head head;
+ u8 tcam_block_type; // only NIC_TCAM_BLOCK_TYPE_LARGE
+ u8 tcam_table_type; // TCAM_RULE_PPA_TYPE or TCAM_RULE_FDIR_TYPE
+ u16 tcam_block_index;
+ u8 valid[NIC_TCAM_BLOCK_LARGE_SIZE];
+ struct tcam_key_x_y key[NIC_TCAM_BLOCK_LARGE_SIZE];
+ struct tcam_result data[NIC_TCAM_BLOCK_LARGE_SIZE];
+};
+
+struct hinic3_tcam_key_ipv4_mem {
+ u32 rsvd1 : 1;
+ u32 bifur_flag : 2;
+ u32 model : 1;
+ u32 tunnel_type : 4;
+ u32 ip_proto : 8;
+ u32 rsvd0 : 16;
+ u32 sipv4_h : 16;
+ u32 ip_type : 1;
+ u32 function_id : 15;
+ u32 dipv4_h : 16;
+ u32 sipv4_l : 16;
+ u32 vlan_id : 15;
+ u32 vlan_flag : 1;
+ u32 dipv4_l : 16;
+ u32 rsvd3;
+ u32 dport : 16;
+ u32 rsvd4 : 16;
+ u32 rsvd5 : 16;
+ u32 sport : 16;
+ u32 outer_sipv4_h : 16;
+ u32 rsvd6 : 16;
+ u32 outer_dipv4_h : 16;
+ u32 outer_sipv4_l : 16;
+ u32 vni_h : 16;
+ u32 outer_dipv4_l : 16;
+ u32 rsvd7 : 16;
+ u32 vni_l : 16;
+};
+
+union hinic3_tag_tcam_ext_info {
+ struct {
+ u32 id : 16; /* id */
+ u32 type : 4; /* type: 0-func, 1-vmdq, 2-port, 3-rsvd, 4-trunk, 5-dp, 6-mc */
+ u32 host_id : 3;
+ u32 rss_q_num : 8; /* rss queue num */
+ u32 ext : 1;
+ } bs;
+ u32 value;
+};
+
+struct hinic3_tcam_key_ipv6_mem {
+ u32 bifur_flag : 2;
+ u32 vlan_flag : 1;
+ u32 outer_ip_type : 1;
+ u32 tunnel_type : 4;
+ u32 ip_proto : 8;
+ u32 rsvd0 : 16;
+ u32 sipv6_key0 : 16;
+ u32 ip_type : 1;
+ u32 function_id : 15;
+ u32 sipv6_key2 : 16;
+ u32 sipv6_key1 : 16;
+ u32 sipv6_key4 : 16;
+ u32 sipv6_key3 : 16;
+ u32 sipv6_key6 : 16;
+ u32 sipv6_key5 : 16;
+ u32 dport : 16;
+ u32 sipv6_key7 : 16;
+ u32 dipv6_key0 : 16;
+ u32 sport : 16;
+ u32 dipv6_key2 : 16;
+ u32 dipv6_key1 : 16;
+ u32 dipv6_key4 : 16;
+ u32 dipv6_key3 : 16;
+ u32 dipv6_key6 : 16;
+ u32 dipv6_key5 : 16;
+ u32 rsvd2 : 16;
+ u32 dipv6_key7 : 16;
+};
+
+struct hinic3_tcam_key_vxlan_ipv6_mem {
+ u32 rsvd1 : 4;
+ u32 tunnel_type : 4;
+ u32 ip_proto : 8;
+ u32 rsvd0 : 16;
+
+ u32 dipv6_key0 : 16;
+ u32 ip_type : 1;
+ u32 function_id : 15;
+
+ u32 dipv6_key2 : 16;
+ u32 dipv6_key1 : 16;
+
+ u32 dipv6_key4 : 16;
+ u32 dipv6_key3 : 16;
+
+ u32 dipv6_key6 : 16;
+ u32 dipv6_key5 : 16;
+
+ u32 dport : 16;
+ u32 dipv6_key7 : 16;
+
+ u32 rsvd2 : 16;
+ u32 sport : 16;
+
+ u32 outer_sipv4_h : 16;
+ u32 rsvd3 : 16;
+
+ u32 outer_dipv4_h : 16;
+ u32 outer_sipv4_l : 16;
+
+ u32 vni_h : 16;
+ u32 outer_dipv4_l : 16;
+
+ u32 rsvd4 : 16;
+ u32 vni_l : 16;
+};
+
+struct tag_tcam_key {
+ union {
+ struct hinic3_tcam_key_ipv4_mem key_info;
+ struct hinic3_tcam_key_ipv6_mem key_info_ipv6;
+ struct hinic3_tcam_key_vxlan_ipv6_mem key_info_vxlan_ipv6;
+ };
+
+ union {
+ struct hinic3_tcam_key_ipv4_mem key_mask;
+ struct hinic3_tcam_key_ipv6_mem key_mask_ipv6;
+ struct hinic3_tcam_key_vxlan_ipv6_mem key_mask_vxlan_ipv6;
+ };
+};
+
+enum {
+ PPA_TABLE_ID_CLEAN_CMD = 0,
+ PPA_TABLE_ID_ADD_CMD,
+ PPA_TABLE_ID_DEL_CMD,
+ FDIR_TABLE_ID_ADD_CMD,
+ FDIR_TABLE_ID_DEL_CMD,
+ PPA_TABEL_ID_MAX
+};
+
+struct hinic3_ppa_cfg_table_id_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 rsvd0;
+ u16 cmd;
+ u16 table_id;
+ u16 rsvd1;
+};
+
+struct hinic3_ppa_cfg_ppa_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 func_id;
+ u8 ppa_en;
+ u8 ppa_miss_drop_en;
+};
+
+struct hinic3_func_flow_bifur_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+ u16 func_id;
+ u8 flow_bifur_en;
+ u8 rsvd[5];
+};
+
+struct hinic3_port_flow_bifur_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+ u16 port_id;
+ u8 flow_bifur_en;
+ u8 flow_bifur_type; /* 0->vf bifur, 2->traffic bifur */
+ u8 rsvd[4];
+};
+
+struct hinic3_bond_mask_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+ u16 func_id;
+ u8 bond_mask;
+ u8 bond_en;
+ u8 func_valid;
+ 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;
+ u8 promisc_skip_en; /* 0: disable tx promisc replication, 1: enable */
+ u8 opcode; /* 0: set, 1: get */
+ u8 rsvd1;
+};
+
+struct hinic3_ppa_cfg_mode_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 rsvd0;
+ u8 ppa_mode;
+ u8 qpc_func_nums;
+ u16 base_qpc_func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_ppa_flush_en_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 rsvd0;
+ u8 flush_en; /* 0 flush done, 1 in flush operation */
+ u8 rsvd1;
+};
+
+struct hinic3_ppa_fdir_query_cmd {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u32 index;
+ u32 rsvd;
+ u64 pkt_nums;
+ u64 pkt_bytes;
+};
+
+/* BIOS CONF */
+enum {
+ NIC_NVM_DATA_SET = BIT(0), /* 1-save, 0-read */
+ NIC_NVM_DATA_PXE = BIT(1),
+ NIC_NVM_DATA_VLAN = BIT(2),
+ NIC_NVM_DATA_VLAN_PRI = BIT(3),
+ NIC_NVM_DATA_VLAN_ID = BIT(4),
+ NIC_NVM_DATA_WORK_MODE = BIT(5),
+ NIC_NVM_DATA_PF_TX_SPEED_LIMIT = BIT(6),
+ NIC_NVM_DATA_GE_MODE = BIT(7),
+ NIC_NVM_DATA_AUTO_NEG = BIT(8),
+ NIC_NVM_DATA_LINK_FEC = BIT(9),
+ NIC_NVM_DATA_PF_ADAPTIVE_LINK = BIT(10),
+ NIC_NVM_DATA_SRIOV_CONTROL = BIT(11),
+ NIC_NVM_DATA_EXTEND_MODE = BIT(12),
+ NIC_NVM_DATA_LEGACY_VLAN = BIT(13),
+ NIC_NVM_DATA_LEGACY_VLAN_PRI = BIT(14),
+ NIC_NVM_DATA_LEGACY_VLAN_ID = BIT(15),
+ NIC_NVM_DATA_RESET = BIT(31),
+};
+
+#define BIOS_CFG_SIGNATURE 0x1923E518
+#define BIOS_OP_CFG_ALL(op_code_val) \
+ ((((op_code_val) >> 1) & (0xFFFFFFFF)) != 0)
+#define BIOS_OP_CFG_WRITE(op_code_val) \
+ ((((op_code_val) & NIC_NVM_DATA_SET)) != 0)
+#define BIOS_OP_CFG_PXE_EN(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_PXE) != 0)
+#define BIOS_OP_CFG_VLAN_EN(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_VLAN) != 0)
+#define BIOS_OP_CFG_VLAN_PRI(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_VLAN_PRI) != 0)
+#define BIOS_OP_CFG_VLAN_ID(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_VLAN_ID) != 0)
+#define BIOS_OP_CFG_WORK_MODE(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_WORK_MODE) != 0)
+#define BIOS_OP_CFG_PF_BW(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_PF_TX_SPEED_LIMIT) != 0)
+#define BIOS_OP_CFG_GE_SPEED(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_GE_MODE) != 0)
+#define BIOS_OP_CFG_AUTO_NEG(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_AUTO_NEG) != 0)
+#define BIOS_OP_CFG_LINK_FEC(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LINK_FEC) != 0)
+#define BIOS_OP_CFG_AUTO_ADPAT(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_PF_ADAPTIVE_LINK) != 0)
+#define BIOS_OP_CFG_SRIOV_ENABLE(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_SRIOV_CONTROL) != 0)
+#define BIOS_OP_CFG_EXTEND_MODE(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_EXTEND_MODE) != 0)
+#define BIOS_OP_CFG_LEGACY_VLAN_EN(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LEGACY_VLAN) != 0)
+#define BIOS_OP_CFG_LEGACY_VLAN_PRI(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LEGACY_VLAN_PRI) != 0)
+#define BIOS_OP_CFG_LEGACY_VLAN_ID(op_code_val) \
+ (((op_code_val) & NIC_NVM_DATA_LEGACY_VLAN_ID) != 0)
+#define BIOS_OP_CFG_RST_DEF_SET(op_code_val) \
+ (((op_code_val) & (u32)NIC_NVM_DATA_RESET) != 0)
+
+
+#define NIC_BIOS_CFG_MAX_PF_BW 100
+
+struct nic_legacy_vlan_cfg {
+ /* Legacy mode PXE VLAN enable: 0 - disable 1 - enable */
+ u8 pxe_vlan_en : 1;
+ /* Legacy mode PXE VLAN priority: 0-7 */
+ u8 pxe_vlan_pri : 3;
+ /* Legacy mode PXE VLAN ID 1-4094 */
+ u16 pxe_vlan_id : 12;
+};
+
+/* Note: This structure must be 4-byte aligned. */
+struct nic_bios_cfg {
+ u32 signature;
+ u8 pxe_en;
+ u8 extend_mode;
+ struct nic_legacy_vlan_cfg nlvc;
+ u8 pxe_vlan_en;
+ u8 pxe_vlan_pri;
+ u16 pxe_vlan_id;
+ u32 service_mode;
+ u32 pf_tx_bw;
+ u8 speed;
+ u8 auto_neg;
+ u8 lanes;
+ u8 fec;
+ u8 auto_adapt;
+ u8 func_valid;
+ u8 func_id;
+ u8 sriov_en;
+};
+
+struct nic_cmd_bios_cfg {
+ struct hinic3_mgmt_msg_head head;
+ u32 op_code; /* Operation Code: Bit0[0: read 1:write, BIT1-6: cfg_mask */
+ struct nic_bios_cfg bios_cfg;
+};
+
+struct nic_rx_rate_bios_cfg {
+ struct mgmt_msg_head msg_head;
+
+ u32 op_code; /* Operation Code:[0:read 1:write] */
+ u8 rx_rate_limit;
+ u8 func_id;
+};
+
+struct nic_cmd_vhd_config {
+ struct hinic3_mgmt_msg_head head;
+
+ u16 func_id;
+ u8 vhd_type;
+ u8 virtio_small_enable; /* 0: mergeable mode, 1: small mode */
+};
+
+/* BOND */
+struct hinic3_create_bond_info {
+ u32 bond_id;
+ u32 master_slave_port_id;
+ u32 slave_bitmap; /* bond port id bitmap */
+ u32 poll_timeout; /* Bond device link check time */
+ u32 up_delay; /* Temporarily reserved */
+ u32 down_delay; /* Temporarily reserved */
+ u32 bond_mode; /* Temporarily reserved */
+ u32 active_pf; /* bond use active pf id */
+ u32 active_port_max_num; /* Maximum number of active bond member interfaces */
+ u32 active_port_min_num; /* Minimum number of active bond member interfaces */
+ u32 xmit_hash_policy;
+ u32 default_param_flag;
+ u32 rsvd;
+};
+
+struct hinic3_cmd_create_bond {
+ struct hinic3_mgmt_msg_head head;
+ struct hinic3_create_bond_info create_bond_info;
+};
+
+struct hinic3_cmd_delete_bond {
+ struct hinic3_mgmt_msg_head head;
+ u32 bond_id;
+ u32 rsvd[2];
+};
+
+struct hinic3_open_close_bond_info {
+ u32 bond_id;
+ u32 open_close_flag; /* Bond flag. 1: open; 0: close. */
+ u32 rsvd[2];
+};
+
+struct hinic3_cmd_open_close_bond {
+ struct hinic3_mgmt_msg_head head;
+ struct hinic3_open_close_bond_info open_close_bond_info;
+};
+
+struct lacp_port_params {
+ u16 port_number;
+ u16 port_priority;
+ u16 key;
+ u16 system_priority;
+ u8 system[ETH_ALEN];
+ u8 port_state;
+ u8 rsvd;
+};
+
+struct lacp_port_info {
+ u32 selected;
+ u32 aggregator_port_id;
+
+ struct lacp_port_params actor;
+ struct lacp_port_params partner;
+
+ u64 tx_lacp_pkts;
+ u64 rx_lacp_pkts;
+ u64 rx_8023ad_drop;
+ u64 tx_8023ad_drop;
+ u64 unknown_pkt_drop;
+ u64 rx_marker_pkts;
+ u64 tx_marker_pkts;
+};
+
+struct hinic3_bond_status_info {
+ struct hinic3_mgmt_msg_head head;
+ u32 bond_id;
+ u32 bon_mmi_status;
+ u32 active_bitmap;
+ u32 port_count;
+
+ struct lacp_port_info port_info[4];
+
+ u64 success_report_cnt[4];
+ u64 fail_report_cnt[4];
+
+ u64 poll_timeout;
+ u64 fast_periodic_timeout;
+ u64 slow_periodic_timeout;
+ u64 short_timeout;
+ u64 long_timeout;
+ u64 aggregate_wait_timeout;
+ u64 tx_period_timeout;
+ u64 rx_marker_timer;
+};
+
+struct hinic3_bond_active_report_info {
+ struct hinic3_mgmt_msg_head head;
+ u32 bond_id;
+ u32 bon_mmi_status;
+ u32 active_bitmap;
+
+ u8 rsvd[16];
+};
+
+/* IP checksum error packets, enable rss quadruple hash. */
+struct hinic3_ipcs_err_rss_enable_operation_s {
+ struct hinic3_mgmt_msg_head head;
+
+ u8 en_tag;
+ u8 type; /* 1: set 0: get */
+ u8 rsvd[2];
+};
+
+struct hinic3_smac_check_state {
+ struct hinic3_mgmt_msg_head head;
+ u8 smac_check_en; /* 1: enable 0: disable */
+ u8 op_code; /* 1: set 0: get */
+ u8 flash_en; /* 1: enable 0: disable */
+ u8 rsvd;
+};
+
+struct hinic3_clear_log_state {
+ struct hinic3_mgmt_msg_head head;
+ u32 type;
+};
+
+struct hinic3_outband_cfg_info {
+ struct hinic3_mgmt_msg_head msg_head;
+
+ u16 outband_default_vid;
+ u16 func_id;
+};
+
+struct hinic3_wr_ordering {
+ struct hinic3_mgmt_msg_head head;
+ u8 op_code; /* 1: set 0: get */
+ u8 wr_pkt_so_ro;
+ u8 rd_pkt_so_ro;
+ u8 rsvd;
+};
+
+struct hinic3_function_active_info {
+ struct hinic3_mgmt_msg_head head;
+ u16 func_id;
+ u16 rsvd1;
+};
+
+struct hinic3_rq_info {
+ struct hinic3_mgmt_msg_head head;
+ u16 func_id;
+ u16 rq_depth;
+ u16 rq_num;
+ u16 pf_num;
+ u16 port_num;
+};
+
+#endif /* HINIC_MGMT_INTERFACE_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h b/drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h
new file mode 100644
index 0000000..3e625fc
--- /dev/null
+++ b/drivers/net/ethernet/huawei/hinic3/nic_npu_cmd.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C), 2001-2011, Huawei Tech. Co., Ltd.
+ * File Name : nic_npu_cmd.h
+ * Version : Initial Draft
+ * Created : 2019/4/25
+ * Last Modified :
+ * Description : NIC Commands between Driver and NPU
+ * Function List :
+ */
+
+#ifndef NIC_NPU_CMD_H
+#define NIC_NPU_CMD_H
+
+/* NIC CMDQ MODE */
+enum hinic3_ucode_cmd {
+ HINIC3_UCODE_CMD_MODIFY_QUEUE_CTX = 0,
+ HINIC3_UCODE_CMD_CLEAN_QUEUE_CONTEXT,
+ HINIC3_UCODE_CMD_ARM_SQ, /**< Unused */
+ HINIC3_UCODE_CMD_ARM_RQ, /**< Unused */
+ HINIC3_UCODE_CMD_SET_RSS_INDIR_TABLE,
+ 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,
+ HINIC3_UCODE_CMD_MODIFY_VLAN_CTX,
+ HINIC3_UCODE_CMD_PPA_HASH_TABLE,
+ HINIC3_UCODE_CMD_RXQ_INFO_GET = 13,
+ HINIC3_UCODE_MIG_CFG_Q_CTX = 14,
+ HINIC3_UCODE_MIG_CHK_SQ_STOP,
+ HINIC3_UCODE_CHK_RQ_STOP,
+ HINIC3_UCODE_MIG_CFG_BAT_INFO,
+};
+
+#endif /* NIC_NPU_CMD_H */
diff --git a/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h b/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h
index 78a8d7f..66f4305 100644
--- a/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h
+++ b/drivers/net/ethernet/huawei/hinic3/ossl_knl_linux.h
@@ -5,6 +5,7 @@
#define OSSL_KNL_LINUX_H_
#include <net/ipv6.h>
+#include <net/devlink.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/device.h>
@@ -18,6 +19,12 @@
#include <linux/list.h>
#include <linux/bitmap.h>
#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/filter.h>
+#include <linux/aer.h>
+#include <linux/socket.h>
#ifndef NETIF_F_SCTP_CSUM
#define NETIF_F_SCTP_CSUM 0
@@ -173,12 +180,10 @@ static inline void *_hinic3_dma_zalloc_coherent(struct device *dev,
}
#endif
-#ifndef DT_KNL_EMU
struct timeval {
__kernel_old_time_t tv_sec; /* seconds */
__kernel_suseconds_t tv_usec; /* microseconds */
};
-#endif
#ifndef do_gettimeofday
#define do_gettimeofday(time) _kc_do_gettimeofday(time)
@@ -196,6 +201,10 @@ static inline void _kc_do_gettimeofday(struct timeval *tv)
#define ETH_GET_HEADLEN_NEED_DEV
#define HAVE_GENL_OPS_FIELD_VALIDATE
+#ifndef FIELD_SIZEOF
+#define FIELD_SIZEOF(t, f) (sizeof(((t *)0)->f))
+#endif
+
#define HAVE_DEVLINK_FLASH_UPDATE_PARAMS
#ifndef rtc_time_to_tm
@@ -253,12 +262,12 @@ static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
size, vaddr, dma_handle);
}
-#define HAVE_DEVLINK_FW_FILE_NAME_MEMBER
-
#define HAVE_ENCAPSULATION_TSO
#define HAVE_ENCAPSULATION_CSUM
+#define HAVE_UDP_TUNNEL_NIC_INFO
+
#ifndef eth_zero_addr
static inline void hinic3_eth_zero_addr(u8 *addr)
{
@@ -333,4 +342,15 @@ u64 ossl_get_real_time(void);
#define tasklet_state(tasklet) ((tasklet)->state)
+dma_addr_t pci_map_single(struct pci_dev *pdev,
+ void *ptr, size_t size, int direction);
+int pci_dma_mapping_error(struct pci_dev *pdev,
+ dma_addr_t dma_addr);
+void pci_unmap_single(struct pci_dev *pdev,
+ dma_addr_t dma_addr, size_t size, int direction);
+void *pci_alloc_consistent(struct pci_dev *pdev,
+ size_t size, dma_addr_t *dma_handle);
+void pci_free_consistent(struct pci_dev *pdev,
+ size_t size, void *vaddr, dma_addr_t dma_handle);
+
#endif
--
2.45.1.windows.1
2
1

09 May '25
From: Chenyuan Yang <chenyuan0y(a)gmail.com>
stable inclusion
from stable-v6.6.88
commit c17ef974bfcf1a50818168b47c4606b425a957c4
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IC5BKW
CVE: CVE-2025-37755
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
[ Upstream commit 7f1ff1b38a7c8b872382b796023419d87d78c47e ]
page_pool_dev_alloc_pages could return NULL. There was a WARN_ON(!page)
but it would still proceed to use the NULL pointer and then crash.
This is similar to commit 001ba0902046
("net: fec: handle page_pool_dev_alloc_pages error").
This is found by our static analysis tool KNighter.
Signed-off-by: Chenyuan Yang <chenyuan0y(a)gmail.com>
Fixes: 3c47e8ae113a ("net: libwx: Support to receive packets in NAPI")
Reviewed-by: Joe Damato <jdamato(a)fastly.com>
Link: https://patch.msgid.link/20250407184952.2111299-1-chenyuan0y@gmail.com
Signed-off-by: Jakub Kicinski <kuba(a)kernel.org>
Signed-off-by: Sasha Levin <sashal(a)kernel.org>
Signed-off-by: Yuntao Liu <liuyuntao12(a)huawei.com>
---
drivers/net/ethernet/wangxun/libwx/wx_lib.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
index 3b120d078793..c0ae843fed54 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c
@@ -311,7 +311,8 @@ static bool wx_alloc_mapped_page(struct wx_ring *rx_ring,
return true;
page = page_pool_dev_alloc_pages(rx_ring->page_pool);
- WARN_ON(!page);
+ if (unlikely(!page))
+ return false;
dma = page_pool_get_dma_addr(page);
bi->page_dma = dma;
--
2.34.1
2
1

[openeuler:OLK-5.10 2891/2891] versioncheck: ./drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c: 682: need linux/version.h
by kernel test robot 09 May '25
by kernel test robot 09 May '25
09 May '25
tree: https://gitee.com/openeuler/kernel.git OLK-5.10
head: 2e5032bf08eca1f3b062773540ff27c51788390d
commit: 79871cd2cd720225eb582c9ed49fb4a96a270b3b [2891/2891] net/hinic3: Synchronize new NIC features and bug fixes
reproduce: (https://download.01.org/0day-ci/archive/20250509/202505091231.o5lexadJ-lkp@…)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp(a)intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505091231.o5lexadJ-lkp@intel.com/
versioncheck warnings: (new ones prefixed by >>)
INFO PATH=/opt/cross/rustc-1.58.0-bindgen-0.56.0/cargo/bin:/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
/usr/bin/timeout -k 100 3h /usr/bin/make KCFLAGS= -Wno-error=return-type -Wreturn-type -funsigned-char -Wundef W=1 --keep-going LLVM=1 -j32 ARCH=x86_64 versioncheck
find ./* \( -name SCCS -o -name BitKeeper -o -name .svn -o -name CVS -o -name .pc -o -name .hg -o -name .git \) -prune -o \
-name '*.[hcS]' -type f -print | sort \
| xargs perl -w ./scripts/checkversion.pl
./arch/csky/include/asm/atomic.h: 6 linux/version.h not needed.
./arch/csky/include/asm/io.h: 9 linux/version.h not needed.
./arch/csky/include/asm/thread_info.h: 9 linux/version.h not needed.
./arch/csky/include/asm/uaccess.h: 15 linux/version.h not needed.
./arch/csky/kernel/process.c: 5 linux/version.h not needed.
./arch/csky/mm/dma-mapping.c: 12 linux/version.h not needed.
./arch/csky/mm/fault.c: 16 linux/version.h not needed.
./arch/s390/include/asm/setup.h: 183: need linux/version.h
./arch/um/drivers/vector_kern.c: 11 linux/version.h not needed.
./drivers/block/rsxx/rsxx_priv.h: 14 linux/version.h not needed.
./drivers/char/ipmi/ipmi_si_ls2k500.c: 19 linux/version.h not needed.
./drivers/crypto/cavium/cpt/cptpf_main.c: 13 linux/version.h not needed.
./drivers/crypto/cavium/zip/common.h: 59 linux/version.h not needed.
./drivers/crypto/ccree/cc_driver.h: 26 linux/version.h not needed.
./drivers/crypto/montage/tsse/tsse_vuart.c: 21 linux/version.h not needed.
./drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c: 62 linux/version.h not needed.
./drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c: 28 linux/version.h not needed.
./drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c: 26 linux/version.h not needed.
./drivers/gpu/drm/inspur/inspur_drm_de.c: 513: need linux/version.h
./drivers/gpu/drm/inspur/inspur_drm_drv.c: 456: need linux/version.h
./drivers/gpu/drm/pl111/pl111_display.c: 14 linux/version.h not needed.
./drivers/gpu/drm/pl111/pl111_drv.c: 47 linux/version.h not needed.
./drivers/gpu/drm/tve200/tve200_display.c: 14 linux/version.h not needed.
./drivers/gpu/drm/tve200/tve200_drv.c: 38 linux/version.h not needed.
./drivers/hv/hv.c: 16 linux/version.h not needed.
./drivers/i2c/busses/i2c-brcmstb.c: 25 linux/version.h not needed.
./drivers/i2c/busses/i2c-xgene-slimpro.c: 22 linux/version.h not needed.
./drivers/media/pci/cx25821/cx25821.h: 31 linux/version.h not needed.
./drivers/media/platform/s3c-camif/camif-core.c: 26 linux/version.h not needed.
./drivers/media/platform/sti/c8sectpfe/c8sectpfe-common.h: 16 linux/version.h not needed.
./drivers/media/platform/sti/c8sectpfe/c8sectpfe-core.c: 31 linux/version.h not needed.
./drivers/media/platform/sti/c8sectpfe/c8sectpfe-dvb.c: 14 linux/version.h not needed.
./drivers/media/usb/uvc/uvc_driver.c: 18 linux/version.h not needed.
./drivers/net/ethernet/3snic/sssnic/include/kernel/sss_linux_kernel.h: 12 linux/version.h not needed.
./drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c: 21 linux/version.h not needed.
./drivers/net/ethernet/huawei/bma/edma_drv/bma_include.h: 32 linux/version.h not needed.
./drivers/net/ethernet/huawei/bma/edma_drv/bma_pci.c: 17 linux/version.h not needed.
./drivers/net/ethernet/huawei/bma/kbox_drv/kbox_include.h: 20 linux/version.h not needed.
./drivers/net/ethernet/huawei/bma/kbox_drv/kbox_main.c: 22 linux/version.h not needed.
./drivers/net/ethernet/huawei/bma/kbox_drv/kbox_mce.c: 16 linux/version.h not needed.
./drivers/net/ethernet/huawei/bma/kbox_drv/kbox_ram_op.c: 16 linux/version.h not needed.
./drivers/net/ethernet/huawei/hinic/ossl_knl.h: 22 linux/version.h not needed.
./drivers/net/ethernet/huawei/hinic3/bond/hinic3_bond.c: 12 linux/version.h not needed.
>> ./drivers/net/ethernet/huawei/hinic3/cqm/cqm_memsec.c: 682: need linux/version.h
./drivers/net/ethernet/linkdata/sxe/base/compat/sxe_compat.h: 16 linux/version.h not needed.
./drivers/net/ethernet/linkdata/sxevf/base/compat/sxe_compat.h: 16 linux/version.h not needed.
./drivers/net/ethernet/mucse/rnpm/rnpm_common.h: 7 linux/version.h not needed.
./drivers/net/ethernet/nebula-matrix/m1600/common.h: 12 linux/version.h not needed.
./drivers/net/ethernet/nebula-matrix/m1600/txrx.c: 9 linux/version.h not needed.
./drivers/net/ethernet/qlogic/qede/qede.h: 10 linux/version.h not needed.
./drivers/net/ethernet/qlogic/qede/qede_ethtool.c: 7 linux/version.h not needed.
./drivers/net/ethernet/qlogic/qede/qede_main.c: 10 linux/version.h not needed.
./drivers/net/ethernet/yunsilicon/xsc/common/xsc_core.h: 26 linux/version.h not needed.
./drivers/net/usb/lan78xx.c: 5 linux/version.h not needed.
./drivers/net/wireless/rsi/rsi_91x_ps.c: 19 linux/version.h not needed.
./drivers/scsi/cxgbi/libcxgbi.h: 27 linux/version.h not needed.
./drivers/scsi/hisi_raid/hiraid_main.c: 9 linux/version.h not needed.
./drivers/scsi/huawei/hifc/hifc_knl_adp.h: 23 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/linux/ps3_base.c: 12 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/linux/ps3_cli.c: 15 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/linux/ps3_driver_log.c: 4 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/ps3_device_manager.h: 10 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/ps3_device_manager_sas.h: 7 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/ps3_qos.c: 7 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/ps3_rb_tree.h: 8 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/ps3_sas_transport.h: 10 linux/version.h not needed.
./drivers/scsi/linkdata/ps3stor/ps3_scsi_cmd_err.c: 10 linux/version.h not needed.
./drivers/scsi/qedf/qedf.h: 15 linux/version.h not needed.
./drivers/scsi/qedf/qedf_dbg.h: 13 linux/version.h not needed.
./drivers/scsi/qedi/qedi_dbg.h: 14 linux/version.h not needed.
./drivers/scsi/sssraid/sssraid_fw.c: 6 linux/version.h not needed.
./drivers/scsi/sssraid/sssraid_os.c: 6 linux/version.h not needed.
./drivers/soc/tegra/powergate-bpmp.c: 10 linux/version.h not needed.
./drivers/staging/media/atomisp/include/linux/atomisp.h: 23 linux/version.h not needed.
./drivers/staging/rtl8723bs/include/drv_types.h: 17 linux/version.h not needed.
./drivers/staging/rtl8723bs/include/ioctl_cfg80211.h: 10 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_cdev_file.c: 23 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_device.c: 33 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_genl.c: 26 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_genl_admin.c: 20 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_main.c: 28 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_tp.c: 26 linux/version.h not needed.
./drivers/ub/urma/ubcore/ubcore_umem.c: 26 linux/version.h not needed.
./drivers/ub/urma/uburma/uburma_main.c: 29 linux/version.h not needed.
./drivers/ub/urma/uburma/uburma_mmap.c: 21 linux/version.h not needed.
./drivers/watchdog/ziirave_wdt.c: 21 linux/version.h not needed.
./fs/eulerfs/euler.h: 20 linux/version.h not needed.
./fs/eulerfs/euler_common.h: 25 linux/version.h not needed.
./fs/proc/etmem_scan.c: 13 linux/version.h not needed.
./include/linux/qed/qed_ll2_if.h: 15 linux/version.h not needed.
./kernel/bpf/syscall.c: 20 linux/version.h not needed.
./samples/bpf/sampleip_kern.c: 7 linux/version.h not needed.
./samples/bpf/trace_event_kern.c: 8 linux/version.h not needed.
./sound/soc/codecs/cs35l35.c: 12 linux/version.h not needed.
./sound/soc/codecs/cs42l42.c: 14 linux/version.h not needed.
./tools/lib/bpf/libbpf_sched.h: 21 linux/version.h not needed.
./tools/perf/include/bpf/bpf.h: 70: need linux/version.h
./tools/perf/tests/bpf-script-example.c: 49: need linux/version.h
./tools/perf/tests/bpf-script-test-kbuild.c: 21: need linux/version.h
./tools/perf/tests/bpf-script-test-prologue.c: 47: need linux/version.h
./tools/perf/tests/bpf-script-test-relocation.c: 51: need linux/version.h
./tools/testing/selftests/bpf/progs/test_map_lock.c: 4 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_send_signal_kern.c: 4 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_spin_lock.c: 4 linux/version.h not needed.
./tools/testing/selftests/bpf/progs/test_tcp_estats.c: 37 linux/version.h not needed.
./tools/testing/selftests/wireguard/qemu/init.c: 25 linux/version.h not needed.
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
1
0
Support fuse fastpath by using the newly added fast_ipc module.
chenrenhui (2):
ipc: add fast_ipc module to enable fast process switching
fuse: support fastpath via fast_ipc
Kconfig | 2 +
arch/arm64/configs/openeuler_defconfig | 2 +
arch/x86/configs/openeuler_defconfig | 2 +
fs/fuse/Kconfig | 9 +
fs/fuse/dev.c | 744 +++++++++++++++++++++++++
fs/fuse/dir.c | 87 ++-
fs/fuse/file.c | 235 +++++++-
fs/fuse/fuse_i.h | 55 ++
fs/fuse/inode.c | 112 ++++
fs/fuse/readdir.c | 8 +
include/linux/fast_ipc.h | 48 ++
include/uapi/linux/fuse.h | 15 +-
ipc/Kconfig | 5 +
ipc/Makefile | 2 +-
ipc/fast_ipc.c | 299 ++++++++++
15 files changed, 1597 insertions(+), 28 deletions(-)
create mode 100644 include/linux/fast_ipc.h
create mode 100644 ipc/Kconfig
create mode 100644 ipc/fast_ipc.c
--
2.33.0
2
3