X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fllc%2Fllc_core.c;h=bd242a49514add8e1d9a128b937904389e065dbc;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=e1140375e66584c290359432e00675f848790b9a;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index e1140375e..bd242a495 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -22,7 +22,7 @@ #include LIST_HEAD(llc_sap_list); -rwlock_t llc_sap_list_lock = RW_LOCK_UNLOCKED; +DEFINE_RWLOCK(llc_sap_list_lock); unsigned char llc_station_mac_sa[ETH_ALEN]; @@ -31,7 +31,7 @@ unsigned char llc_station_mac_sa[ETH_ALEN]; * * Allocates and initializes sap. */ -struct llc_sap *llc_sap_alloc(void) +static struct llc_sap *llc_sap_alloc(void) { struct llc_sap *sap = kmalloc(sizeof(*sap), GFP_ATOMIC); @@ -40,6 +40,7 @@ struct llc_sap *llc_sap_alloc(void) sap->state = LLC_SAP_STATE_ACTIVE; memcpy(sap->laddr.mac, llc_station_mac_sa, ETH_ALEN); rwlock_init(&sap->sk_list.lock); + atomic_set(&sap->refcnt, 1); } return sap; } @@ -50,11 +51,9 @@ struct llc_sap *llc_sap_alloc(void) * * Adds a sap to the LLC's station sap list. */ -void llc_add_sap(struct llc_sap *sap) +static void llc_add_sap(struct llc_sap *sap) { - write_lock_bh(&llc_sap_list_lock); list_add_tail(&sap->node, &llc_sap_list); - write_unlock_bh(&llc_sap_list_lock); } /** @@ -63,18 +62,32 @@ void llc_add_sap(struct llc_sap *sap) * * Removes a sap to the LLC's station sap list. */ -void llc_del_sap(struct llc_sap *sap) +static void llc_del_sap(struct llc_sap *sap) { write_lock_bh(&llc_sap_list_lock); list_del(&sap->node); write_unlock_bh(&llc_sap_list_lock); } +static struct llc_sap *__llc_sap_find(unsigned char sap_value) +{ + struct llc_sap* sap; + + list_for_each_entry(sap, &llc_sap_list, node) + if (sap->laddr.lsap == sap_value) + goto out; + sap = NULL; +out: + return sap; +} + /** * llc_sap_find - searchs a SAP in station * @sap_value: sap to be found * * Searchs for a sap in the sap list of the LLC's station upon the sap ID. + * If the sap is found it will be refcounted and the user will have to do + * a llc_sap_put after use. * Returns the sap or %NULL if not found. */ struct llc_sap *llc_sap_find(unsigned char sap_value) @@ -82,11 +95,9 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) struct llc_sap* sap; read_lock_bh(&llc_sap_list_lock); - list_for_each_entry(sap, &llc_sap_list, node) - if (sap->laddr.lsap == sap_value) - goto out; - sap = NULL; -out: + sap = __llc_sap_find(sap_value); + if (sap) + llc_sap_hold(sap); read_unlock_bh(&llc_sap_list_lock); return sap; } @@ -103,14 +114,14 @@ out: struct llc_sap *llc_sap_open(unsigned char lsap, int (*func)(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt)) + struct packet_type *pt, + struct net_device *orig_dev)) { - struct llc_sap *sap = llc_sap_find(lsap); + struct llc_sap *sap = NULL; - if (sap) { /* SAP already exists */ - sap = NULL; + write_lock_bh(&llc_sap_list_lock); + if (__llc_sap_find(lsap)) /* SAP already exists */ goto out; - } sap = llc_sap_alloc(); if (!sap) goto out; @@ -118,6 +129,7 @@ struct llc_sap *llc_sap_open(unsigned char lsap, sap->rcv_func = func; llc_add_sap(sap); out: + write_unlock_bh(&llc_sap_list_lock); return sap; }