Freezer: make kernel threads nonfreezable by default
[safe/jmp/linux-2.6] / net / bluetooth / bnep / core.c
index d908d49..1f78c3e 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
    BNEP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2001-2002 Inventel Systemes
    Written 2001-2002 by
    BNEP implementation for Linux Bluetooth stack (BlueZ).
    Copyright (C) 2001-2002 Inventel Systemes
    Written 2001-2002 by
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
-   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 
-   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
-   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
+   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 
-   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 
+   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
    SOFTWARE IS DISCLAIMED.
 */
 
 /*
  * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $
    SOFTWARE IS DISCLAIMED.
 */
 
 /*
  * $Id: core.c,v 1.20 2002/08/04 21:23:58 maxk Exp $
- */ 
+ */
 
 
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -37,8 +36,8 @@
 #include <linux/signal.h>
 #include <linux/init.h>
 #include <linux/wait.h>
 #include <linux/signal.h>
 #include <linux/init.h>
 #include <linux/wait.h>
+#include <linux/freezer.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
-#include <linux/smp_lock.h>
 #include <linux/net.h>
 #include <net/sock.h>
 
 #include <linux/net.h>
 #include <net/sock.h>
 
@@ -52,6 +51,7 @@
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
 #include <asm/unaligned.h>
 
 #include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/l2cap.h>
 
 #include "bnep.h"
 #include <net/bluetooth/l2cap.h>
 
 #include "bnep.h"
@@ -74,7 +74,7 @@ static struct bnep_session *__bnep_get_session(u8 *dst)
        BT_DBG("");
 
        list_for_each(p, &bnep_session_list) {
        BT_DBG("");
 
        list_for_each(p, &bnep_session_list) {
-               s = list_entry(p, struct bnep_session, list);   
+               s = list_entry(p, struct bnep_session, list);
                if (!compare_ether_addr(dst, s->eh.h_source))
                        return s;
        }
                if (!compare_ether_addr(dst, s->eh.h_source))
                        return s;
        }
@@ -87,7 +87,7 @@ static void __bnep_link_session(struct bnep_session *s)
           by the socket layer which has to hold the refference to this module.
         */
        __module_get(THIS_MODULE);
           by the socket layer which has to hold the refference to this module.
         */
        __module_get(THIS_MODULE);
-       list_add(&s->list, &bnep_session_list); 
+       list_add(&s->list, &bnep_session_list);
 }
 
 static void __bnep_unlink_session(struct bnep_session *s)
 }
 
 static void __bnep_unlink_session(struct bnep_session *s)
@@ -117,18 +117,18 @@ static int bnep_send_rsp(struct bnep_session *s, u8 ctrl, u16 resp)
 static inline void bnep_set_default_proto_filter(struct bnep_session *s)
 {
        /* (IPv4, ARP)  */
 static inline void bnep_set_default_proto_filter(struct bnep_session *s)
 {
        /* (IPv4, ARP)  */
-       s->proto_filter[0].start = htons(0x0800);
-       s->proto_filter[0].end   = htons(0x0806);
+       s->proto_filter[0].start = ETH_P_IP;
+       s->proto_filter[0].end   = ETH_P_ARP;
        /* (RARP, AppleTalk) */
        /* (RARP, AppleTalk) */
-       s->proto_filter[1].start = htons(0x8035);
-       s->proto_filter[1].end   = htons(0x80F3);
+       s->proto_filter[1].start = ETH_P_RARP;
+       s->proto_filter[1].end   = ETH_P_AARP;
        /* (IPX, IPv6) */
        /* (IPX, IPv6) */
-       s->proto_filter[2].start = htons(0x8137);
-       s->proto_filter[2].end   = htons(0x86DD);
+       s->proto_filter[2].start = ETH_P_IPX;
+       s->proto_filter[2].end   = ETH_P_IPV6;
 }
 #endif
 
 }
 #endif
 
