Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. ===== Overview ===== The various forms of allocating a netdevice. ===== netdev private data ===== From ''include/linux/netdevice.h'', optional private data is stored (aligned) after the end of the structure: <code> static inline void *netdev_priv(const struct net_device *dev) { return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); } </code> <code> #define NETDEV_ALIGN 32 </code> Explanation of ''NETDEV_ALIGN'' [[https://stackoverflow.com/questions/31459565/memory-alignment-in-the-alloc-netdev-mqs|here]]. ===== alloc_netdev_mqs ===== The base allocation routine from ''net/core/dev.c'' for allocating a //single// device: <code> /** * alloc_netdev_mqs - allocate network device * @sizeof_priv: size of private data to allocate space for * @name: device name format string * @name_assign_type: origin of device name * @setup: callback to initialize device * @txqs: the number of TX subqueues to allocate * @rxqs: the number of RX subqueues to allocate * * Allocates a struct net_device with private data area for driver use * and performs basic initialization. Also allocates subqueue structs * for each queue on the device. */ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, unsigned char name_assign_type, void (*setup)(struct net_device *), unsigned int txqs, unsigned int rxqs) { struct net_device *dev; unsigned int alloc_size; struct net_device *p; BUG_ON(strlen(name) >= sizeof(dev->name)); if (txqs < 1) { pr_err("alloc_netdev: Unable to allocate device with zero queues\n"); return NULL; } if (rxqs < 1) { pr_err("alloc_netdev: Unable to allocate device with zero RX queues\n"); return NULL; } alloc_size = sizeof(struct net_device); if (sizeof_priv) { /* ensure 32-byte alignment of private area */ alloc_size = ALIGN(alloc_size, NETDEV_ALIGN); alloc_size += sizeof_priv; } /* ensure 32-byte alignment of whole construct */ alloc_size += NETDEV_ALIGN - 1; p = kvzalloc(alloc_size, GFP_KERNEL | __GFP_RETRY_MAYFAIL); if (!p) return NULL; ... snip ... </code> Not a lot of drivers call this routine directly given that you can call more convenient wrappers (see below). ===== Wrappers/variations ===== ==== alloc_netdev()/alloc_netdev_mq() ==== From ''include/linux/netdevice.h'': <code> #define alloc_netdev(sizeof_priv, name, name_assign_type, setup) \ alloc_netdev_mqs(sizeof_priv, name, name_assign_type, setup, 1, 1) #define alloc_netdev_mq(sizeof_priv, name, name_assign_type, setup, count) \ alloc_netdev_mqs(sizeof_priv, name, name_assign_type, setup, count, \ count) </code> ==== alloc_etherdev(),alloc_etherdev_mq(),alloc_etherdev_mqs() ==== From ''include/linux/etherdevice.h'': <code> struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs); #define alloc_etherdev(sizeof_priv) alloc_etherdev_mq(sizeof_priv, 1) #define alloc_etherdev_mq(sizeof_priv, count) alloc_etherdev_mqs(sizeof_priv, count, count) </code> From ''net/ethernet/net.c'': <code> struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, unsigned int rxqs) { return alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN, ether_setup, txqs, rxqs); } </code> ==== devm_alloc_etherdev*() ==== From ''include/linux/etherdevice.h'': <code> struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv, unsigned int txqs, unsigned int rxqs); #define devm_alloc_etherdev(dev, sizeof_priv) devm_alloc_etherdev_mqs(dev, sizeof_priv, 1, 1) </code> From ''net/ethernet/net.c'': <code> struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv, unsigned int txqs, unsigned int rxqs) { struct net_device **dr; struct net_device *netdev; dr = devres_alloc(devm_free_netdev, sizeof(*dr), GFP_KERNEL); if (!dr) return NULL; netdev = alloc_etherdev_mqs(sizeof_priv, txqs, rxqs); if (!netdev) { devres_free(dr); return NULL; } *dr = netdev; devres_add(dev, dr); return netdev; } </code> alloc_netdev_etherdev.txt Last modified: 2018/08/28 08:00by rpjday