Subject: Re: pcn interfac under vmware issue?
To: Peter Eisch <peter@boku.net>
From: Jason Thorpe <thorpej@shagadelic.org>
List: netbsd-users
Date: 10/31/2006 09:28:40
--Apple-Mail-1--675073169
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed;
	delsp=yes


On Oct 30, 2006, at 9:39 PM, Jason Thorpe wrote:

> In any case, it should be trivial to deal with this using a quirk in  
> the pcn driver -- we can look for the OUI for VMware in the MAC  
> address, and simply drop the number of Tx segments that bus_dma will  
> create for a packet to 15 (from 16).  I think it's pretty rare that  
> we bump up against the limit anyway (the driver can even gather  
> these statistics for you).

Please try the attached patch (against -current).  This should work in  
3.x, as well -- just remove the call to prop_dictionary_set_bool() in  
that case.

-- thorpej
--Apple-Mail-1--675073169
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	x-unix-mode=0644;
	name=pcn-vmware-patch.txt
Content-Disposition: attachment;
	filename=pcn-vmware-patch.txt

Index: if_pcn.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_pcn.c,v
retrieving revision 1.33
diff -u -p -r1.33 if_pcn.c
--- if_pcn.c	31 Oct 2006 14:04:29 -0000	1.33
+++ if_pcn.c	31 Oct 2006 17:23:43 -0000
@@ -125,6 +125,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_pcn.c,v 1
  * transmit logic can deal with this, we just are hoping to sneak by.
  */
 #define	PCN_NTXSEGS		16
+#define	PCN_NTXSEGS_VMWARE	15	/* bug in VMware's emulation */
 
 #define	PCN_TXQUEUELEN		128
 #define	PCN_TXQUEUELEN_MASK	(PCN_TXQUEUELEN - 1)
@@ -506,6 +507,27 @@ pcn_bcr_write(struct pcn_softc *sc, int 
 	bus_space_write_4(sc->sc_st, sc->sc_sh, PCN32_BDP, val);
 }
 
+static boolean_t
+pcn_is_vmware(const char *enaddr)
+{
+
+	/*
+	 * VMware uses the OUI 00:0c:29 for auto-generated MAC
+	 * addresses.
+	 */
+	if (enaddr[0] == 0x00 && enaddr[1] == 0x0c && enaddr[2] == 0x29)
+		return (TRUE);
+	
+	/*
+	 * VMware uses the OUI 00:50:56 for manually-set MAC
+	 * addresses.
+	 */
+	if (enaddr[0] == 0x00 && enaddr[1] == 0x50 && enaddr[3] == 0x56)
+		return (TRUE);
+
+	return (FALSE);
+}
+
 static const struct pcn_variant *
 pcn_lookup_variant(uint16_t chipid)
 {
@@ -565,10 +587,11 @@ pcn_attach(struct device *parent __unuse
 	bus_space_handle_t ioh, memh;
 	bus_dma_segment_t seg;
 	int ioh_valid, memh_valid;
-	int i, rseg, error;
+	int ntxsegs, i, rseg, error;
 	uint32_t chipid, reg;
 	uint8_t enaddr[ETHER_ADDR_LEN];
 	prop_object_t obj;
+	boolean_t is_vmware;
 
 	callout_init(&sc->sc_tick_ch);
 
@@ -638,6 +661,9 @@ pcn_attach(struct device *parent __unuse
 		}
 	}
 
+	/* Check to see if this is a VMware emulated network interface. */
+	is_vmware = pcn_is_vmware(enaddr);
+
 	/*
 	 * Now that the device is mapped, attempt to figure out what
 	 * kind of chip we have.  Note that IDL has all 32 bits of
@@ -651,6 +677,20 @@ pcn_attach(struct device *parent __unuse
 	    ether_sprintf(enaddr));
 
 	/*
+	 * VMware has a bug in its network interface emulation; we can't
+	 * have more than 15 Tx segments.
+	 */
+	if (is_vmware) {
+		ntxsegs = PCN_NTXSEGS_VMWARE;
+		prop_dictionary_set_bool(device_properties(&sc->sc_dev),
+					 "am79c970-vmware-tx-bug", TRUE);
+		aprint_verbose("%s: VMware Tx segment count bug detected\n",
+			       sc->sc_dev.dv_xname);
+	} else {
+		ntxsegs = PCN_NTXSEGS;
+	}
+
+	/*
 	 * Map and establish our interrupt.
 	 */
 	if (pci_intr_map(pa, &ih)) {
@@ -708,7 +748,7 @@ pcn_attach(struct device *parent __unuse
 	/* Create the transmit buffer DMA maps. */
 	for (i = 0; i < PCN_TXQUEUELEN; i++) {
 		if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
-		     PCN_NTXSEGS, MCLBYTES, 0, 0,
+		     ntxsegs, MCLBYTES, 0, 0,
 		     &sc->sc_txsoft[i].txs_dmamap)) != 0) {
 			printf("%s: unable to create tx DMA map %d, "
 			    "error = %d\n", sc->sc_dev.dv_xname, i, error);

--Apple-Mail-1--675073169--