mirror of https://gitee.com/openkylin/linux.git
Bluetooth: Make hci_send_acl() void
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>
This commit is contained in:
parent
ff12fd6433
commit
9a9c6a3441
|
@ -636,7 +636,7 @@ int hci_register_notifier(struct notifier_block *nb);
|
||||||
int hci_unregister_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_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_send_sco(struct hci_conn *conn, struct sk_buff *skb);
|
||||||
|
|
||||||
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
|
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
|
||||||
|
|
|
@ -1260,7 +1260,7 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
|
||||||
hdr->dlen = cpu_to_le16(len);
|
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 hci_dev *hdev = conn->hdev;
|
||||||
struct sk_buff *list;
|
struct sk_buff *list;
|
||||||
|
@ -1303,7 +1303,7 @@ int hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
|
||||||
|
|
||||||
tasklet_schedule(&hdev->tx_task);
|
tasklet_schedule(&hdev->tx_task);
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(hci_send_acl);
|
EXPORT_SYMBOL(hci_send_acl);
|
||||||
|
|
||||||
|
|
|
@ -330,19 +330,19 @@ static inline u8 l2cap_get_ident(struct l2cap_conn *conn)
|
||||||
return id;
|
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);
|
struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data);
|
||||||
|
|
||||||
BT_DBG("code 0x%2.2x", code);
|
BT_DBG("code 0x%2.2x", code);
|
||||||
|
|
||||||
if (!skb)
|
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 sk_buff *skb;
|
||||||
struct l2cap_hdr *lh;
|
struct l2cap_hdr *lh;
|
||||||
|
@ -369,7 +369,7 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
|
||||||
|
|
||||||
skb = bt_skb_alloc(count, GFP_ATOMIC);
|
skb = bt_skb_alloc(count, GFP_ATOMIC);
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -ENOMEM;
|
return;
|
||||||
|
|
||||||
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
|
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
|
||||||
lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
|
lh->len = cpu_to_le16(hlen - L2CAP_HDR_SIZE);
|
||||||
|
@ -381,10 +381,10 @@ static inline int l2cap_send_sframe(struct l2cap_pinfo *pi, u16 control)
|
||||||
put_unaligned_le16(fcs, skb_put(skb, 2));
|
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)
|
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY)
|
||||||
control |= L2CAP_SUPER_RCV_NOT_READY;
|
control |= L2CAP_SUPER_RCV_NOT_READY;
|
||||||
|
@ -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;
|
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)
|
static void l2cap_do_start(struct sock *sk)
|
||||||
|
@ -1289,18 +1289,13 @@ static void l2cap_drop_acked_frames(struct sock *sk)
|
||||||
return;
|
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);
|
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
||||||
int err;
|
|
||||||
|
|
||||||
BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
|
BT_DBG("sk %p, skb %p len %d", sk, skb, skb->len);
|
||||||
|
|
||||||
err = hci_send_acl(pi->conn->hcon, skb, 0);
|
hci_send_acl(pi->conn->hcon, skb, 0);
|
||||||
if (err < 0)
|
|
||||||
kfree_skb(skb);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int l2cap_streaming_send(struct sock *sk)
|
static int l2cap_streaming_send(struct sock *sk)
|
||||||
|
@ -1308,7 +1303,6 @@ static int l2cap_streaming_send(struct sock *sk)
|
||||||
struct sk_buff *skb, *tx_skb;
|
struct sk_buff *skb, *tx_skb;
|
||||||
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
||||||
u16 control, fcs;
|
u16 control, fcs;
|
||||||
int err;
|
|
||||||
|
|
||||||
while ((skb = sk->sk_send_head)) {
|
while ((skb = sk->sk_send_head)) {
|
||||||
tx_skb = skb_clone(skb, GFP_ATOMIC);
|
tx_skb = skb_clone(skb, GFP_ATOMIC);
|
||||||
|
@ -1322,11 +1316,7 @@ static int l2cap_streaming_send(struct sock *sk)
|
||||||
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
|
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l2cap_do_send(sk, tx_skb);
|
l2cap_do_send(sk, tx_skb);
|
||||||
if (err < 0) {
|
|
||||||
l2cap_send_disconn_req(pi->conn, sk);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
|
pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
|
||||||
|
|
||||||
|
@ -1346,7 +1336,6 @@ static int l2cap_retransmit_frame(struct sock *sk, u8 tx_seq)
|
||||||
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
||||||
struct sk_buff *skb, *tx_skb;
|
struct sk_buff *skb, *tx_skb;
|
||||||
u16 control, fcs;
|
u16 control, fcs;
|
||||||
int err;
|
|
||||||
|
|
||||||
skb = skb_peek(TX_QUEUE(sk));
|
skb = skb_peek(TX_QUEUE(sk));
|
||||||
do {
|
do {
|
||||||
|
@ -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);
|
put_unaligned_le16(fcs, tx_skb->data + tx_skb->len - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l2cap_do_send(sk, tx_skb);
|
l2cap_do_send(sk, tx_skb);
|
||||||
if (err < 0) {
|
|
||||||
l2cap_send_disconn_req(pi->conn, sk);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
} while(1);
|
} while(1);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1390,7 +1375,7 @@ static int l2cap_ertm_send(struct sock *sk)
|
||||||
struct sk_buff *skb, *tx_skb;
|
struct sk_buff *skb, *tx_skb;
|
||||||
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
struct l2cap_pinfo *pi = l2cap_pi(sk);
|
||||||
u16 control, fcs;
|
u16 control, fcs;
|
||||||
int err, nsent = 0;
|
int nsent = 0;
|
||||||
|
|
||||||
if (pi->conn_state & L2CAP_CONN_WAIT_F)
|
if (pi->conn_state & L2CAP_CONN_WAIT_F)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1423,11 +1408,8 @@ static int l2cap_ertm_send(struct sock *sk)
|
||||||
put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
|
put_unaligned_le16(fcs, skb->data + tx_skb->len - 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l2cap_do_send(sk, tx_skb);
|
l2cap_do_send(sk, tx_skb);
|
||||||
if (err < 0) {
|
|
||||||
l2cap_send_disconn_req(pi->conn, sk);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
__mod_retrans_timer();
|
__mod_retrans_timer();
|
||||||
|
|
||||||
bt_cb(skb)->tx_seq = pi->next_tx_seq;
|
bt_cb(skb)->tx_seq = pi->next_tx_seq;
|
||||||
|
@ -1447,7 +1429,7 @@ static int l2cap_ertm_send(struct sock *sk)
|
||||||
return nsent;
|
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;
|
struct sock *sk = (struct sock *)pi;
|
||||||
u16 control = 0;
|
u16 control = 0;
|
||||||
|
@ -1456,15 +1438,15 @@ static int l2cap_send_ack(struct l2cap_pinfo *pi)
|
||||||
|
|
||||||
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
|
if (pi->conn_state & L2CAP_CONN_LOCAL_BUSY) {
|
||||||
control |= L2CAP_SUPER_RCV_NOT_READY;
|
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) {
|
} else if (l2cap_ertm_send(sk) == 0) {
|
||||||
control |= L2CAP_SUPER_RCV_READY;
|
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;
|
struct srej_list *tail;
|
||||||
u16 control;
|
u16 control;
|
||||||
|
@ -1476,8 +1458,6 @@ static int l2cap_send_srejtail(struct sock *sk)
|
||||||
control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
|
control |= tail->tx_seq << L2CAP_CTRL_REQSEQ_SHIFT;
|
||||||
|
|
||||||
l2cap_send_sframe(l2cap_pi(sk), control);
|
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)
|
static inline int l2cap_skbuff_fromiovec(struct sock *sk, struct msghdr *msg, int len, int count, struct sk_buff *skb)
|
||||||
|
@ -1687,10 +1667,12 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
|
||||||
/* Connectionless channel */
|
/* Connectionless channel */
|
||||||
if (sk->sk_type == SOCK_DGRAM) {
|
if (sk->sk_type == SOCK_DGRAM) {
|
||||||
skb = l2cap_create_connless_pdu(sk, msg, len);
|
skb = l2cap_create_connless_pdu(sk, msg, len);
|
||||||
if (IS_ERR(skb))
|
if (IS_ERR(skb)) {
|
||||||
err = PTR_ERR(skb);
|
err = PTR_ERR(skb);
|
||||||
else
|
} else {
|
||||||
err = l2cap_do_send(sk, skb);
|
l2cap_do_send(sk, skb);
|
||||||
|
err = len;
|
||||||
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1709,9 +1691,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = l2cap_do_send(sk, skb);
|
l2cap_do_send(sk, skb);
|
||||||
if (!err)
|
err = len;
|
||||||
err = len;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case L2CAP_MODE_ERTM:
|
case L2CAP_MODE_ERTM:
|
||||||
|
|
Loading…
Reference in New Issue