-static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
+static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len)
 {
        int n;
 
 {
        int n;
 
@@ -150,8 +150,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, u16 *data, int len)
                int i;
 
                for (i = 0; i < n; i++) {
                int i;
 
                for (i = 0; i < n; i++) {
-                       f[i].start = get_unaligned(data++);
-                       f[i].end   = get_unaligned(data++);
+                       f[i].start = ntohs(get_unaligned(data++));
+                       f[i].end   = ntohs(get_unaligned(data++));
 
                        BT_DBG("proto filter start %d end %d",
                                f[i].start, f[i].end);
 
                        BT_DBG("proto filter start %d end %d",
                                f[i].start, f[i].end);
@@ -180,7 +180,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
        if (len < 2)
                return -EILSEQ;
 
        if (len < 2)
                return -EILSEQ;
 
-       n = ntohs(get_unaligned((u16 *) data)); 
+       n = ntohs(get_unaligned((__be16 *) data));
        data += 2; len -= 2;
 
        if (len < n)
        data += 2; len -= 2;
 
        if (len < n)
@@ -203,7 +203,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
 
                        memcpy(a1, data, ETH_ALEN); data += ETH_ALEN;
                        a2 = data; data += ETH_ALEN;
 
                        memcpy(a1, data, ETH_ALEN); data += ETH_ALEN;
                        a2 = data; data += ETH_ALEN;
-       
+
                        BT_DBG("mc filter %s -> %s",
                                batostr((void *) a1), batostr((void *) a2));
 
                        BT_DBG("mc filter %s -> %s",
                                batostr((void *) a1), batostr((void *) a2));
 
@@ -277,7 +277,7 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
                }
 
                BT_DBG("type 0x%x len %d", h->type, h->len);
                }
 
                BT_DBG("type 0x%x len %d", h->type, h->len);
-       
+
                switch (h->type & BNEP_TYPE_MASK) {
                case BNEP_EXT_CONTROL:
                        bnep_rx_control(s, skb->data, skb->len);
                switch (h->type & BNEP_TYPE_MASK) {
                case BNEP_EXT_CONTROL:
                        bnep_rx_control(s, skb->data, skb->len);
@@ -293,7 +293,7 @@ static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
                        break;
                }
        } while (!err && (h->type & BNEP_EXT_HEADER));
                        break;
                }
        } while (!err && (h->type & BNEP_EXT_HEADER));
-       
+
        return err;
 }
 
        return err;
 }
 
@@ -319,20 +319,20 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
 
        if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
                goto badframe;
 
        if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
                goto badframe;
-       
+
        if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
                bnep_rx_control(s, skb->data, skb->len);
                kfree_skb(skb);
                return 0;
        }
 
        if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
                bnep_rx_control(s, skb->data, skb->len);
                kfree_skb(skb);
                return 0;
        }
 
-       skb->mac.raw = skb->data;
+       skb_reset_mac_header(skb);
 
        /* Verify and pull out header */
        if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
                goto badframe;
 
 
        /* Verify and pull out header */
        if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
                goto badframe;
 
-       s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
+       s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
 
        if (type & BNEP_EXT_HEADER) {
                if (bnep_rx_extension(s, skb) < 0)
 
        if (type & BNEP_EXT_HEADER) {
                if (bnep_rx_extension(s, skb) < 0)
@@ -343,9 +343,9 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
        if (ntohs(s->eh.h_proto) == 0x8100) {
                if (!skb_pull(skb, 4))
                        goto badframe;
        if (ntohs(s->eh.h_proto) == 0x8100) {
                if (!skb_pull(skb, 4))
                        goto badframe;
-               s->eh.h_proto = get_unaligned((u16 *) (skb->data - 2));
+               s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
        }
        }
-       
+
        /* We have to alloc new skb and copy data here :(. Because original skb
         * may not be modified and because of the alignment requirements. */
        nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
        /* We have to alloc new skb and copy data here :(. Because original skb
         * may not be modified and because of the alignment requirements. */
        nskb = alloc_skb(2 + ETH_HLEN + skb->len, GFP_KERNEL);
@@ -361,29 +361,31 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
        case BNEP_COMPRESSED:
                memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
                break;
        case BNEP_COMPRESSED:
                memcpy(__skb_put(nskb, ETH_HLEN), &s->eh, ETH_HLEN);
                break;
-       
+
        case BNEP_COMPRESSED_SRC_ONLY:
                memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
        case BNEP_COMPRESSED_SRC_ONLY:
                memcpy(__skb_put(nskb, ETH_ALEN), s->eh.h_dest, ETH_ALEN);
-               memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
-               put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
+               memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb), ETH_ALEN);
+               put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
                break;
 
        case BNEP_COMPRESSED_DST_ONLY:
                break;
 
        case BNEP_COMPRESSED_DST_ONLY:
-               memcpy(__skb_put(nskb, ETH_ALEN), skb->mac.raw, ETH_ALEN);
-               memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source, ETH_ALEN + 2);
+               memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb),
+                      ETH_ALEN);
+               memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source,
+                      ETH_ALEN + 2);
                break;
 
        case BNEP_GENERAL:
                break;
 
        case BNEP_GENERAL:
-               memcpy(__skb_put(nskb, ETH_ALEN * 2), skb->mac.raw, ETH_ALEN * 2);
-               put_unaligned(s->eh.h_proto, (u16 *) __skb_put(nskb, 2));
+               memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb),
+                      ETH_ALEN * 2);
+               put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
                break;
        }
 
                break;
        }
 
-       memcpy(__skb_put(nskb, skb->len), skb->data, skb->len);
+       skb_copy_from_linear_data(skb, __skb_put(nskb, skb->len), skb->len);
        kfree_skb(skb);
        kfree_skb(skb);
-       
+
        s->stats.rx_packets++;
        s->stats.rx_packets++;
-       nskb->dev       = dev;
        nskb->ip_summed = CHECKSUM_NONE;
        nskb->protocol  = eth_type_trans(nskb, dev);
        netif_rx_ni(nskb);
        nskb->ip_summed = CHECKSUM_NONE;
        nskb->protocol  = eth_type_trans(nskb, dev);
        netif_rx_ni(nskb);
@@ -435,7 +437,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
                iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
                len += ETH_ALEN;
                break;
                iv[il++] = (struct kvec) { eh->h_source, ETH_ALEN };
                len += ETH_ALEN;
                break;
-               
+
        case BNEP_COMPRESSED_DST_ONLY:
                iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
                len += ETH_ALEN;
        case BNEP_COMPRESSED_DST_ONLY:
                iv[il++] = (struct kvec) { eh->h_dest, ETH_ALEN };
                len += ETH_ALEN;
@@ -445,7 +447,7 @@ static inline int bnep_tx_frame(struct bnep_session *s, struct sk_buff *skb)
 send:
        iv[il++] = (struct kvec) { skb->data, skb->len };
        len += skb->len;
 send:
        iv[il++] = (struct kvec) { skb->data, skb->len };
        len += skb->len;
-       
+
        /* FIXME: linearize skb */
        {
                len = kernel_sendmsg(sock, &s->msg, iv, il, len);
        /* FIXME: linearize skb */
        {
                len = kernel_sendmsg(sock, &s->msg, iv, il, len);
@@ -471,9 +473,8 @@ static int bnep_session(void *arg)
 
        BT_DBG("");
 
 
        BT_DBG("");
 
-        daemonize("kbnepd %s", dev->name);
+       daemonize("kbnepd %s", dev->name);
        set_user_nice(current, -15);
        set_user_nice(current, -15);
-       current->flags |= PF_NOFREEZE;
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(sk->sk_sleep, &wait);
 
        init_waitqueue_entry(&wait, current);
        add_wait_queue(sk->sk_sleep, &wait);
@@ -488,13 +489,13 @@ static int bnep_session(void *arg)
 
                if (sk->sk_state != BT_CONNECTED)
                        break;
 
                if (sk->sk_state != BT_CONNECTED)
                        break;
-       
+
                // TX
                while ((skb = skb_dequeue(&sk->sk_write_queue)))
                        if (bnep_tx_frame(s, skb))
                                break;
                netif_wake_queue(dev);
                // TX
                while ((skb = skb_dequeue(&sk->sk_write_queue)))
                        if (bnep_tx_frame(s, skb))
                                break;
                netif_wake_queue(dev);
-       
+
                schedule();
        }
        set_current_state(TASK_RUNNING);
                schedule();
        }
        set_current_state(TASK_RUNNING);
