Commit 541f99a2 authored by Philippe Gerum's avatar Philippe Gerum Committed by Jan Kiszka
Browse files

net/stack: allow initializing pre-allocated device structs



We may want to embed struct rtnet_device into a pre-allocated parent
container struct, which makes rtdev_alloc() and rt_alloc_etherdev()
useless for the purpose.

The new rtdev_init() and rt_init_etherdev() calls can be used to
initialize a pre-allocated device structure and set it up with default
ethernet settings resp. The caller should set the private area pointer
manually (defaults to NULL).
Signed-off-by: Philippe Gerum's avatarPhilippe Gerum <rpm@xenomai.org>
Signed-off-by: Jan Kiszka's avatarJan Kiszka <jan.kiszka@siemens.com>
parent 2ad892cd
......@@ -180,12 +180,21 @@ extern struct mutex rtnet_devices_nrt_lock;
extern struct rtnet_device *rtnet_devices[];
int __rt_init_etherdev(struct rtnet_device *rtdev,
unsigned int dev_pool_size,
struct module *module);
#define rt_init_etherdev(__rtdev, __dev_pool_size) \
__rt_init_etherdev(__rtdev, __dev_pool_size, THIS_MODULE)
struct rtnet_device *__rt_alloc_etherdev(unsigned sizeof_priv,
unsigned dev_pool_size,
struct module *module);
#define rt_alloc_etherdev(priv_size, rx_size) \
__rt_alloc_etherdev(priv_size, rx_size, THIS_MODULE)
void rtdev_destroy(struct rtnet_device *rtdev);
void rtdev_free(struct rtnet_device *rtdev);
int rt_register_rtnetdev(struct rtnet_device *rtdev);
......
......@@ -251,6 +251,39 @@ static const struct rtskb_pool_lock_ops rtdev_ops = {
.unlock = rtdev_pool_unlock,
};
int rtdev_init(struct rtnet_device *rtdev, unsigned dev_pool_size)
{
int ret;
ret = rtskb_pool_init(&rtdev->dev_pool, dev_pool_size, &rtdev_ops, rtdev);
if (ret < dev_pool_size) {
printk(KERN_ERR "RTnet: cannot allocate rtnet device pool\n");
rtskb_pool_release(&rtdev->dev_pool);
return -ENOMEM;
}
rtdm_mutex_init(&rtdev->xmit_mutex);
rtdm_lock_init(&rtdev->rtdev_lock);
mutex_init(&rtdev->nrt_lock);
atomic_set(&rtdev->refcount, 0);
/* scale global rtskb pool */
rtdev->add_rtskbs = rtskb_pool_extend(&global_pool, device_rtskbs);
return 0;
}
EXPORT_SYMBOL_GPL(rtdev_init);
void rtdev_destroy(struct rtnet_device *rtdev)
{
rtskb_pool_release(&rtdev->dev_pool);
rtskb_pool_shrink(&global_pool, rtdev->add_rtskbs);
rtdev->stack_event = NULL;
rtdm_mutex_destroy(&rtdev->xmit_mutex);
}
EXPORT_SYMBOL_GPL(rtdev_destroy);
/***
* rtdev_alloc
* @int sizeof_priv:
......@@ -267,64 +300,88 @@ struct rtnet_device *rtdev_alloc(unsigned sizeof_priv, unsigned dev_pool_size)
/* ensure 32-byte alignment of the private area */
alloc_size = sizeof (*rtdev) + sizeof_priv + 31;
rtdev = (struct rtnet_device *)kmalloc(alloc_size, GFP_KERNEL);
rtdev = kzalloc(alloc_size, GFP_KERNEL);
if (rtdev == NULL) {
printk(KERN_ERR "RTnet: cannot allocate rtnet device\n");
return NULL;
}
memset(rtdev, 0, alloc_size);
ret = rtskb_pool_init(&rtdev->dev_pool, dev_pool_size, &rtdev_ops, rtdev);
if (ret < dev_pool_size) {
printk(KERN_ERR "RTnet: cannot allocate rtnet device pool\n");
rtskb_pool_release(&rtdev->dev_pool);
ret = rtdev_init(rtdev, dev_pool_size);
if (ret) {
kfree(rtdev);
return NULL;
}
rtdm_mutex_init(&rtdev->xmit_mutex);
rtdm_lock_init(&rtdev->rtdev_lock);
mutex_init(&rtdev->nrt_lock);
atomic_set(&rtdev->refcount, 0);
/* scale global rtskb pool */
rtdev->add_rtskbs = rtskb_pool_extend(&global_pool, device_rtskbs);
if (sizeof_priv)
rtdev->priv = (void *)(((long)(rtdev + 1) + 31) & ~31);
return rtdev;
}
/***
* rtdev_free
*/
void rtdev_free (struct rtnet_device *rtdev)
{
if (rtdev != NULL) {
rtskb_pool_release(&rtdev->dev_pool);
rtskb_pool_shrink(&global_pool, rtdev->add_rtskbs);
rtdev->stack_event = NULL;
rtdm_mutex_destroy(&rtdev->xmit_mutex);
rtdev_destroy(rtdev);
kfree(rtdev);
}
}
EXPORT_SYMBOL_GPL(rtdev_free);
static void init_etherdev(struct rtnet_device *rtdev,
struct module *module)
{
rtdev->hard_header = rt_eth_header;
rtdev->type = ARPHRD_ETHER;
rtdev->hard_header_len = ETH_HLEN;
rtdev->mtu = 1500; /* eth_mtu */
rtdev->addr_len = ETH_ALEN;
rtdev->flags = IFF_BROADCAST; /* TODO: IFF_MULTICAST; */
rtdev->get_mtu = rt_hard_mtu;
rtdev->rt_owner = module;
memset(rtdev->broadcast, 0xFF, ETH_ALEN);
strcpy(rtdev->name, "rteth%d");
}
/**
* rt_init_etherdev - sets up an ethernet device
* @module: module initializing the device
*
* Fill in the fields of the device structure with ethernet-generic
* values. This routine can be used to set up a pre-allocated device
* structure. The device still needs to be registered afterwards.
*/
int __rt_init_etherdev(struct rtnet_device *rtdev,
unsigned dev_pool_size,
struct module *module)
{
int ret;
ret = rtdev_init(rtdev, dev_pool_size);
if (ret)
return ret;
init_etherdev(rtdev, module);
return 0;
}
EXPORT_SYMBOL_GPL(__rt_init_etherdev);
/**
* rtalloc_etherdev - Allocates and sets up an ethernet device
* rt_alloc_etherdev - Allocates and sets up an ethernet device
* @sizeof_priv: size of additional driver-private structure to
* be allocated for this ethernet device
* @dev_pool_size: size of the rx pool
* @module: module creating the deivce
* @module: module creating the device
*
* Fill in the fields of the device structure with ethernet-generic
* values. Basically does everything except registering the device.
* Allocates then fills in the fields of a new device structure with
* ethernet-generic values. Basically does everything except
* registering the device.
*
* A 32-byte alignment is enforced for the private data area.
*/
......@@ -338,21 +395,11 @@ struct rtnet_device *__rt_alloc_etherdev(unsigned sizeof_priv,
if (!rtdev)
return NULL;
rtdev->hard_header = rt_eth_header;
rtdev->type = ARPHRD_ETHER;
rtdev->hard_header_len = ETH_HLEN;
rtdev->mtu = 1500; /* eth_mtu */
rtdev->addr_len = ETH_ALEN;
rtdev->flags = IFF_BROADCAST; /* TODO: IFF_MULTICAST; */
rtdev->get_mtu = rt_hard_mtu;
rtdev->rt_owner = module;
memset(rtdev->broadcast, 0xFF, ETH_ALEN);
strcpy(rtdev->name, "rteth%d");
init_etherdev(rtdev, module);
return rtdev;
}
EXPORT_SYMBOL_GPL(__rt_alloc_etherdev);
static inline int __rtdev_new_index(void)
......@@ -907,9 +954,6 @@ unsigned int rt_hard_mtu(struct rtnet_device *rtdev, unsigned int priority)
}
EXPORT_SYMBOL_GPL(__rt_alloc_etherdev);
EXPORT_SYMBOL_GPL(rtdev_free);
EXPORT_SYMBOL_GPL(rtdev_alloc_name);
EXPORT_SYMBOL_GPL(rt_register_rtnetdev);
......
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