Skip to content

Commit 556fdfd

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
i40e/i40evf: Split container ITR into current_itr and target_itr
This patch is mostly prep-work for replacing the current approach to programming the dynamic aka adaptive ITR. Specifically here what we are doing is splitting the Tx and Rx ITR each into two separate values. The first value current_itr represents the current value of the register. The second value target_itr represents the desired value of the register. The general plan by doing this is to allow for deferring the update of the ITR value under certain circumstances. For now we will work with what we have, but in the future I hope to change the behavior so that we always only update one ITR at a time using some simple logic to determine which ITR requires an update. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
1 parent d4942d5 commit 556fdfd

File tree

8 files changed

+115
-86
lines changed

8 files changed

+115
-86
lines changed

drivers/net/ethernet/intel/i40e/i40e_ethtool.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2329,14 +2329,15 @@ static void i40e_set_itr_per_queue(struct i40e_vsi *vsi,
23292329
tx_ring->itr_setting &= ~I40E_ITR_DYNAMIC;
23302330

23312331
q_vector = rx_ring->q_vector;
2332-
q_vector->rx.itr = ITR_TO_REG(rx_ring->itr_setting);
2333-
wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, q_vector->reg_idx),
2334-
q_vector->rx.itr);
2332+
q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
23352333

23362334
q_vector = tx_ring->q_vector;
2337-
q_vector->tx.itr = ITR_TO_REG(tx_ring->itr_setting);
2338-
wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, q_vector->reg_idx),
2339-
q_vector->tx.itr);
2335+
q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
2336+
2337+
/* The interrupt handler itself will take care of programming
2338+
* the Tx and Rx ITR values based on the values we have entered
2339+
* into the q_vector, no need to write the values now.
2340+
*/
23402341

23412342
wr32(hw, I40E_PFINT_RATEN(q_vector->reg_idx), intrl);
23422343
i40e_flush(hw);

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3450,14 +3450,18 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
34503450
struct i40e_q_vector *q_vector = vsi->q_vectors[i];
34513451

34523452
q_vector->itr_countdown = ITR_COUNTDOWN_START;
3453-
q_vector->rx.itr = ITR_TO_REG(vsi->rx_rings[i]->itr_setting);
3453+
q_vector->rx.target_itr =
3454+
ITR_TO_REG(vsi->rx_rings[i]->itr_setting);
34543455
q_vector->rx.latency_range = I40E_LOW_LATENCY;
34553456
wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1),
3456-
q_vector->rx.itr);
3457-
q_vector->tx.itr = ITR_TO_REG(vsi->tx_rings[i]->itr_setting);
3457+
q_vector->rx.target_itr);
3458+
q_vector->rx.current_itr = q_vector->rx.target_itr;
3459+
q_vector->tx.target_itr =
3460+
ITR_TO_REG(vsi->tx_rings[i]->itr_setting);
34583461
q_vector->tx.latency_range = I40E_LOW_LATENCY;
34593462
wr32(hw, I40E_PFINT_ITRN(I40E_TX_ITR, vector - 1),
3460-
q_vector->tx.itr);
3463+
q_vector->tx.target_itr);
3464+
q_vector->tx.current_itr = q_vector->tx.target_itr;
34613465
wr32(hw, I40E_PFINT_RATEN(vector - 1),
34623466
i40e_intrl_usec_to_reg(vsi->int_rate_limit));
34633467

@@ -3559,12 +3563,14 @@ static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi)
35593563

