mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-05 07:46:53 +07:00
Merge branch 'mqprio-offload-more-info'
Alexander Duyck says: ==================== Add support for passing more information in mqprio offload This patch series lays the groundwork for future work to allow us to make full use of the mqprio options when offloading them to hardware. Currently when we specify the hardware offload for mqprio the queue configuration is completely ignored and the hardware is only notified of the total number of traffic classes. The problem is this leads to multiple issues, one specific issue being you can pass the queue configuration you want and it is totally ignored by the hardware. What I am planning to do is add support for "hw" values in the configuration greater than 1. So for example we might have one mode of mqprio offload that uses 1 and only offloads the TC counts like we currently do. Then we might look at adding an option 2 which would factor in the TCs and the queue count information. This way we can select between the type of offload we actually want and existing drivers that don't support this can just fall back to their legacy configuration. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
1aed181413
@ -1854,7 +1854,8 @@ static int xgbe_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
|
||||
if (tc_to_netdev->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
tc = tc_to_netdev->tc;
|
||||
tc_to_netdev->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
tc = tc_to_netdev->mqprio->num_tc;
|
||||
|
||||
if (tc > pdata->hw_feat.tc_cnt)
|
||||
return -EINVAL;
|
||||
|
@ -4277,7 +4277,10 @@ int __bnx2x_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
{
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
return bnx2x_setup_tc(dev, tc->tc);
|
||||
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return bnx2x_setup_tc(dev, tc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
/* called with rtnl_lock */
|
||||
|
@ -6905,7 +6905,9 @@ static int bnxt_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
if (ntc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
return bnxt_setup_mq_tc(dev, ntc->tc);
|
||||
ntc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return bnxt_setup_mq_tc(dev, ntc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
|
@ -346,33 +346,37 @@ static int dpaa_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
|
||||
struct tc_to_netdev *tc)
|
||||
{
|
||||
struct dpaa_priv *priv = netdev_priv(net_dev);
|
||||
u8 num_tc;
|
||||
int i;
|
||||
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
if (tc->tc == priv->num_tc)
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
num_tc = tc->mqprio->num_tc;
|
||||
|
||||
if (num_tc == priv->num_tc)
|
||||
return 0;
|
||||
|
||||
if (!tc->tc) {
|
||||
if (!num_tc) {
|
||||
netdev_reset_tc(net_dev);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (tc->tc > DPAA_TC_NUM) {
|
||||
if (num_tc > DPAA_TC_NUM) {
|
||||
netdev_err(net_dev, "Too many traffic classes: max %d supported.\n",
|
||||
DPAA_TC_NUM);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
netdev_set_num_tc(net_dev, tc->tc);
|
||||
netdev_set_num_tc(net_dev, num_tc);
|
||||
|
||||
for (i = 0; i < tc->tc; i++)
|
||||
for (i = 0; i < num_tc; i++)
|
||||
netdev_set_tc_queue(net_dev, i, DPAA_TC_TXQ_NUM,
|
||||
i * DPAA_TC_TXQ_NUM);
|
||||
|
||||
out:
|
||||
priv->num_tc = tc->tc ? tc->tc : 1;
|
||||
priv->num_tc = num_tc ? : 1;
|
||||
netif_set_real_num_tx_queues(net_dev, priv->num_tc * DPAA_TC_TXQ_NUM);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1226,7 +1226,9 @@ static int __fm10k_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
return fm10k_setup_tc(dev, tc->tc);
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return fm10k_setup_tc(dev, tc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
static void fm10k_assign_l2_accel(struct fm10k_intfc *interface,
|
||||
|
@ -5611,9 +5611,12 @@ static int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
|
||||
struct tc_to_netdev *tc)
|
||||
#endif
|
||||
{
|
||||
if (handle != TC_H_ROOT || tc->type != TC_SETUP_MQPRIO)
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
return i40e_setup_tc(netdev, tc->tc);
|
||||
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return i40e_setup_tc(netdev, tc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8948,7 +8948,9 @@ static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
return ixgbe_setup_tc(dev, tc->tc);
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return ixgbe_setup_tc(dev, tc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PCI_IOV
|
||||
|
@ -92,7 +92,9 @@ static int __mlx4_en_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
return mlx4_en_setup_tc(dev, tc->tc);
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return mlx4_en_setup_tc(dev, tc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_RFS_ACCEL
|
||||
|
@ -2737,7 +2737,9 @@ static int mlx5e_ndo_setup_tc(struct net_device *dev, u32 handle,
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
return mlx5e_setup_tc(dev, tc->tc);
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
return mlx5e_setup_tc(dev, tc->mqprio->num_tc);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -437,11 +437,13 @@ int ef4_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
|
||||
if (ntc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
num_tc = ntc->tc;
|
||||
num_tc = ntc->mqprio->num_tc;
|
||||
|
||||
if (ef4_nic_rev(efx) < EF4_REV_FALCON_B0 || num_tc > EF4_MAX_TX_TC)
|
||||
return -EINVAL;
|
||||
|
||||
ntc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
if (num_tc == net_dev->num_tc)
|
||||
return 0;
|
||||
|
||||
|
@ -665,11 +665,13 @@ int efx_setup_tc(struct net_device *net_dev, u32 handle, __be16 proto,
|
||||
if (ntc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
num_tc = ntc->tc;
|
||||
num_tc = ntc->mqprio->num_tc;
|
||||
|
||||
if (num_tc > EFX_MAX_TX_TC)
|
||||
return -EINVAL;
|
||||
|
||||
ntc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
|
||||
if (num_tc == net_dev->num_tc)
|
||||
return 0;
|
||||
|
||||
|
@ -1882,6 +1882,7 @@ static u16 netcp_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
struct tc_to_netdev *tc)
|
||||
{
|
||||
u8 num_tc;
|
||||
int i;
|
||||
|
||||
/* setup tc must be called under rtnl lock */
|
||||
@ -1890,15 +1891,18 @@ static int netcp_setup_tc(struct net_device *dev, u32 handle, __be16 proto,
|
||||
if (tc->type != TC_SETUP_MQPRIO)
|
||||
return -EINVAL;
|
||||
|
||||
tc->mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
|
||||
num_tc = tc->mqprio->num_tc;
|
||||
|
||||
/* Sanity-check the number of traffic classes requested */
|
||||
if ((dev->real_num_tx_queues <= 1) ||
|
||||
(dev->real_num_tx_queues < tc->tc))
|
||||
(dev->real_num_tx_queues < num_tc))
|
||||
return -EINVAL;
|
||||
|
||||
/* Configure traffic class to queue mappings */
|
||||
if (tc->tc) {
|
||||
netdev_set_num_tc(dev, tc->tc);
|
||||
for (i = 0; i < tc->tc; i++)
|
||||
if (num_tc) {
|
||||
netdev_set_num_tc(dev, num_tc);
|
||||
for (i = 0; i < num_tc; i++)
|
||||
netdev_set_tc_queue(dev, i, 1, i);
|
||||
} else {
|
||||
netdev_reset_tc(dev);
|
||||
|
@ -786,11 +786,11 @@ struct tc_cls_u32_offload;
|
||||
struct tc_to_netdev {
|
||||
unsigned int type;
|
||||
union {
|
||||
u8 tc;
|
||||
struct tc_cls_u32_offload *cls_u32;
|
||||
struct tc_cls_flower_offload *cls_flower;
|
||||
struct tc_cls_matchall_offload *cls_mall;
|
||||
struct tc_cls_bpf_offload *cls_bpf;
|
||||
struct tc_mqprio_qopt *mqprio;
|
||||
};
|
||||
bool egress_dev;
|
||||
};
|
||||
|
@ -617,6 +617,14 @@ struct tc_drr_stats {
|
||||
#define TC_QOPT_BITMASK 15
|
||||
#define TC_QOPT_MAX_QUEUE 16
|
||||
|
||||
enum {
|
||||
TC_MQPRIO_HW_OFFLOAD_NONE, /* no offload requested */
|
||||
TC_MQPRIO_HW_OFFLOAD_TCS, /* offload TCs, no queue counts */
|
||||
__TC_MQPRIO_HW_OFFLOAD_MAX
|
||||
};
|
||||
|
||||
#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
|
||||
|
||||
struct tc_mqprio_qopt {
|
||||
__u8 num_tc;
|
||||
__u8 prio_tc_map[TC_QOPT_BITMASK + 1];
|
||||
|
@ -21,14 +21,13 @@
|
||||
|
||||
struct mqprio_sched {
|
||||
struct Qdisc **qdiscs;
|
||||
int hw_owned;
|
||||
int hw_offload;
|
||||
};
|
||||
|
||||
static void mqprio_destroy(struct Qdisc *sch)
|
||||
{
|
||||
struct net_device *dev = qdisc_dev(sch);
|
||||
struct mqprio_sched *priv = qdisc_priv(sch);
|
||||
struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO};
|
||||
unsigned int ntx;
|
||||
|
||||
if (priv->qdiscs) {
|
||||
@ -39,10 +38,15 @@ static void mqprio_destroy(struct Qdisc *sch)
|
||||
kfree(priv->qdiscs);
|
||||
}
|
||||
|
||||
if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc)
|
||||
if (priv->hw_offload && dev->netdev_ops->ndo_setup_tc) {
|
||||
struct tc_mqprio_qopt offload = { 0 };
|
||||
struct tc_to_netdev tc = { .type = TC_SETUP_MQPRIO,
|
||||
{ .mqprio = &offload } };
|
||||
|
||||
dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
|
||||
else
|
||||
} else {
|
||||
netdev_set_num_tc(dev, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)
|
||||
@ -59,15 +63,20 @@ static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* net_device does not support requested operation */
|
||||
if (qopt->hw && !dev->netdev_ops->ndo_setup_tc)
|
||||
return -EINVAL;
|
||||
/* Limit qopt->hw to maximum supported offload value. Drivers have
|
||||
* the option of overriding this later if they don't support the a
|
||||
* given offload type.
|
||||
*/
|
||||
if (qopt->hw > TC_MQPRIO_HW_OFFLOAD_MAX)
|
||||
qopt->hw = TC_MQPRIO_HW_OFFLOAD_MAX;
|
||||
|
||||
/* if hw owned qcount and qoffset are taken from LLD so
|
||||
* no reason to verify them here
|
||||
/* If hardware offload is requested we will leave it to the device
|
||||
* to either populate the queue counts itself or to validate the
|
||||
* provided queue counts. If ndo_setup_tc is not present then
|
||||
* hardware doesn't support offload and we should return an error.
|
||||
*/
|
||||
if (qopt->hw)
|
||||
return 0;
|
||||
return dev->netdev_ops->ndo_setup_tc ? 0 : -EINVAL;
|
||||
|
||||
for (i = 0; i < qopt->num_tc; i++) {
|
||||
unsigned int last = qopt->offset[i] + qopt->count[i];
|
||||
@ -139,13 +148,15 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
|
||||
* supplied and verified mapping
|
||||
*/
|
||||
if (qopt->hw) {
|
||||
struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,
|
||||
{ .tc = qopt->num_tc }};
|
||||
struct tc_mqprio_qopt offload = *qopt;
|
||||
struct tc_to_netdev tc = { .type = TC_SETUP_MQPRIO,
|
||||
{ .mqprio = &offload } };
|
||||
|
||||
priv->hw_owned = 1;
|
||||
err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
priv->hw_offload = offload.hw;
|
||||
} else {
|
||||
netdev_set_num_tc(dev, qopt->num_tc);
|
||||
for (i = 0; i < qopt->num_tc; i++)
|
||||
@ -243,7 +254,7 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)
|
||||
|
||||
opt.num_tc = netdev_get_num_tc(dev);
|
||||
memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map));
|
||||
opt.hw = priv->hw_owned;
|
||||
opt.hw = priv->hw_offload;
|
||||
|
||||
for (i = 0; i < netdev_get_num_tc(dev); i++) {
|
||||
opt.count[i] = dev->tc_to_txq[i].count;
|
||||
|
Loading…
Reference in New Issue
Block a user