Subject: Node-aware netdevice allocation Adds alloca_netdev_node & friends to allocate a struct netdevice on a given NUMA node. Note: needs benchmarking to prove a gain. Signed-off-by: Christoph Hellwig Index: linux-2.6/include/linux/etherdevice.h =================================================================== --- linux-2.6.orig/include/linux/etherdevice.h +++ linux-2.6/include/linux/etherdevice.h @@ -40,6 +40,7 @@ extern int eth_header_cache(struct neig struct hh_cache *hh); extern struct net_device *alloc_etherdev(int sizeof_priv); +extern struct net_device *alloc_etherdev_node(int sizeof_priv, int node); static inline void eth_copy_and_sum (struct sk_buff *dest, const unsigned char *src, int len, int base) Index: linux-2.6/include/linux/netdevice.h =================================================================== --- linux-2.6.orig/include/linux/netdevice.h +++ linux-2.6/include/linux/netdevice.h @@ -959,6 +959,9 @@ extern void ether_setup(struct net_devi /* Support for loadable net-drivers */ extern struct net_device *alloc_netdev(int sizeof_priv, const char *name, void (*setup)(struct net_device *)); +extern struct net_device *alloc_netdev_node(int sizeof_priv, const char *name, + void (*setup)(struct net_device *), + int node); extern int register_netdev(struct net_device *dev); extern void unregister_netdev(struct net_device *dev); /* Functions used for multicast support */ Index: linux-2.6/net/core/dev.c =================================================================== --- linux-2.6.orig/net/core/dev.c +++ linux-2.6/net/core/dev.c @@ -3184,8 +3184,8 @@ out: * Allocates a struct net_device with private data area for driver use * and performs basic initialization. */ -struct net_device *alloc_netdev(int sizeof_priv, const char *name, - void (*setup)(struct net_device *)) +struct net_device *alloc_netdev_node(int sizeof_priv, const char *name, + void (*setup)(struct net_device *), int node) { void *p; struct net_device *dev; @@ -3195,11 +3195,12 @@ struct net_device *alloc_netdev(int size alloc_size = (sizeof(*dev) + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST; alloc_size += sizeof_priv + NETDEV_ALIGN_CONST; - p = kzalloc(alloc_size, GFP_KERNEL); + p = kmalloc(alloc_size, GFP_KERNEL); if (!p) { printk(KERN_ERR "alloc_dev: Unable to allocate device.\n"); return NULL; } + memset(p, 0, alloc_size); dev = (struct net_device *) (((long)p + NETDEV_ALIGN_CONST) & ~NETDEV_ALIGN_CONST); @@ -3212,6 +3213,13 @@ struct net_device *alloc_netdev(int size strcpy(dev->name, name); return dev; } +EXPORT_SYMBOL(alloc_netdev_node); + +struct net_device *alloc_netdev(int sizeof_priv, const char *name, + void (*setup)(struct net_device *)) +{ + return alloc_netdev_node(sizeof_priv, name, setup, -1); +} EXPORT_SYMBOL(alloc_netdev); /** Index: linux-2.6/net/ethernet/eth.c =================================================================== --- linux-2.6.orig/net/ethernet/eth.c +++ linux-2.6/net/ethernet/eth.c @@ -300,3 +300,27 @@ struct net_device *alloc_etherdev(int si return alloc_netdev(sizeof_priv, "eth%d", ether_setup); } EXPORT_SYMBOL(alloc_etherdev); + +/** + * alloc_etherdev_node - Allocates and sets up an ethernet device + * @sizeof_priv: Size of additional driver-private structure to be allocated + * for this ethernet device + * @node: numa node this netdevice is local to + * + * Fill in the fields of the device structure with ethernet-generic + * values. Basically does everything except registering the device. + * + * Constructs a new net device, complete with a private data area of + * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for + * this private data area. + * + * Memory for the device structure is allocated on @node if possible. + * @node can be -1 in which case this function does the same as + * alloc_etherdev() + */ + +struct net_device *alloc_etherdev_node(int sizeof_priv, int node) +{ + return alloc_netdev_node(sizeof_priv, "eth%d", ether_setup, node); +} +EXPORT_SYMBOL(alloc_etherdev_node);