Skip to content

Commit

Permalink
net: Add init_dummy_netdev() and fix EMAC driver using it
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Benjamin Herrenschmidt authored and David S. Miller committed Jan 15, 2009
1 parent 2950e95 commit 937f1ba
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 1 deletion.
4 changes: 3 additions & 1 deletion drivers/net/ibm_newemac/mal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ibm_newemac/mal.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,8 @@ struct mal_instance {
int index;
spinlock_t lock;

struct net_device dummy_dev;

unsigned int features;
};

Expand Down
3 changes: 3 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
39 changes: 39 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -4430,6 +4430,45 @@ int register_netdevice(struct net_device *dev)
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
* @dev: device to register
Expand Down

0 comments on commit 937f1ba

Please sign in to comment.