Commit 4be000c8 authored by Alexander Duyck's avatar Alexander Duyck Committed by Jeff Kirsher

igb: cleanup IVAR configuration

This change is meant to cleanup some of the IVAR register configuration.
igb_assign_vector had become pretty large with multiple copies of the same
general code for setting the IVAR. This change consolidates most of that
code by adding the igb_write_ivar function which allows us just to compute
the index and offset and then use that information to setup the IVAR.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Tested-by: default avatarAaron Brown  <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 0ba82994
...@@ -754,15 +754,40 @@ static int igb_alloc_queues(struct igb_adapter *adapter) ...@@ -754,15 +754,40 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
return -ENOMEM; return -ENOMEM;
} }
/**
* igb_write_ivar - configure ivar for given MSI-X vector
* @hw: pointer to the HW structure
* @msix_vector: vector number we are allocating to a given ring
* @index: row index of IVAR register to write within IVAR table
* @offset: column offset of in IVAR, should be multiple of 8
*
* This function is intended to handle the writing of the IVAR register
* for adapters 82576 and newer. The IVAR table consists of 2 columns,
* each containing an cause allocation for an Rx and Tx ring, and a
* variable number of rows depending on the number of queues supported.
**/
static void igb_write_ivar(struct e1000_hw *hw, int msix_vector,
int index, int offset)
{
u32 ivar = array_rd32(E1000_IVAR0, index);
/* clear any bits that are currently set */
ivar &= ~((u32)0xFF << offset);
/* write vector and valid bit */
ivar |= (msix_vector | E1000_IVAR_VALID) << offset;
array_wr32(E1000_IVAR0, index, ivar);
}
#define IGB_N0_QUEUE -1 #define IGB_N0_QUEUE -1
static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
{ {
u32 msixbm = 0;
struct igb_adapter *adapter = q_vector->adapter; struct igb_adapter *adapter = q_vector->adapter;
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 ivar, index;
int rx_queue = IGB_N0_QUEUE; int rx_queue = IGB_N0_QUEUE;
int tx_queue = IGB_N0_QUEUE; int tx_queue = IGB_N0_QUEUE;
u32 msixbm = 0;
if (q_vector->rx.ring) if (q_vector->rx.ring)
rx_queue = q_vector->rx.ring->reg_idx; rx_queue = q_vector->rx.ring->reg_idx;
...@@ -785,72 +810,39 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector) ...@@ -785,72 +810,39 @@ static void igb_assign_vector(struct igb_q_vector *q_vector, int msix_vector)
q_vector->eims_value = msixbm; q_vector->eims_value = msixbm;
break; break;
case e1000_82576: case e1000_82576:
/* 82576 uses a table-based method for assigning vectors. /*
Each queue has a single entry in the table to which we write * 82576 uses a table that essentially consists of 2 columns
a vector number along with a "valid" bit. Sadly, the layout * with 8 rows. The ordering is column-major so we use the
of the table is somewhat counterintuitive. */ * lower 3 bits as the row index, and the 4th bit as the
if (rx_queue > IGB_N0_QUEUE) { * column offset.
index = (rx_queue & 0x7); */
ivar = array_rd32(E1000_IVAR0, index); if (rx_queue > IGB_N0_QUEUE)
if (rx_queue < 8) { igb_write_ivar(hw, msix_vector,
/* vector goes into low byte of register */ rx_queue & 0x7,
ivar = ivar & 0xFFFFFF00; (rx_queue & 0x8) << 1);
ivar |= msix_vector | E1000_IVAR_VALID; if (tx_queue > IGB_N0_QUEUE)
} else { igb_write_ivar(hw, msix_vector,
/* vector goes into third byte of register */ tx_queue & 0x7,
ivar = ivar & 0xFF00FFFF; ((tx_queue & 0x8) << 1) + 8);
ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
}
array_wr32(E1000_IVAR0, index, ivar);
}
if (tx_queue > IGB_N0_QUEUE) {
index = (tx_queue & 0x7);
ivar = array_rd32(E1000_IVAR0, index);
if (tx_queue < 8) {
/* vector goes into second byte of register */
ivar = ivar & 0xFFFF00FF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
} else {
/* vector goes into high byte of register */
ivar = ivar & 0x00FFFFFF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
}
array_wr32(E1000_IVAR0, index, ivar);
}
q_vector->eims_value = 1 << msix_vector; q_vector->eims_value = 1 << msix_vector;
break; break;
case e1000_82580: case e1000_82580:
case e1000_i350: case e1000_i350:
/* 82580 uses the same table-based approach as 82576 but has fewer /*
entries as a result we carry over for queues greater than 4. */ * On 82580 and newer adapters the scheme is similar to 82576
if (rx_queue > IGB_N0_QUEUE) { * however instead of ordering column-major we have things
index = (rx_queue >> 1); * ordered row-major. So we traverse the table by using
ivar = array_rd32(E1000_IVAR0, index); * bit 0 as the column offset, and the remaining bits as the
if (rx_queue & 0x1) { * row index.
/* vector goes into third byte of register */ */
ivar = ivar & 0xFF00FFFF; if (rx_queue > IGB_N0_QUEUE)
ivar |= (msix_vector | E1000_IVAR_VALID) << 16; igb_write_ivar(hw, msix_vector,
} else { rx_queue >> 1,
/* vector goes into low byte of register */ (rx_queue & 0x1) << 4);
ivar = ivar & 0xFFFFFF00; if (tx_queue > IGB_N0_QUEUE)
ivar |= msix_vector | E1000_IVAR_VALID; igb_write_ivar(hw, msix_vector,
} tx_queue >> 1,
array_wr32(E1000_IVAR0, index, ivar); ((tx_queue & 0x1) << 4) + 8);
}
if (tx_queue > IGB_N0_QUEUE) {
index = (tx_queue >> 1);
ivar = array_rd32(E1000_IVAR0, index);
if (tx_queue & 0x1) {
/* vector goes into high byte of register */
ivar = ivar & 0x00FFFFFF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
} else {
/* vector goes into second byte of register */
ivar = ivar & 0xFFFF00FF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
}
array_wr32(E1000_IVAR0, index, ivar);
}
q_vector->eims_value = 1 << msix_vector; q_vector->eims_value = 1 << msix_vector;
break; break;
default: default:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment