diff options
Diffstat (limited to 'sys/dev/e1000/if_lem.c')
-rw-r--r-- | sys/dev/e1000/if_lem.c | 104 |
1 files changed, 30 insertions, 74 deletions
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c index 4ade180..882bd3c 100644 --- a/sys/dev/e1000/if_lem.c +++ b/sys/dev/e1000/if_lem.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2012, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -85,7 +85,7 @@ /********************************************************************* * Legacy Em Driver version: *********************************************************************/ -char lem_driver_version[] = "1.0.4"; +char lem_driver_version[] = "1.0.5"; /********************************************************************* * PCI Device ID Table @@ -239,16 +239,12 @@ static void lem_enable_wakeup(device_t); static int lem_enable_phy_wakeup(struct adapter *); static void lem_led_func(void *, int); -#define EM_LEGACY_IRQ /* slightly faster, at least in qemu */ -#ifdef EM_LEGACY_IRQ static void lem_intr(void *); -#else /* FAST IRQ */ static int lem_irq_fast(void *); static void lem_handle_rxtx(void *context, int pending); static void lem_handle_link(void *context, int pending); static void lem_add_rx_process_limit(struct adapter *, const char *, const char *, int *, int); -#endif /* ~EM_LEGACY_IRQ */ #ifdef DEVICE_POLLING static poll_handler_t lem_poll; @@ -305,11 +301,13 @@ TUNABLE_INT("hw.em.txd", &lem_txd); TUNABLE_INT("hw.em.smart_pwr_down", &lem_smart_pwr_down); TUNABLE_INT("hw.em.sbp", &lem_debug_sbp); -#ifndef EM_LEGACY_IRQ +/* Interrupt style - default to fast */ +static int lem_use_legacy_irq = 0; +TUNABLE_INT("hw.em.use_legacy_irq", &lem_use_legacy_irq); + /* How many packets rxeof tries to clean at a time */ static int lem_rx_process_limit = 100; TUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit); -#endif /* Flow control setting - default to FULL */ static int lem_fc_setting = e1000_fc_full; @@ -451,12 +449,10 @@ lem_attach(device_t dev) lem_tx_abs_int_delay_dflt); } -#ifndef EM_LEGACY_IRQ /* Sysctls for limiting the amount of work done in the taskqueue */ lem_add_rx_process_limit(adapter, "rx_processing_limit", "max number of rx packets to process", &adapter->rx_process_limit, lem_rx_process_limit); -#endif /* Sysctl for setting the interface flow control */ lem_set_flow_cntrl(adapter, "flow_control", @@ -1198,22 +1194,6 @@ lem_init_locked(struct adapter *adapter) callout_reset(&adapter->timer, hz, lem_local_timer, adapter); e1000_clear_hw_cntrs_base_generic(&adapter->hw); - /* MSI/X configuration for 82574 */ - if (adapter->hw.mac.type == e1000_82574) { - int tmp; - tmp = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT); - tmp |= E1000_CTRL_EXT_PBA_CLR; - E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT, tmp); - /* - ** Set the IVAR - interrupt vector routing. - ** Each nibble represents a vector, high bit - ** is enable, other 3 bits are the MSIX table - ** entry, we map RXQ0 to 0, TXQ0 to 1, and - ** Link (other) to 2, hence the magic number. - */ - E1000_WRITE_REG(&adapter->hw, E1000_IVAR, 0x800A0908); - } - #ifdef DEVICE_POLLING /* * Only enable interrupts if we are not polling, make sure @@ -1282,7 +1262,6 @@ lem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) } #endif /* DEVICE_POLLING */ -#ifdef EM_LEGACY_IRQ /********************************************************************* * * Legacy Interrupt Service routine @@ -1296,7 +1275,8 @@ lem_intr(void *arg) u32 reg_icr; - if (ifp->if_capenable & IFCAP_POLLING) + if ((ifp->if_capenable & IFCAP_POLLING) || + ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)) return; EM_CORE_LOCK(adapter); @@ -1304,11 +1284,10 @@ lem_intr(void *arg) if (reg_icr & E1000_ICR_RXO) adapter->rx_overruns++; - if ((reg_icr == 0xffffffff) || (reg_icr == 0)) - goto out; - - if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) - goto out; + if ((reg_icr == 0xffffffff) || (reg_icr == 0)) { + EM_CORE_UNLOCK(adapter); + return; + } if (reg_icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { callout_stop(&adapter->timer); @@ -1318,23 +1297,22 @@ lem_intr(void *arg) lem_tx_purge(adapter); callout_reset(&adapter->timer, hz, lem_local_timer, adapter); - goto out; + EM_CORE_UNLOCK(adapter); + return; } - EM_TX_LOCK(adapter); + EM_CORE_UNLOCK(adapter); lem_rxeof(adapter, -1, NULL); + + EM_TX_LOCK(adapter); lem_txeof(adapter); if (ifp->if_drv_flags & IFF_DRV_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd)) lem_start_locked(ifp); EM_TX_UNLOCK(adapter); - -out: - EM_CORE_UNLOCK(adapter); return; } -#else /* EM_FAST_IRQ, then fast interrupt routines only */ static void lem_handle_link(void *context, int pending) @@ -1418,7 +1396,6 @@ lem_irq_fast(void *arg) adapter->rx_overruns++; return FILTER_HANDLED; } -#endif /* ~EM_LEGACY_IRQ */ /********************************************************************* @@ -2215,19 +2192,21 @@ lem_allocate_irq(struct adapter *adapter) return (ENXIO); } -#ifdef EM_LEGACY_IRQ - /* We do Legacy setup */ - if ((error = bus_setup_intr(dev, adapter->res[0], - INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter, - &adapter->tag[0])) != 0) { - device_printf(dev, "Failed to register interrupt handler"); - return (error); + /* Do Legacy setup? */ + if (lem_use_legacy_irq) { + if ((error = bus_setup_intr(dev, adapter->res[0], + INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter, + &adapter->tag[0])) != 0) { + device_printf(dev, + "Failed to register interrupt handler"); + return (error); + } + return (0); } -#else /* FAST_IRQ */ /* - * Try allocating a fast interrupt and the associated deferred - * processing contexts. + * Use a Fast interrupt and the associated + * deferred processing contexts. */ TASK_INIT(&adapter->rxtx_task, 0, lem_handle_rxtx, adapter); TASK_INIT(&adapter->link_task, 0, lem_handle_link, adapter); @@ -2244,7 +2223,6 @@ lem_allocate_irq(struct adapter *adapter) adapter->tq = NULL; return (error); } -#endif /* EM_LEGACY_IRQ */ return (0); } @@ -3302,20 +3280,6 @@ lem_initialize_receive_unit(struct adapter *adapter) E1000_WRITE_REG(&adapter->hw, E1000_ITR, DEFAULT_ITR); } - /* - ** When using MSIX interrupts we need to throttle - ** using the EITR register (82574 only) - */ - if (adapter->msix) - for (int i = 0; i < 4; i++) - E1000_WRITE_REG(&adapter->hw, - E1000_EITR_82574(i), DEFAULT_ITR); - - /* Disable accelerated ackknowledge */ - if (adapter->hw.mac.type == e1000_82574) - E1000_WRITE_REG(&adapter->hw, - E1000_RFCTL, E1000_RFCTL_ACK_DIS); - /* Setup the Base and Length of the Rx Descriptor Ring */ bus_addr = adapter->rxdma.dma_paddr; E1000_WRITE_REG(&adapter->hw, E1000_RDLEN(0), @@ -3835,10 +3799,6 @@ lem_enable_intr(struct adapter *adapter) struct e1000_hw *hw = &adapter->hw; u32 ims_mask = IMS_ENABLE_MASK; - if (adapter->msix) { - E1000_WRITE_REG(hw, EM_EIAC, EM_MSIX_MASK); - ims_mask |= EM_MSIX_MASK; - } E1000_WRITE_REG(hw, E1000_IMS, ims_mask); } @@ -3847,9 +3807,7 @@ lem_disable_intr(struct adapter *adapter) { struct e1000_hw *hw = &adapter->hw; - if (adapter->msix) - E1000_WRITE_REG(hw, EM_EIAC, 0); - E1000_WRITE_REG(&adapter->hw, E1000_IMC, 0xffffffff); + E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); } /* @@ -4683,7 +4641,6 @@ lem_set_flow_cntrl(struct adapter *adapter, const char *name, OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); } -#ifndef EM_LEGACY_IRQ static void lem_add_rx_process_limit(struct adapter *adapter, const char *name, const char *description, int *limit, int value) @@ -4693,4 +4650,3 @@ lem_add_rx_process_limit(struct adapter *adapter, const char *name, SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)), OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description); } -#endif |