Author: jfv
Date: Thu Nov  6 23:45:05 2014
New Revision: 274205
URL: https://svnweb.freebsd.org/changeset/base/274205

Log:
  Update the Intel i40e drivers, ixl version 1.2.8, ixlv version 1.1.18
        -Improved VF stability, thanks to changes from Ryan Stone,
         and Juniper.
        - RSS fixes in the ixlv driver
        - link detection in the ixlv driver
        - New sysctl's added in ixl and ixlv
        - reset timeout increased for ixlv
        - stability fixes in detach
        - correct media reporting
        - Coverity warnings fixed
        - Many small bug fixes
        - VF Makefile modified - nvm shared code needed
        - remove unused sleep channels in ixlv_sc struct
  
  Submitted by: Eric Joyner (committed by jfv)
  MFC after:    1 week

Modified:
  head/sys/dev/ixl/i40e_osdep.c
  head/sys/dev/ixl/i40e_osdep.h
  head/sys/dev/ixl/if_ixl.c
  head/sys/dev/ixl/if_ixlv.c
  head/sys/dev/ixl/ixl.h
  head/sys/dev/ixl/ixl_txrx.c
  head/sys/dev/ixl/ixlv.h
  head/sys/dev/ixl/ixlvc.c
  head/sys/modules/ixlv/Makefile

Modified: head/sys/dev/ixl/i40e_osdep.c
==============================================================================
--- head/sys/dev/ixl/i40e_osdep.c       Thu Nov  6 23:35:22 2014        
(r274204)
+++ head/sys/dev/ixl/i40e_osdep.c       Thu Nov  6 23:45:05 2014        
(r274205)
@@ -107,6 +107,7 @@ i40e_allocate_dma_mem(struct i40e_hw *hw
                    "error %u\n", err);
                goto fail_2;
        }
+       mem->nseg = 1;
        mem->size = size;
        bus_dmamap_sync(mem->tag, mem->map,
            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);

Modified: head/sys/dev/ixl/i40e_osdep.h
==============================================================================
--- head/sys/dev/ixl/i40e_osdep.h       Thu Nov  6 23:35:22 2014        
(r274204)
+++ head/sys/dev/ixl/i40e_osdep.h       Thu Nov  6 23:45:05 2014        
(r274205)
@@ -147,8 +147,7 @@ void prefetch(void *x)
 #define        prefetch(x)
 #endif
 
-struct i40e_osdep
-{
+struct i40e_osdep {
        bus_space_tag_t         mem_bus_space_tag;
        bus_space_handle_t      mem_bus_space_handle;
        bus_size_t              mem_bus_space_size;

Modified: head/sys/dev/ixl/if_ixl.c
==============================================================================
--- head/sys/dev/ixl/if_ixl.c   Thu Nov  6 23:35:22 2014        (r274204)
+++ head/sys/dev/ixl/if_ixl.c   Thu Nov  6 23:45:05 2014        (r274205)
@@ -40,7 +40,7 @@
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixl_driver_version[] = "1.2.2";
+char ixl_driver_version[] = "1.2.8";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -109,6 +109,7 @@ static bool ixl_config_link(struct i40e_
 static void    ixl_config_rss(struct ixl_vsi *);
 static void    ixl_set_queue_rx_itr(struct ixl_queue *);
 static void    ixl_set_queue_tx_itr(struct ixl_queue *);
+static int     ixl_set_advertised_speeds(struct ixl_pf *, int);
 
 static void    ixl_enable_rings(struct ixl_vsi *);
 static void    ixl_disable_rings(struct ixl_vsi *);
@@ -155,6 +156,7 @@ static void ixl_do_adminq(void *, int);
 static int     ixl_set_flowcntl(SYSCTL_HANDLER_ARGS);
 static int     ixl_set_advertise(SYSCTL_HANDLER_ARGS);
 static int     ixl_current_speed(SYSCTL_HANDLER_ARGS);
+static int     ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS);
 
 /* Statistics */
 static void     ixl_add_hw_stats(struct ixl_pf *);
@@ -176,7 +178,8 @@ static void ixl_stat_update32(struct i40
 static int     ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS);
 static int     ixl_sysctl_phy_abilities(SYSCTL_HANDLER_ARGS);
 static int     ixl_sysctl_sw_filter_list(SYSCTL_HANDLER_ARGS);
-static int     ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS);
+static int     ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS);
+static int     ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS);
 static int     ixl_sysctl_dump_txd(SYSCTL_HANDLER_ARGS);
 #endif
 
@@ -276,6 +279,7 @@ int ixl_atr_rate = 20;
 TUNABLE_INT("hw.ixl.atr_rate", &ixl_atr_rate);
 #endif
 
+
 static char *ixl_fc_string[6] = {
        "None",
        "Rx",
@@ -398,6 +402,11 @@ ixl_attach(device_t dev)
            OID_AUTO, "current_speed", CTLTYPE_STRING | CTLFLAG_RD,
            pf, 0, ixl_current_speed, "A", "Current Port Speed");
 
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "fw_version", CTLTYPE_STRING | CTLFLAG_RD,
+           pf, 0, ixl_sysctl_show_fw, "A", "Firmware version");
+
        SYSCTL_ADD_INT(device_get_sysctl_ctx(dev),
            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
            OID_AUTO, "rx_itr", CTLFLAG_RW,
@@ -436,8 +445,13 @@ ixl_attach(device_t dev)
 
        SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
-           OID_AUTO, "hw_res_info", CTLTYPE_STRING | CTLFLAG_RD,
-           pf, 0, ixl_sysctl_hw_res_info, "A", "HW Resource Allocation");
+           OID_AUTO, "hw_res_alloc", CTLTYPE_STRING | CTLFLAG_RD,
+           pf, 0, ixl_sysctl_hw_res_alloc, "A", "HW Resource Allocation");
+
+       SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
+           SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
+           OID_AUTO, "switch_config", CTLTYPE_STRING | CTLFLAG_RD,
+           pf, 0, ixl_sysctl_switch_config, "A", "HW Switch Configuration");
 
        SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
            SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
