diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-01-14 21:05:05 -0800 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2009-01-14 21:05:05 -0800 | 
| commit | 937f1ba56b4be37d9e2ad77412f95048662058d2 (patch) | |
| tree | 154e0c5ce11b5afe25816d667c76b19ac679d530 | |
| parent | 2950e952920811be465ec95c6b56f03dc66a05c0 (diff) | |
| download | olio-linux-3.10-937f1ba56b4be37d9e2ad77412f95048662058d2.tar.xz olio-linux-3.10-937f1ba56b4be37d9e2ad77412f95048662058d2.zip  | |
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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Tested-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/ibm_newemac/mal.c | 4 | ||||
| -rw-r--r-- | drivers/net/ibm_newemac/mal.h | 2 | ||||
| -rw-r--r-- | include/linux/netdevice.h | 3 | ||||
| -rw-r--r-- | net/core/dev.c | 39 | 
4 files changed, 47 insertions, 1 deletions
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index ecf9798987f..2a2fc17b287 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c @@ -613,7 +613,9 @@ static int __devinit mal_probe(struct of_device *ofdev,  	INIT_LIST_HEAD(&mal->list);  	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);  	/* Load power-on reset defaults */ diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 2f0a8736084..9ededfbf072 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h @@ -214,6 +214,8 @@ struct mal_instance {  	int			index;  	spinlock_t		lock; +	struct net_device	dummy_dev; +  	unsigned int features;  }; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4647604c7ca..ec54785d34f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -795,6 +795,7 @@ struct net_device  	       NETREG_UNREGISTERING,	/* called unregister_netdevice */  	       NETREG_UNREGISTERED,	/* completed unregister todo */  	       NETREG_RELEASED,		/* called free_netdev */ +	       NETREG_DUMMY,		/* dummy device for NAPI poll */  	} reg_state;  	/* Called from unregister, can be used to call free_netdev */ @@ -1077,6 +1078,8 @@ extern void		free_netdev(struct net_device *dev);  extern void		synchronize_net(void);  extern int 		register_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 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); diff --git a/net/core/dev.c b/net/core/dev.c index 60377b6c0a8..8d675975d85 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4431,6 +4431,45 @@ err_uninit:  }  /** + *	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   *	@dev: device to register   *  |