diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index f284de27506..819ae802e65 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1508,6 +1508,7 @@ em_msix_link(void *arg) { struct adapter *adapter = arg; u32 reg_icr; + bool notlink = false; ++adapter->link_irq; MPASS(adapter->hw.back != NULL); @@ -1516,15 +1517,19 @@ em_msix_link(void *arg) if (reg_icr & E1000_ICR_RXO) adapter->rx_overruns++; - if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) em_handle_link(adapter->ctx); - } else if (adapter->hw.mac.type == e1000_82574) { - /* Only re-arm 82574 if em_if_update_admin_status() won't. */ - E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | - E1000_IMS_LSC); - } + else + notlink = true; - if (adapter->hw.mac.type == e1000_82574) { + /* Re-arm for other/spurious interrupts */ + if (notlink && adapter->hw.mac.type >= igb_mac_min) { + E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); + E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask); + } else if (adapter->hw.mac.type == e1000_82574) { + if (notlink) + E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC | + E1000_IMS_OTHER); /* * Because we must read the ICR for this interrupt it may * clear other causes using autoclear, for this reason we @@ -1532,10 +1537,6 @@ em_msix_link(void *arg) */ if (reg_icr) E1000_WRITE_REG(&adapter->hw, E1000_ICS, adapter->ims); - } else { - /* Re-arm unconditionally */ - E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); - E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask); } return (FILTER_HANDLED); @@ -1872,10 +1873,13 @@ em_if_update_admin_status(if_ctx_t ctx) if (hw->mac.type < em_mac_min) lem_smartspeed(adapter); - else if (hw->mac.type == e1000_82574 && + else if (hw->mac.type >= igb_mac_min && + adapter->intr_type == IFLIB_INTR_MSIX) { + E1000_WRITE_REG(&adapter->hw, E1000_IMS, E1000_IMS_LSC); + E1000_WRITE_REG(&adapter->hw, E1000_EIMS, adapter->link_mask); + } else if (hw->mac.type == e1000_82574 && adapter->intr_type == IFLIB_INTR_MSIX) - E1000_WRITE_REG(&adapter->hw, E1000_IMS, EM_MSIX_LINK | - E1000_IMS_LSC); + E1000_WRITE_REG(hw, E1000_IMS, E1000_IMS_LSC | E1000_IMS_OTHER); } static void @@ -2087,7 +2091,10 @@ em_if_msix_intr_assign(if_ctx_t ctx, int msix) if (adapter->hw.mac.type < igb_mac_min) { adapter->ivars |= (8 | rx_vectors) << 16; adapter->ivars |= 0x80000000; + /* Enable the "Other" interrupt type for link status change */ + adapter->ims |= E1000_IMS_OTHER; } + return (0); fail: iflib_irq_free(ctx, &adapter->irq); @@ -3476,8 +3483,8 @@ em_if_intr_enable(if_ctx_t ctx) struct e1000_hw *hw = &adapter->hw; u32 ims_mask = IMS_ENABLE_MASK; - if (hw->mac.type == e1000_82574) { - E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK); + if (adapter->intr_type == IFLIB_INTR_MSIX) { + E1000_WRITE_REG(hw, EM_EIAC, adapter->ims); ims_mask |= adapter->ims; } E1000_WRITE_REG(hw, E1000_IMS, ims_mask); @@ -3489,7 +3496,7 @@ em_if_intr_disable(if_ctx_t ctx) struct adapter *adapter = iflib_get_softc(ctx); struct e1000_hw *hw = &adapter->hw; - if (hw->mac.type == e1000_82574) + if (adapter->intr_type == IFLIB_INTR_MSIX) E1000_WRITE_REG(hw, EM_EIAC, 0); E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); } diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index bfc1b3f2a11..b8967e9ac52 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -337,8 +337,6 @@ #define EM_VFTA_SIZE 128 #define EM_TSO_SIZE 65535 #define EM_TSO_SEG_SIZE 4096 /* Max dma segment size */ -#define EM_MSIX_MASK 0x01F00000 /* For 82574 use */ -#define EM_MSIX_LINK 0x01000000 /* For 82574 use */ #define ETH_ZLEN 60 #define ETH_ADDR_LEN 6 #define EM_CSUM_OFFLOAD (CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP) /* Offload bits in mbuf flag */