mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-14 18:25:48 -04:00
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:
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user