Commit e3b37a1b authored by David S. Miller's avatar David S. Miller
parents 9c223f9b 2c4af694
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
/* TX/RX descriptor defines */ /* TX/RX descriptor defines */
#define IXGBE_DEFAULT_TXD 512 #define IXGBE_DEFAULT_TXD 512
#define IXGBE_DEFAULT_TX_WORK 256
#define IXGBE_MAX_TXD 4096 #define IXGBE_MAX_TXD 4096
#define IXGBE_MIN_TXD 64 #define IXGBE_MIN_TXD 64
...@@ -490,7 +491,6 @@ struct ixgbe_adapter { ...@@ -490,7 +491,6 @@ struct ixgbe_adapter {
int node; int node;
u32 led_reg; u32 led_reg;
u32 interrupt_event; u32 interrupt_event;
char lsc_int_name[IFNAMSIZ + 9];
/* SR-IOV */ /* SR-IOV */
DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
......
...@@ -820,8 +820,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) ...@@ -820,8 +820,8 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
* Issue global reset to the MAC. This needs to be a SW reset. * Issue global reset to the MAC. This needs to be a SW reset.
* If link reset is used, it might reset the MAC when mng is using it * If link reset is used, it might reset the MAC when mng is using it
*/ */
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL) | IXGBE_CTRL_RST;
IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */ /* Poll for reset bit to self-clear indicating reset is complete */
...@@ -836,21 +836,18 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw) ...@@ -836,21 +836,18 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
hw_dbg(hw, "Reset polling failed to complete.\n"); hw_dbg(hw, "Reset polling failed to complete.\n");
} }
msleep(50);
/* /*
* Double resets are required for recovery from certain error * Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time * conditions. Between resets, it is necessary to stall to allow time
* for any pending HW events to complete. We use 1usec since that is * for any pending HW events to complete.
* what is needed for ixgbe_disable_pcie_master(). The second reset
* then clears out any effects of those events.
*/ */
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
udelay(1);
goto mac_reset_top; goto mac_reset_top;
} }
msleep(50);
gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR); gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6)); gheccr &= ~((1 << 21) | (1 << 18) | (1 << 9) | (1 << 6));
IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr); IXGBE_WRITE_REG(hw, IXGBE_GHECCR, gheccr);
......
...@@ -904,11 +904,10 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw, ...@@ -904,11 +904,10 @@ static s32 ixgbe_setup_copper_link_82599(struct ixgbe_hw *hw,
**/ **/
static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
{ {
s32 status = 0; ixgbe_link_speed link_speed;
u32 ctrl; s32 status;
u32 i; u32 ctrl, i, autoc, autoc2;
u32 autoc; bool link_up = false;
u32 autoc2;
/* Call adapter stop to disable tx/rx and clear interrupts */ /* Call adapter stop to disable tx/rx and clear interrupts */
hw->mac.ops.stop_adapter(hw); hw->mac.ops.stop_adapter(hw);
...@@ -942,40 +941,47 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw) ...@@ -942,40 +941,47 @@ static s32 ixgbe_reset_hw_82599(struct ixgbe_hw *hw)
mac_reset_top: mac_reset_top:
/* /*
* Issue global reset to the MAC. This needs to be a SW reset. * Issue global reset to the MAC. Needs to be SW reset if link is up.
* If link reset is used, it might reset the MAC when mng is using it * If link reset is used when link is up, it might reset the PHY when
* mng is using it. If link is down or the flag to force full link
* reset is set, then perform link reset.
*/ */
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl = IXGBE_CTRL_LNK_RST;
IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | IXGBE_CTRL_RST)); if (!hw->force_full_reset) {
hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
if (link_up)
ctrl = IXGBE_CTRL_RST;
}
ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */ /* Poll for reset bit to self-clear indicating reset is complete */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
udelay(1); udelay(1);
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
if (!(ctrl & IXGBE_CTRL_RST)) if (!(ctrl & IXGBE_CTRL_RST_MASK))
break; break;
} }
if (ctrl & IXGBE_CTRL_RST) {
if (ctrl & IXGBE_CTRL_RST_MASK) {
status = IXGBE_ERR_RESET_FAILED; status = IXGBE_ERR_RESET_FAILED;
hw_dbg(hw, "Reset polling failed to complete.\n"); hw_dbg(hw, "Reset polling failed to complete.\n");
} }
msleep(50);
/* /*
* Double resets are required for recovery from certain error * Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time * conditions. Between resets, it is necessary to stall to allow time
* for any pending HW events to complete. We use 1usec since that is * for any pending HW events to complete.
* what is needed for ixgbe_disable_pcie_master(). The second reset
* then clears out any effects of those events.
*/ */
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
udelay(1);
goto mac_reset_top; goto mac_reset_top;
} }
msleep(50);
/* /*
* Store the original AUTOC/AUTOC2 values if they have not been * Store the original AUTOC/AUTOC2 values if they have not been
* stored off yet. Otherwise restore the stored original * stored off yet. Otherwise restore the stored original
......
...@@ -1570,26 +1570,26 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter) ...@@ -1570,26 +1570,26 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter)
/* X540 needs to set the MACC.FLU bit to force link up */ /* X540 needs to set the MACC.FLU bit to force link up */
if (adapter->hw.mac.type == ixgbe_mac_X540) { if (adapter->hw.mac.type == ixgbe_mac_X540) {
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_MACC); reg_data = IXGBE_READ_REG(hw, IXGBE_MACC);
reg_data |= IXGBE_MACC_FLU; reg_data |= IXGBE_MACC_FLU;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_MACC, reg_data); IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data);
} }
/* right now we only support MAC loopback in the driver */ /* right now we only support MAC loopback in the driver */
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_HLREG0); reg_data = IXGBE_READ_REG(hw, IXGBE_HLREG0);
/* Setup MAC loopback */ /* Setup MAC loopback */
reg_data |= IXGBE_HLREG0_LPBK; reg_data |= IXGBE_HLREG0_LPBK;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_HLREG0, reg_data); IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg_data);
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); reg_data = IXGBE_READ_REG(hw, IXGBE_FCTRL);
reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE; reg_data |= IXGBE_FCTRL_BAM | IXGBE_FCTRL_SBP | IXGBE_FCTRL_MPE;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, reg_data); IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg_data);
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_AUTOC); reg_data = IXGBE_READ_REG(hw, IXGBE_AUTOC);
reg_data &= ~IXGBE_AUTOC_LMS_MASK; reg_data &= ~IXGBE_AUTOC_LMS_MASK;
reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU; reg_data |= IXGBE_AUTOC_LMS_10G_LINK_NO_AN | IXGBE_AUTOC_FLU;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_AUTOC, reg_data); IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_data);
IXGBE_WRITE_FLUSH(&adapter->hw); IXGBE_WRITE_FLUSH(hw);
usleep_range(10000, 20000); usleep_range(10000, 20000);
/* Disable Atlas Tx lanes; re-enabled in reset path */ /* Disable Atlas Tx lanes; re-enabled in reset path */
......
...@@ -79,59 +79,32 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = { ...@@ -79,59 +79,32 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {
* Class, Class Mask, private data (not used) } * Class, Class Mask, private data (not used) }
*/ */
static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598), board_82598 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_DUAL_PORT), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), board_82598 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2), board_82598 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), board_82598 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT2), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM), board_82598 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM), board_82598 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX), board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4), board_82599 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR), board_82599 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM), board_82599 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), board_82599 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE), board_82599 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_BX), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE), board_82599 },
board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T), board_X540 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4), {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2), board_82599 },
board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_XAUI_LOM),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KR),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_EM),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_BACKPLANE_FCOE),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_FCOE),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T),
board_X540 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF2),
board_82599 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS),
board_82599 },
/* required last entry */ /* required last entry */
{0, } {0, }
}; };
...@@ -804,7 +777,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -804,7 +777,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_tx_buffer *tx_buffer; struct ixgbe_tx_buffer *tx_buffer;
union ixgbe_adv_tx_desc *tx_desc; union ixgbe_adv_tx_desc *tx_desc;
unsigned int total_bytes = 0, total_packets = 0; unsigned int total_bytes = 0, total_packets = 0;
u16 budget = q_vector->tx.work_limit; unsigned int budget = q_vector->tx.work_limit;
u16 i = tx_ring->next_to_clean; u16 i = tx_ring->next_to_clean;
tx_buffer = &tx_ring->tx_buffer_info[i]; tx_buffer = &tx_ring->tx_buffer_info[i];
...@@ -891,7 +864,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -891,7 +864,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
ixgbe_tx_timeout_reset(adapter); ixgbe_tx_timeout_reset(adapter);
/* the adapter is about to reset, no point in enabling stuff */ /* the adapter is about to reset, no point in enabling stuff */
return budget; return true;
} }
#define TX_WAKE_THRESHOLD (DESC_NEEDED * 2) #define TX_WAKE_THRESHOLD (DESC_NEEDED * 2)
...@@ -908,7 +881,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, ...@@ -908,7 +881,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector,
} }
} }
return budget; return !!budget;
} }
#ifdef CONFIG_IXGBE_DCA #ifdef CONFIG_IXGBE_DCA
...@@ -924,12 +897,12 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter, ...@@ -924,12 +897,12 @@ static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
switch (hw->mac.type) { switch (hw->mac.type) {
case ixgbe_mac_82598EB: case ixgbe_mac_82598EB:
rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK; rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
rxctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); rxctrl |= dca3_get_tag(rx_ring->dev, cpu);
break; break;
case ixgbe_mac_82599EB: case ixgbe_mac_82599EB:
case ixgbe_mac_X540: case ixgbe_mac_X540:
rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599; rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK_82599;
rxctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << rxctrl |= (dca3_get_tag(rx_ring->dev, cpu) <<
IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599); IXGBE_DCA_RXCTRL_CPUID_SHIFT_82599);
break; break;
default: default:
...@@ -953,7 +926,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, ...@@ -953,7 +926,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
case ixgbe_mac_82598EB: case ixgbe_mac_82598EB:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(reg_idx)); txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(reg_idx));
txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK; txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
txctrl |= dca3_get_tag(&adapter->pdev->dev, cpu); txctrl |= dca3_get_tag(tx_ring->dev, cpu);
txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(reg_idx), txctrl); IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(reg_idx), txctrl);
break; break;
...@@ -961,7 +934,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter, ...@@ -961,7 +934,7 @@ static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
case ixgbe_mac_X540: case ixgbe_mac_X540:
txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx)); txctrl = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx));
txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599; txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK_82599;
txctrl |= (dca3_get_tag(&adapter->pdev->dev, cpu) << txctrl |= (dca3_get_tag(tx_ring->dev, cpu) <<
IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599); IXGBE_DCA_TXCTRL_CPUID_SHIFT_82599);
txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN; txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx), txctrl); IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(reg_idx), txctrl);
...@@ -1297,9 +1270,9 @@ static inline bool ixgbe_get_rsc_state(union ixgbe_adv_rx_desc *rx_desc) ...@@ -1297,9 +1270,9 @@ static inline bool ixgbe_get_rsc_state(union ixgbe_adv_rx_desc *rx_desc)
IXGBE_RXDADV_RSCCNT_MASK); IXGBE_RXDADV_RSCCNT_MASK);
} }
static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
struct ixgbe_ring *rx_ring, struct ixgbe_ring *rx_ring,
int *work_done, int work_to_do) int budget)
{ {
struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_adapter *adapter = q_vector->adapter;
union ixgbe_adv_rx_desc *rx_desc, *next_rxd; union ixgbe_adv_rx_desc *rx_desc, *next_rxd;
...@@ -1479,11 +1452,11 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ...@@ -1479,11 +1452,11 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
#endif /* IXGBE_FCOE */ #endif /* IXGBE_FCOE */
ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc); ixgbe_receive_skb(q_vector, skb, staterr, rx_ring, rx_desc);
budget--;
next_desc: next_desc:
rx_desc->wb.upper.status_error = 0; rx_desc->wb.upper.status_error = 0;
(*work_done)++; if (!budget)
if (*work_done >= work_to_do)
break; break;
/* return some buffers to hardware, one at a time is too slow */ /* return some buffers to hardware, one at a time is too slow */
...@@ -1524,9 +1497,10 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, ...@@ -1524,9 +1497,10 @@ static void ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
u64_stats_update_end(&rx_ring->syncp); u64_stats_update_end(&rx_ring->syncp);
q_vector->rx.total_packets += total_rx_packets; q_vector->rx.total_packets += total_rx_packets;
q_vector->rx.total_bytes += total_rx_bytes; q_vector->rx.total_bytes += total_rx_bytes;
return !!budget;
} }
static int ixgbe_clean_rxonly(struct napi_struct *, int);
/** /**
* ixgbe_configure_msix - Configure MSI-X hardware * ixgbe_configure_msix - Configure MSI-X hardware
* @adapter: board private structure * @adapter: board private structure
...@@ -1542,6 +1516,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) ...@@ -1542,6 +1516,12 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
/* Populate MSIX to EITR Select */
if (adapter->num_vfs > 32) {
u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel);
}
/* /*
* Populate the IVAR table and set the ITR values to the * Populate the IVAR table and set the ITR values to the
* corresponding register. * corresponding register.
...@@ -1564,20 +1544,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter) ...@@ -1564,20 +1544,6 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
q_vector->eitr = adapter->rx_eitr_param; q_vector->eitr = adapter->rx_eitr_param;
ixgbe_write_eitr(q_vector); ixgbe_write_eitr(q_vector);
/* If ATR is enabled, set interrupt affinity */
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
/*
* Allocate the affinity_hint cpumask, assign the mask
* for this vector, and set our affinity_hint for
* this irq.
*/
if (!alloc_cpumask_var(&q_vector->affinity_mask,
GFP_KERNEL))
return;
cpumask_set_cpu(v_idx, q_vector->affinity_mask);
irq_set_affinity_hint(adapter->msix_entries[v_idx].vector,
q_vector->affinity_mask);
}
} }
switch (adapter->hw.mac.type) { switch (adapter->hw.mac.type) {
...@@ -1862,72 +1828,6 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter) ...@@ -1862,72 +1828,6 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
} }
} }
static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
{
struct ixgbe_adapter *adapter = data;
struct ixgbe_hw *hw = &adapter->hw;
u32 eicr;
/*
* Workaround for Silicon errata. Use clear-by-write instead
* of clear-by-read. Reading with EICS will return the
* interrupt causes without clearing, which later be done
* with the write to EICR.
*/
eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
if (eicr & IXGBE_EICR_LSC)
ixgbe_check_lsc(adapter);
if (eicr & IXGBE_EICR_MAILBOX)
ixgbe_msg_task(adapter);
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
/* Handle Flow Director Full threshold interrupt */
if (eicr & IXGBE_EICR_FLOW_DIR) {
int reinit_count = 0;
int i;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *ring = adapter->tx_ring[i];
if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE,
&ring->state))
reinit_count++;
}
if (reinit_count) {
/* no more flow director interrupts until after init */
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
eicr &= ~IXGBE_EICR_FLOW_DIR;
adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
ixgbe_service_event_schedule(adapter);
}
}
ixgbe_check_sfp_event(adapter, eicr);
if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
adapter->interrupt_event = eicr;
adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
ixgbe_service_event_schedule(adapter);
}
}
break;
default:
break;
}
ixgbe_check_fan_failure(adapter, eicr);
/* re-enable the original interrupt state, no lsc, no queues */
if (!test_bit(__IXGBE_DOWN, &adapter->state))
IXGBE_WRITE_REG(hw, IXGBE_EIMS, eicr &
~(IXGBE_EIMS_LSC | IXGBE_EIMS_RTX_QUEUE));
return IRQ_HANDLED;
}
static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter, static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
u64 qmask) u64 qmask)
{ {
...@@ -1980,165 +1880,122 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter, ...@@ -1980,165 +1880,122 @@ static inline void ixgbe_irq_disable_queues(struct ixgbe_adapter *adapter,
/* skip the flush */ /* skip the flush */
} }
static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
{
struct ixgbe_q_vector *q_vector = data;
if (!q_vector->tx.count)
return IRQ_HANDLED;
/* EIAM disabled interrupts (on this vector) for us */
napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
/**
* ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
* @irq: unused
* @data: pointer to our q_vector struct for this interrupt vector
**/
static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
{
struct ixgbe_q_vector *q_vector = data;
if (!q_vector->rx.count)
return IRQ_HANDLED;
/* EIAM disabled interrupts (on this vector) for us */
napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
static irqreturn_t ixgbe_msix_clean_many(int irq, void *data)
{
struct ixgbe_q_vector *q_vector = data;
if (!q_vector->tx.count && !q_vector->rx.count)
return IRQ_HANDLED;
/* EIAM disabled interrupts (on this vector) for us */
napi_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
/** /**
* ixgbe_clean_rxonly - msix (aka one shot) rx clean routine * ixgbe_irq_enable - Enable default interrupt generation settings
* @napi: napi struct with our devices info in it * @adapter: board private structure
* @budget: amount of work driver is allowed to do this pass, in packets
*
* This function is optimized for cleaning one queue only on a single
* q_vector!!!
**/ **/
static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget) static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
bool flush)
{ {
struct ixgbe_q_vector *q_vector = u32 mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
int work_done = 0;
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
ixgbe_update_dca(q_vector);
#endif
ixgbe_clean_rx_irq(q_vector, q_vector->rx.ring, &work_done, budget); /* don't reenable LSC while waiting for link */
if (adapter->flags & IXGBE_FLAG_NEED_LINK_UPDATE)
mask &= ~IXGBE_EIMS_LSC;
/* If all Rx work done, exit the polling mode */ if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
if (work_done < budget) { mask |= IXGBE_EIMS_GPI_SDP0;
napi_complete(napi); if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
if (adapter->rx_itr_setting & 1) mask |= IXGBE_EIMS_GPI_SDP1;
ixgbe_set_itr(q_vector); switch (adapter->hw.mac.type) {
if (!test_bit(__IXGBE_DOWN, &adapter->state)) case ixgbe_mac_82599EB:
ixgbe_irq_enable_queues(adapter, case ixgbe_mac_X540:
((u64)1 << q_vector->v_idx)); mask |= IXGBE_EIMS_ECC;
mask |= IXGBE_EIMS_GPI_SDP1;
mask |= IXGBE_EIMS_GPI_SDP2;
mask |= IXGBE_EIMS_MAILBOX;
break;
default:
break;
} }
if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
!(adapter->flags2 & IXGBE_FLAG2_FDIR_REQUIRES_REINIT))
mask |= IXGBE_EIMS_FLOW_DIR;
return work_done; IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
if (queues)
ixgbe_irq_enable_queues(adapter, ~0);
if (flush)
IXGBE_WRITE_FLUSH(&adapter->hw);
} }
/** static irqreturn_t ixgbe_msix_other(int irq, void *data)
* ixgbe_clean_rxtx_many - msix (aka one shot) rx clean routine
* @napi: napi struct with our devices info in it
* @budget: amount of work driver is allowed to do this pass, in packets
*
* This function will clean more than one rx queue associated with a
* q_vector.
**/
static int ixgbe_clean_rxtx_many(struct napi_struct *napi, int budget)
{ {
struct ixgbe_q_vector *q_vector = struct ixgbe_adapter *adapter = data;
container_of(napi, struct ixgbe_q_vector, napi); struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_adapter *adapter = q_vector->adapter; u32 eicr;
struct ixgbe_ring *ring;
int work_done = 0;
bool clean_complete = true;
#ifdef CONFIG_IXGBE_DCA /*
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) * Workaround for Silicon errata. Use clear-by-write instead
ixgbe_update_dca(q_vector); * of clear-by-read. Reading with EICS will return the
#endif * interrupt causes without clearing, which later be done
* with the write to EICR.
*/
eicr = IXGBE_READ_REG(hw, IXGBE_EICS);
IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr);
for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next) if (eicr & IXGBE_EICR_LSC)
clean_complete &= ixgbe_clean_tx_irq(q_vector, ring); ixgbe_check_lsc(adapter);
/* attempt to distribute budget to each queue fairly, but don't allow if (eicr & IXGBE_EICR_MAILBOX)
* the budget to go below 1 because we'll exit polling */ ixgbe_msg_task(adapter);
budget /= (q_vector->rx.count ?: 1);
budget = max(budget, 1);
for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next) switch (hw->mac.type) {
ixgbe_clean_rx_irq(q_vector, ring, &work_done, budget); case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
if (eicr & IXGBE_EICR_ECC)
e_info(link, "Received unrecoverable ECC Err, please "
"reboot\n");
/* Handle Flow Director Full threshold interrupt */
if (eicr & IXGBE_EICR_FLOW_DIR) {
int reinit_count = 0;
int i;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct ixgbe_ring *ring = adapter->tx_ring[i];
if (test_and_clear_bit(__IXGBE_TX_FDIR_INIT_DONE,
&ring->state))
reinit_count++;
}
if (reinit_count) {
/* no more flow director interrupts until after init */
IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_FLOW_DIR);
adapter->flags2 |= IXGBE_FLAG2_FDIR_REQUIRES_REINIT;
ixgbe_service_event_schedule(adapter);
}
}
ixgbe_check_sfp_event(adapter, eicr);
if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) &&
((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) {
if (!test_bit(__IXGBE_DOWN, &adapter->state)) {
adapter->interrupt_event = eicr;
adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_EVENT;
ixgbe_service_event_schedule(adapter);
}
}
break;
default:
break;
}
if (!clean_complete) ixgbe_check_fan_failure(adapter, eicr);
work_done = budget;
/* If all Rx work done, exit the polling mode */ /* re-enable the original interrupt state, no lsc, no queues */
if (work_done < budget) { if (!test_bit(__IXGBE_DOWN, &adapter->state))
napi_complete(napi); ixgbe_irq_enable(adapter, false, false);
if (adapter->rx_itr_setting & 1)
ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter,
((u64)1 << q_vector->v_idx));
return 0;
}
return work_done; return IRQ_HANDLED;
} }
/** static irqreturn_t ixgbe_msix_clean_rings(int irq, void *data)
* ixgbe_clean_txonly - msix (aka one shot) tx clean routine
* @napi: napi struct with our devices info in it
* @budget: amount of work driver is allowed to do this pass, in packets
*
* This function is optimized for cleaning one queue only on a single
* q_vector!!!
**/
static int ixgbe_clean_txonly(struct napi_struct *napi, int budget)
{ {
struct ixgbe_q_vector *q_vector = struct ixgbe_q_vector *q_vector = data;
container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter;
#ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
ixgbe_update_dca(q_vector);
#endif
if (!ixgbe_clean_tx_irq(q_vector, q_vector->tx.ring)) /* EIAM disabled interrupts (on this vector) for us */
return budget;
/* If all Tx work done, exit the polling mode */ if (q_vector->rx.ring || q_vector->tx.ring)
napi_complete(napi); napi_schedule(&q_vector->napi);
if (adapter->tx_itr_setting & 1)
ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
return 0; return IRQ_HANDLED;
} }
static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx, static inline void map_vector_to_rxq(struct ixgbe_adapter *a, int v_idx,
...@@ -2176,59 +2033,41 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx, ...@@ -2176,59 +2033,41 @@ static inline void map_vector_to_txq(struct ixgbe_adapter *a, int v_idx,
* group the rings as "efficiently" as possible. You would add new * group the rings as "efficiently" as possible. You would add new
* mapping configurations in here. * mapping configurations in here.
**/ **/
static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter) static void ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter)
{ {
int q_vectors; int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
int rxr_remaining = adapter->num_rx_queues, rxr_idx = 0;
int txr_remaining = adapter->num_tx_queues, txr_idx = 0;
int v_start = 0; int v_start = 0;
int rxr_idx = 0, txr_idx = 0;
int rxr_remaining = adapter->num_rx_queues;
int txr_remaining = adapter->num_tx_queues;
int i, j;
int rqpv, tqpv;
int err = 0;
/* No mapping required if MSI-X is disabled. */ /* only one q_vector if MSI-X is disabled. */
if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED))
goto out; q_vectors = 1;
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
/* /*
* The ideal configuration... * If we don't have enough vectors for a 1-to-1 mapping, we'll have to
* We have enough vectors to map one per queue. * group them so there are multiple queues per vector.
*
* Re-adjusting *qpv takes care of the remainder.
*/ */
if (q_vectors == adapter->num_rx_queues + adapter->num_tx_queues) { for (; v_start < q_vectors && rxr_remaining; v_start++) {
for (; rxr_idx < rxr_remaining; v_start++, rxr_idx++) int rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - v_start);
for (; rqpv; rqpv--, rxr_idx++, rxr_remaining--)
map_vector_to_rxq(adapter, v_start, rxr_idx); map_vector_to_rxq(adapter, v_start, rxr_idx);
for (; txr_idx < txr_remaining; v_start++, txr_idx++)
map_vector_to_txq(adapter, v_start, txr_idx);
goto out;
} }
/* /*
* If we don't have enough vectors for a 1-to-1 * If there are not enough q_vectors for each ring to have it's own
* mapping, we'll have to group them so there are * vector then we must pair up Rx/Tx on a each vector
* multiple queues per vector.
*/ */
/* Re-adjusting *qpv takes care of the remainder. */ if ((v_start + txr_remaining) > q_vectors)
for (i = v_start; i < q_vectors; i++) { v_start = 0;
rqpv = DIV_ROUND_UP(rxr_remaining, q_vectors - i);
for (j = 0; j < rqpv; j++) { for (; v_start < q_vectors && txr_remaining; v_start++) {
map_vector_to_rxq(adapter, i, rxr_idx); int tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - v_start);
rxr_idx++; for (; tqpv; tqpv--, txr_idx++, txr_remaining--)
rxr_remaining--; map_vector_to_txq(adapter, v_start, txr_idx);
}
tqpv = DIV_ROUND_UP(txr_remaining, q_vectors - i);
for (j = 0; j < tqpv; j++) {
map_vector_to_txq(adapter, i, txr_idx);
txr_idx++;
txr_remaining--;
}
} }
out:
return err;
} }
/** /**
...@@ -2241,53 +2080,45 @@ static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter) ...@@ -2241,53 +2080,45 @@ static int ixgbe_map_rings_to_vectors(struct ixgbe_adapter *adapter)
static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
irqreturn_t (*handler)(int, void *); int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
int i, vector, q_vectors, err; int vector, err;
int ri = 0, ti = 0; int ri = 0, ti = 0;
/* Decrement for Other and TCP Timer vectors */
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
err = ixgbe_map_rings_to_vectors(adapter);
if (err)
return err;
#define SET_HANDLER(_v) (((_v)->rx.count && (_v)->tx.count) \
? &ixgbe_msix_clean_many : \
(_v)->rx.count ? &ixgbe_msix_clean_rx : \
(_v)->tx.count ? &ixgbe_msix_clean_tx : \
NULL)
for (vector = 0; vector < q_vectors; vector++) { for (vector = 0; vector < q_vectors; vector++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[vector]; struct ixgbe_q_vector *q_vector = adapter->q_vector[vector];
handler = SET_HANDLER(q_vector); struct msix_entry *entry = &adapter->msix_entries[vector];
if (handler == &ixgbe_msix_clean_rx) { if (q_vector->tx.ring && q_vector->rx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1, snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", netdev->name, "rx", ri++); "%s-%s-%d", netdev->name, "TxRx", ri++);
} else if (handler == &ixgbe_msix_clean_tx) { ti++;
} else if (q_vector->rx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1, snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", netdev->name, "tx", ti++); "%s-%s-%d", netdev->name, "rx", ri++);
} else if (handler == &ixgbe_msix_clean_many) { } else if (q_vector->tx.ring) {
snprintf(q_vector->name, sizeof(q_vector->name) - 1, snprintf(q_vector->name, sizeof(q_vector->name) - 1,
"%s-%s-%d", netdev->name, "TxRx", ri++); "%s-%s-%d", netdev->name, "tx", ti++);
ti++;
} else { } else {
/* skip this unused q_vector */ /* skip this unused q_vector */
continue; continue;
} }
err = request_irq(adapter->msix_entries[vector].vector, err = request_irq(entry->vector, &ixgbe_msix_clean_rings, 0,
handler, 0, q_vector->name, q_vector->name, q_vector);
q_vector);
if (err) { if (err) {
e_err(probe, "request_irq failed for MSIX interrupt " e_err(probe, "request_irq failed for MSIX interrupt "
"Error: %d\n", err); "Error: %d\n", err);
goto free_queue_irqs; goto free_queue_irqs;
} }
/* If Flow Director is enabled, set interrupt affinity */
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) {
/* assign the mask for this irq */
irq_set_affinity_hint(entry->vector,
q_vector->affinity_mask);
}
} }
sprintf(adapter->lsc_int_name, "%s:lsc", netdev->name);
err = request_irq(adapter->msix_entries[vector].vector, err = request_irq(adapter->msix_entries[vector].vector,
ixgbe_msix_lsc, 0, adapter->lsc_int_name, adapter); ixgbe_msix_other, 0, netdev->name, adapter);
if (err) { if (err) {
e_err(probe, "request_irq for msix_lsc failed: %d\n", err); e_err(probe, "request_irq for msix_lsc failed: %d\n", err);
goto free_queue_irqs; goto free_queue_irqs;
...@@ -2296,9 +2127,13 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) ...@@ -2296,9 +2127,13 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
return 0; return 0;
free_queue_irqs: free_queue_irqs:
for (i = vector - 1; i >= 0; i--) while (vector) {
free_irq(adapter->msix_entries[--vector].vector, vector--;
adapter->q_vector[i]); irq_set_affinity_hint(adapter->msix_entries[vector].vector,
NULL);
free_irq(adapter->msix_entries[vector].vector,
adapter->q_vector[vector]);
}
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED; adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
pci_disable_msix(adapter->pdev); pci_disable_msix(adapter->pdev);
kfree(adapter->msix_entries); kfree(adapter->msix_entries);
...@@ -2306,47 +2141,6 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter) ...@@ -2306,47 +2141,6 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
return err; return err;
} }
/**
* ixgbe_irq_enable - Enable default interrupt generation settings
* @adapter: board private structure
**/
static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
bool flush)
{
u32 mask;
mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE);
if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE)
mask |= IXGBE_EIMS_GPI_SDP0;
if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
mask |= IXGBE_EIMS_GPI_SDP1;
switch (adapter->hw.mac.type) {
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
mask |= IXGBE_EIMS_ECC;
mask |= IXGBE_EIMS_GPI_SDP1;
mask |= IXGBE_EIMS_GPI_SDP2;
if (adapter->num_vfs)
mask |= IXGBE_EIMS_MAILBOX;
break;
default:
break;
}
if (adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE)
mask |= IXGBE_EIMS_FLOW_DIR;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
if (queues)
ixgbe_irq_enable_queues(adapter, ~0);
if (flush)
IXGBE_WRITE_FLUSH(&adapter->hw);
if (adapter->num_vfs > 32) {
u32 eitrsel = (1 << (adapter->num_vfs - 32)) - 1;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, eitrsel);
}
}
/** /**
* ixgbe_intr - legacy mode Interrupt Handler * ixgbe_intr - legacy mode Interrupt Handler
* @irq: interrupt number * @irq: interrupt number
...@@ -2455,19 +2249,25 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter) ...@@ -2455,19 +2249,25 @@ static int ixgbe_request_irq(struct ixgbe_adapter *adapter)
struct net_device *netdev = adapter->netdev; struct net_device *netdev = adapter->netdev;
int err; int err;
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { /* map all of the rings to the q_vectors */
ixgbe_map_rings_to_vectors(adapter);
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
err = ixgbe_request_msix_irqs(adapter); err = ixgbe_request_msix_irqs(adapter);
} else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED) { else if (adapter->flags & IXGBE_FLAG_MSI_ENABLED)
err = request_irq(adapter->pdev->irq, ixgbe_intr, 0, err = request_irq(adapter->pdev->irq, ixgbe_intr, 0,
netdev->name, adapter); netdev->name, adapter);
} else { else
err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED, err = request_irq(adapter->pdev->irq, ixgbe_intr, IRQF_SHARED,
netdev->name, adapter); netdev->name, adapter);
}
if (err) if (err) {
e_err(probe, "request_irq failed, Error %d\n", err); e_err(probe, "request_irq failed, Error %d\n", err);
/* place q_vectors and rings back into a known good state */
ixgbe_reset_q_vectors(adapter);
}
return err; return err;
} }
...@@ -2477,25 +2277,29 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter) ...@@ -2477,25 +2277,29 @@ static void ixgbe_free_irq(struct ixgbe_adapter *adapter)
int i, q_vectors; int i, q_vectors;
q_vectors = adapter->num_msix_vectors; q_vectors = adapter->num_msix_vectors;
i = q_vectors - 1; i = q_vectors - 1;
free_irq(adapter->msix_entries[i].vector, adapter); free_irq(adapter->msix_entries[i].vector, adapter);
i--; i--;
for (; i >= 0; i--) { for (; i >= 0; i--) {
/* free only the irqs that were actually requested */ /* free only the irqs that were actually requested */
if (!adapter->q_vector[i]->rx.count && if (!adapter->q_vector[i]->rx.ring &&
!adapter->q_vector[i]->tx.count) !adapter->q_vector[i]->tx.ring)
continue; continue;
/* clear the affinity_mask in the IRQ descriptor */
irq_set_affinity_hint(adapter->msix_entries[i].vector,
NULL);
free_irq(adapter->msix_entries[i].vector, free_irq(adapter->msix_entries[i].vector,
adapter->q_vector[i]); adapter->q_vector[i]);
} }
ixgbe_reset_q_vectors(adapter);
} else { } else {
free_irq(adapter->pdev->irq, adapter); free_irq(adapter->pdev->irq, adapter);
} }
/* clear q_vector state information */
ixgbe_reset_q_vectors(adapter);
} }
/** /**
...@@ -2513,8 +2317,6 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter) ...@@ -2513,8 +2317,6 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
if (adapter->num_vfs > 32)
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0);
break; break;
default: default:
break; break;
...@@ -2543,9 +2345,6 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter) ...@@ -2543,9 +2345,6 @@ static void ixgbe_configure_msi_and_legacy(struct ixgbe_adapter *adapter)
ixgbe_set_ivar(adapter, 0, 0, 0); ixgbe_set_ivar(adapter, 0, 0, 0);
ixgbe_set_ivar(adapter, 1, 0, 0); ixgbe_set_ivar(adapter, 1, 0, 0);
map_vector_to_rxq(adapter, 0, 0);
map_vector_to_txq(adapter, 0, 0);
e_info(hw, "Legacy interrupt IVAR setup done\n"); e_info(hw, "Legacy interrupt IVAR setup done\n");
} }
...@@ -2562,13 +2361,11 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, ...@@ -2562,13 +2361,11 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u64 tdba = ring->dma; u64 tdba = ring->dma;
int wait_loop = 10; int wait_loop = 10;
u32 txdctl; u32 txdctl = IXGBE_TXDCTL_ENABLE;
u8 reg_idx = ring->reg_idx; u8 reg_idx = ring->reg_idx;
/* disable queue to avoid issues while updating state */ /* disable queue to avoid issues while updating state */
txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx)); IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), 0);
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx),
txdctl & ~IXGBE_TXDCTL_ENABLE);
IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_FLUSH(hw);
IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx), IXGBE_WRITE_REG(hw, IXGBE_TDBAL(reg_idx),
...@@ -2580,18 +2377,22 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, ...@@ -2580,18 +2377,22 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0); IXGBE_WRITE_REG(hw, IXGBE_TDT(reg_idx), 0);
ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx); ring->tail = hw->hw_addr + IXGBE_TDT(reg_idx);
/* configure fetching thresholds */ /*
if (adapter->rx_itr_setting == 0) { * set WTHRESH to encourage burst writeback, it should not be set
/* cannot set wthresh when itr==0 */ * higher than 1 when ITR is 0 as it could cause false TX hangs
txdctl &= ~0x007F0000; *
} else { * In order to avoid issues WTHRESH + PTHRESH should always be equal
/* enable WTHRESH=8 descriptors, to encourage burst writeback */ * to or less than the number of on chip descriptors, which is
txdctl |= (8 << 16); * currently 40.
} */
if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) { if (!adapter->tx_itr_setting || !adapter->rx_itr_setting)
/* PThresh workaround for Tx hang with DFP enabled. */ txdctl |= (1 << 16); /* WTHRESH = 1 */
txdctl |= 32; else
} txdctl |= (8 << 16); /* WTHRESH = 8 */
/* PTHRESH=32 is needed to avoid a Tx hang with DFP enabled. */
txdctl |= (1 << 8) | /* HTHRESH = 1 */
32; /* PTHRESH = 32 */
/* reinitialize flowdirector state */ /* reinitialize flowdirector state */
if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) && if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) &&
...@@ -2606,7 +2407,6 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter, ...@@ -2606,7 +2407,6 @@ void ixgbe_configure_tx_ring(struct ixgbe_adapter *adapter,
clear_bit(__IXGBE_HANG_CHECK_ARMED, &ring->state); clear_bit(__IXGBE_HANG_CHECK_ARMED, &ring->state);
/* enable queue */ /* enable queue */
txdctl |= IXGBE_TXDCTL_ENABLE;
IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl); IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), txdctl);
/* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */ /* TXDCTL.EN will return 0 on 82598 if link is down, so skip it */
...@@ -3478,19 +3278,8 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter) ...@@ -3478,19 +3278,8 @@ static void ixgbe_napi_enable_all(struct ixgbe_adapter *adapter)
q_vectors = 1; q_vectors = 1;
for (q_idx = 0; q_idx < q_vectors; q_idx++) { for (q_idx = 0; q_idx < q_vectors; q_idx++) {
struct napi_struct *napi;
q_vector = adapter->q_vector[q_idx]; q_vector = adapter->q_vector[q_idx];
napi = &q_vector->napi; napi_enable(&q_vector->napi);
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
if (!q_vector->rx.count || !q_vector->tx.count) {
if (q_vector->tx.count == 1)
napi->poll = &ixgbe_clean_txonly;
else if (q_vector->rx.count == 1)
napi->poll = &ixgbe_clean_rxonly;
}
}
napi_enable(napi);
} }
} }
...@@ -4045,7 +3834,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ...@@ -4045,7 +3834,6 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 rxctrl; u32 rxctrl;
int i; int i;
int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
/* signal that we are down to the interrupt handler */ /* signal that we are down to the interrupt handler */
set_bit(__IXGBE_DOWN, &adapter->state); set_bit(__IXGBE_DOWN, &adapter->state);
...@@ -4077,26 +3865,19 @@ void ixgbe_down(struct ixgbe_adapter *adapter) ...@@ -4077,26 +3865,19 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
del_timer_sync(&adapter->service_timer); del_timer_sync(&adapter->service_timer);
/* disable receive for all VFs and wait one second */
if (adapter->num_vfs) { if (adapter->num_vfs) {
/* ping all the active vfs to let them know we are going down */ /* Clear EITR Select mapping */
ixgbe_ping_all_vfs(adapter); IXGBE_WRITE_REG(&adapter->hw, IXGBE_EITRSEL, 0);
/* Disable all VFTE/VFRE TX/RX */
ixgbe_disable_tx_rx(adapter);
/* Mark all the VFs as inactive */ /* Mark all the VFs as inactive */
for (i = 0 ; i < adapter->num_vfs; i++) for (i = 0 ; i < adapter->num_vfs; i++)
adapter->vfinfo[i].clear_to_send = 0; adapter->vfinfo[i].clear_to_send = 0;
}
/* Cleanup the affinity_hint CPU mask memory and callback */ /* ping all the active vfs to let them know we are going down */
for (i = 0; i < num_q_vectors; i++) { ixgbe_ping_all_vfs(adapter);
struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
/* clear the affinity_mask in the IRQ descriptor */ /* Disable all VFTE/VFRE TX/RX */
irq_set_affinity_hint(adapter->msix_entries[i]. vector, NULL); ixgbe_disable_tx_rx(adapter);
/* release the CPU mask memory */
free_cpumask_var(q_vector->affinity_mask);
} }
/* disable transmits in the hardware now that interrupts are off */ /* disable transmits in the hardware now that interrupts are off */
...@@ -4148,28 +3929,41 @@ static int ixgbe_poll(struct napi_struct *napi, int budget) ...@@ -4148,28 +3929,41 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
struct ixgbe_q_vector *q_vector = struct ixgbe_q_vector *q_vector =
container_of(napi, struct ixgbe_q_vector, napi); container_of(napi, struct ixgbe_q_vector, napi);
struct ixgbe_adapter *adapter = q_vector->adapter; struct ixgbe_adapter *adapter = q_vector->adapter;
int tx_clean_complete, work_done = 0; struct ixgbe_ring *ring;
int per_ring_budget;
bool clean_complete = true;
#ifdef CONFIG_IXGBE_DCA #ifdef CONFIG_IXGBE_DCA
if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
ixgbe_update_dca(q_vector); ixgbe_update_dca(q_vector);
#endif #endif
tx_clean_complete = ixgbe_clean_tx_irq(q_vector, adapter->tx_ring[0]); for (ring = q_vector->tx.ring; ring != NULL; ring = ring->next)
ixgbe_clean_rx_irq(q_vector, adapter->rx_ring[0], &work_done, budget); clean_complete &= !!ixgbe_clean_tx_irq(q_vector, ring);
if (!tx_clean_complete) /* attempt to distribute budget to each queue fairly, but don't allow
work_done = budget; * the budget to go below 1 because we'll exit polling */
if (q_vector->rx.count > 1)
per_ring_budget = max(budget/q_vector->rx.count, 1);
else
per_ring_budget = budget;
/* If budget not fully consumed, exit the polling mode */ for (ring = q_vector->rx.ring; ring != NULL; ring = ring->next)
if (work_done < budget) { clean_complete &= ixgbe_clean_rx_irq(q_vector, ring,
napi_complete(napi); per_ring_budget);
if (adapter->rx_itr_setting & 1)
ixgbe_set_itr(q_vector); /* If all work not completed, return budget and keep polling */
if (!test_bit(__IXGBE_DOWN, &adapter->state)) if (!clean_complete)
ixgbe_irq_enable_queues(adapter, IXGBE_EIMS_RTX_QUEUE); return budget;
}
return work_done; /* all work done, exit the polling mode */
napi_complete(napi);
if (adapter->rx_itr_setting & 1)
ixgbe_set_itr(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
ixgbe_irq_enable_queues(adapter, ((u64)1 << q_vector->v_idx));
return 0;
} }
/** /**
...@@ -4810,19 +4604,15 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter) ...@@ -4810,19 +4604,15 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
**/ **/
static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
{ {
int q_idx, num_q_vectors; int v_idx, num_q_vectors;
struct ixgbe_q_vector *q_vector; struct ixgbe_q_vector *q_vector;
int (*poll)(struct napi_struct *, int);
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) { if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
poll = &ixgbe_clean_rxtx_many; else
} else {
num_q_vectors = 1; num_q_vectors = 1;
poll = &ixgbe_poll;
}
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { for (v_idx = 0; v_idx < num_q_vectors; v_idx++) {
q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector), q_vector = kzalloc_node(sizeof(struct ixgbe_q_vector),
GFP_KERNEL, adapter->node); GFP_KERNEL, adapter->node);
if (!q_vector) if (!q_vector)
...@@ -4830,25 +4620,35 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) ...@@ -4830,25 +4620,35 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
GFP_KERNEL); GFP_KERNEL);
if (!q_vector) if (!q_vector)
goto err_out; goto err_out;
q_vector->adapter = adapter; q_vector->adapter = adapter;
q_vector->v_idx = v_idx;
/* Allocate the affinity_hint cpumask, configure the mask */
if (!alloc_cpumask_var(&q_vector->affinity_mask, GFP_KERNEL))
goto err_out;
cpumask_set_cpu(v_idx, q_vector->affinity_mask);
if (q_vector->tx.count && !q_vector->rx.count) if (q_vector->tx.count && !q_vector->rx.count)
q_vector->eitr = adapter->tx_eitr_param; q_vector->eitr = adapter->tx_eitr_param;
else else
q_vector->eitr = adapter->rx_eitr_param; q_vector->eitr = adapter->rx_eitr_param;
q_vector->v_idx = q_idx;
netif_napi_add(adapter->netdev, &q_vector->napi, (*poll), 64); netif_napi_add(adapter->netdev, &q_vector->napi,
adapter->q_vector[q_idx] = q_vector; ixgbe_poll, 64);
adapter->q_vector[v_idx] = q_vector;
} }
return 0; return 0;
err_out: err_out:
while (q_idx) { while (v_idx) {
q_idx--; v_idx--;
q_vector = adapter->q_vector[q_idx]; q_vector = adapter->q_vector[v_idx];
netif_napi_del(&q_vector->napi); netif_napi_del(&q_vector->napi);
free_cpumask_var(q_vector->affinity_mask);
kfree(q_vector); kfree(q_vector);
adapter->q_vector[q_idx] = NULL; adapter->q_vector[v_idx] = NULL;
} }
return -ENOMEM; return -ENOMEM;
} }
...@@ -4863,17 +4663,18 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter) ...@@ -4863,17 +4663,18 @@ static int ixgbe_alloc_q_vectors(struct ixgbe_adapter *adapter)
**/ **/
static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter) static void ixgbe_free_q_vectors(struct ixgbe_adapter *adapter)
{ {
int q_idx, num_q_vectors; int v_idx, num_q_vectors;
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED)
num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
else else
num_q_vectors = 1; num_q_vectors = 1;
for (q_idx = 0; q_idx < num_q_vectors; q_idx++) { for (v_idx = 0; v_idx < num_q_vectors; v_idx++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[q_idx]; struct ixgbe_q_vector *q_vector = adapter->q_vector[v_idx];
adapter->q_vector[q_idx] = NULL; adapter->q_vector[v_idx] = NULL;
netif_napi_del(&q_vector->napi); netif_napi_del(&q_vector->napi);
free_cpumask_var(q_vector->affinity_mask);
kfree(q_vector); kfree(q_vector);
} }
} }
...@@ -5091,7 +4892,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) ...@@ -5091,7 +4892,7 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
adapter->rx_ring_count = IXGBE_DEFAULT_RXD; adapter->rx_ring_count = IXGBE_DEFAULT_RXD;
/* set default work limits */ /* set default work limits */
adapter->tx_work_limit = adapter->tx_ring_count; adapter->tx_work_limit = IXGBE_DEFAULT_TX_WORK;
/* initialize eeprom parameters */ /* initialize eeprom parameters */
if (ixgbe_init_eeprom_params_generic(hw)) { if (ixgbe_init_eeprom_params_generic(hw)) {
...@@ -6959,7 +6760,7 @@ static void ixgbe_netpoll(struct net_device *netdev) ...@@ -6959,7 +6760,7 @@ static void ixgbe_netpoll(struct net_device *netdev)
int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS; int num_q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
for (i = 0; i < num_q_vectors; i++) { for (i = 0; i < num_q_vectors; i++) {
struct ixgbe_q_vector *q_vector = adapter->q_vector[i]; struct ixgbe_q_vector *q_vector = adapter->q_vector[i];
ixgbe_msix_clean_many(0, q_vector); ixgbe_msix_clean_rings(0, q_vector);
} }
} else { } else {
ixgbe_intr(adapter->pdev->irq, netdev); ixgbe_intr(adapter->pdev->irq, netdev);
......
...@@ -982,6 +982,7 @@ ...@@ -982,6 +982,7 @@
#define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */ #define IXGBE_CTRL_GIO_DIS 0x00000004 /* Global IO Master Disable bit */
#define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */ #define IXGBE_CTRL_LNK_RST 0x00000008 /* Link Reset. Resets everything. */
#define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */ #define IXGBE_CTRL_RST 0x04000000 /* Reset (SW) */
#define IXGBE_CTRL_RST_MASK (IXGBE_CTRL_LNK_RST | IXGBE_CTRL_RST)
/* FACTPS */ /* FACTPS */
#define IXGBE_FACTPS_LFS 0x40000000 /* LAN Function Select */ #define IXGBE_FACTPS_LFS 0x40000000 /* LAN Function Select */
......
...@@ -94,13 +94,8 @@ static s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ...@@ -94,13 +94,8 @@ static s32 ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw,
static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
{ {
ixgbe_link_speed link_speed; ixgbe_link_speed link_speed;
s32 status = 0; s32 status;
u32 ctrl; u32 ctrl, i;
u32 ctrl_ext;
u32 reset_bit;
u32 i;
u32 autoc;
u32 autoc2;
bool link_up = false; bool link_up = false;
/* Call adapter stop to disable tx/rx and clear interrupts */ /* Call adapter stop to disable tx/rx and clear interrupts */
...@@ -119,84 +114,48 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) ...@@ -119,84 +114,48 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
* mng is using it. If link is down or the flag to force full link * mng is using it. If link is down or the flag to force full link
* reset is set, then perform link reset. * reset is set, then perform link reset.
*/ */
if (hw->force_full_reset) { ctrl = IXGBE_CTRL_LNK_RST;
reset_bit = IXGBE_CTRL_LNK_RST; if (!hw->force_full_reset) {
} else {
hw->mac.ops.check_link(hw, &link_speed, &link_up, false); hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
if (!link_up) if (link_up)
reset_bit = IXGBE_CTRL_LNK_RST; ctrl = IXGBE_CTRL_RST;
else
reset_bit = IXGBE_CTRL_RST;
} }
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
IXGBE_WRITE_REG(hw, IXGBE_CTRL, (ctrl | reset_bit)); IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_FLUSH(hw);
/* Poll for reset bit to self-clear indicating reset is complete */ /* Poll for reset bit to self-clear indicating reset is complete */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
udelay(1); udelay(1);
ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL); ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
if (!(ctrl & reset_bit)) if (!(ctrl & IXGBE_CTRL_RST_MASK))
break; break;
} }
if (ctrl & reset_bit) {
if (ctrl & IXGBE_CTRL_RST_MASK) {
status = IXGBE_ERR_RESET_FAILED; status = IXGBE_ERR_RESET_FAILED;
hw_dbg(hw, "Reset polling failed to complete.\n"); hw_dbg(hw, "Reset polling failed to complete.\n");
} }
msleep(50);
/* /*
* Double resets are required for recovery from certain error * Double resets are required for recovery from certain error
* conditions. Between resets, it is necessary to stall to allow time * conditions. Between resets, it is necessary to stall to allow time
* for any pending HW events to complete. We use 1usec since that is * for any pending HW events to complete.
* what is needed for ixgbe_disable_pcie_master(). The second reset
* then clears out any effects of those events.
*/ */
if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) { if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED; hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
udelay(1);
goto mac_reset_top; goto mac_reset_top;
} }
/* Clear PF Reset Done bit so PF/VF Mail Ops can work */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
IXGBE_WRITE_REG(hw, IXGBE_CTRL_EXT, ctrl_ext);
IXGBE_WRITE_FLUSH(hw);
msleep(50);
/* Set the Rx packet buffer size. */ /* Set the Rx packet buffer size. */
IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT); IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), 384 << IXGBE_RXPBSIZE_SHIFT);
/* Store the permanent mac address */ /* Store the permanent mac address */
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr); hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
/*
* Store the original AUTOC/AUTOC2 values if they have not been
* stored off yet. Otherwise restore the stored original
* values since the reset operation sets back to defaults.
*/
autoc = IXGBE_READ_REG(hw, IXGBE_AUTOC);
autoc2 = IXGBE_READ_REG(hw, IXGBE_AUTOC2);
if (hw->mac.orig_link_settings_stored == false) {
hw->mac.orig_autoc = autoc;
hw->mac.orig_autoc2 = autoc2;
hw->mac.orig_link_settings_stored = true;
} else {
if (autoc != hw->mac.orig_autoc)
IXGBE_WRITE_REG(hw, IXGBE_AUTOC, (hw->mac.orig_autoc |
IXGBE_AUTOC_AN_RESTART));
if ((autoc2 & IXGBE_AUTOC2_UPPER_MASK) !=
(hw->mac.orig_autoc2 & IXGBE_AUTOC2_UPPER_MASK)) {
autoc2 &= ~IXGBE_AUTOC2_UPPER_MASK;
autoc2 |= (hw->mac.orig_autoc2 &
IXGBE_AUTOC2_UPPER_MASK);
IXGBE_WRITE_REG(hw, IXGBE_AUTOC2, autoc2);
}
}
/* /*
* Store MAC address from RAR0, clear receive address registers, and * Store MAC address from RAR0, clear receive address registers, and
* clear the multicast table. Also reset num_rar_entries to 128, * clear the multicast table. Also reset num_rar_entries to 128,
...@@ -205,9 +164,6 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw) ...@@ -205,9 +164,6 @@ static s32 ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
hw->mac.num_rar_entries = IXGBE_X540_MAX_TX_QUEUES; hw->mac.num_rar_entries = IXGBE_X540_MAX_TX_QUEUES;
hw->mac.ops.init_rx_addrs(hw); hw->mac.ops.init_rx_addrs(hw);
/* Store the permanent mac address */
hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
/* Store the permanent SAN mac address */ /* Store the permanent SAN mac address */
hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr); hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
......
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