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--