From owner-svn-src-all@FreeBSD.ORG Thu Nov 6 23:45:07 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id D777E3A1; Thu, 6 Nov 2014 23:45:06 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C2EA5FDF; Thu, 6 Nov 2014 23:45:06 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sA6Nj6iq047065; Thu, 6 Nov 2014 23:45:06 GMT (envelope-from jfv@FreeBSD.org) Received: (from jfv@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sA6Nj55a047058; Thu, 6 Nov 2014 23:45:05 GMT (envelope-from jfv@FreeBSD.org) Message-Id: <201411062345.sA6Nj55a047058@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: jfv set sender to jfv@FreeBSD.org using -f From: Jack F Vogel Date: Thu, 6 Nov 2014 23:45:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r274205 - in head/sys: dev/ixl modules/ixlv X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Nov 2014 23:45:07 -0000 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 ***