35603564
/* set the ITR configuration */
35613565
q_vector->itr_countdown = ITR_COUNTDOWN_START;
3562-
q_vector->rx.itr = ITR_TO_REG(vsi->rx_rings[0]->itr_setting);
3566+
q_vector->rx.target_itr = ITR_TO_REG(vsi->rx_rings[0]->itr_setting);
35633567
q_vector->rx.latency_range = I40E_LOW_LATENCY;
3564-
wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.itr);
3565-
q_vector->tx.itr = ITR_TO_REG(vsi->tx_rings[0]->itr_setting);
3568+
wr32(hw, I40E_PFINT_ITR0(I40E_RX_ITR), q_vector->rx.target_itr);
3569+
q_vector->rx.current_itr = q_vector->rx.target_itr;
3570+
q_vector->tx.target_itr = ITR_TO_REG(vsi->tx_rings[0]->itr_setting);
35663571
q_vector->tx.latency_range = I40E_LOW_LATENCY;
3567-
wr32(hw, I40E_PFINT_ITR0(I40E_TX_ITR), q_vector->tx.itr);
3572+
wr32(hw, I40E_PFINT_ITR0(I40E_TX_ITR), q_vector->tx.target_itr);
3573+
q_vector->tx.current_itr = q_vector->tx.target_itr;
35683574

35693575
i40e_enable_misc_int_causes(pf);
35703576

drivers/net/ethernet/intel/i40e/i40e_txrx.c

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,17 +1012,16 @@ void i40e_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
10121012
static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
10131013
{
10141014
enum i40e_latency_range new_latency_range = rc->latency_range;
1015-
u32 new_itr = rc->itr;
10161015
int bytes_per_usec;
10171016
unsigned int usecs, estimated_usecs;
10181017

10191018
if (!rc->ring || !ITR_IS_DYNAMIC(rc->ring->itr_setting))
10201019
return false;
10211020

1022-
if (rc->total_packets == 0 || !rc->itr)
1021+
if (!rc->total_packets || !rc->current_itr)
10231022
return false;
10241023

1025-
usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
1024+
usecs = (rc->current_itr << 1) * ITR_COUNTDOWN_START;
10261025
bytes_per_usec = rc->total_bytes / usecs;
10271026

10281027
/* The calculations in this algorithm depend on interrupts actually
@@ -1070,13 +1069,13 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
10701069

10711070
switch (new_latency_range) {
10721071
case I40E_LOWEST_LATENCY:
1073-
new_itr = I40E_ITR_50K;
1072+
rc->target_itr = I40E_ITR_50K;
10741073
break;
10751074
case I40E_LOW_LATENCY:
1076-
new_itr = I40E_ITR_20K;
1075+
rc->target_itr = I40E_ITR_20K;
10771076
break;
10781077
case I40E_BULK_LATENCY:
1079-
new_itr = I40E_ITR_18K;
1078+
rc->target_itr = I40E_ITR_18K;
10801079
break;
10811080
default:
10821081
break;
@@ -1086,11 +1085,7 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
10861085
rc->total_packets = 0;
10871086
rc->last_itr_update = jiffies;
10881087

1089-
if (new_itr != rc->itr) {
1090-
rc->itr = new_itr;
1091-
return true;
1092-
}
1093-
return false;
1088+
return rc->target_itr != rc->current_itr;
10941089
}
10951090

10961091
/**
@@ -2319,16 +2314,14 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
23192314
{
23202315
struct i40e_hw *hw = &vsi->back->hw;
23212316
bool rx = false, tx = false;
2322-
u32 txval;
2317+
u32 intval;
23232318

23242319
/* If we don't have MSIX, then we only need to re-enable icr0 */
23252320
if (!(vsi->back->flags & I40E_FLAG_MSIX_ENABLED)) {
23262321
i40e_irq_dynamic_enable_icr0(vsi->back);
23272322
return;
23282323
}
23292324

2330-
txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
2331-
23322325
/* avoid dynamic calculation if in countdown mode */
23332326
if (q_vector->itr_countdown > 0)
23342327
goto enable_int;
@@ -2342,26 +2335,43 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
23422335
* use the same value for both ITR registers
23432336
* when in adaptive mode (Rx and/or Tx)
23442337
*/
2345-
u16 itr = max(q_vector->tx.itr, q_vector->rx.itr);
2346-
u32 rxval;
2347-
2348-
q_vector->tx.itr = q_vector->rx.itr = itr;
2349-
2350-
/* set the INTENA_MSK_MASK so that this first write
2351-
* won't actually enable the interrupt, instead just
2352-
* updating the ITR (it's bit 31 PF and VF)
2353-
*/
2354-
rxval = i40e_buildreg_itr(I40E_RX_ITR, itr) | BIT(31);
2338+
u16 itr = max(q_vector->tx.target_itr,
2339+
q_vector->rx.target_itr);
23552340

2356-
/* don't check _DOWN because interrupt isn't being enabled */
2357-
wr32(hw, INTREG(q_vector->reg_idx), rxval);
2358-
2359-
txval = i40e_buildreg_itr(I40E_TX_ITR, itr);
2341+
q_vector->tx.target_itr = itr;
2342+
q_vector->rx.target_itr = itr;
23602343
}
23612344

