Commit f346af6a authored by Alexander Viro's avatar Alexander Viro Committed by Stephen Hemminger

net_device and netdev private struct allocation improvements.

1) Ensure alignment of both net_device and private area.
2) Introduce netdev_priv(), an inline which allows the dynamic private
   area (dev->priv) to be calculated as a constant offset from the
   base struct net_device at compile time.
parent 373ed85e
...@@ -73,23 +73,28 @@ ...@@ -73,23 +73,28 @@
struct net_device *alloc_netdev(int sizeof_priv, const char *mask, struct net_device *alloc_netdev(int sizeof_priv, const char *mask,
void (*setup)(struct net_device *)) void (*setup)(struct net_device *))
{ {
void *p;
struct net_device *dev; struct net_device *dev;
int alloc_size; int alloc_size;
/* ensure 32-byte alignment of the private area */ /* ensure 32-byte alignment of both the device and private area */
alloc_size = sizeof (*dev) + sizeof_priv + 31;
dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL); alloc_size = (sizeof(struct net_device) + 31) & ~31;
if (dev == NULL) alloc_size += sizeof_priv + 31;
{
printk(KERN_ERR "alloc_dev: Unable to allocate device memory.\n"); p = kmalloc (alloc_size, GFP_KERNEL);
if (!p) {
printk(KERN_ERR "alloc_dev: Unable to allocate device.\n");
return NULL; return NULL;
} }
memset(dev, 0, alloc_size); memset(p, 0, alloc_size);
dev = (struct net_device *)(((long)p + 31) & ~31);
dev->padded = (char *)dev - (char *)p;
if (sizeof_priv) if (sizeof_priv)
dev->priv = (void *) (((long)(dev + 1) + 31) & ~31); dev->priv = netdev_priv(dev);
setup(dev); setup(dev);
strcpy(dev->name, mask); strcpy(dev->name, mask);
......
...@@ -470,8 +470,15 @@ struct net_device ...@@ -470,8 +470,15 @@ struct net_device
/* class/net/name entry */ /* class/net/name entry */
struct class_device class_dev; struct class_device class_dev;
struct net_device_stats* (*last_stats)(struct net_device *); struct net_device_stats* (*last_stats)(struct net_device *);
/* how much padding had been added by alloc_netdev() */
int padded;
}; };
static inline void *netdev_priv(struct net_device *dev)
{
return (char *)dev + ((sizeof(struct net_device) + 31) & ~31);
}
#define SET_MODULE_OWNER(dev) do { } while (0) #define SET_MODULE_OWNER(dev) do { } while (0)
/* Set the sysfs physical device reference for the network logical device /* Set the sysfs physical device reference for the network logical device
* if set prior to registration will cause a symlink during initialization. * if set prior to registration will cause a symlink during initialization.
......
...@@ -2899,7 +2899,7 @@ void free_netdev(struct net_device *dev) ...@@ -2899,7 +2899,7 @@ void free_netdev(struct net_device *dev)
{ {
/* Compatiablity with error handling in drivers */ /* Compatiablity with error handling in drivers */
if (dev->reg_state == NETREG_UNINITIALIZED) { if (dev->reg_state == NETREG_UNINITIALIZED) {
kfree(dev); kfree((char *)dev - dev->padded);
return; return;
} }
......
...@@ -372,7 +372,7 @@ static void netdev_release(struct class_device *cd) ...@@ -372,7 +372,7 @@ static void netdev_release(struct class_device *cd)
BUG_ON(dev->reg_state != NETREG_RELEASED); BUG_ON(dev->reg_state != NETREG_RELEASED);
kfree(dev); kfree((char *)dev - dev->padded);
} }
static struct class net_class = { static struct class net_class = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment