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>
This commit is contained in:
parent
2950e95292
commit
937f1ba56b
@ -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 {
|
|||||||
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
|
|||||||
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);
|
|||||||
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:
|
|||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user