mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-20 03:04:01 +08:00
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: Alexander Duyck <alexander.h.duyck@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
0ba829943c
commit
4be000c874
@ -754,15 +754,40 @@ err:
|
|||||||
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)
|
|||||||
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:
|
||||||
|
Loading…
Reference in New Issue
Block a user