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);
 		}

Reply via email to