svn commit: r205544 - stable/8/sys/dev/bce

Pyun YongHyeon yongari at FreeBSD.org
Tue Mar 23 22:04:18 UTC 2010


Author: yongari
Date: Tue Mar 23 22:04:18 2010
New Revision: 205544
URL: http://svn.freebsd.org/changeset/base/205544

Log:
  MFC r204368,204370-204372:
  r204368:
    Allow disabling VLAN hardware tag stripping with software work
    around. Management firmware(ASF/IPMI/UMP) requires the VLAN
    hardware tag stripping so don't actually disable VLAN hardware tag
    stripping. If VLAN hardware tag stripping was disabled, bce(4)
    manually reconstruct VLAN frame by appending stripped VLAN tag.
    Also remove unnecessary IFCAP_VLAN_MTU message.
  
  r204370:
    Make sure to stop controller first before changing MTU. And if
    interface is not running don't initialize controller.
    While here remove unnecessary update of error variable.
  
  r204371:
    Make toggling TSO, VLAN hardware checksum offloading work. Also fix
    TX/RX checksum handler to set/clear relavant assist bits which was
    used to cause unexpected results.
    With this change, bce(4) can be bridged with other interfaces that
    lack TSO, VLAN checksum offloading.
  
  r204372:
    Prefer m_collapse(9) over m_defrag(9).

Modified:
  stable/8/sys/dev/bce/if_bce.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)
  stable/8/sys/net/   (props changed)

Modified: stable/8/sys/dev/bce/if_bce.c
==============================================================================
--- stable/8/sys/dev/bce/if_bce.c	Tue Mar 23 21:56:07 2010	(r205543)
+++ stable/8/sys/dev/bce/if_bce.c	Tue Mar 23 22:04:18 2010	(r205544)
@@ -5886,6 +5886,7 @@ bce_rx_intr(struct bce_softc *sc)
 {
 	struct ifnet *ifp = sc->bce_ifp;
 	struct l2_fhdr *l2fhdr;
+	struct ether_vlan_header *vh;
 	unsigned int pkt_len;
 	u16 sw_rx_cons, sw_rx_cons_idx, hw_rx_cons;
 	u32 status;
@@ -6141,12 +6142,37 @@ bce_rx_intr(struct bce_softc *sc)
 
 		/* Attach the VLAN tag.	*/
 		if (status & L2_FHDR_STATUS_L2_VLAN_TAG) {
+			if (ifp->if_capenable & IFCAP_VLAN_HWTAGGING) {
 #if __FreeBSD_version < 700000
-			VLAN_INPUT_TAG(ifp, m0, l2fhdr->l2_fhdr_vlan_tag, continue);
+				VLAN_INPUT_TAG(ifp, m0,
+				    l2fhdr->l2_fhdr_vlan_tag, continue);
 #else
-			m0->m_pkthdr.ether_vtag = l2fhdr->l2_fhdr_vlan_tag;
-			m0->m_flags |= M_VLANTAG;
+				m0->m_pkthdr.ether_vtag =
+				    l2fhdr->l2_fhdr_vlan_tag;
+				m0->m_flags |= M_VLANTAG;
 #endif
+			} else {
+				/*
+				 * bce(4) controllers can't disable VLAN
+				 * tag stripping if management firmware
+				 * (ASF/IPMI/UMP) is running. So we always
+				 * strip VLAN tag and manually reconstruct
+				 * the VLAN frame by appending stripped
+				 * VLAN tag in driver if VLAN tag stripping
+				 * was disabled.
+				 *
+				 * TODO: LLC SNAP handling.
+				 */
+				bcopy(mtod(m0, uint8_t *),
+				    mtod(m0, uint8_t *) - ETHER_VLAN_ENCAP_LEN,
+				    ETHER_ADDR_LEN * 2);
+				m0->m_data -= ETHER_VLAN_ENCAP_LEN;
+				vh = mtod(m0, struct ether_vlan_header *);
+				vh->evl_encap_proto = htons(ETHERTYPE_VLAN);
+				vh->evl_tag = htons(l2fhdr->l2_fhdr_vlan_tag);
+				m0->m_pkthdr.len += ETHER_VLAN_ENCAP_LEN;
+				m0->m_len += ETHER_VLAN_ENCAP_LEN;
+			}
 		}
 
 		/* Increment received packet statistics. */
@@ -6687,7 +6713,7 @@ bce_tx_encap_skip_tso:
 		sc->fragmented_mbuf_count++;
 
 		/* Try to defrag the mbuf. */
-		m0 = m_defrag(*m_head, M_DONTWAIT);
+		m0 = m_collapse(*m_head, M_DONTWAIT, BCE_MAX_SEGMENTS);
 		if (m0 == NULL) {
 			/* Defrag was unsuccessful */
 			m_freem(*m_head);
@@ -6963,7 +6989,7 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 	struct bce_softc *sc = ifp->if_softc;
 	struct ifreq *ifr = (struct ifreq *) data;
 	struct mii_data *mii;
-	int mask, error = 0;
+	int mask, error = 0, reinit;
 
 	DBENTER(BCE_VERBOSE_MISC);
 
@@ -6984,7 +7010,16 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 
 			BCE_LOCK(sc);
 			ifp->if_mtu = ifr->ifr_mtu;
-			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+			reinit = 0;
+			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+				/*
+				 * Because allocation size is used in RX
+				 * buffer allocation, stop controller if
+				 * it is already running.
+				 */
+				bce_stop(sc);
+				reinit = 1;
+			}
 #ifdef BCE_JUMBO_HDRSPLIT
 			/* No buffer allocation size changes are necessary. */
 #else
@@ -7002,7 +7037,8 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 			}
 #endif
 
