Thursday 6 January 2011

Fixing vmxnet for vmwaretools-7.9.9 on Linux-2.6.32+

I just tried to load up vmwaretools on Ubuntu 10.04 Karmic (Kernel linux-2.6.32 - for later kernels see below) and things went ok till it tried to compile vmxnet.c - things have changed and VMware haven't kept up... So I fixed it - see attached patch below. I took a short cut to get the modified file into the vmware-install.pl build process: It copies the src files to a directory in /tmp/vmware-configX/ (where X is a number) - You'll need to run the vmware-install.pl script and then suspend (hit Ctrl-Z) it once it has got to the very first step of compiling vmxnet (ie before it starts the actual compilation) - then copy in the patched file and put the installer into the foreground (type '%'). I guess it's possible to copy it to a tar file somewhere but I didn't bother locating the correct one.

--- vmxnet.c 2011-01-05 17:46:30.820624430 +0000
+++ vmxnet.c.orig 2010-11-20 02:24:48.000000000 +0000
@@ -162,31 +162,6 @@
#define VMXNET_LOG(msg...)
#endif // VMXNET_DEBUG

-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43)
-/*
- *-----------------------------------------------------------------------------
- *
- * vmxnet_tx_timeout --
- *
- * Network device tx_timeout routine. Called by Linux when the tx
- * queue has been stopped for more than dev->watchdog_timeo jiffies.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Tries to restart the transmit queue.
- *
- *-----------------------------------------------------------------------------
- */
-static void
-vmxnet_tx_timeout(struct net_device *dev)
-{
- netif_wake_queue(dev);
-}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43) */
-
-
/* Data structure used when determining what hardware the driver supports. */

static const struct pci_device_id vmxnet_chips[] =
@@ -210,26 +185,6 @@
.probe = vmxnet_probe_device,
.remove = vmxnet_remove_device,
};
-static struct net_device_ops
-vmxnet_netdev_ops = {
- .ndo_open = vmxnet_open,
- .ndo_start_xmit = vmxnet_start_tx,
- .ndo_stop = vmxnet_close,
- .ndo_get_stats = vmxnet_get_stats,
- .ndo_set_multicast_list = vmxnet_set_multicast_list,
-#ifdef HAVE_CHANGE_MTU
- .ndo_change_mtu = vmxnet_change_mtu,
-#endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43)
- .ndo_tx_timeout = vmxnet_tx_timeout,
-#endif
-#ifdef VMW_HAVE_POLL_CONTROLLER
- .ndo_poll_controller = vmxnet_netpoll,
-#endif
- /* Do this after ether_setup(), which sets the default value. */
- .ndo_set_mac_address = vmxnet_set_mac_address,
-};
-

#ifdef HAVE_CHANGE_MTU
static int
@@ -373,6 +328,8 @@
.set_tso = vmxnet_set_tso,
#endif
};
+
+
#else /* !defined(SET_ETHTOOL_OPS) */


@@ -649,6 +606,30 @@
}


+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * vmxnet_tx_timeout --
+ *
+ * Network device tx_timeout routine. Called by Linux when the tx
+ * queue has been stopped for more than dev->watchdog_timeo jiffies.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Tries to restart the transmit queue.
+ *
+ *-----------------------------------------------------------------------------
+ */
+static void
+vmxnet_tx_timeout(struct net_device *dev)
+{
+ netif_wake_queue(dev);
+}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43) */
+

/*
*-----------------------------------------------------------------------------
@@ -1072,9 +1053,25 @@
#endif

dev->irq = irq_line;
+
+ dev->open = &vmxnet_open;
+ dev->hard_start_xmit = &vmxnet_start_tx;
+ dev->stop = &vmxnet_close;
+ dev->get_stats = &vmxnet_get_stats;
+ dev->set_multicast_list = &vmxnet_set_multicast_list;
+#ifdef HAVE_CHANGE_MTU
+ dev->change_mtu = &vmxnet_change_mtu;
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,43)
+ dev->tx_timeout = &vmxnet_tx_timeout;
dev->watchdog_timeo = VMXNET_WATCHDOG_TIMEOUT;
+#endif
+#ifdef VMW_HAVE_POLL_CONTROLLER
+ dev->poll_controller = vmxnet_netpoll;
+#endif

- dev->netdev_ops = &vmxnet_netdev_ops;
+ /* Do this after ether_setup(), which sets the default value. */
+ dev->set_mac_address = &vmxnet_set_mac_address;

#ifdef SET_ETHTOOL_OPS
SET_ETHTOOL_OPS(dev, &vmxnet_ethtool_ops);


If you're running linux-2.6.35 (Ubuntu 10.10 Maverick) then you'll also need to apply the following patch (once you've applied the above one):

--- vmxnet.c 2011-01-06 14:44:41.000000000 +0000
+++ vmxnet.c.linux2.6.32 2011-01-06 14:44:41.000000000 +0000
@@ -2405,10 +2405,9 @@
{
struct Vmxnet_Private *lp = netdev_priv(dev);
volatile u16 *mcast_table = (u16 *)lp->dd->LADRF;
- struct netdev_hw_addr_list *mc_list = &dev->mc;
- struct netdev_hw_addr *ha;
+ struct dev_mc_list *dmi = dev->mc_list;
char *addrs;
- int j, bit, byte;
+ int i, j, bit, byte;
u32 crc, poly = CRC_POLYNOMIAL_LE;

/* clear the multicast filter */
@@ -2416,9 +2415,9 @@
lp->dd->LADRF[1] = 0;

/* Add addresses */
-
- netdev_hw_addr_list_for_each(ha, mc_list) {
- addrs = ha->addr;
+ for (i = 0; i < dev->mc_count; i++){
+ addrs = dmi->dmi_addr;
+ dmi = dmi->next;

/* multicast address? */
if (!(*addrs & 1))
@@ -2441,7 +2440,7 @@
crc = crc >> 26;
mcast_table [crc >> 4] |= 1 << (crc & 0xf); } - return mc_list->count;
+ return i;
}

/*

1 comment:

  1. Very good to know about this, as I was puzzled why my vmxnet stopped working. But it was easier for me just to switch to AMD Lance (pcnet32) instead, until VMWare fix it properly.

    I am using Ubuntu Server 10.04 with kernel 2.6.32-28. Maybe it just upgraded from kernel 2.6.32-27, and this was wot broke it?

    ReplyDelete