23622345
enable_int:
2346+
if (q_vector->rx.target_itr != q_vector->rx.current_itr) {
2347+
intval = i40e_buildreg_itr(I40E_RX_ITR,
2348+
q_vector->rx.target_itr);
2349+
q_vector->rx.current_itr = q_vector->rx.target_itr;
2350+
2351+
if (q_vector->tx.target_itr != q_vector->tx.current_itr) {
2352+
/* set the INTENA_MSK_MASK so that this first write
2353+
* won't actually enable the interrupt, instead just
2354+
* updating the ITR (it's bit 31 PF and VF)
2355+
*
2356+
* don't check _DOWN because interrupt isn't being
2357+
* enabled
2358+
*/
2359+
wr32(hw, INTREG(q_vector->reg_idx),
2360+
intval | BIT(31));
2361+
/* now that Rx is done process Tx update */
2362+
goto update_tx;
2363+
}
2364+
} else if (q_vector->tx.target_itr != q_vector->tx.current_itr) {
2365+
update_tx:
2366+
intval = i40e_buildreg_itr(I40E_TX_ITR,
2367+
q_vector->tx.target_itr);
2368+
q_vector->tx.current_itr = q_vector->tx.target_itr;
2369+
} else {
2370+
intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
2371+
}
2372+
23632373
if (!test_bit(__I40E_VSI_DOWN, vsi->state))
2364-
wr32(hw, INTREG(q_vector->reg_idx), txval);
2374+
wr32(hw, INTREG(q_vector->reg_idx), intval);
23652375

23662376
if (q_vector->itr_countdown)
23672377
q_vector->itr_countdown--;

drivers/net/ethernet/intel/i40e/i40e_txrx.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,8 @@ struct i40e_ring_container {
477477
unsigned long last_itr_update; /* jiffies of last ITR update */
478478
u16 count;
479479
enum i40e_latency_range latency_range;
480-
u16 itr;
480+
u16 target_itr; /* target ITR setting for ring(s) */
481+
u16 current_itr; /* current ITR setting for ring(s) */
481482
};
482483

483484
/* iterator for handling rings in ring container */

