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: Yunsheng Lin <linyunsheng@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
56fd2b2ca4
commit
30d240dfa2
|
@ -381,6 +381,7 @@ struct hnae3_dcb_ops {
|
||||||
u8 (*setdcbx)(struct hnae3_handle *, u8);
|
u8 (*setdcbx)(struct hnae3_handle *, u8);
|
||||||
|
|
||||||
int (*map_update)(struct hnae3_handle *);
|
int (*map_update)(struct hnae3_handle *);
|
||||||
|
int (*setup_tc)(struct hnae3_handle *, u8, u8 *);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hnae3_ae_algo {
|
struct hnae3_ae_algo {
|
||||||
|
|
|
@ -178,7 +178,8 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
|
||||||
u8 num_tc = 0;
|
u8 num_tc = 0;
|
||||||
int ret;
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = hclge_ets_validate(hdev, ets, &num_tc, &map_changed);
|
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;
|
struct hclge_dev *hdev = vport->back;
|
||||||
u8 i, j, pfc_map, *prio_tc;
|
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;
|
return -EINVAL;
|
||||||
|
|
||||||
prio_tc = hdev->tm_info.prio_tc;
|
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_vport *vport = hclge_get_vport(h);
|
||||||
struct hclge_dev *hdev = vport->back;
|
struct hclge_dev *hdev = vport->back;
|
||||||
|
|
||||||
|
if (hdev->flag & HCLGE_FLAG_MQPRIO_ENABLE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return hdev->dcbx_cap;
|
return hdev->dcbx_cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +281,43 @@ static u8 hclge_setdcbx(struct hnae3_handle *h, u8 mode)
|
||||||
return 0;
|
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 = {
|
static const struct hnae3_dcb_ops hns3_dcb_ops = {
|
||||||
.ieee_getets = hclge_ieee_getets,
|
.ieee_getets = hclge_ieee_getets,
|
||||||
.ieee_setets = hclge_ieee_setets,
|
.ieee_setets = hclge_ieee_setets,
|
||||||
|
@ -284,6 +326,7 @@ static const struct hnae3_dcb_ops hns3_dcb_ops = {
|
||||||
.getdcbx = hclge_getdcbx,
|
.getdcbx = hclge_getdcbx,
|
||||||
.setdcbx = hclge_setdcbx,
|
.setdcbx = hclge_setdcbx,
|
||||||
.map_update = hclge_map_update,
|
.map_update = hclge_map_update,
|
||||||
|
.setup_tc = hclge_setup_tc,
|
||||||
};
|
};
|
||||||
|
|
||||||
void hclge_dcb_ops_set(struct hclge_dev *hdev)
|
void hclge_dcb_ops_set(struct hclge_dev *hdev)
|
||||||
|
|
|
@ -470,6 +470,7 @@ struct hclge_dev {
|
||||||
#define HCLGE_FLAG_MAIN 0x00000004
|
#define HCLGE_FLAG_MAIN 0x00000004
|
||||||
#define HCLGE_FLAG_DCB_CAPABLE 0x00000008
|
#define HCLGE_FLAG_DCB_CAPABLE 0x00000008
|
||||||
#define HCLGE_FLAG_DCB_ENABLE 0x00000010
|
#define HCLGE_FLAG_DCB_ENABLE 0x00000010
|
||||||
|
#define HCLGE_FLAG_MQPRIO_ENABLE 0x00000020
|
||||||
u32 flag;
|
u32 flag;
|
||||||
|
|
||||||
u32 pkt_buf_size; /* Total pf buf size for tx/rx */
|
u32 pkt_buf_size; /* Total pf buf size for tx/rx */
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/sctp.h>
|
#include <linux/sctp.h>
|
||||||
#include <linux/vermagic.h>
|
#include <linux/vermagic.h>
|
||||||
#include <net/gre.h>
|
#include <net/gre.h>
|
||||||
|
#include <net/pkt_cls.h>
|
||||||
#include <net/vxlan.h>
|
#include <net/vxlan.h>
|
||||||
|
|
||||||
#include "hnae3.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_handle *h = hns3_get_handle(netdev);
|
||||||
struct hnae3_knic_private_info *kinfo = &h->kinfo;
|
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;
|
unsigned int i;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (!((hw == TC_MQPRIO_HW_OFFLOAD_TCS &&
|
||||||
|
mode == TC_MQPRIO_MODE_CHANNEL) || (!hw && tc == 0)))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (tc > HNAE3_MAX_TC)
|
if (tc > HNAE3_MAX_TC)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (kinfo->num_tc == tc)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (!netdev)
|
if (!netdev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (!tc) {
|
if_running = netif_running(netdev);
|
||||||
netdev_reset_tc(netdev);
|
if (if_running) {
|
||||||
return 0;
|
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);
|
ret = netdev_set_num_tc(netdev, tc);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto out;
|
||||||
|
|
||||||
/* Set per TC queues for the VSI */
|
|
||||||
for (i = 0; i < HNAE3_MAX_TC; i++) {
|
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,
|
netdev_set_tc_queue(netdev,
|
||||||
kinfo->tc_info[i].tc,
|
kinfo->tc_info[i].tc,
|
||||||
kinfo->tc_info[i].tqp_count,
|
kinfo->tc_info[i].tqp_count,
|
||||||
kinfo->tc_info[i].tqp_offset);
|
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,
|
static int hns3_nic_setup_tc(struct net_device *dev, enum tc_setup_type type,
|
||||||
void *type_data)
|
void *type_data)
|
||||||
{
|
{
|
||||||
struct tc_mqprio_qopt *mqprio = type_data;
|
|
||||||
|
|
||||||
if (type != TC_SETUP_MQPRIO)
|
if (type != TC_SETUP_MQPRIO)
|
||||||
return -EOPNOTSUPP;
|
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,
|
static int hns3_vlan_rx_add_vid(struct net_device *netdev,
|
||||||
|
|
Loading…
Reference in New Issue