int mlx4_en_setup_tc(struct net_device *dev, u8 up) { struct mlx4_en_priv *priv = netdev_priv(dev); int i; unsigned int offset = 0; if (up && up != MLX4_EN_NUM_UP) return -EINVAL; netdev_set_num_tc(dev, up); /* Partition Tx queues evenly amongst UP's */ for (i = 0; i < up; i++) { netdev_set_tc_queue(dev, i, priv->num_tx_rings_p_up, offset); offset += priv->num_tx_rings_p_up; } return 0; }
static inline bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) { int per_tc_q, q, i, offset = 0; struct net_device *dev = adapter->netdev; int tcs = netdev_get_num_tc(dev); if (!tcs) return false; /* Map queue offset and counts onto allocated tx queues */ per_tc_q = min_t(unsigned int, dev->num_tx_queues / tcs, DCB_QUEUE_CAP); q = min_t(int, num_online_cpus(), per_tc_q); for (i = 0; i < tcs; i++) { netdev_set_tc_queue(dev, i, q, offset); offset += q; } adapter->num_tx_queues = q * tcs; adapter->num_rx_queues = q * tcs; #ifdef IXGBE_FCOE /* FCoE enabled queues require special configuration indexed * by feature specific indices and mask. Here we map FCoE * indices onto the DCB queue pairs allowing FCoE to own * configuration later. */ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { u8 prio_tc[MAX_USER_PRIORITY] = {0}; int tc; struct ixgbe_ring_feature *f = &adapter->ring_feature[RING_F_FCOE]; ixgbe_dcb_unpack_map(&adapter->dcb_cfg, DCB_TX_CONFIG, prio_tc); tc = prio_tc[adapter->fcoe.up]; f->indices = dev->tc_to_txq[tc].count; f->mask = dev->tc_to_txq[tc].offset; } #endif return true; }
static bool ixgbe_set_dcb_queues(struct ixgbe_adapter *adapter) { struct net_device *dev = adapter->netdev; struct ixgbe_ring_feature *f; int rss_i, rss_m, i; int tcs; /* Map queue offset and counts onto allocated tx queues */ tcs = netdev_get_num_tc(dev); /* verify we have DCB queueing enabled before proceeding */ if (tcs <= 1) return false; /* determine the upper limit for our current DCB mode */ rss_i = dev->num_tx_queues / tcs; if (adapter->hw.mac.type == ixgbe_mac_82598EB) { /* 8 TC w/ 4 queues per TC */ rss_i = min_t(u16, rss_i, 4); rss_m = IXGBE_RSS_4Q_MASK; } else if (tcs > 4) { /* 8 TC w/ 8 queues per TC */ rss_i = min_t(u16, rss_i, 8); rss_m = IXGBE_RSS_8Q_MASK; } else { /* 4 TC w/ 16 queues per TC */ rss_i = min_t(u16, rss_i, 16); rss_m = IXGBE_RSS_16Q_MASK; } /* set RSS mask and indices */ f = &adapter->ring_feature[RING_F_RSS]; rss_i = min_t(int, rss_i, f->limit); f->indices = rss_i; f->mask = rss_m; /* disable ATR as it is not supported when multiple TCs are enabled */ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; #ifdef IXGBE_FCOE /* FCoE enabled queues require special configuration indexed * by feature specific indices and offset. Here we map FCoE * indices onto the DCB queue pairs allowing FCoE to own * configuration later. */ if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { u8 tc = ixgbe_fcoe_get_tc(adapter); f = &adapter->ring_feature[RING_F_FCOE]; f->indices = min_t(u16, rss_i, f->limit); f->offset = rss_i * tc; } #endif /* IXGBE_FCOE */ for (i = 0; i < tcs; i++) netdev_set_tc_queue(dev, i, rss_i, rss_i * i); adapter->num_tx_queues = rss_i * tcs; adapter->num_rx_queues = rss_i * tcs; return true; }
/** * ixgbe_set_dcb_sriov_queues: Allocate queues for SR-IOV devices w/ DCB * @adapter: board private structure to initialize * * When SR-IOV (Single Root IO Virtualiztion) is enabled, allocate queues * and VM pools where appropriate. Also assign queues based on DCB * priorities and map accordingly.. * **/ static bool ixgbe_set_dcb_sriov_queues(struct ixgbe_adapter *adapter) { int i; u16 vmdq_i = adapter->ring_feature[RING_F_VMDQ].limit; u16 vmdq_m = 0; #ifdef IXGBE_FCOE u16 fcoe_i = 0; #endif u8 tcs = netdev_get_num_tc(adapter->netdev); /* verify we have DCB queueing enabled before proceeding */ if (tcs <= 1) return false; /* verify we have VMDq enabled before proceeding */ if (!(adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)) return false; /* Add starting offset to total pool count */ vmdq_i += adapter->ring_feature[RING_F_VMDQ].offset; /* 16 pools w/ 8 TC per pool */ if (tcs > 4) { vmdq_i = min_t(u16, vmdq_i, 16); vmdq_m = IXGBE_82599_VMDQ_8Q_MASK; /* 32 pools w/ 4 TC per pool */ } else { vmdq_i = min_t(u16, vmdq_i, 32); vmdq_m = IXGBE_82599_VMDQ_4Q_MASK; } #ifdef IXGBE_FCOE /* queues in the remaining pools are available for FCoE */ fcoe_i = (128 / __ALIGN_MASK(1, ~vmdq_m)) - vmdq_i; #endif /* remove the starting offset from the pool count */ vmdq_i -= adapter->ring_feature[RING_F_VMDQ].offset; /* save features for later use */ adapter->ring_feature[RING_F_VMDQ].indices = vmdq_i; adapter->ring_feature[RING_F_VMDQ].mask = vmdq_m; /* * We do not support DCB, VMDq, and RSS all simultaneously * so we will disable RSS since it is the lowest priority */ adapter->ring_feature[RING_F_RSS].indices = 1; adapter->ring_feature[RING_F_RSS].mask = IXGBE_RSS_DISABLED_MASK; /* disable ATR as it is not supported when VMDq is enabled */ adapter->flags &= ~IXGBE_FLAG_FDIR_HASH_CAPABLE; adapter->num_rx_pools = vmdq_i; adapter->num_rx_queues_per_pool = tcs; adapter->num_tx_queues = vmdq_i * tcs; adapter->num_rx_queues = vmdq_i * tcs; #ifdef IXGBE_FCOE if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) { struct ixgbe_ring_feature *fcoe; fcoe = &adapter->ring_feature[RING_F_FCOE]; /* limit ourselves based on feature limits */ fcoe_i = min_t(u16, fcoe_i, fcoe->limit); if (fcoe_i) { /* alloc queues for FCoE separately */ fcoe->indices = fcoe_i; fcoe->offset = vmdq_i * tcs; /* add queues to adapter */ adapter->num_tx_queues += fcoe_i; adapter->num_rx_queues += fcoe_i; } else if (tcs > 1) { /* use queue belonging to FcoE TC */ fcoe->indices = 1; fcoe->offset = ixgbe_fcoe_get_tc(adapter); } else { adapter->flags &= ~IXGBE_FLAG_FCOE_ENABLED; fcoe->indices = 0; fcoe->offset = 0; } } #endif /* IXGBE_FCOE */ /* configure TC to queue mapping */ for (i = 0; i < tcs; i++) netdev_set_tc_queue(adapter->netdev, i, 1, i); return true; }
static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) { struct net_device *dev = qdisc_dev(sch); struct mqprio_sched *priv = qdisc_priv(sch); struct netdev_queue *dev_queue; struct Qdisc *qdisc; int i, err = -EOPNOTSUPP; struct tc_mqprio_qopt *qopt = NULL; BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); if (sch->parent != TC_H_ROOT) return -EOPNOTSUPP; if (!netif_is_multiqueue(dev)) return -EOPNOTSUPP; if (nla_len(opt) < sizeof(*qopt)) return -EINVAL; qopt = nla_data(opt); if (mqprio_parse_opt(dev, qopt)) return -EINVAL; /* pre-allocate qdisc, attachment can't fail */ priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), GFP_KERNEL); if (priv->qdiscs == NULL) { err = -ENOMEM; goto err; } for (i = 0; i < dev->num_tx_queues; i++) { dev_queue = netdev_get_tx_queue(dev, i); qdisc = qdisc_create_dflt(dev_queue, &pfifo_fast_ops, TC_H_MAKE(TC_H_MAJ(sch->handle), TC_H_MIN(i + 1))); if (qdisc == NULL) { err = -ENOMEM; goto err; } priv->qdiscs[i] = qdisc; } /* If the mqprio options indicate that hardware should own * the queue mapping then run ndo_setup_tc otherwise use the * supplied and verified mapping */ if (qopt->hw) { priv->hw_owned = 1; err = dev->netdev_ops->ndo_setup_tc(dev, qopt->num_tc); if (err) goto err; } else { netdev_set_num_tc(dev, qopt->num_tc); for (i = 0; i < qopt->num_tc; i++) netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); } /* Always use supplied priority mappings */ for (i = 0; i < TC_BITMASK + 1; i++) netdev_set_prio_tc_map(dev, i, qopt->prio_tc_map[i]); sch->flags |= TCQ_F_MQROOT; return 0; err: mqprio_destroy(sch); return err; }
static int mqprio_init(struct Qdisc *sch, struct nlattr *opt) { struct net_device *dev = qdisc_dev(sch); struct mqprio_sched *priv = qdisc_priv(sch); struct netdev_queue *dev_queue; struct Qdisc *qdisc; int i, err = -EOPNOTSUPP; struct tc_mqprio_qopt *qopt = NULL; BUILD_BUG_ON(TC_MAX_QUEUE != TC_QOPT_MAX_QUEUE); BUILD_BUG_ON(TC_BITMASK != TC_QOPT_BITMASK); if (sch->parent != TC_H_ROOT) return -EOPNOTSUPP; if (!netif_is_multiqueue(dev)) return -EOPNOTSUPP; if (!opt || nla_len(opt) < sizeof(*qopt)) return -EINVAL; qopt = nla_data(opt); if (mqprio_parse_opt(dev, qopt)) return -EINVAL; /* pre-allocate qdisc, attachment can't fail */ priv->qdiscs = kcalloc(dev->num_tx_queues, sizeof(priv->qdiscs[0]), GFP_KERNEL); if (priv->qdiscs == NULL) { err = -ENOMEM; goto err; } for (i = 0; i < dev->num_tx_queues; i++) { dev_queue = netdev_get_tx_queue(dev, i); qdisc = qdisc_create_dflt(dev, dev_queue, &pfifo_fast_ops, TC_H_MAKE(TC_H_MAJ(sch->handle), TC_H_MIN(i + 1))); if (qdisc == NULL) { err = -ENOMEM; goto err; } qdisc->flags |= TCQ_F_CAN_BYPASS; priv->qdiscs[i] = qdisc; } netdev_set_num_tc(dev, qopt->num_tc); for (i = 0; i < qopt->num_tc; i++) netdev_set_tc_queue(dev, i, qopt->count[i], qopt->offset[i]); /* Always use supplied priority mappings */ for (i = 0; i < TC_BITMASK + 1; i++) netdev_set_prio_tc_map(dev, i, qopt->prio_tc_map[i]); sch->flags |= TCQ_F_MQROOT; return 0; err: mqprio_destroy(sch); return err; }