Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 30d240df authored by Yunsheng Lin's avatar Yunsheng Lin Committed by David S. Miller
Browse files

net: hns3: Add mqprio hardware offload support in hns3 driver



When using tc qdisc, dcb_ops->setup_tc is used to tell hclge_dcb
module to do the tm related setup. Only TC_MQPRIO_MODE_CHANNEL
offload mode is supported.

Signed-off-by: default avatarYunsheng Lin <linyunsheng@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 56fd2b2c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -381,6 +381,7 @@ struct hnae3_dcb_ops {
	u8   (*setdcbx)(struct hnae3_handle *, u8);

	int (*map_update)(struct hnae3_handle *);
	int (*setup_tc)(struct hnae3_handle *, u8, u8 *);
};

struct hnae3_ae_algo {
+45 −2
Original line number Diff line number Diff line
@@ -178,7 +178,8 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
	u8 num_tc = 0;
	int ret;

	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
	    hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
		return -EINVAL;

	ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);
@@ -228,7 +229,8 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
	struct hclge_dev *hdev = vport->back;
	u8 i, j, pfc_map, *prio_tc;

	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
	if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE) ||
	    hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
		return -EINVAL;

	prio_tc = hdev->tm_info.prio_tc;
@@ -257,6 +259,9 @@ static u8 hclge_getdcbx(struct hnae3_handle *h)
	struct hclge_vport *vport = hclge_get_vport(h);
	struct hclge_dev *hdev = vport->back;

	if (hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
		return 0;

	return hdev->dcbx_cap;
}

@@ -276,6 +281,43 @@ static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)
	return 0;
}

/* Set up TC for hardware offloaded mqprio in channel mode */
static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc)
{
	struct hclge_vport *vport = hclge_get_vport(h);
	struct hclge_dev *hdev = vport->back;
	int ret;

	if (hdev->flag & HCLGE_FLAG_DCB_ENABLE)
		return -EINVAL;

	if (tc > hdev->tc_max) {
		dev_err(&hdev->pdev->dev,
			"setup tc failed, tc(%u) > tc_max(%u)\n",
			tc, hdev->tc_max);
		return -EINVAL;
	}

	hclge_tm_schd_info_update(hdev, tc);

	ret = hclge_tm_prio_tc_info_update(hdev, prio_tc);
	if (ret)
		return ret;

	ret = hclge_tm_init_hw(hdev);
	if (ret)
		return ret;

	hdev->flag &= ~HCLGE_FLAG_DCB_ENABLE;

	if (tc > 1)
		hdev->flag |= HCLGE_FLAG_MQPRIO_ENABLE;
	else
		hdev->flag &= ~HCLGE_FLAG_MQPRIO_ENABLE;

	return 0;
}

static const struct hnae3_dcb_ops hns3_dcb_ops = {
	.ieee_getets	= hclge_ieee_getets,
	.ieee_setets	= hclge_ieee_setets,
@@ -284,6 +326,7 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = {
	.getdcbx	= hclge_getdcbx,
	.setdcbx	= hclge_setdcbx,
	.map_update	= hclge_map_update,
	.setup_tc	= hclge_setup_tc,
};

void hclge_dcb_ops_set(struct hclge_dev *hdev)
+1 −0
Original line number Diff line number Diff line
@@ -470,6 +470,7 @@ struct hclge_dev {
#define HCLGE_FLAG_MAIN		0x00000004
#define HCLGE_FLAG_DCB_CAPABLE	0x00000008
#define HCLGE_FLAG_DCB_ENABLE	0x00000010
#define HCLGE_FLAG_MQPRIO_ENABLE	0x00000020
	u32 flag;

	u32 pkt_buf_size; /* Total pf buf size for tx/rx */
+39 −17
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <linux/sctp.h>
#include <linux/vermagic.h>
#include <net/gre.h>
#include <net/pkt_cls.h>
#include <net/vxlan.h>

#include "hnae3.h"
@@ -1186,53 +1187,74 @@ static void hns3_nic_udp_tunnel_del(struct net_device *netdev,
	}
}

static int hns3_setup_tc(struct net_device *netdev, u8 tc)
static int hns3_setup_tc(struct net_device *netdev, void *type_data)
{
	struct tc_mqprio_qopt_offload *mqprio_qopt = type_data;
	struct hnae3_handle *h = hns3_get_handle(netdev);
	struct hnae3_knic_private_info *kinfo = &h->kinfo;
	u8 *prio_tc = mqprio_qopt->qopt.prio_tc_map;
	u8 tc = mqprio_qopt->qopt.num_tc;
	u16 mode = mqprio_qopt->mode;
	u8 hw = mqprio_qopt->qopt.hw;
	bool if_running;
	unsigned int i;
	int ret;

	if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS &&
	       mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0)))
		return -EOPNOTSUPP;

	if (tc > HNAE3_MAX_TC)
		return -EINVAL;

	if (kinfo->num_tc == tc)
		return 0;

	if (!netdev)
		return -EINVAL;

	if (!tc) {
		netdev_reset_tc(netdev);
		return 0;
	if_running = netif_running(netdev);
	if (if_running) {
		hns3_nic_net_stop(netdev);
		msleep(100);
	}

	/* Set num_tc for netdev */
	ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
		kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
	if (ret)
		goto out;

	if (tc <= 1) {
		netdev_reset_tc(netdev);
	} else {
		ret = netdev_set_num_tc(netdev, tc);
		if (ret)
		return ret;
			goto out;

	/* Set per TC queues for the VSI */
		for (i = 0; i < HNAE3_MAX_TC; i++) {
		if (kinfo->tc_info[i].enable)
			if (!kinfo->tc_info[i].enable)
				continue;

			netdev_set_tc_queue(netdev,
					    kinfo->tc_info[i].tc,
					    kinfo->tc_info[i].tqp_count,
					    kinfo->tc_info[i].tqp_offset);
		}
	}

	return 0;
	ret = hns3_nic_set_real_num_queue(netdev);

out:
	if (if_running)
		hns3_nic_net_open(netdev);

	return ret;
}

static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
			     void *type_data)
{
	struct tc_mqprio_qopt *mqprio = type_data;

	if (type != TC_SETUP_MQPRIO)
		return -EOPNOTSUPP;

	return hns3_setup_tc(dev, mqprio->num_tc);
	return hns3_setup_tc(dev, type_data);
}

static int hns3_vlan_rx_add_vid(struct net_device *netdev,