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:
Родитель
56fd2b2ca4
Коммит
30d240dfa2
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 = netdev_set_num_tc(netdev, tc);
|
||||
ret = (kinfo->dcb_ops && kinfo->dcb_ops->setup_tc) ?
|
||||
kinfo->dcb_ops->setup_tc(h, tc, prio_tc) : -EOPNOTSUPP;
|
||||
if (ret)
|
||||
return ret;
|
||||
goto out;
|
||||
|
||||
if (tc <= 1) {
|
||||
netdev_reset_tc(netdev);
|
||||
} else {
|
||||
ret = netdev_set_num_tc(netdev, tc);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < HNAE3_MAX_TC; i++) {
|
||||
if (!kinfo->tc_info[i].enable)
|
||||
continue;
|
||||
|
||||
/* Set per TC queues for the VSI */
|
||||
for (i = 0; i < HNAE3_MAX_TC; i++) {
|
||||
if (kinfo->tc_info[i].enable)
|
||||
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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче