[PATCH 2/2] bnx2x: Support for RX queue weights
From: Tom Herbert <hidden>
Date: 2011-02-12 00:00:57
Subsystem:
networking drivers, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Apply relative weights to populate the RSS indirection table. Signed-off-by: Tom Herbert <redacted> --- drivers/net/bnx2x/bnx2x_main.c | 76 +++++++++++++++++++++++++++++++++++---- 1 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c
index c238c4d..3fb83ee 100644
--- a/drivers/net/bnx2x/bnx2x_main.c
+++ b/drivers/net/bnx2x/bnx2x_main.c@@ -4257,18 +4257,65 @@ static void bnx2x_init_eq_ring(struct bnx2x *bp) static void bnx2x_init_ind_table(struct bnx2x *bp) { int func = BP_FUNC(bp); - int i; + int i, j, num_queues, slots; + int index = 0, max_weight_queue = 0; + u32 weight, max_weight = 0; + u64 frac = 0, sum = 0; if (bp->multi_mode == ETH_RSS_MODE_DISABLED) return; - DP(NETIF_MSG_IFUP, - "Initializing indirection table multi_mode %d\n", bp->multi_mode); - for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) - REG_WR8(bp, BAR_TSTRORM_INTMEM + - TSTORM_INDIRECTION_TABLE_OFFSET(func) + i, - bp->fp->cl_id + (i % (bp->num_queues - - NONE_ETH_CONTEXT_USE))); + num_queues = bp->num_queues - NONE_ETH_CONTEXT_USE; + for (i = 0; i < num_queues; i++) + sum += netdev_rxq_weight(bp->dev, i); + + if (!sum) { + /* All weights zero. Just apply equal weighting */ + for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++) + REG_WR8(bp, BAR_TSTRORM_INTMEM + + TSTORM_INDIRECTION_TABLE_OFFSET(func) + i, + bp->fp->cl_id + (i % (bp->num_queues - + NONE_ETH_CONTEXT_USE))); + } else { + /* + * For each queue, compute number of slots to allocate + * based on the relative weights. This is essentially: + * + * num_slots = (weight / sum_of_weights) * table_size + frac + * + * frac is the fraction carried over from the previous + * queue's calculation. At the end if there's any fraction + * remaining, the queue with highest weight is assigned to the + * last slot. + * + * This algorithm should result in all slots always being + * set. Note that this recomputes the whole table after + * each weight change, this should not be an issue if this + * operation is fairly rare. + */ + for (i = 0; i < bp->num_queues; i++) { + weight = netdev_rxq_weight(bp->dev, i); + if (weight > max_weight) { + max_weight = weight; + max_weight_queue = i; + } + frac = (((u64)weight << 32) / sum) * + TSTORM_INDIRECTION_TABLE_SIZE + frac; + slots = frac >> 32; + frac -= (u64)slots << 32; + for (j = 0; j < slots; j++, index++) + REG_WR8(bp, BAR_TSTRORM_INTMEM + + TSTORM_INDIRECTION_TABLE_OFFSET(func) + + index, bp->fp->cl_id + i); + } + if (frac) { + REG_WR8(bp, BAR_TSTRORM_INTMEM + + TSTORM_INDIRECTION_TABLE_OFFSET(func) + index, + bp->fp->cl_id + max_weight_queue); + index++; + } + BUG_ON(index != TSTORM_INDIRECTION_TABLE_SIZE); + } } void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
@@ -9278,6 +9325,16 @@ static void poll_bnx2x(struct net_device *dev) } #endif +#ifdef CONFIG_RPS +void bnx2x_set_rxq_weight(struct net_device *dev, u16 rxq, u32 weight) +{ + struct bnx2x *bp = netdev_priv(dev); + + /* Reinitialize the whole table */ + bnx2x_init_ind_table(bp); +} +#endif + static const struct net_device_ops bnx2x_netdev_ops = { .ndo_open = bnx2x_open, .ndo_stop = bnx2x_close,
@@ -9292,6 +9349,9 @@ static const struct net_device_ops bnx2x_netdev_ops = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = poll_bnx2x, #endif +#ifdef CONFIG_RPS + .ndo_set_rxq_weight = bnx2x_set_rxq_weight, +#endif }; static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
--
1.7.3.1