@@ -445,7 +459,7 @@ ixl_attach(device_t dev)
            pf, 0, ixl_sysctl_dump_txd, "I", "Desc dump");
 #endif
 
-       /* Save off the information about this board */
+       /* Save off the PCI information */
        hw->vendor_id = pci_get_vendor(dev);
        hw->device_id = pci_get_device(dev);
        hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
@@ -593,6 +607,7 @@ ixl_attach(device_t dev)
        bcopy(hw->mac.addr, hw->mac.perm_addr, ETHER_ADDR_LEN);
        i40e_get_port_mac_addr(hw, hw->mac.port_addr);
 
+       /* Set up VSI and queues */
        if (ixl_setup_stations(pf) != 0) { 
                device_printf(dev, "setup stations failed!\n");
                error = ENOMEM;
@@ -630,8 +645,11 @@ ixl_attach(device_t dev)
                    "an unqualified module was detected\n");
 
        /* Setup OS specific network interface */
-       if (ixl_setup_interface(dev, vsi) != 0)
+       if (ixl_setup_interface(dev, vsi) != 0) {
+               device_printf(dev, "interface setup failed!\n");
+               error = EIO;
                goto err_late;
+       }
 
        /* Get the bus configuration and set the shared code */
        bus = ixl_get_bus_info(hw, dev);
@@ -642,25 +660,32 @@ ixl_attach(device_t dev)
        ixl_update_stats_counters(pf);
        ixl_add_hw_stats(pf);
 
+       /* Reset port's advertised speeds */
+       if (!i40e_is_40G_device(hw->device_id)) {
+               pf->advertised_speed = 0x7;
+               ixl_set_advertised_speeds(pf, 0x7);
+       }
+
        /* Register for VLAN events */
        vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
            ixl_register_vlan, vsi, EVENTHANDLER_PRI_FIRST);
        vsi->vlan_detach = EVENTHANDLER_REGISTER(vlan_unconfig,
            ixl_unregister_vlan, vsi, EVENTHANDLER_PRI_FIRST);
 
+
        INIT_DEBUGOUT("ixl_attach: end");
        return (0);
 
 err_late:
-       ixl_free_vsi(vsi);
+       if (vsi->ifp != NULL)
+               if_free(vsi->ifp);
 err_mac_hmc:
        i40e_shutdown_lan_hmc(hw);
 err_get_cap:
        i40e_shutdown_adminq(hw);
 err_out:
-       if (vsi->ifp != NULL)
-               if_free(vsi->ifp);
        ixl_free_pci_resources(pf);
+       ixl_free_vsi(vsi);
        IXL_PF_LOCK_DESTROY(pf);
        return (error);
 }
@@ -725,6 +750,7 @@ ixl_detach(device_t dev)
        ether_ifdetach(vsi->ifp);
        callout_drain(&pf->timer);
 
+
        ixl_free_pci_resources(pf);
        bus_generic_detach(dev);
        if_free(vsi->ifp);
@@ -2246,6 +2272,34 @@ early:
        return;
 }
 
+static void
+ixl_add_ifmedia(struct ixl_vsi *vsi, u32 phy_type)
+{
+       /* Display supported media types */
+       if (phy_type & (1 << I40E_PHY_TYPE_100BASE_TX))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
+
+       if (phy_type & (1 << I40E_PHY_TYPE_1000BASE_T))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
+
+       if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) ||
+           phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
+       if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
+       if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
+       if (phy_type & (1 << I40E_PHY_TYPE_10GBASE_T))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL);
+
+       if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) ||
+           phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
+       if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
+       if (phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4))
+               ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
+}
 
 /*********************************************************************
  *
@@ -2276,7 +2330,7 @@ ixl_setup_interface(device_t dev, struct
        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
        ifp->if_ioctl = ixl_ioctl;
 
-#if __FreeBSD_version >= 1100000
+#if __FreeBSD_version >= 1100036
        if_setgetcounterfn(ifp, ixl_get_counter);
 #endif
 
@@ -2286,8 +2340,6 @@ ixl_setup_interface(device_t dev, struct
 
        ifp->if_snd.ifq_maxlen = que->num_desc - 2;
 
-       ether_ifattach(ifp, hw->mac.addr);
-
        vsi->max_frame_size =
            ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
            + ETHER_VLAN_ENCAP_LEN;
@@ -2328,40 +2380,26 @@ ixl_setup_interface(device_t dev, struct
                     ixl_media_status);
 
        aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, 
&abilities_resp, NULL);
-       if (aq_error) {
-               printf("Error getting supported media types, AQ error %d\n", 
aq_error);
-               return (EPERM);
-       }
-
-       /* Display supported media types */
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_100BASE_TX))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_100_TX, 0, NULL);
-
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_1000BASE_T))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_1000_T, 0, NULL);
-
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_CR1_CU) ||
-           abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SFPP_CU))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_TWINAX, 0, NULL);
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_SR))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_SR, 0, NULL);
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_LR))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_LR, 0, NULL);
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_10GBASE_T))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_10G_T, 0, NULL);
-               
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4_CU) ||
-           abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_CR4))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_CR4, 0, NULL);
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_SR4))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_SR4, 0, NULL);
-       if (abilities_resp.phy_type & (1 << I40E_PHY_TYPE_40GBASE_LR4))
-               ifmedia_add(&vsi->media, IFM_ETHER | IFM_40G_LR4, 0, NULL);
+       if (aq_error == I40E_ERR_UNKNOWN_PHY) {
+               /* Need delay to detect fiber correctly */
+               i40e_msec_delay(200);
+               aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, TRUE, 
&abilities_resp, NULL);
+               if (aq_error == I40E_ERR_UNKNOWN_PHY)
+                       device_printf(dev, "Unknown PHY type detected!\n");
+               else
+                       ixl_add_ifmedia(vsi, abilities_resp.phy_type);
+       } else if (aq_error) {
+               device_printf(dev, "Error getting supported media types, err 
%d,"
+                   " AQ error %d\n", aq_error, hw->aq.asq_last_status);
+       } else
+               ixl_add_ifmedia(vsi, abilities_resp.phy_type);
 
        /* Use autoselect media by default */
        ifmedia_add(&vsi->media, IFM_ETHER | IFM_AUTO, 0, NULL);
        ifmedia_set(&vsi->media, IFM_ETHER | IFM_AUTO);
 
