hinic3: Add .ndo_vlan_rx_add/kill_vid and .ndo_validate_addr

Implement following callback function:
.ndo_vlan_rx_add_vid
.ndo_vlan_rx_kill_vid
.ndo_validate_addr

Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/70be187afcaa7b38981d114c088ffdc2cba0b4f1.1768375903.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Fan Gong
2026-01-14 16:38:25 +08:00
committed by Paolo Abeni
parent 2467a04660
commit 0f9e2d9574
6 changed files with 128 additions and 0 deletions

View File

@@ -137,11 +137,17 @@ static int hinic3_init_nic_dev(struct net_device *netdev,
nic_dev->rx_buf_len = HINIC3_RX_BUF_LEN;
nic_dev->lro_replenish_thld = HINIC3_LRO_REPLENISH_THLD;
nic_dev->vlan_bitmap = kzalloc(HINIC3_VLAN_BITMAP_SIZE(nic_dev),
GFP_KERNEL);
if (!nic_dev->vlan_bitmap)
return -ENOMEM;
nic_dev->nic_svc_cap = hwdev->cfg_mgmt->cap.nic_svc_cap;
nic_dev->workq = create_singlethread_workqueue(HINIC3_NIC_DEV_WQ_NAME);
if (!nic_dev->workq) {
dev_err(hwdev->dev, "Failed to initialize nic workqueue\n");
kfree(nic_dev->vlan_bitmap);
return -ENOMEM;
}
@@ -335,6 +341,7 @@ static void hinic3_nic_event(struct auxiliary_device *adev,
static void hinic3_free_nic_dev(struct hinic3_nic_dev *nic_dev)
{
destroy_workqueue(nic_dev->workq);
kfree(nic_dev->vlan_bitmap);
}
static int hinic3_nic_probe(struct auxiliary_device *adev,

View File

@@ -56,6 +56,15 @@ struct l2nic_cmd_update_mac {
u8 new_mac[ETH_ALEN];
};
struct l2nic_cmd_vlan_config {
struct mgmt_msg_head msg_head;
u16 func_id;
u8 opcode;
u8 rsvd1;
u16 vlan_id;
u16 rsvd2;
};
struct l2nic_cmd_vlan_offload {
struct mgmt_msg_head msg_head;
u16 func_id;
@@ -205,6 +214,7 @@ enum l2nic_cmd {
L2NIC_CMD_SET_MAC = 21,
L2NIC_CMD_DEL_MAC = 22,
L2NIC_CMD_UPDATE_MAC = 23,
L2NIC_CMD_CFG_FUNC_VLAN = 25,
L2NIC_CMD_SET_VLAN_FILTER_EN = 26,
L2NIC_CMD_SET_RX_VLAN_OFFLOAD = 27,
L2NIC_CMD_CFG_RSS = 60,

View File

@@ -17,6 +17,12 @@
#define HINIC3_LRO_DEFAULT_COAL_PKT_SIZE 32
#define HINIC3_LRO_DEFAULT_TIME_LIMIT 16
#define VLAN_BITMAP_BITS_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bitmap) * 8)
#define VID_LINE(nic_dev, vid) \
((vid) / VLAN_BITMAP_BITS_SIZE(nic_dev))
#define VID_COL(nic_dev, vid) \
((vid) & (VLAN_BITMAP_BITS_SIZE(nic_dev) - 1))
/* try to modify the number of irq to the target number,
* and return the actual number of irq.
*/
@@ -688,6 +694,59 @@ static int hinic3_set_mac_addr(struct net_device *netdev, void *addr)
return 0;
}
static int hinic3_vlan_rx_add_vid(struct net_device *netdev,
__be16 proto, u16 vid)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
unsigned long *vlan_bitmap = nic_dev->vlan_bitmap;
u32 column, row;
u16 func_id;
int err;
column = VID_COL(nic_dev, vid);
row = VID_LINE(nic_dev, vid);
func_id = hinic3_global_func_id(nic_dev->hwdev);
err = hinic3_add_vlan(nic_dev->hwdev, vid, func_id);
if (err) {
netdev_err(netdev, "Failed to add vlan %u\n", vid);
goto out;
}
set_bit(column, &vlan_bitmap[row]);
netdev_dbg(netdev, "Add vlan %u\n", vid);
out:
return err;
}
static int hinic3_vlan_rx_kill_vid(struct net_device *netdev,
__be16 proto, u16 vid)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
unsigned long *vlan_bitmap = nic_dev->vlan_bitmap;
u32 column, row;
u16 func_id;
int err;
column = VID_COL(nic_dev, vid);
row = VID_LINE(nic_dev, vid);
func_id = hinic3_global_func_id(nic_dev->hwdev);
err = hinic3_del_vlan(nic_dev->hwdev, vid, func_id);
if (err) {
netdev_err(netdev, "Failed to delete vlan %u\n", vid);
goto out;
}
clear_bit(column, &vlan_bitmap[row]);
netdev_dbg(netdev, "Remove vlan %u\n", vid);
out:
return err;
}
static void hinic3_tx_timeout(struct net_device *netdev, unsigned int txqueue)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
@@ -771,6 +830,9 @@ static const struct net_device_ops hinic3_netdev_ops = {
.ndo_features_check = hinic3_features_check,
.ndo_change_mtu = hinic3_change_mtu,
.ndo_set_mac_address = hinic3_set_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_vlan_rx_add_vid = hinic3_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = hinic3_vlan_rx_kill_vid,
.ndo_tx_timeout = hinic3_tx_timeout,
.ndo_get_stats64 = hinic3_get_stats64,
.ndo_start_xmit = hinic3_xmit_frame,

View File

@@ -10,6 +10,9 @@
#include "hinic3_nic_dev.h"
#include "hinic3_nic_io.h"
#define MGMT_MSG_CMD_OP_ADD 1
#define MGMT_MSG_CMD_OP_DEL 0
static int hinic3_feature_nego(struct hinic3_hwdev *hwdev, u8 opcode,
u64 *s_feature, u16 size)
{
@@ -496,6 +499,44 @@ int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev)
return pkt_drop.msg_head.status;
}
static int hinic3_config_vlan(struct hinic3_hwdev *hwdev,
u8 opcode, u16 vlan_id, u16 func_id)
{
struct l2nic_cmd_vlan_config vlan_info = {};
struct mgmt_msg_params msg_params = {};
int err;
vlan_info.opcode = opcode;
vlan_info.func_id = func_id;
vlan_info.vlan_id = vlan_id;
mgmt_msg_params_init_default(&msg_params, &vlan_info,
sizeof(vlan_info));
err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
L2NIC_CMD_CFG_FUNC_VLAN, &msg_params);
if (err || vlan_info.msg_head.status) {
dev_err(hwdev->dev,
"Failed to %s vlan, err: %d, status: 0x%x\n",
opcode == MGMT_MSG_CMD_OP_ADD ? "add" : "delete",
err, vlan_info.msg_head.status);
return -EFAULT;
}
return 0;
}
int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id)
{
return hinic3_config_vlan(hwdev, MGMT_MSG_CMD_OP_ADD, vlan_id, func_id);
}
int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id)
{
return hinic3_config_vlan(hwdev, MGMT_MSG_CMD_OP_DEL, vlan_id, func_id);
}
int hinic3_set_port_enable(struct hinic3_hwdev *hwdev, bool enable)
{
struct mag_cmd_set_port_enable en_state = {};

View File

@@ -83,5 +83,7 @@ int hinic3_set_port_enable(struct hinic3_hwdev *hwdev, bool enable);
int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_up);
int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id,
bool enable);
int hinic3_add_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id);
int hinic3_del_vlan(struct hinic3_hwdev *hwdev, u16 vlan_id, u16 func_id);
#endif

View File

@@ -4,12 +4,17 @@
#ifndef _HINIC3_NIC_DEV_H_
#define _HINIC3_NIC_DEV_H_
#include <linux/if_vlan.h>
#include <linux/netdevice.h>
#include "hinic3_hw_cfg.h"
#include "hinic3_hwdev.h"
#include "hinic3_mgmt_interface.h"
#define HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev) (sizeof(*(nic_dev)->vlan_bitmap))
#define HINIC3_VLAN_BITMAP_SIZE(nic_dev) \
(VLAN_N_VID / HINIC3_VLAN_BITMAP_BYTE_SIZE(nic_dev))
enum hinic3_flags {
HINIC3_RSS_ENABLE,
};
@@ -71,6 +76,7 @@ struct hinic3_nic_dev {
u16 max_qps;
u16 rx_buf_len;
u32 lro_replenish_thld;
unsigned long *vlan_bitmap;
unsigned long flags;
struct hinic3_nic_service_cap nic_svc_cap;