summaryrefslogtreecommitdiffstats
path: root/sys/dev/e1000
diff options
context:
space:
mode:
authorjfv <jfv@FreeBSD.org>2010-11-01 20:19:25 +0000
committerjfv <jfv@FreeBSD.org>2010-11-01 20:19:25 +0000
commita4ab528826d1ac9cc9de0ba3fead29d68b978e3e (patch)
treecbc2856488d5cba69f4f2bc4f0921e4e8502f757 /sys/dev/e1000
parente0a2a85d3a72725ab12bf363f472b29193ad6aaa (diff)
downloadFreeBSD-src-a4ab528826d1ac9cc9de0ba3fead29d68b978e3e.zip
FreeBSD-src-a4ab528826d1ac9cc9de0ba3fead29d68b978e3e.tar.gz
Sync the lem code up with the vlan and other fixes in em.
Delete a unneeded test from the beginning of em_xmit. CRITICAL: shared code fix for 82574, a mutex might not be released, this can cause hangs.
Diffstat (limited to 'sys/dev/e1000')
-rw-r--r--sys/dev/e1000/e1000_82571.c7
-rw-r--r--sys/dev/e1000/if_em.c13
-rw-r--r--sys/dev/e1000/if_lem.c228
-rw-r--r--sys/dev/e1000/if_lem.h18
4 files changed, 108 insertions, 158 deletions
diff --git a/sys/dev/e1000/e1000_82571.c b/sys/dev/e1000/e1000_82571.c
index 3554dbe..5e12c49 100644
--- a/sys/dev/e1000/e1000_82571.c
+++ b/sys/dev/e1000/e1000_82571.c
@@ -666,10 +666,15 @@ static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw)
**/
static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw)
{
+ s32 ret_val;
+
DEBUGFUNC("e1000_get_hw_semaphore_82574");
E1000_MUTEX_LOCK(&hw->dev_spec._82571.swflag_mutex);
- return e1000_get_hw_semaphore_82573(hw);
+ ret_val = e1000_get_hw_semaphore_82573(hw);
+ if (ret_val)
+ E1000_MUTEX_UNLOCK(&hw->dev_spec._82571.swflag_mutex);
+ return ret_val;
}
/**
diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c
index 1ce3956..c41e144 100644
--- a/sys/dev/e1000/if_em.c
+++ b/sys/dev/e1000/if_em.c
@@ -1766,19 +1766,6 @@ em_xmit(struct tx_ring *txr, struct mbuf **m_headp)
ip_off = poff = 0;
/*
- ** When doing checksum offload, it is critical to
- ** make sure the first mbuf has more than header,
- ** because that routine expects data to be present.
- */
- if ((m_head->m_pkthdr.csum_flags & CSUM_OFFLOAD) &&
- (m_head->m_len < ETHER_HDR_LEN + sizeof(struct ip))) {
- m_head = m_pullup(m_head, ETHER_HDR_LEN + sizeof(struct ip));
- *m_headp = m_head;
- if (m_head == NULL)
- return (ENOBUFS);
- }
-
- /*
* Intel recommends entire IP/TCP header length reside in a single
* buffer. If multiple descriptors are used to describe the IP and
* TCP header, each descriptor should describe one or more
diff --git a/sys/dev/e1000/if_lem.c b/sys/dev/e1000/if_lem.c
index 846d6bf..21686e6 100644
--- a/sys/dev/e1000/if_lem.c
+++ b/sys/dev/e1000/if_lem.c
@@ -51,9 +51,7 @@
#include <sys/sockio.h>
#include <sys/sysctl.h>
#include <sys/taskqueue.h>
-#if __FreeBSD_version >= 700029
#include <sys/eventhandler.h>
-#endif
#include <machine/bus.h>
#include <machine/resource.h>
@@ -86,8 +84,7 @@
/*********************************************************************
* Legacy Em Driver version:
*********************************************************************/
-char lem_driver_version[] = "1.0.2";
-
+char lem_driver_version[] = "1.0.3";
/*********************************************************************
* PCI Device ID Table
@@ -209,11 +206,9 @@ static void lem_disable_promisc(struct adapter *);
static void lem_set_multi(struct adapter *);
static void lem_update_link_status(struct adapter *);
static int lem_get_buf(struct adapter *, int);
-#if __FreeBSD_version >= 700029
static void lem_register_vlan(void *, struct ifnet *, u16);
static void lem_unregister_vlan(void *, struct ifnet *, u16);
static void lem_setup_vlan_hw_support(struct adapter *);
-#endif
static int lem_xmit(struct adapter *, struct mbuf **);
static void lem_smartspeed(struct adapter *);
static int lem_82547_fifo_workaround(struct adapter *, int);
@@ -231,6 +226,8 @@ static u32 lem_fill_descriptors (bus_addr_t address, u32 length,
static int lem_sysctl_int_delay(SYSCTL_HANDLER_ARGS);
static void lem_add_int_delay_sysctl(struct adapter *, const char *,
const char *, struct em_int_delay_info *, int, int);
+static void lem_set_flow_cntrl(struct adapter *, const char *,
+ const char *, int *, int);
/* Management and WOL Support */
static void lem_init_manageability(struct adapter *);
static void lem_release_manageability(struct adapter *);
@@ -244,11 +241,7 @@ static void lem_led_func(void *, int);
#ifdef EM_LEGACY_IRQ
static void lem_intr(void *);
#else /* FAST IRQ */
-#if __FreeBSD_version < 700000
-static void lem_irq_fast(void *);
-#else
static int lem_irq_fast(void *);
-#endif
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 *,
@@ -320,14 +313,6 @@ TUNABLE_INT("hw.em.rx_process_limit", &lem_rx_process_limit);
static int lem_fc_setting = e1000_fc_full;
TUNABLE_INT("hw.em.fc_setting", &lem_fc_setting);
-/*
-** Shadow VFTA table, this is needed because
-** the real vlan filter table gets cleared during
-** a soft reset and the driver needs to be able
-** to repopulate it.
-*/
-static u32 lem_shadow_vfta[EM_VFTA_SIZE];
-
/* Global used in WOL setup with multiport cards */
static int global_quad_port_a = 0;
@@ -462,6 +447,11 @@ lem_attach(device_t dev)
lem_rx_process_limit);
#endif
+ /* Sysctl for setting the interface flow control */
+ lem_set_flow_cntrl(adapter, "flow_control",
+ "max number of rx packets to process",
+ &adapter->fc_setting, lem_fc_setting);
+
/*
* Validate number of transmit and receive descriptors. It
* must not exceed hardware maximum, and must be multiple
@@ -638,13 +628,11 @@ lem_attach(device_t dev)
else
adapter->pcix_82544 = FALSE;
-#if __FreeBSD_version >= 700029
/* Register for VLAN events */
adapter->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
lem_register_vlan, adapter, EVENTHANDLER_PRI_FIRST);
adapter->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
lem_unregister_vlan, adapter, EVENTHANDLER_PRI_FIRST);
-#endif
lem_add_hw_stats(adapter);
@@ -702,11 +690,7 @@ lem_detach(device_t dev)
INIT_DEBUGOUT("em_detach: begin");
/* Make sure VLANS are not using driver */
-#if __FreeBSD_version >= 700000
if (adapter->ifp->if_vlantrunk != NULL) {
-#else
- if (adapter->ifp->if_nvlans != 0) {
-#endif
device_printf(dev,"Vlan in use, detach first\n");
return (EBUSY);
}
@@ -730,13 +714,11 @@ lem_detach(device_t dev)
EM_TX_UNLOCK(adapter);
EM_CORE_UNLOCK(adapter);
-#if __FreeBSD_version >= 700029
/* Unregister VLAN events */
if (adapter->vlan_attach != NULL)
EVENTHANDLER_DEREGISTER(vlan_config, adapter->vlan_attach);
if (adapter->vlan_detach != NULL)
EVENTHANDLER_DEREGISTER(vlan_unconfig, adapter->vlan_detach);
-#endif
ether_ifdetach(adapter->ifp);
callout_drain(&adapter->timer);
@@ -831,6 +813,19 @@ lem_start_locked(struct ifnet *ifp)
if (!adapter->link_active)
return;
+ /*
+ * Force a cleanup if number of TX descriptors
+ * available hits the threshold
+ */
+ if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
+ lem_txeof(adapter);
+ /* Now do we at least have a minimal? */
+ if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) {
+ adapter->no_tx_desc_avail1++;
+ return;
+ }
+ }
+
while (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
@@ -1043,9 +1038,7 @@ lem_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
}
if (reinit && (ifp->if_drv_flags & IFF_DRV_RUNNING))
lem_init(adapter);
-#if __FreeBSD_version >= 700000
VLAN_CAPABILITIES(ifp);
-#endif
break;
}
@@ -1135,17 +1128,8 @@ lem_init_locked(struct adapter *adapter)
/* Setup VLAN support, basic and offload if available */
E1000_WRITE_REG(&adapter->hw, E1000_VET, ETHERTYPE_VLAN);
-#if __FreeBSD_version < 700029
- if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
- u32 ctrl;
- ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
- ctrl |= E1000_CTRL_VME;
- E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
- }
-#else
/* Use real VLAN Filter support */
lem_setup_vlan_hw_support(adapter);
-#endif
/* Set hardware offload abilities */
ifp->if_hwassist = 0;
@@ -1174,6 +1158,19 @@ lem_init_locked(struct adapter *adapter)
}
lem_initialize_receive_unit(adapter);
+ /* Use real VLAN Filter support? */
+ if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ /* Use real VLAN Filter support */
+ lem_setup_vlan_hw_support(adapter);
+ else {
+ u32 ctrl;
+ ctrl = E1000_READ_REG(&adapter->hw, E1000_CTRL);
+ ctrl |= E1000_CTRL_VME;
+ E1000_WRITE_REG(&adapter->hw, E1000_CTRL, ctrl);
+ }
+ }
+
/* Don't lose promiscuous settings */
lem_set_promisc(adapter);
@@ -1276,7 +1273,6 @@ lem_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
* Legacy Interrupt Service routine
*
*********************************************************************/
-
static void
lem_intr(void *arg)
{
@@ -1311,7 +1307,6 @@ lem_intr(void *arg)
}
EM_TX_LOCK(adapter);
- lem_txeof(adapter);
lem_rxeof(adapter, -1, NULL);
lem_txeof(adapter);
if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
@@ -1354,8 +1349,7 @@ lem_handle_rxtx(void *context, int pending)
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if (lem_rxeof(adapter, adapter->rx_process_limit, NULL) != 0)
- taskqueue_enqueue(adapter->tq, &adapter->rxtx_task);
+ lem_rxeof(adapter, adapter->rx_process_limit, NULL);
EM_TX_LOCK(adapter);
lem_txeof(adapter);
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
@@ -1363,7 +1357,8 @@ lem_handle_rxtx(void *context, int pending)
EM_TX_UNLOCK(adapter);
}
- lem_enable_intr(adapter);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ lem_enable_intr(adapter);
}
/*********************************************************************
@@ -1371,13 +1366,7 @@ lem_handle_rxtx(void *context, int pending)
* Fast Legacy/MSI Combined Interrupt Service routine
*
*********************************************************************/
-#if __FreeBSD_version < 700000
-#define FILTER_STRAY
-#define FILTER_HANDLED
-static void
-#else
static int
-#endif
lem_irq_fast(void *arg)
{
struct adapter *adapter = arg;
@@ -1550,25 +1539,10 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
struct mbuf *m_head;
u32 txd_upper, txd_lower, txd_used, txd_saved;
int error, nsegs, i, j, first, last = 0;
-#if __FreeBSD_version < 700000
- struct m_tag *mtag;
-#endif
+
m_head = *m_headp;
txd_upper = txd_lower = txd_used = txd_saved = 0;
- /*
- * Force a cleanup if number of TX descriptors
- * available hits the threshold
- */
- if (adapter->num_tx_desc_avail <= EM_TX_CLEANUP_THRESHOLD) {
- lem_txeof(adapter);
- /* Now do we at least have a minimal? */
- if (adapter->num_tx_desc_avail <= EM_TX_OP_THRESHOLD) {
- adapter->no_tx_desc_avail1++;
- return (ENOBUFS);
- }
- }
-
/*
** When doing checksum offload, it is critical to
** make sure the first mbuf has more than header,
@@ -1712,20 +1686,6 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
else
adapter->num_tx_desc_avail -= nsegs;
- /*
- ** Handle VLAN tag, this is the
- ** biggest difference between
- ** 6.x and 7
- */
-#if __FreeBSD_version < 700000
- /* Find out if we are in vlan mode. */
- mtag = VLAN_OUTPUT_TAG(ifp, m_head);
- if (mtag != NULL) {
- ctxd->upper.fields.special =
- htole16(VLAN_TAG_VALUE(mtag));
- ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE);
- }
-#else /* FreeBSD 7 */
if (m_head->m_flags & M_VLANTAG) {
/* Set the vlan id. */
ctxd->upper.fields.special =
@@ -1733,7 +1693,6 @@ lem_xmit(struct adapter *adapter, struct mbuf **m_headp)
/* Tell hardware to add tag */
ctxd->lower.data |= htole32(E1000_TXD_CMD_VLE);
}
-#endif
tx_buffer->m_head = m_head;
tx_buffer_mapped->map = tx_buffer->map;
@@ -2249,11 +2208,7 @@ lem_allocate_irq(struct adapter *adapter)
#ifdef EM_LEGACY_IRQ
/* We do Legacy setup */
if ((error = bus_setup_intr(dev, adapter->res[0],
-#if __FreeBSD_version > 700000
INTR_TYPE_NET | INTR_MPSAFE, NULL, lem_intr, adapter,
-#else /* 6.X */
- INTR_TYPE_NET | INTR_MPSAFE, lem_intr, adapter,
-#endif
&adapter->tag[0])) != 0) {
device_printf(dev, "Failed to register interrupt handler");
return (error);
@@ -2270,13 +2225,8 @@ lem_allocate_irq(struct adapter *adapter)
taskqueue_thread_enqueue, &adapter->tq);
taskqueue_start_threads(&adapter->tq, 1, PI_NET, "%s taskq",
device_get_nameunit(adapter->dev));
-#if __FreeBSD_version < 700000
- if ((error = bus_setup_intr(dev, adapter->res[0],
- INTR_TYPE_NET | INTR_FAST, lem_irq_fast, adapter,
-#else
if ((error = bus_setup_intr(dev, adapter->res[0],
INTR_TYPE_NET, lem_irq_fast, NULL, adapter,
-#endif
&adapter->tag[0])) != 0) {
device_printf(dev, "Failed to register fast interrupt "
"handler: %d\n", error);
@@ -2362,7 +2312,7 @@ lem_hardware_init(struct adapter *adapter)
adapter->hw.fc.send_xon = TRUE;
/* Set Flow control, use the tunable location if sane */
- if ((lem_fc_setting >= 0) || (lem_fc_setting < 4))
+ if ((lem_fc_setting >= 0) && (lem_fc_setting < 4))
adapter->hw.fc.requested_mode = lem_fc_setting;
else
adapter->hw.fc.requested_mode = e1000_fc_none;
@@ -2410,14 +2360,8 @@ lem_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities = ifp->if_capenable = 0;
if (adapter->hw.mac.type >= e1000_82543) {
- int version_cap;
-#if __FreeBSD_version < 700000
- version_cap = IFCAP_HWCSUM;
-#else
- version_cap = IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
-#endif
- ifp->if_capabilities |= version_cap;
- ifp->if_capenable |= version_cap;
+ ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
+ ifp->if_capenable |= IFCAP_HWCSUM | IFCAP_VLAN_HWCSUM;
}
/*
@@ -2427,6 +2371,16 @@ lem_setup_interface(device_t dev, struct adapter *adapter)
ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
ifp->if_capenable |= IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU;
+ /*
+ ** Dont turn this on by default, if vlans are
+ ** created on another pseudo device (eg. lagg)
+ ** then vlan events are not passed thru, breaking
+ ** operation, but with HW FILTER off it works. If
+ ** using vlans directly on the em driver you can
+ ** enable this and get full hardware tag filtering.
+ */
+ ifp->if_capabilities |= IFCAP_VLAN_HWFILTER;
+
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
#endif
@@ -2551,11 +2505,7 @@ lem_dma_malloc(struct adapter *adapter, bus_size_t size,
{
int error;
-#if __FreeBSD_version >= 700000
error = bus_dma_tag_create(bus_get_dma_tag(adapter->dev), /* parent */
-#else
- error = bus_dma_tag_create(NULL, /* parent */
-#endif
EM_DBA_ALIGN, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -2640,21 +2590,17 @@ lem_allocate_transmit_structures(struct adapter *adapter)
/*
* Create DMA tags for tx descriptors
*/
-#if __FreeBSD_version >= 700000
if ((error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
-#else
- if ((error = bus_dma_tag_create(NULL, /* parent */
-#endif
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- EM_TSO_SIZE, /* maxsize */
+ MCLBYTES * EM_MAX_SCATTER, /* maxsize */
EM_MAX_SCATTER, /* nsegments */
- EM_TSO_SEG_SIZE, /* maxsegsize */
+ MCLBYTES, /* maxsegsize */
0, /* flags */
- NULL, /* lockfunc */
- NULL, /* lockarg */
+ NULL, /* lockfunc */
+ NULL, /* lockarg */
&adapter->txtag)) != 0) {
device_printf(dev, "Unable to allocate TX DMA tag\n");
goto fail;
@@ -3072,23 +3018,20 @@ lem_txeof(struct adapter *adapter)
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
adapter->next_tx_to_clean = first;
+ adapter->num_tx_desc_avail = num_avail;
/*
* If we have enough room, clear IFF_DRV_OACTIVE to
* tell the stack that it is OK to send packets.
* If there are no pending descriptors, clear the watchdog.
*/
- if (num_avail > EM_TX_CLEANUP_THRESHOLD) {
+ if (adapter->num_tx_desc_avail > EM_TX_CLEANUP_THRESHOLD) {
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- if (num_avail == adapter->num_tx_desc) {
+ if (adapter->num_tx_desc_avail == adapter->num_tx_desc) {
adapter->watchdog_check = FALSE;
- adapter->num_tx_desc_avail = num_avail;
return;
}
}
-
- adapter->num_tx_desc_avail = num_avail;
- return;
}
/*********************************************************************
@@ -3185,11 +3128,7 @@ lem_allocate_receive_structures(struct adapter *adapter)
return (ENOMEM);
}
-#if __FreeBSD_version >= 700000
error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
-#else
- error = bus_dma_tag_create(NULL, /* parent */
-#endif
1, 0, /* alignment, bounds */
BUS_SPACE_MAXADDR, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
@@ -3459,7 +3398,7 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
{
struct ifnet *ifp = adapter->ifp;;
struct mbuf *mp;
- u8 status, accept_frame = 0, eop = 0;
+ u8 status = 0, accept_frame = 0, eop = 0;
u16 len, desc_len, prev_len_adj;
int i, rx_sent = 0;
struct e1000_rx_desc *current_desc;
@@ -3477,11 +3416,13 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
return (FALSE);
}
- while ((current_desc->status & E1000_RXD_STAT_DD) &&
- (count != 0) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+ while (count != 0 && ifp->if_drv_flags & IFF_DRV_RUNNING) {
struct mbuf *m = NULL;
+ status = current_desc->status;
+ if ((status & E1000_RXD_STAT_DD) == 0)
+ break;
+
mp = adapter->rx_buffer_area[i].m_head;
/*
* Can't defer bus_dmamap_sync(9) because TBI_ACCEPT
@@ -3493,7 +3434,6 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
accept_frame = 1;
prev_len_adj = 0;
desc_len = le16toh(current_desc->length);
- status = current_desc->status;
if (status & E1000_RXD_STAT_EOP) {
count--;
eop = 1;
@@ -3571,16 +3511,10 @@ lem_rxeof(struct adapter *adapter, int count, int *done)
goto skip;
#endif
if (status & E1000_RXD_STAT_VP) {
-#if __FreeBSD_version < 700000
- VLAN_INPUT_TAG_NEW(ifp, adapter->fmp,
- (le16toh(current_desc->special) &
- E1000_RXD_SPC_VLAN_MASK));
-#else
adapter->fmp->m_pkthdr.ether_vtag =
(le16toh(current_desc->special) &
E1000_RXD_SPC_VLAN_MASK);
adapter->fmp->m_flags |= M_VLANTAG;
-#endif
}
#ifndef __NO_STRICT_ALIGNMENT
skip:
@@ -3636,7 +3570,7 @@ discard:
if (done != NULL)
*done = rx_sent;
EM_RX_UNLOCK(adapter);
- return (current_desc->status & E1000_RXD_STAT_DD);
+ return ((status & E1000_RXD_STAT_DD) ? TRUE : FALSE);
}
#ifndef __NO_STRICT_ALIGNMENT
@@ -3728,7 +3662,6 @@ lem_receive_checksum(struct adapter *adapter,
}
}
-#if __FreeBSD_version >= 700029
/*
* This routine is run via an vlan
* config EVENT
@@ -3745,12 +3678,15 @@ lem_register_vlan(void *arg, struct ifnet *ifp, u16 vtag)
if ((vtag == 0) || (vtag > 4095)) /* Invalid ID */
return;
+ EM_CORE_LOCK(adapter);
index = (vtag >> 5) & 0x7F;
bit = vtag & 0x1F;
- lem_shadow_vfta[index] |= (1 << bit);
+ adapter->shadow_vfta[index] |= (1 << bit);
++adapter->num_vlans;
/* Re-init to load the changes */
- lem_init(adapter);
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ lem_init_locked(adapter);
+ EM_CORE_UNLOCK(adapter);
}
/*
@@ -3769,12 +3705,15 @@ lem_unregister_vlan(void *arg, struct ifnet *ifp, u16 vtag)
if ((vtag == 0) || (vtag > 4095)) /* Invalid */
return;
+ EM_CORE_LOCK(adapter);
index = (vtag >> 5) & 0x7F;
bit = vtag & 0x1F;
- lem_shadow_vfta[index] &= ~(1 << bit);
+ adapter->shadow_vfta[index] &= ~(1 << bit);
--adapter->num_vlans;
/* Re-init to load the changes */
- lem_init(adapter);
+ if (ifp->if_capenable & IFCAP_VLAN_HWFILTER)
+ lem_init_locked(adapter);
+ EM_CORE_UNLOCK(adapter);
}
static void
@@ -3797,9 +3736,9 @@ lem_setup_vlan_hw_support(struct adapter *adapter)
** we need to repopulate it now.
*/
for (int i = 0; i < EM_VFTA_SIZE; i++)
- if (lem_shadow_vfta[i] != 0)
+ if (adapter->shadow_vfta[i] != 0)
E1000_WRITE_REG_ARRAY(hw, E1000_VFTA,
- i, lem_shadow_vfta[i]);
+ i, adapter->shadow_vfta[i]);
reg = E1000_READ_REG(hw, E1000_CTRL);
reg |= E1000_CTRL_VME;
@@ -3815,7 +3754,6 @@ lem_setup_vlan_hw_support(struct adapter *adapter)
E1000_WRITE_REG(&adapter->hw, E1000_RLPML,
adapter->max_frame_size + VLAN_TAG_SIZE);
}
-#endif
static void
lem_enable_intr(struct adapter *adapter)
@@ -4661,6 +4599,16 @@ lem_add_int_delay_sysctl(struct adapter *adapter, const char *name,
info, 0, lem_sysctl_int_delay, "I", description);
}
+static void
+lem_set_flow_cntrl(struct adapter *adapter, const char *name,
+ const char *description, int *limit, int value)
+{
+ *limit = value;
+ SYSCTL_ADD_INT(device_get_sysctl_ctx(adapter->dev),
+ SYSCTL_CHILDREN(device_get_sysctl_tree(adapter->dev)),
+ 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,
@@ -4672,5 +4620,3 @@ lem_add_rx_process_limit(struct adapter *adapter, const char *name,
OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
}
#endif
-
-
diff --git a/sys/dev/e1000/if_lem.h b/sys/dev/e1000/if_lem.h
index 2f76aa8..e866d07e 100644
--- a/sys/dev/e1000/if_lem.h
+++ b/sys/dev/e1000/if_lem.h
@@ -328,11 +328,9 @@ struct adapter {
struct task tx_task;
struct taskqueue *tq; /* private task queue */
-#if __FreeBSD_version >= 700029
eventhandler_tag vlan_attach;
eventhandler_tag vlan_detach;
u32 num_vlans;
-#endif
/* Management and WOL features */
u32 wol;
@@ -341,11 +339,22 @@ struct adapter {
/* Multicast array memory */
u8 *mta;
- /* Info about the board itself */
+
+ /*
+ ** Shadow VFTA table, this is needed because
+ ** the real vlan filter table gets cleared during
+ ** a soft reset and the driver needs to be able
+ ** to repopulate it.
+ */
+ u32 shadow_vfta[EM_VFTA_SIZE];
+
+ /* Info about the interface */
uint8_t link_active;
uint16_t link_speed;
uint16_t link_duplex;
uint32_t smartspeed;
+ uint32_t fc_setting;
+
struct em_int_delay_info tx_int_delay;
struct em_int_delay_info tx_abs_int_delay;
struct em_int_delay_info rx_int_delay;
@@ -407,6 +416,9 @@ struct adapter {
unsigned long no_tx_dma_setup;
unsigned long watchdog_events;
unsigned long rx_overruns;
+ unsigned long rx_irq;
+ unsigned long tx_irq;
+ unsigned long link_irq;
/* 82547 workaround */
uint32_t tx_fifo_size;
OpenPOWER on IntegriCloud