Commit 2026fecf authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

mqprio: Change handling of hw u8 to allow for multiple hardware offload modes

This patch is meant to allow for support of multiple hardware offload type
for a single device. There is currently no bounds checking for the hw
member of the mqprio_qopt structure.  This results in us being able to pass
values from 1 to 255 with all being treated the same.  On retreiving the
value it is returned as 1 for anything 1 or greater being set.

With this change we are currently adding limited bounds checking by
defining an enum and using those values to limit the reported hardware
offloads.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5b769649
...@@ -617,6 +617,14 @@ struct tc_drr_stats { ...@@ -617,6 +617,14 @@ struct tc_drr_stats {
#define TC_QOPT_BITMASK 15 #define TC_QOPT_BITMASK 15
#define TC_QOPT_MAX_QUEUE 16 #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 { struct tc_mqprio_qopt {
__u8 num_tc; __u8 num_tc;
__u8 prio_tc_map[TC_QOPT_BITMASK + 1]; __u8 prio_tc_map[TC_QOPT_BITMASK + 1];
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
struct mqprio_sched { struct mqprio_sched {
struct Qdisc **qdiscs; struct Qdisc **qdiscs;
int hw_owned; int hw_offload;
}; };
static void mqprio_destroy(struct Qdisc *sch) static void mqprio_destroy(struct Qdisc *sch)
...@@ -39,7 +39,7 @@ static void mqprio_destroy(struct Qdisc *sch) ...@@ -39,7 +39,7 @@ static void mqprio_destroy(struct Qdisc *sch)
kfree(priv->qdiscs); kfree(priv->qdiscs);
} }
if (priv->hw_owned && dev->netdev_ops->ndo_setup_tc) if (priv->hw_offload && dev->netdev_ops->ndo_setup_tc)
dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc); dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
else else
netdev_set_num_tc(dev, 0); netdev_set_num_tc(dev, 0);
...@@ -59,15 +59,20 @@ static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt) ...@@ -59,15 +59,20 @@ static int mqprio_parse_opt(struct net_device *dev, struct tc_mqprio_qopt *qopt)
return -EINVAL; return -EINVAL;
} }
/* net_device does not support requested operation */ /* Limit qopt->hw to maximum supported offload value. Drivers have
if (qopt->hw && !dev->netdev_ops->ndo_setup_tc) * the option of overriding this later if they don't support the a
return -EINVAL; * 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 /* If hardware offload is requested we will leave it to the device
* no reason to verify them here * 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) if (qopt->hw)
return 0; return dev->netdev_ops->ndo_setup_tc ? 0 : -EINVAL;
for (i = 0; i < qopt->num_tc; i++) { for (i = 0; i < qopt->num_tc; i++) {
unsigned int last = qopt->offset[i] + qopt->count[i]; unsigned int last = qopt->offset[i] + qopt->count[i];
...@@ -142,10 +147,11 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) ...@@ -142,10 +147,11 @@ static int mqprio_init(struct Qdisc *sch, struct nlattr *opt)
struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO, struct tc_to_netdev tc = {.type = TC_SETUP_MQPRIO,
{ .tc = qopt->num_tc }}; { .tc = qopt->num_tc }};
priv->hw_owned = 1;
err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc); err = dev->netdev_ops->ndo_setup_tc(dev, sch->handle, 0, &tc);
if (err) if (err)
return err; return err;
priv->hw_offload = qopt->hw;
} else { } else {
netdev_set_num_tc(dev, qopt->num_tc); netdev_set_num_tc(dev, qopt->num_tc);
for (i = 0; i < qopt->num_tc; i++) for (i = 0; i < qopt->num_tc; i++)
...@@ -243,7 +249,7 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb) ...@@ -243,7 +249,7 @@ static int mqprio_dump(struct Qdisc *sch, struct sk_buff *skb)
opt.num_tc = netdev_get_num_tc(dev); opt.num_tc = netdev_get_num_tc(dev);
memcpy(opt.prio_tc_map, dev->prio_tc_map, sizeof(opt.prio_tc_map)); 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++) { for (i = 0; i < netdev_get_num_tc(dev); i++) {
opt.count[i] = dev->tc_to_txq[i].count; opt.count[i] = dev->tc_to_txq[i].count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment