hinic3: Add port management

Add port management of enable/disable/query/flush function.

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/122cbde6dec03e091340bda32c8b0d7fac3a2fb4.1757653621.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Fan Gong
2025-09-12 14:28:29 +08:00
committed by Paolo Abeni
parent 1f3838b84a
commit 45f97ae93d
4 changed files with 161 additions and 0 deletions

View File

@@ -69,12 +69,27 @@ struct l2nic_cmd_set_ci_attr {
u64 ci_addr;
};
struct l2nic_cmd_clear_qp_resource {
struct mgmt_msg_head msg_head;
u16 func_id;
u16 rsvd1;
};
struct l2nic_cmd_force_pkt_drop {
struct mgmt_msg_head msg_head;
u8 port;
u8 rsvd1[3];
};
struct l2nic_cmd_set_vport_state {
struct mgmt_msg_head msg_head;
u16 func_id;
u16 rsvd1;
/* 0--disable, 1--enable */
u8 state;
u8 rsvd2[3];
};
struct l2nic_cmd_set_dcb_state {
struct mgmt_msg_head head;
u16 func_id;
@@ -172,6 +187,20 @@ enum l2nic_ucode_cmd {
L2NIC_UCODE_CMD_SET_RSS_INDIR_TBL = 4,
};
/* hilink mac group command */
enum mag_cmd {
MAG_CMD_GET_LINK_STATUS = 7,
};
/* firmware also use this cmd report link event to driver */
struct mag_cmd_get_link_status {
struct mgmt_msg_head head;
u8 port_id;
/* 0:link down 1:link up */
u8 status;
u8 rsvd0[2];
};
enum hinic3_nic_feature_cap {
HINIC3_NIC_F_CSUM = BIT(0),
HINIC3_NIC_F_SCTP_CRC = BIT(1),

View File

@@ -327,6 +327,59 @@ static void hinic3_close_channel(struct net_device *netdev)
hinic3_free_qp_ctxts(nic_dev);
}
static int hinic3_vport_up(struct net_device *netdev)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
bool link_status_up;
u16 glb_func_id;
int err;
glb_func_id = hinic3_global_func_id(nic_dev->hwdev);
err = hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, true);
if (err) {
netdev_err(netdev, "Failed to enable vport\n");
goto err_flush_qps_res;
}
err = netif_set_real_num_queues(netdev, nic_dev->q_params.num_qps,
nic_dev->q_params.num_qps);
if (err) {
netdev_err(netdev, "Failed to set real number of queues\n");
goto err_flush_qps_res;
}
netif_tx_start_all_queues(netdev);
err = hinic3_get_link_status(nic_dev->hwdev, &link_status_up);
if (!err && link_status_up)
netif_carrier_on(netdev);
return 0;
err_flush_qps_res:
hinic3_flush_qps_res(nic_dev->hwdev);
/* wait to guarantee that no packets will be sent to host */
msleep(100);
return err;
}
static void hinic3_vport_down(struct net_device *netdev)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
u16 glb_func_id;
netif_carrier_off(netdev);
netif_tx_disable(netdev);
glb_func_id = hinic3_global_func_id(nic_dev->hwdev);
hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false);
hinic3_flush_txqs(netdev);
/* wait to guarantee that no packets will be sent to host */
msleep(100);
hinic3_flush_qps_res(nic_dev->hwdev);
}
static int hinic3_open(struct net_device *netdev)
{
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
@@ -356,8 +409,14 @@ static int hinic3_open(struct net_device *netdev)
if (err)
goto err_uninit_qps;
err = hinic3_vport_up(netdev);
if (err)
goto err_close_channel;
return 0;
err_close_channel:
hinic3_close_channel(netdev);
err_uninit_qps:
hinic3_uninit_qps(nic_dev, &qp_params);
hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params);
@@ -374,6 +433,7 @@ static int hinic3_close(struct net_device *netdev)
struct hinic3_nic_dev *nic_dev = netdev_priv(netdev);
struct hinic3_dyna_qp_params qp_params;
hinic3_vport_down(netdev);
hinic3_close_channel(netdev);
hinic3_uninit_qps(nic_dev, &qp_params);
hinic3_free_channel_resources(netdev, &qp_params, &nic_dev->q_params);

View File

@@ -267,6 +267,28 @@ int hinic3_set_ci_table(struct hinic3_hwdev *hwdev, struct hinic3_sq_attr *attr)
return 0;
}
int hinic3_flush_qps_res(struct hinic3_hwdev *hwdev)
{
struct l2nic_cmd_clear_qp_resource sq_res = {};
struct mgmt_msg_params msg_params = {};
int err;
sq_res.func_id = hinic3_global_func_id(hwdev);
mgmt_msg_params_init_default(&msg_params, &sq_res, sizeof(sq_res));
err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
L2NIC_CMD_CLEAR_QP_RESOURCE,
&msg_params);
if (err || sq_res.msg_head.status) {
dev_err(hwdev->dev, "Failed to clear sq resources, err: %d, status: 0x%x\n",
err, sq_res.msg_head.status);
return -EINVAL;
}
return 0;
}
int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev)
{
struct l2nic_cmd_force_pkt_drop pkt_drop = {};
@@ -314,3 +336,49 @@ int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state)
return 0;
}
int hinic3_get_link_status(struct hinic3_hwdev *hwdev, bool *link_status_up)
{
struct mag_cmd_get_link_status get_link = {};
struct mgmt_msg_params msg_params = {};
int err;
get_link.port_id = hinic3_physical_port_id(hwdev);
mgmt_msg_params_init_default(&msg_params, &get_link, sizeof(get_link));
err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_HILINK,
MAG_CMD_GET_LINK_STATUS, &msg_params);
if (err || get_link.head.status) {
dev_err(hwdev->dev, "Failed to get link state, err: %d, status: 0x%x\n",
err, get_link.head.status);
return -EIO;
}
*link_status_up = !!get_link.status;
return 0;
}
int hinic3_set_vport_enable(struct hinic3_hwdev *hwdev, u16 func_id,
bool enable)
{
struct l2nic_cmd_set_vport_state en_state = {};
struct mgmt_msg_params msg_params = {};
int err;
en_state.func_id = func_id;
en_state.state = enable ? 1 : 0;
mgmt_msg_params_init_default(&msg_params, &en_state, sizeof(en_state));
err = hinic3_send_mbox_to_mgmt(hwdev, MGMT_MOD_L2NIC,
L2NIC_CMD_SET_VPORT_ENABLE, &msg_params);
if (err || en_state.msg_head.status) {
dev_err(hwdev->dev, "Failed to set vport state, err: %d, status: 0x%x\n",
err, en_state.msg_head.status);
return -EINVAL;
}
return 0;
}

View File

@@ -50,8 +50,12 @@ int hinic3_update_mac(struct hinic3_hwdev *hwdev, const u8 *old_mac,
int hinic3_set_ci_table(struct hinic3_hwdev *hwdev,
struct hinic3_sq_attr *attr);
int hinic3_flush_qps_res(struct hinic3_hwdev *hwdev);
int hinic3_force_drop_tx_pkt(struct hinic3_hwdev *hwdev);
int hinic3_sync_dcb_state(struct hinic3_hwdev *hwdev, u8 op_code, u8 state);
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);
#endif