diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-01-15 00:05:05 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-15 00:05:05 -0500 |
commit | 937f1ba56b4be37d9e2ad77412f95048662058d2 (patch) | |
tree | 154e0c5ce11b5afe25816d667c76b19ac679d530 | |
parent | 2950e952920811be465ec95c6b56f03dc66a05c0 (diff) |
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 ecf9798987fa..2a2fc17b2878 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, | |||
613 | INIT_LIST_HEAD(&mal->list); | 613 | INIT_LIST_HEAD(&mal->list); |
614 | spin_lock_init(&mal->lock); | 614 | spin_lock_init(&mal->lock); |
615 | 615 | ||
616 | netif_napi_add(NULL, &mal->napi, mal_poll, | 616 | init_dummy_netdev(&mal->dummy_dev); |
617 | |||
618 | netif_napi_add(&mal->dummy_dev, &mal->napi, mal_poll, | ||
617 | CONFIG_IBM_NEW_EMAC_POLL_WEIGHT); | 619 | CONFIG_IBM_NEW_EMAC_POLL_WEIGHT); |
618 | 620 | ||
619 | /* Load power-on reset defaults */ | 621 | /* Load power-on reset defaults */ |
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h index 2f0a87360844..9ededfbf0726 100644 --- a/drivers/net/ibm_newemac/mal.h +++ b/drivers/net/ibm_newemac/mal.h | |||
@@ -214,6 +214,8 @@ struct mal_instance { | |||
214 | int index; | 214 | int index; |
215 | spinlock_t lock; | 215 | spinlock_t lock; |
216 | 216 | ||
217 | struct net_device dummy_dev; | ||
218 | |||
217 | unsigned int features; | 219 | unsigned int features; |
218 | }; | 220 | }; |
219 | 221 | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 4647604c7ca9..ec54785d34f9 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -795,6 +795,7 @@ struct net_device | |||
795 | NETREG_UNREGISTERING, /* called unregister_netdevice */ | 795 | NETREG_UNREGISTERING, /* called unregister_netdevice */ |
796 | NETREG_UNREGISTERED, /* completed unregister todo */ | 796 | NETREG_UNREGISTERED, /* completed unregister todo */ |
797 | NETREG_RELEASED, /* called free_netdev */ | 797 | NETREG_RELEASED, /* called free_netdev */ |
798 | NETREG_DUMMY, /* dummy device for NAPI poll */ | ||
798 | } reg_state; | 799 | } reg_state; |
799 | 800 | ||
800 | /* Called from unregister, can be used to call free_netdev */ | 801 | /* Called from unregister, can be used to call free_netdev */ |
@@ -1077,6 +1078,8 @@ extern void free_netdev(struct net_device *dev); | |||
1077 | extern void synchronize_net(void); | 1078 | extern void synchronize_net(void); |
1078 | extern int register_netdevice_notifier(struct notifier_block *nb); | 1079 | extern int register_netdevice_notifier(struct notifier_block *nb); |
1079 | extern int unregister_netdevice_notifier(struct notifier_block *nb); | 1080 | extern int unregister_netdevice_notifier(struct notifier_block *nb); |
1081 | extern int init_dummy_netdev(struct net_device *dev); | ||
1082 | |||
1080 | extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); | 1083 | extern int call_netdevice_notifiers(unsigned long val, struct net_device *dev); |
1081 | extern struct net_device *dev_get_by_index(struct net *net, int ifindex); | 1084 | extern struct net_device *dev_get_by_index(struct net *net, int ifindex); |
1082 | extern struct net_device *__dev_get_by_index(struct net *net, int ifindex); | 1085 | 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 60377b6c0a80..8d675975d85b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -4431,6 +4431,45 @@ err_uninit: | |||
4431 | } | 4431 | } |
4432 | 4432 | ||
4433 | /** | 4433 | /** |
4434 | * init_dummy_netdev - init a dummy network device for NAPI | ||
4435 | * @dev: device to init | ||
4436 | * | ||
4437 | * This takes a network device structure and initialize the minimum | ||
4438 | * amount of fields so it can be used to schedule NAPI polls without | ||
4439 | * registering a full blown interface. This is to be used by drivers | ||
4440 | * that need to tie several hardware interfaces to a single NAPI | ||
4441 | * poll scheduler due to HW limitations. | ||
4442 | */ | ||
4443 | int init_dummy_netdev(struct net_device *dev) | ||
4444 | { | ||
4445 | /* Clear everything. Note we don't initialize spinlocks | ||
4446 | * are they aren't supposed to be taken by any of the | ||
4447 | * NAPI code and this dummy netdev is supposed to be | ||
4448 | * only ever used for NAPI polls | ||
4449 | */ | ||
4450 | memset(dev, 0, sizeof(struct net_device)); | ||
4451 | |||
4452 | /* make sure we BUG if trying to hit standard | ||
4453 | * register/unregister code path | ||
4454 | */ | ||
4455 | dev->reg_state = NETREG_DUMMY; | ||
4456 | |||
4457 | /* initialize the ref count */ | ||
4458 | atomic_set(&dev->refcnt, 1); | ||
4459 | |||
4460 | /* NAPI wants this */ | ||
4461 | INIT_LIST_HEAD(&dev->napi_list); | ||
4462 | |||
4463 | /* a dummy interface is started by default */ | ||
4464 | set_bit(__LINK_STATE_PRESENT, &dev->state); | ||
4465 | set_bit(__LINK_STATE_START, &dev->state); | ||
4466 | |||
4467 | return 0; | ||
4468 | } | ||
4469 | EXPORT_SYMBOL_GPL(init_dummy_netdev); | ||
4470 | |||
4471 | |||
4472 | /** | ||
4434 | * register_netdev - register a network device | 4473 | * register_netdev - register a network device |
4435 | * @dev: device to register | 4474 | * @dev: device to register |
4436 | * | 4475 | * |