Module Name: src Committed By: martin Date: Thu Sep 26 18:19:27 UTC 2019
Modified Files: src/share/man/man4 [netbsd-8]: ixv.4 src/sys/dev/pci/ixgbe [netbsd-8]: ixgbe.c ixgbe.h ixgbe_type.h ixgbe_vf.c ixgbe_vf.h ixv.c Log Message: Pull up the following revisions, requested by msaitoh in ticket #1389: sys/dev/pci/ixgbe/ixgbe_type.h 1.42-1.43 sys/dev/pci/ixgbe/ixgbe.c 1.209-1.213 via patch sys/dev/pci/ixgbe/ixv.c 1.131-1.138 via patch 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 via patch share/man/man4/ixv.4 1.5 via patch - 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. - 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. To generate a diff of this commit: cvs rdiff -u -r1.3.2.2 -r1.3.2.3 src/share/man/man4/ixv.4 cvs rdiff -u -r1.88.2.34 -r1.88.2.35 src/sys/dev/pci/ixgbe/ixgbe.c cvs rdiff -u -r1.24.6.17 -r1.24.6.18 src/sys/dev/pci/ixgbe/ixgbe.h cvs rdiff -u -r1.22.2.10 -r1.22.2.11 src/sys/dev/pci/ixgbe/ixgbe_type.h cvs rdiff -u -r1.12.8.3 -r1.12.8.4 src/sys/dev/pci/ixgbe/ixgbe_vf.c cvs rdiff -u -r1.8.6.3 -r1.8.6.4 src/sys/dev/pci/ixgbe/ixgbe_vf.h cvs rdiff -u -r1.56.2.24 -r1.56.2.25 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.3.2.2 src/share/man/man4/ixv.4:1.3.2.3 --- src/share/man/man4/ixv.4:1.3.2.2 Sat May 12 10:35:45 2018 +++ src/share/man/man4/ixv.4 Thu Sep 26 18:19:27 2019 @@ -1,4 +1,4 @@ -.\" $NetBSD: ixv.4,v 1.3.2.2 2018/05/12 10:35:45 martin Exp $ +.\" $NetBSD: ixv.4,v 1.3.2.3 2019/09/26 18:19:27 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 May 9, 2018 +.Dd September 5, 2019 .Dt IXV 4 .Os .Sh NAME @@ -60,6 +60,23 @@ The 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 +.Sh BUGS VLAN over .Nm won't work because VLAN hardware filter function is not currently implemented Index: src/sys/dev/pci/ixgbe/ixgbe.c diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.34 src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.35 --- src/sys/dev/pci/ixgbe/ixgbe.c:1.88.2.34 Fri Sep 6 13:44:36 2019 +++ src/sys/dev/pci/ixgbe/ixgbe.c Thu Sep 26 18:19:26 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.c,v 1.88.2.34 2019/09/06 13:44:36 martin Exp $ */ +/* $NetBSD: ixgbe.c,v 1.88.2.35 2019/09/26 18:19:26 martin Exp $ */ /****************************************************************************** @@ -209,8 +209,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 *); @@ -1579,7 +1578,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 */ @@ -2134,7 +2133,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; @@ -3003,49 +3003,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); - if (ifp->if_flags & IFF_ALLMULTI) - mcnt = MAX_NUM_MULTICAST_ADDRESSES; - else { - ETHER_LOCK(ec); - ETHER_FIRST_MULTI(step, ec, enm); - while (enm != NULL) { - if (mcnt == MAX_NUM_MULTICAST_ADDRESSES) - break; - mcnt++; - ETHER_NEXT_MULTI(step, enm); - } - ETHER_UNLOCK(ec); - } - 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 (ifp->if_flags & IFF_ALLMULTI) { - rctl |= IXGBE_FCTRL_MPE; - rctl &= ~IXGBE_FCTRL_UPE; - IXGBE_WRITE_REG(&adapter->hw, IXGBE_FCTRL, rctl); - } -} /* ixgbe_set_promisc */ - -/************************************************************************ * ixgbe_msix_link - Link status change ISR (MSI/MSI-X) ************************************************************************/ static int @@ -3955,7 +3912,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) @@ -4343,12 +4300,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; @@ -4360,7 +4317,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); @@ -4384,29 +4341,29 @@ ixgbe_set_multi(struct adapter *adapter) ETHER_UNLOCK(ec); 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 (ifp->if_flags & IFF_ALLMULTI) { fctrl |= IXGBE_FCTRL_MPE; - } + 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) { + if (mcnt <= MAX_NUM_MULTICAST_ADDRESSES) { update_ptr = (u8 *)mta; ixgbe_update_mc_addr_list(&adapter->hw, update_ptr, mcnt, ixgbe_mc_array_itr, TRUE); } - -} /* ixgbe_set_multi */ +} /* ixgbe_set_filter */ /************************************************************************ * 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) @@ -6164,7 +6121,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); @@ -6176,7 +6134,7 @@ ixgbe_ifflags_cb(struct ethercom *ec) rv = ENETRESET; goto out; } else if ((change & (IFF_PROMISC | IFF_ALLMULTI)) != 0) - ixgbe_set_promisc(adapter); + ixgbe_set_rxfilter(adapter); /* Set up VLAN support and filter */ ixgbe_setup_vlan_hw_support(adapter); @@ -6322,7 +6280,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.24.6.17 src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.18 --- src/sys/dev/pci/ixgbe/ixgbe.h:1.24.6.17 Mon Jul 22 17:53:35 2019 +++ src/sys/dev/pci/ixgbe/ixgbe.h Thu Sep 26 18:19:26 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe.h,v 1.24.6.17 2019/07/22 17:53:35 martin Exp $ */ +/* $NetBSD: ixgbe.h,v 1.24.6.18 2019/09/26 18:19:26 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; + u_short if_flags; /* saved ifp->if_flags */ kmutex_t core_mtx; Index: src/sys/dev/pci/ixgbe/ixgbe_type.h diff -u src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.10 src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.11 --- src/sys/dev/pci/ixgbe/ixgbe_type.h:1.22.2.10 Thu Aug 1 14:14:30 2019 +++ src/sys/dev/pci/ixgbe/ixgbe_type.h Thu Sep 26 18:19:26 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_type.h,v 1.22.2.10 2019/08/01 14:14:30 martin Exp $ */ +/* $NetBSD: ixgbe_type.h,v 1.22.2.11 2019/09/26 18:19:26 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.12.8.3 src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.4 --- src/sys/dev/pci/ixgbe/ixgbe_vf.c:1.12.8.3 Mon Jul 22 17:53:35 2019 +++ src/sys/dev/pci/ixgbe/ixgbe_vf.c Thu Sep 26 18:19:26 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_vf.c,v 1.12.8.3 2019/07/22 17:53:35 martin Exp $ */ +/* $NetBSD: ixgbe_vf.c,v 1.12.8.4 2019/09/26 18:19:26 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.8.6.3 src/sys/dev/pci/ixgbe/ixgbe_vf.h:1.8.6.4 --- src/sys/dev/pci/ixgbe/ixgbe_vf.h:1.8.6.3 Sat Apr 14 10:25:11 2018 +++ src/sys/dev/pci/ixgbe/ixgbe_vf.h Thu Sep 26 18:19:26 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: ixgbe_vf.h,v 1.8.6.3 2018/04/14 10:25:11 martin Exp $ */ +/* $NetBSD: ixgbe_vf.h,v 1.8.6.4 2019/09/26 18:19:26 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/ixv.c diff -u src/sys/dev/pci/ixgbe/ixv.c:1.56.2.24 src/sys/dev/pci/ixgbe/ixv.c:1.56.2.25 --- src/sys/dev/pci/ixgbe/ixv.c:1.56.2.24 Thu Sep 5 09:06:08 2019 +++ src/sys/dev/pci/ixgbe/ixv.c Thu Sep 26 18:19:26 2019 @@ -1,4 +1,4 @@ -/*$NetBSD: ixv.c,v 1.56.2.24 2019/09/05 09:06:08 martin Exp $*/ +/*$NetBSD: ixv.c,v 1.56.2.25 2019/09/26 18:19:26 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 *, @@ -761,7 +762,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 @@ -1090,7 +1091,6 @@ ixv_media_change(struct ifnet *ifp) return (0); } /* ixv_media_change */ - /************************************************************************ * ixv_negotiate_api * @@ -1101,7 +1101,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; @@ -1121,45 +1123,124 @@ 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 { + ifp->if_flags |= IFF_ALLMULTI; + 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 */ + ifp->if_flags &= ~IFF_ALLMULTI; + 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) @@ -2565,6 +2646,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 ************************************************************************/ @@ -2725,20 +2876,30 @@ ixv_ifflags_cb(struct ethercom *ec) { struct ifnet *ifp = &ec->ec_if; struct adapter *adapter = ifp->if_softc; - int change, rc = 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; if ((change & ~(IFF_CANTCHANGE | IFF_DEBUG)) != 0) - rc = ENETRESET; + rv = ENETRESET; + else if ((change & IFF_PROMISC) != 0) { + rv = ixv_set_rxfilter(adapter); + if (rv != 0) { + /* Restore previous */ + adapter->if_flags = saved_flags; + } + } IXGBE_CORE_UNLOCK(adapter); - return rc; + return rv; } @@ -2753,9 +2914,10 @@ 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; struct ifreq *ifr = 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; @@ -2764,7 +2926,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 && ((ifp->if_flags & IFF_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 + ifp->if_flags |= IFF_ALLMULTI; + } + if (error) + return error; + } + /*FALLTHROUGH*/ case SIOCDELMULTI: IOCTL_DEBUGOUT("ioctl: SIOC(ADD|DEL)MULTI"); break; @@ -2778,6 +2992,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; @@ -2815,7 +3034,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); }