drivers/net/ethernet/intel/i40evf/i40e_txrx.c

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -409,17 +409,16 @@ void i40evf_force_wb(struct i40e_vsi *vsi, struct i40e_q_vector *q_vector)
409409
static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
410410
{
411411
enum i40e_latency_range new_latency_range = rc->latency_range;
412-
u32 new_itr = rc->itr;
413412
int bytes_per_usec;
414413
unsigned int usecs, estimated_usecs;
415414

416415
if (!rc->ring || !ITR_IS_DYNAMIC(rc->ring->itr_setting))
417416
return false;
418417

419-
if (rc->total_packets == 0 || !rc->itr)
418+
if (!rc->total_packets || !rc->current_itr)
420419
return false;
421420

422-
usecs = (rc->itr << 1) * ITR_COUNTDOWN_START;
421+
usecs = (rc->current_itr << 1) * ITR_COUNTDOWN_START;
423422
bytes_per_usec = rc->total_bytes / usecs;
424423

425424
/* The calculations in this algorithm depend on interrupts actually
@@ -467,13 +466,13 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
467466

468467
switch (new_latency_range) {
469468
case I40E_LOWEST_LATENCY:
470-
new_itr = I40E_ITR_50K;
469+
rc->target_itr = I40E_ITR_50K;
471470
break;
472471
case I40E_LOW_LATENCY:
473-
new_itr = I40E_ITR_20K;
472+
rc->target_itr = I40E_ITR_20K;
474473
break;
475474
case I40E_BULK_LATENCY:
476-
new_itr = I40E_ITR_18K;
475+
rc->target_itr = I40E_ITR_18K;
477476
break;
478477
default:
479478
break;
@@ -483,11 +482,7 @@ static bool i40e_set_new_dynamic_itr(struct i40e_ring_container *rc)
483482
rc->total_packets = 0;
484483
rc->last_itr_update = jiffies;
485484

486-
if (new_itr != rc->itr) {
487-
rc->itr = new_itr;
488-
return true;
489-
}
490-
return false;
485+
return rc->target_itr != rc->current_itr;
491486
}
492487

493488
/**
@@ -1502,9 +1497,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
15021497
{
15031498
struct i40e_hw *hw = &vsi->back->hw;
15041499
bool rx = false, tx = false;
1505-
u32 txval;
1506-
1507-
txval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
1500+
u32 intval;
15081501

15091502
/* avoid dynamic calculation if in countdown mode */
15101503
if (q_vector->itr_countdown > 0)
@@ -1519,26 +1512,43 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
15191512
* use the same value for both ITR registers
15201513
* when in adaptive mode (Rx and/or Tx)
15211514
*/
1522-
u16 itr = max(q_vector->tx.itr, q_vector->rx.itr);
1523-
u32 rxval;
1524-
1525-
q_vector->tx.itr = q_vector->rx.itr = itr;
1526-
1527-
/* set the INTENA_MSK_MASK so that this first write
1528-
* won't actually enable the interrupt, instead just
1529-
* updating the ITR (it's bit 31 PF and VF)
1530-
*/
1531-
rxval = i40e_buildreg_itr(I40E_RX_ITR, itr) | BIT(31);
1515+
u16 itr = max(q_vector->tx.target_itr,
1516+
q_vector->rx.target_itr);
15321517

1533-
/* don't check _DOWN because interrupt isn't being enabled */
1534-
wr32(hw, INTREG(q_vector->reg_idx), rxval);
1535-
1536-
txval = i40e_buildreg_itr(I40E_TX_ITR, itr);
1518+
q_vector->tx.target_itr = itr;
1519+
q_vector->rx.target_itr = itr;
15371520
}
15381521

15391522
enable_int:
1523+
if (q_vector->rx.target_itr != q_vector->rx.current_itr) {
1524+
intval = i40e_buildreg_itr(I40E_RX_ITR,
1525+
q_vector->rx.target_itr);
1526+
q_vector->rx.current_itr = q_vector->rx.target_itr;
1527+
1528+
if (q_vector->tx.target_itr != q_vector->tx.current_itr) {
1529+
/* set the INTENA_MSK_MASK so that this first write
1530+
* won't actually enable the interrupt, instead just
1531+
* updating the ITR (it's bit 31 PF and VF)
1532+
*
1533+
* don't check _DOWN because interrupt isn't being
1534+
* enabled
1535+
*/
1536+
wr32(hw, INTREG(q_vector->reg_idx),
1537+
intval | BIT(31));
1538+
/* now that Rx is done process Tx update */
1539+
goto update_tx;
1540+
}
1541+
} else if (q_vector->tx.target_itr != q_vector->tx.current_itr) {
1542+
update_tx:
1543+
intval = i40e_buildreg_itr(I40E_TX_ITR,
1544+
q_vector->tx.target_itr);
1545+
q_vector->tx.current_itr = q_vector->tx.target_itr;
1546+
} else {
1547+
intval = i40e_buildreg_itr(I40E_ITR_NONE, 0);
1548+
}
1549+
15401550
if (!test_bit(__I40E_VSI_DOWN, vsi->state))
1541-
wr32(hw, INTREG(q_vector->reg_idx), txval);
1551+
wr32(hw, INTREG(q_vector->reg_idx), intval);
15421552

