Module Name: src Committed By: martin Date: Thu Sep 26 19:07:23 UTC 2019
Modified Files: src/share/man/man4 [netbsd-9]: ixv.4 src/sys/dev/pci/ixgbe [netbsd-9]: ixgbe.c ixgbe.h ixgbe_type.h ixgbe_vf.c ixgbe_vf.h ixgbe_x550.c ixv.c Log Message: Pull up the following revisions, requested by msaitoh in ticket #246: sys/dev/pci/ixgbe/ixgbe_type.h 1.42-1.43 sys/dev/pci/ixgbe/ixgbe.c 1.209-1.213 sys/dev/pci/ixgbe/ixgbe_x550.c 1.16 sys/dev/pci/ixgbe/ixv.c 1.131-1.138 sys/dev/pci/ixgbe/ixgbe_vf.c 1.19-1.22 sys/dev/pci/ixgbe/ixgbe_vf.h 1.14 sys/dev/pci/ixgbe/ixgbe.h 1.57-1.58 share/man/man4/ixv.4 1.5 - Fix a bug that MBSDC (Bad SFD Count) isn't counted on X550EM_X and X550EM_A. The register is for X550 and newer. - ixv(4): Make SIOCADDMULTI returns ENOSPC and print error message when the Ethernet multicast address list exceeds the limit(30) and can't be ALLMULTI. - ixv(4): SIOCZIFDATA clear the event counters as ixgbe.c. - Reduce ixv(4)'s multicast table array size in ixv_set_multi from MAX_NUM_MULTICAST_ADDRESSES(128) to IXGBE_MAX_VF_MC(30). - ixv(4): Add support ALLMULTI and PROMISC. - if_flags is neither int nor short. It's unsigned short. - ixg(4): Fix a bug that the multicast filter isn't correctly initialized when the total number of the Ethernet multicast addresses is just 128. - Make ixv_set_multi() work correctly (especially for PROMISC) when the function is called from if_init(). - Remove *_set_promisc() and use *_set_multi(). And then, rename *_set_multi() to *_set_rxfilter(). - ixv(4): If a multicast entry has range, use ALLMULTI like others. - Fix typo in comment. Found by Wataru Ashihara. To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.4.2.1 src/share/man/man4/ixv.4 cvs rdiff -u -r1.199.2.4 -r1.199.2.5 src/sys/dev/pci/ixgbe/ixgbe.c cvs rdiff -u -r1.56 -r1.56.2.1 src/sys/dev/pci/ixgbe/ixgbe.h cvs rdiff -u -r1.41 -r1.41.2.1 src/sys/dev/pci/ixgbe/ixgbe_type.h cvs rdiff -u -r1.18 -r1.18.2.1 src/sys/dev/pci/ixgbe/ixgbe_vf.c cvs rdiff -u -r1.13 -r1.13.8.1 src/sys/dev/pci/ixgbe/ixgbe_vf.h cvs rdiff -u -r1.15 -r1.15.2.1 src/sys/dev/pci/ixgbe/ixgbe_x550.c cvs rdiff -u -r1.125.2.3 -r1.125.2.4 src/sys/dev/pci/ixgbe/ixv.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man4/ixv.4 diff -u src/share/man/man4/ixv.4:1.4 src/share/man/man4/ixv.4:1.4.2.1 --- src/share/man/man4/ixv.4:1.4 Thu Jul 18 03:52:26 2019 +++ src/share/man/man4/ixv.4 Thu Sep 26 19:07:23 2019 @@ -1,4 +1,4 @@ -.\" $NetBSD: ixv.4,v 1.4 2019/07/18 03:52:26 msaitoh Exp $ +.\" $NetBSD: ixv.4,v 1.4.2.1 2019/09/26 19:07:23 martin Exp $ .\" .\" Copyright (c) 2018 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd July 18, 2019 +.Dd September 5, 2019 .Dt IXV 4 .Os .Sh NAME @@ -61,3 +61,20 @@ The .Nm driver was written by .An Intel Corporation Aq Mt freebsd...@mailbox.intel.com . +.Sh BUGS +The following event counters are not cleared by +.Dv SIOCZIFDATA +because the corresponding registers are read only and not cleared on read: +.Pp +.Bl -item -offset indent -compact +.It +Good Packets Received +.It +Good Octets Received +.It +Multicast Packets Received +.It +Good Packets Transmitted +.It +Good Octets Transmitted +.El Index: src/sys/dev/pci/ixgbe/ixgbe.c diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.4 src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.5 --- src/sys/dev/pci/ixgbe/ixgbe.c:1.199.2.4 Thu Sep 5 09:11:03 2019 +++ src/sys/dev/pci/ixgbe/ixgbe.c Thu Sep 26 19:07:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.c,v 1.199.2.4 2019/09/05 09:11:03 martin Exp $ */ +/* $NetBSD: ixgbe.c,v 1.199.2.5 2019/09/26 19:07:22 martin Exp $ */ /****************************************************************************** @@ -211,8 +211,7 @@ static void ixgbe_initialize_rss_mapping static void ixgbe_enable_intr(struct adapter *); static void ixgbe_disable_intr(struct adapter *); static void ixgbe_update_stats_counters(struct adapter *); -static void ixgbe_set_promisc(struct adapter *); -static void ixgbe_set_multi(struct adapter *); +static void ixgbe_set_rxfilter(struct adapter *); static void ixgbe_update_link_status(struct adapter *); static void ixgbe_set_ivar(struct adapter *, u8, u8, s8); static void ixgbe_configure_ivars(struct adapter *); @@ -1571,7 +1570,7 @@ ixgbe_update_stats_counters(struct adapt stats->illerrc.ev_count += IXGBE_READ_REG(hw, IXGBE_ILLERRC); stats->errbc.ev_count += IXGBE_READ_REG(hw, IXGBE_ERRBC); stats->mspdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MSPDC); - if (hw->mac.type == ixgbe_mac_X550) + if (hw->mac.type >= ixgbe_mac_X550) stats->mbsdc.ev_count += IXGBE_READ_REG(hw, IXGBE_MBSDC); /* 16 registers exist */ @@ -2126,7 +2125,8 @@ ixgbe_clear_evcnt(struct adapter *adapte stats->illerrc.ev_count = 0; stats->errbc.ev_count = 0; stats->mspdc.ev_count = 0; - stats->mbsdc.ev_count = 0; + if (hw->mac.type >= ixgbe_mac_X550) + stats->mbsdc.ev_count = 0; stats->mpctotal.ev_count = 0; stats->mlfc.ev_count = 0; stats->mrfc.ev_count = 0; @@ -3041,49 +3041,6 @@ invalid: } /* ixgbe_media_change */ /************************************************************************ - * ixgbe_set_promisc - ************************************************************************/ -static void -ixgbe_set_promisc(struct adapter *adapter) -{ - struct ifnet *ifp = adapter->ifp; - int mcnt = 0; - u32 rctl; - struct ether_multi *enm; - struct ether_multistep step; - struct ethercom *ec = &adapter->osdep.ec; - - KASSERT(mutex_owned(&adapter->core_mtx)); - rctl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); - rctl &= (~IXGBE_FCTRL_UPE); - ETHER_LOCK(ec); - if (ec->ec_flags & ETHER_F_ALLMULTI) - mcnt = MAX_NUM_MULTICAST_ADDRESSES; - else { - ETHER_FIRST_MULTI(step, ec, enm); - while (enm != NULL) { - if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) - break; - mcnt++; - ETHER_NEXT_MULTI(step, enm); - } - } - if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) - rctl &= (~IXGBE_FCTRL_MPE); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); - - if (ifp->if_flags & IFF_PROMISC) { - rctl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); - } else if (ec->ec_flags & ETHER_F_ALLMULTI) { - rctl |= IXGBE_FCTRL_MPE; - rctl &= ~IXGBE_FCTRL_UPE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); - } - ETHER_UNLOCK(ec); -} /* ixgbe_set_promisc */ - -/************************************************************************ * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) ************************************************************************/ static int @@ -3993,7 +3950,7 @@ ixgbe_init_locked(struct adapter *adapte ixgbe_initialize_transmit_units(adapter); /* Setup Multicast table */ - ixgbe_set_multi(adapter); + ixgbe_set_rxfilter(adapter); /* Determine the correct mbuf pool, based on frame size */ if (adapter->max_frame_size <= MCLBYTES) @@ -4382,12 +4339,12 @@ ixgbe_config_delay_values(struct adapter } /* ixgbe_config_delay_values */ /************************************************************************ - * ixgbe_set_multi - Multicast Update + * ixgbe_set_rxfilter - Multicast Update * * Called whenever multicast address list is updated. ************************************************************************/ static void -ixgbe_set_multi(struct adapter *adapter) +ixgbe_set_rxfilter(struct adapter *adapter) { struct ixgbe_mc_addr *mta; struct ifnet *ifp = adapter->ifp; @@ -4399,7 +4356,7 @@ ixgbe_set_multi(struct adapter *adapter) struct ether_multistep step; KASSERT(mutex_owned(&adapter->core_mtx)); - IOCTL_DEBUGOUT("ixgbe_set_multi: begin"); + IOCTL_DEBUGOUT("ixgbe_set_rxfilter: begin"); mta = adapter->mta; bzero(mta, sizeof(*mta) * MAX_NUM_MULTICAST_ADDRESSES); @@ -4422,30 +4379,32 @@ ixgbe_set_multi(struct adapter *adapter) } fctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_FCTRL); - fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); if (ifp->if_flags & IFF_PROMISC) fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); else if (ec->ec_flags & ETHER_F_ALLMULTI) { fctrl |= IXGBE_FCTRL_MPE; - } - ETHER_UNLOCK(ec); + fctrl &= ~IXGBE_FCTRL_UPE; + } else + fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, fctrl); - if (mcnt < MAX_NUM_MULTICAST_ADDRESSES) { + /* Update multicast filter entries only when it's not ALLMULTI */ + if ((ec->ec_flags & ETHER_F_ALLMULTI) == 0) { + ETHER_UNLOCK(ec); update_ptr = (u8 *)mta; ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt, ixgbe_mc_array_itr, TRUE); - } - -} /* ixgbe_set_multi */ + } else + ETHER_UNLOCK(ec); +} /* ixgbe_set_rxfilter */ /************************************************************************ * ixgbe_mc_array_itr * * An iterator function needed by the multicast shared code. * It feeds the shared code routine the addresses in the - * array of ixgbe_set_multi() one by one. + * array of ixgbe_set_rxfilter() one by one. ************************************************************************/ static u8 * ixgbe_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) @@ -6203,7 +6162,8 @@ ixgbe_ifflags_cb(struct ethercom *ec) { struct ifnet *ifp = &ec->ec_if; struct adapter *adapter = ifp->if_softc; - int change, rv = 0; + u_short change; + int rv = 0; IXGBE_CORE_LOCK(adapter); @@ -6215,7 +6175,7 @@ ixgbe_ifflags_cb(struct ethercom *ec) rv = ENETRESET; goto out; } else if ((change & IFF_PROMISC) != 0) - ixgbe_set_promisc(adapter); + ixgbe_set_rxfilter(adapter); /* Check for ec_capenable. */ change = ec->ec_capenable ^ adapter->ec_capenable; @@ -6373,7 +6333,7 @@ ixgbe_ioctl(struct ifnet * ifp, u_long c */ IXGBE_CORE_LOCK(adapter); ixgbe_disable_intr(adapter); - ixgbe_set_multi(adapter); + ixgbe_set_rxfilter(adapter); ixgbe_enable_intr(adapter); IXGBE_CORE_UNLOCK(adapter); } Index: src/sys/dev/pci/ixgbe/ixgbe.h diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.56 src/sys/dev/pci/ixgbe/ixgbe.h:1.56.2.1 --- src/sys/dev/pci/ixgbe/ixgbe.h:1.56 Wed Jul 17 03:26:24 2019 +++ src/sys/dev/pci/ixgbe/ixgbe.h Thu Sep 26 19:07:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.h,v 1.56 2019/07/17 03:26:24 msaitoh Exp $ */ +/* $NetBSD: ixgbe.h,v 1.56.2.1 2019/09/26 19:07:22 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -436,8 +436,6 @@ struct rx_ring { u64 flm; }; -#define IXGBE_MAX_VF_MC 30 /* Max number of multicast entries */ - struct ixgbe_vf { u_int pool; u_int rar_index; @@ -475,7 +473,7 @@ struct adapter { struct ifmedia media; callout_t timer; - int if_flags; /* saved ifp->if_flags */ + u_short if_flags; /* saved ifp->if_flags */ int ec_capenable; /* saved ec->ec_capenable */ kmutex_t core_mtx; Index: src/sys/dev/pci/ixgbe/ixgbe_type.h diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41.2.1 --- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.41 Wed Jul 24 06:07:58 2019 +++ src/sys/dev/pci/ixgbe/ixgbe_type.h Thu Sep 26 19:07:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_type.h,v 1.41 2019/07/24 06:07:58 msaitoh Exp $ */ +/* $NetBSD: ixgbe_type.h,v 1.41.2.1 2019/09/26 19:07:22 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -4311,6 +4311,9 @@ struct ixgbe_hw { #define IXGBE_ERR_FW_RESP_INVALID -39 #define IXGBE_ERR_TOKEN_RETRY -40 +#define IXGBE_ERR_NOT_TRUSTED -50 /* XXX NetBSD */ +#define IXGBE_ERR_NOT_IN_PROMISC -51 /* XXX NetBSD */ + #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF Index: src/sys/dev/pci/ixgbe/ixgbe_vf.c diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.18 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.18.2.1 --- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.18 Tue Jul 2 04:09:03 2019 +++ src/sys/dev/pci/ixgbe/ixgbe_vf.c Thu Sep 26 19:07:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_vf.c,v 1.18 2019/07/02 04:09:03 msaitoh Exp $ */ +/* $NetBSD: ixgbe_vf.c,v 1.18.2.1 2019/09/26 19:07:22 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -409,7 +409,13 @@ s32 ixgbe_update_mc_addr_list_vf(struct DEBUGOUT1("MC Addr Count = %d\n", mc_addr_count); - cnt = (mc_addr_count > 30) ? 30 : mc_addr_count; + if (mc_addr_count > IXGBE_MAX_VF_MC) { + device_printf(ixgbe_dev_from_hw(hw), + "number of Ethernet multicast addresses exceeded " + "the limit (%u > %d)\n", mc_addr_count, IXGBE_MAX_VF_MC); + cnt = IXGBE_MAX_VF_MC; + } else + cnt = mc_addr_count; msgbuf[0] = IXGBE_VF_SET_MULTICAST; msgbuf[0] |= cnt << IXGBE_VT_MSGINFO_SHIFT; @@ -454,8 +460,32 @@ s32 ixgbevf_update_xcast_mode(struct ixg return err; msgbuf[0] &= ~IXGBE_VT_MSGTYPE_CTS; - if (msgbuf[0] == (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK)) - return IXGBE_ERR_FEATURE_NOT_SUPPORTED; + if (msgbuf[0] == + (IXGBE_VF_UPDATE_XCAST_MODE | IXGBE_VT_MSGTYPE_NACK)) { + if (xcast_mode == IXGBEVF_XCAST_MODE_PROMISC) { + /* + * If the API version matched and the reply was NACK, + * assume the PF was not in PROMISC mode. + */ + return IXGBE_ERR_NOT_IN_PROMISC; + } else + return IXGBE_ERR_FEATURE_NOT_SUPPORTED; + } + /* + * On linux's PF driver implementation, the PF replies VF's + * XCAST_MODE_ALLMULTI message not with NACK but with ACK even if the + * virtual function is NOT marked "trust" and act as + * XCAST_MODE_"MULTI". If ixv(4) simply check the return vaule of + * update_xcast_mode(XCAST_MODE_ALLMULTI), SIOCSADDMULTI success and + * the user may have trouble with some addresses. Fortunately, the + * Linux's PF driver's "ACK" message has not XCAST_MODE_"ALL"MULTI but + * XCAST_MODE_MULTI, so we can check this state by checking if the + * send message's argument and the reply message's argument are + * different. + */ + if ((xcast_mode > IXGBEVF_XCAST_MODE_MULTI) + && (xcast_mode != msgbuf[1])) + return IXGBE_ERR_NOT_TRUSTED; return IXGBE_SUCCESS; } Index: src/sys/dev/pci/ixgbe/ixgbe_vf.h diff -u src/sys/dev/pci/ixgbe/ixgbe_vf.h:1.13 src/sys/dev/pci/ixgbe/ixgbe_vf.h:1.13.8.1 --- src/sys/dev/pci/ixgbe/ixgbe_vf.h:1.13 Wed Apr 4 08:13:07 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_vf.h Thu Sep 26 19:07:22 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_vf.h,v 1.13 2018/04/04 08:13:07 msaitoh Exp $ */ +/* $NetBSD: ixgbe_vf.h,v 1.13.8.1 2019/09/26 19:07:22 martin Exp $ */ /****************************************************************************** SPDX-License-Identifier: BSD-3-Clause @@ -42,6 +42,8 @@ #define IXGBE_VF_MAX_TX_QUEUES 8 #define IXGBE_VF_MAX_RX_QUEUES 8 +#define IXGBE_MAX_VF_MC 30 /* Max number of multicast entries */ + /* DCB define */ #define IXGBE_VF_MAX_TRAFFIC_CLASS 8 Index: src/sys/dev/pci/ixgbe/ixgbe_x550.c diff -u src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15 src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15.2.1 --- src/sys/dev/pci/ixgbe/ixgbe_x550.c:1.15 Thu Jun 27 06:00:11 2019 +++ src/sys/dev/pci/ixgbe/ixgbe_x550.c Thu Sep 26 19:07:22 2019 @@ -875,7 +875,7 @@ static s32 ixgbe_setup_fw_link(struct ix * Broken firmware sets BMCR register incorrectly if * FW_PHY_ACT_SETUP_LINK_AN isn't set. * a) FDX may not be set. - * b) BMCR_SPEED1 (bit 6) is always cleard. + * b) BMCR_SPEED1 (bit 6) is always cleared. * + -------+------+-----------+-----+--------------------------+ * |request | BMCR | BMCR spd | BMCR | | * | | (HEX)| (in bits)| FDX | | Index: src/sys/dev/pci/ixgbe/ixv.c diff -u src/sys/dev/pci/ixgbe/ixv.c:1.125.2.3 src/sys/dev/pci/ixgbe/ixv.c:1.125.2.4 --- src/sys/dev/pci/ixgbe/ixv.c:1.125.2.3 Thu Sep 5 09:11:03 2019 +++ src/sys/dev/pci/ixgbe/ixv.c Thu Sep 26 19:07:22 2019 @@ -1,4 +1,4 @@ -/*$NetBSD: ixv.c,v 1.125.2.3 2019/09/05 09:11:03 martin Exp $*/ +/*$NetBSD: ixv.c,v 1.125.2.4 2019/09/26 19:07:22 martin Exp $*/ /****************************************************************************** @@ -112,7 +112,7 @@ static s32 ixv_check_link(struct adapter static void ixv_enable_intr(struct adapter *); static void ixv_disable_intr(struct adapter *); -static void ixv_set_multi(struct adapter *); +static int ixv_set_rxfilter(struct adapter *); static void ixv_update_link_status(struct adapter *); static int ixv_sysctl_debug(SYSCTLFN_PROTO); static void ixv_set_ivar(struct adapter *, u8, u8, s8); @@ -131,6 +131,7 @@ static void ixv_save_stats(struct adapte static void ixv_init_stats(struct adapter *); static void ixv_update_stats(struct adapter *); static void ixv_add_stats_sysctls(struct adapter *); +static void ixv_clear_evcnt(struct adapter *); /* Sysctl handlers */ static void ixv_set_sysctl_value(struct adapter *, const char *, @@ -741,7 +742,7 @@ ixv_init_locked(struct adapter *adapter) ixv_initialize_transmit_units(adapter); /* Setup Multicast table */ - ixv_set_multi(adapter); + ixv_set_rxfilter(adapter); /* * Determine the correct mbuf pool @@ -1073,7 +1074,6 @@ ixv_media_change(struct ifnet *ifp) return (0); } /* ixv_media_change */ - /************************************************************************ * ixv_negotiate_api * @@ -1084,7 +1084,9 @@ static int ixv_negotiate_api(struct adapter *adapter) { struct ixgbe_hw *hw = &adapter->hw; - int mbx_api[] = { ixgbe_mbox_api_11, + int mbx_api[] = { ixgbe_mbox_api_13, + ixgbe_mbox_api_12, + ixgbe_mbox_api_11, ixgbe_mbox_api_10, ixgbe_mbox_api_unknown }; int i = 0; @@ -1104,45 +1106,128 @@ ixv_negotiate_api(struct adapter *adapte * * Called whenever multicast address list is updated. ************************************************************************/ -static void -ixv_set_multi(struct adapter *adapter) +static int +ixv_set_rxfilter(struct adapter *adapter) { - struct ether_multi *enm; - struct ether_multistep step; - struct ethercom *ec = &adapter->osdep.ec; - u8 mta[MAX_NUM_MULTICAST_ADDRESSES * IXGBE_ETH_LENGTH_OF_ADDRESS]; - u8 *update_ptr; - int mcnt = 0; + u8 mta[IXGBE_MAX_VF_MC * IXGBE_ETH_LENGTH_OF_ADDRESS]; + struct ifnet *ifp = adapter->ifp; + struct ixgbe_hw *hw = &adapter->hw; + u8 *update_ptr; + int mcnt = 0; + struct ethercom *ec = &adapter->osdep.ec; + struct ether_multi *enm; + struct ether_multistep step; + bool overflow = false; + int error, rc = 0; KASSERT(mutex_owned(&adapter->core_mtx)); - IOCTL_DEBUGOUT("ixv_set_multi: begin"); + IOCTL_DEBUGOUT("ixv_set_rxfilter: begin"); + /* 1: For PROMISC */ + if (ifp->if_flags & IFF_PROMISC) { + error = hw->mac.ops.update_xcast_mode(hw, + IXGBEVF_XCAST_MODE_PROMISC); + if (error == IXGBE_ERR_NOT_TRUSTED) { + device_printf(adapter->dev, + "this interface is not trusted\n"); + error = EPERM; + } else if (error == IXGBE_ERR_FEATURE_NOT_SUPPORTED) { + device_printf(adapter->dev, + "the PF doesn't support promisc mode\n"); + error = EOPNOTSUPP; + } else if (error == IXGBE_ERR_NOT_IN_PROMISC) { + device_printf(adapter->dev, + "the PF may not in promisc mode\n"); + error = EINVAL; + } else if (error) { + device_printf(adapter->dev, + "failed to set promisc mode. error = %d\n", + error); + error = EIO; + } else + return 0; + rc = error; + } + + /* 2: For ALLMULTI or normal */ ETHER_LOCK(ec); ETHER_FIRST_MULTI(step, ec, enm); while (enm != NULL) { + if ((mcnt >= IXGBE_MAX_VF_MC) || + (memcmp(enm->enm_addrlo, enm->enm_addrhi, + ETHER_ADDR_LEN) != 0)) { + overflow = true; + break; + } bcopy(enm->enm_addrlo, &mta[mcnt * IXGBE_ETH_LENGTH_OF_ADDRESS], IXGBE_ETH_LENGTH_OF_ADDRESS); mcnt++; - /* XXX This might be required --msaitoh */ - if (mcnt >= MAX_NUM_MULTICAST_ADDRESSES) - break; ETHER_NEXT_MULTI(step, enm); } ETHER_UNLOCK(ec); + /* 3: For ALLMULTI */ + if (overflow) { + error = hw->mac.ops.update_xcast_mode(hw, + IXGBEVF_XCAST_MODE_ALLMULTI); + if (error == IXGBE_ERR_NOT_TRUSTED) { + device_printf(adapter->dev, + "this interface is not trusted\n"); + error = EPERM; + } else if (error == IXGBE_ERR_FEATURE_NOT_SUPPORTED) { + device_printf(adapter->dev, + "the PF doesn't support allmulti mode\n"); + error = EOPNOTSUPP; + } else if (error) { + device_printf(adapter->dev, + "number of Ethernet multicast addresses " + "exceeds the limit (%d). error = %d\n", + IXGBE_MAX_VF_MC, error); + error = ENOSPC; + } else { + ETHER_LOCK(ec); + ec->ec_flags |= ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); + return rc; /* Promisc might failed */ + } + + if (rc == 0) + rc = error; + + /* Continue to update the multicast table as many as we can */ + } + + /* 4: For normal operation */ + error = hw->mac.ops.update_xcast_mode(hw, IXGBEVF_XCAST_MODE_MULTI); + if ((error == IXGBE_ERR_FEATURE_NOT_SUPPORTED) || (error == 0)) { + /* Normal operation */ + ETHER_LOCK(ec); + ec->ec_flags &= ~ETHER_F_ALLMULTI; + ETHER_UNLOCK(ec); + error = 0; + } else if (error) { + device_printf(adapter->dev, + "failed to set Ethernet multicast address " + "operation to normal. error = %d\n", error); + } + update_ptr = mta; - adapter->hw.mac.ops.update_mc_addr_list(&adapter->hw, update_ptr, mcnt, - ixv_mc_array_itr, TRUE); -} /* ixv_set_multi */ + error = adapter->hw.mac.ops.update_mc_addr_list(&adapter->hw, + update_ptr, mcnt, ixv_mc_array_itr, TRUE); + if (rc == 0) + rc = error; + + return rc; +} /* ixv_set_rxfilter */ /************************************************************************ * ixv_mc_array_itr * * An iterator function needed by the multicast shared code. * It feeds the shared code routine the addresses in the - * array of ixv_set_multi() one by one. + * array of ixv_set_rxfilter() one by one. ************************************************************************/ static u8 * ixv_mc_array_itr(struct ixgbe_hw *hw, u8 **update_ptr, u32 *vmdq) @@ -2630,6 +2715,76 @@ ixv_add_stats_sysctls(struct adapter *ad } /* ixv_add_stats_sysctls */ +static void +ixv_clear_evcnt(struct adapter *adapter) +{ + struct tx_ring *txr = adapter->tx_rings; + struct rx_ring *rxr = adapter->rx_rings; + struct ixgbevf_hw_stats *stats = &adapter->stats.vf; + struct ixgbe_hw *hw = &adapter->hw; + int i; + + /* Driver Statistics */ + adapter->efbig_tx_dma_setup.ev_count = 0; + adapter->mbuf_defrag_failed.ev_count = 0; + adapter->efbig2_tx_dma_setup.ev_count = 0; + adapter->einval_tx_dma_setup.ev_count = 0; + adapter->other_tx_dma_setup.ev_count = 0; + adapter->eagain_tx_dma_setup.ev_count = 0; + adapter->enomem_tx_dma_setup.ev_count = 0; + adapter->watchdog_events.ev_count = 0; + adapter->tso_err.ev_count = 0; + adapter->link_irq.ev_count = 0; + + for (i = 0; i < adapter->num_queues; i++, rxr++, txr++) { + adapter->queues[i].irqs.ev_count = 0; + adapter->queues[i].handleq.ev_count = 0; + adapter->queues[i].req.ev_count = 0; + txr->tso_tx.ev_count = 0; + txr->no_desc_avail.ev_count = 0; + txr->total_packets.ev_count = 0; +#ifndef IXGBE_LEGACY_TX + txr->pcq_drops.ev_count = 0; +#endif + txr->q_efbig_tx_dma_setup = 0; + txr->q_mbuf_defrag_failed = 0; + txr->q_efbig2_tx_dma_setup = 0; + txr->q_einval_tx_dma_setup = 0; + txr->q_other_tx_dma_setup = 0; + txr->q_eagain_tx_dma_setup = 0; + txr->q_enomem_tx_dma_setup = 0; + txr->q_tso_err = 0; + + rxr->rx_packets.ev_count = 0; + rxr->rx_bytes.ev_count = 0; + rxr->rx_copies.ev_count = 0; + rxr->no_jmbuf.ev_count = 0; + rxr->rx_discarded.ev_count = 0; + } + + /* MAC stats get their own sub node */ + + stats->ipcs.ev_count = 0; + stats->l4cs.ev_count = 0; + stats->ipcs_bad.ev_count = 0; + stats->l4cs_bad.ev_count = 0; + + /* Packet Reception Stats */ + stats->vfgprc.ev_count = 0; + stats->vfgorc.ev_count = 0; + stats->vfmprc.ev_count = 0; + stats->vfgptc.ev_count = 0; + stats->vfgotc.ev_count = 0; + + /* Mailbox Stats */ + hw->mbx.stats.msgs_tx.ev_count = 0; + hw->mbx.stats.msgs_rx.ev_count = 0; + hw->mbx.stats.acks.ev_count = 0; + hw->mbx.stats.reqs.ev_count = 0; + hw->mbx.stats.rsts.ev_count = 0; + +} /* ixv_clear_evcnt */ + /************************************************************************ * ixv_set_sysctl_value ************************************************************************/ @@ -2790,10 +2945,13 @@ ixv_ifflags_cb(struct ethercom *ec) { struct ifnet *ifp = &ec->ec_if; struct adapter *adapter = ifp->if_softc; - int change, rv = 0; + u_short saved_flags; + u_short change; + int rv = 0; IXGBE_CORE_LOCK(adapter); + saved_flags = adapter->if_flags; change = ifp->if_flags ^ adapter->if_flags; if (change != 0) adapter->if_flags = ifp->if_flags; @@ -2801,6 +2959,13 @@ ixv_ifflags_cb(struct ethercom *ec) if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) { rv = ENETRESET; goto out; + } else if ((change & IFF_PROMISC) != 0) { + rv = ixv_set_rxfilter(adapter); + if (rv != 0) { + /* Restore previous */ + adapter->if_flags = saved_flags; + goto out; + } } /* Check for ec_capenable. */ @@ -2839,8 +3004,9 @@ static int ixv_ioctl(struct ifnet *ifp, u_long command, void *data) { struct adapter *adapter = ifp->if_softc; + struct ixgbe_hw *hw = &adapter->hw; struct ifcapreq *ifcr = data; - int error = 0; + int error; int l4csum_en; const int l4csum = IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx | IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx; @@ -2849,7 +3015,59 @@ ixv_ioctl(struct ifnet *ifp, u_long comm case SIOCSIFFLAGS: IOCTL_DEBUGOUT("ioctl: SIOCSIFFLAGS (Set Interface Flags)"); break; - case SIOCADDMULTI: + case SIOCADDMULTI: { + struct ether_multi *enm; + struct ether_multistep step; + struct ethercom *ec = &adapter->osdep.ec; + bool overflow = false; + int mcnt = 0; + + /* + * Check the number of multicast address. If it exceeds, + * return ENOSPC. + * Update this code when we support API 1.3. + */ + ETHER_LOCK(ec); + ETHER_FIRST_MULTI(step, ec, enm); + while (enm != NULL) { + mcnt++; + + /* + * This code is before adding, so one room is required + * at least. + */ + if (mcnt > (IXGBE_MAX_VF_MC - 1)) { + overflow = true; + break; + } + ETHER_NEXT_MULTI(step, enm); + } + ETHER_UNLOCK(ec); + error = 0; + if (overflow && ((ec->ec_flags & ETHER_F_ALLMULTI) == 0)) { + error = hw->mac.ops.update_xcast_mode(hw, + IXGBEVF_XCAST_MODE_ALLMULTI); + if (error == IXGBE_ERR_NOT_TRUSTED) { + device_printf(adapter->dev, + "this interface is not trusted\n"); + error = EPERM; + } else if (error == IXGBE_ERR_FEATURE_NOT_SUPPORTED) { + device_printf(adapter->dev, + "the PF doesn't support allmulti mode\n"); + error = EOPNOTSUPP; + } else if (error) { + device_printf(adapter->dev, + "number of Ethernet multicast addresses " + "exceeds the limit (%d). error = %d\n", + IXGBE_MAX_VF_MC, error); + error = ENOSPC; + } else + ec->ec_flags |= ETHER_F_ALLMULTI; + } + if (error) + return error; + } + /*FALLTHROUGH*/ case SIOCDELMULTI: IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI"); break; @@ -2863,6 +3081,11 @@ ixv_ioctl(struct ifnet *ifp, u_long comm case SIOCSIFMTU: IOCTL_DEBUGOUT("ioctl: SIOCSIFMTU (Set Interface MTU)"); break; + case SIOCZIFDATA: + IOCTL_DEBUGOUT("ioctl: SIOCZIFDATA (Zero counter)"); + ixv_update_stats(adapter); + ixv_clear_evcnt(adapter); + break; default: IOCTL_DEBUGOUT1("ioctl: UNKNOWN (0x%X)", (int)command); break; @@ -2897,7 +3120,7 @@ ixv_ioctl(struct ifnet *ifp, u_long comm */ IXGBE_CORE_LOCK(adapter); ixv_disable_intr(adapter); - ixv_set_multi(adapter); + ixv_set_rxfilter(adapter); ixv_enable_intr(adapter); IXGBE_CORE_UNLOCK(adapter); }