Commit 45f97ae9 authored by Fan Gong's avatar Fan Gong Committed by Paolo Abeni
Browse files

hinic3: Add port management

parent 1f3838b8
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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),
+60 −0
Original line number Diff line number Diff line
@@ -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);
+68 −0
Original line number Diff line number Diff line
@@ -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;
}
+4 −0
Original line number Diff line number Diff line
@@ -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