Merge ../linux-2.6-watchdog-mm
[pandora-kernel.git] / net / ax25 / ax25_iface.c
index 3bb1527..aff3e65 100644 (file)
@@ -6,7 +6,6 @@
  *
  * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
  */
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-static struct protocol_struct {
-       struct protocol_struct *next;
-       unsigned int pid;
-       int (*func)(struct sk_buff *, ax25_cb *);
-} *protocol_list = NULL;
+static struct ax25_protocol *protocol_list;
 static DEFINE_RWLOCK(protocol_list_lock);
 
-static struct linkfail_struct {
-       struct linkfail_struct *next;
-       void (*func)(ax25_cb *, int);
-} *linkfail_list = NULL;
+static HLIST_HEAD(ax25_linkfail_list);
 static DEFINE_SPINLOCK(linkfail_lock);
 
 static struct listen_struct {
@@ -50,47 +42,34 @@ static struct listen_struct {
 } *listen_list = NULL;
 static DEFINE_SPINLOCK(listen_lock);
 
-int ax25_protocol_register(unsigned int pid,
-       int (*func)(struct sk_buff *, ax25_cb *))
+/*
+ * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT,
+ * AX25_P_IP or AX25_P_ARP ...
+ */
+void ax25_register_pid(struct ax25_protocol *ap)
 {
-       struct protocol_struct *protocol;
-
-       if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT)
-               return 0;
-#ifdef CONFIG_INET
-       if (pid == AX25_P_IP || pid == AX25_P_ARP)
-               return 0;
-#endif
-       if ((protocol = kmalloc(sizeof(*protocol), GFP_ATOMIC)) == NULL)
-               return 0;
-
-       protocol->pid  = pid;
-       protocol->func = func;
-
-       write_lock(&protocol_list_lock);
-       protocol->next = protocol_list;
-       protocol_list  = protocol;
-       write_unlock(&protocol_list_lock);
-
-       return 1;
+       write_lock_bh(&protocol_list_lock);
+       ap->next = protocol_list;
+       protocol_list = ap;
+       write_unlock_bh(&protocol_list_lock);
 }
 
-EXPORT_SYMBOL(ax25_protocol_register);
+EXPORT_SYMBOL_GPL(ax25_register_pid);
 
 void ax25_protocol_release(unsigned int pid)
 {
-       struct protocol_struct *s, *protocol;
+       struct ax25_protocol *s, *protocol;
 
-       write_lock(&protocol_list_lock);
+       write_lock_bh(&protocol_list_lock);
        protocol = protocol_list;
        if (protocol == NULL) {
-               write_unlock(&protocol_list_lock);
+               write_unlock_bh(&protocol_list_lock);
                return;
        }
 
        if (protocol->pid == pid) {
                protocol_list = protocol->next;
-               write_unlock(&protocol_list_lock);
+               write_unlock_bh(&protocol_list_lock);
                kfree(protocol);
                return;
        }
@@ -99,66 +78,31 @@ void ax25_protocol_release(unsigned int pid)
                if (protocol->next->pid == pid) {
                        s = protocol->next;
                        protocol->next = protocol->next->next;
-                       write_unlock(&protocol_list_lock);
+                       write_unlock_bh(&protocol_list_lock);
                        kfree(s);
                        return;
                }
 
                protocol = protocol->next;
        }
-       write_unlock(&protocol_list_lock);
+       write_unlock_bh(&protocol_list_lock);
 }
 
 EXPORT_SYMBOL(ax25_protocol_release);
 
-int ax25_linkfail_register(void (*func)(ax25_cb *, int))
+void ax25_linkfail_register(struct ax25_linkfail *lf)
 {
-       struct linkfail_struct *linkfail;
-
-       if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL)
-               return 0;
-
-       linkfail->func = func;
-
        spin_lock_bh(&linkfail_lock);
-       linkfail->next = linkfail_list;
-       linkfail_list  = linkfail;
+       hlist_add_head(&lf->lf_node, &ax25_linkfail_list);
        spin_unlock_bh(&linkfail_lock);
-
-       return 1;
 }
 
 EXPORT_SYMBOL(ax25_linkfail_register);
 
-void ax25_linkfail_release(void (*func)(ax25_cb *, int))
+void ax25_linkfail_release(struct ax25_linkfail *lf)
 {
-       struct linkfail_struct *s, *linkfail;
-
        spin_lock_bh(&linkfail_lock);
-       linkfail = linkfail_list;
-       if (linkfail == NULL) {
-               spin_unlock_bh(&linkfail_lock);
-               return;
-       }
-
-       if (linkfail->func == func) {
-               linkfail_list = linkfail->next;
-               spin_unlock_bh(&linkfail_lock);
-               kfree(linkfail);
-               return;
-       }
-
-       while (linkfail != NULL && linkfail->next != NULL) {
-               if (linkfail->next->func == func) {
-                       s = linkfail->next;
-                       linkfail->next = linkfail->next->next;
-                       spin_unlock_bh(&linkfail_lock);
-                       kfree(s);
-                       return;
-               }
-
-               linkfail = linkfail->next;
-       }
+       hlist_del_init(&lf->lf_node);
        spin_unlock_bh(&linkfail_lock);
 }
 
@@ -172,7 +116,7 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
                return 0;
 
        if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL)
-               return 0;
+               return -ENOMEM;
 
        listen->callsign = *callsign;
        listen->dev      = dev;
@@ -182,7 +126,7 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev)
        listen_list  = listen;
        spin_unlock_bh(&listen_lock);
 
-       return 1;
+       return 0;
 }
 
 EXPORT_SYMBOL(ax25_listen_register);
@@ -224,7 +168,7 @@ EXPORT_SYMBOL(ax25_listen_release);
 int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *)
 {
        int (*res)(struct sk_buff *, ax25_cb *) = NULL;
-       struct protocol_struct *protocol;
+       struct ax25_protocol *protocol;
 
        read_lock(&protocol_list_lock);
        for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
@@ -243,7 +187,8 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
 
        spin_lock_bh(&listen_lock);
        for (listen = listen_list; listen != NULL; listen = listen->next)
-               if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL)) {
+               if (ax25cmp(&listen->callsign, callsign) == 0 &&
+                   (listen->dev == dev || listen->dev == NULL)) {
                        spin_unlock_bh(&listen_lock);
                        return 1;
        }
@@ -254,26 +199,27 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev)
 
 void ax25_link_failed(ax25_cb *ax25, int reason)
 {
-       struct linkfail_struct *linkfail;
+       struct ax25_linkfail *lf;
+       struct hlist_node *node;
 
        spin_lock_bh(&linkfail_lock);
-       for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next)
-               (linkfail->func)(ax25, reason);
+       hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node)
+               lf->func(ax25, reason);
        spin_unlock_bh(&linkfail_lock);
 }
 
 int ax25_protocol_is_registered(unsigned int pid)
 {
-       struct protocol_struct *protocol;
+       struct ax25_protocol *protocol;
        int res = 0;
 
-       read_lock(&protocol_list_lock);
+       read_lock_bh(&protocol_list_lock);
        for (protocol = protocol_list; protocol != NULL; protocol = protocol->next)
                if (protocol->pid == pid) {
                        res = 1;
                        break;
                }
-       read_unlock(&protocol_list_lock);
+       read_unlock_bh(&protocol_list_lock);
 
        return res;
 }