Commit 0f9e2d95 authored by Fan Gong's avatar Fan Gong Committed by Paolo Abeni
Browse files

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: default avatarZhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: default avatarZhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: default avatarFan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/70be187afcaa7b38981d114c088ffdc2cba0b4f1.1768375903.git.zhuyikai1@h-partners.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 2467a046
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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,
+10 −0
Original line number Diff line number Diff line
@@ -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,
+62 −0
Original line number Diff line number Diff line
@@ -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,
+41 −0
Original line number Diff line number Diff line
@@ -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 = {};
+2 −0
Original line number Diff line number Diff line
@@ -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
Loading