Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

enetc: Enable TC offloading with mqprio

Add support to configure multiple prioritized TX traffic
classes with mqprio.

Configure one BD ring per TC for the moment, one netdev
queue per TC.

Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Camelia Groza and committed by
David S. Miller
cbe9e835 7f334323

+72 -1
+56
drivers/net/ethernet/freescale/enetc/enetc.c
··· 1427 1427 return 0; 1428 1428 } 1429 1429 1430 + int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, 1431 + void *type_data) 1432 + { 1433 + struct enetc_ndev_priv *priv = netdev_priv(ndev); 1434 + struct tc_mqprio_qopt *mqprio = type_data; 1435 + struct enetc_bdr *tx_ring; 1436 + u8 num_tc; 1437 + int i; 1438 + 1439 + if (type != TC_SETUP_QDISC_MQPRIO) 1440 + return -EOPNOTSUPP; 1441 + 1442 + mqprio->hw = TC_MQPRIO_HW_OFFLOAD_TCS; 1443 + num_tc = mqprio->num_tc; 1444 + 1445 + if (!num_tc) { 1446 + netdev_reset_tc(ndev); 1447 + netif_set_real_num_tx_queues(ndev, priv->num_tx_rings); 1448 + 1449 + /* Reset all ring priorities to 0 */ 1450 + for (i = 0; i < priv->num_tx_rings; i++) { 1451 + tx_ring = priv->tx_ring[i]; 1452 + enetc_set_bdr_prio(&priv->si->hw, tx_ring->index, 0); 1453 + } 1454 + 1455 + return 0; 1456 + } 1457 + 1458 + /* Check if we have enough BD rings available to accommodate all TCs */ 1459 + if (num_tc > priv->num_tx_rings) { 1460 + netdev_err(ndev, "Max %d traffic classes supported\n", 1461 + priv->num_tx_rings); 1462 + return -EINVAL; 1463 + } 1464 + 1465 + /* For the moment, we use only one BD ring per TC. 1466 + * 1467 + * Configure num_tc BD rings with increasing priorities. 1468 + */ 1469 + for (i = 0; i < num_tc; i++) { 1470 + tx_ring = priv->tx_ring[i]; 1471 + enetc_set_bdr_prio(&priv->si->hw, tx_ring->index, i); 1472 + } 1473 + 1474 + /* Reset the number of netdev queues based on the TC count */ 1475 + netif_set_real_num_tx_queues(ndev, num_tc); 1476 + 1477 + netdev_set_num_tc(ndev, num_tc); 1478 + 1479 + /* Each TC is associated with one netdev queue */ 1480 + for (i = 0; i < num_tc; i++) 1481 + netdev_set_tc_queue(ndev, i, 1, i); 1482 + 1483 + return 0; 1484 + } 1485 + 1430 1486 struct net_device_stats *enetc_get_stats(struct net_device *ndev) 1431 1487 { 1432 1488 struct enetc_ndev_priv *priv = netdev_priv(ndev);
+3
drivers/net/ethernet/freescale/enetc/enetc.h
··· 229 229 int enetc_set_features(struct net_device *ndev, 230 230 netdev_features_t features); 231 231 int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd); 232 + int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type, 233 + void *type_data); 234 + 232 235 /* ethtool */ 233 236 void enetc_set_ethtool_ops(struct net_device *ndev); 234 237
+11 -1
drivers/net/ethernet/freescale/enetc/enetc_hw.h
··· 127 127 #define ENETC_TBSR_BUSY BIT(0) 128 128 #define ENETC_TBMR_VIH BIT(9) 129 129 #define ENETC_TBMR_PRIO_MASK GENMASK(2, 0) 130 - #define ENETC_TBMR_PRIO_SET(val) val 130 + #define ENETC_TBMR_SET_PRIO(val) ((val) & ENETC_TBMR_PRIO_MASK) 131 131 #define ENETC_TBMR_EN BIT(31) 132 132 #define ENETC_TBSR 0x4 133 133 #define ENETC_TBBAR0 0x10 ··· 543 543 544 544 val = (val & ~ENETC_TBMR_VIH) | (en ? ENETC_TBMR_VIH : 0); 545 545 enetc_txbdr_wr(hw, si_idx, ENETC_TBMR, val); 546 + } 547 + 548 + static inline void enetc_set_bdr_prio(struct enetc_hw *hw, int bdr_idx, 549 + int prio) 550 + { 551 + u32 val = enetc_txbdr_rd(hw, bdr_idx, ENETC_TBMR); 552 + 553 + val &= ~ENETC_TBMR_PRIO_MASK; 554 + val |= ENETC_TBMR_SET_PRIO(prio); 555 + enetc_txbdr_wr(hw, bdr_idx, ENETC_TBMR, val); 546 556 }
+1
drivers/net/ethernet/freescale/enetc/enetc_pf.c
··· 703 703 .ndo_set_vf_spoofchk = enetc_pf_set_vf_spoofchk, 704 704 .ndo_set_features = enetc_pf_set_features, 705 705 .ndo_do_ioctl = enetc_ioctl, 706 + .ndo_setup_tc = enetc_setup_tc, 706 707 }; 707 708 708 709 static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
+1
drivers/net/ethernet/freescale/enetc/enetc_vf.c
··· 112 112 .ndo_set_mac_address = enetc_vf_set_mac_addr, 113 113 .ndo_set_features = enetc_vf_set_features, 114 114 .ndo_do_ioctl = enetc_ioctl, 115 + .ndo_setup_tc = enetc_setup_tc, 115 116 }; 116 117 117 118 static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,