Skip to content

Commit

Permalink
Bluetooth: Make hci_send_acl() void
Browse files Browse the repository at this point in the history
hci_send_acl can't fail, so we can make it void. This patch changes
that and all the funcions that use hci_send_acl().
That change exposed a bug on sending connectionless data. We were not
reporting the lenght send back to the user space.

Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
Reviewed-by: João Paulo Rechi Vita <jprvita@profusion.mobi>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
  • Loading branch information
Gustavo F. Padovan authored and Marcel Holtmann committed May 10, 2010
1 parent ff12fd6 commit 9a9c6a3
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 49 deletions.
2 changes: 1 addition & 1 deletion include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ int hci_register_notifier(struct notifier_block *nb);
int hci_unregister_notifier(struct notifier_block *nb);

int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);

void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
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 @@ -1260,7 +1260,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
hdr->dlen = cpu_to_le16(len);
}

int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
{
struct hci_dev *hdev = conn->hdev;
struct sk_buff *list;
Expand Down Expand Up @@ -1303,7 +1303,7 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)

tasklet_schedule(&hdev->tx_task);

return 0;
return;
}
EXPORT_SYMBOL(hci_send_acl);

Expand Down
73 changes: 27 additions & 46 deletions net/bluetooth/l2cap.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,19 +330,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
return id;
}

static inline int l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
static inline void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data)
{
struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);

BT_DBG("code 0x%2.2x", code);

if (!skb)
return -ENOMEM;
return;

return hci_send_acl(conn->hcon, skb, 0);
hci_send_acl(conn->hcon, skb, 0);
}

static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
static inline void l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
{
struct sk_buff *skb;
struct l2cap_hdr *lh;
Expand All @@ -369,7 +369,7 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)

skb = bt_skb_alloc(count, GFP_ATOMIC);
if (!skb)
return -ENOMEM;
return;

lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
Expand All @@ -381,10 +381,10 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
put_unaligned_le16(fcs, skb_put(skb, 2));
}

return hci_send_acl(pi->conn->hcon, skb, 0);
hci_send_acl(pi->conn->hcon, skb, 0);
}

static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
static inline void l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)
{
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY)
control |= L2CAP_SUPER_RCV_NOT_READY;
Expand All @@ -393,7 +393,7 @@ static inline int l2cap_send_rr_or_rnr(struct l2cap_pinfo *pi, u16 control)

control |= pi->buffer_seq << L2CAP_CTRL_REQSEQ_SHIFT;

return l2cap_send_sframe(pi, control);
l2cap_send_sframe(pi, control);
}

static void l2cap_do_start(struct sock *sk)
Expand Down Expand Up @@ -1289,26 +1289,20 @@ static void l2cap_drop_acked_frames(struct sock *sk)
return;
}

static inline int l2cap_do_send(struct sock *sk, struct sk_buff *skb)
static inline void l2cap_do_send(struct sock *sk, struct sk_buff *skb)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
int err;

BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);

err = hci_send_acl(pi->conn->hcon, skb, 0);
if (err < 0)
kfree_skb(skb);

return err;
hci_send_acl(pi->conn->hcon, skb, 0);
}

static int l2cap_streaming_send(struct sock *sk)
{
struct sk_buff *skb, *tx_skb;
struct l2cap_pinfo *pi = l2cap_pi(sk);
u16 control, fcs;
int err;

while ((skb = sk->sk_send_head)) {
tx_skb = skb_clone(skb, GFP_ATOMIC);
Expand All @@ -1322,11 +1316,7 @@ static int l2cap_streaming_send(struct sock *sk)
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
}

err = l2cap_do_send(sk, tx_skb);
if (err < 0) {
l2cap_send_disconn_req(pi->conn, sk);
return err;
}
l2cap_do_send(sk, tx_skb);

pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;

Expand All @@ -1346,7 +1336,6 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct sk_buff *skb, *tx_skb;
u16 control, fcs;
int err;

skb = skb_peek(TX_QUEUE(sk));
do {
Expand Down Expand Up @@ -1375,11 +1364,7 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
}

err = l2cap_do_send(sk, tx_skb);
if (err < 0) {
l2cap_send_disconn_req(pi->conn, sk);
return err;
}
l2cap_do_send(sk, tx_skb);
break;
} while(1);
return 0;
Expand All @@ -1390,7 +1375,7 @@ static int l2cap_ertm_send(struct sock *sk)
struct sk_buff *skb, *tx_skb;
struct l2cap_pinfo *pi = l2cap_pi(sk);
u16 control, fcs;
int err, nsent = 0;
int nsent = 0;

if (pi->conn_state & L2CAP_CONN_WAIT_F)
return 0;
Expand Down Expand Up @@ -1423,11 +1408,8 @@ static int l2cap_ertm_send(struct sock *sk)
put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
}

err = l2cap_do_send(sk, tx_skb);
if (err < 0) {
l2cap_send_disconn_req(pi->conn, sk);
return err;
}
l2cap_do_send(sk, tx_skb);

__mod_retrans_timer();

bt_cb(skb)->tx_seq = pi->next_tx_seq;
Expand All @@ -1447,7 +1429,7 @@ static int l2cap_ertm_send(struct sock *sk)
return nsent;
}

static int l2cap_send_ack(struct l2cap_pinfo *pi)
static void l2cap_send_ack(struct l2cap_pinfo *pi)
{
struct sock *sk = (struct sock *)pi;
u16 control = 0;
Expand All @@ -1456,15 +1438,15 @@ static int l2cap_send_ack(struct l2cap_pinfo *pi)

if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
control |= L2CAP_SUPER_RCV_NOT_READY;
return l2cap_send_sframe(pi, control);
l2cap_send_sframe(pi, control);
return;
} else if (l2cap_ertm_send(sk) == 0) {
control |= L2CAP_SUPER_RCV_READY;
return l2cap_send_sframe(pi, control);
l2cap_send_sframe(pi, control);
}
return 0;
}

static int l2cap_send_srejtail(struct sock *sk)
static void l2cap_send_srejtail(struct sock *sk)
{
struct srej_list *tail;
u16 control;
Expand All @@ -1476,8 +1458,6 @@ static int l2cap_send_srejtail(struct sock *sk)
control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;

l2cap_send_sframe(l2cap_pi(sk), control);

return 0;
}

static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
Expand Down Expand Up @@ -1687,10 +1667,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
/* Connectionless channel */
if (sk->sk_type == SOCK_DGRAM) {
skb = l2cap_create_connless_pdu(sk, msg, len);
if (IS_ERR(skb))
if (IS_ERR(skb)) {
err = PTR_ERR(skb);
else
err = l2cap_do_send(sk, skb);
} else {
l2cap_do_send(sk, skb);
err = len;
}
goto done;
}

Expand All @@ -1709,9 +1691,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
goto done;
}

err = l2cap_do_send(sk, skb);
if (!err)
err = len;
l2cap_do_send(sk, skb);
err = len;
break;

case L2CAP_MODE_ERTM:
Expand Down

0 comments on commit 9a9c6a3

Please sign in to comment.