Author: sbruno
Date: Wed Jul 19 22:41:22 2017
New Revision: 321257
URL: https://svnweb.freebsd.org/changeset/base/321257

Log:
  Restore igb(4) code dropped during iflib conversion
   - restore newer code for vf, i350, i210, i211
   - restore dmac init code for i354 and i350
   - restore WUC/WUFC update
   - check for igb mac type before attempting trying to assert
     a media changed event.
   - handle link events for igb(4) and em(4) devices differently
     and appropriately for their respective model types.
  
  Submitted by: Matt Macy <mm...@mattmacy.io>
  Sponsored by: Limelight Networks

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

Modified: head/sys/dev/e1000/if_em.c
==============================================================================
--- head/sys/dev/e1000/if_em.c  Wed Jul 19 22:06:35 2017        (r321256)
+++ head/sys/dev/e1000/if_em.c  Wed Jul 19 22:41:22 2017        (r321257)
@@ -1025,7 +1025,7 @@ em_if_attach_post(if_ctx_t ctx)
        /* Non-AMT based hardware can now take control from firmware */
        if (adapter->has_manage && !adapter->has_amt)
                em_get_hw_control(adapter);
-       
+
        INIT_DEBUGOUT("em_if_attach_post: end");
 
        return (error);
@@ -1691,8 +1691,9 @@ em_if_update_admin_status(if_ctx_t ctx)
        struct e1000_hw *hw = &adapter->hw;
        struct ifnet *ifp = iflib_get_ifp(ctx);
        device_t dev = iflib_get_dev(ctx);
-       u32 link_check = 0;
+       u32 link_check, thstat, ctrl;
 
+       link_check = thstat = ctrl = 0;
        /* Get the cached link value or read phy for real */
        switch (hw->phy.media_type) {
        case e1000_media_type_copper:
@@ -1717,11 +1718,21 @@ em_if_update_admin_status(if_ctx_t ctx)
                e1000_check_for_link(hw);
                link_check = adapter->hw.mac.serdes_has_link;
                break;
-       default:
+       /* VF device is type_unknown */
        case e1000_media_type_unknown:
+                e1000_check_for_link(hw);
+               link_check = !hw->mac.get_link_status;
+               /* Fall thru */
+       default:
                break;
        }
 
