123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- From: Gregory CLEMENT <gregory.clement@free-electrons.com>
- Date: Wed, 9 Dec 2015 18:23:51 +0100
- Subject: [PATCH] net: mvneta: Configure XPS support
- With this patch each CPU is associated with its own set of TX queues.
- It also setup the XPS with an initial configuration which set the
- affinity matching the hardware configuration.
- Suggested-by: Arnd Bergmann <arnd@arndb.de>
- Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
- Signed-off-by: David S. Miller <davem@davemloft.net>
- ---
- --- a/drivers/net/ethernet/marvell/mvneta.c
- +++ b/drivers/net/ethernet/marvell/mvneta.c
- @@ -111,6 +111,7 @@
- #define MVNETA_CPU_RXQ_ACCESS_ALL_MASK 0x000000ff
- #define MVNETA_CPU_TXQ_ACCESS_ALL_MASK 0x0000ff00
- #define MVNETA_CPU_RXQ_ACCESS(rxq) BIT(rxq)
- +#define MVNETA_CPU_TXQ_ACCESS(txq) BIT(txq + 8)
- #define MVNETA_RXQ_TIME_COAL_REG(q) (0x2580 + ((q) << 2))
-
- /* Exception Interrupt Port/Queue Cause register
- @@ -514,6 +515,9 @@ struct mvneta_tx_queue {
-
- /* DMA address of TSO headers */
- dma_addr_t tso_hdrs_phys;
- +
- + /* Affinity mask for CPUs*/
- + cpumask_t affinity_mask;
- };
-
- struct mvneta_rx_queue {
- @@ -1062,20 +1066,30 @@ static void mvneta_defaults_set(struct m
- /* Enable MBUS Retry bit16 */
- mvreg_write(pp, MVNETA_MBUS_RETRY, 0x20);
-
- - /* Set CPU queue access map. CPUs are assigned to the RX
- - * queues modulo their number and all the TX queues are
- - * assigned to the CPU associated to the default RX queue.
- + /* Set CPU queue access map. CPUs are assigned to the RX and
- + * TX queues modulo their number. If there is only one TX
- + * queue then it is assigned to the CPU associated to the
- + * default RX queue.
- */
- for_each_present_cpu(cpu) {
- int rxq_map = 0, txq_map = 0;
- - int rxq;
- + int rxq, txq;
-
- for (rxq = 0; rxq < rxq_number; rxq++)
- if ((rxq % max_cpu) == cpu)
- rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
-
- - if (cpu == pp->rxq_def)
- - txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
- + for (txq = 0; txq < txq_number; txq++)
- + if ((txq % max_cpu) == cpu)
- + txq_map |= MVNETA_CPU_TXQ_ACCESS(txq);
- +
- + /* With only one TX queue we configure a special case
- + * which will allow to get all the irq on a single
- + * CPU
- + */
- + if (txq_number == 1)
- + txq_map = (cpu == pp->rxq_def) ?
- + MVNETA_CPU_TXQ_ACCESS(1) : 0;
-
- mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map);
- }
- @@ -2362,6 +2376,8 @@ static void mvneta_rxq_deinit(struct mvn
- static int mvneta_txq_init(struct mvneta_port *pp,
- struct mvneta_tx_queue *txq)
- {
- + int cpu;
- +
- txq->size = pp->tx_ring_size;
-
- /* A queue must always have room for at least one skb.
- @@ -2414,6 +2430,14 @@ static int mvneta_txq_init(struct mvneta
- }
- mvneta_tx_done_pkts_coal_set(pp, txq, txq->done_pkts_coal);
-
- + /* Setup XPS mapping */
- + if (txq_number > 1)
- + cpu = txq->id % num_present_cpus();
- + else
- + cpu = pp->rxq_def % num_present_cpus();
- + cpumask_set_cpu(cpu, &txq->affinity_mask);
- + netif_set_xps_queue(pp->dev, &txq->affinity_mask, txq->id);
- +
- return 0;
- }
-
- @@ -2836,13 +2860,23 @@ static void mvneta_percpu_elect(struct m
- if ((rxq % max_cpu) == cpu)
- rxq_map |= MVNETA_CPU_RXQ_ACCESS(rxq);
-
- - if (i == online_cpu_idx) {
- - /* Map the default receive queue and transmit
- - * queue to the elected CPU
- + if (i == online_cpu_idx)
- + /* Map the default receive queue queue to the
- + * elected CPU
- */
- rxq_map |= MVNETA_CPU_RXQ_ACCESS(pp->rxq_def);
- - txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
- - }
- +
- + /* We update the TX queue map only if we have one
- + * queue. In this case we associate the TX queue to
- + * the CPU bound to the default RX queue
- + */
- + if (txq_number == 1)
- + txq_map = (i == online_cpu_idx) ?
- + MVNETA_CPU_TXQ_ACCESS(1) : 0;
- + else
- + txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) &
- + MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
- +
- mvreg_write(pp, MVNETA_CPU_MAP(cpu), rxq_map | txq_map);
-
- /* Update the interrupt mask on each CPU according the
|