mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-15 03:53:12 -05:00
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:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 = {};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user