15431553
if (q_vector->itr_countdown)
15441554
q_vector->itr_countdown--;

drivers/net/ethernet/intel/i40evf/i40e_txrx.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,8 @@ struct i40e_ring_container {
442442
unsigned long last_itr_update; /* jiffies of last ITR update */
443443
u16 count;
444444
enum i40e_latency_range latency_range;
445-
u16 itr;
445+
u16 target_itr; /* target ITR setting for ring(s) */
446+
u16 current_itr; /* current ITR setting for ring(s) */
446447
};
447448

448449
/* iterator for handling rings in ring container */

drivers/net/ethernet/intel/i40evf/i40evf_ethtool.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,6 @@ static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
514514
{
515515
struct i40e_ring *rx_ring = &adapter->rx_rings[queue];
516516
struct i40e_ring *tx_ring = &adapter->tx_rings[queue];
517-
struct i40e_hw *hw = &adapter->hw;
518517
struct i40e_q_vector *q_vector;
519518

520519
rx_ring->itr_setting = ITR_REG_ALIGN(ec->rx_coalesce_usecs);
@@ -529,16 +528,15 @@ static void i40evf_set_itr_per_queue(struct i40evf_adapter *adapter,
529528
tx_ring->itr_setting ^= I40E_ITR_DYNAMIC;
530529

531530
q_vector = rx_ring->q_vector;
532-
q_vector->rx.itr = ITR_TO_REG(rx_ring->itr_setting);
533-
wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, q_vector->reg_idx),
534-
q_vector->rx.itr);
531+
q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
535532

536533
q_vector = tx_ring->q_vector;
537-
q_vector->tx.itr = ITR_TO_REG(tx_ring->itr_setting);
538-
wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, q_vector->reg_idx),
539-
q_vector->tx.itr);
534+
q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
540535

541-
i40e_flush(hw);
536+
/* The interrupt handler itself will take care of programming
537+
* the Tx and Rx ITR values based on the values we have entered
538+
* into the q_vector, no need to write the values now.
539+
*/
542540
}
543541

544542
/**

drivers/net/ethernet/intel/i40evf/i40evf_main.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,12 @@ i40evf_map_vector_to_rxq(struct i40evf_adapter *adapter, int v_idx, int r_idx)
354354
q_vector->rx.ring = rx_ring;
355355
q_vector->rx.count++;
356356
q_vector->rx.latency_range = I40E_LOW_LATENCY;
357-
q_vector->rx.itr = ITR_TO_REG(rx_ring->itr_setting);
357+
q_vector->rx.target_itr = ITR_TO_REG(rx_ring->itr_setting);
358358
q_vector->ring_mask |= BIT(r_idx);
359359
q_vector->itr_countdown = ITR_COUNTDOWN_START;
360360
wr32(hw, I40E_VFINT_ITRN1(I40E_RX_ITR, q_vector->reg_idx),
361-
q_vector->rx.itr);
361+
q_vector->rx.current_itr);
362+
q_vector->rx.current_itr = q_vector->rx.target_itr;
362363
}
363364

364365
/**
@@ -380,11 +381,12 @@ i40evf_map_vector_to_txq(struct i40evf_adapter *adapter, int v_idx, int t_idx)
380381
q_vector->tx.ring = tx_ring;
381382
q_vector->tx.count++;
382383
q_vector->tx.latency_range = I40E_LOW_LATENCY;
383-
q_vector->tx.itr = ITR_TO_REG(tx_ring->itr_setting);
384+
q_vector->tx.target_itr = ITR_TO_REG(tx_ring->itr_setting);
384385
q_vector->itr_countdown = ITR_COUNTDOWN_START;
385386
q_vector->num_ringpairs++;
386387
wr32(hw, I40E_VFINT_ITRN1(I40E_TX_ITR, q_vector->reg_idx),
387-
q_vector->tx.itr);
388+
q_vector->tx.target_itr);
389+
q_vector->tx.current_itr = q_vector->tx.target_itr;
388390
}
389391

390392
/**

0 commit comments

Comments
 (0)