Skip to content

Commit

Permalink
enetc: Enable TC offloading with mqprio
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Camelia Groza authored and David S. Miller committed May 29, 2019
1 parent 7f33432 commit cbe9e83
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 1 deletion.
56 changes: 56 additions & 0 deletions drivers/net/ethernet/freescale/enetc/enetc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1427,6 +1427,62 @@ int enetc_close(struct net_device *ndev)
return 0;
}

int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void *type_data)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct tc_mqprio_qopt *mqprio = type_data;
struct enetc_bdr *tx_ring;
u8 num_tc;
int i;

if (type != TC_SETUP_QDISC_MQPRIO)
return -EOPNOTSUPP;

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, priv->num_tx_rings);

/* Reset all ring priorities to 0 */
for (i = 0; i < priv->num_tx_rings; i++) {
tx_ring = priv->tx_ring[i];
enetc_set_bdr_prio(&priv->si->hw, tx_ring->index, 0);
}

return 0;
}

/* Check if we have enough BD rings available to accommodate all TCs */
if (num_tc > priv->num_tx_rings) {
netdev_err(ndev, "Max %d traffic classes supported\n",
priv->num_tx_rings);
return -EINVAL;
}

/* 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];
enetc_set_bdr_prio(&priv->si->hw, tx_ring->index, i);
}

/* Reset the number of netdev queues based on the TC count */
netif_set_real_num_tx_queues(ndev, num_tc);

netdev_set_num_tc(ndev, num_tc);

/* Each TC is associated with one netdev queue */
for (i = 0; i < num_tc; i++)
netdev_set_tc_queue(ndev, i, 1, i);

return 0;
}

struct net_device_stats *enetc_get_stats(struct net_device *ndev)
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/freescale/enetc/enetc.h
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,9 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev);
int enetc_set_features(struct net_device *ndev,
netdev_features_t features);
int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd);
int enetc_setup_tc(struct net_device *ndev, enum tc_setup_type type,
void *type_data);

/* ethtool */
void enetc_set_ethtool_ops(struct net_device *ndev);

Expand Down
12 changes: 11 additions & 1 deletion drivers/net/ethernet/freescale/enetc/enetc_hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_TBSR_BUSY BIT(0)
#define ENETC_TBMR_VIH BIT(9)
#define ENETC_TBMR_PRIO_MASK GENMASK(2, 0)
#define ENETC_TBMR_PRIO_SET(val) val
#define ENETC_TBMR_SET_PRIO(val) ((val) & ENETC_TBMR_PRIO_MASK)
#define ENETC_TBMR_EN BIT(31)
#define ENETC_TBSR 0x4
#define ENETC_TBBAR0 0x10
Expand Down Expand Up @@ -544,3 +544,13 @@ static inline void enetc_enable_txvlan(struct enetc_hw *hw, int si_idx,
val = (val & ~ENETC_TBMR_VIH) | (en ? ENETC_TBMR_VIH : 0);
enetc_txbdr_wr(hw, si_idx, ENETC_TBMR, val);
}

static inline void enetc_set_bdr_prio(struct enetc_hw *hw, int bdr_idx,
int prio)
{
u32 val = enetc_txbdr_rd(hw, bdr_idx, ENETC_TBMR);

val &= ~ENETC_TBMR_PRIO_MASK;
val |= ENETC_TBMR_SET_PRIO(prio);
enetc_txbdr_wr(hw, bdr_idx, ENETC_TBMR, val);
}
1 change: 1 addition & 0 deletions drivers/net/ethernet/freescale/enetc/enetc_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,7 @@ static const struct net_device_ops enetc_ndev_ops = {
.ndo_set_vf_spoofchk = enetc_pf_set_vf_spoofchk,
.ndo_set_features = enetc_pf_set_features,
.ndo_do_ioctl = enetc_ioctl,
.ndo_setup_tc = enetc_setup_tc,
};

static void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/freescale/enetc/enetc_vf.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ static const struct net_device_ops enetc_ndev_ops = {
.ndo_set_mac_address = enetc_vf_set_mac_addr,
.ndo_set_features = enetc_vf_set_features,
.ndo_do_ioctl = enetc_ioctl,
.ndo_setup_tc = enetc_setup_tc,
};

static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
Expand Down

0 comments on commit cbe9e83

Please sign in to comment.