Skip to content

Commit

Permalink
Bluetooth: Split sending for HCI raw and control sockets
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
holtmann authored and Johan Hedberg committed Feb 20, 2012
1 parent 48c7aba commit 470fe1b
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 18 deletions.
4 changes: 2 additions & 2 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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)) {
Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
51 changes: 39 additions & 12 deletions net/bluetooth/hci_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,35 +85,29 @@ 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;

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;

/* Don't send frame to the socket it came from */
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;

Expand All @@ -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);
}

Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 470fe1b

Please sign in to comment.