-			bce_init_locked(sc);
+			if (reinit != 0)
+				bce_init_locked(sc);
 			BCE_UNLOCK(sc);
 			break;
 
@@ -7036,7 +7072,6 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 			}
 
 			BCE_UNLOCK(sc);
-			error = 0;
 
 			break;
 
@@ -7046,10 +7081,8 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 			DBPRINT(sc, BCE_VERBOSE_MISC, "Received SIOCADDMULTI/SIOCDELMULTI\n");
 
 			BCE_LOCK(sc);
-			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
 				bce_set_rx_mode(sc);
-				error = 0;
-			}
 			BCE_UNLOCK(sc);
 
 			break;
@@ -7069,50 +7102,46 @@ bce_ioctl(struct ifnet *ifp, u_long comm
 			mask = ifr->ifr_reqcap ^ ifp->if_capenable;
 			DBPRINT(sc, BCE_INFO_MISC, "Received SIOCSIFCAP = 0x%08X\n", (u32) mask);
 
-			/* Toggle the TX checksum capabilites enable flag. */
-			if (mask & IFCAP_TXCSUM) {
+			/* Toggle the TX checksum capabilities enable flag. */
+			if (mask & IFCAP_TXCSUM &&
+			    ifp->if_capabilities & IFCAP_TXCSUM) {
 				ifp->if_capenable ^= IFCAP_TXCSUM;
 				if (IFCAP_TXCSUM & ifp->if_capenable)
-					ifp->if_hwassist = BCE_IF_HWASSIST;
+					ifp->if_hwassist |= BCE_IF_HWASSIST;
 				else
-					ifp->if_hwassist = 0;
+					ifp->if_hwassist &= ~BCE_IF_HWASSIST;
 			}
 
 			/* Toggle the RX checksum capabilities enable flag. */
-			if (mask & IFCAP_RXCSUM) {
+			if (mask & IFCAP_RXCSUM &&
+			    ifp->if_capabilities & IFCAP_RXCSUM)
 				ifp->if_capenable ^= IFCAP_RXCSUM;
-				if (IFCAP_RXCSUM & ifp->if_capenable)
-					ifp->if_hwassist = BCE_IF_HWASSIST;
-				else
-					ifp->if_hwassist = 0;
-			}
 
 			/* Toggle the TSO capabilities enable flag. */
-			if (bce_tso_enable && (mask & IFCAP_TSO4)) {
+			if (bce_tso_enable && (mask & IFCAP_TSO4) &&
+			    ifp->if_capabilities & IFCAP_TSO4) {
 				ifp->if_capenable ^= IFCAP_TSO4;
-				if (IFCAP_RXCSUM & ifp->if_capenable)
-					ifp->if_hwassist = BCE_IF_HWASSIST;
+				if (IFCAP_TSO4 & ifp->if_capenable)
+					ifp->if_hwassist |= CSUM_TSO;
 				else
-					ifp->if_hwassist = 0;
+					ifp->if_hwassist &= ~CSUM_TSO;
 			}
 
-			/* Toggle VLAN_MTU capabilities enable flag. */
-			if (mask & IFCAP_VLAN_MTU) {
-				BCE_PRINTF("%s(%d): Changing VLAN_MTU not supported.\n",
-					__FILE__, __LINE__);
-			}
-
-			/* Toggle VLANHWTAG capabilities enabled flag. */
-			if (mask & IFCAP_VLAN_HWTAGGING) {
-				if (sc->bce_flags & BCE_MFW_ENABLE_FLAG)
-					BCE_PRINTF("%s(%d): Cannot change VLAN_HWTAGGING while "
-						"management firmware (ASF/IPMI/UMP) is running!\n",
-						__FILE__, __LINE__);
-				else
-					BCE_PRINTF("%s(%d): Changing VLAN_HWTAGGING not supported!\n",
-						__FILE__, __LINE__);
-			}
+			if (mask & IFCAP_VLAN_HWCSUM &&
+			    ifp->if_capabilities & IFCAP_VLAN_HWCSUM)
+				ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
 
+			/*
+			 * Don't actually disable VLAN tag stripping as
+			 * management firmware (ASF/IPMI/UMP) requires the
+			 * feature. If VLAN tag stripping is disabled driver
+			 * will manually reconstruct the VLAN frame by
+			 * appending stripped VLAN tag.
+			 */
+			if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
+			    (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING))
+				ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
+			VLAN_CAPABILITIES(ifp);
 			break;
 		default:
 			/* We don't know how to handle the IOCTL, pass it on. */


More information about the svn-src-stable-8 mailing list