Commit 937f1ba5 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by David S. Miller

net: Add init_dummy_netdev() and fix EMAC driver using it

This adds an init_dummy_netdev() function that gets a network device
structure (allocation and lifetime entirely under caller's control) and
initialize the minimum amount of fields so it can be used to schedule
NAPI polls without registering a full blown interface. This is to be
used by drivers that need to tie several hardware interfaces to a single
NAPI poll scheduler due to HW limitations.

It also updates the ibm_newemac driver to use that, this fixing the
oops on 2.6.29 due to passing NULL as "dev" to netif_napi_add()

Symbol is exported GPL only a I don't think we want binary drivers doing
that sort of acrobatics (if we want them at all).
Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tested-by: default avatarGeert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2950e952
...@@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev, ...@@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev,
INIT_LIST_HEAD(&mal->list); INIT_LIST_HEAD(&mal->list);
spin_lock_init(&mal->lock); spin_lock_init(&mal->lock);
netif_napi_add(NULL, &mal->napi, mal_poll, init_dummy_netdev(&mal->dummy_dev);
netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll,
CONFIG_IBM_NEW_EMAC_POLL_WEIGHT); CONFIG_IBM_NEW_EMAC_POLL_WEIGHT);
/* Load power-on reset defaults */ /* Load power-on reset defaults */
......
...@@ -214,6 +214,8 @@ struct mal_instance { ...@@ -214,6 +214,8 @@ struct mal_instance {
int index; int index;
spinlock_t lock; spinlock_t lock;
struct net_device dummy_dev;
unsigned int features; unsigned int features;
}; };
......
...@@ -795,6 +795,7 @@ struct net_device ...@@ -795,6 +795,7 @@ struct net_device
NETREG_UNREGISTERING, /* called unregister_netdevice */ NETREG_UNREGISTERING, /* called unregister_netdevice */
NETREG_UNREGISTERED, /* completed unregister todo */ NETREG_UNREGISTERED, /* completed unregister todo */
NETREG_RELEASED, /* called free_netdev */ NETREG_RELEASED, /* called free_netdev */
NETREG_DUMMY, /* dummy device for NAPI poll */
} reg_state; } reg_state;
/* Called from unregister, can be used to call free_netdev */ /* Called from unregister, can be used to call free_netdev */
...@@ -1077,6 +1078,8 @@ extern void free_netdev(struct net_device *dev); ...@@ -1077,6 +1078,8 @@ extern void free_netdev(struct net_device *dev);
extern void synchronize_net(void); extern void synchronize_net(void);
extern int register_netdevice_notifier(struct notifier_block *nb); extern int register_netdevice_notifier(struct notifier_block *nb);
extern int unregister_netdevice_notifier(struct notifier_block *nb); extern int unregister_netdevice_notifier(struct notifier_block *nb);
extern int init_dummy_netdev(struct net_device *dev);
extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev);
extern struct net_device *dev_get_by_index(struct net *net, int ifindex); extern struct net_device *dev_get_by_index(struct net *net, int ifindex);
extern struct net_device *__dev_get_by_index(struct net *net, int ifindex); extern struct net_device *__dev_get_by_index(struct net *net, int ifindex);
......
...@@ -4430,6 +4430,45 @@ err_uninit: ...@@ -4430,6 +4430,45 @@ err_uninit:
goto out; goto out;
} }
/**
* init_dummy_netdev - init a dummy network device for NAPI
* @dev: device to init
*
* This takes a network device structure and initialize the minimum
* amount of fields so it can be used to schedule NAPI polls without
* registering a full blown interface. This is to be used by drivers
* that need to tie several hardware interfaces to a single NAPI
* poll scheduler due to HW limitations.
*/
int init_dummy_netdev(struct net_device *dev)
{
/* Clear everything. Note we don't initialize spinlocks
* are they aren't supposed to be taken by any of the
* NAPI code and this dummy netdev is supposed to be
* only ever used for NAPI polls
*/
memset(dev, 0, sizeof(struct net_device));
/* make sure we BUG if trying to hit standard
* register/unregister code path
*/
dev->reg_state = NETREG_DUMMY;
/* initialize the ref count */
atomic_set(&dev->refcnt, 1);
/* NAPI wants this */
INIT_LIST_HEAD(&dev->napi_list);
/* a dummy interface is started by default */
set_bit(__LINK_STATE_PRESENT, &dev->state);
set_bit(__LINK_STATE_START, &dev->state);
return 0;
}
EXPORT_SYMBOL_GPL(init_dummy_netdev);
/** /**
* register_netdev - register a network device * register_netdev - register a network device
* @dev: device to register * @dev: device to register
......
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