Commit c3a93e09 authored by Chas Williams's avatar Chas Williams Committed by David S. Miller

[ATM]: lane and mpoa module refcounting and locking cleanup.

parent 29146e24
...@@ -32,21 +32,61 @@ ...@@ -32,21 +32,61 @@
#include <linux/atmlec.h> #include <linux/atmlec.h>
#include "lec.h" #include "lec.h"
#include "lec_arpc.h" #include "lec_arpc.h"
struct atm_lane_ops atm_lane_ops; struct atm_lane_ops *atm_lane_ops;
#endif static DECLARE_MUTEX(atm_lane_ops_mutex);
#ifdef CONFIG_ATM_LANE_MODULE
void atm_lane_ops_set(struct atm_lane_ops *hook)
{
down(&atm_lane_ops_mutex);
atm_lane_ops = hook;
up(&atm_lane_ops_mutex);
}
int try_atm_lane_ops(void)
{
down(&atm_lane_ops_mutex);
if (atm_lane_ops && try_module_get(atm_lane_ops->owner)) {
up(&atm_lane_ops_mutex);
return 1;
}
up(&atm_lane_ops_mutex);
return 0;
}
#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_ATM_MPOA_MODULE)
EXPORT_SYMBOL(atm_lane_ops); EXPORT_SYMBOL(atm_lane_ops);
EXPORT_SYMBOL(try_atm_lane_ops);
EXPORT_SYMBOL(atm_lane_ops_set);
#endif
#endif #endif
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE) #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
#include <linux/atmmpc.h> #include <linux/atmmpc.h>
#include "mpc.h" #include "mpc.h"
struct atm_mpoa_ops atm_mpoa_ops; struct atm_mpoa_ops *atm_mpoa_ops;
#endif static DECLARE_MUTEX(atm_mpoa_ops_mutex);
void atm_mpoa_ops_set(struct atm_mpoa_ops *hook)
{
down(&atm_mpoa_ops_mutex);
atm_mpoa_ops = hook;
up(&atm_mpoa_ops_mutex);
}
int try_atm_mpoa_ops(void)
{
down(&atm_mpoa_ops_mutex);
if (atm_mpoa_ops && try_module_get(atm_mpoa_ops->owner)) {
up(&atm_mpoa_ops_mutex);
return 1;
}
up(&atm_mpoa_ops_mutex);
return 0;
}
#ifdef CONFIG_ATM_MPOA_MODULE #ifdef CONFIG_ATM_MPOA_MODULE
EXPORT_SYMBOL(atm_mpoa_ops); EXPORT_SYMBOL(atm_mpoa_ops);
#ifndef CONFIG_ATM_LANE_MODULE EXPORT_SYMBOL(try_atm_mpoa_ops);
EXPORT_SYMBOL(atm_lane_ops); EXPORT_SYMBOL(atm_mpoa_ops_set);
#endif #endif
#endif #endif
...@@ -728,27 +768,40 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) ...@@ -728,27 +768,40 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
ret_val = -EPERM; ret_val = -EPERM;
goto done; goto done;
} }
if (atm_lane_ops.lecd_attach == NULL) #if defined(CONFIG_ATM_LANE_MODULE)
atm_lane_init(); if (!atm_lane_ops)
if (atm_lane_ops.lecd_attach == NULL) { /* try again */ request_module("lec");
#endif
if (try_atm_lane_ops()) {
error = atm_lane_ops->lecd_attach(vcc, (int) arg);
module_put(atm_lane_ops->owner);
if (error >= 0)
sock->state = SS_CONNECTED;
ret_val = error;
} else
ret_val = -ENOSYS; ret_val = -ENOSYS;
goto done;
}
error = atm_lane_ops.lecd_attach(vcc, (int)arg);
if (error >= 0) sock->state = SS_CONNECTED;
ret_val = error;
goto done; goto done;
case ATMLEC_MCAST: case ATMLEC_MCAST:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
ret_val = -EPERM; ret_val = -EPERM;
else goto done;
ret_val = atm_lane_ops.mcast_attach(vcc, (int)arg); }
if (try_atm_lane_ops()) {
ret_val = atm_lane_ops->mcast_attach(vcc, (int) arg);
module_put(atm_lane_ops->owner);
} else
ret_val = -ENOSYS;
goto done; goto done;
case ATMLEC_DATA: case ATMLEC_DATA:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
ret_val = -EPERM; ret_val = -EPERM;
else goto done;
ret_val = atm_lane_ops.vcc_attach(vcc, (void*)arg); }
if (try_atm_lane_ops()) {
ret_val = atm_lane_ops->vcc_attach(vcc, (void *) arg);
module_put(atm_lane_ops->owner);
} else
ret_val = -ENOSYS;
goto done; goto done;
#endif #endif
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE) #if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
...@@ -757,21 +810,29 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg) ...@@ -757,21 +810,29 @@ int atm_ioctl(struct socket *sock,unsigned int cmd,unsigned long arg)
ret_val = -EPERM; ret_val = -EPERM;
goto done; goto done;
} }
if (atm_mpoa_ops.mpoad_attach == NULL) #if defined(CONFIG_ATM_MPOA_MODULE)
atm_mpoa_init(); if (!atm_mpoa_ops)
if (atm_mpoa_ops.mpoad_attach == NULL) { /* try again */ request_module("mpoa");
#endif
if (try_atm_mpoa_ops()) {
error = atm_mpoa_ops->mpoad_attach(vcc, (int) arg);
module_put(atm_mpoa_ops->owner);
if (error >= 0)
sock->state = SS_CONNECTED;
ret_val = error;
} else
ret_val = -ENOSYS; ret_val = -ENOSYS;
goto done;
}
error = atm_mpoa_ops.mpoad_attach(vcc, (int)arg);
if (error >= 0) sock->state = SS_CONNECTED;
ret_val = error;
goto done; goto done;
case ATMMPC_DATA: case ATMMPC_DATA:
if (!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN)) {
ret_val = -EPERM; ret_val = -EPERM;
else goto done;
ret_val = atm_mpoa_ops.vcc_attach(vcc, arg); }
if (try_atm_mpoa_ops()) {
ret_val = atm_mpoa_ops->vcc_attach(vcc, arg);
module_put(atm_mpoa_ops->owner);
} else
ret_val = -ENOSYS;
goto done; goto done;
#endif #endif
#if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE) #if defined(CONFIG_ATM_TCP) || defined(CONFIG_ATM_TCP_MODULE)
...@@ -1155,40 +1216,6 @@ int atm_getsockopt(struct socket *sock,int level,int optname, ...@@ -1155,40 +1216,6 @@ int atm_getsockopt(struct socket *sock,int level,int optname,
} }
/*
* lane_mpoa_init.c: A couple of helper functions
* to make modular LANE and MPOA client easier to implement
*/
/*
* This is how it goes:
*
* if xxxx is not compiled as module, call atm_xxxx_init_ops()
* from here
* else call atm_mpoa_init_ops() from init_module() within
* the kernel when xxxx module is loaded
*
* In either case function pointers in struct atm_xxxx_ops
* are initialized to their correct values. Either they
* point to functions in the module or in the kernel
*/
extern struct atm_mpoa_ops atm_mpoa_ops; /* in common.c */
extern struct atm_lane_ops atm_lane_ops; /* in common.c */
#if defined(CONFIG_ATM_MPOA) || defined(CONFIG_ATM_MPOA_MODULE)
void atm_mpoa_init(void)
{
#ifndef CONFIG_ATM_MPOA_MODULE /* not module */
atm_mpoa_init_ops(&atm_mpoa_ops);
#else
request_module("mpoa");
#endif
return;
}
#endif
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
...@@ -1199,18 +1226,8 @@ EXPORT_SYMBOL(br_fdb_get_hook); ...@@ -1199,18 +1226,8 @@ EXPORT_SYMBOL(br_fdb_get_hook);
EXPORT_SYMBOL(br_fdb_put_hook); EXPORT_SYMBOL(br_fdb_put_hook);
#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */ #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
#endif /* defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) */
void atm_lane_init(void)
{
#ifndef CONFIG_ATM_LANE_MODULE /* not module */
atm_lane_init_ops(&atm_lane_ops);
#else
request_module("lec");
#endif
return;
}
#endif
static int __init atm_init(void) static int __init atm_init(void)
{ {
......
This diff is collapsed.
...@@ -64,7 +64,8 @@ struct atm_lane_ops { ...@@ -64,7 +64,8 @@ struct atm_lane_ops {
int (*lecd_attach)(struct atm_vcc *vcc, int arg); int (*lecd_attach)(struct atm_vcc *vcc, int arg);
int (*mcast_attach)(struct atm_vcc *vcc, int arg); int (*mcast_attach)(struct atm_vcc *vcc, int arg);
int (*vcc_attach)(struct atm_vcc *vcc, void *arg); int (*vcc_attach)(struct atm_vcc *vcc, void *arg);
struct net_device **(*get_lecs)(void); struct net_device * (*get_lec)(int itf);
struct module *owner;
}; };
/* /*
...@@ -102,6 +103,7 @@ struct lec_priv { ...@@ -102,6 +103,7 @@ struct lec_priv {
collects all those VCCs. LANEv1 client has only one item in this collects all those VCCs. LANEv1 client has only one item in this
list. These entries are not aged out. */ list. These entries are not aged out. */
atomic_t lec_arp_users; atomic_t lec_arp_users;
spinlock_t lec_arp_lock;
struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */ struct atm_vcc *mcast_vcc; /* Default Multicast Send VCC */
struct atm_vcc *lecd; struct atm_vcc *lecd;
struct timer_list lec_arp_timer; struct timer_list lec_arp_timer;
...@@ -148,14 +150,16 @@ struct lec_priv { ...@@ -148,14 +150,16 @@ struct lec_priv {
int lecd_attach(struct atm_vcc *vcc, int arg); int lecd_attach(struct atm_vcc *vcc, int arg);
int lec_vcc_attach(struct atm_vcc *vcc, void *arg); int lec_vcc_attach(struct atm_vcc *vcc, void *arg);
int lec_mcast_attach(struct atm_vcc *vcc, int arg); int lec_mcast_attach(struct atm_vcc *vcc, int arg);
struct net_device **get_dev_lec(void); struct net_device *get_dev_lec(int itf);
int make_lec(struct atm_vcc *vcc); int make_lec(struct atm_vcc *vcc);
int send_to_lecd(struct lec_priv *priv, int send_to_lecd(struct lec_priv *priv,
atmlec_msg_type type, unsigned char *mac_addr, atmlec_msg_type type, unsigned char *mac_addr,
unsigned char *atm_addr, struct sk_buff *data); unsigned char *atm_addr, struct sk_buff *data);
void lec_push(struct atm_vcc *vcc, struct sk_buff *skb); void lec_push(struct atm_vcc *vcc, struct sk_buff *skb);
void atm_lane_init(void); extern struct atm_lane_ops *atm_lane_ops;
void atm_lane_init_ops(struct atm_lane_ops *ops); void atm_lane_ops_set(struct atm_lane_ops *hook);
int try_atm_lane_ops(void);
#endif /* _LEC_H_ */ #endif /* _LEC_H_ */
...@@ -251,12 +251,13 @@ void atm_mpoa_disp_qos(char *page, int *len) ...@@ -251,12 +251,13 @@ void atm_mpoa_disp_qos(char *page, int *len)
static struct net_device *find_lec_by_itfnum(int itf) static struct net_device *find_lec_by_itfnum(int itf)
{ {
extern struct atm_lane_ops atm_lane_ops; /* in common.c */ struct net_device *dev;
if (!try_atm_lane_ops())
if (atm_lane_ops.get_lecs == NULL)
return NULL; return NULL;
return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */ dev = atm_lane_ops->get_lec(itf);
module_put(atm_lane_ops->owner);
return dev;
} }
static struct mpoa_client *alloc_mpc(void) static struct mpoa_client *alloc_mpc(void)
...@@ -779,9 +780,10 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) ...@@ -779,9 +780,10 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
if (mpc->dev) { /* check if the lec is LANE2 capable */ if (mpc->dev) { /* check if the lec is LANE2 capable */
priv = (struct lec_priv *)mpc->dev->priv; priv = (struct lec_priv *)mpc->dev->priv;
if (priv->lane_version < 2) if (priv->lane_version < 2) {
dev_put(mpc->dev);
mpc->dev = NULL; mpc->dev = NULL;
else } else
priv->lane2_ops->associate_indicator = lane2_assoc_ind; priv->lane2_ops->associate_indicator = lane2_assoc_ind;
} }
...@@ -802,7 +804,7 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) ...@@ -802,7 +804,7 @@ int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc); send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
} }
MOD_INC_USE_COUNT; __module_get(THIS_MODULE);
return arg; return arg;
} }
...@@ -839,6 +841,7 @@ static void mpoad_close(struct atm_vcc *vcc) ...@@ -839,6 +841,7 @@ static void mpoad_close(struct atm_vcc *vcc)
struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv; struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
priv->lane2_ops->associate_indicator = NULL; priv->lane2_ops->associate_indicator = NULL;
stop_mpc(mpc); stop_mpc(mpc);
dev_put(mpc->dev);
} }
mpc->in_ops->destroy_cache(mpc); mpc->in_ops->destroy_cache(mpc);
...@@ -851,7 +854,7 @@ static void mpoad_close(struct atm_vcc *vcc) ...@@ -851,7 +854,7 @@ static void mpoad_close(struct atm_vcc *vcc)
printk("mpoa: (%s) going down\n", printk("mpoa: (%s) going down\n",
(mpc->dev) ? mpc->dev->name : "<unknown>"); (mpc->dev) ? mpc->dev->name : "<unknown>");
MOD_DEC_USE_COUNT; module_put(THIS_MODULE);
return; return;
} }
...@@ -975,6 +978,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo ...@@ -975,6 +978,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
} }
mpc->dev_num = priv->itfnum; mpc->dev_num = priv->itfnum;
mpc->dev = dev; mpc->dev = dev;
dev_hold(dev);
dprintk("mpoa: (%s) was initialized\n", dev->name); dprintk("mpoa: (%s) was initialized\n", dev->name);
break; break;
case NETDEV_UNREGISTER: case NETDEV_UNREGISTER:
...@@ -984,6 +988,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo ...@@ -984,6 +988,7 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo
break; break;
dprintk("mpoa: device (%s) was deallocated\n", dev->name); dprintk("mpoa: device (%s) was deallocated\n", dev->name);
stop_mpc(mpc); stop_mpc(mpc);
dev_put(mpc->dev);
mpc->dev = NULL; mpc->dev = NULL;
break; break;
case NETDEV_UP: case NETDEV_UP:
...@@ -1393,13 +1398,18 @@ static void mpc_cache_check( unsigned long checking_time ) ...@@ -1393,13 +1398,18 @@ static void mpc_cache_check( unsigned long checking_time )
return; return;
} }
void atm_mpoa_init_ops(struct atm_mpoa_ops *ops) static struct atm_mpoa_ops __atm_mpoa_ops = {
.mpoad_attach = atm_mpoa_mpoad_attach,
.vcc_attach = atm_mpoa_vcc_attach,
.owner = THIS_MODULE
};
static __init int atm_mpoa_init(void)
{ {
ops->mpoad_attach = atm_mpoa_mpoad_attach; atm_mpoa_ops_set(&__atm_mpoa_ops);
ops->vcc_attach = atm_mpoa_vcc_attach;
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
if(mpc_proc_init() != 0) if (mpc_proc_init() != 0)
printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n"); printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
else else
printk(KERN_INFO "mpoa: /proc/mpoa initialized\n"); printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
...@@ -1407,22 +1417,11 @@ void atm_mpoa_init_ops(struct atm_mpoa_ops *ops) ...@@ -1407,22 +1417,11 @@ void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
return;
}
#ifdef MODULE
int init_module(void)
{
extern struct atm_mpoa_ops atm_mpoa_ops;
atm_mpoa_init_ops(&atm_mpoa_ops);
return 0; return 0;
} }
void cleanup_module(void) void __exit atm_mpoa_cleanup(void)
{ {
extern struct atm_mpoa_ops atm_mpoa_ops;
struct mpoa_client *mpc, *tmp; struct mpoa_client *mpc, *tmp;
struct atm_mpoa_qos *qos, *nextqos; struct atm_mpoa_qos *qos, *nextqos;
struct lec_priv *priv; struct lec_priv *priv;
...@@ -1433,8 +1432,7 @@ void cleanup_module(void) ...@@ -1433,8 +1432,7 @@ void cleanup_module(void)
del_timer(&mpc_timer); del_timer(&mpc_timer);
unregister_netdevice_notifier(&mpoa_notifier); unregister_netdevice_notifier(&mpoa_notifier);
atm_mpoa_ops.mpoad_attach = NULL; atm_mpoa_ops_set(NULL);
atm_mpoa_ops.vcc_attach = NULL;
mpc = mpcs; mpc = mpcs;
mpcs = NULL; mpcs = NULL;
...@@ -1469,5 +1467,8 @@ void cleanup_module(void) ...@@ -1469,5 +1467,8 @@ void cleanup_module(void)
return; return;
} }
#endif /* MODULE */
module_init(atm_mpoa_init);
module_exit(atm_mpoa_cleanup);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -48,11 +48,13 @@ struct atm_mpoa_qos { ...@@ -48,11 +48,13 @@ struct atm_mpoa_qos {
struct atm_mpoa_ops { struct atm_mpoa_ops {
int (*mpoad_attach)(struct atm_vcc *vcc, int arg); /* attach mpoa daemon */ int (*mpoad_attach)(struct atm_vcc *vcc, int arg); /* attach mpoa daemon */
int (*vcc_attach)(struct atm_vcc *vcc, long arg); /* attach shortcut vcc */ int (*vcc_attach)(struct atm_vcc *vcc, long arg); /* attach shortcut vcc */
struct module *owner;
}; };
/* Boot/module initialization function */ /* Boot/module initialization function */
void atm_mpoa_init(void); extern struct atm_mpoa_ops *atm_mpoa_ops;
void atm_mpoa_init_ops(struct atm_mpoa_ops *ops); int try_atm_mpoa_ops(void);
void atm_mpoa_ops_set(struct atm_mpoa_ops *hook);
/* MPOA QoS operations */ /* MPOA QoS operations */
struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos); struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos);
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#include "lec.h" #include "lec.h"
#include "lec_arpc.h" #include "lec_arpc.h"
extern struct atm_lane_ops atm_lane_ops; /* in common.c */
#endif #endif
static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count, static ssize_t proc_dev_atm_read(struct file *file,char *buf,size_t count,
...@@ -481,57 +480,72 @@ static int atm_arp_info(loff_t pos,char *buf) ...@@ -481,57 +480,72 @@ static int atm_arp_info(loff_t pos,char *buf)
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
static int atm_lec_info(loff_t pos,char *buf) static int atm_lec_info(loff_t pos,char *buf)
{ {
unsigned long flags;
struct lec_priv *priv; struct lec_priv *priv;
struct lec_arp_table *entry; struct lec_arp_table *entry;
int i, count, d, e; int i, count, d, e;
struct net_device **dev_lec; struct net_device *dev;
if (!pos) { if (!pos) {
return sprintf(buf,"Itf MAC ATM destination" return sprintf(buf,"Itf MAC ATM destination"
" Status Flags " " Status Flags "
"VPI/VCI Recv VPI/VCI\n"); "VPI/VCI Recv VPI/VCI\n");
} }
if (atm_lane_ops.get_lecs == NULL) if (!try_atm_lane_ops())
return 0; /* the lane module is not there yet */ return 0; /* the lane module is not there yet */
else
dev_lec = atm_lane_ops.get_lecs();
count = pos; count = pos;
for(d=0;d<MAX_LEC_ITF;d++) { for(d = 0; d < MAX_LEC_ITF; d++) {
if (!dev_lec[d] || !(priv = dev = atm_lane_ops->get_lec(d);
(struct lec_priv *) dev_lec[d]->priv)) continue; if (!dev || !(priv = (struct lec_priv *) dev->priv))
for(i=0;i<LEC_ARP_TABLE_SIZE;i++) { continue;
entry = priv->lec_arp_tables[i]; spin_lock_irqsave(&priv->lec_arp_lock, flags);
for(;entry;entry=entry->next) { for(i = 0; i < LEC_ARP_TABLE_SIZE; i++) {
if (--count) continue; for(entry = priv->lec_arp_tables[i]; entry; entry = entry->next) {
e=sprintf(buf,"%s ", if (--count)
dev_lec[d]->name); continue;
lec_info(entry,buf+e); e = sprintf(buf,"%s ", dev->name);
lec_info(entry, buf+e);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dev_put(dev);
module_put(atm_lane_ops->owner);
return strlen(buf); return strlen(buf);
} }
} }
for(entry=priv->lec_arp_empty_ones; entry; for(entry = priv->lec_arp_empty_ones; entry; entry = entry->next) {
entry=entry->next) { if (--count)
if (--count) continue; continue;
e=sprintf(buf,"%s ",dev_lec[d]->name); e = sprintf(buf,"%s ", dev->name);
lec_info(entry, buf+e); lec_info(entry, buf+e);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dev_put(dev);
module_put(atm_lane_ops->owner);
return strlen(buf); return strlen(buf);
} }
for(entry=priv->lec_no_forward; entry; for(entry = priv->lec_no_forward; entry; entry=entry->next) {
entry=entry->next) { if (--count)
if (--count) continue; continue;
e=sprintf(buf,"%s ",dev_lec[d]->name); e = sprintf(buf,"%s ", dev->name);
lec_info(entry, buf+e); lec_info(entry, buf+e);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dev_put(dev);
module_put(atm_lane_ops->owner);
return strlen(buf); return strlen(buf);
} }
for(entry=priv->mcast_fwds; entry; for(entry = priv->mcast_fwds; entry; entry = entry->next) {
entry=entry->next) { if (--count)
if (--count) continue; continue;
e=sprintf(buf,"%s ",dev_lec[d]->name); e = sprintf(buf,"%s ", dev->name);
lec_info(entry, buf+e); lec_info(entry, buf+e);
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dev_put(dev);
module_put(atm_lane_ops->owner);
return strlen(buf); return strlen(buf);
} }
spin_unlock_irqrestore(&priv->lec_arp_lock, flags);
dev_put(dev);
} }
module_put(atm_lane_ops->owner);
return 0; return 0;
} }
#endif #endif
......
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