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 [email protected] .
.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);
}