@@ -516,6 +517,24 @@ static int bnep_session(void *arg)
        return 0;
 }
 
        return 0;
 }
 
+static struct device *bnep_get_device(struct bnep_session *session)
+{
+       bdaddr_t *src = &bt_sk(session->sock->sk)->src;
+       bdaddr_t *dst = &bt_sk(session->sock->sk)->dst;
+       struct hci_dev *hdev;
+       struct hci_conn *conn;
+
+       hdev = hci_get_route(dst, src);
+       if (!hdev)
+               return NULL;
+
+       conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
+
+       hci_dev_put(hdev);
+
+       return conn ? &conn->dev : NULL;
+}
+
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 {
        struct net_device *dev;
 int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
 {
        struct net_device *dev;
@@ -535,7 +554,6 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        if (!dev)
                return -ENOMEM;
 
        if (!dev)
                return -ENOMEM;
 
-
        down_write(&bnep_session_sem);
 
        ss = __bnep_get_session(dst);
        down_write(&bnep_session_sem);
 
        ss = __bnep_get_session(dst);
@@ -552,11 +570,11 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        memcpy(s->eh.h_source, &dst, ETH_ALEN);
        memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
        memcpy(s->eh.h_source, &dst, ETH_ALEN);
        memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
 
-       s->dev = dev;
+       s->dev   = dev;
        s->sock  = sock;
        s->role  = req->role;
        s->state = BT_CONNECTED;
        s->sock  = sock;
        s->role  = req->role;
        s->state = BT_CONNECTED;
-       
+
        s->msg.msg_flags = MSG_NOSIGNAL;
 
 #ifdef CONFIG_BT_BNEP_MC_FILTER
        s->msg.msg_flags = MSG_NOSIGNAL;
 
 #ifdef CONFIG_BT_BNEP_MC_FILTER
@@ -569,13 +587,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
        bnep_set_default_proto_filter(s);
 #endif
 
        bnep_set_default_proto_filter(s);
 #endif
 
+       SET_NETDEV_DEV(dev, bnep_get_device(s));
+
        err = register_netdev(dev);
        if (err) {
                goto failed;
        }
 
        __bnep_link_session(s);
        err = register_netdev(dev);
        if (err) {
                goto failed;
        }
 
        __bnep_link_session(s);
-       
+
        err = kernel_thread(bnep_session, s, CLONE_KERNEL);
        if (err < 0) {
                /* Session thread start failed, gotta cleanup. */
        err = kernel_thread(bnep_session, s, CLONE_KERNEL);
        if (err < 0) {
                /* Session thread start failed, gotta cleanup. */
@@ -608,7 +628,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
                /* Wakeup user-space which is polling for socket errors.
                 * This is temporary hack untill we have shutdown in L2CAP */
                s->sock->sk->sk_err = EUNATCH;
                /* Wakeup user-space which is polling for socket errors.
                 * This is temporary hack untill we have shutdown in L2CAP */
                s->sock->sk->sk_err = EUNATCH;
-               
+
                /* Kill session thread */
                atomic_inc(&s->killed);
                wake_up_interruptible(s->sock->sk->sk_sleep);
                /* Kill session thread */
                atomic_inc(&s->killed);
                wake_up_interruptible(s->sock->sk->sk_sleep);
@@ -642,7 +662,7 @@ int bnep_get_connlist(struct bnep_connlist_req *req)
                s = list_entry(p, struct bnep_session, list);
 
                __bnep_copy_ci(&ci, s);
                s = list_entry(p, struct bnep_session, list);
 
                __bnep_copy_ci(&ci, s);
-               
+
                if (copy_to_user(req->ci, &ci, sizeof(ci))) {
                        err = -EFAULT;
                        break;
                if (copy_to_user(req->ci, &ci, sizeof(ci))) {
                        err = -EFAULT;
                        break;
@@ -677,7 +697,7 @@ int bnep_get_conninfo(struct bnep_conninfo *ci)
 }
 
 static int __init bnep_init(void)
 }
 
 static int __init bnep_init(void)
-{      
+{
        char flt[50] = "";
 
        l2cap_load();
        char flt[50] = "";
 
        l2cap_load();