+       ether_ifattach(ifp, hw->mac.addr);
+
        return (0);
 }
 
@@ -3728,10 +3766,6 @@ ixl_update_stats_counters(struct ixl_pf 
                           pf->stat_offsets_loaded,
                           &osd->eth.rx_discards,
                           &nsd->eth.rx_discards);
-       ixl_stat_update32(hw, I40E_GLPRT_TDPC(hw->port),
-                          pf->stat_offsets_loaded,
-                          &osd->eth.tx_discards,
-                          &nsd->eth.tx_discards);
        ixl_stat_update48(hw, I40E_GLPRT_UPRCH(hw->port),
                           I40E_GLPRT_UPRCL(hw->port),
                           pf->stat_offsets_loaded,
@@ -3915,8 +3949,8 @@ ixl_do_adminq(void *context, int pending
        u32                             reg, loop = 0;
        u16                             opcode, result;
 
-       event.msg_len = IXL_AQ_BUF_SZ;
-       event.msg_buf = malloc(event.msg_len,
+       event.buf_len = IXL_AQ_BUF_SZ;
+       event.msg_buf = malloc(event.buf_len,
            M_DEVBUF, M_NOWAIT | M_ZERO);
        if (!event.msg_buf) {
                printf("Unable to allocate adminq memory\n");
@@ -4300,6 +4334,52 @@ ixl_current_speed(SYSCTL_HANDLER_ARGS)
        return (error);
 }
 
+static int
+ixl_set_advertised_speeds(struct ixl_pf *pf, int speeds)
+{
+       struct i40e_hw *hw = &pf->hw;
+       device_t dev = pf->dev;
+       struct i40e_aq_get_phy_abilities_resp abilities;
+       struct i40e_aq_set_phy_config config;
+       enum i40e_status_code aq_error = 0;
+
+       /* Get current capability information */
+       aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, FALSE, &abilities, 
NULL);
+       if (aq_error) {
+               device_printf(dev, "%s: Error getting phy capabilities %d,"
+                   " aq error: %d\n", __func__, aq_error,
+                   hw->aq.asq_last_status);
+               return (EAGAIN);
+       }
+
+       /* Prepare new config */
+       bzero(&config, sizeof(config));
+       config.phy_type = abilities.phy_type;
+       config.abilities = abilities.abilities
+           | I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
+       config.eee_capability = abilities.eee_capability;
+       config.eeer = abilities.eeer_val;
+       config.low_power_ctrl = abilities.d3_lpan;
+       /* Translate into aq cmd link_speed */
+       if (speeds & 0x4)
+               config.link_speed |= I40E_LINK_SPEED_10GB;
+       if (speeds & 0x2)
+               config.link_speed |= I40E_LINK_SPEED_1GB;
+       if (speeds & 0x1)
+               config.link_speed |= I40E_LINK_SPEED_100MB;
+
+       /* Do aq command & restart link */
+       aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
+       if (aq_error) {
+               device_printf(dev, "%s: Error setting new phy config %d,"
+                   " aq error: %d\n", __func__, aq_error,
+                   hw->aq.asq_last_status);
+               return (EAGAIN);
+       }
+
+       return (0);
+}
+
 /*
 ** Control link advertise speed:
 **     Flags:
@@ -4315,10 +4395,7 @@ ixl_set_advertise(SYSCTL_HANDLER_ARGS)
        struct ixl_pf *pf = (struct ixl_pf *)arg1;
        struct i40e_hw *hw = &pf->hw;
        device_t dev = pf->dev;
-       struct i40e_aq_get_phy_abilities_resp abilities;
-       struct i40e_aq_set_phy_config config;
        int requested_ls = 0;
-       enum i40e_status_code aq_error = 0;
        int error = 0;
 
        /*
@@ -4343,39 +4420,9 @@ ixl_set_advertise(SYSCTL_HANDLER_ARGS)
        if (pf->advertised_speed == requested_ls)
                return (0);
 
-       /* Get current capability information */
-       aq_error = i40e_aq_get_phy_capabilities(hw, FALSE, FALSE, &abilities, 
NULL);
-       if (aq_error) {
-               device_printf(dev, "%s: Error getting phy capabilities %d,"
-                   " aq error: %d\n", __func__, aq_error,
-                   hw->aq.asq_last_status);
-               return (EAGAIN);
-       }
-
-       /* Prepare new config */
-       bzero(&config, sizeof(config));
-       config.phy_type = abilities.phy_type;
-       config.abilities = abilities.abilities
-           | I40E_AQ_PHY_ENABLE_ATOMIC_LINK;
-       config.eee_capability = abilities.eee_capability;
-       config.eeer = abilities.eeer_val;
-       config.low_power_ctrl = abilities.d3_lpan;
-       /* Translate into aq cmd link_speed */
-       if (requested_ls & 0x4)
-               config.link_speed |= I40E_LINK_SPEED_10GB;
-       if (requested_ls & 0x2)
-               config.link_speed |= I40E_LINK_SPEED_1GB;
-       if (requested_ls & 0x1)
-               config.link_speed |= I40E_LINK_SPEED_100MB;
-
-       /* Do aq command & restart link */
-       aq_error = i40e_aq_set_phy_config(hw, &config, NULL);
-       if (aq_error) {
-               device_printf(dev, "%s: Error setting new phy config %d,"
-                   " aq error: %d\n", __func__, aq_error,
-                   hw->aq.asq_last_status);
-               return (EAGAIN);
-       }
+       error = ixl_set_advertised_speeds(pf, requested_ls);
+       if (error)
+               return (error);
 
        pf->advertised_speed = requested_ls;
        ixl_update_link_status(pf);
@@ -4454,6 +4501,26 @@ ixl_get_bus_info(struct i40e_hw *hw, dev
         return (link);
 }
 
+static int
+ixl_sysctl_show_fw(SYSCTL_HANDLER_ARGS)
+{
+       struct ixl_pf   *pf = (struct ixl_pf *)arg1;
+       struct i40e_hw  *hw = &pf->hw;
+       char            buf[32];
+
+       snprintf(buf, sizeof(buf),
+           "f%d.%d a%d.%d n%02x.%02x e%08x",
+           hw->aq.fw_maj_ver, hw->aq.fw_min_ver,
+           hw->aq.api_maj_ver, hw->aq.api_min_ver,
+           (hw->nvm.version & IXL_NVM_VERSION_HI_MASK) >>
+           IXL_NVM_VERSION_HI_SHIFT,
+           (hw->nvm.version & IXL_NVM_VERSION_LO_MASK) >>
+           IXL_NVM_VERSION_LO_SHIFT,
+           hw->nvm.eetrack);
+       return (sysctl_handle_string(oidp, buf, strlen(buf), req));
+}
+
+
 #ifdef IXL_DEBUG
 static int
 ixl_sysctl_link_status(SYSCTL_HANDLER_ARGS)
@@ -4563,7 +4630,7 @@ ixl_sysctl_sw_filter_list(SYSCTL_HANDLER
 
 #define IXL_SW_RES_SIZE 0x14
 static int
-ixl_sysctl_hw_res_info(SYSCTL_HANDLER_ARGS)
+ixl_sysctl_hw_res_alloc(SYSCTL_HANDLER_ARGS)
 {
        struct ixl_pf *pf = (struct ixl_pf *)arg1;
        struct i40e_hw *hw = &pf->hw;
@@ -4620,7 +4687,120 @@ ixl_sysctl_hw_res_info(SYSCTL_HANDLER_AR
                device_printf(dev, "sysctl error: %d\n", error);
        sbuf_delete(buf);
        return error;
+}
+
+/*
+** Caller must init and delete sbuf; this function will clear and
+** finish it for caller.
+*/
+static char *
+ixl_switch_element_string(struct sbuf *s, u16 seid, bool uplink)
+{
+       sbuf_clear(s);
 
+       if (seid == 0 && uplink)
+               sbuf_cat(s, "Network");
+       else if (seid == 0)
+               sbuf_cat(s, "Host");
+       else if (seid == 1)
+               sbuf_cat(s, "EMP");
+       else if (seid <= 5)
+               sbuf_printf(s, "MAC %d", seid - 2);
+       else if (seid <= 15)
+               sbuf_cat(s, "Reserved");
+       else if (seid <= 31)
+               sbuf_printf(s, "PF %d", seid - 16);
+       else if (seid <= 159)
+               sbuf_printf(s, "VF %d", seid - 32);
+       else if (seid <= 287)
+               sbuf_cat(s, "Reserved");
+       else if (seid <= 511)
+               sbuf_cat(s, "Other"); // for other structures
+       else if (seid <= 895)
+               sbuf_printf(s, "VSI %d", seid - 512);
+       else if (seid <= 1023)
+               sbuf_printf(s, "Reserved");
+       else
+               sbuf_cat(s, "Invalid");
+
+       sbuf_finish(s);
+       return sbuf_data(s);
+}
+
+static int
+ixl_sysctl_switch_config(SYSCTL_HANDLER_ARGS)
+{
+       struct ixl_pf *pf = (struct ixl_pf *)arg1;
+       struct i40e_hw *hw = &pf->hw;
+       device_t dev = pf->dev;
+       struct sbuf *buf;
+       struct sbuf *nmbuf;
+       int error = 0;
+       u8 aq_buf[I40E_AQ_LARGE_BUF];
+
+       u16 next = 0;
+       struct i40e_aqc_get_switch_config_resp *sw_config;
+       sw_config = (struct i40e_aqc_get_switch_config_resp *)aq_buf;
+
+       buf = sbuf_new_for_sysctl(NULL, NULL, 0, req);
+       if (!buf) {
+               device_printf(dev, "Could not allocate sbuf for sysctl 
output.\n");
+               return (ENOMEM);
+       }
+
+       error = i40e_aq_get_switch_config(hw, sw_config,
+           sizeof(aq_buf), &next, NULL);
+       if (error) {
+               device_printf(dev, "%s: aq_get_switch_config() error %d, aq 
error %d\n",
+                   __func__, error, hw->aq.asq_last_status);
+               sbuf_delete(buf);
+               return error;
+       }
+
+       nmbuf = sbuf_new_auto();
+       if (!nmbuf) {
+               device_printf(dev, "Could not allocate sbuf for name 
output.\n");
+               return (ENOMEM);
+       }
+
+       sbuf_cat(buf, "\n");
+       // Assuming <= 255 elements in switch
+       sbuf_printf(buf, "# of elements: %d\n", sw_config->header.num_reported);
+       /* Exclude:
+       ** Revision -- all elements are revision 1 for now
+       */
+       sbuf_printf(buf,
+           "SEID (  Name  ) |  Uplink  | Downlink | Conn Type\n"
+           "                |          |          | (uplink)\n");
+       for (int i = 0; i < sw_config->header.num_reported; i++) {
+               // "%4d (%8s) | %8s   %8s   %#8x",
+               sbuf_printf(buf, "%4d", sw_config->element[i].seid);
+               sbuf_cat(buf, " ");
+               sbuf_printf(buf, "(%8s)", ixl_switch_element_string(nmbuf, 
sw_config->element[i].seid, false));
+               sbuf_cat(buf, " | ");
+               sbuf_printf(buf, "%8s", ixl_switch_element_string(nmbuf, 
sw_config->element[i].uplink_seid, true));
+               sbuf_cat(buf, "   ");
+               sbuf_printf(buf, "%8s", ixl_switch_element_string(nmbuf, 
sw_config->element[i].downlink_seid, false));
+               sbuf_cat(buf, "   ");
+               sbuf_printf(buf, "%#8x", sw_config->element[i].connection_type);
+               if (i < sw_config->header.num_reported - 1)
+                       sbuf_cat(buf, "\n");
+       }
+       sbuf_delete(nmbuf);
+
+       error = sbuf_finish(buf);
+       if (error) {
+               device_printf(dev, "Error finishing sbuf: %d\n", error);
+               sbuf_delete(buf);
+               return error;
+       }
+
+       error = sysctl_handle_string(oidp, sbuf_data(buf), sbuf_len(buf), req);
+       if (error)
+               device_printf(dev, "sysctl error: %d\n", error);
+       sbuf_delete(buf);
+
+       return (error);
 }
 
 /*

Modified: head/sys/dev/ixl/if_ixlv.c
==============================================================================
--- head/sys/dev/ixl/if_ixlv.c  Thu Nov  6 23:35:22 2014        (r274204)
+++ head/sys/dev/ixl/if_ixlv.c  Thu Nov  6 23:45:05 2014        (r274205)
@@ -40,7 +40,7 @@
 /*********************************************************************
  *  Driver version
  *********************************************************************/
-char ixlv_driver_version[] = "1.1.4";
+char ixlv_driver_version[] = "1.1.18";
 
 /*********************************************************************
  *  PCI Device ID Table
@@ -87,7 +87,6 @@ static void   ixlv_config_rss(struct ixlv_
 static void    ixlv_stop(struct ixlv_sc *);
 static void    ixlv_add_multi(struct ixl_vsi *);
 static void    ixlv_del_multi(struct ixl_vsi *);
-static void    ixlv_update_link_status(struct ixlv_sc *);
 static void    ixlv_free_queues(struct ixl_vsi *);
 static int     ixlv_setup_interface(device_t, struct ixlv_sc *);
 
@@ -97,18 +96,21 @@ static void ixlv_media_status(struct ifn
 static void    ixlv_local_timer(void *);
 
 static int     ixlv_add_mac_filter(struct ixlv_sc *, u8 *, u16);
+static int     ixlv_del_mac_filter(struct ixlv_sc *sc, u8 *macaddr);
 static void    ixlv_init_filters(struct ixlv_sc *);
 static void    ixlv_free_filters(struct ixlv_sc *);
 
 static void    ixlv_msix_que(void *);
 static void    ixlv_msix_adminq(void *);
 static void    ixlv_do_adminq(void *, int);
-static void    ixlv_sched_aq(void *);
+static void    ixlv_do_adminq_locked(struct ixlv_sc *sc);
 static void    ixlv_handle_que(void *, int);
 static int     ixlv_reset(struct ixlv_sc *);
 static int     ixlv_reset_complete(struct i40e_hw *);
 static void    ixlv_set_queue_rx_itr(struct ixl_queue *);
 static void    ixlv_set_queue_tx_itr(struct ixl_queue *);
+static void    ixl_init_cmd_complete(struct ixl_vc_cmd *, void *,
+                   enum i40e_status_code);
 
 static void    ixlv_enable_adminq_irq(struct i40e_hw *);
 static void    ixlv_disable_adminq_irq(struct i40e_hw *);
@@ -119,10 +121,16 @@ static void       ixlv_setup_vlan_filters(stru
 static void    ixlv_register_vlan(void *, struct ifnet *, u16);
 static void    ixlv_unregister_vlan(void *, struct ifnet *, u16);
 
+static void    ixlv_init_hw(struct ixlv_sc *);
+static int     ixlv_setup_vc(struct ixlv_sc *);
+static int     ixlv_vf_config(struct ixlv_sc *);
+
 static void    ixlv_cap_txcsum_tso(struct ixl_vsi *,
                    struct ifnet *, int);
 
-static void    ixlv_add_stats_sysctls(struct ixlv_sc *);
+static void    ixlv_add_sysctls(struct ixlv_sc *);
+static int     ixlv_sysctl_qtx_tail_handler(SYSCTL_HANDLER_ARGS);
+static int     ixlv_sysctl_qrx_tail_handler(SYSCTL_HANDLER_ARGS);
 
 /*********************************************************************
  *  FreeBSD Device Interface Entry Points
@@ -271,7 +279,7 @@ ixlv_attach(device_t dev)
        struct ixlv_sc  *sc;
        struct i40e_hw  *hw;
        struct ixl_vsi  *vsi;
-       int             bufsz, error = 0, retries = 0;
+       int             error = 0;
 
        INIT_DBG_DEV(dev, "begin");
 
@@ -282,30 +290,18 @@ ixlv_attach(device_t dev)
        vsi = &sc->vsi;
        vsi->dev = dev;
 
+       /* Initialize hw struct */
+       ixlv_init_hw(sc);
+
        /* Allocate filter lists */
        ixlv_init_filters(sc);
 
        /* Core Lock Init*/
        mtx_init(&sc->mtx, device_get_nameunit(dev),
            "IXL SC Lock", MTX_DEF);
-       mtx_init(&sc->aq_task_mtx, device_get_nameunit(dev),
-           "IXL AQ Task Lock", MTX_DEF);
 
-       /* Set up the timer & aq watchdog callouts */
+       /* Set up the timer callout */
        callout_init_mtx(&sc->timer, &sc->mtx, 0);
-       callout_init_mtx(&sc->aq_task, &sc->aq_task_mtx, 0);
-
-       /* Save off the information about this board */
-       hw->vendor_id = pci_get_vendor(dev);
-       hw->device_id = pci_get_device(dev);
-       hw->revision_id = pci_read_config(dev, PCIR_REVID, 1);
-       hw->subsystem_vendor_id =
-           pci_read_config(dev, PCIR_SUBVEND_0, 2);
-       hw->subsystem_device_id =
-           pci_read_config(dev, PCIR_SUBDEV_0, 2);
-
-       hw->bus.device = pci_get_slot(dev);
-       hw->bus.func = pci_get_function(dev);
 
        /* Do PCI setup - map BAR0, etc */
        if (ixlv_allocate_pci_resources(sc)) {
@@ -333,50 +329,16 @@ ixlv_attach(device_t dev)
 
        INIT_DBG_DEV(dev, "VF Device is ready for configuration");
 
-       hw->aq.num_arq_entries = IXL_AQ_LEN;
-       hw->aq.num_asq_entries = IXL_AQ_LEN;
-       hw->aq.arq_buf_size = IXL_AQ_BUFSZ;
-       hw->aq.asq_buf_size = IXL_AQ_BUFSZ;
-
-       error = i40e_init_adminq(hw);
+       error = ixlv_setup_vc(sc);
        if (error) {
-               device_printf(dev, "%s: init_adminq failed: %d\n",
+               device_printf(dev, "%s: Error setting up PF comms, %d\n",
                    __func__, error);
                goto err_pci_res;
        }
 
-       INIT_DBG_DEV(dev, "Initialized Admin Queue");
-
-       error = ixlv_send_api_ver(sc);
-       if (error) {
-               device_printf(dev, "%s: unable to send to PF (%d)\n",
-                    __func__, error);
-               goto err_aq;
-       }
-
-       while (!i40e_asq_done(hw)) {
-               if (++retries > IXLV_AQ_MAX_ERR) {
-                       device_printf(dev, "%s: Admin Queue timeout "
-                           "(waiting for send_api_ver)\n", __func__);
-                       error = ENXIO;
-                       goto err_aq;
-               }
-               i40e_msec_delay(10);
-       }
-
-       INIT_DBG_DEV(dev, "Sent API version message to PF");
-
-       /* Wait for API version msg to arrive */
-       error = ixlv_verify_api_ver(sc);
-       if (error) {
-               device_printf(dev,
-                   "%s: Unable to verify API version, error %d\n",
-                           __func__, error);
-               goto err_aq;
-       }
-
        INIT_DBG_DEV(dev, "PF API version verified");
 
+       /* TODO: Figure out why MDD events occur when this reset is removed. */
        /* Need API version before sending reset message */
        error = ixlv_reset(sc);
        if (error) {
@@ -387,49 +349,14 @@ ixlv_attach(device_t dev)
        INIT_DBG_DEV(dev, "VF reset complete");
 
        /* Ask for VF config from PF */
-       error = ixlv_send_vf_config_msg(sc);
+       error = ixlv_vf_config(sc);
        if (error) {
-               device_printf(dev,
-                   "%s: Unable to send VF config request, error %d\n",
-                   __func__, error);
-               goto err_aq;
-       }
-
-       retries = 0;
-       while (!i40e_asq_done(hw)) {
-               if (++retries > IXLV_AQ_MAX_ERR) {
-                       device_printf(dev, "%s: Admin Queue timeout "
-                           "(waiting for send_vf_config_msg)\n", __func__);
-                       error = ENXIO;
-                       goto err_aq;
-               }
-               i40e_msec_delay(10);
-       }
-
-       INIT_DBG_DEV(dev, "Sent VF config message to PF");
-
-       bufsz = sizeof(struct i40e_virtchnl_vf_resource) +
-           (I40E_MAX_VF_VSI * sizeof(struct i40e_virtchnl_vsi_resource));
-       sc->vf_res = malloc(bufsz, M_DEVBUF, M_NOWAIT);
-       if (!sc->vf_res) {
-               device_printf(dev,
-                   "%s: Unable to allocate memory for VF configuration"
-                   " message from PF\n", __func__);
-               error = ENOMEM;
+               device_printf(dev, "Error getting configuration from PF: %d\n",
+                   error);
                goto err_aq;
        }
 
-       /* Check for VF config response */
-       error = ixlv_get_vf_config(sc);
-       if (error) {
-               device_printf(dev,
-                   "%s: Unable to get VF configuration from PF\n",
-                   __func__);
-               error = EBUSY;
-               goto err_res_buf;
-       }
-
-       INIT_DBG_DEV(dev, "Received valid VF config from PF");
+       INIT_DBG_DEV(dev, "VF config from PF:");
        INIT_DBG_DEV(dev, "VSIs %d, Queues %d, Max Vectors %d, Max MTU %d",
            sc->vf_res->num_vsis,
            sc->vf_res->num_queue_pairs,
@@ -438,6 +365,7 @@ ixlv_attach(device_t dev)
        INIT_DBG_DEV(dev, "Offload flags: %#010x",
            sc->vf_res->vf_offload_flags);
 
+       // TODO: Move this into ixlv_vf_config?
        /* got VF config message back from PF, now we can parse it */
        for (int i = 0; i < sc->vf_res->num_vsis; i++) {
                if (sc->vf_res->vsi_res[i].vsi_type == I40E_VSI_SRIOV)
@@ -445,6 +373,7 @@ ixlv_attach(device_t dev)
        }
        if (!sc->vsi_res) {
                device_printf(dev, "%s: no LAN VSI found\n", __func__);
+               error = EIO;
                goto err_res_buf;
        }
 
@@ -461,14 +390,13 @@ ixlv_attach(device_t dev)
 
        vsi->id = sc->vsi_res->vsi_id;
        vsi->back = (void *)sc;
-
-       /* Link in this virtual environment is always 'up' */
        vsi->link_up = TRUE;
 
        /* This allocates the memory and early settings */
        if (ixlv_setup_queues(sc) != 0) {
                device_printf(dev, "%s: setup queues failed!\n",
                    __func__);
+               error = EIO;
                goto out;
        }
 
@@ -476,6 +404,7 @@ ixlv_attach(device_t dev)
        if (ixlv_setup_interface(dev, sc) != 0) {
                device_printf(dev, "%s: setup interface failed!\n",
                    __func__);
+               error = EIO;
                goto out;
        }
 
@@ -487,12 +416,9 @@ ixlv_attach(device_t dev)
        /* Start AdminQ taskqueue */
        ixlv_init_taskqueue(sc);
 
-       /* Start the admin queue scheduler timer */
-       callout_reset(&sc->aq_task, 2 * hz, ixlv_sched_aq, sc);
-
        /* Initialize stats */
        bzero(&sc->vsi.eth_stats, sizeof(struct i40e_eth_stats));
-       ixlv_add_stats_sysctls(sc);
+       ixlv_add_sysctls(sc);
 
        /* Register for VLAN events */
        vsi->vlan_attach = EVENTHANDLER_REGISTER(vlan_config,
@@ -504,10 +430,10 @@ ixlv_attach(device_t dev)
        ixlv_enable_adminq_irq(hw);
 
        /* Set things up to run init */
-       sc->aq_pending = 0;
-       sc->aq_required = 0;
        sc->init_state = IXLV_INIT_READY;
 
+       ixl_vc_init_mgr(sc, &sc->vc_mgr);
+
        INIT_DBG_DEV(dev, "end");
        return (error);
 
@@ -521,7 +447,6 @@ err_pci_res:
        ixlv_free_pci_resources(sc);
 err_early:
        mtx_destroy(&sc->mtx);
-       mtx_destroy(&sc->aq_task_mtx);
        ixlv_free_filters(sc);
        INIT_DBG_DEV(dev, "end: error %d", error);
        return (error);
@@ -542,7 +467,6 @@ ixlv_detach(device_t dev)
 {
        struct ixlv_sc  *sc = device_get_softc(dev);
        struct ixl_vsi  *vsi = &sc->vsi;
-       int                      retries = 0;
 
        INIT_DBG_DEV(dev, "begin");
 
@@ -554,23 +478,11 @@ ixlv_detach(device_t dev)
        }
 
        /* Stop driver */
+       ether_ifdetach(vsi->ifp);
        if (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING) {
                mtx_lock(&sc->mtx);     
                ixlv_stop(sc);
                mtx_unlock(&sc->mtx);   
-
-               /*
-               ** Ensure queues are disabled before examining
-               ** admin queue state later in detach.
-               */
-               while (vsi->ifp->if_drv_flags & IFF_DRV_RUNNING
-                   && ++retries < IXLV_AQ_MAX_ERR) {
-                       i40e_msec_delay(10);
-               }
-#ifdef IXL_DEBUG
-               if (retries >= IXLV_AQ_MAX_ERR)
-                       device_printf(dev, "Issue disabling queues for 
detach\n");
-#endif
        }
 
        /* Unregister VLAN events */
@@ -579,37 +491,16 @@ ixlv_detach(device_t dev)
        if (vsi->vlan_detach != NULL)
                EVENTHANDLER_DEREGISTER(vlan_unconfig, vsi->vlan_detach);
 
-       /* Stop AQ callout */
-       callout_drain(&sc->aq_task);
-       callout_stop(&sc->aq_task);
-
-#ifdef IXL_DEBUG
-       /* Report on possible AQ failures */
-       if (sc->aq_required || sc->aq_pending) {
-               device_printf(dev, "AQ status on detach:\n");
-               device_printf(dev, "required  : 0x%4b\n", sc->aq_required,
-                   IXLV_FLAGS);
-               device_printf(dev, "pending   : 0x%4b\n", sc->aq_pending,
-                   IXLV_FLAGS);
-               device_printf(dev, "current_op: %d\n", sc->current_op);
-       }
-#endif
+       /* Drain VC mgr */
+       callout_drain(&sc->vc_mgr.callout);
 
        i40e_shutdown_adminq(&sc->hw);
-       while (taskqueue_cancel(sc->tq, &sc->aq_irq, NULL) != 0)
-               taskqueue_drain(sc->tq, &sc->aq_irq);
        taskqueue_free(sc->tq);
-
-       /* force the state down */
-       vsi->ifp->if_flags &= ~IFF_UP;
-       ether_ifdetach(vsi->ifp);
        if_free(vsi->ifp);
-
        free(sc->vf_res, M_DEVBUF);
        ixlv_free_pci_resources(sc);
        ixlv_free_queues(vsi);
        mtx_destroy(&sc->mtx);
-       mtx_destroy(&sc->aq_task_mtx);
        ixlv_free_filters(sc);
 
        bus_generic_detach(dev);
@@ -754,7 +645,7 @@ ixlv_ioctl(struct ifnet *ifp, u_long com
                if (avoid_reset) {
                        ifp->if_flags |= IFF_UP;
                        if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
-                               ixlv_init(sc);
+                               ixlv_init(vsi);
 #ifdef INET
                        if (!(ifp->if_flags & IFF_NOARP))
                                arp_ifinit(ifp, ifa);
@@ -773,11 +664,10 @@ ixlv_ioctl(struct ifnet *ifp, u_long com
                } else {
                        IOCTL_DBG_IF2(ifp, "mtu: %lu -> %d", ifp->if_mtu, 
ifr->ifr_mtu);
                        // ERJ: Interestingly enough, these types don't match
-                       ifp->if_mtu = ifr->ifr_mtu;
+                       ifp->if_mtu = (u_long)ifr->ifr_mtu;
                        vsi->max_frame_size =
                            ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN
                            + ETHER_VLAN_ENCAP_LEN;
-
                        ixlv_init_locked(sc);
                }
                mtx_unlock(&sc->mtx);
@@ -839,7 +729,7 @@ ixlv_ioctl(struct ifnet *ifp, u_long com
                if (mask & IFCAP_VLAN_HWTSO)
                        ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
                if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
-                       ixlv_init(sc);
+                       ixlv_init(vsi);
                }
                VLAN_CAPABILITIES(ifp);
 
@@ -869,6 +759,7 @@ ixlv_reinit_locked(struct ixlv_sc *sc)
        struct i40e_hw          *hw = &sc->hw;
        struct ixl_vsi          *vsi = &sc->vsi;
        struct ifnet            *ifp = vsi->ifp;
+       struct ixlv_mac_filter  *mf, *mf_temp;
        struct ixlv_vlan_filter *vf;
        int                     error = 0;
 
@@ -877,13 +768,25 @@ ixlv_reinit_locked(struct ixlv_sc *sc)
        if (ifp->if_drv_flags & IFF_DRV_RUNNING)
                ixlv_stop(sc);
 
-       if ((sc->init_state == IXLV_RESET_REQUIRED) ||
-           (sc->init_state == IXLV_RESET_PENDING))
-               error = ixlv_reset(sc);
+       error = ixlv_reset(sc);
+
+       INIT_DBG_IF(ifp, "VF was reset");
 
        /* set the state in case we went thru RESET */
        sc->init_state = IXLV_RUNNING;
 
+       /*
+       ** Resetting the VF drops all filters from hardware;
+       ** we need to mark them to be re-added in init.
+       */
+       SLIST_FOREACH_SAFE(mf, sc->mac_filters, next, mf_temp) {
+               if (mf->flags & IXL_FILTER_DEL) {
+                       SLIST_REMOVE(sc->mac_filters, mf,
+                           ixlv_mac_filter, next);
+                       free(mf, M_DEVBUF);
+               } else
+                       mf->flags |= IXL_FILTER_ADD;
+       }
        if (vsi->num_vlans != 0)
                SLIST_FOREACH(vf, sc->vlan_filters, next)
                        vf->flags = IXL_FILTER_ADD;
@@ -896,13 +799,31 @@ ixlv_reinit_locked(struct ixlv_sc *sc)
        }
 
        ixlv_enable_adminq_irq(hw);
-       sc->aq_pending = 0;
-       sc->aq_required = 0;
+       ixl_vc_flush(&sc->vc_mgr);
 

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[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