+       /* Check for thermal downshift or shutdown */
+       if (hw->mac.type == e1000_i350) {
+               thstat = E1000_READ_REG(hw, E1000_THSTAT);
+               ctrl = E1000_READ_REG(hw, E1000_CTRL_EXT);
+       }
+
        /* Now check for a transition */
        if (link_check && (adapter->link_active == 0)) {
                e1000_get_speed_and_duplex(hw, &adapter->link_speed,
@@ -1743,6 +1754,21 @@ em_if_update_admin_status(if_ctx_t ctx)
                adapter->link_active = 1;
                adapter->smartspeed = 0;
                if_setbaudrate(ifp, adapter->link_speed * 1000000);
+               if ((ctrl & E1000_CTRL_EXT_LINK_MODE_GMII) &&
+                   (thstat & E1000_THSTAT_LINK_THROTTLE))
+                       device_printf(dev, "Link: thermal downshift\n");
+               /* Delay Link Up for Phy update */
+               if (((hw->mac.type == e1000_i210) ||
+                   (hw->mac.type == e1000_i211)) &&
+                   (hw->phy.id == I210_I_PHY_ID))
+                       msec_delay(I210_LINK_DELAY);
+               /* Reset if the media type changed. */
+               if ((hw->dev_spec._82575.media_changed) &&
+                       (adapter->hw.mac.type >= igb_mac_min)) {
+                       hw->dev_spec._82575.media_changed = false;
+                       adapter->flags |= IGB_MEDIA_RESET;
+                       em_reset(ctx);
+               }
                iflib_link_state_change(ctx, LINK_STATE_UP, ifp->if_baudrate);
                printf("Link state changed to up\n");
        } else if (!link_check && (adapter->link_active == 1)) {
@@ -2210,7 +2236,115 @@ lem_smartspeed(struct adapter *adapter)
                adapter->smartspeed = 0;
 }
 
+/*********************************************************************
+ *
+ *  Initialize the DMA Coalescing feature
+ *
+ **********************************************************************/
+static void
+igb_init_dmac(struct adapter *adapter, u32 pba)
+{
+       device_t        dev = adapter->dev;
+       struct e1000_hw *hw = &adapter->hw;
+       u32             dmac, reg = ~E1000_DMACR_DMAC_EN;
+       u16             hwm;
+       u16             max_frame_size;
 
+       if (hw->mac.type == e1000_i211)
+               return;
+
+       max_frame_size = adapter->shared->isc_max_frame_size;
+       if (hw->mac.type > e1000_82580) {
+
+               if (adapter->dmac == 0) { /* Disabling it */
+                       E1000_WRITE_REG(hw, E1000_DMACR, reg);
+                       return;
+               } else
+                       device_printf(dev, "DMA Coalescing enabled\n");
+
+               /* Set starting threshold */
+               E1000_WRITE_REG(hw, E1000_DMCTXTH, 0);
+
+               hwm = 64 * pba - max_frame_size / 16;
+               if (hwm < 64 * (pba - 6))
+                       hwm = 64 * (pba - 6);
+               reg = E1000_READ_REG(hw, E1000_FCRTC);
+               reg &= ~E1000_FCRTC_RTH_COAL_MASK;
+               reg |= ((hwm << E1000_FCRTC_RTH_COAL_SHIFT)
+                   & E1000_FCRTC_RTH_COAL_MASK);
+               E1000_WRITE_REG(hw, E1000_FCRTC, reg);
+
+
+               dmac = pba - max_frame_size / 512;
+               if (dmac < pba - 10)
+                       dmac = pba - 10;
+               reg = E1000_READ_REG(hw, E1000_DMACR);
+               reg &= ~E1000_DMACR_DMACTHR_MASK;
+               reg = ((dmac << E1000_DMACR_DMACTHR_SHIFT)
+                   & E1000_DMACR_DMACTHR_MASK);
+
+               /* transition to L0x or L1 if available..*/
+               reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
+
+               /* Check if status is 2.5Gb backplane connection
+               * before configuration of watchdog timer, which is
+               * in msec values in 12.8usec intervals
+               * watchdog timer= msec values in 32usec intervals
+               * for non 2.5Gb connection
+               */
+               if (hw->mac.type == e1000_i354) {
+                       int status = E1000_READ_REG(hw, E1000_STATUS);
+                       if ((status & E1000_STATUS_2P5_SKU) &&
+                           (!(status & E1000_STATUS_2P5_SKU_OVER)))
+                               reg |= ((adapter->dmac * 5) >> 6);
+                       else
+                               reg |= (adapter->dmac >> 5);
+               } else {
+                       reg |= (adapter->dmac >> 5);
+               }
+
+               E1000_WRITE_REG(hw, E1000_DMACR, reg);
+
+               E1000_WRITE_REG(hw, E1000_DMCRTRH, 0);
+
+               /* Set the interval before transition */
+               reg = E1000_READ_REG(hw, E1000_DMCTLX);
+               if (hw->mac.type == e1000_i350)
+                       reg |= IGB_DMCTLX_DCFLUSH_DIS;
+               /*
+               ** in 2.5Gb connection, TTLX unit is 0.4 usec
+               ** which is 0x4*2 = 0xA. But delay is still 4 usec
+               */
+               if (hw->mac.type == e1000_i354) {
+                       int status = E1000_READ_REG(hw, E1000_STATUS);
+                       if ((status & E1000_STATUS_2P5_SKU) &&
+                           (!(status & E1000_STATUS_2P5_SKU_OVER)))
+                               reg |= 0xA;
+                       else
+                               reg |= 0x4;
+               } else {
+                       reg |= 0x4;
+               }
+
+               E1000_WRITE_REG(hw, E1000_DMCTLX, reg);
+
+               /* free space in tx packet buffer to wake from DMA coal */
+               E1000_WRITE_REG(hw, E1000_DMCTXTH, (IGB_TXPBSIZE -
+                   (2 * max_frame_size)) >> 6);
+
+               /* make low power state decision controlled by DMA coal */
+               reg = E1000_READ_REG(hw, E1000_PCIEMISC);
+               reg &= ~E1000_PCIEMISC_LX_DECISION;
+               E1000_WRITE_REG(hw, E1000_PCIEMISC, reg);
+
+       } else if (hw->mac.type == e1000_82580) {
+               u32 reg = E1000_READ_REG(hw, E1000_PCIEMISC);
+               E1000_WRITE_REG(hw, E1000_PCIEMISC,
+                   reg & ~E1000_PCIEMISC_LX_DECISION);
+               E1000_WRITE_REG(hw, E1000_DMACR, 0);
+       }
+}
+
 static void
 em_reset(if_ctx_t ctx)
 {
@@ -2222,6 +2356,8 @@ em_reset(if_ctx_t ctx)
        u32 pba;
 
        INIT_DEBUGOUT("em_reset: begin");
+       /* Let the firmware know the OS is in control */
+       em_get_hw_control(adapter);
 
        /* Set up smart power down as default off on newer adapters. */
        if (!em_smart_pwr_down && (hw->mac.type == e1000_82571 ||
@@ -2417,13 +2553,24 @@ em_reset(if_ctx_t ctx)
 
        /* Issue a global reset */
        e1000_reset_hw(hw);
-       E1000_WRITE_REG(hw, E1000_WUFC, 0);
-       em_disable_aspm(adapter);
+       if (adapter->hw.mac.type >= igb_mac_min) {
+               E1000_WRITE_REG(hw, E1000_WUC, 0);
+       } else {
+               E1000_WRITE_REG(hw, E1000_WUFC, 0);
+               em_disable_aspm(adapter);
+       }
+       if (adapter->flags & IGB_MEDIA_RESET) {
+               e1000_setup_init_funcs(hw, TRUE);
+               e1000_get_bus_info(hw);
+               adapter->flags &= ~IGB_MEDIA_RESET;
+       }
        /* and a re-init */
        if (e1000_init_hw(hw) < 0) {
                device_printf(dev, "Hardware Initialization Failed\n");
                return;
        }
+       if (adapter->hw.mac.type >= igb_mac_min)
+               igb_init_dmac(adapter, pba);
 
        E1000_WRITE_REG(hw, E1000_VET, ETHERTYPE_VLAN);
        e1000_get_phy_info(hw);
@@ -3307,6 +3454,9 @@ em_get_hw_control(struct adapter *adapter)
 {
        u32 ctrl_ext, swsm;
 
+       if (adapter->vf_ifp)
+               return;
+
        if (adapter->hw.mac.type == e1000_82573) {
                swsm = E1000_READ_REG(&adapter->hw, E1000_SWSM);
                E1000_WRITE_REG(&adapter->hw, E1000_SWSM,
@@ -3317,7 +3467,6 @@ em_get_hw_control(struct adapter *adapter)
        ctrl_ext = E1000_READ_REG(&adapter->hw, E1000_CTRL_EXT);
        E1000_WRITE_REG(&adapter->hw, E1000_CTRL_EXT,
            ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
-       return;
 }
 
 /*

Modified: head/sys/dev/e1000/if_em.h
==============================================================================
--- head/sys/dev/e1000/if_em.h  Wed Jul 19 22:06:35 2017        (r321256)
+++ head/sys/dev/e1000/if_em.h  Wed Jul 19 22:41:22 2017        (r321257)
@@ -235,6 +235,27 @@
 #define EM_EEPROM_APME                 0x400;
 #define EM_82544_APME                  0x0004;
 
+
+/* Support AutoMediaDetect for Marvell M88 PHY in i354 */
+#define IGB_MEDIA_RESET                        (1 << 0)
+
+/* Define the starting Interrupt rate per Queue */
+#define IGB_INTS_PER_SEC        8000
+#define IGB_DEFAULT_ITR         ((1000000/IGB_INTS_PER_SEC) << 2)
+
+#define IGB_LINK_ITR            2000
+#define I210_LINK_DELAY                1000
+
+#define IGB_MAX_SCATTER                40
+#define IGB_VFTA_SIZE          128
+#define IGB_BR_SIZE            4096    /* ring buf size */
+#define IGB_TSO_SIZE           (65535 + sizeof(struct ether_vlan_header))
+#define IGB_TSO_SEG_SIZE       4096    /* Max dma segment size */
+#define IGB_TXPBSIZE           20408
+#define IGB_HDR_BUF            128
+#define IGB_PKTTYPE_MASK       0x0000FFF0
+#define IGB_DMCTLX_DCFLUSH_DIS 0x80000000  /* Disable DMA Coalesce Flush */
+
 /*
  * Driver state logic for the detection of a hung state
  * in hardware.  Set TX_HUNG whenever a TX packet is used
@@ -455,11 +476,11 @@ struct adapter {
        struct ifmedia  *media;
        int             msix;
        int             if_flags;
-       int             min_frame_size;
        int             em_insert_vlan_header;
        u32             ims;
        bool            in_detach;
 
+       u32             flags;
        /* Task for FAST handling */
        struct grouptask link_task;
 
@@ -514,6 +535,7 @@ struct adapter {
        unsigned long   watchdog_events;
 
        struct e1000_hw_stats stats;
+       u16             vf_ifp;
 };
 
 
/********************************************************************************
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to