Author: jfv
Date: Mon Nov  1 20:19:25 2010
New Revision: 214646
URL: http://svn.freebsd.org/changeset/base/214646

Log:
  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.

Modified:
  head/sys/dev/e1000/e1000_82571.c
  head/sys/dev/e1000/if_em.c
  head/sys/dev/e1000/if_lem.c
  head/sys/dev/e1000/if_lem.h

Modified: head/sys/dev/e1000/e1000_82571.c
==============================================================================
--- head/sys/dev/e1000/e1000_82571.c    Mon Nov  1 20:17:15 2010        
(r214645)
+++ head/sys/dev/e1000/e1000_82571.c    Mon Nov  1 20:19:25 2010        
(r214646)
@@ -666,10 +666,15 @@ static void e1000_put_hw_semaphore_82573
  **/
 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;
 }
 
 /**

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c  Mon Nov  1 20:17:15 2010        (r214645)
+++ head/sys/dev/e1000/if_em.c  Mon Nov  1 20:19:25 2010        (r214646)
@@ -1766,19 +1766,6 @@ em_xmit(struct tx_ring *txr, struct mbuf
        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

Modified: head/sys/dev/e1000/if_lem.c
==============================================================================
--- head/sys/dev/e1000/if_lem.c Mon Nov  1 20:17:15 2010        (r214645)
+++ head/sys/dev/e1000/if_lem.c Mon Nov  1 20:19:25 2010        (r214646)
@@ -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 a
 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_add
 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", &l
 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 comm
                }
                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_cm
  *  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 pendi
 
 
        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 pendi
                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 pendi
  *  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
        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
        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
                 /* 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 *adapte
        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
        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
        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, 
 {
        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 
        /*
         * 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 a
                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 c
 {
        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 c
                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 c
                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 c
                                        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 *ada
        }
 }
 
-#if __FreeBSD_version >= 700029
 /*
  * This routine is run via an vlan
  * config EVENT
@@ -3745,12 +3678,15 @@ lem_register_vlan(void *arg, struct ifne
        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 if
        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
        ** 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
        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 
            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 
            OID_AUTO, name, CTLTYPE_INT|CTLFLAG_RW, limit, value, description);
 }
 #endif
-
-

Modified: head/sys/dev/e1000/if_lem.h
==============================================================================
--- head/sys/dev/e1000/if_lem.h Mon Nov  1 20:17:15 2010        (r214645)
+++ head/sys/dev/e1000/if_lem.h Mon Nov  1 20:19:25 2010        (r214646)
@@ -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;
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to