]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Bluetooth: Split sending for HCI raw and control sockets
authorMarcel Holtmann <marcel@holtmann.org>
Mon, 20 Feb 2012 13:50:30 +0000 (14:50 +0100)
committerJohan Hedberg <johan.hedberg@intel.com>
Mon, 20 Feb 2012 13:55:11 +0000 (15:55 +0200)
The sending functions for HCI raw and control sockets have nothing in
common except that they iterate over the socket list. Split them into
two so they can do their job more efficient. In addition the code becomes
more readable.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sock.c
net/bluetooth/mgmt.c

index 2aafeb3a879365f29b2798328e3cc16f6c805688..9209e4c8a211c6c36939fafe9729acd7dff0073c 100644 (file)
@@ -953,8 +953,8 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
 void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
 
 /* ----- HCI Sockets ----- */
-void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
-                                                       struct sock *skip_sk);
+void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb);
+void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk);
 
 /* Management interface */
 #define MGMT_ADDR_BREDR                        0x00
index fabca080ae704994b720ae9f33d01c5cad7d9c42..638fa8c393d896fab9affede48634be966106077 100644 (file)
@@ -2131,7 +2131,7 @@ static int hci_send_frame(struct sk_buff *skb)
                /* Time stamp */
                __net_timestamp(skb);
 
-               hci_send_to_sock(hdev, skb, NULL);
+               hci_send_to_sock(hdev, skb);
        }
 
        /* Get rid of skb owner, prior to sending to the driver. */
@@ -2818,7 +2818,7 @@ static void hci_rx_work(struct work_struct *work)
        while ((skb = skb_dequeue(&hdev->rx_q))) {
                if (atomic_read(&hdev->promisc)) {
                        /* Send copy to the sockets */
-                       hci_send_to_sock(hdev, skb, NULL);
+                       hci_send_to_sock(hdev, skb);
                }
 
                if (test_bit(HCI_RAW, &hdev->flags)) {
index 04fb1f02dfcca80cff400ddf9bcfc347b1278bd8..e69db4a7b3ef6589775d703adaa7dffb14c245ab 100644 (file)
@@ -3571,7 +3571,7 @@ void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data)
 
        bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
        skb->dev = (void *) hdev;
-       hci_send_to_sock(hdev, skb, NULL);
+       hci_send_to_sock(hdev, skb);
        kfree_skb(skb);
 }
 
index 9e854d9fb4607a9e46e196439920476b1ecda8ed..b5b3bc8d28489af10eafcdea76b0768badd98cf5 100644 (file)
@@ -85,8 +85,7 @@ static struct bt_sock_list hci_sk_list = {
 };
 
 /* Send frame to RAW socket */
-void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
-                                                       struct sock *skip_sk)
+void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct sock *sk;
        struct hlist_node *node;
@@ -94,13 +93,11 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
        BT_DBG("hdev %p len %d", hdev, skb->len);
 
        read_lock(&hci_sk_list.lock);
+
        sk_for_each(sk, node, &hci_sk_list.head) {
                struct hci_filter *flt;
                struct sk_buff *nskb;
 
-               if (sk == skip_sk)
-                       continue;
-
                if (sk->sk_state != BT_BOUND || hci_pi(sk)->hdev != hdev)
                        continue;
 
@@ -108,12 +105,9 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
                if (skb->sk == sk)
                        continue;
 
-               if (bt_cb(skb)->channel != hci_pi(sk)->channel)
+               if (hci_pi(sk)->channel != HCI_CHANNEL_RAW)
                        continue;
 
-               if (bt_cb(skb)->channel == HCI_CHANNEL_CONTROL)
-                       goto clone;
-
                /* Apply filter */
                flt = &hci_pi(sk)->filter;
 
@@ -137,18 +131,51 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
                                continue;
                }
 
-clone:
                nskb = skb_clone(skb, GFP_ATOMIC);
                if (!nskb)
                        continue;
 
                /* Put type byte before the data */
-               if (bt_cb(skb)->channel == HCI_CHANNEL_RAW)
-                       memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
+               memcpy(skb_push(nskb, 1), &bt_cb(nskb)->pkt_type, 1);
+
+               if (sock_queue_rcv_skb(sk, nskb))
+                       kfree_skb(nskb);
+       }
+
+       read_unlock(&hci_sk_list.lock);
+}
+
+/* Send frame to control socket */
+void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk)
+{
+       struct sock *sk;
+       struct hlist_node *node;
+
+       BT_DBG("len %d", skb->len);
+
+       read_lock(&hci_sk_list.lock);
+
+       sk_for_each(sk, node, &hci_sk_list.head) {
+               struct sk_buff *nskb;
+
+               /* Skip the original socket */
+               if (sk == skip_sk)
+                       continue;
+
+               if (sk->sk_state != BT_BOUND)
+                       continue;
+
+               if (hci_pi(sk)->channel != HCI_CHANNEL_CONTROL)
+                       continue;
+
+               nskb = skb_clone(skb, GFP_ATOMIC);
+               if (!nskb)
+                       continue;
 
                if (sock_queue_rcv_skb(sk, nskb))
                        kfree_skb(nskb);
        }
+
        read_unlock(&hci_sk_list.lock);
 }
 
index 18d593f23934db7ca19e7c5fa31102dcec57ac27..1695d04d927d3291cde81ef9a0c200b2daf6467f 100644 (file)
@@ -924,7 +924,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data,
        if (data)
                memcpy(skb_put(skb, data_len), data, data_len);
 
-       hci_send_to_sock(NULL, skb, skip_sk);
+       hci_send_to_control(skb, skip_sk);
        kfree_skb(skb);
 
        return 0;