return err;
 }
 
-int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
+static void enetc_debug_tx_ring_prios(struct enetc_ndev_priv *priv)
+{
+       int i;
+
+       for (i = 0; i < priv->num_tx_rings; i++)
+               netdev_dbg(priv->ndev, "TX ring %d prio %d\n", i,
+                          priv->tx_ring[i]->prio);
+}
+
+static void enetc_reset_tc_mqprio(struct net_device *ndev)
 {
        struct enetc_ndev_priv *priv = netdev_priv(ndev);
-       struct tc_mqprio_qopt *mqprio = type_data;
        struct enetc_hw *hw = &priv->si->hw;
        struct enetc_bdr *tx_ring;
        int num_stack_tx_queues;
-       u8 num_tc;
        int i;
 
        num_stack_tx_queues = enetc_num_stack_tx_queues(priv);
-       mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS;
-       num_tc = mqprio->num_tc;
 
-       if (!num_tc) {
-               netdev_reset_tc(ndev);
-               netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);
-               priv->min_num_stack_tx_queues = num_possible_cpus();
-
-               /* Reset all ring priorities to 0 */
-               for (i = 0; i < priv->num_tx_rings; i++) {
-                       tx_ring = priv->tx_ring[i];
-                       tx_ring->prio = 0;
-                       enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio);
-               }
+       netdev_reset_tc(ndev);
+       netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);
+       priv->min_num_stack_tx_queues = num_possible_cpus();
+
+       /* Reset all ring priorities to 0 */
+       for (i = 0; i < priv->num_tx_rings; i++) {
+               tx_ring = priv->tx_ring[i];
+               tx_ring->prio = 0;
+               enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio);
+       }
+
+       enetc_debug_tx_ring_prios(priv);
+}
 
+int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data)
+{
+       struct enetc_ndev_priv *priv = netdev_priv(ndev);
+       struct tc_mqprio_qopt *mqprio = type_data;
+       struct enetc_hw *hw = &priv->si->hw;
+       int num_stack_tx_queues = 0;
+       u8 num_tc = mqprio->num_tc;
+       struct enetc_bdr *tx_ring;
+       int offset, count;
+       int err, tc, q;
+
+       if (!num_tc) {
+               enetc_reset_tc_mqprio(ndev);
                return 0;
        }
 
-       /* For the moment, we use only one BD ring per TC.
-        *
-        * Configure num_tc BD rings with increasing priorities.
-        */
-       for (i = 0; i < num_tc; i++) {
-               tx_ring = priv->tx_ring[i];
-               tx_ring->prio = i;
-               enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio);
+       err = netdev_set_num_tc(ndev, num_tc);
+       if (err)
+               return err;
+
+       for (tc = 0; tc < num_tc; tc++) {
+               offset = mqprio->offset[tc];
+               count = mqprio->count[tc];
+               num_stack_tx_queues += count;
+
+               err = netdev_set_tc_queue(ndev, tc, count, offset);
+               if (err)
+                       goto err_reset_tc;
+
+               for (q = offset; q < offset + count; q++) {
+                       tx_ring = priv->tx_ring[q];
+                       /* The prio_tc_map is skb_tx_hash()'s way of selecting
+                        * between TX queues based on skb->priority. As such,
+                        * there's nothing to offload based on it.
+                        * Make the mqprio "traffic class" be the priority of
+                        * this ring group, and leave the Tx IPV to traffic
+                        * class mapping as its default mapping value of 1:1.
+                        */
+                       tx_ring->prio = tc;
+                       enetc_set_bdr_prio(hw, tx_ring->index, tx_ring->prio);
+               }
        }
 
-       /* Reset the number of netdev queues based on the TC count */
-       netif_set_real_num_tx_queues(ndev, num_tc);
-       priv->min_num_stack_tx_queues = num_tc;
+       err = netif_set_real_num_tx_queues(ndev, num_stack_tx_queues);
+       if (err)
+               goto err_reset_tc;
 
-       netdev_set_num_tc(ndev, num_tc);
+       priv->min_num_stack_tx_queues = num_stack_tx_queues;
 
-       /* Each TC is associated with one netdev queue */
-       for (i = 0; i < num_tc; i++)
-               netdev_set_tc_queue(ndev, i, 1, i);
+       enetc_debug_tx_ring_prios(priv);
 
        return 0;
+
+err_reset_tc:
+       enetc_reset_tc_mqprio(ndev);
+       return err;
 }
 EXPORT_SYMBOL_GPL(enetc_setup_tc_mqprio);